blob: 2ed202887b43b05455eae9515167d9264dcf6a20 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#define INFO_PREFIX "video_rdma"
#define pr_fmt(fmt) "rdma: " fmt
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/dma-mapping.h>
#include <linux/string.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/ctype.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/clk.h>
#include <linux/kthread.h>
#include <linux/slab.h>
#include "rdma.h"
#include <linux/amlogic/media/utils/vdec_reg.h>
#include <linux/amlogic/media/registers/register_map.h>
#include <linux/amlogic/media/rdma/rdma_mgr.h>
#define Wr(adr, val) WRITE_VCBUS_REG(adr, val)
#define Rd(adr) READ_VCBUS_REG(adr)
#define Wr_reg_bits(adr, val, start, len) \
WRITE_VCBUS_REG_BITS(adr, val, start, len)
#define RDMA_NUM 4
static int second_rdma_feature;
static int vsync_rdma_handle[RDMA_NUM];
static int irq_count[RDMA_NUM];
static int enable[RDMA_NUM];
static int cur_enable[RDMA_NUM];
static int pre_enable_[RDMA_NUM];
static int debug_flag[RDMA_NUM];
static int vsync_cfg_count[RDMA_NUM];
static u32 force_rdma_config[RDMA_NUM];
static bool first_config[RDMA_NUM];
static bool rdma_done[RDMA_NUM];
static void vsync_rdma_irq(void *arg);
static void vsync_rdma_vpp1_irq(void *arg);
static void vsync_rdma_vpp2_irq(void *arg);
static void pre_vsync_rdma_irq(void *arg);
static void line_n_int_rdma_irq(void *arg);
static void vsync_rdma_read_irq(void *arg);
struct rdma_op_s vsync_rdma_op = {
vsync_rdma_irq,
NULL
};
struct rdma_op_s vsync_rdma_vpp1_op = {
vsync_rdma_vpp1_irq,
NULL
};
struct rdma_op_s vsync_rdma_vpp2_op = {
vsync_rdma_vpp2_irq,
NULL
};
struct rdma_op_s pre_vsync_rdma_op = {
pre_vsync_rdma_irq,
NULL
};
struct rdma_op_s line_n_int_rdma_op = {
line_n_int_rdma_irq,
NULL
};
struct rdma_op_s vsync_rdma_read_op = {
vsync_rdma_read_irq,
NULL
};
static void set_rdma_trigger_line(void)
{
int trigger_line;
switch (aml_read_vcbus(VPU_VIU_VENC_MUX_CTRL) & 0x3) {
case 0:
trigger_line = aml_read_vcbus(ENCL_VIDEO_VAVON_ELINE)
- aml_read_vcbus(ENCL_VIDEO_VSO_BLINE);
break;
case 1:
if ((aml_read_vcbus(ENCI_VIDEO_MODE) & 1) == 0)
trigger_line = 260; /* 480i */
else
trigger_line = 310; /* 576i */
break;
case 2:
if (aml_read_vcbus(ENCP_VIDEO_MODE) & (1 << 12))
trigger_line = aml_read_vcbus(ENCP_DE_V_END_EVEN);
else
trigger_line = aml_read_vcbus(ENCP_VIDEO_VAVON_ELINE)
- aml_read_vcbus(ENCP_VIDEO_VSO_BLINE);
break;
case 3:
trigger_line = aml_read_vcbus(ENCT_VIDEO_VAVON_ELINE)
- aml_read_vcbus(ENCT_VIDEO_VSO_BLINE);
break;
}
aml_write_vcbus(VPP_INT_LINE_NUM, trigger_line);
}
void _vsync_rdma_config(int rdma_type)
{
int iret = 0;
int enable_ = cur_enable[rdma_type] & 0xf;
if (vsync_rdma_handle[rdma_type] <= 0)
return;
/* first frame not use rdma */
if (!first_config[rdma_type]) {
cur_enable[rdma_type] = enable[rdma_type];
pre_enable_[rdma_type] = enable_;
first_config[rdma_type] = true;
rdma_done[rdma_type] = false;
return;
}
/* if rdma mode changed, reset rdma */
if (pre_enable_[rdma_type] != enable_) {
rdma_clear(vsync_rdma_handle[rdma_type]);
force_rdma_config[rdma_type] = 1;
}
if (force_rdma_config[rdma_type])
rdma_done[rdma_type] = true;
if (enable_ == 1) {
if (rdma_done[rdma_type])
iret = rdma_watchdog_setting(0);
else
iret = rdma_watchdog_setting(1);
} else {
/* not vsync mode */
iret = rdma_watchdog_setting(0);
force_rdma_config[rdma_type] = 1;
}
rdma_done[rdma_type] = false;
if (iret)
force_rdma_config[rdma_type] = 1;
iret = 0;
if (force_rdma_config[rdma_type]) {
if (enable_ == 1) {
if (has_multi_vpp) {
if (rdma_type == VSYNC_RDMA) {
iret = rdma_config(vsync_rdma_handle[rdma_type],
RDMA_TRIGGER_VSYNC_INPUT);
} else if (rdma_type == VSYNC_RDMA_VPP1) {
iret = rdma_config(vsync_rdma_handle[rdma_type],
RDMA_TRIGGER_VPP1_VSYNC_INPUT);
} else if (rdma_type == VSYNC_RDMA_VPP2) {
iret = rdma_config(vsync_rdma_handle[rdma_type],
RDMA_TRIGGER_VPP2_VSYNC_INPUT);
} else if (rdma_type == PRE_VSYNC_RDMA) {
iret = rdma_config(vsync_rdma_handle[rdma_type],
RDMA_TRIGGER_PRE_VSYNC_INPUT);
}
} else {
if (rdma_type == VSYNC_RDMA) {
iret = rdma_config(vsync_rdma_handle[rdma_type],
RDMA_TRIGGER_VSYNC_INPUT);
} else if (rdma_type == LINE_N_INT_RDMA) {
set_rdma_trigger_line();
iret = rdma_config(vsync_rdma_handle[rdma_type],
RDMA_TRIGGER_LINE_INPUT);
} else if (rdma_type == VSYNC_RDMA_READ) {
iret = rdma_config(vsync_rdma_handle[rdma_type],
RDMA_TRIGGER_VSYNC_INPUT |
RDMA_READ_MASK);
}
}
if (iret)
vsync_cfg_count[rdma_type]++;
} else if (enable_ == 2) {
/*manually in cur vsync*/
rdma_config(vsync_rdma_handle[rdma_type],
RDMA_TRIGGER_MANUAL);
} else if (enable_ == 3) {
;
} else if (enable_ == 4) {
rdma_config(vsync_rdma_handle[rdma_type],
RDMA_TRIGGER_DEBUG1); /*for debug*/
} else if (enable_ == 5) {
rdma_config(vsync_rdma_handle[rdma_type],
RDMA_TRIGGER_DEBUG2); /*for debug*/
} else if (enable_ == 6) {
;
}
if (!iret)
force_rdma_config[rdma_type] = 1;
else
force_rdma_config[rdma_type] = 0;
}
pre_enable_[rdma_type] = enable_;
cur_enable[rdma_type] = enable[rdma_type];
}
void vsync_rdma_config(void)
{
_vsync_rdma_config(VSYNC_RDMA);
if (!has_multi_vpp) {
_vsync_rdma_config(VSYNC_RDMA_READ);
if (second_rdma_feature &&
is_meson_g12b_revb())
_vsync_rdma_config(LINE_N_INT_RDMA);
}
}
EXPORT_SYMBOL(vsync_rdma_config);
void vsync_rdma_vpp1_config(void)
{
_vsync_rdma_config(VSYNC_RDMA_VPP1);
}
EXPORT_SYMBOL(vsync_rdma_vpp1_config);
void vsync_rdma_vpp2_config(void)
{
_vsync_rdma_config(VSYNC_RDMA_VPP2);
}
EXPORT_SYMBOL(vsync_rdma_vpp2_config);
void pre_vsync_rdma_config(void)
{
_vsync_rdma_config(PRE_VSYNC_RDMA);
}
EXPORT_SYMBOL(pre_vsync_rdma_config);
void _vsync_rdma_config_pre(int rdma_type)
{
int enable_ = cur_enable[rdma_type] & 0xf;
if (vsync_rdma_handle[rdma_type] == 0)
return;
if (enable_ == 3)/*manually in next vsync*/
rdma_config(vsync_rdma_handle[rdma_type], 0);
else if (enable_ == 6)
rdma_config(vsync_rdma_handle[rdma_type], 0x101); /*for debug*/
}
void vsync_rdma_config_pre(void)
{
_vsync_rdma_config_pre(VSYNC_RDMA);
if (!has_multi_vpp) {
_vsync_rdma_config_pre(VSYNC_RDMA_READ);
if (second_rdma_feature &&
is_meson_g12b_revb())
_vsync_rdma_config_pre(LINE_N_INT_RDMA);
}
}
EXPORT_SYMBOL(vsync_rdma_config_pre);
void vsync_rdma_vpp1_config_pre(void)
{
_vsync_rdma_config_pre(VSYNC_RDMA_VPP1);
}
EXPORT_SYMBOL(vsync_rdma_vpp1_config_pre);
void vsync_rdma_vpp2_config_pre(void)
{
_vsync_rdma_config_pre(VSYNC_RDMA_VPP2);
}
EXPORT_SYMBOL(vsync_rdma_vpp2_config_pre);
void pre_vsync_rdma_config_pre(void)
{
_vsync_rdma_config_pre(PRE_VSYNC_RDMA);
}
EXPORT_SYMBOL(pre_vsync_rdma_config_pre);
static void vsync_rdma_irq(void *arg)
{
int iret;
int enable_ = cur_enable[VSYNC_RDMA] & 0xf;
if (enable_ == 1) {
/*triggered by next vsync*/
iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA],
RDMA_TRIGGER_VSYNC_INPUT);
if (iret)
vsync_cfg_count[VSYNC_RDMA]++;
} else {
iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA], 0);
}
pre_enable_[VSYNC_RDMA] = enable_;
if (!iret || enable_ != 1)
force_rdma_config[VSYNC_RDMA] = 1;
else
force_rdma_config[VSYNC_RDMA] = 0;
rdma_done[VSYNC_RDMA] = true;
irq_count[VSYNC_RDMA]++;
}
static void vsync_rdma_vpp1_irq(void *arg)
{
int iret;
int enable_ = cur_enable[VSYNC_RDMA_VPP1] & 0xf;
if (enable_ == 1) {
/*triggered by next vsync*/
iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA_VPP1],
RDMA_TRIGGER_VPP1_VSYNC_INPUT);
if (iret)
vsync_cfg_count[VSYNC_RDMA_VPP1]++;
} else {
iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA_VPP1], 0);
}
pre_enable_[VSYNC_RDMA_VPP1] = enable_;
if (!iret || enable_ != 1)
force_rdma_config[VSYNC_RDMA_VPP1] = 1;
else
force_rdma_config[VSYNC_RDMA_VPP1] = 0;
rdma_done[VSYNC_RDMA_VPP1] = true;
irq_count[VSYNC_RDMA_VPP1]++;
}
static void vsync_rdma_vpp2_irq(void *arg)
{
int iret;
int enable_ = cur_enable[VSYNC_RDMA_VPP2] & 0xf;
if (enable_ == 1) {
/*triggered by next vsync*/
iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA_VPP2],
RDMA_TRIGGER_VPP2_VSYNC_INPUT);
if (iret)
vsync_cfg_count[VSYNC_RDMA_VPP2]++;
} else {
iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA_VPP2], 0);
}
pre_enable_[VSYNC_RDMA_VPP2] = enable_;
if (!iret || enable_ != 1)
force_rdma_config[VSYNC_RDMA_VPP2] = 1;
else
force_rdma_config[VSYNC_RDMA_VPP2] = 0;
rdma_done[VSYNC_RDMA_VPP2] = true;
irq_count[VSYNC_RDMA_VPP2]++;
}
static void pre_vsync_rdma_irq(void *arg)
{
int iret;
int enable_ = cur_enable[PRE_VSYNC_RDMA] & 0xf;
if (enable_ == 1) {
iret = rdma_config(vsync_rdma_handle[PRE_VSYNC_RDMA],
RDMA_TRIGGER_PRE_VSYNC_INPUT);
if (iret)
vsync_cfg_count[PRE_VSYNC_RDMA]++;
} else {
iret = rdma_config(vsync_rdma_handle[PRE_VSYNC_RDMA], 0);
}
pre_enable_[PRE_VSYNC_RDMA] = enable_;
if (!iret || enable_ != 1)
force_rdma_config[PRE_VSYNC_RDMA] = 1;
else
force_rdma_config[PRE_VSYNC_RDMA] = 0;
rdma_done[PRE_VSYNC_RDMA] = true;
irq_count[PRE_VSYNC_RDMA]++;
}
static void line_n_int_rdma_irq(void *arg)
{
int iret;
int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf;
if (enable_ == 1) {
/*triggered by next vsync*/
//set_rdma_trigger_line();
iret = rdma_config(vsync_rdma_handle[LINE_N_INT_RDMA],
RDMA_TRIGGER_LINE_INPUT);
if (iret)
vsync_cfg_count[LINE_N_INT_RDMA]++;
} else {
iret = rdma_config(vsync_rdma_handle[LINE_N_INT_RDMA], 0);
}
pre_enable_[LINE_N_INT_RDMA] = enable_;
if (!iret || enable_ != 1)
force_rdma_config[LINE_N_INT_RDMA] = 1;
else
force_rdma_config[LINE_N_INT_RDMA] = 0;
rdma_done[LINE_N_INT_RDMA] = true;
irq_count[LINE_N_INT_RDMA]++;
}
static void vsync_rdma_read_irq(void *arg)
{
int iret;
int enable_ = cur_enable[VSYNC_RDMA_READ] & 0xf;
if (enable_ == 1) {
/*triggered by next vsync*/
iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA_READ],
RDMA_TRIGGER_VSYNC_INPUT | RDMA_READ_MASK);
if (iret)
vsync_cfg_count[VSYNC_RDMA_READ]++;
} else {
iret = rdma_config(vsync_rdma_handle[VSYNC_RDMA_READ], 0);
}
pre_enable_[VSYNC_RDMA_READ] = enable_;
if (!iret || enable_ != 1)
force_rdma_config[VSYNC_RDMA_READ] = 1;
else
force_rdma_config[VSYNC_RDMA_READ] = 0;
rdma_done[VSYNC_RDMA_READ] = true;
irq_count[VSYNC_RDMA_READ]++;
}
/* add a register addr to read list
* success: return index, this index can be used in read-back table
* fail: return -1
*/
s32 VSYNC_ADD_RD_REG(u32 adr)
{
int enable_ = cur_enable[VSYNC_RDMA_READ] & 0xf;
int handle = vsync_rdma_handle[VSYNC_RDMA_READ];
if (enable_ != 0 && handle > 0)
return rdma_add_read_reg(handle, adr);
pr_info("%s: VSYNC_RDMA_READ is diabled\n", __func__);
return -1;
}
EXPORT_SYMBOL(VSYNC_ADD_RD_REG);
/* get read-back addr, this func should be invoked everytime before getting vals
* success: return start addr of read-back
* fail: return NULL
*/
u32 *VSYNC_GET_RD_BACK_ADDR(void)
{
int enable_ = cur_enable[VSYNC_RDMA_READ] & 0xf;
int handle = vsync_rdma_handle[VSYNC_RDMA_READ];
if (enable_ != 0 && handle > 0)
return rdma_get_read_back_addr(handle);
return NULL;
}
EXPORT_SYMBOL(VSYNC_GET_RD_BACK_ADDR);
u32 VSYNC_RD_MPEG_REG(u32 adr)
{
int enable_ = cur_enable[VSYNC_RDMA] & 0xf;
u32 read_val = Rd(adr);
if (enable_ != 0 && vsync_rdma_handle[VSYNC_RDMA] > 0)
read_val = rdma_read_reg(vsync_rdma_handle[VSYNC_RDMA], adr);
return read_val;
}
EXPORT_SYMBOL(VSYNC_RD_MPEG_REG);
u32 VSYNC_RD_MPEG_REG_VPP1(u32 adr)
{
int enable_ = cur_enable[VSYNC_RDMA_VPP1] & 0xf;
u32 read_val = Rd(adr);
if (enable_ != 0 && vsync_rdma_handle[VSYNC_RDMA_VPP1] > 0)
read_val = rdma_read_reg(vsync_rdma_handle[VSYNC_RDMA_VPP1], adr);
return read_val;
}
EXPORT_SYMBOL(VSYNC_RD_MPEG_REG_VPP1);
u32 VSYNC_RD_MPEG_REG_VPP2(u32 adr)
{
int enable_ = cur_enable[VSYNC_RDMA_VPP2] & 0xf;
u32 read_val = Rd(adr);
if (enable_ != 0 && vsync_rdma_handle[VSYNC_RDMA_VPP2] > 0)
read_val = rdma_read_reg(vsync_rdma_handle[VSYNC_RDMA_VPP2], adr);
return read_val;
}
EXPORT_SYMBOL(VSYNC_RD_MPEG_REG_VPP2);
u32 PRE_VSYNC_RD_MPEG_REG(u32 adr)
{
int enable_ = cur_enable[PRE_VSYNC_RDMA] & 0xf;
u32 read_val = Rd(adr);
if (enable_ != 0 && vsync_rdma_handle[PRE_VSYNC_RDMA] > 0)
read_val = rdma_read_reg(vsync_rdma_handle[PRE_VSYNC_RDMA], adr);
return read_val;
}
EXPORT_SYMBOL(PRE_VSYNC_RD_MPEG_REG);
int VSYNC_WR_MPEG_REG(u32 adr, u32 val)
{
int enable_ = cur_enable[VSYNC_RDMA] & 0xf;
if (enable_ != 0 && vsync_rdma_handle[VSYNC_RDMA] > 0) {
rdma_write_reg(vsync_rdma_handle[VSYNC_RDMA], adr, val);
} else {
Wr(adr, val);
if (debug_flag[VSYNC_RDMA] & 1)
pr_info("VSYNC_WR(%x)=%x\n", adr, val);
}
return 0;
}
EXPORT_SYMBOL(VSYNC_WR_MPEG_REG);
int VSYNC_WR_MPEG_REG_VPP1(u32 adr, u32 val)
{
int enable_ = cur_enable[VSYNC_RDMA_VPP1] & 0xf;
if (enable_ != 0 && vsync_rdma_handle[VSYNC_RDMA_VPP1] > 0) {
rdma_write_reg(vsync_rdma_handle[VSYNC_RDMA_VPP1], adr, val);
} else {
Wr(adr, val);
if (debug_flag[VSYNC_RDMA_VPP1] & 1)
pr_info("VSYNC_VPP1_WR(%x)=%x\n", adr, val);
}
return 0;
}
EXPORT_SYMBOL(VSYNC_WR_MPEG_REG_VPP1);
int VSYNC_WR_MPEG_REG_VPP2(u32 adr, u32 val)
{
int enable_ = cur_enable[VSYNC_RDMA_VPP2] & 0xf;
if (enable_ != 0 && vsync_rdma_handle[VSYNC_RDMA_VPP2] > 0) {
rdma_write_reg(vsync_rdma_handle[VSYNC_RDMA_VPP2], adr, val);
} else {
Wr(adr, val);
if (debug_flag[VSYNC_RDMA_VPP2] & 1)
pr_info("VSYNC_VPP2_WR(%x)=%x\n", adr, val);
}
return 0;
}
EXPORT_SYMBOL(VSYNC_WR_MPEG_REG_VPP2);
int PRE_VSYNC_WR_MPEG_REG(u32 adr, u32 val)
{
int enable_ = cur_enable[PRE_VSYNC_RDMA] & 0xf;
if (enable_ != 0 && vsync_rdma_handle[PRE_VSYNC_RDMA] > 0) {
rdma_write_reg(vsync_rdma_handle[PRE_VSYNC_RDMA], adr, val);
} else {
Wr(adr, val);
if (debug_flag[PRE_VSYNC_RDMA] & 1)
pr_info("PRE_VSYNC_RDMA_WR(%x)=%x\n", adr, val);
}
return 0;
}
EXPORT_SYMBOL(PRE_VSYNC_WR_MPEG_REG);
int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len)
{
int enable_ = cur_enable[VSYNC_RDMA] & 0xf;
if (enable_ != 0 && vsync_rdma_handle[VSYNC_RDMA] > 0) {
rdma_write_reg_bits(vsync_rdma_handle[VSYNC_RDMA],
adr, val, start, len);
} else {
u32 read_val = Rd(adr);
u32 write_val = (read_val &
~(((1L << (len)) - 1) << (start)))
| ((unsigned int)(val) << (start));
Wr(adr, write_val);
if (debug_flag[VSYNC_RDMA] & 1)
pr_info("VSYNC_WR(%x)=%x\n", adr, write_val);
}
return 0;
}
EXPORT_SYMBOL(VSYNC_WR_MPEG_REG_BITS);
int VSYNC_WR_MPEG_REG_BITS_VPP1(u32 adr, u32 val, u32 start, u32 len)
{
int enable_ = cur_enable[VSYNC_RDMA_VPP1] & 0xf;
if (enable_ != 0 && vsync_rdma_handle[VSYNC_RDMA_VPP1] > 0) {
rdma_write_reg_bits(vsync_rdma_handle[VSYNC_RDMA_VPP1],
adr, val, start, len);
} else {
u32 read_val = Rd(adr);
u32 write_val = (read_val &
~(((1L << (len)) - 1) << (start)))
| ((unsigned int)(val) << (start));
Wr(adr, write_val);
if (debug_flag[VSYNC_RDMA_VPP1] & 1)
pr_info("VSYNC_VPP1_WR(%x)=%x\n", adr, write_val);
}
return 0;
}
EXPORT_SYMBOL(VSYNC_WR_MPEG_REG_BITS_VPP1);
int VSYNC_WR_MPEG_REG_BITS_VPP2(u32 adr, u32 val, u32 start, u32 len)
{
int enable_ = cur_enable[VSYNC_RDMA_VPP2] & 0xf;
if (enable_ != 0 && vsync_rdma_handle[VSYNC_RDMA_VPP2] > 0) {
rdma_write_reg_bits(vsync_rdma_handle[VSYNC_RDMA_VPP2],
adr, val, start, len);
} else {
u32 read_val = Rd(adr);
u32 write_val = (read_val &
~(((1L << (len)) - 1) << (start)))
| ((unsigned int)(val) << (start));
Wr(adr, write_val);
if (debug_flag[VSYNC_RDMA_VPP2] & 1)
pr_info("VSYNC_VPP2_WR(%x)=%x\n", adr, write_val);
}
return 0;
}
EXPORT_SYMBOL(VSYNC_WR_MPEG_REG_BITS_VPP2);
int PRE_VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len)
{
int enable_ = cur_enable[PRE_VSYNC_RDMA] & 0xf;
if (enable_ != 0 && vsync_rdma_handle[PRE_VSYNC_RDMA] > 0) {
rdma_write_reg_bits(vsync_rdma_handle[PRE_VSYNC_RDMA],
adr, val, start, len);
} else {
u32 read_val = Rd(adr);
u32 write_val = (read_val &
~(((1L << (len)) - 1) << (start)))
| ((unsigned int)(val) << (start));
Wr(adr, write_val);
if (debug_flag[PRE_VSYNC_RDMA] & 1)
pr_info("PRE_VSYNC_VPP2_WR(%x)=%x\n", adr, write_val);
}
return 0;
}
EXPORT_SYMBOL(PRE_VSYNC_WR_MPEG_REG_BITS);
u32 _VSYNC_RD_MPEG_REG(u32 adr)
{
u32 read_val = 0;
if (second_rdma_feature && is_meson_g12b_revb()) {
int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf;
read_val = Rd(adr);
if (enable_ != 0 &&
vsync_rdma_handle[LINE_N_INT_RDMA] > 0)
read_val = rdma_read_reg
(vsync_rdma_handle[LINE_N_INT_RDMA], adr);
} else {
read_val = VSYNC_RD_MPEG_REG(adr);
}
return read_val;
}
EXPORT_SYMBOL(_VSYNC_RD_MPEG_REG);
int _VSYNC_WR_MPEG_REG(u32 adr, u32 val)
{
if (second_rdma_feature && is_meson_g12b_revb()) {
int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf;
if (enable_ != 0 &&
vsync_rdma_handle[LINE_N_INT_RDMA] > 0) {
rdma_write_reg
(vsync_rdma_handle[LINE_N_INT_RDMA], adr, val);
} else {
Wr(adr, val);
if (debug_flag[LINE_N_INT_RDMA] & 1)
pr_info("VSYNC_WR(%x)=%x\n", adr, val);
}
} else {
VSYNC_WR_MPEG_REG(adr, val);
}
return 0;
}
EXPORT_SYMBOL(_VSYNC_WR_MPEG_REG);
int _VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len)
{
if (second_rdma_feature && is_meson_g12b_revb()) {
int enable_ = cur_enable[LINE_N_INT_RDMA] & 0xf;
if (enable_ != 0 &&
vsync_rdma_handle[LINE_N_INT_RDMA] > 0) {
rdma_write_reg_bits
(vsync_rdma_handle[LINE_N_INT_RDMA],
adr, val, start, len);
} else {
u32 read_val = Rd(adr);
u32 write_val = (read_val &
~(((1L << (len)) - 1) << (start)))
| ((unsigned int)(val) << (start));
Wr(adr, write_val);
if (debug_flag[LINE_N_INT_RDMA] & 1)
pr_info("VSYNC_WR(%x)<=%x\n", adr, write_val);
}
} else {
VSYNC_WR_MPEG_REG_BITS(adr, val, start, len);
}
return 0;
}
EXPORT_SYMBOL(_VSYNC_WR_MPEG_REG_BITS);
bool is_vsync_rdma_enable(void)
{
bool ret;
int enable_ = cur_enable[VSYNC_RDMA] & 0xf;
ret = (enable_ != 0);
return ret;
}
EXPORT_SYMBOL(is_vsync_rdma_enable);
bool is_vsync_vpp1_rdma_enable(void)
{
bool ret;
int enable_ = cur_enable[VSYNC_RDMA_VPP1] & 0xf;
ret = (enable_ != 0);
return ret;
}
EXPORT_SYMBOL(is_vsync_vpp1_rdma_enable);
bool is_vsync_vpp2_rdma_enable(void)
{
bool ret;
int enable_ = cur_enable[VSYNC_RDMA_VPP2] & 0xf;
ret = (enable_ != 0);
return ret;
}
EXPORT_SYMBOL(is_vsync_vpp2_rdma_enable);
bool is_pre_vsync_rdma_enable(void)
{
bool ret;
int enable_ = cur_enable[PRE_VSYNC_RDMA] & 0xf;
ret = (enable_ != 0);
return ret;
}
EXPORT_SYMBOL(is_pre_vsync_rdma_enable);
void enable_rdma_log(int flag)
{
if (flag) {
debug_flag[VSYNC_RDMA] |= 0x1;
if (has_multi_vpp) {
debug_flag[VSYNC_RDMA_VPP1] |= 0x1;
debug_flag[VSYNC_RDMA_VPP2] |= 0x1;
debug_flag[PRE_VSYNC_RDMA] |= 0x1;
} else {
debug_flag[LINE_N_INT_RDMA] |= 0x1;
debug_flag[VSYNC_RDMA_READ] |= 0x1;
}
} else {
debug_flag[VSYNC_RDMA] &= (~0x1);
if (has_multi_vpp) {
debug_flag[VSYNC_RDMA_VPP1] &= (~0x1);
debug_flag[VSYNC_RDMA_VPP2] &= (~0x1);
debug_flag[PRE_VSYNC_RDMA] &= (~0x1);
} else {
debug_flag[LINE_N_INT_RDMA] &= (~0x1);
debug_flag[VSYNC_RDMA_READ] &= (~0x1);
}
}
}
EXPORT_SYMBOL(enable_rdma_log);
void enable_rdma(int enable_flag)
{
enable[VSYNC_RDMA] = enable_flag;
if (has_multi_vpp) {
enable[VSYNC_RDMA_VPP1] = enable_flag;
enable[VSYNC_RDMA_VPP2] = enable_flag;
enable[PRE_VSYNC_RDMA] = enable_flag;
} else {
enable[LINE_N_INT_RDMA] = enable_flag;
enable[VSYNC_RDMA_READ] = enable_flag;
}
}
EXPORT_SYMBOL(enable_rdma);
struct rdma_op_s *get_rdma_ops(int rdma_type)
{
if (has_multi_vpp) {
if (rdma_type == VSYNC_RDMA)
return &vsync_rdma_op;
else if (rdma_type == VSYNC_RDMA_VPP1)
return &vsync_rdma_vpp1_op;
else if (rdma_type == VSYNC_RDMA_VPP2)
return &vsync_rdma_vpp2_op;
else if (rdma_type == PRE_VSYNC_RDMA)
return &pre_vsync_rdma_op;
else
return NULL;
} else {
if (rdma_type == VSYNC_RDMA)
return &vsync_rdma_op;
else if (rdma_type == LINE_N_INT_RDMA)
return &line_n_int_rdma_op;
else if (rdma_type == VSYNC_RDMA_READ)
return &vsync_rdma_read_op;
else
return NULL;
}
}
void set_rdma_handle(int rdma_type, int handle)
{
vsync_rdma_handle[rdma_type] = handle;
pr_info("%s video rdma handle = %d.\n", __func__,
vsync_rdma_handle[rdma_type]);
}
int get_rdma_handle(int rdma_type)
{
return vsync_rdma_handle[rdma_type];
}
u32 is_line_n_rdma_enable(void)
{
return second_rdma_feature;
}
static int parse_para(const char *para, int para_num, int *result)
{
char *token = NULL;
char *params, *params_base;
int *out = result;
int len = 0, count = 0;
int res = 0;
int ret = 0;
if (!para)
return 0;
params = kstrdup(para, GFP_KERNEL);
params_base = params;
token = params;
len = strlen(token);
do {
token = strsep(&params, " ");
while (token && (isspace(*token) ||
!isgraph(*token)) && len) {
token++;
len--;
}
if (len == 0)
break;
ret = kstrtoint(token, 0, &res);
if (ret < 0)
break;
len = strlen(token);
*out++ = res;
count++;
} while ((token) && (count < para_num) && (len > 0));
kfree(params_base);
return count;
}
static ssize_t show_second_rdma_feature(struct class *class,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, 40, "%d\n", second_rdma_feature);
}
static ssize_t store_second_rdma_feature(struct class *class,
struct class_attribute *attr,
const char *buf, size_t count)
{
int res = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &res);
pr_info("second_rdma_feature: %d->%d\n", second_rdma_feature, res);
second_rdma_feature = res;
return count;
}
static ssize_t enable_show(struct class *class,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
enable[0], enable[1],
enable[2], enable[3]);
}
static ssize_t enable_store(struct class *class,
struct class_attribute *attr,
const char *buf, size_t count)
{
int i = 0;
if (likely(parse_para(buf, RDMA_NUM, enable) == RDMA_NUM)) {
for (i = 0; i < RDMA_NUM; i++)
pr_info("enalbe[%d]: %d\n", i, enable[i]);
} else {
pr_err("set enable error\n");
}
return count;
}
static ssize_t show_irq_count(struct class *class,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
irq_count[0], irq_count[1],
irq_count[2], irq_count[3]);
}
static ssize_t store_irq_count(struct class *class,
struct class_attribute *attr,
const char *buf, size_t count)
{
int i = 0;
if (likely(parse_para(buf, RDMA_NUM, irq_count) == RDMA_NUM)) {
for (i = 0; i < RDMA_NUM; i++)
pr_info("enalbe[%d]: %d\n", i, irq_count[i]);
} else {
pr_err("set irq_count error\n");
}
return count;
}
static ssize_t show_debug_flag(struct class *class,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d %d, %d, %d\n",
debug_flag[0], debug_flag[1],
debug_flag[2], debug_flag[3]);
}
static ssize_t store_debug_flag(struct class *class,
struct class_attribute *attr,
const char *buf, size_t count)
{
int i = 0;
if (likely(parse_para(buf, RDMA_NUM, debug_flag) == RDMA_NUM)) {
for (i = 0; i < RDMA_NUM; i++)
pr_info("debug_flag[%d]: %d\n", i, debug_flag[i]);
} else {
pr_err("set debug_flag error\n");
}
return count;
}
static ssize_t show_vsync_cfg_count(struct class *class,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d %d, %d, %d\n",
vsync_cfg_count[0], vsync_cfg_count[1],
vsync_cfg_count[2], vsync_cfg_count[3]);
}
static ssize_t store_vsync_cfg_count(struct class *class,
struct class_attribute *attr,
const char *buf, size_t count)
{
int i = 0;
if (likely(parse_para(buf, RDMA_NUM, vsync_cfg_count) == RDMA_NUM)) {
for (i = 0; i < RDMA_NUM; i++)
pr_info("vsync_cfg_count[%d]: %d\n",
i, vsync_cfg_count[i]);
} else {
pr_err("set vsync_cfg_count error\n");
}
return count;
}
static ssize_t show_force_rdma_config(struct class *class,
struct class_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d %d, %d, %d\n",
force_rdma_config[0], force_rdma_config[1],
force_rdma_config[2], force_rdma_config[3]);
}
static ssize_t store_force_rdma_config(struct class *class,
struct class_attribute *attr,
const char *buf, size_t count)
{
int i = 0;
if (likely(parse_para(buf, RDMA_NUM, force_rdma_config) == RDMA_NUM)) {
for (i = 0; i < RDMA_NUM; i++)
pr_info("force_rdma_config[%d]: %d\n",
i, force_rdma_config[i]);
} else {
pr_err("set force_rdma_config error\n");
}
return count;
}
static struct class_attribute rdma_attrs[] = {
__ATTR(second_rdma_feature, 0664,
show_second_rdma_feature, store_second_rdma_feature),
__ATTR(enable, 0664,
enable_show, enable_store),
__ATTR(irq_count, 0664,
show_irq_count, store_irq_count),
__ATTR(debug_flag, 0664,
show_debug_flag, store_debug_flag),
__ATTR(vsync_cfg_count, 0664,
show_vsync_cfg_count, store_vsync_cfg_count),
__ATTR(force_rdma_config, 0664,
show_force_rdma_config, store_force_rdma_config),
};
static struct class *rdma_class;
static int create_rdma_class(void)
{
int i;
rdma_class = class_create(THIS_MODULE, "rdma");
if (IS_ERR_OR_NULL(rdma_class)) {
pr_err("create rdma_class failed\n");
return -1;
}
for (i = 0; i < ARRAY_SIZE(rdma_attrs); i++) {
if (class_create_file(rdma_class,
&rdma_attrs[i])) {
pr_err("create rdma attribute %s failed\n",
rdma_attrs[i].attr.name);
}
}
return 0;
}
static int remove_rdma_class(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(rdma_attrs); i++)
class_remove_file(rdma_class, &rdma_attrs[i]);
class_destroy(rdma_class);
rdma_class = NULL;
return 0;
}
int rdma_init(void)
{
second_rdma_feature = 0;
cur_enable[VSYNC_RDMA] = 0;
enable[VSYNC_RDMA] = 1;
force_rdma_config[VSYNC_RDMA] = 1;
if (has_multi_vpp) {
cur_enable[VSYNC_RDMA_VPP1] = 0;
enable[VSYNC_RDMA_VPP1] = 1;
force_rdma_config[VSYNC_RDMA_VPP1] = 1;
cur_enable[VSYNC_RDMA_VPP2] = 0;
enable[VSYNC_RDMA_VPP2] = 1;
force_rdma_config[VSYNC_RDMA_VPP2] = 1;
cur_enable[PRE_VSYNC_RDMA] = 0;
enable[PRE_VSYNC_RDMA] = 1;
force_rdma_config[PRE_VSYNC_RDMA] = 1;
} else {
cur_enable[VSYNC_RDMA_READ] = 0;
enable[VSYNC_RDMA_READ] = 1;
force_rdma_config[VSYNC_RDMA_READ] = 1;
if (second_rdma_feature) {
cur_enable[LINE_N_INT_RDMA] = 0;
enable[LINE_N_INT_RDMA] = 1;
force_rdma_config[LINE_N_INT_RDMA] = 1;
}
}
create_rdma_class();
return 0;
}
void rdma_exit(void)
{
remove_rdma_class();
}