356 lines
12 KiB
C
356 lines
12 KiB
C
|
/*
|
||
|
* sunxi_dspo/dspo_reg.c
|
||
|
*
|
||
|
* Copyright (c) 2007-2021 Allwinnertech Co., Ltd.
|
||
|
* Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
|
||
|
*
|
||
|
* This software is licensed under the terms of the GNU General Public
|
||
|
* License version 2, as published by the Free Software Foundation, and
|
||
|
* may be copied, distributed, and modified under those terms.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
*/
|
||
|
#include "dspo_param.h"
|
||
|
#include "dspo_reg.h"
|
||
|
|
||
|
volatile __dspo_dev *dspo_dev[1];
|
||
|
|
||
|
void dspo_set_reg_base(u32 sel, unsigned long base)
|
||
|
{
|
||
|
dspo_dev[sel] = (__dspo_dev *)(base);
|
||
|
}
|
||
|
|
||
|
void dspo_module_en(u32 dev_sel, u32 module_en, u32 sepa_sync_en)
|
||
|
{
|
||
|
dspo_dev[dev_sel]->module_ctrl.bits.seperate_sync_en = sepa_sync_en;
|
||
|
dspo_dev[dev_sel]->module_ctrl.bits.dspo_mudule_en = module_en;
|
||
|
}
|
||
|
|
||
|
void dspo_dma_aidb_sel(u32 dev_sel, u32 sel)
|
||
|
{
|
||
|
dspo_dev[dev_sel]->module_ctrl.bits.dma_aidb_sel = sel;
|
||
|
}
|
||
|
|
||
|
void dspo_soft_rst(u32 dev_sel, u32 rst)
|
||
|
{
|
||
|
dspo_dev[dev_sel]->module_ctrl.bits.soft_rst = rst;
|
||
|
}
|
||
|
|
||
|
void dspo_fmt_set(u32 dev_sel, u32 data_seq_sel, u32 sync_fmt, u32 data_width,
|
||
|
u32 interlace)
|
||
|
{
|
||
|
dspo_dev[dev_sel]->fmt_ctrl.bits.data_seq_sel = data_seq_sel;
|
||
|
dspo_dev[dev_sel]->fmt_ctrl.bits.embedded_sync_fmt = sync_fmt;
|
||
|
dspo_dev[dev_sel]->fmt_ctrl.bits.output_data_width = data_width;
|
||
|
dspo_dev[dev_sel]->fmt_ctrl.bits.interlace_mode = interlace;
|
||
|
}
|
||
|
|
||
|
void dspo_yuv_data_src_sel(u32 dev_sel, u32 sel)
|
||
|
{
|
||
|
dspo_dev[dev_sel]->fmt_ctrl.bits.data_src_sel = sel;
|
||
|
}
|
||
|
|
||
|
void dspo_chroma_spl_set(u32 dev_sel, u8 cr_type, u8 cb_type)
|
||
|
{
|
||
|
dspo_dev[dev_sel]->hor_spl_ctrl.bits.cb_hori_spl_type = cb_type;
|
||
|
dspo_dev[dev_sel]->hor_spl_ctrl.bits.cr_hori_spl_type = cr_type;
|
||
|
}
|
||
|
|
||
|
void dspo_clamp_set(u32 dev_sel, u16 y_min, u16 y_max, u16 cb_min, u16 cb_max,
|
||
|
u16 cr_min, u16 cr_max)
|
||
|
{
|
||
|
dspo_dev[dev_sel]->clamp0.bits.y_val_range_min = y_min;
|
||
|
dspo_dev[dev_sel]->clamp0.bits.y_val_range_max = y_max;
|
||
|
dspo_dev[dev_sel]->clamp1.bits.cb_val_range_min = cb_min;
|
||
|
dspo_dev[dev_sel]->clamp1.bits.cb_val_range_max = cb_max;
|
||
|
dspo_dev[dev_sel]->clamp2.bits.cr_val_range_min = cr_min;
|
||
|
dspo_dev[dev_sel]->clamp2.bits.cr_val_range_max = cr_max;
|
||
|
}
|
||
|
|
||
|
void dspo_sync_pol_set(u32 dev_sel, u8 hb_pol, u8 vb_pol, u8 field_pol)
|
||
|
{
|
||
|
dspo_dev[dev_sel]->sync_ctrl.bits.h_blank_pol = hb_pol;
|
||
|
dspo_dev[dev_sel]->sync_ctrl.bits.v_blank_pol = vb_pol;
|
||
|
dspo_dev[dev_sel]->sync_ctrl.bits.field_pol = field_pol;
|
||
|
}
|
||
|
|
||
|
void dspo_dclk_adjust(u32 dev_sel, u8 dclk_invt, u8 dly_en, u8 dly_num)
|
||
|
{
|
||
|
dspo_dev[dev_sel]->sync_ctrl.bits.dclk_invert = dclk_invt;
|
||
|
dspo_dev[dev_sel]->sync_ctrl.bits.dclk_dly_num = dly_num;
|
||
|
dspo_dev[dev_sel]->sync_ctrl.bits.dclk_dly_en = dly_en;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
u32 dspo_get_curline(u32 sel)
|
||
|
{
|
||
|
u32 line = dspo_dev[sel]->status.bits.current_line;
|
||
|
return line;
|
||
|
}
|
||
|
|
||
|
u32 dspo_get_field(u32 sel)
|
||
|
{
|
||
|
u32 field = dspo_dev[sel]->status.bits.field_pol_sta;
|
||
|
return field;
|
||
|
}
|
||
|
|
||
|
void dspo_irq_en(u32 sel, u32 int_type, u32 line)
|
||
|
{
|
||
|
if (int_type == DSPO_V_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.vb_int_en = 1;
|
||
|
} else if (int_type == DSPO_L_INT) {
|
||
|
dspo_dev[sel]->line_int_num.bits.int_line_num = line;
|
||
|
dspo_dev[sel]->int_ctrl.bits.line_match_int_en = 1;
|
||
|
} else if (int_type == DSPO_DMA_DONE_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.dma_done_int_en = 1;
|
||
|
} else if (int_type == DSPO_DMA_DESC_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.dma_desc_int_en = 1;
|
||
|
} else if (int_type == DSPO_FRAME_DONE_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.frame_int_en = 1;
|
||
|
} else {
|
||
|
printk("irq type 0x%x error!!\n", int_type);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void dspo_irq_disable(u32 sel, u32 int_type)
|
||
|
{
|
||
|
if (int_type == DSPO_V_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.vb_int_en = 0;
|
||
|
} else if (int_type == DSPO_L_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.line_match_int_en = 0;
|
||
|
} else if (int_type == DSPO_DMA_DONE_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.dma_done_int_en = 0;
|
||
|
} else if (int_type == DSPO_DMA_DESC_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.dma_desc_int_en = 0;
|
||
|
} else if (int_type == DSPO_FRAME_DONE_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.frame_int_en = 0;
|
||
|
} else if (int_type == DSPO_LINE_DONE_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.line_int_en = 0;
|
||
|
} else if (int_type == DSPO_UV_LINE_DONE_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.dma_uv_line_int_en = 0;
|
||
|
} else if (int_type == DSPO_UV_BUF_UF_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.line_buf_uv_underflow_int_en = 0;
|
||
|
} else if (int_type == DSPO_UV_BUF_OF_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.line_buf_uv_overflow_int_en = 0;
|
||
|
} else if (int_type == DSPO_Y_BUF_UF_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.line_buf_y_underflow_int_en = 0;
|
||
|
} else if (int_type == DSPO_Y_BUF_OF_INT) {
|
||
|
dspo_dev[sel]->int_ctrl.bits.line_buf_y_overflow_int_en = 0;
|
||
|
} else {
|
||
|
printk("irq type error!!\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
u32 dspo_irq_process(u32 sel)
|
||
|
{
|
||
|
u32 ret = 0;
|
||
|
if ((dspo_dev[sel]->int_ctrl.bits.vb_int_flag) &&
|
||
|
(dspo_dev[sel]->int_ctrl.bits.vb_int_en))
|
||
|
ret = DSPO_V_INT;
|
||
|
else if ((dspo_dev[sel]->int_ctrl.bits.line_match_int_flag) &&
|
||
|
(dspo_dev[sel]->int_ctrl.bits.line_match_int_en))
|
||
|
ret = DSPO_L_INT;
|
||
|
else if ((dspo_dev[sel]->int_ctrl.bits.dma_done_int_flag) &&
|
||
|
(dspo_dev[sel]->int_ctrl.bits.dma_done_int_en))
|
||
|
ret = DSPO_DMA_DONE_INT;
|
||
|
else if ((dspo_dev[sel]->int_ctrl.bits.dma_desc_int_flag) &&
|
||
|
(dspo_dev[sel]->int_ctrl.bits.dma_desc_int_en))
|
||
|
ret = DSPO_DMA_DESC_INT;
|
||
|
else if ((dspo_dev[sel]->int_ctrl.bits.frame_int_flag) &&
|
||
|
(dspo_dev[sel]->int_ctrl.bits.frame_int_en))
|
||
|
ret = DSPO_FRAME_DONE_INT;
|
||
|
|
||
|
if (dspo_dev[sel]->int_ctrl.bits.line_buf_uv_underflow_int_flag)
|
||
|
ret |= DSPO_UV_BUF_UF_INT;
|
||
|
else if (dspo_dev[sel]->int_ctrl.bits.line_buf_uv_overflow_int_flag)
|
||
|
ret |= DSPO_UV_BUF_OF_INT;
|
||
|
else if (dspo_dev[sel]->int_ctrl.bits.line_buf_y_underflow_int_flag)
|
||
|
ret |= DSPO_Y_BUF_UF_INT;
|
||
|
else if (dspo_dev[sel]->int_ctrl.bits.line_buf_y_overflow_int_flag)
|
||
|
ret |= DSPO_Y_BUF_OF_INT;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
u32 dspo_clr_irq(u32 sel, u32 int_type)
|
||
|
{
|
||
|
if (int_type == DSPO_V_INT)
|
||
|
dspo_dev[sel]->int_ctrl.bits.vb_int_flag = 0;
|
||
|
else if (int_type == DSPO_L_INT)
|
||
|
dspo_dev[sel]->int_ctrl.bits.line_match_int_flag = 0;
|
||
|
else if (int_type == DSPO_DMA_DONE_INT)
|
||
|
dspo_dev[sel]->int_ctrl.bits.dma_done_int_flag = 0;
|
||
|
else if (int_type == DSPO_DMA_DESC_INT)
|
||
|
dspo_dev[sel]->int_ctrl.bits.dma_desc_int_flag = 0;
|
||
|
else if (int_type == DSPO_FRAME_DONE_INT)
|
||
|
dspo_dev[sel]->int_ctrl.bits.frame_int_flag = 0;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void dspo_timing_set(u32 sel, u32 h_active, u32 hbp, u32 hfp, u32 hsync,
|
||
|
u32 v_active, u32 vbp, u32 v_total, u32 vfp, u32 vsync,
|
||
|
u32 interlace, u32 itl_mode)
|
||
|
{
|
||
|
dspo_dev[sel]->h_timing0.bits.h_sync = hsync;
|
||
|
dspo_dev[sel]->h_timing0.bits.h_fp = hfp;
|
||
|
dspo_dev[sel]->h_timing1.bits.h_active = h_active;
|
||
|
dspo_dev[sel]->h_timing1.bits.h_bp = hbp;
|
||
|
dspo_dev[sel]->v_timing0.bits.v_sync = vsync;
|
||
|
dspo_dev[sel]->v_timing0.bits.v_fp = vfp;
|
||
|
dspo_dev[sel]->v_timing1.bits.v_active = v_active; ///(interlace+1)-1;
|
||
|
dspo_dev[sel]->v_timing1.bits.v_bp = vbp;
|
||
|
|
||
|
dspo_dev[sel]->interlace_mode.bits.v_total_para =
|
||
|
v_total * 2 / (interlace + 1);
|
||
|
if (interlace) {
|
||
|
dspo_dev[sel]->interlace_mode.bits.interlace_mode_op = itl_mode;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void dspo_vtotal_cfg_auto_set(u32 sel, u32 set)
|
||
|
{
|
||
|
dspo_dev[sel]->interlace_mode.bits.V_total_cfg_auto = set;
|
||
|
}
|
||
|
|
||
|
void dspo_dma_start(u32 sel)
|
||
|
{
|
||
|
dspo_dev[sel]->dma_start.bits.dma_start = 1;
|
||
|
}
|
||
|
|
||
|
void dspo_dma_ctrl_set(u32 sel, u32 desc_mode, u32 block_size_sel,
|
||
|
u32 input_data_type)
|
||
|
{
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.descriptor_mode = desc_mode;
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.dma_block_size_sel = block_size_sel;
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.input_data_type = input_data_type;
|
||
|
}
|
||
|
|
||
|
void dspo_dma_start_check_set(u32 sel, u32 start_chk_dly, u32 start_chk_en)
|
||
|
{
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.dma_start_check = start_chk_dly;
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.dma_start_check_en = start_chk_en;
|
||
|
}
|
||
|
|
||
|
void dspo_tcon_manu_set(u32 sel, u32 manu_mode, u32 manu_en)
|
||
|
{
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.tcon_manu = manu_mode;
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.tcon_manu_en = manu_en;
|
||
|
}
|
||
|
|
||
|
void dspo_work_mode_set(u32 sel, u32 mode)
|
||
|
{
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.tcon_tri_mode = mode;
|
||
|
if (mode == 1) {
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.tcon_manu = 1;
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.tcon_manu_en = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void dspo_tcon_tri_on(u32 sel)
|
||
|
{
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.tcon_tri = 1;
|
||
|
}
|
||
|
|
||
|
void dspo_tcon_tri_off(u32 sel)
|
||
|
{
|
||
|
dspo_dev[sel]->dma_tcon_ctrl.bits.tcon_tri = 0;
|
||
|
}
|
||
|
|
||
|
void dspo_dma_size_set(u32 sel, u32 x, u32 y)
|
||
|
{
|
||
|
dspo_dev[sel]->dma_size.bits.x = x;
|
||
|
dspo_dev[sel]->dma_size.bits.y = y;
|
||
|
}
|
||
|
|
||
|
void dspo_dma_y_addr_set(u32 sel, u32 addr)
|
||
|
{
|
||
|
dspo_dev[sel]->dma_y_base_addr.bits.buf0_addr = (addr >> 2);
|
||
|
}
|
||
|
|
||
|
void dspo_dma_uv_addr_set(u32 sel, u32 addr)
|
||
|
{
|
||
|
dspo_dev[sel]->dma_crcb_base_addr.bits.buf1_addr = (addr >> 2);
|
||
|
}
|
||
|
|
||
|
void dspo_dma_buf_line_stride_set(u32 sel, u32 y_line_stride,
|
||
|
u32 uv_line_stride)
|
||
|
{
|
||
|
dspo_dev[sel]->dma_buf_line_stride.bits.buf0_line_stride =
|
||
|
y_line_stride;
|
||
|
dspo_dev[sel]->dma_buf_line_stride.bits.buf1_line_stride =
|
||
|
uv_line_stride;
|
||
|
}
|
||
|
|
||
|
void dspo_desc_base_addr_set(u32 sel, u32 addr)
|
||
|
{
|
||
|
dspo_dev[sel]->desc_base_addr.bits.desc_base_addr = addr;
|
||
|
}
|
||
|
|
||
|
void dspo_ceu_enable(u32 sel, u32 en)
|
||
|
{
|
||
|
dspo_dev[sel]->csc_ceu_ctl.bits.ceu_en = en;
|
||
|
}
|
||
|
|
||
|
|
||
|
void dspo_ceu_mul_val_set(u32 sel, u32 rr, u32 rg, u32 rb, u32 gr, u32 gg,
|
||
|
u32 gb, u32 br, u32 bg, u32 bb)
|
||
|
{
|
||
|
dspo_dev[sel]->csc_ceu_coef_mul_rr.bits.ceu_coef_mul_val = rr;
|
||
|
dspo_dev[sel]->csc_ceu_coef_mul_rg.bits.ceu_coef_mul_val = rg;
|
||
|
dspo_dev[sel]->csc_ceu_coef_mul_rb.bits.ceu_coef_mul_val = rb;
|
||
|
dspo_dev[sel]->csc_ceu_coef_mul_gr.bits.ceu_coef_mul_val = gr;
|
||
|
dspo_dev[sel]->csc_ceu_coef_mul_gg.bits.ceu_coef_mul_val = gg;
|
||
|
dspo_dev[sel]->csc_ceu_coef_mul_gb.bits.ceu_coef_mul_val = gb;
|
||
|
dspo_dev[sel]->csc_ceu_coef_mul_br.bits.ceu_coef_mul_val = br;
|
||
|
dspo_dev[sel]->csc_ceu_coef_mul_bg.bits.ceu_coef_mul_val = bg;
|
||
|
dspo_dev[sel]->csc_ceu_coef_mul_bb.bits.ceu_coef_mul_val = bb;
|
||
|
}
|
||
|
|
||
|
void dspo_ceu_add_val_set(u32 sel, u32 rc, u32 gc, u32 bc)
|
||
|
{
|
||
|
dspo_dev[sel]->csc_ceu_coef_rc.bits.ceu_coef_add_val = rc;
|
||
|
dspo_dev[sel]->csc_ceu_coef_gc.bits.ceu_coef_add_val = gc;
|
||
|
dspo_dev[sel]->csc_ceu_coef_bc.bits.ceu_coef_add_val = bc;
|
||
|
}
|
||
|
|
||
|
void dspo_ceu_range_set(u32 sel, u32 ymax, u32 ymin, u32 umax, u32 umin,
|
||
|
u32 vmax, u32 vmin)
|
||
|
{
|
||
|
dspo_dev[sel]->csc_ceu_coef_rang_y.bits.ceu_coef_range_max = ymax;
|
||
|
dspo_dev[sel]->csc_ceu_coef_rang_y.bits.ceu_coef_range_min = ymin;
|
||
|
dspo_dev[sel]->csc_ceu_coef_rang_u.bits.ceu_coef_range_max = umax;
|
||
|
dspo_dev[sel]->csc_ceu_coef_rang_u.bits.ceu_coef_range_min = umin;
|
||
|
dspo_dev[sel]->csc_ceu_coef_rang_v.bits.ceu_coef_range_max = vmax;
|
||
|
dspo_dev[sel]->csc_ceu_coef_rang_v.bits.ceu_coef_range_min = vmin;
|
||
|
}
|
||
|
|
||
|
void dspo_dma_mode_line_buf_range_set(u32 sel, u32 x)
|
||
|
{
|
||
|
dspo_dev[sel]->line_buf_rang0.bits.dma_mode_lb_y_cap = x;
|
||
|
dspo_dev[sel]->line_buf_rang1.bits.dma_mode_lb_uv_cap = x;
|
||
|
}
|
||
|
|
||
|
u32 dspo_is_line_buf_ready(u32 sel)
|
||
|
{
|
||
|
return dspo_dev[sel]->line_buf_rang3.bits.line_buf_cap_rdy;
|
||
|
}
|
||
|
|
||
|
void dspo_rgb2yuv(u32 sel)
|
||
|
{
|
||
|
u32 CEU_R_Para[6] = {0x0041, 0x0081, 0x0019, 0x00100, 0x00, 0xFF};
|
||
|
u32 CEU_G_Para[6] = {0x1025, 0x104a, 0x0070, 0x00800, 0x00, 0xFF};
|
||
|
u32 CEU_B_Para[6] = {0x0070, 0x107e, 0x1012, 0x00800, 0x00, 0xFF};
|
||
|
|
||
|
dspo_ceu_mul_val_set(sel, CEU_R_Para[0], CEU_R_Para[1], CEU_R_Para[2],
|
||
|
CEU_G_Para[0], CEU_G_Para[1], CEU_G_Para[2],
|
||
|
CEU_B_Para[0], CEU_B_Para[1], CEU_B_Para[2]);
|
||
|
dspo_ceu_add_val_set(sel, CEU_R_Para[3], CEU_G_Para[3], CEU_G_Para[3]);
|
||
|
dspo_ceu_range_set(sel, CEU_R_Para[5], CEU_R_Para[4], CEU_G_Para[5],
|
||
|
CEU_G_Para[4], CEU_B_Para[5], CEU_B_Para[4]);
|
||
|
dspo_ceu_enable(sel, 1);
|
||
|
}
|