Files
vi-kernel/vvcam_ry/isp/isp_miv1.c
2022-09-13 10:34:22 +08:00

627 lines
20 KiB
C
Executable File

/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2020 VeriSilicon Holdings Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (c) 2020 VeriSilicon Holdings Co., Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program;
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
#ifdef ISP_MIV1
extern MrvAllRegister_t *all_regs;
static int getRawBit(u32 type, u32 *bit, u32 *len)
{
*len = 16;
switch (type) {
case ISP_PICBUF_TYPE_RAW8:
*bit = 0;
*len = 8;
break;
#if 0 /* normal process, need pass type from engine. */
case ISP_PICBUF_TYPE_RAW10:
*bit = 1;
break;
case ISP_PICBUF_TYPE_RAW12:
*bit = 2;
break;
case ISP_PICBUF_TYPE_RAW14:
*bit = 3;
break;
case ISP_PICBUF_TYPE_RAW16:
*bit = 4;
break;
#else /* WA */
case ISP_PICBUF_TYPE_RAW10:
case ISP_PICBUF_TYPE_RAW12:
case ISP_PICBUF_TYPE_RAW14:
case ISP_PICBUF_TYPE_RAW16:
*bit = 4;
break;
#endif
default:
pr_err("unsupport raw formt: %d\n", type);
return -1;
}
return 0;
}
int isp_ioc_cfg_dma(struct isp_ic_dev *dev, void __user *args)
{
return 0;
}
int isp_ioc_start_dma_read(struct isp_ic_dev *dev, void __user *args)
{
struct isp_dma_context dma;
u32 mi_dma_ctrl = isp_read_reg(dev, REG_ADDR(mi_dma_ctrl));
u32 llength = 0, mcm_rd_fmt_bit = 0;
u32 mi_imsc = 0, mcm_fmt = 0;
pr_info("enter %s\n", __func__);
viv_check_retval(copy_from_user(&dma, args, sizeof(dma)));
REG_SET_SLICE(mi_dma_ctrl, MRV_MI_DMA_BURST_LEN_LUM, dma.burst_y);
REG_SET_SLICE(mi_dma_ctrl, MRV_MI_DMA_BURST_LEN_CHROM, dma.burst_c);
isp_write_reg(dev, REG_ADDR(mi_dma_y_pic_start_ad),
(MRV_MI_DMA_Y_PIC_START_AD_MASK & dma.base));
getRawBit(dma.type, &mcm_rd_fmt_bit, &llength);
llength = dma.width * llength / 8;
REG_SET_SLICE(mcm_fmt, MCM_RD_RAW_BIT, mcm_rd_fmt_bit);
isp_write_reg(dev, REG_ADDR(mi_dma_y_pic_width),
(MRV_MI_DMA_Y_PIC_WIDTH_MASK & dma.width));
isp_write_reg(dev, REG_ADDR(mi_dma_y_llength),
(MRV_MI_DMA_Y_LLENGTH_MASK & llength));
isp_write_reg(dev, REG_ADDR(mi_dma_y_pic_size),
(MRV_MI_DMA_Y_PIC_SIZE_MASK & (llength * dma.height)));
isp_write_reg(dev, REG_ADDR(mi_dma_cb_pic_start_ad), 0);
isp_write_reg(dev, REG_ADDR(mi_dma_cr_pic_start_ad), 0);
isp_write_reg(dev, REG_ADDR(mi_dma_ctrl), mi_dma_ctrl);
isp_write_reg(dev, REG_ADDR(mi_dma_status), 0);
isp_write_reg(dev, REG_ADDR(mi_dma_y_raw_fmt), mcm_fmt);
isp_write_reg(dev, REG_ADDR(mi_dma_y_raw_lval),
(MRV_MI_DMA_Y_LLENGTH_MASK & llength));
mi_imsc = isp_read_reg(dev, REG_ADDR(mi_imsc));
mi_imsc |= MRV_MI_DMA_READY_MASK;
isp_write_reg(dev, REG_ADDR(mi_imsc), mi_imsc);
isp_write_reg(dev, REG_ADDR(mi_dma_start), MRV_MI_DMA_START_MASK);
return 0;
}
u32 getScaleFactor(u32 src, u32 dst)
{
if (dst > src) {
return ((65536 * (src - 1)) / (dst - 1));
} else if (dst < src) {
return ((65536 * (dst - 1)) / (src - 1)) + 1;
}
return 65536;
}
int set_scaling(int id, struct isp_ic_dev *dev, bool stabilization)
{
u32 addr, ctrl;
u32 iw, ih, ow, oh;
u32 inputWidth, inputHeight, outputWidth, outputHeight;
u32 scale_hy, scale_hcb, scale_hcr, scale_vy, scale_vc;
struct isp_mi_data_path_context *path = &dev->mi.path[id];
if (id == IC_MI_PATH_MAIN) { /* mp */
addr = REG_ADDR(mrsz_ctrl);
} else if (id == IC_MI_PATH_SELF) { /* sp */
addr = REG_ADDR(srsz_ctrl);
} else {
return -EINVAL;
}
inputWidth = path->in_width;
inputHeight = path->in_height;
outputWidth = path->out_width;
outputHeight = path->out_height;
if (stabilization) { /* enabled image stabilization. */
inputWidth = isp_read_reg(dev, REG_ADDR(isp_is_h_size));
inputHeight = isp_read_reg(dev, REG_ADDR(isp_is_v_size));
}
ctrl = isp_read_reg(dev, addr);
iw = inputWidth / 2;
ih = inputHeight;
ow = outputWidth / 2;
oh = outputHeight;
switch (path->in_mode) {
case IC_MI_DATAMODE_YUV422:
oh = outputHeight;
break;
case IC_MI_DATAMODE_YUV420:
oh = outputHeight / 2; /* scale cbcr */
break;
default:
return -EFAULT;
}
REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_HY_ENABLE,
inputWidth != outputWidth);
REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_VY_ENABLE,
inputHeight != outputHeight);
REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_HY_UP, inputWidth < outputWidth);
REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_VY_UP, inputHeight < outputHeight);
scale_hy = getScaleFactor(inputWidth, outputWidth);
scale_vy = getScaleFactor(inputHeight, outputHeight);
REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_HC_ENABLE, iw != ow);
REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_VC_ENABLE, ih != oh);
REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_HC_UP, iw < ow);
REG_SET_SLICE(ctrl, MRV_MRSZ_SCALE_VC_UP, ih < oh);
scale_hcr = getScaleFactor(iw, ow);
scale_hcb = getScaleFactor(iw, ow);
scale_vc = getScaleFactor(ih, oh);
REG_SET_SLICE(ctrl, MRV_MRSZ_AUTO_UPD, 1);
if (id == IC_MI_PATH_MAIN) {
isp_write_reg(dev, REG_ADDR(mrsz_scale_vc), scale_vc);
isp_write_reg(dev, REG_ADDR(mrsz_scale_vy), scale_vy);
isp_write_reg(dev, REG_ADDR(mrsz_scale_hcr), scale_hcr);
isp_write_reg(dev, REG_ADDR(mrsz_scale_hcb), scale_hcb);
isp_write_reg(dev, REG_ADDR(mrsz_scale_hy), scale_hy);
isp_write_reg(dev, REG_ADDR(mrsz_ctrl),
ctrl | MRV_MRSZ_CFG_UPD_MASK);
} else if (id == IC_MI_PATH_SELF) {
isp_write_reg(dev, REG_ADDR(srsz_scale_vc), scale_vc);
isp_write_reg(dev, REG_ADDR(srsz_scale_vy), scale_vy);
isp_write_reg(dev, REG_ADDR(srsz_scale_hcr), scale_hcr);
isp_write_reg(dev, REG_ADDR(srsz_scale_hcb), scale_hcb);
isp_write_reg(dev, REG_ADDR(srsz_scale_hy), scale_hy);
isp_write_reg(dev, REG_ADDR(srsz_ctrl),
ctrl | MRV_MRSZ_CFG_UPD_MASK);
}
return 0;
}
#ifdef ISP_MI_BP
int isp_bppath_start(struct isp_ic_dev *dev)
{
struct isp_mi_context mi = *(&dev->mi);
u32 bp_ctrl = 0, lval = 0;
struct isp_mi_data_path_context *path = &mi.path[2];
u32 mi_imsc = isp_read_reg(dev, REG_ADDR(mi_imsc));
int i;
pr_info("enter %s\n", __func__);
bp_ctrl = 0;
lval = path->out_width;
if (mi.path[2].enable) {
bp_ctrl &= ~MRV_MI_BP_WRITE_RAWBIT_MASK;
if (path->data_alignMode == ISP_MI_DATA_ALIGN_16BIT_MODE) {
if ((path->out_mode == IC_MI_DATAMODE_RAW10) ||
(path->out_mode == IC_MI_DATAMODE_RAW12) ||
(path->out_mode == IC_MI_DATAMODE_RAW14)) {
lval = (path->out_width + 3) / 4;
}
} else if (path->data_alignMode ==
ISP_MI_DATA_ALIGN_128BIT_MODE) {
if ((path->out_mode == IC_MI_DATAMODE_RAW10)
|| (path->out_mode == IC_MI_DATAMODE_RAW12)
|| (path->out_mode == IC_MI_DATAMODE_RAW14)) {
lval = (path->out_width * 2 + 126) / 128;
}
} else {
if (path->out_mode == IC_MI_DATAMODE_RAW10) {
lval = (path->out_width * 10 + 63) / 64;
} else if (path->out_mode == IC_MI_DATAMODE_RAW12) {
lval = (path->out_width * 12 + 63) / 64;
} else if (path->out_mode == IC_MI_DATAMODE_RAW14) {
lval = (path->out_width * 14 + 63) / 64;
} else if (path->out_mode == IC_MI_DATAMODE_RAW16) {
lval = (path->out_width * 16 + 63) / 64;
} else {
lval = (path->out_width * 8 + 63) / 64;
}
}
lval <<= 3;
REG_SET_SLICE(bp_ctrl, BP_WR_RAW_ALIGNED, path->data_alignMode);
switch (mi.path[2].out_mode) {
case (IC_MI_DATAMODE_RAW8):
REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_RAWBIT,
MRV_MI_BP_WRITE_RAWBIT_RAW_8);
REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_FORMAT,
MRV_MI_BP_WRITE_INTERLEAVE_FORMAT);
break;
case (IC_MI_DATAMODE_RAW12):
REG_SET_SLICE(bp_ctrl, BP_WR_BYTE_SWAP, 1);
REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_RAWBIT,
MRV_MI_BP_WRITE_RAWBIT_RAW_12);
REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_FORMAT,
MRV_MI_BP_WRITE_INTERLEAVE_FORMAT);
break;
case (IC_MI_DATAMODE_RAW10):
REG_SET_SLICE(bp_ctrl, BP_WR_BYTE_SWAP, 1);
REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_RAWBIT,
MRV_MI_BP_WRITE_RAWBIT_RAW_10);
REG_SET_SLICE(bp_ctrl, MRV_MI_BP_WRITE_FORMAT,
MRV_MI_BP_WRITE_INTERLEAVE_FORMAT);
break;
default:
break;
}
isp_write_reg(dev, REG_ADDR(mi_bp_wr_size_init),
lval * mi.path[2].out_height);
isp_write_reg(dev, REG_ADDR(mi_bp_pic_width),
mi.path[2].out_width);
isp_write_reg(dev, REG_ADDR(mi_bp_wr_llength), lval);
isp_write_reg(dev, REG_ADDR(mi_bp_pic_height),
mi.path[2].out_height);
isp_write_reg(dev, REG_ADDR(mi_bp_pic_size),
lval * mi.path[2].out_height);
/* enable frame end irq for bp path */
mi_imsc |=
MRV_MI_BP_FRAME_END_MASK | MRV_MI_BP_WRAP_R_MASK |
MRV_MI_BP_WRAP_GR_MASK | MRV_MI_BP_WRAP_GB_MASK |
MRV_MI_BP_WRAP_B_MASK;
}
if (!dev->rawis.enable) {
isp_write_reg(dev, REG_ADDR(isp_raw_is_h_size),
mi.path[2].out_width);
isp_write_reg(dev, REG_ADDR(isp_raw_is_v_size),
mi.path[2].out_height);
isp_write_reg(dev, REG_ADDR(isp_raw_is_ctrl), 0);
}
bp_ctrl |= MRV_MI_BP_PATH_ENABLE_MASK;
isp_write_reg(dev, REG_ADDR(mi_bp_ctrl), bp_ctrl);
isp_write_reg(dev, REG_ADDR(mi_imsc), mi_imsc);
return 0;
}
#endif
int isp_mi_start(struct isp_ic_dev *dev)
{
struct isp_mi_context mi = *(&dev->mi);
u32 mi_init, mi_ctrl, mi_imsc;
u32 out_stride;
int i;
u8 retry = 3;
pr_info("enter %s\n", __func__);
isp_write_reg(dev, REG_ADDR(mrsz_ctrl), 0);
isp_write_reg(dev, REG_ADDR(mrsz_ctrl_shd), 0);
for (i = 0; i < 2; i++) {
if (mi.path[i].hscale || mi.path[i].vscale) {
set_scaling(i, dev, dev->is.enable);
}
}
mi_init = 0;
mi_ctrl = 0;
mi_imsc = 0;
if (mi.path[0].enable) {
/* remove update enable bits for offset and base registers */
mi_init &= ~MRV_MI_MP_OUTPUT_FORMAT_MASK;
mi_ctrl &= ~MRV_MI_MP_WRITE_FORMAT_MASK;
/* config mi_init output format for yuv format */
if (mi.path[0].out_mode <= IC_MI_DATAMODE_YUV400)
REG_SET_SLICE(mi_init, MRV_MI_MP_OUTPUT_FORMAT,
IC_MI_DATAMODE_YUV400 -
mi.path[0].out_mode);
switch (mi.path[0].out_mode) {
case (IC_MI_DATAMODE_RAW8):
REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
MRV_MI_MP_WRITE_FORMAT_RAW_8);
REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, 1);
REG_SET_SLICE(mi_init, MRV_MI_MP_OUTPUT_FORMAT,
MRV_MI_MP_OUTPUT_FORMAT_RAW8);
break;
case (IC_MI_DATAMODE_RAW12):
REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
MRV_MI_MP_WRITE_FORMAT_RAW_12);
REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, 1);
REG_SET_SLICE(mi_init, MRV_MI_MP_OUTPUT_FORMAT,
MRV_MI_MP_OUTPUT_FORMAT_RAW12);
isp_write_reg(dev, REG_ADDR(mi_output_align_format), 1);
break;
case (IC_MI_DATAMODE_RAW10):
REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
MRV_MI_MP_WRITE_FORMAT_RAW_12);
REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, 1);
REG_SET_SLICE(mi_init, MRV_MI_MP_OUTPUT_FORMAT,
MRV_MI_MP_OUTPUT_FORMAT_RAW10);
isp_write_reg(dev, REG_ADDR(mi_output_align_format), 1);
break;
case (IC_MI_DATAMODE_JPEG):
REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
MRV_MI_MP_WRITE_FORMAT_PLANAR);
REG_SET_SLICE(mi_ctrl, MRV_MI_JPEG_ENABLE, 1);
break;
case (IC_MI_DATAMODE_YUV444):
case (IC_MI_DATAMODE_YUV422):
case (IC_MI_DATAMODE_YUV420):
case (IC_MI_DATAMODE_YUV400):
if (mi.path[0].data_layout == IC_MI_DATASTORAGE_PLANAR) {
REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
MRV_MI_MP_WRITE_FORMAT_PLANAR);
} else if (mi.path[0].data_layout ==
IC_MI_DATASTORAGE_SEMIPLANAR) {
REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
MRV_MI_MP_WRITE_FORMAT_SEMIPLANAR);
} else if (mi.path[0].data_layout ==
IC_MI_DATASTORAGE_INTERLEAVED) {
REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
MRV_MI_MP_WRITE_FORMAT_INTERLEAVED);
} else {
break;
}
REG_SET_SLICE(mi_ctrl, MRV_MI_MP_ENABLE, 1);
break;
default:
break;
}
out_stride = mi.path[0].data_layout ==
IC_MI_DATASTORAGE_INTERLEAVED ?
(mi.path[0].out_width * 2) : (mi.path[0].out_width);
isp_write_reg(dev, REG_ADDR(mi_mp_y_pic_width), out_stride);
isp_write_reg(dev, REG_ADDR(mi_mp_y_llength), out_stride);
isp_write_reg(dev, REG_ADDR(mi_mp_y_pic_height),
mi.path[0].out_height);
isp_write_reg(dev, REG_ADDR(mi_mp_y_pic_size),
out_stride * mi.path[0].out_height);
/* workaround to resolve the problem that the mi_mp_y_pic_width can't be written */
for(i = 0; i < retry; i++) {
if(isp_read_reg(dev, REG_ADDR(mi_mp_y_pic_width)) != out_stride) {
isp_write_reg(dev, REG_ADDR(mi_mp_y_pic_width), out_stride);
} else {
break;
}
}
if(retry == i) {
pr_info("%s: update mi_mp_y_pic_width error!\n", __func__);
}
/* enable frame end irq for main path */
mi_imsc |=
(MRV_MI_MP_FRAME_END_MASK | MRV_MI_WRAP_MP_Y_MASK |
MRV_MI_WRAP_MP_CB_MASK | MRV_MI_WRAP_MP_CR_MASK);
}
if (mi.path[1].enable) {
/* setup mi for self-path */
mi_ctrl &= ~(MRV_MI_SP_WRITE_FORMAT_MASK);
REG_SET_SLICE(mi_ctrl, MRV_MI_SP_INPUT_FORMAT,
mi.path[1].in_mode - 1);
REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT,
mi.path[1].out_mode - 1);
switch (mi.path[1].out_mode) {
case (IC_MI_DATAMODE_RGB888):
case (IC_MI_DATAMODE_RGB666):
case (IC_MI_DATAMODE_RGB565):
REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
MRV_MI_SP_WRITE_FORMAT_RGB_INTERLEAVED);
break;
case (IC_MI_DATAMODE_YUV444):
case (IC_MI_DATAMODE_YUV400):
if (mi.path[1].data_layout == IC_MI_DATASTORAGE_PLANAR) {
REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
MRV_MI_SP_WRITE_FORMAT_PLANAR);
}
break;
case (IC_MI_DATAMODE_YUV422):
switch (mi.path[1].data_layout) {
case (IC_MI_DATASTORAGE_PLANAR):
REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
MRV_MI_SP_WRITE_FORMAT_PLANAR);
break;
case (IC_MI_DATASTORAGE_SEMIPLANAR):
REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
MRV_MI_SP_WRITE_FORMAT_SEMIPLANAR);
break;
case (IC_MI_DATASTORAGE_INTERLEAVED):
REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
MRV_MI_SP_WRITE_FORMAT_INTERLEAVED);
break;
default:
break;
}
break;
case (IC_MI_DATAMODE_YUV420):
switch (mi.path[1].data_layout) {
case (IC_MI_DATASTORAGE_PLANAR):
REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
MRV_MI_SP_WRITE_FORMAT_PLANAR);
break;
case (IC_MI_DATASTORAGE_SEMIPLANAR):
REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
MRV_MI_SP_WRITE_FORMAT_SEMIPLANAR);
break;
default:
break;
}
break;
default:
break;
}
out_stride = mi.path[1].data_layout ==
IC_MI_DATASTORAGE_INTERLEAVED ?
mi.path[1].out_width * 2 : mi.path[1].out_width;
REG_SET_SLICE(mi_ctrl, MRV_MI_SP_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(mi_sp_y_pic_width), out_stride);
isp_write_reg(dev, REG_ADDR(mi_sp_y_llength), out_stride);
isp_write_reg(dev, REG_ADDR(mi_sp_y_pic_height),
mi.path[1].out_height);
isp_write_reg(dev, REG_ADDR(mi_sp_y_pic_size),
out_stride * mi.path[1].out_height);
/* enable frame end interrupt on self path */
mi_imsc |=
(MRV_MI_SP_FRAME_END_MASK | MRV_MI_WRAP_SP_Y_MASK |
MRV_MI_WRAP_SP_CB_MASK | MRV_MI_WRAP_SP_CR_MASK);
}
#if defined(__KERNEL__) && defined(ENABLE_IRQ)
for (i = 0; i < MI_PATH_NUM; ++i) {
dev->mi_buf[i] = NULL;
dev->mi_buf_shd[i] = NULL;
}
if (dev->state)
*dev->state |= STATE_DRIVER_STARTED;
#endif
mi_ctrl |= (MRV_MI_INIT_BASE_EN_MASK | MRV_MI_INIT_OFFSET_EN_MASK);
REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_CHROM, mi.burst_len);
REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_LUM, mi.burst_len);
isp_write_reg(dev, REG_ADDR(mi_ctrl), mi_ctrl | 0x2000);
REG_SET_SLICE(mi_init, MRV_MI_MI_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(mi_imsc), mi_imsc);
#ifdef ISP_MI_BP
isp_bppath_start(dev);
#endif
isp_write_reg(dev, REG_ADDR(mi_init), mi_init);
return 0;
}
int isp_mi_stop(struct isp_ic_dev *dev)
{
u32 mi_ctrl = 0, mi_init = 0;
pr_info("enter %s\n", __func__);
isp_write_reg(dev, REG_ADDR(mi_imsc), 0);
/* disable mi path */
mi_ctrl = isp_read_reg(dev, REG_ADDR(mi_ctrl));
REG_SET_SLICE(mi_ctrl, MRV_MI_MP_ENABLE, 0);
REG_SET_SLICE(mi_ctrl, MRV_MI_SP_ENABLE, 0);
REG_SET_SLICE(mi_ctrl, MRV_MI_JPEG_ENABLE, 0);
REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(mi_ctrl), mi_ctrl);
mi_init = isp_read_reg(dev, REG_ADDR(mi_init));
REG_SET_SLICE(mi_init, MRV_MI_MI_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(mi_init), mi_init);
#if defined(__KERNEL__) && defined(ENABLE_IRQ)
if (dev->state)
*dev->state &= ~STATE_DRIVER_STARTED;
clean_dma_buffer(dev);
#endif
return 0;
}
int isp_set_buffer(struct isp_ic_dev *dev, struct isp_buffer_context *buf)
{
u32 addr;
if (!dev || !buf) {
pr_err("NULL pointer %s\n", __func__);
return -EINVAL;
}
addr = buf->path == 0 ?
REG_ADDR(mi_mp_y_base_ad_init) : REG_ADDR(mi_sp_y_base_ad_init);
isp_write_reg(dev, addr, (buf->addr_y & MRV_MI_MP_Y_BASE_AD_INIT_MASK));
isp_write_reg(dev, addr + 1 * 4,
(buf->size_y & MRV_MI_MP_Y_SIZE_INIT_MASK));
isp_write_reg(dev, addr + 2 * 4, 0);
isp_write_reg(dev, addr + 5 * 4,
(buf->addr_cb & MRV_MI_MP_CB_BASE_AD_INIT_MASK));
isp_write_reg(dev, addr + 6 * 4,
(buf->size_cb & MRV_MI_MP_CB_SIZE_INIT_MASK));
isp_write_reg(dev, addr + 7 * 4, 0);
isp_write_reg(dev, addr + 9 * 4,
(buf->addr_cr & MRV_MI_MP_CR_BASE_AD_INIT_MASK));
isp_write_reg(dev, addr + 10 * 4,
(buf->size_cr & MRV_MI_MP_CR_SIZE_INIT_MASK));
isp_write_reg(dev, addr + 11 * 4, 0);
return 0;
}
int isp_set_bp_buffer(struct isp_ic_dev *dev, struct isp_bp_buffer_context *buf)
{
#ifndef ISP_MI_BP
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
isp_write_reg(dev, REG_ADDR(mi_bp_r_base_ad_init),
(buf->addr_r & BP_R_BASE_AD_INIT_MASK));
isp_write_reg(dev, REG_ADDR(mi_bp_gr_base_ad_init),
(buf->addr_gr & BP_GR_BASE_AD_INIT_MASK));
isp_write_reg(dev, REG_ADDR(mi_bp_gb_base_ad_init),
(buf->addr_gb & BP_GB_BASE_AD_INIT_MASK));
isp_write_reg(dev, REG_ADDR(mi_bp_b_base_ad_init),
(buf->addr_b & BP_B_BASE_AD_INIT_MASK));
return 0;
#endif
}
u32 isp_read_mi_irq(struct isp_ic_dev * dev)
{
return isp_read_reg(dev, REG_ADDR(mi_mis));
}
void isp_reset_mi_irq(struct isp_ic_dev *dev, u32 icr)
{
isp_write_reg(dev, REG_ADDR(mi_icr), icr);
}
#endif