oleavr-rgl-a500-mini-linux-.../drivers/media/platform/sunxi-vin/vin-csi/bsp_csi.c
Ole André Vadla Ravnås 169c65d57e Initial commit
2022-05-07 01:01:45 +02:00

727 lines
22 KiB
C

/*
* linux-3.10/drivers/media/platform/sunxi-vin/vin-csi/bsp_csi.c
*
* Copyright (c) 2007-2017 Allwinnertech Co., Ltd.
*
* 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.
*
*/
/*
* sunxi csi bsp interface
* Author:raymonxiu
*/
#include "bsp_csi.h"
static struct frame_arrange frm_arrange_gbl[MAX_CSI];
static unsigned int line_stride_y_ch_gbl[MAX_CSI][MAX_CH_NUM];
static unsigned int line_stride_c_ch_gbl[MAX_CSI][MAX_CH_NUM];
static unsigned int buf_height_y_ch_gbl[MAX_CSI][MAX_CH_NUM];
static unsigned int buf_height_cb_ch_gbl[MAX_CSI][MAX_CH_NUM];
static unsigned int buf_height_cr_ch_gbl[MAX_CSI][MAX_CH_NUM];
static unsigned int line_stride_y_row_gbl[MAX_CSI][MAX_CH_NUM];
static unsigned int line_stride_c_row_gbl[MAX_CSI][MAX_CH_NUM];
int bsp_csi_set_base_addr(unsigned int sel, unsigned long addr)
{
return csi_set_base_addr(sel, addr);
}
void bsp_csi_enable(unsigned int sel)
{
csi_enable(sel);
}
void bsp_csi_disable(unsigned int sel)
{
csi_disable(sel);
}
void bsp_csi_reset(unsigned int sel)
{
csi_disable(sel);
csi_enable(sel);
}
/* bsp_csi_set_fmt
* function:
* set csi timing/format/size, return 0(ok) or -1(error)
*
* struct bus_info
* {
* enum v4l2_mbus_type bus_if;
* struct bus_timing bus_tmg;
* enum v4l2_mbus_pixelcode bus_ch_fmt[MAX_CH_NUM];
* unsigned int ch_total_num;
* };
*
* struct frame_info
* {
* struct frame_arrange arrange;
* struct frame_size ch_size[MAX_CH_NUM];
* struct frame_offset ch_offset[MAX_CH_NUM];
* unsigned int pix_ch_fmt[MAX_CH_NUM];
* enum field ch_field[MAX_CH_NUM];
* unsigned int frm_byte_size;
* };
*
* input parameters:
* bus_if,
* bus_tmg,
* bus_ch_fmt,
* ch_total_num,
* pix_ch_fmt,
* ch_field,
*
* output parameters:
* none
*/
int bsp_csi_set_fmt(unsigned int sel, struct bus_info *bus_info,
struct frame_info *frame_info)
{
struct csi_if_cfg if_cfg;
struct csi_timing_cfg tmg_cfg;
struct csi_fmt_cfg fmt_cfg[MAX_CH_NUM];
unsigned int is_buf_itl[MAX_CH_NUM];
enum bus_pixeltype bus_pix_type[MAX_CH_NUM];
enum bit_width bus_width[MAX_CH_NUM];
enum bit_width bus_precision[MAX_CH_NUM];
unsigned int ch;
switch (bus_info->bus_if) {
case V4L2_MBUS_PARALLEL:
if_cfg.interface = CSI_IF_INTLV;
break;
case V4L2_MBUS_BT656:
if_cfg.interface = CSI_IF_CCIR656_1CH;
break;
case V4L2_MBUS_CSI2:
if_cfg.interface = CSI_IF_MIPI;
break;
default:
return -1;
}
for (ch = 0; ch < bus_info->ch_total_num; ch++) {
/*get bus pixel type, bus width and bus data precision
*depends on bus format
*/
bus_pix_type[ch] = find_bus_type(bus_info->bus_ch_fmt[ch]);
bus_width[ch] = find_bus_width(bus_info->bus_ch_fmt[ch]);
bus_precision[ch] =
find_bus_precision(bus_info->bus_ch_fmt[ch]);
if (if_cfg.interface != CSI_IF_MIPI)
if_cfg.data_width = bus_width[ch];
/*set csi field info
*depends on field format
*/
switch (frame_info->ch_field[ch]) {
case V4L2_FIELD_ANY:
case V4L2_FIELD_NONE:
if_cfg.src_type = CSI_PROGRESSIVE;
fmt_cfg[ch].field_sel = CSI_EITHER;
break;
case V4L2_FIELD_TOP:
if_cfg.src_type = CSI_INTERLACE;
fmt_cfg[ch].field_sel = CSI_ODD;
break;
case V4L2_FIELD_BOTTOM:
if_cfg.src_type = CSI_INTERLACE;
fmt_cfg[ch].field_sel = CSI_EVEN;
break;
case V4L2_FIELD_INTERLACED:
case V4L2_FIELD_INTERLACED_TB:
if_cfg.src_type = CSI_INTERLACE;
tmg_cfg.field = CSI_FIELD_TF;
fmt_cfg[ch].field_sel = CSI_EITHER;
break;
case V4L2_FIELD_INTERLACED_BT:
if_cfg.src_type = CSI_INTERLACE;
tmg_cfg.field = CSI_FIELD_BF;
fmt_cfg[ch].field_sel = CSI_EITHER;
break;
default:
return -1;
}
/*if the target frame buffer is interlaced
*depends on field format
*/
if (frame_info->ch_field[ch] == V4L2_FIELD_INTERLACED ||
frame_info->ch_field[ch] == V4L2_FIELD_INTERLACED_TB ||
frame_info->ch_field[ch] == V4L2_FIELD_INTERLACED_BT)
is_buf_itl[ch] = 1;
else
is_buf_itl[ch] = 0;
/*set input/output format and size/line stride/offset
*depends on bus format, bus precision,
*target frame format, field format
*/
switch (frame_info->pix_ch_fmt[ch]) {
case V4L2_PIX_FMT_RGB565:
if (bus_pix_type[ch] == BUS_FMT_RGB565) {
fmt_cfg[ch].input_fmt = CSI_RAW;
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RGB565 : CSI_FIELD_RGB565;
} else {
return -1;
}
break;
case V4L2_PIX_FMT_RGB24:
if (bus_pix_type[ch] == BUS_FMT_RGB888) {
fmt_cfg[ch].input_fmt = CSI_RAW;
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RGB888 : CSI_FIELD_RGB888;
} else {
return -1;
}
break;
case V4L2_PIX_FMT_RGB32:
if (bus_pix_type[ch] == BUS_FMT_RGB888) {
fmt_cfg[ch].input_fmt = CSI_RAW;
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_PRGB888 : CSI_FIELD_PRGB888;
} else {
return -1;
}
break;
case V4L2_PIX_FMT_YUYV:
if (bus_pix_type[ch] == BUS_FMT_YUYV) {
fmt_cfg[ch].input_fmt = CSI_RAW;
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8;
} else {
return -1;
}
break;
case V4L2_PIX_FMT_YVYU:
if (bus_pix_type[ch] == BUS_FMT_YVYU) {
fmt_cfg[ch].input_fmt = CSI_RAW;
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8;
} else {
return -1;
}
break;
case V4L2_PIX_FMT_UYVY:
if (bus_pix_type[ch] == BUS_FMT_UYVY) {
fmt_cfg[ch].input_fmt = CSI_RAW;
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8;
} else {
return -1;
}
break;
case V4L2_PIX_FMT_VYUY:
if (bus_pix_type[ch] == BUS_FMT_VYUY) {
fmt_cfg[ch].input_fmt = CSI_RAW;
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8;
} else {
return -1;
}
break;
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_YUV420M:
case V4L2_PIX_FMT_YVU420M:
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21:
case V4L2_PIX_FMT_NV21M:
case V4L2_PIX_FMT_NV12M:
if (bus_pix_type[ch] == BUS_FMT_YUYV ||
bus_pix_type[ch] == BUS_FMT_YVYU ||
bus_pix_type[ch] == BUS_FMT_UYVY ||
bus_pix_type[ch] == BUS_FMT_VYUY)
fmt_cfg[ch].input_fmt = CSI_YUV422;
else if (bus_pix_type[ch] == BUS_FMT_YY_YUYV ||
bus_pix_type[ch] == BUS_FMT_YY_YVYU ||
bus_pix_type[ch] == BUS_FMT_YY_UYVY ||
bus_pix_type[ch] == BUS_FMT_YY_VYUY)
fmt_cfg[ch].input_fmt = CSI_YUV420;
else if (bus_pix_type[ch] == BUS_FMT_SBGGR ||
bus_pix_type[ch] == BUS_FMT_SGBRG ||
bus_pix_type[ch] == BUS_FMT_SRGGB ||
bus_pix_type[ch] == BUS_FMT_SGRBG)
fmt_cfg[ch].input_fmt = CSI_RAW; /*parse to isp*/
if (fmt_cfg[ch].input_fmt == CSI_YUV422 ||
fmt_cfg[ch].input_fmt == CSI_YUV420) {
if (frame_info->pix_ch_fmt[ch] == V4L2_PIX_FMT_YUV420
|| frame_info->pix_ch_fmt[ch] == V4L2_PIX_FMT_YVU420
|| frame_info->pix_ch_fmt[ch] == V4L2_PIX_FMT_YUV420M
|| frame_info->pix_ch_fmt[ch] == V4L2_PIX_FMT_YVU420M)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_PLANAR_YUV420 :
CSI_FIELD_PLANAR_YUV420;
else if (frame_info->pix_ch_fmt[ch] == V4L2_PIX_FMT_NV12
|| frame_info->pix_ch_fmt[ch] == V4L2_PIX_FMT_NV21
|| frame_info->pix_ch_fmt[ch] == V4L2_PIX_FMT_NV12M
|| frame_info->pix_ch_fmt[ch] == V4L2_PIX_FMT_NV21M)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_UV_CB_YUV420 :
CSI_FIELD_UV_CB_YUV420;
} else {
if (bus_precision[ch] == W_8BIT)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] ==
1) ? CSI_FRAME_RAW_8 :
CSI_FIELD_RAW_8;
else if (bus_precision[ch] == W_10BIT)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] ==
1) ? CSI_FRAME_RAW_10 :
CSI_FIELD_RAW_10;
else if (bus_precision[ch] == W_12BIT)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] ==
1) ? CSI_FRAME_RAW_12 :
CSI_FIELD_RAW_12;
}
break;
case V4L2_PIX_FMT_YUV422P:
case V4L2_PIX_FMT_NV16:
case V4L2_PIX_FMT_NV61:
if (bus_pix_type[ch] == BUS_FMT_YUYV ||
bus_pix_type[ch] == BUS_FMT_YVYU ||
bus_pix_type[ch] == BUS_FMT_UYVY ||
bus_pix_type[ch] == BUS_FMT_VYUY)
fmt_cfg[ch].input_fmt = CSI_YUV422;
else if (bus_pix_type[ch] == BUS_FMT_SBGGR ||
bus_pix_type[ch] == BUS_FMT_SGBRG ||
bus_pix_type[ch] == BUS_FMT_SRGGB ||
bus_pix_type[ch] == BUS_FMT_SGRBG)
fmt_cfg[ch].input_fmt = CSI_RAW; /*parse to isp*/
if (fmt_cfg[ch].input_fmt == CSI_YUV422) {
if (frame_info->pix_ch_fmt[ch] == V4L2_PIX_FMT_YUV422P)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] ==
1) ? CSI_FRAME_PLANAR_YUV422 :
CSI_FIELD_PLANAR_YUV422;
else if (frame_info->pix_ch_fmt[ch] == V4L2_PIX_FMT_NV16
|| frame_info->pix_ch_fmt[ch] == V4L2_PIX_FMT_NV61)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_UV_CB_YUV422 : CSI_FIELD_UV_CB_YUV422;
} else {
if (bus_precision[ch] == W_8BIT)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8;
else if (bus_precision[ch] == W_10BIT)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RAW_10 : CSI_FIELD_RAW_10;
else if (bus_precision[ch] == W_12BIT)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RAW_12 : CSI_FIELD_RAW_12;
}
break;
case V4L2_PIX_FMT_SBGGR8: /*all below are for debug*/
case V4L2_PIX_FMT_SGBRG8:
case V4L2_PIX_FMT_SGRBG8:
case V4L2_PIX_FMT_SRGGB8:
case V4L2_PIX_FMT_SBGGR10:
case V4L2_PIX_FMT_SGBRG10:
case V4L2_PIX_FMT_SGRBG10:
case V4L2_PIX_FMT_SRGGB10:
case V4L2_PIX_FMT_SBGGR12:
case V4L2_PIX_FMT_SGBRG12:
case V4L2_PIX_FMT_SGRBG12:
case V4L2_PIX_FMT_SRGGB12:
fmt_cfg[ch].input_fmt = CSI_RAW;
if (bus_precision[ch] == W_8BIT)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8;
else if (bus_precision[ch] == W_10BIT)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RAW_10 : CSI_FIELD_RAW_10;
else if (bus_precision[ch] == W_12BIT)
fmt_cfg[ch].output_fmt =
(is_buf_itl[ch] == 1) ? CSI_FRAME_RAW_12 : CSI_FIELD_RAW_12;
break;
default:
return -1;
}
/*change input sequence
*depends on bus format and target frame format
*/
switch (frame_info->pix_ch_fmt[ch]) {
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YUV420M:
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV12M:
case V4L2_PIX_FMT_YUV422P:
case V4L2_PIX_FMT_NV16:
if (bus_pix_type[ch] == BUS_FMT_YUYV)
fmt_cfg[ch].input_seq = CSI_YUYV;
else if (bus_pix_type[ch] == BUS_FMT_YVYU)
fmt_cfg[ch].input_seq = CSI_YVYU;
else if (bus_pix_type[ch] == BUS_FMT_UYVY)
fmt_cfg[ch].input_seq = CSI_UYVY;
else if (bus_pix_type[ch] == BUS_FMT_VYUY)
fmt_cfg[ch].input_seq = CSI_VYUY;
break;
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_YVU420M:
case V4L2_PIX_FMT_NV21:
case V4L2_PIX_FMT_NV21M:
case V4L2_PIX_FMT_NV61:
if (bus_pix_type[ch] == BUS_FMT_YUYV)
fmt_cfg[ch].input_seq = CSI_YVYU;
else if (bus_pix_type[ch] == BUS_FMT_YVYU)
fmt_cfg[ch].input_seq = CSI_YUYV;
else if (bus_pix_type[ch] == BUS_FMT_UYVY)
fmt_cfg[ch].input_seq = CSI_VYUY;
else if (bus_pix_type[ch] == BUS_FMT_VYUY)
fmt_cfg[ch].input_seq = CSI_UYVY;
break;
default:
fmt_cfg[ch].input_seq = CSI_UYVY;
break;
}
csi_fmt_cfg(sel, ch, &fmt_cfg[ch]);
}
csi_if_cfg(sel, &if_cfg);
/*set csi timing parameter*/
tmg_cfg.href = bus_info->bus_tmg.href_pol;
tmg_cfg.vref = bus_info->bus_tmg.vref_pol;
tmg_cfg.sample = bus_info->bus_tmg.pclk_sample;
tmg_cfg.field = 0;
csi_timing_cfg(sel, &tmg_cfg);
return 0;
}
/* bsp_csi_set_size
* function:
* set csi timing/format/size, return 0(ok) or -1(error)
*
* struct bus_info
* {
* enum v4l2_mbus_type bus_if;
* struct bus_timing bus_tmg;
* enum v4l2_mbus_pixelcode bus_ch_fmt[MAX_CH_NUM];
* unsigned int ch_total_num;
* };
*
* struct frame_info
* {
* struct frame_arrange arrange;
* struct frame_size ch_size[MAX_CH_NUM];
* struct frame_offset ch_offset[MAX_CH_NUM];
* unsigned int pix_ch_fmt[MAX_CH_NUM];
* enum field ch_field[MAX_CH_NUM];
* unsigned int frm_byte_size;
* };
*
* input parameters:
* bus_ch_fmt,
* ch_total_num,
* arrange,
* ch_size,
* ch_offset,
* pix_ch_fmt,
* ch_field,
*
* output parameters:
* frm_byte_size;
*/
int bsp_csi_set_size(unsigned int sel, struct bus_info *bus_info,
struct frame_info *frame_info)
{
enum bit_width bus_width[MAX_CH_NUM];
enum bit_width bus_precision[MAX_CH_NUM];
unsigned int is_buf_itl[MAX_CH_NUM];
unsigned int input_len_h[MAX_CH_NUM], input_len_v[MAX_CH_NUM];
unsigned int start_h[MAX_CH_NUM], start_v[MAX_CH_NUM];
unsigned int buf_height_y_ch[MAX_CH_NUM], buf_height_cb_ch[MAX_CH_NUM],
buf_height_cr_ch[MAX_CH_NUM];
unsigned int line_stride_y_ch[MAX_CH_NUM], line_stride_c_ch[MAX_CH_NUM];
unsigned int line_stride_y_row[MAX_CH_NUM],
line_stride_c_row[MAX_CH_NUM];
unsigned int ch, i, j, row, column;
row = frame_info->arrange.row;
column = frame_info->arrange.column;
frm_arrange_gbl[sel].row = row;
frm_arrange_gbl[sel].column = column;
for (ch = 0; ch < bus_info->ch_total_num; ch++) {
/*if the target frame buffer is interlaced
*depends on field format
*/
if (frame_info->ch_field[ch] == V4L2_FIELD_INTERLACED ||
frame_info->ch_field[ch] == V4L2_FIELD_INTERLACED_TB ||
frame_info->ch_field[ch] == V4L2_FIELD_INTERLACED_BT)
is_buf_itl[ch] = 1;
else
is_buf_itl[ch] = 0;
bus_width[ch] = find_bus_width(bus_info->bus_ch_fmt[ch]);
bus_precision[ch] =
find_bus_precision(bus_info->bus_ch_fmt[ch]);
/*common initial value*/
buf_height_cb_ch[ch] = 0;
buf_height_cr_ch[ch] = 0;
input_len_h[ch] = frame_info->ch_size[ch].width;
input_len_v[ch] =
frame_info->ch_size[ch].height >> ((is_buf_itl[ch] == 1) ? 1 : 0);
start_h[ch] = frame_info->ch_offset[ch].hoff;
start_v[ch] = frame_info->ch_offset[ch].voff;
switch (frame_info->pix_ch_fmt[ch]) {
case V4L2_PIX_FMT_RGB565:
line_stride_y_ch[ch] =
frame_info->ch_size[ch].width << 1;
line_stride_y_ch[ch] =
frame_info->ch_size[ch].width << 1;
line_stride_c_ch[ch] = 0;
buf_height_y_ch[ch] = frame_info->ch_size[ch].height;
break;
case V4L2_PIX_FMT_RGB24:
line_stride_y_ch[ch] =
frame_info->ch_size[ch].width * 3;
line_stride_c_ch[ch] = 0;
buf_height_y_ch[ch] = frame_info->ch_size[ch].height;
break;
case V4L2_PIX_FMT_RGB32:
line_stride_y_ch[ch] =
frame_info->ch_size[ch].width << 2;
line_stride_c_ch[ch] = 0;
buf_height_y_ch[ch] = frame_info->ch_size[ch].height;
break;
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_VYUY:
input_len_h[ch] = frame_info->ch_size[ch].width << 1;
start_h[ch] = frame_info->ch_offset[ch].hoff >> 1 << 3;
start_v[ch] = frame_info->ch_offset[ch].voff >> 1 << 3;
line_stride_y_ch[ch] =
frame_info->ch_size[ch].width << 1;
line_stride_c_ch[ch] = 0;
buf_height_y_ch[ch] = frame_info->ch_size[ch].height;
break;
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_YUV420M:
case V4L2_PIX_FMT_YVU420M:
line_stride_y_ch[ch] =
CSI_ALIGN_16B(frame_info->ch_size[ch].width);
line_stride_c_ch[ch] =
CSI_ALIGN_16B(line_stride_y_ch[ch] >> 1);
buf_height_y_ch[ch] = frame_info->ch_size[ch].height;
buf_height_cb_ch[ch] = buf_height_y_ch[ch] >> 1;
buf_height_cr_ch[ch] = buf_height_y_ch[ch] >> 1;
break;
case V4L2_PIX_FMT_YUV422P:
line_stride_y_ch[ch] =
CSI_ALIGN_16B(frame_info->ch_size[ch].width);
line_stride_c_ch[ch] =
CSI_ALIGN_16B(line_stride_y_ch[ch] >> 1);
buf_height_y_ch[ch] = frame_info->ch_size[ch].height;
buf_height_cb_ch[ch] = buf_height_y_ch[ch];
buf_height_cr_ch[ch] = buf_height_y_ch[ch];
break;
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21:
case V4L2_PIX_FMT_NV21M:
case V4L2_PIX_FMT_NV12M:
line_stride_y_ch[ch] =
CSI_ALIGN_16B(frame_info->ch_size[ch].width);
line_stride_c_ch[ch] = line_stride_y_ch[ch];
buf_height_y_ch[ch] = frame_info->ch_size[ch].height;
buf_height_cb_ch[ch] = buf_height_y_ch[ch] >> 1;
break;
case V4L2_PIX_FMT_NV16:
case V4L2_PIX_FMT_NV61:
line_stride_y_ch[ch] =
CSI_ALIGN_16B(frame_info->ch_size[ch].width);
line_stride_c_ch[ch] = line_stride_y_ch[ch];
buf_height_y_ch[ch] = frame_info->ch_size[ch].height;
buf_height_cb_ch[ch] = buf_height_y_ch[ch];
break;
case V4L2_PIX_FMT_SBGGR8: /*all below are for debug*/
case V4L2_PIX_FMT_SGBRG8:
case V4L2_PIX_FMT_SGRBG8:
case V4L2_PIX_FMT_SRGGB8:
case V4L2_PIX_FMT_SBGGR10:
case V4L2_PIX_FMT_SGBRG10:
case V4L2_PIX_FMT_SGRBG10:
case V4L2_PIX_FMT_SRGGB10:
case V4L2_PIX_FMT_SBGGR12:
case V4L2_PIX_FMT_SGBRG12:
case V4L2_PIX_FMT_SGRBG12:
case V4L2_PIX_FMT_SRGGB12:
line_stride_y_ch[ch] =
frame_info->ch_size[ch].width << ((bus_precision[ch] == W_8BIT) ? 0 : 1);
buf_height_y_ch[ch] = frame_info->ch_size[ch].height;
break;
default:
break;
}
line_stride_y_ch_gbl[sel][ch] = line_stride_y_ch[ch];
line_stride_c_ch_gbl[sel][ch] = line_stride_c_ch[ch];
buf_height_y_ch_gbl[sel][ch] = buf_height_y_ch[ch];
buf_height_cb_ch_gbl[sel][ch] = buf_height_cb_ch[ch];
buf_height_cr_ch_gbl[sel][ch] = buf_height_cr_ch[ch];
csi_set_offset(sel, ch, start_h[ch], start_v[ch]);
}
/*assume channels at the same row has the same height
*assume channels at the same column has the same width
*/
for (i = 0; i < row; i++) {
line_stride_y_row[i] = 0;
line_stride_c_row[i] = 0;
for (j = 0; j < column; j++) {
ch = i * column + j; /*ch=i when column==1*/
line_stride_y_row[i] += line_stride_y_ch[ch];
line_stride_c_row[i] += line_stride_c_ch[ch];
line_stride_y_row_gbl[sel][i] = line_stride_y_row[i];
line_stride_c_row_gbl[sel][i] = line_stride_c_row[i];
csi_set_size(sel, ch, input_len_h[ch], input_len_v[ch],
line_stride_y_row[i],
line_stride_c_row[i]);
}
}
frame_info->frm_byte_size = 0;
for (ch = 0; ch < row * column; ch++) {
frame_info->frm_byte_size +=
line_stride_y_ch[ch] * buf_height_y_ch[ch] +
line_stride_c_ch[ch] * buf_height_cb_ch[ch] +
line_stride_c_ch[ch] * buf_height_cr_ch[ch];
}
return 0;
}
/* bsp_csi_set_addr
* function:
* set csi output address, no return
* must be called after bsp_csi_set_size
*
* input parameters:
* buffer base address
*
*/
void bsp_csi_set_addr(unsigned int sel, u64 buf_base_addr, u64 buf_base_addr_y,
u64 buf_base_addr_u, u64 buf_base_addr_v)
{
#if 0
u64 buf_addr_plane0[MAX_CH_NUM];
u64 buf_addr_plane1[MAX_CH_NUM];
u64 buf_addr_plane2[MAX_CH_NUM];
unsigned int ch, i, j, k, l, row, column;
row = frm_arrange_gbl[sel].row;
column = frm_arrange_gbl[sel].column;
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++) {
ch = i * column + j;
buf_addr_plane0[ch] = buf_base_addr;
buf_addr_plane1[ch] = buf_addr_plane0[ch]
+ line_stride_y_row_gbl[sel][i] *
buf_height_y_ch_gbl[sel][ch];
buf_addr_plane2[ch] = buf_addr_plane1[ch]
+ line_stride_c_row_gbl[sel][i] *
buf_height_cb_ch_gbl[sel][ch];
for (k = 0; k < j; k++) {
buf_addr_plane0[ch] +=
line_stride_y_ch_gbl[sel][i * column + k - 1];
buf_addr_plane1[ch] +=
line_stride_c_ch_gbl[sel][i * column + k - 1];
buf_addr_plane2[ch] +=
line_stride_c_ch_gbl[sel][i * column + k - 1];
}
for (l = 1; l < i; l++) {
buf_addr_plane0[ch] +=
((line_stride_y_row_gbl[sel][l - 1] *
buf_height_y_ch_gbl[sel][l * column + j - 1])
+
(line_stride_c_row_gbl[sel][l - 1] *
buf_height_cb_ch_gbl[sel][l * column + j - 1])
+
(line_stride_c_row_gbl[sel][l - 1] *
buf_height_cr_ch_gbl[sel][l * column + j - 1]));
buf_addr_plane1[ch] +=
((line_stride_c_row_gbl[sel][l - 1] *
buf_height_cb_ch_gbl[sel][l * column + j - 1])
+
(line_stride_c_row_gbl[sel][l - 1] *
buf_height_cr_ch_gbl[sel][l * column + j - 1])
+
(line_stride_y_row_gbl[sel][l] *
buf_height_y_ch_gbl[sel][l * column + j]));
buf_addr_plane2[ch] +=
((line_stride_c_row_gbl[sel][l - 1] *
buf_height_cr_ch_gbl[sel][l * column + j - 1])
+ (line_stride_y_row_gbl[sel][l] *
buf_height_y_ch_gbl[sel][l * column + j])
+ (line_stride_c_row_gbl[sel][l] *
buf_height_cb_ch_gbl[sel][l * column + j]));
}
csi_set_buffer_address(sel, ch, CSI_BUF_0_A,
buf_base_addr_y);
csi_set_buffer_address(sel, ch, CSI_BUF_1_A,
buf_base_addr_u);
csi_set_buffer_address(sel, ch, CSI_BUF_2_A,
buf_base_addr_v);
}
}
#else
csi_set_buffer_address(sel, 0, CSI_BUF_0_A, buf_base_addr_y);
csi_set_buffer_address(sel, 0, CSI_BUF_1_A, buf_base_addr_u);
csi_set_buffer_address(sel, 0, CSI_BUF_2_A, buf_base_addr_v);
#endif
}
void bsp_csi_cap_start(unsigned int sel, unsigned int ch_total_num,
enum csi_cap_mode csi_cap_mode)
{
csi_capture_start(sel, ch_total_num, csi_cap_mode);
}
void bsp_csi_cap_stop(unsigned int sel, unsigned int ch_total_num,
enum csi_cap_mode csi_cap_mode)
{
csi_capture_stop(sel, ch_total_num, csi_cap_mode);
}
void bsp_csi_int_enable(unsigned int sel, unsigned int ch,
enum csi_int_sel interrupt)
{
csi_int_enable(sel, ch, interrupt);
}
void bsp_csi_int_disable(unsigned int sel, unsigned int ch,
enum csi_int_sel interrupt)
{
csi_int_disable(sel, ch, interrupt);
}
void bsp_csi_int_get_status(unsigned int sel, unsigned int ch,
struct csi_int_status *status)
{
csi_int_get_status(sel, ch, status);
}
void bsp_csi_int_clear_status(unsigned int sel, unsigned int ch,
enum csi_int_sel interrupt)
{
csi_int_clear_status(sel, ch, interrupt);
}