blob: 745ec21a4b4e17be309c2cfa169c4ed3af58cea9 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
/* Linux Headers */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/string.h>
#include <linux/io.h>
#include <linux/ctype.h>
#include <linux/poll.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/dma-contiguous.h>
#include <linux/dma-mapping.h>
#include <linux/mm.h>
#include <linux/of_device.h>
/* media module used media/registers/cpu_version.h since kernel 5.4 */
#include <linux/amlogic/media/registers/cpu_version.h>
/* Local Headers */
#include "osd.h"
#include "osd_io.h"
#include "osd_reg.h"
#include "osd_rdma.h"
#include "osd_hw.h"
#include "osd_backup.h"
#include "osd_log.h"
#include <linux/amlogic/media/registers/register_map.h>
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
#include <linux/amlogic/media/rdma/rdma_mgr.h>
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM
#include <linux/amlogic/media/amvecm/ve.h>
#endif
#endif
#define RDMA_TABLE_INTERNAL_COUNT 512
#define RDMA_TEMP_TBL_SIZE (8 * RDMA_TABLE_INTERNAL_COUNT)
#define VPP_NUM 3
static DEFINE_SPINLOCK(rdma_lock_vpp0);
static DEFINE_SPINLOCK(rdma_lock_vpp1);
static DEFINE_SPINLOCK(rdma_lock_vpp2);
static struct rdma_table_item *rdma_table[VPP_NUM];
static struct device *osd_rdma_dev;
static void *osd_rdma_table_virt[VPP_NUM];
static dma_addr_t osd_rdma_table_phy[VPP_NUM];
static ulong table_paddr[VPP_NUM];
static void *table_vaddr[VPP_NUM];
static u32 rdma_enable[VPP_NUM];
static u32 item_count[VPP_NUM];
static u32 rdma_debug;
static u32 rdma_hdr_delay;
static bool osd_rdma_init_flag;
#define OSD_RDMA_UPDATE_RETRY_COUNT 10
static unsigned int debug_rdma_status[VPP_NUM];
static unsigned int rdma_irq_count[VPP_NUM];
static unsigned int rdma_lost_count[VPP_NUM];
static unsigned int dump_reg_trigger;
static unsigned int rdma_recovery_count[VPP_NUM];
#ifdef OSD_RDMA_ISR
static unsigned int second_rdma_irq;
#endif
static unsigned int vsync_irq_count[VPP_NUM];
static bool osd_rdma_done[VPP_NUM];
static int osd_rdma_handle[VPP_NUM] = {-1, -1, -1};
static struct rdma_table_item *rdma_temp_tbl[VPP_NUM];
static int support_64bit_addr = 1;
static uint num_reject = 2;
static int rdma_reject_cnt[2];
module_param_array(rdma_reject_cnt, uint, &num_reject, 0664);
MODULE_PARM_DESC(rdma_reject_cnt, "\n rdma_reject_cnt\n");
void *memcpy(void *dest, const void *src, size_t len);
static inline void spin_lock_irqsave_vpp(u32 vpp_index, unsigned long *flags)
{
switch (vpp_index) {
case VPU_VPP0:
spin_lock_irqsave(&rdma_lock_vpp0, *flags);
break;
case VPU_VPP1:
spin_lock_irqsave(&rdma_lock_vpp1, *flags);
break;
case VPU_VPP2:
spin_lock_irqsave(&rdma_lock_vpp2, *flags);
break;
}
}
static inline void spin_unlock_irqrestore_vpp(u32 vpp_index, unsigned long flags)
{
switch (vpp_index) {
case VPU_VPP0:
spin_unlock_irqrestore(&rdma_lock_vpp0, flags);
break;
case VPU_VPP1:
spin_unlock_irqrestore(&rdma_lock_vpp1, flags);
break;
case VPU_VPP2:
spin_unlock_irqrestore(&rdma_lock_vpp2, flags);
break;
}
}
static void rdma_start_end_addr_update(u32 vpp_index, ulong table_paddr)
{
u32 start_addr = 0, start_addr_msb = 0;
u32 end_addr = 0, end_addr_msb = 0;
switch (vpp_index) {
case VPU_VPP0:
start_addr = START_ADDR;
start_addr_msb = START_ADDR_MSB;
end_addr = END_ADDR;
end_addr_msb = END_ADDR_MSB;
break;
case VPU_VPP1:
start_addr = START_ADDR_VPP1;
start_addr_msb = START_ADDR_MSB_VPP1;
end_addr = END_ADDR_VPP1;
end_addr_msb = END_ADDR_MSB_VPP1;
break;
case VPU_VPP2:
start_addr = START_ADDR_VPP2;
start_addr_msb = START_ADDR_MSB_VPP2;
end_addr = END_ADDR_VPP2;
end_addr_msb = END_ADDR_MSB_VPP2;
break;
}
if (support_64bit_addr) {
#ifdef CONFIG_ARM64
osd_reg_write(start_addr,
table_paddr & 0xffffffff);
osd_reg_write(start_addr_msb,
(table_paddr >> 32) & 0xffffffff);
osd_reg_write(end_addr,
(table_paddr - 1) & 0xffffffff);
osd_reg_write(end_addr_msb,
((table_paddr - 1) >> 32) & 0xffffffff);
#else
osd_reg_write(start_addr,
table_paddr & 0xffffffff);
osd_reg_write(start_addr_msb, 0);
osd_reg_write(end_addr,
(table_paddr - 1) & 0xffffffff);
osd_reg_write(end_addr_msb, 0);
#endif
} else {
osd_reg_write(start_addr,
table_paddr & 0xffffffff);
osd_reg_write(end_addr,
(table_paddr - 1) & 0xffffffff);
}
}
static void rdma_end_addr_update(u32 vpp_index, ulong table_paddr, u32 count)
{
u32 end_addr = 0, end_addr_msb = 0;
switch (vpp_index) {
case VPU_VPP0:
end_addr = END_ADDR;
end_addr_msb = END_ADDR_MSB;
break;
case VPU_VPP1:
end_addr = END_ADDR_VPP1;
end_addr_msb = END_ADDR_MSB_VPP1;
break;
case VPU_VPP2:
end_addr = END_ADDR_VPP2;
end_addr_msb = END_ADDR_MSB_VPP2;
break;
}
if (support_64bit_addr) {
#ifdef CONFIG_ARM64
osd_reg_write(end_addr,
(table_paddr +
count * 8 - 1) & 0xffffffff);
osd_reg_write(end_addr_msb,
((table_paddr +
count * 8 - 1) >> 32) & 0xffffffff);
#else
osd_reg_write(end_addr,
(table_paddr +
count * 8 - 1) & 0xffffffff);
osd_reg_write(end_addr_msb, 0);
#endif
} else {
osd_reg_write(end_addr,
(table_paddr +
count * 8 - 1) & 0xffffffff);
}
}
static ulong rdma_end_addr_get(u32 vpp_index)
{
u32 end_addr = 0, end_addr_msb = 0;
ulong rdma_end_addr = 0;
switch (vpp_index) {
case VPU_VPP0:
end_addr = END_ADDR;
end_addr_msb = END_ADDR_MSB;
break;
case VPU_VPP1:
end_addr = END_ADDR_VPP1;
end_addr_msb = END_ADDR_MSB_VPP1;
break;
case VPU_VPP2:
end_addr = END_ADDR_VPP2;
end_addr_msb = END_ADDR_MSB_VPP2;
break;
}
if (support_64bit_addr) {
#ifdef CONFIG_ARM64
rdma_end_addr = osd_reg_read(end_addr_msb);
rdma_end_addr = (rdma_end_addr & 0xffffffff) << 32;
rdma_end_addr |= osd_reg_read(end_addr);
rdma_end_addr++;
#else
rdma_end_addr = osd_reg_read(end_addr);
rdma_end_addr++;
#endif
} else {
rdma_end_addr = osd_reg_read(end_addr) + 1;
}
return rdma_end_addr;
}
static u32 rdma_current_table_addr_get(u32 vpp_index)
{
u32 current_table_addr = 0;
switch (vpp_index) {
case VPU_VPP0:
current_table_addr = OSD_RDMA_FLAG_REG;
break;
case VPU_VPP1:
current_table_addr = OSD_RDMA_FLAG_REG_VPP1;
break;
case VPU_VPP2:
current_table_addr = OSD_RDMA_FLAG_REG_VPP2;
break;
}
return current_table_addr;
}
static int osd_rdma_init(void);
static u32 osd_rdma_flag_reg[VPP_NUM] = {
OSD_RDMA_FLAG_REG,
OSD_RDMA_FLAG_REG_VPP1,
OSD_RDMA_FLAG_REG_VPP2
};
static u32 osd_rdma_status_is_reject(u32 vpp_index)
{
u32 ret = 0;
switch (vpp_index) {
case 0:
ret = OSD_RDMA_STATUS_IS_REJECT;
break;
case 1:
ret = OSD_RDMA_VPP1_STATUS_IS_REJECT;
break;
case 2:
ret = OSD_RDMA_VPP2_STATUS_IS_REJECT;
break;
}
return ret;
}
static u32 osd_rdma_status_mark_tbl_done(u32 vpp_index)
{
u32 ret = 0;
switch (vpp_index) {
case 0:
ret = OSD_RDMA_STATUS_MARK_TBL_DONE;
break;
case 1:
ret = OSD_RDMA_VPP1_STATUS_MARK_TBL_DONE;
break;
case 2:
ret = OSD_RDMA_VPP2_STATUS_MARK_TBL_DONE;
break;
}
return ret;
}
static void osd_rdma_status_clear_reject(u32 vpp_index)
{
switch (vpp_index) {
case 0:
OSD_RDMA_STATUS_CLEAR_REJECT;
break;
case 1:
OSD_RDMA_VPP1_STATUS_CLEAR_REJECT;
break;
case 2:
OSD_RDMA_VPP2_STATUS_CLEAR_REJECT;
break;
}
}
#if defined(CONFIG_ARM64) && !defined(__clang__)
static inline void osd_rdma_mem_cpy(struct rdma_table_item *dst,
struct rdma_table_item *src, u32 len)
{
asm volatile
(" stp x5, x6, [sp, #-16]!\n"
" cmp %2,#8\n"
" bne 1f\n"
" ldr x5, [%0]\n"
" str x5, [%1]\n"
" b 2f\n"
"1: ldp x5, x6, [%0]\n"
" stp x5, x6, [%1]\n"
"2: nop\n"
" ldp x5, x6, [sp], #16\n"
:
: "r" (src), "r" (dst), "r" (len)
: "x5", "x6");
}
#else
inline void osd_rdma_mem_cpy(struct rdma_table_item *dst,
struct rdma_table_item *src, u32 len)
{
memcpy(dst, src, len);
}
#endif
static inline void reset_rdma_table(u32 vpp_index)
{
struct rdma_table_item request_item;
unsigned long flags = 0;
u32 old_count;
ulong end_addr;
int i, j = 0, k = 0, trace_num = 0;
struct rdma_table_item reset_item[VPP_NUM][2] = {
{
{
.addr = OSD_RDMA_FLAG_REG,
.val = OSD_RDMA_STATUS_MARK_TBL_RST,
},
{
.addr = OSD_RDMA_FLAG_REG,
.val = OSD_RDMA_STATUS_MARK_TBL_DONE,
}
},
{
{
.addr = OSD_RDMA_FLAG_REG_VPP1,
.val = OSD_RDMA_STATUS_MARK_TBL_RST,
},
{
.addr = OSD_RDMA_FLAG_REG_VPP1,
.val = OSD_RDMA_STATUS_MARK_TBL_DONE,
}
},
{
{
.addr = OSD_RDMA_FLAG_REG_VPP2,
.val = OSD_RDMA_STATUS_MARK_TBL_RST,
},
{
.addr = OSD_RDMA_FLAG_REG_VPP2,
.val = OSD_RDMA_STATUS_MARK_TBL_DONE,
}
},
};
if (osd_hw.rdma_trace_enable)
trace_num = osd_hw.rdma_trace_num;
else
trace_num = 0;
spin_lock_irqsave_vpp(vpp_index, &flags);
if (!osd_rdma_status_is_reject(vpp_index)) {
u32 val, mask;
int iret;
if ((item_count[vpp_index] * (sizeof(struct rdma_table_item))) >
RDMA_TEMP_TBL_SIZE) {
pr_info("more memory: allocate(%x), expect(%zu)\n",
(unsigned int)RDMA_TEMP_TBL_SIZE,
sizeof(struct rdma_table_item) *
item_count[vpp_index]);
WARN_ON(1);
}
memset(rdma_temp_tbl[vpp_index], 0,
(sizeof(struct rdma_table_item) * item_count[vpp_index]));
end_addr = rdma_end_addr_get(vpp_index);
if (end_addr > table_paddr[vpp_index])
old_count = (end_addr - table_paddr[vpp_index]) >> 3;
else
old_count = 0;
rdma_end_addr_update(vpp_index, table_paddr[vpp_index], 0);
for (i = (int)(item_count[vpp_index] - 1);
i >= 0; i--) {
if (!rdma_temp_tbl[vpp_index])
break;
if (rdma_table[vpp_index][i].addr ==
rdma_current_table_addr_get(vpp_index))
continue;
if (rdma_table[vpp_index][i].addr ==
VPP_MISC)
continue;
iret = get_recovery_item(rdma_table[vpp_index][i].addr,
&val, &mask);
if (!iret) {
request_item.addr =
rdma_table[vpp_index][i].addr;
request_item.val = val;
osd_rdma_mem_cpy(&rdma_temp_tbl[vpp_index][j],
&request_item, 8);
j++;
for (k = 0; k < trace_num; k++) {
if (osd_hw.rdma_trace_reg[k] & 0x10000)
pr_info("recovery -- 0x%04x:0x%08x, mask:0x%08x\n",
rdma_table[vpp_index][i].addr,
val, mask);
}
rdma_recovery_count[vpp_index]++;
} else if ((iret < 0) && (i >= old_count)) {
request_item.addr =
rdma_table[vpp_index][i].addr;
request_item.val =
rdma_table[vpp_index][i].val;
osd_rdma_mem_cpy(&rdma_temp_tbl[vpp_index][j],
&request_item, 8);
j++;
for (k = 0; k < trace_num; k++) {
if (osd_hw.rdma_trace_reg[k] & 0x10000) {
pr_info("recovery -- 0x%04x:0x%08x, mask:0x%08x\n",
rdma_table[vpp_index][i].addr,
rdma_table[vpp_index][i].val,
mask);
pr_info("recovery -- i:%d,item_count:%d,old_count:%d\n",
i,
item_count[vpp_index],
old_count);
}
}
rdma_recovery_count[vpp_index]++;
}
}
for (i = 0; i < j; i++) {
osd_rdma_mem_cpy
(&rdma_table[vpp_index][1 + i],
&rdma_temp_tbl[vpp_index][j - i - 1], 8);
update_recovery_item
(rdma_temp_tbl[vpp_index][j - i - 1].addr,
rdma_temp_tbl[vpp_index][j - i - 1].val);
}
item_count[vpp_index] = j + 2;
osd_rdma_mem_cpy(rdma_table[vpp_index], &reset_item[vpp_index][0], 8);
osd_rdma_mem_cpy(&rdma_table[vpp_index][item_count[vpp_index] - 1],
&reset_item[vpp_index][1], 8);
rdma_end_addr_update(vpp_index, table_paddr[vpp_index],
item_count[vpp_index]);
}
spin_unlock_irqrestore_vpp(vpp_index, flags);
}
static int update_table_item(u32 vpp_index, u32 addr, u32 val, u8 irq_mode)
{
unsigned long flags = 0;
int retry_count = OSD_RDMA_UPDATE_RETRY_COUNT;
struct rdma_table_item request_item;
int reject1 = 0, reject2 = 0, ret = 0;
ulong paddr;
static int pace_logging[VPP_NUM];
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
if (item_count[vpp_index] > 500 || rdma_reset_tigger_flag) {
//#else
// if (item_count[vpp_index] > 500) {
#endif
int i;
struct rdma_table_item reset_item[VPP_NUM][2] = {
{
{
.addr = OSD_RDMA_FLAG_REG,
.val = OSD_RDMA_STATUS_MARK_TBL_RST,
},
{
.addr = OSD_RDMA_FLAG_REG,
.val = OSD_RDMA_STATUS_MARK_TBL_DONE,
}
},
{
{
.addr = OSD_RDMA_FLAG_REG_VPP1,
.val = OSD_RDMA_VPP1_STATUS_MARK_TBL_RST,
},
{
.addr = OSD_RDMA_FLAG_REG_VPP1,
.val = OSD_RDMA_VPP1_STATUS_MARK_TBL_DONE,
}
},
{
{
.addr = OSD_RDMA_FLAG_REG_VPP2,
.val = OSD_RDMA_VPP2_STATUS_MARK_TBL_RST,
},
{
.addr = OSD_RDMA_FLAG_REG_VPP2,
.val = OSD_RDMA_VPP2_STATUS_MARK_TBL_DONE,
}
},
};
/* rdma table is full */
if (!(pace_logging[vpp_index]++ % 50))
pr_info("%s overflow!vsync_cnt=%d, rdma_cnt=%d\n",
__func__, vsync_irq_count[vpp_index], rdma_irq_count[vpp_index]);
/* update rdma table */
for (i = 1; i < item_count[vpp_index] - 1; i++)
osd_reg_write(rdma_table[vpp_index][i].addr, rdma_table[vpp_index][i].val);
osd_reg_write(addr, val);
update_recovery_item(addr, val);
item_count[vpp_index] = 2;
osd_rdma_mem_cpy(rdma_table[vpp_index], &reset_item[vpp_index][0], 8);
osd_rdma_mem_cpy(&rdma_table[vpp_index][item_count[vpp_index] - 1],
&reset_item[vpp_index][1], 8);
rdma_end_addr_update(vpp_index, table_paddr[vpp_index],
item_count[vpp_index]);
return -1;
}
/* pr_debug("%02dth, ctrl: 0x%x, status: 0x%x, auto:0x%x, flag:0x%x\n",
* item_count, osd_reg_read(RDMA_CTRL),
* osd_reg_read(RDMA_STATUS),
* osd_reg_read(RDMA_ACCESS_AUTO),
* osd_reg_read(OSD_RDMA_FLAG_REG));
*/
retry:
if (0 == (retry_count--)) {
pr_debug("OSD RDMA stuck: 0x%x = 0x%x, status: 0x%x\n",
addr, val, osd_reg_read(RDMA_STATUS));
pr_debug("::retry count: %d-%d, count: %d, flag: 0x%x\n",
reject1, reject2, item_count[vpp_index],
osd_reg_read(osd_rdma_flag_reg[vpp_index]));
spin_lock_irqsave_vpp(vpp_index, &flags);
request_item.addr = osd_rdma_flag_reg[vpp_index];
request_item.val = osd_rdma_status_mark_tbl_done(vpp_index);
osd_rdma_mem_cpy
(&rdma_table[vpp_index][item_count[vpp_index]],
&request_item, 8);
request_item.addr = addr;
request_item.val = val;
update_backup_reg(addr, val);
update_recovery_item(addr, val);
osd_rdma_mem_cpy
(&rdma_table[vpp_index][item_count[vpp_index] - 1],
&request_item, 8);
item_count[vpp_index]++;
spin_unlock_irqrestore_vpp(vpp_index, flags);
return -1;
}
if (osd_rdma_status_is_reject(vpp_index) && (irq_mode)) {
/* should not be here. Using the wrong write function
* or rdma isr is block
*/
pr_info("update reg but rdma running, mode: %d\n",
irq_mode);
return -2;
}
if (osd_rdma_status_is_reject(vpp_index) && !irq_mode) {
/* should not be here. Using the wrong write function
* or rdma isr is block
*/
reject1++;
rdma_reject_cnt[0] = reject1;
pr_debug("update reg but rdma running, mode: %d,",
irq_mode);
pr_debug("retry count:%d (%d), flag: 0x%x, status: 0x%x\n",
retry_count, reject1,
osd_reg_read(osd_rdma_flag_reg[vpp_index]),
osd_reg_read(RDMA_STATUS));
goto retry;
}
/*atom_lock_start:*/
spin_lock_irqsave_vpp(vpp_index, &flags);
request_item.addr = osd_rdma_flag_reg[vpp_index];
request_item.val = osd_rdma_status_mark_tbl_done(vpp_index);
osd_rdma_mem_cpy(&rdma_table[vpp_index][item_count[vpp_index]], &request_item, 8);
request_item.addr = addr;
request_item.val = val;
update_backup_reg(addr, val);
update_recovery_item(addr, val);
osd_rdma_mem_cpy(&rdma_table[vpp_index][item_count[vpp_index] - 1], &request_item, 8);
item_count[vpp_index]++;
paddr = table_paddr[vpp_index] + item_count[vpp_index] * 8;
if (!osd_rdma_status_is_reject(vpp_index)) {
rdma_end_addr_update(vpp_index, paddr, 0);
} else if (!irq_mode) {
reject2++;
rdma_reject_cnt[1] = reject1;
pr_debug("need update ---, but rdma running,");
pr_debug("retry count:%d (%d), flag: 0x%x, status: 0x%x\n",
retry_count, reject2,
osd_reg_read(osd_rdma_flag_reg[vpp_index]),
osd_reg_read(RDMA_STATUS));
item_count[vpp_index]--;
spin_unlock_irqrestore_vpp(vpp_index, flags);
goto retry;
} else {
ret = -3;
}
/*atom_lock_end:*/
spin_unlock_irqrestore_vpp(vpp_index, flags);
return ret;
}
static inline u32 is_rdma_reg(u32 addr)
{
u32 rdma_en = 1;
if (addr >= VIU2_OSD1_CTRL_STAT && addr <= VIU2_OSD1_BLK3_CFG_W4)
rdma_en = 0;
else
rdma_en = 1;
return rdma_en;
}
static inline u32 read_reg_internal(u32 vpp_index, u32 addr)
{
int i;
u32 val = 0;
u32 rdma_en = 0;
if (!is_rdma_reg(addr))
rdma_en = 0;
else
rdma_en = rdma_enable[vpp_index];
if (rdma_en) {
for (i = (int)(item_count[vpp_index] - 1);
i >= 0; i--) {
if (addr == rdma_table[vpp_index][i].addr) {
val = rdma_table[vpp_index][i].val;
break;
}
}
if (i >= 0)
return val;
}
return osd_reg_read(addr);
}
static inline int wrtie_reg_internal(u32 vpp_index, u32 addr, u32 val)
{
struct rdma_table_item request_item;
u32 rdma_en = 0;
if (!is_rdma_reg(addr)) {
/* need write at vsync, update table here */
viu2_osd_reg_set(addr, val);
return 0;
}
rdma_en = rdma_enable[vpp_index];
if (!rdma_en) {
osd_reg_write(addr, val);
return 0;
}
if (item_count[vpp_index] > 500) {
/* rdma table is full */
pr_info("%s overflow!\n", __func__);
return -1;
}
/* TODO remove the Done write operation to save the time */
request_item.addr = osd_rdma_flag_reg[vpp_index];
request_item.val = osd_rdma_status_mark_tbl_done(vpp_index);
/* afbc start before afbc reset will cause afbc decode error */
if (addr == VIU_SW_RESET) {
int i = 0;
for (i = 0; i < item_count[vpp_index]; i++) {
if (rdma_table[vpp_index][i].addr == VPU_MAFBC_COMMAND) {
rdma_table[vpp_index][i].addr = VIU_OSD1_TEST_RDDATA;
rdma_table[vpp_index][i].val = 0x0;
}
}
}
osd_rdma_mem_cpy
(&rdma_table[vpp_index][item_count[vpp_index]],
&request_item, 8);
request_item.addr = addr;
request_item.val = val;
update_backup_reg(addr, val);
update_recovery_item(addr, val);
osd_rdma_mem_cpy
(&rdma_table[vpp_index][item_count[vpp_index] - 1],
&request_item, 8);
item_count[vpp_index]++;
return 0;
}
static u32 _VSYNCOSD_RD_MPEG_REG(u32 vpp_index, u32 addr)
{
int i;
bool find = false;
u32 val = 0;
unsigned long flags = 0;
u32 rdma_en = 0;
if (!is_rdma_reg(addr)) {
/* need write at vsync, update table here */
val = viu2_osd_reg_read(addr);
return val;
}
rdma_en = rdma_enable[vpp_index];
if (rdma_en) {
spin_lock_irqsave_vpp(vpp_index, &flags);
/* 1st, read from rdma table */
for (i = (int)(item_count[vpp_index] - 1);
i >= 0; i--) {
if (addr == rdma_table[vpp_index][i].addr) {
val = rdma_table[vpp_index][i].val;
break;
}
}
if (i >= 0)
find = true;
else if (get_backup_reg(addr, &val) == 0)
find = true;
/* 2nd, read from backup reg */
spin_unlock_irqrestore_vpp(vpp_index, flags);
if (find)
return val;
}
/* 3rd, read from osd reg */
return osd_reg_read(addr);
}
u32 VSYNCOSD_RD_MPEG_REG(u32 addr)
{
return _VSYNCOSD_RD_MPEG_REG(VPP0, addr);
}
EXPORT_SYMBOL(VSYNCOSD_RD_MPEG_REG);
u32 VSYNCOSD_RD_MPEG_REG_VPP1(u32 addr)
{
return _VSYNCOSD_RD_MPEG_REG(VPP1, addr);
}
u32 VSYNCOSD_RD_MPEG_REG_VPP2(u32 addr)
{
return _VSYNCOSD_RD_MPEG_REG(VPP2, addr);
}
static int _VSYNCOSD_WR_MPEG_REG(u32 vpp_index, u32 addr, u32 val)
{
int ret = 0, k = 0;
u32 rdma_en = 0, trace_num = 0;
if (!is_rdma_reg(addr)) {
/* need write at vsync, update table here */
viu2_osd_reg_set(addr, val);
return ret;
}
rdma_en = rdma_enable[vpp_index];
if (rdma_en)
ret = update_table_item(vpp_index, addr, val, 0);
else
osd_reg_write(addr, val);
if (osd_hw.rdma_trace_enable)
trace_num = osd_hw.rdma_trace_num;
else
trace_num = 0;
for (k = 0; k < trace_num; k++) {
if (addr == (osd_hw.rdma_trace_reg[k] & 0xffff))
pr_info("(%s), %04x=0x%08x, rdma_en=%d, ret=%d\n",
__func__,
addr, val,
rdma_en, ret);
}
return ret;
}
int VSYNCOSD_WR_MPEG_REG(u32 addr, u32 val)
{
return _VSYNCOSD_WR_MPEG_REG(VPP0, addr, val);
}
EXPORT_SYMBOL(VSYNCOSD_WR_MPEG_REG);
int VSYNCOSD_WR_MPEG_REG_VPP1(u32 addr, u32 val)
{
return _VSYNCOSD_WR_MPEG_REG(VPP1, addr, val);
}
int VSYNCOSD_WR_MPEG_REG_VPP2(u32 addr, u32 val)
{
return _VSYNCOSD_WR_MPEG_REG(VPP2, addr, val);
}
static int _VSYNCOSD_WR_MPEG_REG_BITS(u32 vpp_index, u32 addr, u32 val, u32 start, u32 len)
{
u32 read_val;
u32 write_val;
int ret = 0, k = 0;
u32 rdma_en = 0, trace_num = 0;
if (!is_rdma_reg(addr)) {
/* need write at vsync, update table here */
viu2_osd_reg_set_bits(addr, val, start, len);
return ret;
}
rdma_en = rdma_enable[vpp_index];
if (rdma_en) {
read_val = _VSYNCOSD_RD_MPEG_REG(vpp_index, addr);
write_val = (read_val & ~(((1L << (len)) - 1) << (start)))
| ((unsigned int)(val) << (start));
ret = update_table_item(vpp_index, addr, write_val, 0);
} else {
osd_reg_set_bits(addr, val, start, len);
}
if (osd_hw.rdma_trace_enable)
trace_num = osd_hw.rdma_trace_num;
else
trace_num = 0;
for (k = 0; k < trace_num; k++) {
if (addr == (osd_hw.rdma_trace_reg[k] & 0xffff))
pr_info("(%s), %04x=0x%08x, rdma_en=%d, ret=%d\n",
__func__,
addr, val,
rdma_en, ret);
}
return ret;
}
int VSYNCOSD_WR_MPEG_REG_BITS(u32 addr, u32 val, u32 start, u32 len)
{
return _VSYNCOSD_WR_MPEG_REG_BITS(VPP0, addr, val, start, len);
}
EXPORT_SYMBOL(VSYNCOSD_WR_MPEG_REG_BITS);
int VSYNCOSD_WR_MPEG_REG_BITS_VPP1(u32 addr, u32 val, u32 start, u32 len)
{
return _VSYNCOSD_WR_MPEG_REG_BITS(VPP1, addr, val, start, len);
}
int VSYNCOSD_WR_MPEG_REG_BITS_VPP2(u32 addr, u32 val, u32 start, u32 len)
{
return _VSYNCOSD_WR_MPEG_REG_BITS(VPP2, addr, val, start, len);
}
static int _VSYNCOSD_SET_MPEG_REG_MASK(u32 vpp_index, u32 addr, u32 _mask)
{
u32 read_val = 0;
u32 write_val = 0;
int ret = 0, k = 0;
u32 rdma_en = 0, trace_num = 0;
if (!is_rdma_reg(addr)) {
/* need write at vsync, update table here */
viu2_osd_reg_set_mask(addr, _mask);
return ret;
}
rdma_en = rdma_enable[vpp_index];
if (rdma_en) {
read_val = _VSYNCOSD_RD_MPEG_REG(vpp_index, addr);
write_val = read_val | _mask;
ret = update_table_item(vpp_index, addr, write_val, 0);
} else {
osd_reg_set_mask(addr, _mask);
}
if (osd_hw.rdma_trace_enable)
trace_num = osd_hw.rdma_trace_num;
else
trace_num = 0;
for (k = 0; k < trace_num; k++) {
if (addr == (osd_hw.rdma_trace_reg[k] & 0xffff))
pr_info("(%s) %04x=0x%08x->0x%08x, mask=0x%08x, rdma_en=%d, ret=%d\n",
__func__,
addr, read_val, write_val,
_mask, rdma_en, ret);
}
return ret;
}
int VSYNCOSD_SET_MPEG_REG_MASK(u32 addr, u32 _mask)
{
return _VSYNCOSD_SET_MPEG_REG_MASK(VPP0, addr, _mask);
}
EXPORT_SYMBOL(VSYNCOSD_SET_MPEG_REG_MASK);
int VSYNCOSD_SET_MPEG_REG_MASK_VPP1(u32 addr, u32 _mask)
{
return _VSYNCOSD_SET_MPEG_REG_MASK(VPP1, addr, _mask);
}
int VSYNCOSD_SET_MPEG_REG_MASK_VPP2(u32 addr, u32 _mask)
{
return _VSYNCOSD_SET_MPEG_REG_MASK(VPP2, addr, _mask);
}
static int _VSYNCOSD_CLR_MPEG_REG_MASK(u32 vpp_index, u32 addr, u32 _mask)
{
u32 read_val = 0;
u32 write_val = 0;
int ret = 0, k = 0;
u32 rdma_en = 0, trace_num = 0;
if (!is_rdma_reg(addr)) {
/* need write at vsync, update table here */
viu2_osd_reg_clr_mask(addr, _mask);
return ret;
}
rdma_en = rdma_enable[vpp_index];
if (rdma_en) {
read_val = _VSYNCOSD_RD_MPEG_REG(vpp_index, addr);
write_val = read_val & (~_mask);
ret = update_table_item(vpp_index, addr, write_val, 0);
} else {
osd_reg_clr_mask(addr, _mask);
}
if (osd_hw.rdma_trace_enable)
trace_num = osd_hw.rdma_trace_num;
else
trace_num = 0;
for (k = 0; k < trace_num; k++) {
if (addr == (osd_hw.rdma_trace_reg[k] & 0xffff))
pr_info("(%s) %04x=0x%08x->0x%08x, mask=0x%08x, rdma_en=%d, ret=%d\n",
__func__,
addr, read_val, write_val,
_mask, rdma_en, ret);
}
return ret;
}
int VSYNCOSD_CLR_MPEG_REG_MASK(u32 addr, u32 _mask)
{
return _VSYNCOSD_CLR_MPEG_REG_MASK(VPP0, addr, _mask);
}
EXPORT_SYMBOL(VSYNCOSD_CLR_MPEG_REG_MASK);
int VSYNCOSD_CLR_MPEG_REG_MASK_VPP1(u32 addr, u32 _mask)
{
return _VSYNCOSD_CLR_MPEG_REG_MASK(VPP1, addr, _mask);
}
int VSYNCOSD_CLR_MPEG_REG_MASK_VPP2(u32 addr, u32 _mask)
{
return _VSYNCOSD_CLR_MPEG_REG_MASK(VPP2, addr, _mask);
}
int _VSYNCOSD_IRQ_WR_MPEG_REG(u32 vpp_index, u32 addr, u32 val)
{
int ret = 0, k = 0;
u32 rdma_en = 0, trace_num = 0;
if (!is_rdma_reg(addr)) {
/* need write at vsync, update table here */
viu2_osd_reg_set(addr, val);
return ret;
}
rdma_en = rdma_enable[vpp_index];
if (rdma_en)
ret = update_table_item(vpp_index, addr, val, 1);
else
osd_reg_write(addr, val);
if (osd_hw.rdma_trace_enable)
trace_num = osd_hw.rdma_trace_num;
else
trace_num = 0;
for (k = 0; k < trace_num; k++) {
if (addr == (osd_hw.rdma_trace_reg[k] & 0xffff))
pr_info("(%s), %04x=0x%08x, rdma_en=%d, ret=%d\n",
__func__,
addr, val,
rdma_en, ret);
}
return ret;
}
int VSYNCOSD_IRQ_WR_MPEG_REG(u32 addr, u32 val)
{
return _VSYNCOSD_IRQ_WR_MPEG_REG(VPP0, addr, val);
}
EXPORT_SYMBOL(VSYNCOSD_IRQ_WR_MPEG_REG);
int VSYNCOSD_IRQ_WR_MPEG_REG_VPP1(u32 addr, u32 val)
{
return _VSYNCOSD_IRQ_WR_MPEG_REG(VPP1, addr, val);
}
int VSYNCOSD_IRQ_WR_MPEG_REG_VPP2(u32 addr, u32 val)
{
return _VSYNCOSD_IRQ_WR_MPEG_REG(VPP2, addr, val);
}
/* number lines before vsync for reset */
static unsigned int reset_line;
module_param(reset_line, uint, 0664);
MODULE_PARM_DESC(reset_line, "reset_line");
static unsigned int disable_osd_rdma_reset;
module_param(disable_osd_rdma_reset, uint, 0664);
MODULE_PARM_DESC(disable_osd_rdma_reset, "disable_osd_rdma_reset");
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
static int osd_reset_rdma_handle = -1;
void set_reset_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) - reset_line;
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)
- reset_line;
break;
case 3:
trigger_line = aml_read_vcbus(ENCT_VIDEO_VAVON_ELINE)
- aml_read_vcbus(ENCT_VIDEO_VSO_BLINE) - reset_line;
break;
}
aml_write_vcbus(VPP_INT_LINE_NUM, trigger_line);
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM
struct hdr_osd_reg_s hdr_osd_shadow_reg = {
0x00000001, /* VIU_OSD1_MATRIX_CTRL 0x1a90 */
0x00ba0273, /* VIU_OSD1_MATRIX_COEF00_01 0x1a91 */
0x003f1f9a, /* VIU_OSD1_MATRIX_COEF02_10 0x1a92 */
0x1ea801c0, /* VIU_OSD1_MATRIX_COEF11_12 0x1a93 */
0x01c01e6a, /* VIU_OSD1_MATRIX_COEF20_21 0x1a94 */
0x00000000, /* VIU_OSD1_MATRIX_COLMOD_COEF42 0x1a95 */
0x00400200, /* VIU_OSD1_MATRIX_OFFSET0_1 0x1a96 */
0x00000200, /* VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a97 */
0x00000000, /* VIU_OSD1_MATRIX_PRE_OFFSET0_1 0x1a98 */
0x00000000, /* VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a99 */
0x1fd80000, /* VIU_OSD1_MATRIX_COEF22_30 0x1a9d */
0x00000000, /* VIU_OSD1_MATRIX_COEF31_32 0x1a9e */
0x00000000, /* VIU_OSD1_MATRIX_COEF40_41 0x1a9f */
0x00000000, /* VIU_OSD1_EOTF_CTL 0x1ad4 */
0x08000000, /* VIU_OSD1_EOTF_COEF00_01 0x1ad5 */
0x00000000, /* VIU_OSD1_EOTF_COEF02_10 0x1ad6 */
0x08000000, /* VIU_OSD1_EOTF_COEF11_12 0x1ad7 */
0x00000000, /* VIU_OSD1_EOTF_COEF20_21 0x1ad8 */
0x08000001, /* VIU_OSD1_EOTF_COEF22_RS 0x1ad9 */
0x0, /* VIU_OSD1_EOTF_3X3_OFST_0 0x1aa0 */
0x0, /* VIU_OSD1_EOTF_3X3_OFST_1 0x1aa1 */
0x01c00000, /* VIU_OSD1_OETF_CTL 0x1adc */
{
/* eotf table */
{ /* r map */
0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00,
0x0c00, 0x0e00, 0x1000, 0x1200, 0x1400, 0x1600,
0x1800, 0x1a00, 0x1c00, 0x1e00, 0x2000, 0x2200,
0x2400, 0x2600, 0x2800, 0x2a00, 0x2c00, 0x2e00,
0x3000, 0x3200, 0x3400, 0x3600, 0x3800, 0x3a00,
0x3c00, 0x3e00, 0x4000
},
{ /* g map */
0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00,
0x0c00, 0x0e00, 0x1000, 0x1200, 0x1400, 0x1600,
0x1800, 0x1a00, 0x1c00, 0x1e00, 0x2000, 0x2200,
0x2400, 0x2600, 0x2800, 0x2a00, 0x2c00, 0x2e00,
0x3000, 0x3200, 0x3400, 0x3600, 0x3800, 0x3a00,
0x3c00, 0x3e00, 0x4000
},
{ /* b map */
0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00,
0x0c00, 0x0e00, 0x1000, 0x1200, 0x1400, 0x1600,
0x1800, 0x1a00, 0x1c00, 0x1e00, 0x2000, 0x2200,
0x2400, 0x2600, 0x2800, 0x2a00, 0x2c00, 0x2e00,
0x3000, 0x3200, 0x3400, 0x3600, 0x3800, 0x3a00,
0x3c00, 0x3e00, 0x4000
},
/* oetf table */
{ /* or map */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000
},
{ /* og map */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000
},
{ /* ob map */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000
}
},
-1
};
struct hdr_osd_reg_s hdr_osd_display_reg = {
0x00000001, /* VIU_OSD1_MATRIX_CTRL 0x1a90 */
0x00ba0273, /* VIU_OSD1_MATRIX_COEF00_01 0x1a91 */
0x003f1f9a, /* VIU_OSD1_MATRIX_COEF02_10 0x1a92 */
0x1ea801c0, /* VIU_OSD1_MATRIX_COEF11_12 0x1a93 */
0x01c01e6a, /* VIU_OSD1_MATRIX_COEF20_21 0x1a94 */
0x00000000, /* VIU_OSD1_MATRIX_COLMOD_COEF42 0x1a95 */
0x00400200, /* VIU_OSD1_MATRIX_OFFSET0_1 0x1a96 */
0x00000200, /* VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a97 */
0x00000000, /* VIU_OSD1_MATRIX_PRE_OFFSET0_1 0x1a98 */
0x00000000, /* VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a99 */
0x1fd80000, /* VIU_OSD1_MATRIX_COEF22_30 0x1a9d */
0x00000000, /* VIU_OSD1_MATRIX_COEF31_32 0x1a9e */
0x00000000, /* VIU_OSD1_MATRIX_COEF40_41 0x1a9f */
0x00000000, /* VIU_OSD1_EOTF_CTL 0x1ad4 */
0x08000000, /* VIU_OSD1_EOTF_COEF00_01 0x1ad5 */
0x00000000, /* VIU_OSD1_EOTF_COEF02_10 0x1ad6 */
0x08000000, /* VIU_OSD1_EOTF_COEF11_12 0x1ad7 */
0x00000000, /* VIU_OSD1_EOTF_COEF20_21 0x1ad8 */
0x08000001, /* VIU_OSD1_EOTF_COEF22_RS 0x1ad9 */
0x0, /* VIU_OSD1_EOTF_3X3_OFST_0 0x1aa0 */
0x0, /* VIU_OSD1_EOTF_3X3_OFST_1 0x1aa1 */
0x01c00000, /* VIU_OSD1_OETF_CTL 0x1adc */
{
/* eotf table */
{ /* r map */
0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00,
0x0c00, 0x0e00, 0x1000, 0x1200, 0x1400, 0x1600,
0x1800, 0x1a00, 0x1c00, 0x1e00, 0x2000, 0x2200,
0x2400, 0x2600, 0x2800, 0x2a00, 0x2c00, 0x2e00,
0x3000, 0x3200, 0x3400, 0x3600, 0x3800, 0x3a00,
0x3c00, 0x3e00, 0x4000
},
{ /* g map */
0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00,
0x0c00, 0x0e00, 0x1000, 0x1200, 0x1400, 0x1600,
0x1800, 0x1a00, 0x1c00, 0x1e00, 0x2000, 0x2200,
0x2400, 0x2600, 0x2800, 0x2a00, 0x2c00, 0x2e00,
0x3000, 0x3200, 0x3400, 0x3600, 0x3800, 0x3a00,
0x3c00, 0x3e00, 0x4000
},
{ /* b map */
0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00,
0x0c00, 0x0e00, 0x1000, 0x1200, 0x1400, 0x1600,
0x1800, 0x1a00, 0x1c00, 0x1e00, 0x2000, 0x2200,
0x2400, 0x2600, 0x2800, 0x2a00, 0x2c00, 0x2e00,
0x3000, 0x3200, 0x3400, 0x3600, 0x3800, 0x3a00,
0x3c00, 0x3e00, 0x4000
},
/* oetf table */
{ /* or map */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000
},
{ /* og map */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000
},
{ /* ob map */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000
}
},
-1
};
static void hdr_restore_osd_csc(void)
{
u32 i = 0;
u32 addr_port;
u32 data_port;
struct hdr_osd_lut_s *lut = &hdr_osd_shadow_reg.lut_val;
if (osd_reset_rdma_handle == -1 ||
disable_osd_rdma_reset)
return;
/* check osd matrix enable status */
if (hdr_osd_shadow_reg.viu_osd1_matrix_ctrl & 0x00000001) {
/* osd matrix, VPP_MATRIX_0 */
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_PRE_OFFSET0_1,
hdr_osd_shadow_reg.viu_osd1_matrix_pre_offset0_1);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_PRE_OFFSET2,
hdr_osd_shadow_reg.viu_osd1_matrix_pre_offset2);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_COEF00_01,
hdr_osd_shadow_reg.viu_osd1_matrix_coef00_01);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_COEF02_10,
hdr_osd_shadow_reg.viu_osd1_matrix_coef02_10);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_COEF11_12,
hdr_osd_shadow_reg.viu_osd1_matrix_coef11_12);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_COEF20_21,
hdr_osd_shadow_reg.viu_osd1_matrix_coef20_21);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_COEF22_30,
hdr_osd_shadow_reg.viu_osd1_matrix_coef22_30);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_COEF31_32,
hdr_osd_shadow_reg.viu_osd1_matrix_coef31_32);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_COEF40_41,
hdr_osd_shadow_reg.viu_osd1_matrix_coef40_41);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_COLMOD_COEF42,
hdr_osd_shadow_reg.viu_osd1_matrix_colmod_coef42);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_OFFSET0_1,
hdr_osd_shadow_reg.viu_osd1_matrix_offset0_1);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_OFFSET2,
hdr_osd_shadow_reg.viu_osd1_matrix_offset2);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_MATRIX_CTRL,
hdr_osd_shadow_reg.viu_osd1_matrix_ctrl);
}
/* restore eotf lut */
if ((hdr_osd_shadow_reg.viu_osd1_eotf_ctl & 0x80000000) != 0) {
addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
rdma_write_reg
(osd_reset_rdma_handle,
addr_port, 0);
for (i = 0; i < 16; i++)
rdma_write_reg
(osd_reset_rdma_handle,
data_port,
lut->r_map[i * 2]
| (lut->r_map[i * 2 + 1] << 16));
rdma_write_reg
(osd_reset_rdma_handle,
data_port,
lut->r_map[EOTF_LUT_SIZE - 1]
| (lut->g_map[0] << 16));
for (i = 0; i < 16; i++)
rdma_write_reg
(osd_reset_rdma_handle,
data_port,
lut->g_map[i * 2 + 1]
| (lut->b_map[i * 2 + 2] << 16));
for (i = 0; i < 16; i++)
rdma_write_reg
(osd_reset_rdma_handle,
data_port,
lut->b_map[i * 2]
| (lut->b_map[i * 2 + 1] << 16));
rdma_write_reg
(osd_reset_rdma_handle,
data_port, lut->b_map[EOTF_LUT_SIZE - 1]);
/* load eotf matrix */
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_EOTF_COEF00_01,
hdr_osd_shadow_reg.viu_osd1_eotf_coef00_01);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_EOTF_COEF02_10,
hdr_osd_shadow_reg.viu_osd1_eotf_coef02_10);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_EOTF_COEF11_12,
hdr_osd_shadow_reg.viu_osd1_eotf_coef11_12);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_EOTF_COEF20_21,
hdr_osd_shadow_reg.viu_osd1_eotf_coef20_21);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_EOTF_COEF22_RS,
hdr_osd_shadow_reg.viu_osd1_eotf_coef22_rs);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_EOTF_CTL,
hdr_osd_shadow_reg.viu_osd1_eotf_ctl);
}
/* restore oetf lut */
if ((hdr_osd_shadow_reg.viu_osd1_oetf_ctl & 0xe0000000) != 0) {
addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
for (i = 0; i < 20; i++) {
rdma_write_reg
(osd_reset_rdma_handle,
addr_port, i);
rdma_write_reg
(osd_reset_rdma_handle,
data_port,
lut->or_map[i * 2]
| (lut->or_map[i * 2 + 1] << 16));
}
rdma_write_reg
(osd_reset_rdma_handle,
addr_port, 20);
rdma_write_reg
(osd_reset_rdma_handle,
data_port,
lut->or_map[41 - 1]
| (lut->og_map[0] << 16));
for (i = 0; i < 20; i++) {
rdma_write_reg
(osd_reset_rdma_handle,
addr_port, 21 + i);
rdma_write_reg
(osd_reset_rdma_handle,
data_port,
lut->og_map[i * 2 + 1]
| (lut->og_map[i * 2 + 2] << 16));
}
for (i = 0; i < 20; i++) {
rdma_write_reg
(osd_reset_rdma_handle,
addr_port, 41 + i);
rdma_write_reg
(osd_reset_rdma_handle,
data_port,
lut->ob_map[i * 2] |
(lut->ob_map[i * 2 + 1] << 16));
}
rdma_write_reg
(osd_reset_rdma_handle,
addr_port, 61);
rdma_write_reg
(osd_reset_rdma_handle,
data_port,
lut->ob_map[41 - 1]);
rdma_write_reg
(osd_reset_rdma_handle,
VIU_OSD1_OETF_CTL,
hdr_osd_shadow_reg.viu_osd1_oetf_ctl);
}
}
#endif
static void osd_reset_rdma_func(u32 reset_bit)
{
if (disable_osd_rdma_reset == 0 && reset_bit) {
rdma_write_reg(osd_reset_rdma_handle,
VIU_SW_RESET, 1);
rdma_write_reg(osd_reset_rdma_handle,
VIU_SW_RESET, 0);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM
if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) {
if (rdma_hdr_delay == 0 ||
hdr_osd_reg.shadow_mode == 0)
memcpy(&hdr_osd_shadow_reg, &hdr_osd_reg,
sizeof(struct hdr_osd_reg_s));
hdr_restore_osd_csc();
}
/* Todo: what about g12a */
#endif
set_reset_rdma_trigger_line();
rdma_config(osd_reset_rdma_handle, 1 << 6);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM
if (hdr_osd_reg.shadow_mode == -1) {
if (rdma_hdr_delay == 1) {
memcpy(&hdr_osd_shadow_reg,
&hdr_osd_reg,
sizeof(struct hdr_osd_reg_s));
} else if (rdma_hdr_delay == 2) {
memcpy(&hdr_osd_shadow_reg,
&hdr_osd_display_reg,
sizeof(struct hdr_osd_reg_s));
memcpy(&hdr_osd_display_reg,
&hdr_osd_reg,
sizeof(struct hdr_osd_reg_s));
}
} else {
if (hdr_osd_reg.shadow_mode == 1) {
memcpy(&hdr_osd_shadow_reg,
&hdr_osd_reg,
sizeof(struct hdr_osd_reg_s));
} else if (hdr_osd_reg.shadow_mode == 2) {
memcpy(&hdr_osd_shadow_reg,
&hdr_osd_display_reg,
sizeof(struct hdr_osd_reg_s));
memcpy(&hdr_osd_display_reg,
&hdr_osd_reg,
sizeof(struct hdr_osd_reg_s));
}
}
#endif
} else {
rdma_clear(osd_reset_rdma_handle);
}
}
static void osd_rdma_irq(void *arg)
{
u32 rdma_status;
if (osd_rdma_handle[0] == -1)
return;
rdma_status = osd_reg_read(RDMA_STATUS);
debug_rdma_status[VIU1] = rdma_status;
OSD_RDMA_STATUS_CLEAR_REJECT;
osd_update_vsync_hit();
reset_rdma_table(VIU1);
osd_update_scan_mode();
osd_update_3d_mode();
osd_hw_reset(VIU1);
rdma_irq_count[VIU1]++;
osd_rdma_done[VIU1] = true;
{
/*This is a memory barrier*/
wmb();
}
}
static void osd_rdma_vpp1_irq(void *arg)
{
u32 rdma_status;
if (osd_rdma_handle[1] == -1)
return;
rdma_status = osd_reg_read(RDMA_STATUS);
debug_rdma_status[VIU2] = rdma_status;
OSD_RDMA_VPP1_STATUS_CLEAR_REJECT;
osd_update_vsync_hit_viu2();
reset_rdma_table(VIU2);
//osd_update_scan_mode();
osd_hw_reset(VIU2);
rdma_irq_count[VIU2]++;
osd_rdma_done[VIU2] = true;
{
/*This is a memory barrier*/
wmb();
}
}
static void osd_rdma_vpp2_irq(void *arg)
{
u32 rdma_status;
if (osd_rdma_handle[2] == -1)
return;
rdma_status = osd_reg_read(RDMA_STATUS);
debug_rdma_status[VIU3] = rdma_status;
OSD_RDMA_VPP2_STATUS_CLEAR_REJECT;
osd_update_vsync_hit_viu3();
reset_rdma_table(VIU3);
//osd_update_scan_mode();
osd_hw_reset(VIU3);
rdma_irq_count[VIU3]++;
osd_rdma_done[VIU3] = true;
{
/*This is a memory barrier*/
wmb();
}
}
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
static void osd_reset_rdma_irq(void *arg)
{
}
static struct rdma_op_s osd_reset_rdma_op = {
osd_reset_rdma_irq,
NULL
};
#endif
static struct rdma_op_s osd_rdma_op = {
osd_rdma_irq,
NULL
};
static struct rdma_op_s osd_rdma_vpp1_op = {
osd_rdma_vpp1_irq,
NULL
};
static struct rdma_op_s osd_rdma_vpp2_op = {
osd_rdma_vpp2_irq,
NULL
};
#endif
static int start_osd_rdma(char channel, u32 vpp_index)
{
#ifndef CONFIG_AMLOGIC_MEDIA_RDMA
char intr_bit = 8 * channel;
char rw_bit = 4 + channel;
char inc_bit = channel;
u32 data32;
data32 = 0;
data32 |= 1 << 7; /* [31: 6] Rsrv. */
data32 |= 1 << 6; /* [31: 6] Rsrv. */
data32 |= 3 << 4;
/* [ 5: 4] ctrl_ahb_wr_burst_size. 0=16; 1=24; 2=32; 3=48. */
data32 |= 3 << 2;
/* [ 3: 2] ctrl_ahb_rd_burst_size. 0=16; 1=24; 2=32; 3=48. */
data32 |= 0 << 1;
/* [ 1] ctrl_sw_reset.*/
data32 |= 0 << 0;
/* [ 0] ctrl_free_clk_enable.*/
osd_reg_write(RDMA_CTRL, data32);
data32 = osd_reg_read(RDMA_ACCESS_AUTO);
/*
* [23: 16] interrupt inputs enable mask for auto-start
* 1: vsync int bit 0
*/
data32 |= 0x1 << intr_bit;
/* [ 6] ctrl_cbus_write_1. 1=Register write; 0=Register read. */
data32 |= 1 << rw_bit;
/*
* [ 2] ctrl_cbus_addr_incr_1.
* 1=Incremental register access; 0=Non-incremental.
*/
data32 &= ~(1 << inc_bit);
osd_reg_write(RDMA_ACCESS_AUTO, data32);
#else
switch (vpp_index) {
case VPU_VPP0:
rdma_config(channel,
RDMA_TRIGGER_VSYNC_INPUT |
RDMA_AUTO_START_MASK);
break;
case VPU_VPP1:
rdma_config(channel,
RDMA_TRIGGER_VPP1_VSYNC_INPUT |
RDMA_AUTO_START_MASK);
break;
case VPU_VPP2:
rdma_config(channel,
RDMA_TRIGGER_VPP2_VSYNC_INPUT |
RDMA_AUTO_START_MASK);
break;
}
osd_hw.line_n_rdma = 0;
#endif
return 1;
}
static int stop_rdma(char channel)
{
#ifndef CONFIG_AMLOGIC_MEDIA_RDMA
char intr_bit = 8 * channel;
u32 data32 = 0x0;
data32 = osd_reg_read(RDMA_ACCESS_AUTO);
data32 &= ~(0x1 <<
intr_bit);
/* [23: 16] interrupt inputs enable mask
* for auto-start 1: vsync int bit 0
*/
osd_reg_write(RDMA_ACCESS_AUTO, data32);
#else
rdma_clear(channel);
if (osd_reset_rdma_handle != -1)
rdma_clear(osd_reset_rdma_handle);
#endif
return 0;
}
static void osd_rdma_config(u32 vpp_index)
{
switch (vpp_index) {
case 0:
rdma_config(osd_rdma_handle[vpp_index],
RDMA_TRIGGER_VSYNC_INPUT |
RDMA_AUTO_START_MASK);
break;
case 1:
rdma_config(osd_rdma_handle[vpp_index],
RDMA_TRIGGER_VPP1_VSYNC_INPUT |
RDMA_AUTO_START_MASK);
break;
case 2:
rdma_config(osd_rdma_handle[vpp_index],
RDMA_TRIGGER_VPP2_VSYNC_INPUT |
RDMA_AUTO_START_MASK);
break;
}
}
void enable_line_n_rdma(void)
{
unsigned long flags = 0;
osd_log_info("%s\n", __func__);
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
rdma_clear(OSD_RDMA_CHANNEL_INDEX);
#endif
spin_lock_irqsave_vpp(0, &flags);
OSD_RDMA_STATUS_CLEAR_REJECT;
if (support_64bit_addr) {
#ifdef CONFIG_ARM64
osd_reg_write(START_ADDR,
table_paddr[0] & 0xffffffff);
osd_reg_write(START_ADDR_MSB,
(table_paddr[0] >> 32) & 0xffffffff);
osd_reg_write(END_ADDR,
(table_paddr[0] - 1) & 0xffffffff);
osd_reg_write(END_ADDR_MSB,
((table_paddr[0] - 1) >> 32) & 0xffffffff);
#else
osd_reg_write(START_ADDR,
table_paddr[0] & 0xffffffff);
osd_reg_write(START_ADDR_MSB, 0);
osd_reg_write(END_ADDR,
(table_paddr[0] - 1) & 0xffffffff);
osd_reg_write(END_ADDR_MSB, 0);
#endif
} else {
osd_reg_write(START_ADDR,
table_paddr[0] & 0xffffffff);
osd_reg_write(END_ADDR,
(table_paddr[0] - 1) & 0xffffffff);
}
item_count[0] = 0;
spin_unlock_irqrestore_vpp(0, flags);
reset_rdma_table(0);
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
rdma_config(OSD_RDMA_CHANNEL_INDEX,
RDMA_TRIGGER_LINE_INPUT |
RDMA_AUTO_START_MASK);
#endif
}
void enable_vsync_rdma(u32 vpp_index)
{
unsigned long flags = 0;
osd_log_info("%s\n", __func__);
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
rdma_clear(osd_rdma_handle[vpp_index]);
#endif
spin_lock_irqsave_vpp(vpp_index, &flags);
OSD_RDMA_STATUS_CLEAR_REJECT;
if (support_64bit_addr) {
#ifdef CONFIG_ARM64
osd_reg_write(START_ADDR,
table_paddr[vpp_index] & 0xffffffff);
osd_reg_write(START_ADDR_MSB,
(table_paddr[vpp_index] >> 32) & 0xffffffff);
osd_reg_write(END_ADDR,
(table_paddr[vpp_index] - 1) & 0xffffffff);
osd_reg_write(END_ADDR_MSB,
((table_paddr[vpp_index] - 1) >> 32) & 0xffffffff);
#else
osd_reg_write(START_ADDR,
table_paddr[vpp_index] & 0xffffffff);
osd_reg_write(START_ADDR_MSB, 0);
osd_reg_write(END_ADDR,
(table_paddr[vpp_index] - 1) & 0xffffffff);
osd_reg_write(END_ADDR_MSB, 0);
#endif
} else {
osd_reg_write(START_ADDR,
table_paddr[vpp_index] & 0xffffffff);
osd_reg_write(END_ADDR,
(table_paddr[vpp_index] - 1) & 0xffffffff);
}
item_count[vpp_index] = 0;
spin_unlock_irqrestore_vpp(vpp_index, flags);
reset_rdma_table(vpp_index);
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
osd_rdma_config(vpp_index);
#endif
}
void osd_rdma_interrupt_done_clear(u32 vpp_index)
{
vsync_irq_count[vpp_index]++;
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
if (osd_rdma_done[vpp_index])
rdma_watchdog_setting(0);
else
rdma_watchdog_setting(1);
#endif
osd_rdma_done[vpp_index] = false;
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
if (rdma_reset_tigger_flag) {
u32 rdma_status;
rdma_status =
osd_reg_read(RDMA_STATUS);
pr_info("osd rdma restart! 0x%x\n",
rdma_status);
osd_rdma_enable(vpp_index, 0);
osd_rdma_enable(vpp_index, 2);
rdma_reset_tigger_flag = 0;
}
#endif
}
int read_rdma_table(u32 vpp_index)
{
int rdma_count = 0;
int i, reg;
if (rdma_debug) {
for (rdma_count = 0; rdma_count < item_count[vpp_index] + 1; rdma_count++)
pr_info("rdma_table addr is 0x%x, value is 0x%x\n",
rdma_table[vpp_index][rdma_count].addr,
rdma_table[vpp_index][rdma_count].val);
reg = 0x1100;
pr_info("RDMA relative registers-----------------\n");
for (i = 0 ; i < 24 ; i++)
pr_info("[0x%x]== 0x%x\n",
reg + i, osd_reg_read(reg + i));
}
return 0;
}
EXPORT_SYMBOL(read_rdma_table);
int osd_rdma_enable(u32 vpp_index, u32 enable)
{
int ret = 0;
unsigned long flags = 0;
if ((enable && rdma_enable[vpp_index]) ||
(!enable && !rdma_enable[vpp_index]))
return 0;
ret = osd_rdma_init();
if (ret != 0)
return -1;
rdma_enable[vpp_index] = enable;
if (enable) {
spin_lock_irqsave_vpp(vpp_index, &flags);
osd_rdma_status_clear_reject(vpp_index);
rdma_start_end_addr_update(vpp_index, table_paddr[vpp_index]);
item_count[vpp_index] = 0;
spin_unlock_irqrestore_vpp(vpp_index, flags);
reset_rdma_table(vpp_index);
start_osd_rdma(osd_rdma_handle[vpp_index], vpp_index);
} else {
stop_rdma(osd_rdma_handle[vpp_index]);
}
return 1;
}
EXPORT_SYMBOL(osd_rdma_enable);
int osd_rdma_reset_and_flush(u32 output_index, u32 reset_bit)
{
int i, ret = 0;
unsigned long flags = 0;
u32 reset_reg_mask;
u32 base;
u32 addr;
u32 value;
spin_lock_irqsave_vpp(output_index, &flags);
reset_reg_mask = reset_bit;
reset_reg_mask &= ~HW_RESET_OSD1_REGS;
if (disable_osd_rdma_reset != 0) {
reset_reg_mask = 0;
reset_bit = 0;
}
if (reset_reg_mask) {
wrtie_reg_internal(output_index, VIU_SW_RESET,
reset_reg_mask);
wrtie_reg_internal(output_index, VIU_SW_RESET, 0);
}
/* same bit, but gxm only reset hardware, not top reg*/
if (osd_hw.osd_meson_dev.cpu_id >= __MESON_CPU_MAJOR_ID_GXM)
reset_bit &= ~HW_RESET_AFBCD_REGS;
i = 0;
base = hw_osd_reg_array[OSD1].osd_ctrl_stat;
while ((reset_bit & HW_RESET_OSD1_REGS) &&
(i < OSD_REG_BACKUP_COUNT)) {
addr = osd_reg_backup[i];
wrtie_reg_internal(output_index, addr, osd_backup[addr - base]);
i++;
}
i = 0;
base = OSD1_AFBCD_ENABLE;
while ((reset_bit & HW_RESET_AFBCD_REGS) &&
(i < OSD_AFBC_REG_BACKUP_COUNT)) {
addr = osd_afbc_reg_backup[i];
value = osd_afbc_backup[addr - base];
if (addr == OSD1_AFBCD_ENABLE)
value |= 0x100;
wrtie_reg_internal(output_index, addr, value);
i++;
}
if (osd_hw.osd_meson_dev.afbc_type == MALI_AFBC &&
!osd_dev_hw.multi_afbc_core &&
reset_bit & HW_RESET_MALI_AFBCD_REGS) {
/* restore mali afbcd regs */
if (osd_hw.afbc_regs_backup) {
int i;
u32 addr;
u32 value;
u32 base = VPU_MAFBC_IRQ_MASK;
for (i = 0; i < MALI_AFBC_REG_BACKUP_COUNT;
i++) {
addr = mali_afbc_reg_backup[i];
value = mali_afbc_backup[addr - base];
wrtie_reg_internal(output_index, addr, value);
}
}
}
if (osd_hw.osd_meson_dev.afbc_type == MALI_AFBC &&
osd_dev_hw.multi_afbc_core) {
u32 afbc_reset;
reset_bit &= ~HW_RESET_MALI_AFBCD_ARB;
afbc_reset = HW_RESET_MALI_AFBCD_REGS;
afbc_reset &= ~HW_RESET_MALI_AFBCD_ARB;
if (reset_bit & afbc_reset) {
/* restore mali afbcd regs */
if (osd_hw.afbc_regs_backup) {
int i;
u32 addr;
u32 value;
u32 base = VPU_MAFBC_IRQ_MASK;
for (i = 0; i < MALI_AFBC_REG_T7_BACKUP_COUNT;
i++) {
addr = mali_afbc_reg_t7_backup[i];
value = mali_afbc_t7_backup[addr - base];
wrtie_reg_internal(output_index, addr, value);
}
}
}
afbc_reset = HW_RESET_MALI_AFBCD1_REGS;
afbc_reset &= ~HW_RESET_MALI_AFBCD_ARB;
if (reset_bit & afbc_reset) {
/* restore mali afbcd regs */
if (osd_hw.afbc_regs_backup) {
int i;
u32 addr;
u32 value;
u32 base = VPU_MAFBC1_IRQ_MASK;
for (i = 0; i < MALI_AFBC1_REG_T7_BACKUP_COUNT;
i++) {
addr = mali_afbc1_reg_t7_backup[i];
value = mali_afbc1_t7_backup[addr - base];
wrtie_reg_internal(output_index, addr, value);
}
}
}
afbc_reset = HW_RESET_MALI_AFBCD2_REGS;
afbc_reset &= ~HW_RESET_MALI_AFBCD_ARB;
if (reset_bit & afbc_reset) {
/* restore mali afbcd regs */
if (osd_hw.afbc_regs_backup) {
int i;
u32 addr;
u32 value;
u32 base = VPU_MAFBC2_IRQ_MASK;
for (i = 0; i < MALI_AFBC2_REG_T7_BACKUP_COUNT;
i++) {
addr = mali_afbc2_reg_t7_backup[i];
value = mali_afbc2_t7_backup[addr - base];
wrtie_reg_internal(output_index, addr, value);
}
}
}
}
if (osd_hw.osd_meson_dev.afbc_type == MALI_AFBC &&
osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE &&
!osd_dev_hw.multi_afbc_core)
wrtie_reg_internal(output_index, VPU_MAFBC_COMMAND, 1);
if (osd_hw.osd_meson_dev.afbc_type == MALI_AFBC &&
osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE &&
osd_dev_hw.multi_afbc_core) {
//if (reset_bit & HW_RESET_MALI_AFBCD_REGS)
if (osd_hw.osd_afbcd[0].enable || osd_hw.osd_afbcd[1].enable)
wrtie_reg_internal(output_index, VPU_MAFBC_COMMAND, 1);
//if (reset_bit & HW_RESET_MALI_AFBCD1_REGS)
if (osd_hw.osd_afbcd[2].enable)
wrtie_reg_internal(output_index, VPU_MAFBC1_COMMAND, 1);
//if (reset_bit & HW_RESET_MALI_AFBCD2_REGS)
if (osd_hw.osd_afbcd[3].enable)
wrtie_reg_internal(output_index, VPU_MAFBC2_COMMAND, 1);
}
if (item_count[output_index] < 500) {
rdma_end_addr_update(output_index,
table_paddr[output_index],
item_count[output_index]);
} else {
pr_info("%s item overflow %d\n",
__func__, item_count[output_index]);
ret = -1;
}
if (dump_reg_trigger > 0) {
for (i = 0; i < item_count[output_index]; i++)
pr_info("dump rdma reg[%d]:0x%x, data:0x%x\n",
i, rdma_table[output_index][i].addr,
rdma_table[output_index][i].val);
dump_reg_trigger--;
}
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
if (osd_reset_rdma_handle != -1)
osd_reset_rdma_func(reset_bit &
HW_RESET_OSD1_REGS);
#endif
spin_unlock_irqrestore_vpp(output_index, flags);
return ret;
}
EXPORT_SYMBOL(osd_rdma_reset_and_flush);
static void osd_rdma_release(struct device *dev)
{
int i, vpp_num;
vpp_num = osd_hw.vpp_num;
for (i = 0; i < vpp_num; i++)
dma_free_coherent(osd_rdma_dev,
PAGE_SIZE,
osd_rdma_table_virt[i],
(dma_addr_t)&osd_rdma_table_phy[i]);
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
if (osd_reset_rdma_handle != -1) {
rdma_unregister(osd_reset_rdma_handle);
osd_reset_rdma_handle = -1;
}
for (i = 0; i < vpp_num; i++) {
if (osd_rdma_handle[i] != -1) {
rdma_unregister(osd_rdma_handle[i]);
osd_rdma_handle[i] = -1;
}
}
#endif
}
#ifdef OSD_RDMA_ISR
static irqreturn_t osd_rdma_isr(int irq, void *dev_id)
{
u32 rdma_status;
rdma_status = osd_reg_read(RDMA_STATUS);
debug_rdma_status = rdma_status;
if (rdma_status & (1 << (24 + OSD_RDMA_CHANNEL_INDEX))) {
OSD_RDMA_STATUS_CLEAR_REJECT;
reset_rdma_table();
osd_update_scan_mode();
osd_update_3d_mode();
osd_mali_afbc_start();
osd_update_vsync_hit();
osd_hw_reset(VIU1);
rdma_irq_count++;
{
/*This is a memory barrier*/
wmb();
}
osd_reg_write(RDMA_CTRL,
1 << (24 + OSD_RDMA_CHANNEL_INDEX));
} else {
rdma_lost_count++;
}
rdma_status = osd_reg_read(RDMA_STATUS);
if (rdma_status & 0xf7000000) {
if (!second_rdma_irq)
pr_info("osd rdma irq as first function call, status: 0x%x\n",
rdma_status);
pr_info("osd rdma miss done isr, status: 0x%x\n", rdma_status);
osd_reg_write(RDMA_CTRL, rdma_status & 0xf7000000);
}
return IRQ_HANDLED;
}
#endif
static int osd_rdma_init(void)
{
int ret = -1, i;
u32 vpp_num = osd_hw.vpp_num;
if (osd_rdma_init_flag)
return 0;
osd_rdma_dev = kzalloc(sizeof(*osd_rdma_dev), GFP_KERNEL);
if (!osd_rdma_dev) {
/* osd_log_err("osd rdma init error!\n"); */
return -1;
}
for (i = 0; i < vpp_num; i++) {
rdma_temp_tbl[i] = kmalloc(RDMA_TEMP_TBL_SIZE, GFP_KERNEL);
if (!rdma_temp_tbl[i]) {
/* osd_log_err("osd rdma alloc temp_tbl error!\n"); */
goto error2;
}
}
osd_rdma_dev->release = osd_rdma_release;
dev_set_name(osd_rdma_dev, "osd-rdma-dev");
dev_set_drvdata(osd_rdma_dev, osd_rdma_dev);
ret = device_register(osd_rdma_dev);
if (ret) {
osd_log_err("register rdma dev error\n");
goto error1;
}
#ifdef OSD_RDMA_ISR
second_rdma_irq = 0;
#endif
dump_reg_trigger = 0;
osd_rdma_dev->coherent_dma_mask = DMA_BIT_MASK(32);
osd_rdma_dev->dma_mask = &osd_rdma_dev->coherent_dma_mask;
of_dma_configure(osd_rdma_dev, osd_rdma_dev->of_node, true);
for (i = 0; i < vpp_num; i++) {
osd_rdma_table_virt[i] =
dma_alloc_coherent(osd_rdma_dev, PAGE_SIZE,
&osd_rdma_table_phy[i], GFP_KERNEL);
if (!osd_rdma_table_virt[i]) {
osd_log_err("osd rdma dma alloc failed!\n");
goto error2;
}
table_vaddr[i] = osd_rdma_table_virt[i];
table_paddr[i] = osd_rdma_table_phy[i];
rdma_table[i] = (struct rdma_table_item *)table_vaddr[i];
if (!rdma_table[i]) {
osd_log_err("%s: failed to remap rmda_table_addr\n", __func__);
goto error2;
}
}
#ifdef OSD_RDMA_ISR
if (rdma_mgr_irq_request) {
second_rdma_irq = 1;
pr_info("osd rdma request irq as second interrput function!\n");
}
if (request_irq(INT_RDMA, &osd_rdma_isr,
IRQF_SHARED, "osd_rdma", (void *)"osd_rdma")) {
osd_log_err("can't request irq for rdma\n");
goto error2;
}
#endif
osd_rdma_init_flag = true;
osd_reg_write(OSD_RDMA_FLAG_REG, 0x0);
osd_reg_write(OSD_RDMA_FLAG_REG_VPP1, 0x0);
osd_reg_write(OSD_RDMA_FLAG_REG_VPP2, 0x0);
#ifdef CONFIG_AMLOGIC_MEDIA_RDMA
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
if (osd_hw.osd_meson_dev.cpu_id >= __MESON_CPU_MAJOR_ID_GXL &&
osd_hw.osd_meson_dev.cpu_id <= __MESON_CPU_MAJOR_ID_TXL) {
osd_reset_rdma_op.arg = osd_rdma_dev;
osd_reset_rdma_handle = rdma_register(&osd_reset_rdma_op,
NULL, PAGE_SIZE);
pr_info("%s:osd reset rdma handle = %d.\n", __func__,
osd_reset_rdma_handle);
}
#endif
osd_rdma_op.arg = osd_rdma_dev;
osd_rdma_handle[0] = rdma_register(&osd_rdma_op,
NULL, PAGE_SIZE);
pr_info("%s:osd rdma handle[0] = %d.\n", __func__,
osd_rdma_handle[0]);
if (osd_hw.osd_meson_dev.has_vpp1 &&
osd_hw.display_dev_cnt == 2) {
/* vpp1 used then register rdma channel */
osd_rdma_handle[1] = rdma_register(&osd_rdma_vpp1_op,
NULL, PAGE_SIZE);
pr_info("%s:osd rdma handle[1] = %d.\n", __func__,
osd_rdma_handle[1]);
}
if (osd_hw.osd_meson_dev.has_vpp2 &&
osd_hw.display_dev_cnt == 3) {
/* vpp2 used then register rdma channel */
osd_rdma_handle[2] = rdma_register(&osd_rdma_vpp2_op,
NULL, PAGE_SIZE);
pr_info("%s:osd rdma handle[2] = %d.\n", __func__,
osd_rdma_handle[2]);
}
#else
osd_rdma_handle[0] = 3; /* use channel 3 as default */
#endif
if (osd_hw.osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_T7)
support_64bit_addr = 1;
else
support_64bit_addr = 0;
return 0;
error2:
device_unregister(osd_rdma_dev);
error1:
kfree(osd_rdma_dev);
osd_rdma_dev = NULL;
for (i = 0; i < vpp_num; i++) {
kfree(rdma_temp_tbl[i]);
rdma_temp_tbl[i] = NULL;
}
return -1;
}
int osd_rdma_uninit(void)
{
int i;
if (osd_rdma_init_flag) {
device_unregister(osd_rdma_dev);
kfree(osd_rdma_dev);
osd_rdma_dev = NULL;
for (i = 0; i < VPP_NUM; i++) {
kfree(rdma_temp_tbl[i]);
rdma_temp_tbl[i] = NULL;
}
osd_rdma_init_flag = false;
}
return 0;
}
EXPORT_SYMBOL(osd_rdma_uninit);
static int param_vpp_num = VPP_NUM;
module_param_array(item_count, uint, &param_vpp_num, 0664);
MODULE_PARM_DESC(item_count, "\n item_count\n");
module_param_array(table_paddr, ulong, &param_vpp_num, 0664);
MODULE_PARM_DESC(table_paddr, "\n table_paddr\n");
module_param_array(debug_rdma_status, uint, &param_vpp_num, 0664);
MODULE_PARM_DESC(debug_rdma_status, "\n debug_rdma_status\n");
module_param_array(rdma_irq_count, uint, &param_vpp_num, 0664);
MODULE_PARM_DESC(rdma_irq_count, "\n rdma_irq_count\n");
module_param_array(rdma_lost_count, uint, &param_vpp_num, 0664);
MODULE_PARM_DESC(rdma_lost_count, "\n rdma_lost_count\n");
module_param_array(rdma_recovery_count, uint, &param_vpp_num, 0664);
MODULE_PARM_DESC(rdma_recovery_count, "\n rdma_recovery_count\n");
module_param_array(vsync_irq_count, uint, &param_vpp_num, 0664);
MODULE_PARM_DESC(vsync_irq_count, "\n vsync_irq_count\n");
MODULE_PARM_DESC(rdma_debug, "\n rdma_debug\n");
module_param(rdma_debug, uint, 0664);
MODULE_PARM_DESC(dump_reg_trigger, "\n dump_reg_trigger\n");
module_param(dump_reg_trigger, uint, 0664);
MODULE_PARM_DESC(rdma_hdr_delay, "\n rdma_hdr_delay\n");
module_param(rdma_hdr_delay, uint, 0664);