Linux_SDK_V0.9.5

This commit is contained in:
thead_admin
2022-09-13 10:34:22 +08:00
commit 23b8671032
457 changed files with 213390 additions and 0 deletions

164
Makefile Executable file
View File

@@ -0,0 +1,164 @@
##
# Copyright (C) 2020 Alibaba Group Holding Limited
##
test = $(shell if [ -f "../.param" ]; then echo "exist"; else echo "noexist"; fi)
ifeq ("$(test)", "exist")
include ../.param
endif
CONFIG_COMPILE_PLATFORM=RISCV
CONFIG_ISP_BUILD_TYPE=DEBUG
#CONFIG_ISP_BUILD_TYPE=RELEASE
CONFIG_ISP_VERSION=ISP8000L_V2008
CONFIG_ISP_RY_BUILD_TYPE=DEBUG
#CONFIG_ISP_RY_BUILD_TYPE=RELEASE
CONFIG_ISP_RY_VERSION=ISP8000_V2009
CONFIG_MAKE_ISP_DRIVER_CMD:= \
make -C vvcam/native VERSION_CFG=$(CONFIG_ISP_VERSION) \
KERNEL=$(LINUX_DIR) CROSS=$(CROSS_COMPILE) ARCH=$(ARCH) BOARD_NAME=$(BOARD_NAME)
CONFIG_DW200_CMAKE_CMD:= \
cmake -DCMODEL=$(CONFIG_DW200_CMODEL) \
-DV4L2=$(CONFIG_DW200_V4L2) \
-DARM64_LOCAL_CROSS=OFF ..
CONFIG_DEC400_CMAKE_CMD:= \
cmake -Wno-dev ..
CONFIG_MAKE_ISP_RY_DRIVER_CMD:= \
make -C vvcam_ry/native VERSION_CFG=$(CONFIG_ISP_RY_VERSION) \
KERNEL=$(LINUX_DIR) CROSS=$(CROSS_COMPILE) ARCH=$(ARCH) BOARD_NAME=$(BOARD_NAME)
DIR_ISP_TARGET_BASE=bsp/isp
DIR_ISP_TARGET_KO =bsp/isp/ko
DIR_ISP_RY_TARGET_BASE=bsp/isp_ry
DIR_ISP_RY_TARGET_KO =bsp/isp_ry/ko
DIR_DW200_TARGET_BASE=bsp/dw200
DIR_DEC400_TARGET_BASE=bsp/dec400
MODULE_NAME=ISP
BUILD_LOG_START="\033[47;30m>>> $(MODULE_NAME) $@ begin\033[0m"
BUILD_LOG_END ="\033[47;30m<<< $(MODULE_NAME) $@ end\033[0m"
#
# Do a parallel build with multiple jobs, based on the number of CPUs online
# in this system: 'make -j8' on a 8-CPU system, etc.
#
# (To override it, run 'make JOBS=1' and similar.)
#
ifeq ($(JOBS),)
JOBS := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null)
ifeq ($(JOBS),)
JOBS := 1
endif
endif
all: info isp_driver isp_ry_driver\
install_local_output install_rootfs
.PHONY: info isp_driver isp_ry_driver\
install_local_output install_rootfs \
clean_isp_driver clean_isp_ry_driver \
clean_output clean
info:
@echo $(BUILD_LOG_START)
@echo " ====== Build Info from repo project ======"
@echo " BUILDROOT_DIR="$(BUILDROOT_DIR)
@echo " CROSS_COMPILE="$(CROSS_COMPILE)
@echo " LINUX_DIR="$(LINUX_DIR)
@echo " ARCH="$(ARCH)
@echo " BOARD_NAME="$(BOARD_NAME)
@echo " KERNEL_ID="$(KERNELVERSION)
@echo " KERNEL_DIR="$(LINUX_DIR)
@echo " INSTALL_DIR_ROOTFS="$(INSTALL_DIR_ROOTFS)
@echo " DIR_MODULE_TOP="$(DIR_MODULE_TOP)
@echo " ====== Build configuration by settings ======"
@echo " COMPILE_PLATFORM="$(CONFIG_COMPILE_PLATFORM)
@echo " JOBS="$(JOBS)
@echo " ISP_BUILD_TYPE="$(CONFIG_ISP_BUILD_TYPE)
@echo " ISP_VERSION="$(CONFIG_ISP_VERSION)
@echo " CMAKE_ISP_DRIVER_CMD=" $(CONFIG_MAKE_ISP_DRIVER_CMD)
@echo " DW200_CMODEL="$(CONFIG_DW200_CMODEL)
@echo " DW200_V4L2="$(CONFIG_DW200_V4L2)
@echo " DW200_BUILD_DIR="$(CONFIG_DW200_BUILD_DIR)
@echo " DW200_CMAKE_CMD="$(CONFIG_DW200_CMAKE_CMD)
@echo " DEC400_BUILD_DIR="$(CONFIG_DEC400_BUILD_DIR)
@echo " DEC400_CMAKE_CMD="$(CONFIG_DEC400_CMAKE_CMD)
@echo " ISP_RY_BUILD_TYPE="$(CONFIG_ISP_RY_BUILD_TYPE)
@echo " ISP_RY_VERSION="$(CONFIG_ISP_RY_VERSION)
@echo $(BUILD_LOG_END)
isp_driver:
@echo $(BUILD_LOG_START)
$(CONFIG_MAKE_ISP_DRIVER_CMD)
@echo $(BUILD_LOG_END)
clean_isp_driver:
@echo $(BUILD_LOG_START)
make -C vvcam/native VERSION_CFG=$(CONFIG_ISP_VERSION) clean
#make -C vvcam/v4l2 VERSION_CFG=$(CONFIG_ISP_VERSION) clean
rm -f vvcam/dw200/.*.o.cmd
rm -f vvcam/isp/.*.o.cmd
rm -f vvcam/native/bin/*.ko
@echo $(BUILD_LOG_END)
isp_ry_driver:
@echo $(BUILD_LOG_START)
$(CONFIG_MAKE_ISP_RY_DRIVER_CMD)
@echo $(BUILD_LOG_END)
clean_isp_ry_driver:
@echo $(BUILD_LOG_START)
make -C vvcam_ry/native VERSION_CFG=$(CONFIG_ISP_RY_VERSION) clean
make -C vvcam_ry/v4l2 VERSION_CFG=$(CONFIG_ISP_RY_VERSION) clean
rm -f vvcam_ry/dw200/.*.o.cmd
rm -f vvcam_ry/isp/.*.o.cmd
rm -f vvcam_ry/native/bin/*.ko
@echo $(BUILD_LOG_END)
install_local_output: isp_driver isp_ry_driver
@echo $(BUILD_LOG_START)
# isp driver files
mkdir -p ./output/rootfs/$(DIR_ISP_TARGET_KO)
chmod +x ./vvcam/native/bin/*.sh
cp -f ./vvcam/native/bin/* ./output/rootfs/$(DIR_ISP_TARGET_KO)
# isp ry driver files
mkdir -p ./output/rootfs/$(DIR_ISP_RY_TARGET_KO)
chmod +x ./vvcam_ry/native/bin/*.sh
cp -f ./vvcam_ry/native/bin/vvcam_isp_ry.ko ./output/rootfs/$(DIR_ISP_TARGET_KO)
install_rootfs: install_local_output
@echo $(BUILD_LOG_START)
# cp -rf output/rootfs/* $(INSTALL_DIR_ROOTFS)
@echo $(BUILD_LOG_END)
clean_output:
@echo $(BUILD_LOG_START)
rm -rf ./output
rm -rf $(INSTALL_DIR_ROOTFS)/$(DIR_ISP_TARGET_BASE)
rm -rf $(INSTALL_DIR_ROOTFS)/$(DIR_ISP_RY_TARGET_BASE)
rm -rf $(INSTALL_DIR_ROOTFS)/$(DIR_DW200_TARGET_BASE)
rm -rf $(INSTALL_DIR_ROOTFS)/$(DIR_DEC400_TARGET_BASE)
@echo $(BUILD_LOG_END)
clean_proprietories_include:
@echo $(BUILD_LOG_START)
@echo $(BUILD_LOG_END)
clean: clean_output clean_isp_driver \
clean_isp_ry_driver clean_proprietories_include

0
README.md Normal file
View File

15
vvcam/.gitignore vendored Executable file
View File

@@ -0,0 +1,15 @@
*.cmd
*.mod
*.o
*.swp
.vscode/*
.tmp_versions/*
Module.symvers
*.ko
modules.order
*mod.c
*cmd.c
*.o.d
*.a
*.tmp
.cache.mk

114
vvcam/LICENSE Executable file
View File

@@ -0,0 +1,114 @@
/****************************************************************************
*
* 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;
*
*****************************************************************************/
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

4
vvcam/README.md Executable file
View File

@@ -0,0 +1,4 @@
# vvcam
ISP8000 vvcam project.
ISP8000NANO TAG:origin/nxp_4.2.2_rc5

191
vvcam/common/viv_video_kevent.h Executable file
View File

@@ -0,0 +1,191 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _VIV_VIDEO_KEVENT_H_
#define _VIV_VIDEO_KEVENT_H_
#include <linux/videodev2.h>
#ifndef __KERNEL__
#include <stdint.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
#endif
enum {
VIV_VIDEO_EVENT_MIN = 0,
VIV_VIDEO_EVENT_NEW_STREAM,
VIV_VIDEO_EVENT_DEL_STREAM,
VIV_VIDEO_EVENT_START_STREAM,
VIV_VIDEO_EVENT_STOP_STREAM,
VIV_VIDEO_EVENT_SET_FMT,
VIV_VIDEO_EVENT_SET_CROP,
VIV_VIDEO_EVENT_SET_COMPOSE,
VIV_VIDEO_EVENT_QUERYCAPS,
VIV_VIDEO_EVENT_PASS_JSON,
VIV_VIDEO_EVENT_EXTCTRL,
VIV_VIDEO_EVENT_EXTCTRL2,
VIV_VIDEO_EVENT_SET_CAPSMODE,
VIV_VIDEO_EVENT_GET_CAPS_SUPPORTS,
VIV_VIDEO_EVENT_CREATE_PIPELINE,
VIV_VIDEO_EVENT_QBUF,
VIV_VIDEO_EVENT_MAX,
};
enum {
VIV_DWE_EVENT_MIN = VIV_VIDEO_EVENT_MAX + 1,
VIV_DWE_EVENT_FRAMEDONE,
VIV_DWE_EVENT_MAX,
};
/* max support to 64 bytes! */
struct viv_video_event {
u32 stream_id;
void *file;
u64 addr;
int buf_index;
u64 response;
u32 sync;
};
struct v4l2_user_buffer {
u64 addr;
int streamid;
void *file;
};
struct viv_rect {
__s16 left;
__s16 top;
__u16 width;
__u16 height;
};
#define VIV_EVENT_BUF_SIZE (4*1024)
#define VIV_JSON_BUFFER_SIZE (64*1024)
struct viv_control_event {
/* physical address of json request, fixed size 64K */
u64 request;
/* physical address of json response fixed size 64K */
u64 response;
u32 id;
};
struct ext_buf_info {
u64 addr;
u64 size;
};
struct vvcam_constant_modeinfo {
unsigned index;
unsigned w;
unsigned h;
unsigned fps;
unsigned brpat; /*bayer pattern*/
unsigned bitw; /*bit width*/
};
#define CALIBXML_FILE_NAME_SIZE 64
struct viv_caps_mode_s {
int mode;
char CalibXmlName[CALIBXML_FILE_NAME_SIZE];
};
enum viv_caps_hdr_mode_e
{
VIV_CAPS_MODE_LINEAR ,
VIV_CAPS_MODE_HDR_STITCH,
VIV_CAPS_MODE_HDR_NATIVE,
};
struct viv_caps_mode_info_s{
unsigned int index;
unsigned int width;
unsigned int height;
unsigned int hdr_mode;
unsigned int fps;
};
#define VIV_CAPS_MODE_MAX_COUNT 20
struct viv_caps_supports{
unsigned int count;
struct viv_caps_mode_info_s mode[VIV_CAPS_MODE_MAX_COUNT];
};
#define VIV_VIDEO_ISPIRQ_TYPE (V4L2_EVENT_PRIVATE_START + 0x0)
#define VIV_VIDEO_MIIRQ_TYPE (V4L2_EVENT_PRIVATE_START + 0x1)
#define VIV_VIDEO_EVENT_TYPE (V4L2_EVENT_PRIVATE_START + 0x2000)
#define VIV_DWE_EVENT_TYPE (V4L2_EVENT_PRIVATE_START + 0x3000)
#define VIV_VIDEO_EVENT_TIMOUT_MS 5000
#define VIV_VIDIOC_EVENT_COMPLETE _IOW('V', BASE_VIDIOC_PRIVATE + 100, struct viv_video_event)
#define VIV_VIDIOC_BUFFER_ALLOC _IOWR('V', BASE_VIDIOC_PRIVATE + 101, struct ext_buf_info)
#define VIV_VIDIOC_BUFFER_FREE _IOWR('V', BASE_VIDIOC_PRIVATE + 102, struct ext_buf_info)
#define VIV_VIDIOC_CONTROL_EVENT _IOWR('V', BASE_VIDIOC_PRIVATE + 103, struct viv_control_event)
#define VIV_VIDIOC_S_STREAMID _IOW('V', BASE_VIDIOC_PRIVATE + 104, int)
#define VIV_VIDIOC_BUFDONE _IOW('V', BASE_VIDIOC_PRIVATE + 105, struct v4l2_user_buffer)
#define VIV_VIDIOC_QUERY_EXTMEM _IOWR('V', BASE_VIDIOC_PRIVATE + 106, struct ext_buf_info)
#define VIV_VIDIOC_S_ENDPOINT _IOW('V', BASE_VIDIOC_PRIVATE + 107, int)
#define VIV_VIDIOC_S_MODEINFO _IOW('V', BASE_VIDIOC_PRIVATE + 108, struct vvcam_constant_modeinfo)
#define VIV_VIDIOC_S_CAPS_MODE _IOW('V', BASE_VIDIOC_PRIVATE + 109, struct viv_caps_mode_s)
#define VIV_VIDIOC_G_CAPS_MODE _IOWR('V', BASE_VIDIOC_PRIVATE + 110, struct viv_caps_mode_s)
#define VIV_VIDIOC_EVENT_RESULT _IOWR('V', BASE_VIDIOC_PRIVATE + 111,int)
#define VIV_VIDIOC_GET_CAPS_SUPPORTS _IOWR('V', BASE_VIDIOC_PRIVATE + 112,struct viv_caps_supports)
#define VIV_VIDIOC_SET_CAPS_SUPPORTS _IOWR('V', BASE_VIDIOC_PRIVATE + 113,struct viv_caps_supports)
#define VIV_VIDIOC_S_DWECFG _IOW('V', BASE_VIDIOC_PRIVATE + 114, int)
#define VIV_VIDIOC_G_DWECFG _IOR('V', BASE_VIDIOC_PRIVATE + 115, int)
#endif

77
vvcam/common/vvcsioc.h Executable file
View File

@@ -0,0 +1,77 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _VVCAM_CSIOC_H_
#define _VVCAM_CSIOC_H_
#ifdef __KERNEL__
#include <media/v4l2-subdev.h>
#else
#include <linux/videodev2.h>
#endif
enum {
VVCSIOC_RESET = 0x100,
VVCSIOC_POWERON,
VVCSIOC_POWEROFF,
VVCSIOC_STREAMON,
VVCSIOC_STREAMOFF,
VVCSIOC_S_FMT,
VVCSIOC_S_HDR,
};
struct csi_sam_format {
int64_t format;
__u32 width;
__u32 height;
};
#endif /* _VVCAM_CSIOC_H_ */

148
vvcam/common/vvctrl.h Executable file
View File

@@ -0,0 +1,148 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _VVCTRL_H_
#define _VVCTRL_H_
#include <linux/videodev2.h>
#define VIV_CUSTOM_CID_BASE (V4L2_CID_USER_BASE | 0xf000)
#define V4L2_CID_VIV_STRING (VIV_CUSTOM_CID_BASE + 0x01)
#define V4L2_CID_VIV_SENSOR_MODE (VIV_CUSTOM_CID_BASE + 0x02)
#define V4L2_CID_VIV_SENSOR_RES_W (VIV_CUSTOM_CID_BASE + 0x03)
#define V4L2_CID_VIV_SENSOR_RES_H (VIV_CUSTOM_CID_BASE + 0x04)
#define V4L2_CID_VIV_SENSOR_TPG_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x05)
#define V4L2_CID_VIV_DEWARP_MODE (VIV_CUSTOM_CID_BASE + 0x06)
#define V4L2_CID_VIV_DEWARP_BYPASS_STATUS (VIV_CUSTOM_CID_BASE + 0x07)
#define V4L2_CID_VIV_AEC_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x08)
#define V4L2_CID_VIV_AWB_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x09)
#define V4L2_CID_VIV_AWB_DAMPING_STATUS (VIV_CUSTOM_CID_BASE + 0x0A)
#define V4L2_CID_VIV_LSC_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x0B)
#define V4L2_CID_VIV_CPROC_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x0C)
#define V4L2_CID_VIV_GAMMA_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x0D)
#define V4L2_CID_VIV_GAMMA_MODE (VIV_CUSTOM_CID_BASE + 0x0E)
#define V4L2_CID_VIV_DEMOSAIC_MODE (VIV_CUSTOM_CID_BASE + 0x0F)
#define V4L2_CID_VIV_FILTER_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x10)
#define V4L2_CID_VIV_CAC_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x11)
#define V4L2_CID_VIV_DPCC_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x12)
#define V4L2_CID_VIV_CNR_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x13)
#define V4L2_CID_VIV_DPF_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x14)
#define V4L2_CID_VIV_WDR3_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x15)
#define V4L2_CID_VIV_AVS_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x16)
#define V4L2_CID_VIV_2DNR_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x17)
#define V4L2_CID_VIV_3DNR_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x18)
#define V4L2_CID_VIV_HDR_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x19)
#define V4L2_CID_VIV_HDR_MODE (VIV_CUSTOM_CID_BASE + 0x1A)
#define V4L2_CID_VIV_STITCHING_MODE (VIV_CUSTOM_CID_BASE + 0x1B)
#define V4L2_CID_VIV_IS_OUT_RES_W (VIV_CUSTOM_CID_BASE + 0x1C)
#define V4L2_CID_VIV_IS_OUT_RES_H (VIV_CUSTOM_CID_BASE + 0x1D)
#define V4L2_CID_VIV_MP_OUT_RES_W (VIV_CUSTOM_CID_BASE + 0x1E)
#define V4L2_CID_VIV_MP_OUT_RES_H (VIV_CUSTOM_CID_BASE + 0x1F)
#define V4L2_CID_VIV_MP_OUT_FORMAT (VIV_CUSTOM_CID_BASE + 0x20)
#define V4L2_CID_VIV_PIPELINE_SMP_MODE (VIV_CUSTOM_CID_BASE + 0x21)
#define V4L2_CID_VIV_PIPELINE_DWE_ENABLED_STATUS (VIV_CUSTOM_CID_BASE + 0x22)
enum v4l2_ctrl_direction {
V4L2_CTRL_GET,
V4L2_CTRL_SET,
};
struct v4l2_ctrl_data {
struct v4l2_ext_controls ctrls;
enum v4l2_ctrl_direction dir;
int ret;
};
#define nextof(ptr, new_type) ((new_type)((ptr) + 1))
#ifdef __KERNEL__
int viv_gen_g_ctrl(struct v4l2_ctrl *ctrl);
int viv_gen_s_ctrl(struct v4l2_ctrl *ctrl);
static const struct v4l2_ctrl_ops viv_gen_ctrl_ops = {
.g_volatile_ctrl = viv_gen_g_ctrl,
.s_ctrl = viv_gen_s_ctrl,
};
static const struct v4l2_ctrl_config viv_ctrl_sensor_resw = {
.ops = &viv_gen_ctrl_ops,
.id = V4L2_CID_VIV_SENSOR_RES_W,
.name = "sensor.resw",
.type = V4L2_CTRL_TYPE_INTEGER,
.flags = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
.min = 0,
.max = 3840,
.def = 1920,
.step = 1,
};
static const struct v4l2_ctrl_config viv_ctrl_sensor_resh = {
.ops = &viv_gen_ctrl_ops,
.id = V4L2_CID_VIV_SENSOR_RES_H,
.name = "sensor.resh",
.type = V4L2_CTRL_TYPE_INTEGER,
.flags = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
.min = 0,
.max = 2160,
.def = 1080,
.step = 1,
};
#define create_controls(handler) \
do { \
v4l2_ctrl_new_custom(handler, &viv_ctrl_sensor_resw, NULL); \
v4l2_ctrl_new_custom(handler, &viv_ctrl_sensor_resh, NULL); \
} while (0)
#endif
#endif /* _VVCTRL_H_ */

146
vvcam/common/vvdefs.h Executable file
View File

@@ -0,0 +1,146 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _ISP_VVDEFS_H_
#define _ISP_VVDEFS_H_
#define viv_check_retval(x)\
do {\
if ((x))\
return -EIO;\
} while (0)
#ifndef VIV_MEDIA_PIX_FMT
#define VIV_MEDIA_PIX_FMT
enum {
MEDIA_PIX_FMT_YUV422SP = 0,
MEDIA_PIX_FMT_YUV422I,
MEDIA_PIX_FMT_YUV420SP,
MEDIA_PIX_FMT_YUV444P,
MEDIA_PIX_FMT_YUV444I,
MEDIA_PIX_FMT_RGB888,
MEDIA_PIX_FMT_RGB888P,
MEDIA_PIX_FMT_BGR888P,
MEDIA_PIX_FMT_RAW8,
MEDIA_PIX_FMT_RAW10,
MEDIA_PIX_FMT_RAW12,
};
#endif
#ifndef __KERNEL__
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <stdio.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
#define pr_info(...) printf(__VA_ARGS__)
#define pr_err(...) printf(__VA_ARGS__)
#define pr_debug(...) printf(__VA_ARGS__)
#define __user
#define __iomem
#else /* __KERNEL__ */
/* if v4l2 */
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/io.h>
#include <linux/list.h>
#include <linux/delay.h>
#include <media/v4l2-subdev.h>
#include <linux/platform_device.h>
enum STATE_CODE {
STATE_STOPPED = 0,
STATE_STREAM_STARTED = 1 << 1,
STATE_DRIVER_STARTED = 1 << 2,
};
#endif
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef ALIGN_UP
#define ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align)-1))
#endif
#define ISP_COMPAT_NAME "fsl,imx8mp-isp"
#define DWE_COMPAT_NAME "fsl,imx8mp-dwe"
#define ISP_DEVICE_NAME "vvcam-isp"
#define DWE_DEVICE_NAME "vvcam-dwe"
#define ISP_PAD_SOURCE (0)
#define ISP_PADS_NUM (1)
#define DWE_PAD_SOURCE (0)
#define DWE_PAD_SINK (1)
#define DWE_PADS_NUM (2)
#define RESV_STREAMID_ISP(id) \
((id) ? RESV_STREAMID_ISP1 : RESV_STREAMID_ISP0)
#define RESV_STREAMID_ISP0 (-2)
#define RESV_STREAMID_ISP1 (-3)
#define RESV_STREAMID_DWE (-4)
#endif /* _ISP_VVDEFS_H_ */

642
vvcam/common/vvnative.c Executable file
View File

@@ -0,0 +1,642 @@
/****************************************************************************
*
* 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 <linux/module.h> /* Module support */
#include <linux/version.h> /* Kernel version */
#include <linux/cdev.h> /* Charactor device support */
#include <linux/vermagic.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/ioctl.h>
#include <linux/mm.h>
#include "vvnative.h"
#include "vvnative_cfg.h"
#include "vvnative_combo.h"
#ifdef SENSOR_USE_GPIO_I2C
#include "soc_i2c.h"
#endif
#ifndef MODULE_LICENSE
# define MODULE_LICENSE(x)
#endif /* MODULE_LICENSE */
#ifndef MODULE_VERSION
# define MODULE_VERSION(x)
#endif /* MODULE_VERSION */
#define DRIVER_AUTHOR "VeriSilicon IPD"
#define DRIVER_DESC "Verisilicon ISP driver"
#define DRIVER_LICENSE "GPL"
#define DRIVER_VERSION "1.0"
#ifdef MODULE
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE( DRIVER_LICENSE );
MODULE_INFO( vermagic, VERMAGIC_STRING);
#endif /* MODULE */
/* vvcam_isp_dev_major: device major number */
unsigned int vvcam_isp_dev_major = 0;
module_param(vvcam_isp_dev_major, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvcam_isp_dev_major, "vvcam ISP device major number");
/* vvcam_isp_dev_minor: device base(start) minor number */
unsigned int vvcam_isp_dev_minor = 0;
module_param(vvcam_isp_dev_minor, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(vvcam_isp_dev_minor, "vvcam ISP device base minor number");
/* vvcam_isp_dev_count: counts */
unsigned int vvcam_isp_dev_count = VVCAM_ISP_DEVICES;
module_param(vvcam_isp_dev_count, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvcam_isp_dev_count, "vvcam ISP device counts");
struct vvcam_isp_dev *vvcam_isp_drv;
struct vvcam_common *vvcam_drv_common;
static int vvcam_isp_dev_open(struct inode *inode, struct file *file);
static int vvcam_isp_dev_release(struct inode *inode, struct file *file);
static long vvcam_isp_dev_ioctl(struct file * pFile, unsigned int cmd, unsigned long arg);
static int vvcam_isp_dev_mmap(struct file *pFile, struct vm_area_struct *vma);
static int vvcam_isp_devio_remap(int dev_no);
static int vvcam_isp_devio_unmap(int dev_no);
long (*vvnative_ioctl[])(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args)=
{
vvcam_combo_isp_ioctl, /*devid0*/
vvcam_combo_isp_ioctl, /*devid1*/
vvcam_combo_csi_ioctl, /*devid2*/
vvcam_combo_csi_ioctl, /*devid3*/
vvcam_combo_sensor_ioctl, /*devid4*/
vvcam_combo_sensor_ioctl, /*devid5*/
vvcam_combo_dwe_ioctl, /*devid6*/
vvcam_combo_vse_ioctl, /*devid7*/
vvcam_combo_soc_ioctl, /*devid8*/
};
int (*vvnative_init[])(struct vvcam_isp_dev *vvcam_isp_drv)=
{
vvcam_combo_isp_init, /*devid0*/
vvcam_combo_isp_init, /*devid1*/
vvcam_combo_csi_init, /*devid2*/
vvcam_combo_csi_init, /*devid3*/
vvcam_combo_sensor_init, /*devid4*/
vvcam_combo_sensor_init, /*devid5*/
vvcam_combo_dwe_init, /*devid6*/
vvcam_combo_vse_init, /*devid7*/
vvcam_combo_soc_init, /*devid8*/
};
int (*vvnative_deinit[])(struct vvcam_isp_dev *vvcam_isp_drv)=
{
vvcam_combo_isp_deinit, /*devid0*/
vvcam_combo_isp_deinit, /*devid1*/
vvcam_combo_csi_deinit, /*devid2*/
vvcam_combo_csi_deinit, /*devid3*/
vvcam_combo_sensor_deinit, /*devid4*/
vvcam_combo_sensor_deinit, /*devid5*/
vvcam_combo_dwe_deinit, /*devid6*/
vvcam_combo_vse_deinit, /*devid7*/
vvcam_combo_soc_deinit, /*devid8*/
};
/*TODO:expand dual camera devs*/
struct file_operations vvcam_isp_fops = {
.owner = THIS_MODULE,
.open = vvcam_isp_dev_open,
.release = vvcam_isp_dev_release,
.unlocked_ioctl = vvcam_isp_dev_ioctl,
.mmap = vvcam_isp_dev_mmap,
};
/*On-the-fly debug opitions*/
char * on_the_fly_str="VIV ISP local debug buffer";
static void vivdev_dump_buf(unsigned char *out_buf, unsigned char* dump_data, int len, unsigned char * phy_address)
{
int m;
int n;
char *buf;
buf = out_buf;
int llength = 0x10;
unsigned int udata;
sprintf (buf, "Phy Addr: 0x%lx, Va Addr:0x%lx, len:%d\n", (unsigned long)phy_address, dump_data, len);
buf += strlen(buf);
for (m=0; m<len; m++)
{
if(m%llength == 0)
{
sprintf(buf, "%04x| ", m);
buf += strlen(buf);
}
if((m%2) == 0){
sprintf (buf, " ");
buf += strlen(buf);
}
udata = (unsigned int)(*(dump_data+m));
sprintf (buf, "%02x", udata&0xff);
buf += strlen(buf);
if(m%llength == (llength-1))
{
sprintf (buf, " | ");
buf += strlen(buf);
for (n=llength;n>0;n--)
{
if ((*(dump_data+m+1-n)>31) && (*(dump_data+m+1-n)<127))
{
sprintf (buf, "%c", *(dump_data+m+1-n));
buf += strlen(buf);
}
else
{
sprintf (buf, ".");
buf += strlen(buf);
}
}
sprintf (buf, "\n");
buf += strlen(buf);
}
}
sprintf (buf, "\n");
buf += strlen(buf);
}
static ssize_t get_vivdev(struct device *dev,
struct device_attribute *attr, char *buf)
{
const char * name;
char dev_name_perfix[8];
int dev_index;
int ret;
if(NULL == vvcam_drv_common)
{
pr_info("-->%s Error, null pointer of vvcam_drv_common\n", __func__);
return 0;
}
mutex_lock(&vvcam_drv_common->vvmutex);
name = dev_name(dev);
pr_info("-->%s dev_name name:%s\n", __func__, name);
ret = sscanf(name, "%6s%d", dev_name_perfix, &dev_index);
pr_info("-->%s sscanf ret:%d, name:%s, id:%d\n", __func__, ret, dev_name_perfix, dev_index);
ret = sprintf(buf, "%s\n", vvcam_drv_common->viv_buf);
mutex_unlock(&vvcam_drv_common->vvmutex);
return ret;
}
static ssize_t set_vivdev(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
const char * name;
char dev_name_perfix[8];
int dev_index;
unsigned int data;
unsigned int addr;
unsigned int read_cnt;
unsigned char mode;
int ret;
if(NULL == vvcam_drv_common)
{
pr_info("-->%s Error, null pointer of vvcam_drv_common\n", __func__);
return 0;
}
mutex_lock(&vvcam_drv_common->vvmutex);
name = dev_name(dev);
pr_info("-->%s dev_name name:%s\n", __func__, name);
ret = sscanf(name, "%6s%d", dev_name_perfix, &dev_index);
pr_info("-->%s sscanf ret:%d, name:%s, id:%d\n", __func__, ret, dev_name_perfix, dev_index);
ret = sscanf(buf, "%c, 0x%x, 0x%x, 0x%d", &mode, &addr, &data, &read_cnt);
if(ret < 3)
{
sprintf(vvcam_drv_common->viv_buf, "Error input string %s The parameters number:%d, expect format: 'r/w, 0xAddress, 0xData, 0xReadCnt'",
buf, ret);
pr_info("Error input string %s The parameters number:%d, expect format: 'r/w, 0xAddress, 0xData, 0xReadNumber'",buf, ret);
mutex_unlock(&vvcam_drv_common->vvmutex);
return len;
}
sprintf(vvcam_drv_common->viv_buf, "init: %s, scanf ret:%d, mode:%c, addr:0x%x, data:0x%x, readcnt:0x%x", buf, ret, mode, addr, data, read_cnt);
pr_info("-->%s init: %s, scanf ret:%d, mode:%c, addr:0x%x, data:0x%x, readcnt:0x%x", __func__, buf, ret, mode, addr, data, read_cnt);
vivdev_dump_buf((unsigned char*)vvcam_drv_common->viv_buf, on_the_fly_str, strlen(on_the_fly_str), 0xaaaa);
mutex_unlock(&vvcam_drv_common->vvmutex);
return len;
}
static DEVICE_ATTR(vivdevio, S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH, get_vivdev, set_vivdev);
static int vvcam_isp_dev_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
pr_info("-->%s: ISPdev%d opened\n", __func__, minor);
mutex_lock(&(vvcam_isp_drv + minor)->vvmutex);
if((vvcam_isp_drv + minor)->open_cnt >= VVISP_OPEN_LIMITATION)
{
pr_info("-->%s: ISPdev%d cannot open device\n", __func__, minor);
mutex_unlock(&(vvcam_isp_drv + minor)->vvmutex);
return -EBUSY;
}
if((vvcam_isp_drv + minor)->initialized == 0)
{
pr_info("-->%s: ISPdev%d device not initialized\n", __func__, minor);
mutex_unlock(&(vvcam_isp_drv + minor)->vvmutex);
return -EBUSY;
}
(vvcam_isp_drv + minor)->open_cnt++;
pr_info("-->%s: ISPdev%d update open_cnt to %d\n", __func__, minor, (vvcam_isp_drv + minor)->open_cnt);
try_module_get(THIS_MODULE);
mutex_unlock(&(vvcam_isp_drv + minor)->vvmutex);
return 0;
}
/* Called when a process closes the device file */
static int vvcam_isp_dev_release(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
pr_info("-->%s: ISPdev%d releaseing...\n", __func__, minor);
mutex_lock(&(vvcam_isp_drv + minor)->vvmutex);
if((vvcam_isp_drv + minor)->open_cnt <= 0)
{
pr_info("-->%s: ISPdev%d internal error\n", __func__, minor);
mutex_unlock(&(vvcam_isp_drv + minor)->vvmutex);
return -EBUSY;
}
(vvcam_isp_drv + minor)->open_cnt--;
module_put(THIS_MODULE);
mutex_unlock(&(vvcam_isp_drv + minor)->vvmutex);
return 0;
}
static long vvcam_isp_dev_ioctl(struct file * pFile, unsigned int cmd, unsigned long arg)
{
long ret;
struct inode *inode =pFile->f_mapping->host;
int minor = iminor(inode);
pr_info("-->%s: ISPdev%d Ioctl runs, cmd:%d, args:%ld...\n", __func__, minor, cmd, arg);
ret = (*(vvnative_ioctl+minor))(vvcam_isp_drv + minor, cmd, arg);
return ret;
};
static int vvcam_isp_dev_mmap(struct file *pFile, struct vm_area_struct *vma)
{
struct inode *inode =pFile->f_mapping->host;
int minor = iminor(inode);
ulong img_buf_base = vvnative_get_img_buf_base();
ulong img_buf_size = vvnative_get_img_buf_size();
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long pfn_start = (img_buf_base >> PAGE_SHIFT) + vma->vm_pgoff;
unsigned long size = vma->vm_end - vma->vm_start;
int ret = 0;
if(size > img_buf_size)
{
size = img_buf_size;
}
pr_info("-->%s: ISPdev%d mmap runs...\n", __func__, minor);
pr_info("-->%s: mmap parameters: phy start:0x%lx, ph size:0x%lx, vm start: 0x%lx, size: 0x%lx, offset, page start: 0x%lx\n",
__func__, img_buf_base, img_buf_size, vma->vm_start, size, offset, pfn_start);
/* Map reserved image buffer memory. */
if (remap_pfn_range(vma, vma->vm_start,
(img_buf_base >> PAGE_SHIFT),
size, vma->vm_page_prot))
{
pr_err("-->%s: remap_pfn_range error!\n", __func__);
pr_info("-->%s: mmap parameters: phy start:0x%lx, ph size:0x%lx, vm start: 0x%lx, size: 0x%lx, offset\n",
__func__, img_buf_base, img_buf_size, vma->vm_start, size, offset);
return -EIO;
}
return ret;
};
static int vvcam_isp_devio_remap(int dev_no)
{
void __iomem *addr;
ulong reg_base = vvnative_get_reg_base_by_idx(dev_no);
ulong reg_size = vvnative_get_reg_size_by_idx(dev_no);
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: NULL pointer!\n", __func__);
return -1;
}
(vvcam_isp_drv + dev_no)->phy_address = reg_base;
(vvcam_isp_drv + dev_no)->size = reg_size;
pr_info("ioremap of dev: %d, phy address:0x%lx, size:0x%lx\n", dev_no, reg_base, reg_size);
if((0 == reg_base) ||(0 == reg_size))
{
(vvcam_isp_drv + dev_no)->base_address = NULL;
pr_info("ioremap of dev: %d, phy address is 0\n", dev_no);
}else{
addr = ioremap(reg_base, reg_size);
pr_info("ioremap of dev: %d, address:0x%lx\n", dev_no, (unsigned long)addr);
(vvcam_isp_drv + dev_no)->base_address = addr;
}
return 0;
}
static int vvcam_isp_devio_unmap(int dev_no)
{
if((NULL == vvcam_isp_drv))
{
pr_err("-->%s: NULL pointer!\n", __func__);
return -1;
}
if(NULL != (vvcam_isp_drv + dev_no)->base_address)
{
iounmap((vvcam_isp_drv + dev_no)->base_address);
}
return 0;
}
/*!
*******************************************************************************
** First function called by the OS. This function registers the device and
** vendor id that this driver handles.
*/
int __init vvcam_isp_dev_initialize( void )
{
int result = 0;
struct device *dev;
dev_t devt;
int retval;
int dev_idx = 0;
struct class *vvisp_class;
pr_info("-->%s enter\n", __func__);
pr_info("-->%s : %d, registerMemBase = 0x%lx, dev number:%d\n", __func__, __LINE__, VVISP0_BASE, VVCAM_ISP_DEVICES);
/**********************************************************************
* register/alloc the device major number and range, if
* major = 0, alloc from kernel to get an available device major number
* major != 0, use the specific value as major number, this value may be invalid
**********************************************************************/
vvcam_isp_drv = kzalloc(sizeof(struct vvcam_isp_dev) * VVCAM_ISP_DEVICES, GFP_KERNEL);
if (!vvcam_isp_drv)
{
return -ENOMEM;
}
vvcam_drv_common = kzalloc(sizeof(struct vvcam_common), GFP_KERNEL);
if (!vvcam_drv_common)
{
return -ENOMEM;
}
if (0 == vvcam_isp_dev_major)
{
result = alloc_chrdev_region(&devt, 0, VVCAM_ISP_DEVICES, DRIVER_NAME);
if (result)
{
goto fail_check;
}
vvcam_isp_dev_major = MAJOR(devt);
vvcam_isp_dev_minor = MINOR(devt);
}
else
{
devt = MKDEV(vvcam_isp_dev_major, vvcam_isp_dev_minor);
result = register_chrdev_region(devt, VVCAM_ISP_DEVICES, DRIVER_NAME);
if (result)
{
result = -EBUSY;
goto fail_check;
}
}
pr_info("--> vvcam ISP init, major id: %d, minor id: %d\n", MAJOR(devt), MINOR(devt));
vvisp_class = class_create(THIS_MODULE, DRIVER_NAME);
if (IS_ERR(vvisp_class))
{
pr_info("-->%s : %d, class_create error!\n", __func__, __LINE__);
goto fail_check;
}
dev_idx = 0;
for(dev_idx = 0; dev_idx < VVCAM_ISP_DEVICES; dev_idx++)
{
if(strcmp(vvnative_get_dev_name_by_idx(dev_idx), VVNATIVE_NA) == 0)
{
pr_info("--> subisp%d is absent, id number:%s, skip..\n", dev_idx, vvnative_get_dev_name_by_idx(dev_idx) );
(vvcam_isp_drv + dev_idx)->initialized = 0;
continue;
}
(vvcam_isp_drv + dev_idx)->devt = MKDEV(vvcam_isp_dev_major, vvcam_isp_dev_minor + dev_idx);
pr_info("--> subisp%d reg, major id: %d, minor id: %d, dev_name:%s\n", dev_idx,
MAJOR((vvcam_isp_drv + dev_idx)->devt), MINOR((vvcam_isp_drv + dev_idx)->devt),
vvnative_get_dev_name_by_idx(dev_idx));
cdev_init(&(vvcam_isp_drv + dev_idx)->cdev, &vvcam_isp_fops);
(vvcam_isp_drv + dev_idx)->cdev.owner = THIS_MODULE;
retval = cdev_add(&(vvcam_isp_drv + dev_idx)->cdev, (vvcam_isp_drv + dev_idx)->devt, 1);
if (retval)
{
pr_info("-->%s : %d, cdev_add error!\n", __func__, __LINE__);
goto fail_check;
}
(vvcam_isp_drv + dev_idx)->class = vvisp_class;
dev = device_create((vvcam_isp_drv + dev_idx)->class, NULL, (vvcam_isp_drv + dev_idx)->devt,
(vvcam_isp_drv + dev_idx), "%s%d", vvnative_get_dev_name_by_idx(dev_idx), vvnative_get_dev_idx(dev_idx));
if (IS_ERR(dev))
{
pr_info("-->%s : %d, device_create error!\n", __func__, __LINE__);
class_destroy(vvcam_isp_drv->class);
goto fail_check;
}
pr_info("-->dev create for subisp %s %d done\n", DRIVER_NAME, dev_idx);
(vvcam_isp_drv + dev_idx)->dev = dev;
if(sysfs_create_file(&(dev->kobj), &dev_attr_vivdevio.attr)) {
pr_info("-->%s : %d, sysfs_create_file error!\n", __func__, __LINE__);
goto fail_check;
}
/* init */
mutex_init(&(vvcam_isp_drv + dev_idx)->vvmutex);
(vvcam_isp_drv + dev_idx)->open_cnt = 0;
(vvcam_isp_drv + dev_idx)->initialized = 1;
(vvcam_isp_drv + dev_idx)->dev_idx = vvnative_get_dev_idx(dev_idx);
result = vvcam_isp_devio_remap(dev_idx);
if(result)
{
pr_err("-->%s: vvcam_isp_devio_remap error!\n", __func__);
goto fail_check;
}
/* submodule initialization */
result = (*(vvnative_init+dev_idx))(vvcam_isp_drv + dev_idx);
if(result)
{
pr_err("-->%s: vvnative_init error with subdev:%d!\n", __func__, dev_idx);
goto fail_check;
}
}
/* on-the-fly debug init */
mutex_init(&vvcam_drv_common->vvmutex);
sprintf(vvcam_drv_common->viv_buf, "vivisp_buf");
return result;
fail_check:
/* Unregister char driver */
pr_info("-->vvcam_isp_dev_initialize error\n");
unregister_chrdev_region(devt, VVCAM_ISP_DEVICES);
return result;
}
/*!
*******************************************************************************
** Unload the driver module
*/
void __exit vvcam_isp_dev_cleanup( void )
{
int result = 0;
int dev_idx = 0;
pr_info("-->%s enter\n", __func__);
if(NULL == vvcam_isp_drv)
{
pr_info("-->%s Internal error, NULL pointer\n", __func__);
return;
}
for(dev_idx = 0; dev_idx < VVCAM_ISP_DEVICES; dev_idx++)
{
if(0 == (vvcam_isp_drv + dev_idx)->initialized)
{
continue;
}
/* submodule un-initialization */
result = (*(vvnative_deinit+dev_idx))(vvcam_isp_drv + dev_idx);
if(result)
{
pr_err("-->%s: vvnative_deinit error with subdev:%d!\n", __func__, dev_idx);
}
result = vvcam_isp_devio_unmap(dev_idx);
if(result)
{
pr_err("-->%s: vvcam_isp_devio_unmap error!\n", __func__);
}
device_destroy((vvcam_isp_drv + dev_idx)->class, (vvcam_isp_drv + dev_idx)->devt);
cdev_del(&(vvcam_isp_drv + dev_idx)->cdev);
/* remove the char device structure (has been added) */
unregister_chrdev_region((vvcam_isp_drv + dev_idx)->devt, VVCAM_ISP_DEVICES);
(vvcam_isp_drv + dev_idx)->dev = NULL;
(vvcam_isp_drv + dev_idx)->open_cnt = 0;
}
class_destroy(vvcam_isp_drv->class);
vvcam_isp_drv->class = NULL;
kfree(vvcam_isp_drv);
vvcam_isp_drv = NULL;
kfree(vvcam_drv_common);
vvcam_drv_common = NULL;
return;
}
module_init(vvcam_isp_dev_initialize);
module_exit(vvcam_isp_dev_cleanup);
MODULE_LICENSE ("GPL");

95
vvcam/common/vvnative.h Executable file
View File

@@ -0,0 +1,95 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _VVNATIVE_H_
#define _VVNATIVE_H_
/* #include <linux/ioctl.h> for kernel space */
/* #include <sys/ioctl.h> for user space */
#define VVISP_OPEN_LIMITATION 1
#define VVISP_DBG_BUFFER 4096
#define IOC_MAGIC 'v'
#define IOCINIT _IO(IOC_MAGIC, 0)
struct vvcam_isp_dev {
struct device *dev;
struct cdev cdev;
dev_t devt;
int dev_idx;
struct class *class;
int status;
long phy_address;
long size;
void __iomem *base_address;
int base_range;
struct mutex vvmutex;
int open_cnt;
int initialized;
void *private_ctx;
};
struct vvcam_common{
struct mutex vvmutex;
char viv_buf[VVISP_DBG_BUFFER];
};
#endif // _VVNATIVE_H_

264
vvcam/common/vvnative_cfg.c Executable file
View File

@@ -0,0 +1,264 @@
/****************************************************************************
*
* 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 <linux/module.h> /* Module support */
#include "vvnative_cfg.h"
char vvcam_driver_name [][8]=
{
#ifdef WITH_VVISP /* devid 0 */
VVNATIVE_ISP,
#else
VVNATIVE_NA,
#endif
#ifdef WITH_VVISP_DUAL /* devid 1 */
VVNATIVE_ISP,
#else
VVNATIVE_NA,
#endif
#ifdef WITH_VVCSI /* devid 2 */
VVNATIVE_CSI,
#else
VVNATIVE_NA,
#endif
#ifdef WITH_VVCSI_DUAL /* devid 3 */
VVNATIVE_CSI,
#else
VVNATIVE_NA,
#endif
#ifdef WITH_VVCAM /* devid 4 */
VVNATIVE_SENSOR,
#else
VVNATIVE_NA,
#endif
#ifdef WITH_VVCAM_DUAL /* devid 5 */
VVNATIVE_SENSOR,
#else
VVNATIVE_NA,
#endif
#ifdef WITH_VVDWE /* devid 6 */
VVNATIVE_DWE,
#else
VVNATIVE_NA,
#endif
#ifdef WITH_VVVSE /* devid 7 */
VVNATIVE_VSE,
#else
VVNATIVE_NA,
#endif
#ifdef WITH_VVCTL /* devid 8 */
VVNATIVE_SOC,
#else
VVNATIVE_NA,
#endif
};
char * vvnative_get_dev_name_by_idx(int devidx)
{
if((devidx > VVCAM_ISP_DEVICES)||(devidx < 0))
{
return VVNATIVE_NA;
}
return vvcam_driver_name[devidx];
}
/* Parameters that can be set with 'insmod' */
/* ISP */
static ulong vvisp0_reg_base = VVISP0_BASE;
module_param(vvisp0_reg_base, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
MODULE_PARM_DESC(vvisp0_reg_base, "VVISP0 Reg Base address of AHB register");
static ulong vvisp1_reg_base = VVISP1_BASE;
module_param(vvisp1_reg_base, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
MODULE_PARM_DESC(vvisp1_reg_base, "VVISP1 Reg Base address of AHB register");
static ulong vvisp_reg_size = VVISP_SIZE;
module_param(vvisp_reg_size, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvisp_reg_size, "VVISP0/1 Reg address range of AHB register");
/* CSI */
static ulong vvcsi0_reg_base = VVCSI0_BASE;
module_param(vvcsi0_reg_base, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvcsi0_reg_base, "VVCSI0 Reg Base address of AHB register");
static ulong vvcsi1_reg_base = VVCSI1_BASE;
module_param(vvcsi1_reg_base, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvcsi1_reg_base, "VVCSI1 Reg Base address of AHB register");
static ulong vvcsi_reg_size = VVCSI_SIZE;
module_param(vvcsi_reg_size, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvcsi_reg_size, "VVCSI0/1 Reg address range of AHB register");
/* Sensor */
static ulong vvcam0_reg_base = VVCAM0_BASE;
module_param(vvcam0_reg_base, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvcam0_reg_base, "VVCAM0 Reg Base address of AHB register");
static ulong vvcam1_reg_base = VVCAM1_BASE;
module_param(vvcam1_reg_base, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvcam1_reg_base, "VVCAM1 Reg Base address of AHB register");
static ulong vvcam_reg_size = VVCAM_SIZE;
module_param(vvcam_reg_size, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvcam_reg_size, "VVCAM0/1 Reg address range of AHB register");
/* Dwe */
static ulong vvdwe_reg_base = VVDWE_BASE;
module_param(vvdwe_reg_base, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvdwe_reg_base, "VVDWE Reg Base address of AHB register");
static ulong vvdwe_reg_size = VVDWE_SIZE;
module_param(vvdwe_reg_size, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvdwe_reg_size, "VVDWE Reg address range of AHB register");
/* Vse */
static ulong vvvse_reg_base = VVVSE_BASE;
module_param(vvvse_reg_base, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvvse_reg_base, "VVVSE Reg Base address of AHB register");
static ulong vvvse_reg_size = VVVSE_SIZE;
module_param(vvvse_reg_size, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvvse_reg_size, "VVVSE Reg address range of AHB register");
/* Crtl */
static ulong vvctl_reg_base = VVCTRL_BASE;
module_param(vvctl_reg_base, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvctl_reg_base, "VVCTRL Reg Base address of AHB register");
static ulong vvctl_reg_size = VVCTRL_SIZE;
module_param(vvctl_reg_size, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvctl_reg_size, "VVCTRL Reg address range of AHB register");
static ulong vvImgBufBase = 0x10000000;
module_param(vvImgBufBase, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvImgBufBase, "Base addrss of memory reserved for ISP");
static ulong vvImgBufSize = 0x10000000;
module_param(vvImgBufSize, ulong, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(vvImgBufSize, "Size of memory reserved for ISP");
ulong* reg_base_size_array[] =
{
&vvisp0_reg_base, /* devid 0 */
&vvisp_reg_size,
&vvisp1_reg_base, /* devid 1 */
&vvisp_reg_size,
&vvcsi0_reg_base, /* devid 2 */
&vvcsi_reg_size,
&vvcsi1_reg_base, /* devid 3 */
&vvcsi_reg_size,
&vvcam0_reg_base, /* devid 4 */
&vvcam_reg_size,
&vvcam1_reg_base, /* devid 5 */
&vvcam_reg_size,
&vvdwe_reg_base, /* devid 6 */
&vvdwe_reg_size,
&vvvse_reg_base, /* devid 7 */
&vvvse_reg_size,
&vvctl_reg_base, /* devid 8 */
&vvctl_reg_size,
};
ulong vvnative_get_reg_base_by_idx(int devidx)
{
if((devidx > VVCAM_ISP_DEVICES)||(devidx < 0))
{
return 0;
}
return *reg_base_size_array[devidx*2];
}
ulong vvnative_get_reg_size_by_idx(int devidx)
{
if((devidx > VVCAM_ISP_DEVICES)||(devidx < 0))
{
return 0;
}
return *reg_base_size_array[devidx*2 + 1];
}
int reg_dev_idx_array[] =
{
0, /* devid 0 isp0*/
1, /* devid 1 isp1 */
0, /* devid 2 csi0*/
1, /* devid 3 csi1*/
0, /* devid 4 cam0*/
1, /* devid 5 cam1*/
0, /* devid 6 dwe0*/
0, /* devid 7 vse0*/
0, /* devid 8 ctrl0*/
};
int vvnative_get_dev_idx(int devidx)
{
if((devidx > VVCAM_ISP_DEVICES)||(devidx < 0))
{
return -1;
}
return reg_dev_idx_array[devidx];
}
ulong vvnative_get_img_buf_base(void)
{
return vvImgBufBase;
}
ulong vvnative_get_img_buf_size(void)
{
return vvImgBufSize;
}

78
vvcam/common/vvnative_cfg.h Executable file
View File

@@ -0,0 +1,78 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _VVNATIVE_CFG_H_
#define _VVNATIVE_CFG_H_
//#define DRIVER_NAME ""
#define DRIVER_NAME "vivisp"
#define VVNATIVE_ISP "vivisp"
//#define VVNATIVE_CSI "vivcsi"
#define VVNATIVE_CSI "bm_csi"
#define VVNATIVE_SENSOR "vivcam"
#define VVNATIVE_DWE "vivdwe"
#define VVNATIVE_VSE "vivvse"
#define VVNATIVE_SOC "vivsoc"
#define VVNATIVE_NA "nondev"
#define VVCAM_ISP_DEVICES (9)
char * vvnative_get_dev_name_by_idx(int devidx);
ulong vvnative_get_reg_base_by_idx(int devidx);
ulong vvnative_get_reg_size_by_idx(int devidx);
ulong vvnative_get_img_buf_base(void);
ulong vvnative_get_img_buf_size(void);
int vvnative_get_dev_idx(int devidx);
#endif // _VVNATIVE_CFG_H_

509
vvcam/common/vvnative_combo.c Executable file
View File

@@ -0,0 +1,509 @@
/****************************************************************************
*
* 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 <linux/cdev.h> /* Charactor device support */
#include <linux/i2c.h>
#include "isp_ioctl.h"
#include "sensor_ioctl.h"
#include "csi_ioctl.h"
#include "soc_ioctl.h"
#include "dwe_ioctl.h"
#include "vse_ioctl.h"
#include "vvnative.h"
#include "vvnative_combo.h"
/* IOCTL combos */
long vvcam_combo_isp_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args)
{
long ret;
struct isp_ic_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: NULL pointer input!\n", __func__);
return -1;
}
mutex_lock(&vvcam_isp_drv->vvmutex);
pr_info("-->%s: Ioctl runs, cmd:%d, args:%px...\n", __func__, cmd, args);
dev = (struct isp_ic_dev *)vvcam_isp_drv->private_ctx;
ret = isp_priv_ioctl(dev, cmd, args);
mutex_unlock(&vvcam_isp_drv->vvmutex);
return ret;
}
long vvcam_combo_csi_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args)
{
long ret;
struct vvcam_csi_dev *dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: NULL pointer input!\n", __func__);
return -1;
}
mutex_lock(&vvcam_isp_drv->vvmutex);
dev = (struct vvcam_csi_dev *)vvcam_isp_drv->private_ctx;
ret = csi_priv_ioctl(dev, cmd, args);
mutex_unlock(&vvcam_isp_drv->vvmutex);
return ret;
}
#if 0
static struct i2c_board_info sensor_i2c_info =
{
I2C_BOARD_INFO("sensor_ov2775", 0x00),
};
static void *vvcamGetSensorI2cClient(struct vvcam_isp_dev *vvcam_isp_drv)
{
struct i2c_adapter *i2c_adap;
static struct i2c_client *i2c_client = NULL;
if (i2c_client == NULL)
{
i2c_adap = i2c_get_adapter(0);
i2c_client = i2c_new_device(i2c_adap, &sensor_i2c_info);
i2c_put_adapter(i2c_adap);
}
return i2c_client;
}
#endif
long vvcam_combo_sensor_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args)
{
long ret;
struct vvcam_sensor_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: NULL pointer input!\n", __func__);
return -1;
}
mutex_lock(&vvcam_isp_drv->vvmutex);
pr_info("-->%s: Ioctl runs, cmd:%d, args:%px...\n", __func__, cmd, args);
dev = (struct vvcam_sensor_dev *)vvcam_isp_drv->private_ctx;
ret = sensor_priv_ioctl(dev, cmd, (void __user *)args);
mutex_unlock(&vvcam_isp_drv->vvmutex);
return ret;
}
long vvcam_combo_dwe_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args)
{
long ret;
struct dwe_ic_dev *dev;
mutex_lock(&vvcam_isp_drv->vvmutex);
pr_info("-->%s: Ioctl runs, cmd:%d, args:%px...\n", __func__, cmd, args);
dev = (struct dwe_ic_dev *)vvcam_isp_drv->private_ctx;
ret = dwe_priv_ioctl(dev, cmd, args);
mutex_unlock(&vvcam_isp_drv->vvmutex);
return ret;
}
long vvcam_combo_vse_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args)
{
long ret;
struct vse_ic_dev *dev;
mutex_lock(&vvcam_isp_drv->vvmutex);
pr_info("-->%s: Ioctl runs, cmd:%d, args:%px...\n", __func__, cmd, args);
dev = (struct vse_ic_dev *)vvcam_isp_drv->private_ctx;
ret = vse_priv_ioctl(dev, cmd, args);
mutex_unlock(&vvcam_isp_drv->vvmutex);
return ret;
}
long vvcam_combo_soc_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args)
{
long ret;
struct vvcam_soc_dev *dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: NULL pointer input!\n", __func__);
return -1;
}
mutex_lock(&vvcam_isp_drv->vvmutex);
dev = (struct vvcam_soc_dev *)vvcam_isp_drv->private_ctx;
ret = soc_priv_ioctl(dev, cmd, (void __user)args);
mutex_unlock(&vvcam_isp_drv->vvmutex);
return ret;
}
/* Submodule init combos */
int vvcam_combo_isp_init(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
struct isp_ic_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
vvcam_isp_drv->private_ctx = kzalloc(sizeof(struct isp_ic_dev), GFP_KERNEL);
if(NULL == vvcam_isp_drv->private_ctx)
{
pr_err("-->%s: internal alloc memory error!\n", __func__);
return -1;
}
dev = (struct isp_ic_dev *)vvcam_isp_drv->private_ctx;
dev->base = vvcam_isp_drv->base_address;
dev->reset = NULL;
return ret;
}
int vvcam_combo_csi_init(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
struct vvcam_csi_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
vvcam_isp_drv->private_ctx = kzalloc(sizeof(struct vvcam_csi_dev), GFP_KERNEL);
if(NULL == vvcam_isp_drv->private_ctx)
{
pr_err("-->%s: internal alloc memory error!\n", __func__);
return -1;
}
dev = (struct vvcam_csi_dev *)vvcam_isp_drv->private_ctx;
dev->base = vvcam_isp_drv->base_address;
dev->device_idx = vvcam_isp_drv->dev_idx;
ret = vvnative_csi_init(dev);
if (ret != 0)
{
pr_err("-->%s: vvnative_csi_init error!\n", __func__);
return -1;
}
return ret;
}
int vvcam_combo_sensor_init(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
struct vvcam_sensor_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
vvcam_isp_drv->private_ctx = kzalloc(sizeof(struct vvcam_sensor_dev), GFP_KERNEL);
if(NULL == vvcam_isp_drv->private_ctx)
{
pr_err("-->%s: internal alloc memory error!\n", __func__);
return -1;
}
dev = (struct vvcam_sensor_dev *)vvcam_isp_drv->private_ctx;
dev->phy_addr = vvcam_isp_drv->phy_address;
dev->reg_size = vvcam_isp_drv->size;
dev->base = vvcam_isp_drv->base_address;
dev->device_idx = vvcam_isp_drv->dev_idx;
ret = vvnative_sensor_init(dev);
if (ret != 0)
{
pr_err("-->%s: vvnative_sensor_init error!\n", __func__);
return -1;
}
return ret;
}
int vvcam_combo_dwe_init(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
struct dwe_ic_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
vvcam_isp_drv->private_ctx = kzalloc(sizeof(struct dwe_ic_dev), GFP_KERNEL);
if(NULL == vvcam_isp_drv->private_ctx)
{
pr_err("-->%s: internal alloc memory error!\n", __func__);
return -1;
}
dev = (struct dwe_ic_dev *)vvcam_isp_drv->private_ctx;
dev->base = vvcam_isp_drv->base_address;
ret = vvnative_dwe_init(dev);
if (ret != 0)
{
pr_err("-->%s: vvnative_dwe_init error!\n", __func__);
return -1;
}
return ret;
}
int vvcam_combo_vse_init(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
struct vse_ic_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
vvcam_isp_drv->private_ctx = kzalloc(sizeof(struct vse_ic_dev), GFP_KERNEL);
if(NULL == vvcam_isp_drv->private_ctx)
{
pr_err("-->%s: internal alloc memory error!\n", __func__);
return -1;
}
dev = (struct vse_ic_dev *)vvcam_isp_drv->private_ctx;
dev->base = vvcam_isp_drv->base_address;
ret = vvnative_vse_init(dev);
if (ret != 0)
{
pr_err("-->%s: vvnative_vse_init error!\n", __func__);
return -1;
}
return ret;
}
int vvcam_combo_soc_init(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
struct vvcam_soc_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
vvcam_isp_drv->private_ctx = kzalloc(sizeof(struct vvcam_soc_dev), GFP_KERNEL);
if(NULL == vvcam_isp_drv->private_ctx)
{
pr_err("-->%s: internal alloc memory error!\n", __func__);
return -1;
}
dev = (struct vvcam_soc_dev *)vvcam_isp_drv->private_ctx;
dev->base = vvcam_isp_drv->base_address;
vvnative_soc_init(dev);
return ret;
}
/* Submodule deinit combos */
int vvcam_combo_isp_deinit(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
if(NULL != vvcam_isp_drv->private_ctx)
{
kzfree(vvcam_isp_drv->private_ctx);
vvcam_isp_drv->private_ctx = NULL;
}
return ret;
}
int vvcam_combo_csi_deinit(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
struct vvcam_csi_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
if(NULL != vvcam_isp_drv->private_ctx)
{
dev = (struct vvcam_csi_dev *)vvcam_isp_drv->private_ctx;
vvnative_csi_deinit(dev);
kzfree(vvcam_isp_drv->private_ctx);
vvcam_isp_drv->private_ctx = NULL;
}
return ret;
}
int vvcam_combo_sensor_deinit(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
struct vvcam_sensor_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
if(NULL != vvcam_isp_drv->private_ctx)
{
dev = (struct vvcam_sensor_dev *)vvcam_isp_drv->private_ctx;
vvnative_sensor_deinit(dev);
kzfree(vvcam_isp_drv->private_ctx);
vvcam_isp_drv->private_ctx = NULL;
}
return ret;
}
int vvcam_combo_dwe_deinit(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
struct dwe_ic_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
if(NULL != vvcam_isp_drv->private_ctx)
{
dev = (struct dwe_ic_dev *)vvcam_isp_drv->private_ctx;
vvnative_dwe_deinit(dev);
kzfree(vvcam_isp_drv->private_ctx);
vvcam_isp_drv->private_ctx = NULL;
}
return ret;
}
int vvcam_combo_vse_deinit(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
struct vse_ic_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
if(NULL != vvcam_isp_drv->private_ctx)
{
dev = (struct vse_ic_dev *)vvcam_isp_drv->private_ctx;
vvnative_vse_deinit(dev);
kzfree(vvcam_isp_drv->private_ctx);
vvcam_isp_drv->private_ctx = NULL;
}
return ret;
}
int vvcam_combo_soc_deinit(struct vvcam_isp_dev *vvcam_isp_drv)
{
int ret = 0;
struct vvcam_soc_dev * dev;
if(NULL == vvcam_isp_drv)
{
pr_err("-->%s: input NULL pointer!\n", __func__);
return -1;
}
if(NULL != vvcam_isp_drv->private_ctx)
{
dev = (struct vvcam_soc_dev *)vvcam_isp_drv->private_ctx;
vvnative_soc_deinit(dev);
kzfree(vvcam_isp_drv->private_ctx);
vvcam_isp_drv->private_ctx = NULL;
}
return ret;
}

78
vvcam/common/vvnative_combo.h Executable file
View File

@@ -0,0 +1,78 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _VVNATIVE_COMBO_H_
#define _VVNATIVE_COMBO_H_
long vvcam_combo_isp_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args);
long vvcam_combo_csi_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args);
long vvcam_combo_sensor_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args);
long vvcam_combo_dwe_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args);
long vvcam_combo_vse_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args);
long vvcam_combo_soc_ioctl(struct vvcam_isp_dev *vvcam_isp_drv,unsigned int cmd, void *args);
int vvcam_combo_isp_init(struct vvcam_isp_dev *vvcam_isp_drv);
int vvcam_combo_csi_init(struct vvcam_isp_dev *vvcam_isp_drv);
int vvcam_combo_sensor_init(struct vvcam_isp_dev *vvcam_isp_drv);
int vvcam_combo_dwe_init(struct vvcam_isp_dev *vvcam_isp_drv);
int vvcam_combo_vse_init(struct vvcam_isp_dev *vvcam_isp_drv);
int vvcam_combo_soc_init(struct vvcam_isp_dev *vvcam_isp_drv);
int vvcam_combo_isp_deinit(struct vvcam_isp_dev *vvcam_isp_drv);
int vvcam_combo_csi_deinit(struct vvcam_isp_dev *vvcam_isp_drv);
int vvcam_combo_sensor_deinit(struct vvcam_isp_dev *vvcam_isp_drv);
int vvcam_combo_dwe_deinit(struct vvcam_isp_dev *vvcam_isp_drv);
int vvcam_combo_vse_deinit(struct vvcam_isp_dev *vvcam_isp_drv);
int vvcam_combo_soc_deinit(struct vvcam_isp_dev *vvcam_isp_drv);
#endif

265
vvcam/common/vvsensor.h Executable file
View File

@@ -0,0 +1,265 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _VVSENSOR_PUBLIC_HEADER_H_
#define _VVSENSOR_PUBLIC_HEADER_H_
#ifndef __KERNEL__
#include <stdint.h>
#else
#include <linux/uaccess.h>
#endif
#define VVCAM_SUPPORT_MAX_MODE_COUNT 20
#define VVCAM_CAP_BUS_INFO_I2C_ADAPTER_NR_POS 8
enum {
VVSENSORIOC_RESET = 0x100,
VVSENSORIOC_S_CLK,
VVSENSORIOC_G_CLK,
VVSENSORIOC_S_POWER,
VVSENSORIOC_G_POWER,
VVSENSORIOC_SENSOR_SCCB_CFG,
VVSENSORIOC_FOCUS_SCCB_CFG,
VVSENSORIOC_READ_REG,
VVSENSORIOC_WRITE_REG,
VVSENSORIOC_READ_ARRAY,
VVSENSORIOC_WRITE_ARRAY,
VVSENSORIOC_AF_READ_REG,
VVSENSORIOC_AF_WRITE_REG,
VVSENSORIOC_G_MIPI,
VVSENSORIOC_G_NAME,
VVSENSORIOC_G_RESERVE_ID,
VVSENSORIOC_G_CHIP_ID,
VVSENSORIOC_S_INIT,
VVSENSORIOC_S_STREAM,
VVSENSORIOC_S_LONG_EXP,
VVSENSORIOC_S_EXP,
VVSENSORIOC_S_VSEXP,
VVSENSORIOC_S_LONG_GAIN,
VVSENSORIOC_S_GAIN,
VVSENSORIOC_S_VSGAIN,
VVSENSORIOC_S_FRAMESIZE,
VVSENSORIOC_ENUM_FRAMESIZES,
VVSENSORIOC_S_HDR_MODE,
VVSENSORIOC_G_HDR_MODE,
VVSENSORIOC_S_FPS,
VVSENSORIOC_G_FPS,
VVSENSORIOC_S_HDR_RADIO,
VVSENSORIOC_G_AE_INFO,
VVSENSORIOC_QUERY,
VVSENSORIOC_G_SENSOR_MODE,
VVSENSORIOC_S_WB,
VVSENSORIOC_S_BLC,
VVSENSORIOC_G_EXPAND_CURVE,
VVSENSORIOC_S_SENSOR_MODE,
VVSENSORIOC_MAX,
};
/* W/R registers */
struct vvcam_sccb_data {
uint32_t addr;
uint32_t data;
};
/* init settings */
struct vvsensor_reg_value_t {
uint16_t addr;
uint8_t val;
uint8_t mask;
uint32_t delay;
};
/* priv ioctl */
struct vvsensor_gain_context {
uint32_t again;
uint32_t dgain;
};
/* vsi native usage */
struct vvcam_sccb_cfg_s {
uint8_t slave_addr;
uint8_t addr_byte;
uint8_t data_byte;
};
struct vvcam_sccb_array {
uint32_t count;
struct vvcam_sccb_data *sccb_data;
};
typedef struct vvcam_ae_info_s {
uint32_t DefaultFrameLengthLines;
uint32_t CurFrameLengthLines;
uint32_t one_line_exp_time_ns;
uint32_t max_integration_time;
uint32_t min_integration_time;
uint32_t integration_accuracy;
uint32_t max_gain;
uint32_t min_gain;
uint32_t gain_accuracy;
uint32_t cur_fps;
uint32_t hdr_radio;
} vvcam_ae_info_t;
struct sensor_mipi_info {
uint32_t mipi_lane;
uint32_t sensor_data_bit;
};
enum sensor_hdr_mode_e
{
SENSOR_MODE_LINEAR ,
SENSOR_MODE_HDR_STITCH,
SENSOR_MODE_HDR_NATIVE,
};
enum SENSOR_BAYER_PATTERN_E
{
BAYER_RGGB = 0,
BAYER_GRBG = 1,
BAYER_GBRG = 2,
BAYER_BGGR = 3,
BAYER_BUTT
};
enum sensor_stitching_mode_e
{
SENSOR_STITCHING_DUAL_DCG = 0, /**< dual DCG mode 3x12-bit */
SENSOR_STITCHING_3DOL = 1, /**< dol3 frame 3x12-bit */
SENSOR_STITCHING_LINEBYLINE = 2, /**< 3x12-bit line by line without waiting */
SENSOR_STITCHING_16BIT_COMPRESS = 3, /**< 16-bit compressed data + 12-bit RAW */
SENSOR_STITCHING_DUAL_DCG_NOWAIT = 4, /**< 2x12-bit dual DCG without waiting */
SENSOR_STITCHING_2DOL = 5, /**< dol2 frame or 1 CG+VS sx12-bit RAW */
SENSOR_STITCHING_L_AND_S = 6, /**< L+S 2x12-bit RAW */
SENSOR_STITCHING_MAX
};
typedef struct sensor_expand_curve_s
{
uint32_t x_bit;
uint32_t y_bit;
uint8_t expand_px[64];
uint32_t expand_x_data[65];
uint32_t expand_y_data[65];
}sensor_expand_curve_t;
typedef struct sensor_data_compress_s
{
uint32_t enable;
uint32_t x_bit;
uint32_t y_bit;
}sensor_data_compress_t;
typedef struct vvcam_mode_info {
uint32_t index;
uint32_t width;
uint32_t height;
uint32_t fps;
uint32_t hdr_mode;
uint32_t stitching_mode;
uint32_t bit_width;
sensor_data_compress_t data_compress;
uint32_t bayer_pattern;
vvcam_ae_info_t ae_info;
void *preg_data;
uint32_t reg_data_count;
uint32_t mipi_phy_freq;
uint32_t mipi_line_num;
} vvcam_mode_info_t;
typedef struct sensor_blc_s
{
uint32_t red;
uint32_t gr;
uint32_t gb;
uint32_t blue;
}sensor_blc_t;
typedef struct sensor_white_balance_s
{
uint32_t r_gain;
uint32_t gr_gain;
uint32_t gb_gain;
uint32_t b_gain;
}sensor_white_balance_t;
typedef struct vvcam_mode_info_array {
uint32_t count;
struct vvcam_mode_info modes[VVCAM_SUPPORT_MAX_MODE_COUNT];
} vvcam_mode_info_array_t;
#ifdef SENSOR_CROP
/**************************************
*Reserved for sensor crop
***************************************/
typedef struct sensor_crop_regions_s
{
uint32_t offs_x;
uint32_t offs_y;
uint32_t width;
uint32_t height;
}sensor_crop_regions_t;
typedef struct sensor_crop_limits_s
{
uint32_t mode_index;
sensor_crop_regions_t max_regions;
sensor_crop_regions_t min_regions;
}sensor_crop_limits_t;
#endif
#endif

204
vvcam/csi/csi_ioctl.c Executable file
View File

@@ -0,0 +1,204 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef __KERNEL__
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#define pr_info printf
#define pr_err printf
#define copy_from_user(a, b, c) csi_copy_data(a, b, c)
#define copy_to_user(a, b, c) csi_copy_data(a, b, c)
#define __user
#define __iomem
void csi_copy_data(void *dst, void *src, int size)
{
if (dst != src)
memcpy(dst, src, size);
}
#else // __KERNEL__
#include <linux/module.h> /* Module support */
#include <linux/uaccess.h>
#endif
#include "csi_ioctl.h"
#include "vivcsi_hub.h"
long csi_priv_ioctl(struct vvcam_csi_dev *dev, unsigned int cmd, void *args)
{
int ret = -1;
if (!dev) {
return ret;
}
switch (cmd) {
case VVCSI_IOC_S_RESET:
ret = vivcsi_hub_reset(dev);
break;
case VVCSI_IOC_S_POWER:
copy_from_user(&dev->power_status, args, sizeof(dev->power_status));
ret = vivcsi_hub_set_power(dev);
break;
case VVCSI_IOC_G_POWER:
ret = vivcsi_hub_get_power(dev);
copy_to_user(args, &dev->power_status, sizeof(dev->power_status));
break;
case VVCSI_IOC_S_CLOCK:
copy_from_user(&dev->clock, args, sizeof(dev->clock));
ret = vivcsi_hub_set_clock(dev);
break;
case VVCSI_IOC_G_CLOCK:
ret = vivcsi_hub_get_clock(dev);
copy_to_user(args, &dev->clock, sizeof(dev->clock));
ret = 0;
break;
case VVCSI_IOC_S_STREAM:
copy_from_user(&dev->streaming_enable, args, sizeof(dev->streaming_enable));
ret = vivcsi_hub_set_stream_control(dev);
break;
case VVCSI_IOC_G_STREAM:
ret = vivcsi_hub_get_stream_control(dev);
copy_to_user(args, &dev->streaming_enable, sizeof(dev->streaming_enable));
break;
case VVCSI_IOC_S_FMT:
copy_from_user(&dev->csi_format, args, sizeof(dev->csi_format));
ret = vivcsi_hub_set_fmt(dev);
break;
case VVCSI_IOC_G_FMT:
ret = vivcsi_hub_get_fmt(dev);
copy_to_user(args, &dev->csi_format, sizeof(dev->csi_format));
break;
case VVCSI_IOC_S_VC_SELECT:
copy_from_user(&dev->csi_vc_select, args, sizeof(dev->csi_vc_select));
ret = vivcsi_hub_set_vc_select(dev);
break;
case VVCSI_IOC_G_VC_SELECT:
ret = vivcsi_hub_get_vc_select(dev);
copy_to_user(args, &dev->csi_vc_select, sizeof(dev->csi_vc_select));
break;
case VVCSI_IOC_S_LANE_CFG:
copy_from_user(&dev->csi_lane_cfg, args, sizeof(dev->csi_lane_cfg));
ret = vivcsi_hub_set_csi_lane_cfg(dev);
break;
default:
pr_err("unsupported command %d", cmd);
break;
}
return ret;
}
extern struct vvcam_csi_hardware_function_s nwl_mipi_function;
int vvnative_csi_init(struct vvcam_csi_dev *dev)
{
int ret = 0;
if (dev == NULL)
{
pr_err("[%s] dev is NULL\n", __func__);
return -1;
}
vvcsi_register_hardware(dev,&nwl_mipi_function);
if (dev->csi_hard_func.init)
{
ret = dev->csi_hard_func.init(dev);
if (ret < 0)
{
pr_err("[%s] init failed\n", __func__);
return -1;
}
}
return 0;
}
int vvnative_csi_deinit(struct vvcam_csi_dev *dev)
{
int ret = 0;
if (dev == NULL)
{
pr_err("[%s] dev is NULL\n", __func__);
return -1;
}
if (dev->csi_hard_func.exit)
{
ret = dev->csi_hard_func.exit(dev);
if (ret < 0)
{
pr_err("[%s] exit failed\n", __func__);
return -1;
}
}
return 0;
}

154
vvcam/csi/csi_ioctl.h Executable file
View File

@@ -0,0 +1,154 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _CSI_IOC_H_
#define _CSI_IOC_H_
#ifndef __KERNEL__
#include <stdint.h>
#endif
#include <linux/ioctl.h>
enum {
VVCSI_IOC_S_RESET = _IO('r', 0),
VVCSI_IOC_S_POWER,
VVCSI_IOC_G_POWER,
VVCSI_IOC_S_CLOCK,
VVCSI_IOC_G_CLOCK,
VVCSI_IOC_S_STREAM,
VVCSI_IOC_G_STREAM,
VVCSI_IOC_S_FMT,
VVCSI_IOC_G_FMT,
VVCSI_IOC_S_VC_SELECT,
VVCSI_IOC_G_VC_SELECT,
VVCSI_IOC_S_LANE_CFG,
VVCSI_IOC_S_BIT_SHIFT,
VVCSI_IOC_MAX,
};
struct csi_vc_select_context {
uint32_t csi_vc_select_mode;
uint32_t vc_channel;
};
struct csi_format_context {
uint32_t format;
uint32_t width;
uint32_t height;
};
struct vvcam_csi_hardware_function_s
{
int (*init)(void* dev);
int (*exit)(void* dev);
int (*reset)(void* dev);
int (*set_power)(void* dev);
int (*get_power)(void* dev);
int (*set_clock)(void* dev);
int (*get_clock)(void* dev);
int (*set_stream_control)(void* dev);
int (*get_stream_control)(void* dev);
int (*set_fmt)(void* dev);
int (*get_fmt)(void* dev);
int (*set_vc_select)(void* dev);
int (*get_vc_select)(void* dev);
int (*set_lane_cfg)(void* dev);
};
struct vvcam_csi_lane_cfg
{
uint32_t mipi_lane_num;
};
struct vvcam_csi_access_s
{
int (*write)(void * ctx, uint32_t address, uint32_t data);
int (*read)(void * ctx, uint32_t address, uint32_t *data);
};
#ifdef __KERNEL__
struct vvcam_csi_dev {
void __iomem *base;
char name[16];
int present;
int device_idx;
uint32_t power_status;
uint32_t clock;
uint32_t streaming_enable;
struct csi_vc_select_context csi_vc_select;
struct csi_format_context csi_format;
struct vvcam_csi_hardware_function_s csi_hard_func;
struct vvcam_csi_access_s csi_access;
struct vvcam_csi_lane_cfg csi_lane_cfg;
void * csi_private;
};
// internal functions
long csi_priv_ioctl(struct vvcam_csi_dev *dev, unsigned int cmd, void *args);
int vvnative_csi_init(struct vvcam_csi_dev *dev);
int vvnative_csi_deinit(struct vvcam_csi_dev *dev);
#else
//User space connections
#endif
#endif // _CSI_IOC_H_

322
vvcam/csi/nwl/nwl_core.c Executable file
View File

@@ -0,0 +1,322 @@
/****************************************************************************
*
* 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 <linux/module.h>
#include <linux/uaccess.h>
#ifdef ISP8000L_V2008
#include <linux/io.h> //Fix thead compile error.
#endif
#include "nwl_regs.h"
#include "../csi_ioctl.h"
int nwl_register_write(void * dev,unsigned int addr, unsigned int data)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
writel(data, base_addr + addr);
return 0;
}
int nwl_register_read(void * dev,unsigned int addr, unsigned int *data)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
*data = readl(base_addr + addr);
return 0;
}
static int nwl_init(void * dev)
{
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
nwl_csi_dev->csi_access.write = nwl_register_write;
nwl_csi_dev->csi_access.read = nwl_register_read;
nwl_csi_dev->csi_access.write(dev,MRV_MIPICSI_NUM_LANES, 0x4);
nwl_csi_dev->csi_access.write(dev,MRV_MIPICSI_LANES_CLK, 0x1);
nwl_csi_dev->csi_access.write(dev,MRV_MIPICSI_LANES_DATA, 0xF);
nwl_csi_dev->csi_access.write(dev,MRV_MIPICSI_IGNORE_VC, 0x1);
if (nwl_csi_dev->device_idx == 0)
{
nwl_csi_dev->csi_access.write(dev,MRV_MIPICSI0_CTRL, 0x4);
}else
{
nwl_csi_dev->csi_access.write(dev,MRV_MIPICSI1_CTRL, 0x4);
}
return 0;
}
static int nwl_exit(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
return 0;
}
static int nwl_reset(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
return 0;
}
static int nwl_set_power(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
return 0;
}
static int nwl_get_power(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
return 0;
}
static int nwl_set_clock(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
return 0;
}
static int nwl_get_clock(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
return 0;
}
static int nwl_set_stream_control(void * dev)
{
struct vvcam_csi_dev *nwl_csi_dev;
u32 clock_status;
u32 data_status;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
if (nwl_csi_dev->streaming_enable)
{
clock_status = 0x01;
data_status = 0xFF;
}
else
{
clock_status = 0x00;
data_status = 0x00;
}
nwl_csi_dev->csi_access.write(dev,MRV_MIPICSI_LANES_CLK, clock_status);
nwl_csi_dev->csi_access.write(dev,MRV_MIPICSI_LANES_DATA, data_status);
return 0;
}
static int nwl_get_stream_control(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
return 0;
}
static int nwl_set_fmt(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
return 0;
}
static int nwl_get_fmt(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
return 0;
}
static int nwl_set_vc_select(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
return 0;
}
static int nwl_get_vc_select(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
return 0;
}
static int nwl_set_lane_cfg(void * dev)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
nwl_csi_dev->csi_access.write(dev,MRV_MIPICSI_NUM_LANES, nwl_csi_dev->csi_lane_cfg.mipi_lane_num);
return 0;
}
struct vvcam_csi_hardware_function_s nwl_mipi_function =
{
.init = nwl_init,
.exit = nwl_exit,
.reset = nwl_reset,
.set_power = nwl_set_power,
.get_power = nwl_get_power,
.set_clock = nwl_set_clock,
.get_clock = nwl_get_clock,
.set_stream_control = nwl_set_stream_control,
.get_stream_control = nwl_get_stream_control,
.set_fmt = nwl_set_fmt,
.get_fmt = nwl_get_fmt,
.set_vc_select = nwl_set_vc_select,
.get_vc_select = nwl_get_vc_select,
.set_lane_cfg = nwl_set_lane_cfg,
};

156
vvcam/csi/nwl/nwl_ioctl.c Executable file
View File

@@ -0,0 +1,156 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include "nwl_driver.h"
#endif
#include "nwl_ioctl.h"
#include "nwl_regs.h"
#ifndef __KERNEL__
#include <hal/hal_api.h>
#include "common_dev.h"
#define NWL_EXTREG_OFFSET 0x308244
#define NWL_REG_OFFSET 0x300000
static HalHandle_t hal_handle;
void nwl_ic_set_hal(HalHandle_t hal)
{
hal_handle = hal;
}
void nwl_write_reg(u32 offset, u32 val)
{
offset += NWL_REG_OFFSET;
HalWriteReg(hal_handle, offset, val);
}
u32 nwl_read_reg(u32 offset)
{
offset += NWL_REG_OFFSET;
return HalReadReg(hal_handle, offset);
}
u32 nwl_write_extreg(u32 offset, u32 val)
{
offset += NWL_EXTREG_OFFSET;
return HalReadReg(hal_handle, offset);
}
int nwl_set_stream(void *dev, int enable)
{
u32 clock_status;
u32 data_status;
nwl_write_reg(MRV_MIPICSI1_NUM_LANES, 0x4);
if (enable == true) {
clock_status = 0x1;
data_status = 0xFF;
} else {
clock_status = 0x0;
data_status = 0x0;
}
nwl_write_reg(MRV_MIPICSI1_LANES_CLK, clock_status);
nwl_write_reg(MRV_MIPICSI1_LANES_DATA, data_status);
return 0;
}
int nwl_init(void)
{
nwl_write_reg(MRV_MIPICSI1_NUM_LANES, 0x4);
nwl_write_reg(MRV_MIPICSI1_LANES_CLK, 0x1);
nwl_write_reg(MRV_MIPICSI1_LANES_DATA, 0xF);
nwl_write_reg(MRV_MIPICSI1_IGNORE_VC, 0x1);
nwl_write_extreg(MRV_MIPICSI1_OUT_SHIFT, 0x4);
return 0;
}
#endif
int nwl_ioc_init(void)
{
nwl_init();
return 0;
}
int nwl_ioc_s_stream(void *dev, void *__user args)
{
int enable;
copy_from_user(&enable, args, sizeof(enable));
nwl_set_stream(dev, enable);
return 0;
}
long nwl_priv_ioctl(void *dev, unsigned int cmd, void *args)
{
int ret = -1;
switch (cmd) {
case CSIIOC_INIT:
ret = nwl_ioc_init();
break;
case CSIIOC_S_STREAM:{
ret = nwl_ioc_s_stream(dev, args);
}
break;
default:
pr_err("Unsupported csi command %d.\n", cmd);
break;
}
return ret;
}

63
vvcam/csi/nwl/nwl_ioctl.h Executable file
View File

@@ -0,0 +1,63 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _NWL_IOC_H_
#define _NWL_IOC_H_
enum {
CSIIOC_INIT = 0,
CSIIOC_S_STREAM,
};
long nwl_priv_ioctl(void *dev, unsigned int cmd, void *args);
#endif /* _NWL_IOC_H_ */

97
vvcam/csi/nwl/nwl_regs.h Executable file
View File

@@ -0,0 +1,97 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _NWL_REGS_H_
#define _NWL_REGS_H_
/*
* MRV_MIPICSI1_NUM_LANES
* Config num lanes register [3:0] rw
* 0000b - controller off
* 0001b - 1 Lane
* 0010b - 2 Lanes
* 0011b - 3 Lanes
* 0100b - 4 Lanes
*/
#define MRV_MIPICSI_NUM_LANES 0x0
/*
* MRV_MIPICSI1_LANES_CLK
* Configure lanes clock [0]
* 0b - disable
* 1b - enable
*/
#define MRV_MIPICSI_LANES_CLK 0x4
/*
* MRV_MIPICSI1_LANES_DATA
* enable/disable lanes data [7:0]
* setting bits to a '1' value enable data lane
*/
#define MRV_MIPICSI_LANES_DATA 0x8
/*
* MRV_MIPICSI1_IGNORE_VC
* enable/disable lanes clock [0]
* setting bits to a '1' value enable data value
*/
#define MRV_MIPICSI_IGNORE_VC 0x80
/*
* MRV_MIPICSI1_OUT_SHIFT
* Configure csi_vid_out register
*/
#define MRV_MIPICSI0_CTRL 0x108240 //0x308240
#define MRV_MIPICSI1_CTRL 0x8244 //0x308244
#endif /* _NWL_REGS_H_ */

335
vvcam/csi/vivcsi_hub.c Executable file
View File

@@ -0,0 +1,335 @@
/****************************************************************************
*
* 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 <linux/module.h>
#include <linux/uaccess.h>
#include <linux/i2c.h>
#include "csi_ioctl.h"
#include "vivcsi_hub.h"
unsigned int vvcsi_register_hardware(struct vvcam_csi_dev *dev, struct vvcam_csi_hardware_function_s *func)
{
int ret = 0;
if (func == NULL)
{
return -1;
}
memcpy(&dev->csi_hard_func,func,sizeof(struct vvcam_csi_hardware_function_s));
return 0;
}
int vivcsi_hub_init(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.init == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.init(dev);
return ret;
}
int vivcsi_hub_reset(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.reset == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.reset(dev);
return ret;
}
int vivcsi_hub_set_power(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.set_power == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.set_power(dev);
return ret;
}
int vivcsi_hub_get_power(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.get_power == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.get_power(dev);
return ret;
}
int vivcsi_hub_set_clock(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.set_clock == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.set_clock(dev);
return ret;
}
int vivcsi_hub_get_clock(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.get_clock == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.get_clock(dev);
return ret;
}
int vivcsi_hub_set_stream_control(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.set_stream_control == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.set_stream_control(dev);
return ret;
}
int vivcsi_hub_get_stream_control(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.get_stream_control == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.get_stream_control(dev);
return ret;
}
int vivcsi_hub_set_fmt(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.set_fmt == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.set_fmt(dev);
return ret;
}
int vivcsi_hub_get_fmt(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.get_fmt == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.get_fmt(dev);
return ret;
}
int vivcsi_hub_set_vc_select(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.set_vc_select == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.set_vc_select(dev);
return ret;
}
int vivcsi_hub_get_vc_select(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.get_vc_select == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.get_vc_select(dev);
return ret;
}
int vivcsi_hub_set_csi_lane_cfg(struct vvcam_csi_dev *dev)
{
int ret = 0;
if(NULL == dev)
{
pr_err("%s:dev is null!\n", __func__);
return -1;
}
if (dev->csi_hard_func.set_lane_cfg == NULL)
{
pr_err("%s:csi_hard_func is NULL!\n", __func__);
return -1;
}
ret = dev->csi_hard_func.set_lane_cfg(dev);
return ret;
}

72
vvcam/csi/vivcsi_hub.h Executable file
View File

@@ -0,0 +1,72 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _VIVCSI_HUB_H_
#define _VIVCSI_HUB_H_
unsigned int vvcsi_register_hardware(struct vvcam_csi_dev *dev, struct vvcam_csi_hardware_function_s *func);
int vivcsi_hub_init(struct vvcam_csi_dev *dev);
int vivcsi_hub_reset(struct vvcam_csi_dev *dev);
int vivcsi_hub_set_power(struct vvcam_csi_dev *dev);
int vivcsi_hub_get_power(struct vvcam_csi_dev *dev);
int vivcsi_hub_set_clock(struct vvcam_csi_dev *dev);
int vivcsi_hub_get_clock(struct vvcam_csi_dev *dev);
int vivcsi_hub_set_stream_control(struct vvcam_csi_dev *dev);
int vivcsi_hub_get_stream_control(struct vvcam_csi_dev *dev);
int vivcsi_hub_set_fmt(struct vvcam_csi_dev *dev);
int vivcsi_hub_get_fmt(struct vvcam_csi_dev *dev);
int vivcsi_hub_set_vc_select(struct vvcam_csi_dev *dev);
int vivcsi_hub_get_vc_select(struct vvcam_csi_dev *dev);
int vivcsi_hub_set_csi_lane_cfg(struct vvcam_csi_dev *dev);
#endif /* _VIVCSI_HUB_H_ */

1127
vvcam/dw200/dw200_ioctl.c Normal file

File diff suppressed because it is too large Load Diff

119
vvcam/dw200/dw200_ioctl.h Normal file
View File

@@ -0,0 +1,119 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _DWE_IOC_H_
#define _DWE_IOC_H_
#include "dw200_subdev.h"
#include "dwe_regs.h"
#include "vse_regs.h"
enum {
DWEIOC_RESET = 0x100,
DWEIOC_S_PARAMS,
DWEIOC_ENABLE_BUS,
DWEIOC_DISABLE_BUS,
DWEIOC_DISABLE_IRQ,
DWEIOC_CLEAR_IRQ,
DWEIOC_READ_IRQ,
DWEIOC_START_DMA_READ,
DWEIOC_SET_BUFFER,
DWEIOC_SET_LUT,
DWEIOC_START,
// vse
VSEIOC_RESET,
VSEIOC_S_PARAMS,
VSEIOC_U_BUFFER,
VSEIOC_U_MI_INFO,
VSEIOC_MASK_IRQ,
VSEIOC_READ_IRQ,
VSEIOC_CLEAR_IRQ,
VSEIOC_START_DMA_READ,
DW200IOC_LOCK, // 113
DW200IOC_UNLOCK,
DW200IOC_UPDATECURR,
DW200IOC_VISYS_RESET,
DW200IOC_GET_RESERVE_ADDR,
DW200IOC_RUNTIME_RESUME,
DW200IOC_RUNTIME_SUSPEND,
};
typedef struct dw_src_addr {
u64 y_addr;
u64 uv_addr;
} dw_src_addr_t;
long dw200_priv_ioctl(struct dw200_subdev *dev, unsigned int cmd, void *args);
int dwe_reset(struct dw200_subdev *dev);
int dwe_s_params(struct dw200_subdev *dev);
int dwe_enable_bus(struct dw200_subdev *dev, bool enable);
int dwe_disable_irq(struct dw200_subdev *dev);
int dwe_clear_irq(struct dw200_subdev *dev, u32 mis);
int dwe_clear_irq_1(struct dw200_subdev *dev);
int dwe_read_irq(struct dw200_subdev *dev, u32 *ret);
int dwe_start_dma_read(struct dw200_subdev *dev, dw_src_addr_t src_addr);
int dwe_set_buffer(struct dw200_subdev *dev, u64 addr);
int dwe_set_lut(struct dw200_subdev *dev, u64 addr);
int vse_reset(struct dw200_subdev *dev);
int vse_s_params(struct dw200_subdev *dev);
int vse_update_mi_info(struct dw200_subdev *dev);
int vse_mask_irq(struct dw200_subdev *dev, u32 mask);
int vse_clear_irq(struct dw200_subdev *dev, u32 mis);
int vse_read_irq(struct dw200_subdev *dev, u32 *ret);
/* dma input pa */
int vse_start_dma_read(struct dw200_subdev *dev, u64 addr);
/* mi output pa */
int vse_update_buffers(struct dw200_subdev *dev, u64 *addr);
#endif // _DWE_IOC_H_

168
vvcam/dw200/dw200_subdev.h Normal file
View File

@@ -0,0 +1,168 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _DW200_DEV_H
#define _DW200_DEV_H
#include <vvdefs.h>
#include "vivdw200_irq_queue.h"
#ifndef __KERNEL__
#include <stdlib.h>
#include <stdio.h>
#define copy_from_user(a, b, c) dw200_copy_data(a, b, c)
#define copy_to_user(a, b, c) dw200_copy_data(a, b, c)
typedef void(*pReadBar) (uint32_t bar, uint32_t *data);
typedef void(*pWriteBar) (uint32_t bar, uint32_t data);
extern void dwe_set_func(pReadBar read_func, pWriteBar write_func);
//extern void dw200_set_func(cmDW200* pDW200,pDw200ReadBar read_func, pDw200WriteBar write_func);
typedef bool(*pVseReadBar) (uint32_t bar, uint32_t * data);
typedef bool(*pVseWriteBar) (uint32_t bar, uint32_t data);
extern void vse_set_func(pVseReadBar read_func, pVseWriteBar write_func);
extern long dw200_copy_data(void *dst, void *src, int size);
#endif
typedef enum dw200_input_id {
DW200_INPUT_DWE = 0,
DW200_INPUT_VSE,
DW200_INPUT_MAX
} dw200_input_id;
typedef enum dw200_output_id {
DW200_OUTPUT_DWE = 0,
DW200_OUTPUT_VSE0,
DW200_OUTPUT_VSE1,
DW200_OUTPUT_VSE2,
DW200_OUTPUT_MAX
} dw200_output_id;
struct dwe_hw_info {
u32 split_line;
u32 scale_factor;
u32 in_format;
u32 out_format;
u32 in_yuvbit;
u32 out_yuvbit;
u32 hand_shake;
u32 roi_x, roi_y;
u32 boundary_y, boundary_u, boundary_v;
u32 map_w, map_h;
u32 src_auto_shadow, dst_auto_shadow;
u32 src_w, src_stride, src_h;
u32 dst_w, dst_stride, dst_h, dst_size_uv;
u32 split_h, split_v1, split_v2;
};
struct vse_crop_size {
u32 left;
u32 right;
u32 top;
u32 bottom;
};
struct vse_size {
u32 width;
u32 height;
};
struct vse_format_conv_settings {
u32 in_format;
u32 out_format;
};
struct vse_mi_settings {
bool enable;
u32 out_format;
u32 width;
u32 height;
u32 yuvbit;
};
struct vse_params {
u32 src_w;
u32 src_h;
u32 in_format;
u32 in_yuvbit;
u32 input_select;
struct vse_crop_size crop_size[3];
struct vse_size out_size[3];
struct vse_format_conv_settings format_conv[3];
bool resize_enable[3];
struct vse_mi_settings mi_settings[3];
};
struct dw200_subdev {
struct dwe_hw_info dwe_info;
struct vse_params vse_info;
void __iomem *dwe_base;
void __iomem *dwe_reset;
void __iomem *vse_base;
void __iomem *vse_reset;
vivdw200_mis_list_t dwe_circle_list;
vivdw200_mis_list_t vse_circle_list;
struct mutex *vvmutex;
};
void dwe_write_reg(struct dw200_subdev *dev, u32 offset, u32 val);
u32 dwe_read_reg(struct dw200_subdev *dev, u32 offset);
void vse_write_reg(struct dw200_subdev *dev, u32 offset, u32 val);
u32 vse_read_reg(struct dw200_subdev *dev, u32 offset);
#endif // _DW200_DEV_H

119
vvcam/dw200/dwe_regs.h Normal file
View File

@@ -0,0 +1,119 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _DWE_REGS_H_
#define _DWE_REGS_H_
//#define REGISTER_NUM 100
#define DEWARP_REGISTER_BASE_ADDR 0x00000C00
#define DEWARP_CTRL 0x00000004
#define SWAP_CONTROL 0x00000058
#define VERTICAL_SPLIT_LINE 0x0000005C
#define HORIZON_SPLIT_LINE 0x00000060
#define SCALE_FACTOR 0x00000064
#define ROI_START 0x00000068
#define BOUNDRY_PIXEL 0x0000006C
#define INTERRUPT_STATUS 0x00000070
#define INT_FRAME_DONE (1 << 0)
#define INT_ERR_STATUS_MASK 0x000000FE
#define INT_ERR_STATUS_SHIFT 1
#define INT_MSK_STATUS_MASK 0x0000FF00
#define INT_MSK_STATUS_SHIFT 8
#define INT_FRAME_BUSY 0x00010000
#ifdef HAL_CMODEL
#define INT_CLR_MASK 0x00007F00
#else
#define INT_CLR_MASK 0x00000100
#endif
#define INT_RESET_MASK 0x01000000
#define BUS_CTRL 0x00000074
#define DEWRAP_BUS_CTRL_ENABLE_MASK (1 << 31)
#define DEWRAP_BUS_CTRL_RD_ID_ENABLE_MASK (1 << 30)
#define DEWRAP_BUS_CTRL_WR_ID_ENABLE_MASK (1 << 29)
#define DEWRAP_BUS_CTRL_RD_ID_SHIFT (8)
#define DEWRAP_BUS_CTRL_WR_ID_SHIFT (16)
#define BUS_CTRL1 0x00000078
#define BUS_TIME_OUT_CYCLE 0x0000007C
#define MAP_LUT_ADDR 0x00000008
#define MAP_LUT_SIZE 0x0000000C
#define SRC_IMG_Y_BASE 0x00000010
#define SRC_IMG_UV_BASE 0x00000014
#define SRC_IMG_SIZE 0x00000018
#define SRC_IMG_STRIDE 0x0000001C
#define MAP_LUT_ADDR2 0x00000020
#define MAP_LUT_SIZE2 0x00000024
#define SRC_IMG_Y_BASE2 0x00000028
#define SRC_IMG_UV_BASE2 0x0000002C
#define SRC_IMG_SIZE2 0x00000030
#define SRC_IMG_STRIDE2 0x00000034
#define DST_IMG_Y_BASE 0x00000038
#define DST_IMG_UV_BASE 0x0000003C
#define DST_IMG_SIZE 0x00000040
#define DST_IMG_STRIDE 0x00000044
#define DST_IMG_Y_BASE2 0x00000048
#define DST_IMG_UV_BASE2 0x0000004C
#define DST_IMG_SIZE2 0x00000050
#define DST_IMG_STRIDE2 0x00000054
#define DST_IMG_Y_SIZE1 0x00000080
#define DST_IMG_UV_SIZE1 0x00000084
#define DST_IMG_Y_SIZE2 0x00000088
#define DST_IMG_UV_SIZE2 0x0000008C
#define DST_IMG_WIDTH_BN 0x0000009C
#endif /* _DWE_REGS_H_ */

View File

@@ -0,0 +1,191 @@
#ifdef __KERNEL__
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/debugfs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#else
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#endif
#include "vivdw200_irq_queue.h"
#ifdef __KERNEL__
#define dw_info(...)
#else
#define dw_info(...)
#endif
//enqueue
int vivdw200_enqueue(vivdw200_mis_t *data,vivdw200_mis_t* head)
{
#ifdef __KERNEL__
vivdw200_mis_t* new_node = (vivdw200_mis_t*)kmalloc(sizeof(vivdw200_mis_t), GFP_KERNEL); //create new node
if (data == NULL || head == NULL) {
//dw_info("%s: input wrong parameter\n", __func__);
return -1;
}
new_node->val = data->val;
dw_info("%s: new_node %px", __func__, new_node);
INIT_LIST_HEAD(&new_node->list);
list_add_tail(&new_node->list, &head->list); //append to tail
#endif
return 0;
}
//dequeue && release memory
int vivdw200_dequeue(vivdw200_mis_t* data, vivdw200_mis_t* head)
{
#ifdef __KERNEL__
vivdw200_mis_t* entry;
if (data == NULL || head == NULL) {
//dw_info("%s: input wrong parameter\n", __func__);
return -1;
}
if (list_empty(&head->list)) {
//dw_info("%s: There is no node\n", __func__);
return -1;
}
entry = list_first_entry(&head->list, vivdw200_mis_t, list);
dw_info("%s: entry %px", __func__, entry);
data->val = entry->val;
list_del_init(&entry->list);
kfree(entry);
#endif
return 0;
}
bool vivdw200_is_queue_empty( vivdw200_mis_t* head)
{
#ifdef __KERNEL__
return list_empty(&head->list);
#else
return 0;
#endif
}
int vivdw200_create_circle_queue(vivdw200_mis_list_t* pCList, int number)
{
#ifdef __KERNEL__
int i;
vivdw200_mis_t* pMisNode;
if (pCList == NULL || number <= 0) {
dw_info("%s: create circle queue failed\n", __func__);
return -1;
}
if (pCList->pHead == NULL) {
pCList->pHead = (vivdw200_mis_t*)kmalloc(sizeof(vivdw200_mis_t), GFP_KERNEL);
INIT_LIST_HEAD(&pCList->pHead->list);
pCList->pRead = pCList->pHead;
pCList->pWrite = pCList->pHead;
}
dw_info("%s:pHead %px\n", __func__, pCList->pHead);
for (i = 0; i < number - 1; i++) {
pMisNode = (vivdw200_mis_t*)kmalloc(sizeof(vivdw200_mis_t), GFP_KERNEL);
INIT_LIST_HEAD(&pMisNode->list);
list_add_tail(&pMisNode->list, &pCList->pHead->list);
dw_info("%s:pMisNode %px\n", __func__, pMisNode);
}
#endif
return 0;
}
int vivdw200_destroy_circle_queue(vivdw200_mis_list_t* pCList)
{
#ifdef __KERNEL__
vivdw200_mis_t* pMisNode;
if (pCList == NULL || (pCList->pHead == NULL) ) {
dw_info("%s: destroy circle queue failed. pClist %px\n", __func__, pCList);
return -1;
}
while(!list_empty(&pCList->pHead->list)) {
pMisNode = list_first_entry(&pCList->pHead->list, vivdw200_mis_t, list);
dw_info("%s:pMisNode %px\n", __func__, pMisNode);
list_del(&pMisNode->list);
kfree(pMisNode);
pMisNode = NULL;
}
dw_info("%s:pHead %px\n", __func__, pCList->pHead);
kfree(pCList->pHead);
pCList->pHead = NULL;
pCList->pRead = NULL;
pCList->pWrite = NULL;
#endif
return 0;
}
int vivdw200_read_circle_queue(vivdw200_mis_t* data, vivdw200_mis_list_t* pCList)
{
#ifdef __KERNEL__
//vivdw200_mis_t* pReadEntry;
if (pCList == NULL) {
dw_info("%s: can not read circle queue\n", __func__);
return -1;
}
if (pCList->pRead == pCList->pWrite) {
dw_info("%s: There is no irq mis data\n", __func__);
return -1;
}
data->val = pCList->pRead->val;
dw_info("%s: entry %px, msi %08x\n", __func__, pCList->pRead, data->val);
/*Get the next entry that link with read entry list*/
/*Update read pointer to next entry*/
pCList->pRead = list_first_entry(&pCList->pRead->list, vivdw200_mis_t, list);
//pCList->pRead = pReadEntry;
#endif
return 0;
}
int vivdw200_write_circle_queue(vivdw200_mis_t* data, vivdw200_mis_list_t* pCList)
{
#ifdef __KERNEL__
vivdw200_mis_t* pWriteEntry;
if (pCList == NULL) {
dw_info("%s: can not read circle queue\n", __func__);
return -1;
}
pCList->pWrite->val = data->val;
dw_info("%s: entry %px, msi %08x\n", __func__, pCList->pWrite, data->val);
/*get the next write entry pointer that link with the write entry list*/
pWriteEntry = list_first_entry(&pCList->pWrite->list, vivdw200_mis_t, list);
/*Update write pointer to point next entry*/
pCList->pWrite = pWriteEntry;
#endif
return 0;
}

View File

@@ -0,0 +1,83 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _VIVDW200_QUEUE_H_
#define _VIVDW200_QUEUE_H_
#ifdef __KERNEL__
#include <linux/list.h>
#endif
typedef struct vivdw200_mis_s {
unsigned int val;
#ifdef __KERNEL__
struct list_head list;
#endif
}vivdw200_mis_t;
typedef struct vivdw200_mis_list_s {
vivdw200_mis_t* pHead;
vivdw200_mis_t* pRead;
vivdw200_mis_t* pWrite;
}vivdw200_mis_list_t;
int vivdw200_enqueue(vivdw200_mis_t *data,vivdw200_mis_t* head);
int vivdw200_dequeue(vivdw200_mis_t* data, vivdw200_mis_t* head);
bool vivdw200_is_queue_empty( vivdw200_mis_t* head);
#define QUEUE_NODE_COUNT 15
int vivdw200_create_circle_queue(vivdw200_mis_list_t* pCList, int number);
int vivdw200_destroy_circle_queue(vivdw200_mis_list_t* pCList);
int vivdw200_read_circle_queue(vivdw200_mis_t* data, vivdw200_mis_list_t* pCList);
int vivdw200_write_circle_queue(vivdw200_mis_t* data, vivdw200_mis_list_t* pCList);
#endif

322
vvcam/dw200/vse_regs.h Normal file
View File

@@ -0,0 +1,322 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _VSE_REGS_H_
#define _VSE_REGS_H_
/* product identification */
#define VSE_REG_ID 0x00000000
#define VSE_REG_CTRL 0x00000004
#define VSE_CONTROL_ENABLE_RAM_CLK 17
#define VSE_CONTROL_AUTO_UPDATE_BIT 16
#define VSE_CONTROL_CONFIG_UPDATE_BIT 15
#define VSE_CONTROL_DMA_FRAME_START_BIT 14
#define VSE_CONTROL_INPUT_SELECT_SHIFT 11
#define VSE_CONTROL_INPUT_SELECT (7 << 11)
#define VSE_CONTROL_INPUT_FORMAT_SHIFT 9
#define VSE_CONTROL_INPUT_FORMAT (3 << 9)
#define VSE_CONTROL_SOFT_RESET_BIT 8
#define VSE_CONTROL_PATH2_ENABLE_BIT 2
#define VSE_CONTROL_PATH1_ENABLE_BIT 1
#define VSE_CONTROL_PATH0_ENABLE_BIT 0
/* input size 28:16 height, 12:0 width */
#define VSE_REG_IN_SIZE 0x00000008
#define VSE_REG_CTRL_SHD 0x0000000C
#define VSE_REG_RSZ0_CTL 0x00000400
#define VSE_REG_RSZ1_CTL 0x00000500
#define VSE_REG_RSZ2_CTL 0x00000600
#define VSE_RSZBASE(c) ((c) == 0 ? VSE_REG_RSZ0_CTL : ((c) == 1 ? VSE_REG_RSZ1_CTL : VSE_REG_RSZ2_CTL))
#define VSE_RSZ_SCALE_HY 0x00000004
#define VSE_RSZ_SCALE_HCB 0x00000008
#define VSE_RSZ_SCALE_HCR 0x0000000C
#define VSE_RSZ_SCALE_VY 0x00000010
#define VSE_RSZ_SCALE_VC 0x00000014
#define VSE_RSZ_PHASE_HY 0x00000018
#define VSE_RSZ_PHASE_HC 0x0000001C
#define VSE_RSZ_PHASE_VY 0x00000020
#define VSE_RSZ_PHASE_VC 0x00000024
#define VSE_RSZ_SCALE_LUT_ADDR 0x00000028
#define VSE_RSZ_SCALE_LUT 0x0000002C
#define VSE_RSZ_CTRL_SHD 0x00000030
#define VSE_RSZ_SCALE_HY_SHD 0x00000034
#define VSE_RSZ_SCALE_HCB_SHD 0x00000038
#define VSE_RSZ_SCALE_HCR_SHD 0x0000003C
#define VSE_RSZ_SCALE_VY_SHD 0x00000040
#define VSE_RSZ_SCALE_VC_SHD 0x00000044
#define VSE_RSZ_PHASE_HY_SHD 0x00000048
#define VSE_RSZ_PHASE_HC_SHD 0x0000004C
#define VSE_RSZ_PHASE_VY_SHD 0x00000050
#define VSE_RSZ_PHASE_VC_SHD 0x00000054
#define VSE_RSZ_CROP_XDIR 0x00000058
#define VSE_RSZ_CROP_YDIR 0x0000005C
#define VSE_RSZ_CROP_XDIR_SHD 0x00000060
#define VSE_RSZ_CROP_YDIR_SHD 0x00000064
#define VSE_RSZ_FRAME_RATE 0x00000068
#define VSE_REG_FORMAT_CONV_CTRL 0x0000006C
#define VSE_REG_HBLANK_VALUE 0x000001A0
#define VSE_REG_VBLANK_VALUE 0x000001A4
#define VSE_REG_VSYNC_WIDTH 0x000001A8
#define VSE_REG_HSYNC_PREAMBLE 0x000001AC
#define VSE_REG_MI_CTRL 0x00000800
#define VSE_REG_MI_CTRL_SHD 0x00000804
#define VSE_REG_MI_PATH_0 0x00000810
#define VSE_REG_MI_PATH_1 0x000008b0
#define VSE_REG_MI_PATH_2 0x00000950
#define VSE_MI_BASE(c) ((c) == 0 ? VSE_REG_MI_PATH_0 : ((c) == 1 ? VSE_REG_MI_PATH_1 : VSE_REG_MI_PATH_2))
#define VSE_REG_MI_FMT 0x00000004
#define VSE_REG_MI_Y_BASE_ADDR_INIT 0x00000014
#define VSE_REG_MI_Y_SIZE_INIT 0x00000018
#define VSE_REG_MI_Y_OFFSET_COUNT_INIT 0x0000001C
#define VSE_REG_MI_Y_LENGTH 0x00000020
#define VSE_REG_MI_Y_PIC_WIDTH 0x00000024
#define VSE_REG_MI_Y_PIC_HEIGHT 0x00000028
#define VSE_REG_MI_Y_PIC_SIZE 0x0000002C
#define VSE_REG_MI_CB_BASE_ADDR_INIT 0x00000030
#define VSE_REG_MI_CB_SIZE_INIT 0x00000034
#define VSE_REG_MI_CB_OFFSET_COUNT_INIT 0x00000038
#define VSE_REG_MI_CR_BASE_ADDR_INIT 0x0000003C
#define VSE_REG_MI_CR_SIZE_INIT 0x00000040
#define VSE_REG_MI_CR_OFFSET_COUNT_INIT 0x00000044
#define VSE_REG_MI_Y_BASE_ADDR_INIT2 0x00000048
#define VSE_REG_MI_CB_BASE_ADDR_INIT2 0x0000004C
#define VSE_REG_MI_CR_BASE_ADDR_INIT2 0x00000050
#define VSE_REG_MI_Y_OFFS_CNT_START 0x00000054
#define VSE_REG_MI_CB_OFFS_CNT_START 0x00000058
#define VSE_REG_MI_CR_OFFS_CNT_START 0x0000005C
#define VSE_REG_MI_Y_BASE_ADDR_SHD 0x00000060
#define VSE_REG_MI_Y_SIZE_SHD 0x00000064
#define VSE_REG_MI_Y_OFFS_COUNT_SHD 0x00000068
#define VSE_REG_MI_CB_BASE_ADDR_SHD 0x0000006C
#define VSE_REG_MI_CB_SIZE_SHD 0x00000070
#define VSE_REG_MI_CB_OFFS_COUNT_SHD 0x00000074
#define VSE_REG_MI_CR_BASE_ADDR_SHD 0x00000078
#define VSE_REG_MI_CR_SIZE_SHD 0x0000007C
#define VSE_REG_MI_CR_OFFS_COUNT_SHD 0x00000080
#define VSE_REG_MI_STATUS_CLR 0x00000084
#define VSE_REG_MI_CTRL_STATUS 0x00000088
#define VSE_REG_MI_Y_IRQ_OFFS_INIT 0x0000008C
#define VSE_REG_MI_Y_IRQ_OFFS_SHD 0x00000090
#define VSE_REG_DMA_CTRL 0x000009E8
#define VSE_REG_DMA_FORMAT 0x000009EC
#define VSE_REG_DMA_Y_PIC_WIDTH 0x000009F0
#define VSE_REG_DMA_Y_PIC_HEIGHT 0x000009F4
#define VSE_REG_DMA_Y_PIC_STRIDE 0x000009F8
#define VSE_REG_Y_PIC_START_ADDR 0x000009FC
#define VSE_REG_CB_PIC_START_ADDR 0x00000A00
#define VSE_REG_CR_PIC_START_ADDR 0x00000A04
#define VSE_REG_Y_START_ADDR_SHD 0x00000A08
#define VSE_REG_CB_START_ADDR_SHD 0x00000A0C
#define VSE_REG_CR_START_ADDR_SHD 0x00000A10
#define VSE_REG_DMA_STATUS 0x00000A14
#define VSE_REG_MI0_BUS_CONFIG 0x00000A20
#define VSE_REG_MI0_BUS_ID 0x00000A24
#define VSE_REG_MI0_BUS_TIME_OUT 0x00000A28
#define VSE_REG_MI0_AXI_STATUS 0x00000A2C
#define VSE_REG_MI1_BUS_CONFIG 0x00000A30
#define VSE_REG_MI1_BUS_ID 0x00000A34
#define VSE_REG_MI1_BUS_TIME_OUT 0x00000A38
#define VSE_REG_MI1_AXI_STATUS 0x00000A3C
#define VSE_REG_MI_IMSC 0x00000A40
#define VSE_REG_MI_IMSC1 0x00000A44
#define VSE_REG_MI_ISR 0x00000A48
#define VSE_REG_MI_ISR1 0x00000A4C
#define VSE_REG_MI_MSI 0x00000A50
#define VSE_REG_MI_MSI1 0x00000A54
#define VSE_REG_MI_ICR 0x00000A58
#define VSE_REG_MI_ICR1 0x00000A5C
#define VSE_REG_MI_RIS 0x00000A60
#define VSE_REG_MI_RIS1 0x00000A64
#define VSE_FORMAT_CONV_ENABLE_PACK_SHIFT 10
#define VSE_FORMAT_CONV_ENABLE_PACK (1 << 10)
#define VSE_FORMAT_CONV_EXPAND_8TO10_METHOD_SHIFT 9
#define VSE_FORMAT_CONV_EXPAND_8TO10_METHOD (1 << 9)
#define VSE_FORMAT_CONV_EXPAND_8TO10_ENABLE_SHIFT 8
#define VSE_FORMAT_CONV_EXPAND_8TO10_ENABLE (1 << 8)
#define VSE_FORMAT_CONV_CONFIG_422NOCO_SHIFT 7
#define VSE_FORMAT_CONV_CONFIG_422NOCO (1 << 7)
#define VSE_FORMAT_CONV_CBCR_FULL_SHIFT 6
#define VSE_FORMAT_CONV_CBCR_FULL (1 << 6)
#define VSE_FORMAT_CONV_Y_FULL_SHIFT 5
#define VSE_FORMAT_CONV_Y_FULL (1 << 5)
#define VSE_FORMAT_CONV_OUTPUT_FORMAT_SHIFT 2
#define VSE_FORMAT_CONV_OUTPUT_FORMAT (7 << 2)
#define VSE_FORMAT_CONV_INPUT_FORMAT_SHIFT 0
#define VSE_FORMAT_CONV_INPUT_FORMAT (3)
/* slice of VSE_REG_RSZ0_CTL */
#define VSE_RESIZE_CONTROL_AUTO_UPDATE_BIT 10
#define VSE_RESIZE_CONTROL_CONFIG_UPDATE_BIT 9
#define VSE_RESIZE_CONTROL_CROP_ENABLE_BIT 8
#define VSE_RESIZE_CONTROL_SCALE_VCUP_BIT 7
#define VSE_RESIZE_CONTROL_SCALE_VYUP_BIT 6
#define VSE_RESIZE_CONTROL_SCALE_HCUP_BIT 5
#define VSE_RESIZE_CONTROL_SCALE_HYUP_BIT 4
#define VSE_RESIZE_CONTROL_SCALE_VC_ENABLE_BIT 3
#define VSE_RESIZE_CONTROL_SCALE_VY_ENABLE_BIT 2
#define VSE_RESIZE_CONTROL_SCALE_HC_ENABLE_BIT 1
#define VSE_RESIZE_CONTROL_SCALE_HY_ENABLE_BIT 0
/* slice of VSE_REG_MI_FMT */
#define VSE_RD_IMG_HSIZE_BN_SHIFT 16
#define VSE_RD_IMG_HSIZE_BN (0x3fff<<16)
#define VSE_MI_FORMAT_WA_MSB_EN_SHIFT 10
#define VSE_MI_FORMAT_WA_MSB_EN (1<<10)
#define VSE_MI_FORMAT_WORD_ALIGNED_SHIFT 9
#define VSE_MI_FORMAT_WORD_ALIGNED (1<<9)
#define VSE_MI_FORMAT_WR_YUV_NVY_SHIFT 7
#define VSE_MI_FORMAT_WR_YUV_NVY (3 << 7)
#define VSE_MI_FORMAT_WR_YUV_N21_SHIFT 6
#define VSE_MI_FORMAT_WR_YUV_N21 (1 << 6)
#define VSE_MI_FORMAT_WR_FMT_ALIGNED_SHIFT 5
#define VSE_MI_FORMAT_WR_FMT_ALIGNED (1 << 5)
#define VSE_MI_FORMAT_WR_YUV_STR_SHIFT 3
#define VSE_MI_FORMAT_WR_YUV_STR (3 << 3)
#define VSE_MI_FORMAT_WR_YUV_FMT_SHIFT 1
#define VSE_MI_FORMAT_WR_YUV_FMT (3 << 1)
#define VSE_MI_FORMAT_WR_YUV_10BIT_SHIFT 0
#define VSE_MI_FORMAT_WR_YUV_10BIT (1)
/* slice of VSE_REG_MI_CTRL */
#define VSE_MI_CONTROL_RDMA_START_BIT 4
#define VSE_MI_CONTROL_RDMA_ENABLE_BIT 3
#define VSE_MI_CONTROL_MI2_PATH_ENABLE_BIT 2
#define VSE_MI_CONTROL_MI1_PATH_ENABLE_BIT 1
#define VSE_MI_CONTROL_MI0_PATH_ENABLE_BIT 0
/* slice of VSE_REG_MI_PATH */
#define VSE_MI_PATH_INIT_OFFSET_EN_BIT 5
#define VSE_MI_PATH_INIT_BASE_EN_BIT 4
#define VSE_MI_PATH_CONFIG_UPDATE_BIT 3
#define VSE_MI_PATH_ENABLE_SKIP_BIT 2
#define VSE_MI_PATH_AUTO_UPDATE_BIT 1
#define VSE_MI_PATH_ENABLE_PINGPONG_BIT 0
#define VSE_MI_ISR_STATUS_VSE_AND_DEWARP_ALL_DONE_BIT 14
#define VSE_MI_ISR_STATUS_FINAL_FRAME_END_BIT 13
#define VSE_MI_ISR_STATUS_DMA_YCBCR_READY_BIT 12
#define VSE_MI_ISR_STATUS_WRAP_MI2_CR_BIT 11
#define VSE_MI_ISR_STATUS_WRAP_MI2_CB_BIT 10
#define VSE_MI_ISR_STATUS_WRAP_MI2_Y_BIT 9
#define VSE_MI_ISR_STATUS_WRAP_MI1_CR_BIT 8
#define VSE_MI_ISR_STATUS_WRAP_MI1_CB_BIT 7
#define VSE_MI_ISR_STATUS_WRAP_MI1_Y_BIT 6
#define VSE_MI_ISR_STATUS_WRAP_MI0_CR_BIT 5
#define VSE_MI_ISR_STATUS_WRAP_MI0_CB_BIT 4
#define VSE_MI_ISR_STATUS_WRAP_MI0_Y_BIT 3
#define VSE_MI_ISR_STATUS_MI2_FRAME_END_BIT 2
#define VSE_MI_ISR_STATUS_MI1_FRAME_END_BIT 1
#define VSE_MI_ISR_STATUS_MI0_FRAME_END_BIT 0
#define VSE_MI_MIS_VSE_AND_DEWARP_ALL_DONE_BIT 14
#define VSE_MI_MIS_FINAL_FRAME_END_BIT 13
#define VSE_MI_MIS_DMA_YCBCR_READY_BIT 12
#define VSE_MI_MIS_WRAP_MI2_CR_BIT 11
#define VSE_MI_MIS_WRAP_MI2_CB_BIT 10
#define VSE_MI_MIS_WRAP_MI2_Y_BIT 9
#define VSE_MI_MIS_WRAP_MI1_CR_BIT 8
#define VSE_MI_MIS_WRAP_MI1_CB_BIT 7
#define VSE_MI_MIS_WRAP_MI1_Y_BIT 6
#define VSE_MI_MIS_WRAP_MI0_CR_BIT 5
#define VSE_MI_MIS_WRAP_MI0_CB_BIT 4
#define VSE_MI_MIS_WRAP_MI0_Y_BIT 3
#define VSE_MI_MIS_MI2_FRAME_END_BIT 2
#define VSE_MI_MIS_MI1_FRAME_END_BIT 1
#define VSE_MI_MIS_MI0_FRAME_END_BIT 0
#define VSE_MI_ISR_ERROR_MI2_BUS_ERROR_BIT 5
#define VSE_MI_ISR_ERROR_MI2_BUS_TIMEOUT_BIT 4
#define VSE_MI_ISR_ERROR_MI1_BUS_ERROR_BIT 3
#define VSE_MI_ISR_ERROR_MI1_BUS_TIMEOUT_BIT 2
#define VSE_MI_ISR_ERROR_MI0_BUS_ERROR_BIT 1
#define VSE_MI_ISR_ERROR_MI0_BUS_TIMEOUT_BIT 0
#define VSE_MI_BUS_CONFIG_WR_SWAP_V_SHIFT 16
#define VSE_MI_BUS_CONFIG_WR_SWAP_V (0XF << 16)
#define VSE_MI_BUS_CONFIG_WR_SWAP_U_SHIFT 12
#define VSE_MI_BUS_CONFIG_WR_SWAP_U (0XF << 12)
#define VSE_MI_BUS_CONFIG_WR_SWAP_Y_SHIFT 8
#define VSE_MI_BUS_CONFIG_WR_SWAP_Y (0XF << 8)
#define VSE_MI_BUS_CONFIG_RD_ISSUE_CAP_SHIFT 6
#define VSE_MI_BUS_CONFIG_RD_ISSUE_CAP (0X3 << 6)
#define VSE_MI_BUS_CONFIG_WR_ISSUE_CAP_SHIFT 4
#define VSE_MI_BUS_CONFIG_WR_ISSUE_CAP (0X3 << 4)
#define VSE_MI_BUS_CONFIG_RD_BURST_LEN_SHIFT 2
#define VSE_MI_BUS_CONFIG_RD_BURST_LEN (0X3 << 2)
#define VSE_MI_BUS_CONFIG_WR_BURST_LEN_SHIFT 0
#define VSE_MI_BUS_CONFIG_WR_BURST_LEN (0X3 << 0)
#ifndef REG_GET_MASK
#define REG_GET_MASK(reg, mask)\
(((reg) & (mask)) >> (mask##_SHIFT))
#define REG_SET_MASK(reg, mask, value)\
{\
((reg) = (((reg) & ~(mask)) | (((value) << (mask##_SHIFT)) & (mask))));\
}
#define REG_GET_BIT(reg, shift)\
(((reg) & 1) >> shift)
#define REG_SET_BIT(reg, shift, value)\
{\
((reg) = (((reg) & ~(1 << (shift))) | (((value) & 1) << (shift))));\
}
#endif
#endif /* _VSE_REGS_H_ */

119
vvcam/dwe/dwe_dev.h Executable file
View File

@@ -0,0 +1,119 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _DWE_DEV_H
#define _DWE_DEV_H
#include "vvdefs.h"
#ifndef __KERNEL__
#define copy_from_user(a, b, c) dwe_copy_data(a, b, c)
#define copy_to_user(a, b, c) dwe_copy_data(a, b, c)
typedef bool(*pReadBar) (uint32_t bar, uint32_t *data);
typedef bool(*pWriteBar) (uint32_t bar, uint32_t data);
extern void dwe_set_func(pReadBar read_func, pWriteBar write_func);
extern long dwe_copy_data(void *dst, void *src, int size);
#endif
#define MAX_DWE_NUM (2)
#define MAX_CFG_NUM (2)
struct dwe_hw_info {
u32 split_line;
u32 scale_factor;
u32 in_format;
u32 out_format;
u32 hand_shake;
u32 roi_x, roi_y;
u32 boundary_y, boundary_u, boundary_v;
u32 map_w, map_h;
u32 src_auto_shadow, dst_auto_shadow;
u32 src_w, src_stride, src_h;
u32 dst_w, dst_stride, dst_h, dst_size_uv;
u32 split_h, split_v1, split_v2;
};
enum BUF_ERR_TYPE {
BUF_ERR_UNDERFLOW = 1,
BUF_ERR_OVERFLOW0 = 1 << 1,
BUF_ERR_OVERFLOW1 = 1 << 2,
BUF_ERR_NO_DIST_MAP0 = 1 << 3,
BUF_ERR_NO_DIST_MAP1 = 1 << 4,
BUF_ERR_WRONGSTATE = 1 << 5,
};
struct dwe_ic_dev {
struct dwe_hw_info info[MAX_DWE_NUM][MAX_CFG_NUM];
int which[MAX_DWE_NUM];
void __iomem *base;
void __iomem *reset;
#if defined(__KERNEL__) && defined(ENABLE_IRQ)
struct vvbuf_ctx *sink_bctx;
struct vvbuf_ctx *src_bctx[MAX_DWE_NUM];
dma_addr_t dist_map[MAX_DWE_NUM][MAX_CFG_NUM];
int *state[MAX_DWE_NUM];
int index;
struct vb2_dc_buf *src;
struct vb2_dc_buf *dst;
spinlock_t irqlock;
u32 error;
int (*get_index)(struct dwe_ic_dev *dev, struct vb2_dc_buf *buf);
#endif
};
void dwe_write_reg(struct dwe_ic_dev *dev, u32 offset, u32 val);
u32 dwe_read_reg(struct dwe_ic_dev *dev, u32 offset);
#endif /* _DWE_DEV_H */

381
vvcam/dwe/dwe_ioctl.c Executable file
View File

@@ -0,0 +1,381 @@
/****************************************************************************
*
* 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 "dwe_ioctl.h"
#include "dwe_regs.h"
#ifndef __KERNEL__
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#ifdef USE_V4L2
#include <linux/videodev2.h>
#endif
#endif
#ifndef __KERNEL__
#ifdef HAL_CMODEL
#define DEWARP_REGISTER_OFFSET 0
#else
#define DEWARP_REGISTER_OFFSET 0x380000
#endif
#define DEWARP_REGISTER_CTL 0x308250
pReadBar g_read_func;
pWriteBar g_write_func;
void dwe_set_func(pReadBar read_func, pWriteBar write_func)
{
g_read_func = read_func;
g_write_func = write_func;
}
void dwe_write_reg(struct dwe_ic_dev *dev, u32 offset, u32 val)
{
g_write_func(DEWARP_REGISTER_OFFSET + offset, val);
}
u32 dwe_read_reg(struct dwe_ic_dev *dev, u32 offset)
{
u32 data;
g_read_func(DEWARP_REGISTER_OFFSET + offset, &data);
return data;
}
void dwe_write_extreg(u32 offset, u32 val)
{
g_write_func(DEWARP_REGISTER_CTL + offset, val);
}
u32 dwe_read_extreg(u32 offset)
{
u32 data;
g_read_func(DEWARP_REGISTER_CTL + offset, &data);
return data;
}
long dwe_copy_data(void *dst, void *src, int size)
{
if (dst != src)
memcpy(dst, src, size);
return 0;
}
#else
void dwe_write_reg(struct dwe_ic_dev *dev, u32 offset, u32 val)
{
__raw_writel(val, dev->base + offset);
}
u32 dwe_read_reg(struct dwe_ic_dev *dev, u32 offset)
{
return __raw_readl(dev->base + offset);
}
#endif
int dwe_reset(struct dwe_ic_dev *dev)
{
pr_debug("enter %s\n", __func__);
#ifdef DWE_REG_RESET
__raw_writel(0, dev->reset);
__raw_writel(1, dev->reset);
#endif
dwe_write_reg(dev, DEWARP_CTRL, 0x0c);
return 0;
}
int dwe_s_params(struct dwe_ic_dev *dev, struct dwe_hw_info *info)
{
u32 reg = 0;
u32 reg_y_rbuff_size = ALIGN_UP(info->dst_stride * info->dst_h, 16);
u32 vUp = (info->split_v1 & ~0x0F) | 0x0C;
u32 vDown = (info->split_v2 & ~0x0F) | 0x0C;
u32 hLine = (info->split_h & ~0x0F) | 0x0C;
pr_debug("enter %s\n", __func__);
dwe_write_reg(dev, MAP_LUT_SIZE,
((info->map_w & 0x7ff) | ((info->map_h & 0x7ff) << 16)));
dwe_write_reg(dev, SRC_IMG_SIZE,
((info->src_w & 0x1fff) |
((info->src_h & 0x1fff) << 16)));
dwe_write_reg(dev, SRC_IMG_STRIDE, info->src_stride);
dwe_write_reg(dev, DST_IMG_SIZE,
((info->dst_w & 0x1FFF) |
((info->dst_h & 0x1FFF) << 16)));
dwe_write_reg(dev, DST_IMG_STRIDE, info->dst_stride);
dwe_write_reg(dev, DST_IMG_Y_SIZE1, reg_y_rbuff_size >> 4);
dwe_write_reg(dev, DST_IMG_UV_SIZE1, info->dst_size_uv >> 4);
dwe_write_reg(dev, VERTICAL_SPLIT_LINE,
(vUp & 0x1fff) | ((vDown & 0x1fff) << 16));
dwe_write_reg(dev, HORIZON_SPLIT_LINE, (hLine & 0x1fff));
reg = 0x4C800001;
reg |= ((info->split_line & 0x1) << 11);
reg |= ((info->in_format & 0x3) << 4);
reg |= ((info->out_format & 0x3) << 6);
reg |=
((info->src_auto_shadow & 0x1) << 8) |
((info->dst_auto_shadow & 0x1) << 10);
reg |= ((info->hand_shake & 0x1) << 9);
dwe_write_reg(dev, DEWARP_CTRL, reg);
dwe_write_reg(dev, BOUNDRY_PIXEL,
(((info->boundary_y & 0xff) << 16) |
((info->boundary_u & 0xff)
<< 8) | (info->boundary_v & 0xff)));
dwe_write_reg(dev, SCALE_FACTOR, info->scale_factor);
dwe_write_reg(dev, ROI_START,
((info->roi_x & 0x1fff) |
((info->roi_y & 0x1fff) << 16)));
return 0;
}
int dwe_enable_bus(struct dwe_ic_dev *dev, bool enable)
{
u32 reg = dwe_read_reg(dev, BUS_CTRL);
/* pr_debug("enter %s\n", __func__); */
if (enable) {
dwe_write_reg(dev, BUS_CTRL, reg | DEWRAP_BUS_CTRL_ENABLE_MASK);
} else {
dwe_write_reg(dev, BUS_CTRL,
reg & ~DEWRAP_BUS_CTRL_ENABLE_MASK);
}
return 0;
}
int dwe_disable_irq(struct dwe_ic_dev *dev)
{
/* pr_debug("enter %s\n", __func__); */
dwe_write_reg(dev, INTERRUPT_STATUS, INT_CLR_MASK);
return 0;
}
int dwe_clear_irq(struct dwe_ic_dev *dev)
{
u32 reg_dewarp_ctrl;
/* pr_debug("enter %s\n", __func__); */
reg_dewarp_ctrl = dwe_read_reg(dev, DEWARP_CTRL);
dwe_write_reg(dev, DEWARP_CTRL, reg_dewarp_ctrl | 2);
dwe_write_reg(dev, DEWARP_CTRL, reg_dewarp_ctrl);
dwe_write_reg(dev, INTERRUPT_STATUS, INT_CLR_MASK | INT_MSK_STATUS_MASK);
return 0;
}
int dwe_read_irq(struct dwe_ic_dev *dev, u32 *ret)
{
u32 irq = 0;
irq = dwe_read_reg(dev, INTERRUPT_STATUS);
*ret = irq;
return 0;
}
int dwe_start(struct dwe_ic_dev *dev)
{
#if defined(__KERNEL__) && defined(ENABLE_IRQ)
dev->src = NULL;
dev->dst = NULL;
dev->error = BUF_ERR_UNDERFLOW;
#endif
return 0;
}
int dwe_stop(struct dwe_ic_dev *dev)
{
dwe_enable_bus(dev, 0);
dwe_disable_irq(dev);
return 0;
}
int dwe_start_dma_read(struct dwe_ic_dev *dev,
struct dwe_hw_info *info, u64 addr)
{
#ifdef DWE_REG_RESET
u32 regStart = 1 << 4;
u32 reg;
#endif
u32 reg_dst_y_base = (u32)addr;
u32 reg_y_rbuff_size = ALIGN_UP(info->src_stride * info->src_h, 16);
u32 reg_dst_uv_base = reg_dst_y_base + reg_y_rbuff_size;
/* pr_debug("enter %s\n", __func__); */
dwe_write_reg(dev, SRC_IMG_Y_BASE, (reg_dst_y_base) >> 4);
dwe_write_reg(dev, SRC_IMG_UV_BASE, (reg_dst_uv_base) >> 4);
#ifdef DWE_REG_RESET
reg = __raw_readl(dev->reset);
__raw_writel(reg | regStart, dev->reset);
__raw_writel(reg & ~regStart, dev->reset);
#endif
return 0;
}
int dwe_set_buffer(struct dwe_ic_dev *dev, struct dwe_hw_info *info, u64 addr)
{
u32 reg_dst_y_base = (u32) addr;
u32 reg_y_rbuff_size = ALIGN_UP(info->dst_stride * info->dst_h, 16);
u32 reg_dst_uv_base = reg_dst_y_base + reg_y_rbuff_size;
/* pr_debug("enter %s\n", __func__); */
dwe_write_reg(dev, DST_IMG_Y_BASE, (reg_dst_y_base) >> 4);
dwe_write_reg(dev, DST_IMG_UV_BASE, (reg_dst_uv_base) >> 4);
return 0;
}
int dwe_set_lut(struct dwe_ic_dev *dev, u64 addr)
{
dwe_write_reg(dev, MAP_LUT_ADDR, ((u32) addr) >> 4);
return 0;
}
int dwe_ioc_qcap(struct dwe_ic_dev *dev, void __user *args)
{
#ifdef __KERNEL__
struct v4l2_capability *cap = (struct v4l2_capability *)args;
strcpy((char *)cap->driver, "viv_dewarp100");
#endif
return 0;
}
long dwe_priv_ioctl(struct dwe_ic_dev *dev, unsigned int cmd, void __user *args)
{
int ret = -1;
switch (cmd) {
case DWEIOC_RESET:
ret = dwe_reset(dev);
break;
case DWEIOC_S_PARAMS:
viv_check_retval(copy_from_user
(&dev->info[0][0], args, sizeof(dev->info[0][0])));
ret = dwe_s_params(dev, &dev->info[0][0]);
break;
#ifndef ENABLE_IRQ
case DWEIOC_ENABLE_BUS:
ret = dwe_enable_bus(dev, 1);
break;
case DWEIOC_DISABLE_BUS:
ret = dwe_enable_bus(dev, 0);
break;
case DWEIOC_DISABLE_IRQ:
ret = dwe_disable_irq(dev);
break;
case DWEIOC_CLEAR_IRQ:
ret = dwe_clear_irq(dev);
break;
#endif
case DWEIOC_READ_IRQ: {
u32 irq = 0;
#ifndef ENABLE_IRQ
ret = dwe_read_irq(dev, &irq);
#endif
viv_check_retval(copy_to_user(args, &irq, sizeof(irq)));
break;
}
case DWEIOC_START:
ret = dwe_start(dev);
break;
case DWEIOC_STOP:
ret = dwe_stop(dev);
break;
case DWEIOC_START_DMA_READ: {
#ifndef ENABLE_IRQ
u64 addr;
viv_check_retval(copy_from_user(&addr, args, sizeof(addr)));
ret = dwe_start_dma_read(dev, &dev->info[0][0], addr);
#endif
break;
}
case DWEIOC_SET_BUFFER: {
#ifndef ENABLE_IRQ
u64 addr;
viv_check_retval(copy_from_user(&addr, args, sizeof(addr)));
ret = dwe_set_buffer(dev, &dev->info[0][0], addr);
#endif
break;
}
case DWEIOC_SET_LUT: {
struct lut_info info;
viv_check_retval(copy_from_user(&info, args, sizeof(info)));
#ifndef ENABLE_IRQ
ret = dwe_set_lut(dev, info.addr);
#endif
break;
}
#ifdef __KERNEL__
case VIDIOC_QUERYCAP:
ret = dwe_ioc_qcap(dev, args);
break;
#endif
default:
pr_err("unsupported dwe command %d", cmd);
break;
}
return ret;
}

94
vvcam/dwe/dwe_ioctl.h Executable file
View File

@@ -0,0 +1,94 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _DWE_IOC_H_
#define _DWE_IOC_H_
#include "dwe_dev.h"
enum {
DWEIOC_RESET = 0x100,
DWEIOC_S_PARAMS,
DWEIOC_ENABLE_BUS,
DWEIOC_DISABLE_BUS,
DWEIOC_DISABLE_IRQ,
DWEIOC_CLEAR_IRQ,
DWEIOC_READ_IRQ,
DWEIOC_START,
DWEIOC_STOP,
DWEIOC_START_DMA_READ,
DWEIOC_SET_BUFFER,
DWEIOC_SET_LUT,
};
struct lut_info {
u32 port;
u64 addr;
};
long dwe_priv_ioctl(struct dwe_ic_dev *dev, unsigned int cmd, void *args);
int dwe_reset(struct dwe_ic_dev *dev);
int dwe_s_params(struct dwe_ic_dev *dev, struct dwe_hw_info *info);
int dwe_enable_bus(struct dwe_ic_dev *dev, bool enable);
int dwe_disable_irq(struct dwe_ic_dev *dev);
int dwe_clear_irq(struct dwe_ic_dev *dev);
int dwe_read_irq(struct dwe_ic_dev *dev, u32 *ret);
int dwe_start_dma_read(struct dwe_ic_dev *dev,
struct dwe_hw_info *info, u64 addr);
int dwe_set_buffer(struct dwe_ic_dev *dev, struct dwe_hw_info *info, u64 addr);
int dwe_set_lut(struct dwe_ic_dev *dev, u64 addr);
#ifdef __KERNEL__
int dwe_on_buf_update(struct dwe_ic_dev *dev);
irqreturn_t dwe_hw_isr(int irq, void *data);
void dwe_clear_interrupts(struct dwe_ic_dev *dev);
#endif
#endif /* _DWE_IOC_H_ */

183
vvcam/dwe/dwe_isr.c Executable file
View File

@@ -0,0 +1,183 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
# include "dwe_driver.h"
# include "video/vvbuf.h"
#endif
#include "dwe_ioctl.h"
#include "dwe_regs.h"
#if defined(__KERNEL__) && defined(ENABLE_IRQ)
static int update_dma_buffer(struct dwe_ic_dev *dev)
{
int no_dist_map_err, overflow_err;
int which;
u32 dewarp_ctrl;
dwe_enable_bus(dev, 0);
if (dev->dst)
return -EBUSY;
if (dev->src) {
vvbuf_ready(dev->sink_bctx, dev->src->pad, dev->src);
dev->src = NULL;
}
dev->src = vvbuf_try_dqbuf(dev->sink_bctx);
if (!dev->src) {
dev->error |= BUF_ERR_UNDERFLOW;
return -ENOMEM;
}
dev->error &= ~BUF_ERR_UNDERFLOW;
if (!dev->get_index) {
dev->error |= BUF_ERR_WRONGSTATE;
dev->src = NULL;
return -ENXIO;
}
dev->index = dev->get_index(dev, dev->src);
if (dev->index < 0 || dev->index >= MAX_DWE_NUM) {
dev->error |= BUF_ERR_WRONGSTATE;
dev->src = NULL;
return -ENXIO;
}
dev->error &= ~BUF_ERR_WRONGSTATE;
if (!(*dev->state[dev->index] & STATE_DRIVER_STARTED)) {
vvbuf_try_dqbuf_done(dev->sink_bctx, dev->src);
vvbuf_ready(dev->sink_bctx, dev->src->pad, dev->src);
dev->error |= BUF_ERR_UNDERFLOW;
dev->src = NULL;
return 0;
}
no_dist_map_err = BUF_ERR_NO_DIST_MAP0 << dev->index;
if (!dev->dist_map[dev->index]) {
dev->error |= no_dist_map_err;
dev->src = NULL;
return -ENOMEM;
}
dev->error &= ~no_dist_map_err;
overflow_err = BUF_ERR_OVERFLOW0 << dev->index;
dev->dst = vvbuf_try_dqbuf(dev->src_bctx[dev->index]);
if (!dev->dst) {
if (!(*dev->state[dev->index] & STATE_STREAM_STARTED)) {
vvbuf_try_dqbuf_done(dev->sink_bctx, dev->src);
vvbuf_ready(dev->sink_bctx, dev->src->pad, dev->src);
}
dev->error |= overflow_err;
dev->src = NULL;
return -ENOMEM;
}
dev->error &= ~overflow_err;
vvbuf_try_dqbuf_done(dev->sink_bctx, dev->src);
vvbuf_try_dqbuf_done(dev->src_bctx[dev->index], dev->dst);
which = dev->which[dev->index];
dwe_s_params(dev, &dev->info[dev->index][which]);
dwe_set_buffer(dev, &dev->info[dev->index][which], dev->dst->dma);
dwe_set_lut(dev, dev->dist_map[dev->index][which]);
dwe_start_dma_read(dev, &dev->info[dev->index][which], dev->src->dma);
dewarp_ctrl = dwe_read_reg(dev, DEWARP_CTRL);
dwe_write_reg(dev, DEWARP_CTRL, dewarp_ctrl | 2);
dwe_write_reg(dev, DEWARP_CTRL, dewarp_ctrl);
dwe_write_reg(dev, INTERRUPT_STATUS, INT_MSK_STATUS_MASK);
dwe_enable_bus(dev, 1);
return 0;
}
int dwe_on_buf_update(struct dwe_ic_dev *dev)
{
int rc = 0;
unsigned long flags;
if (dev) {
spin_lock_irqsave(&dev->irqlock, flags);
if (dev->error)
rc = update_dma_buffer(dev);
spin_unlock_irqrestore(&dev->irqlock, flags);
}
return rc;
}
void dwe_clear_interrupts(struct dwe_ic_dev *dev)
{
u32 status;
u32 clr;
status = dwe_read_reg(dev, INTERRUPT_STATUS);
clr = (status & 0xFF) << 24;
dwe_write_reg(dev, INTERRUPT_STATUS, clr);
}
irqreturn_t dwe_hw_isr(int irq, void *data)
{
struct dwe_ic_dev *dev = (struct dwe_ic_dev *)data;
u32 status;
u32 clr;
unsigned long flags;
if (!dev)
return IRQ_HANDLED;
status = dwe_read_reg(dev, INTERRUPT_STATUS);
if (status & INT_FRAME_DONE) {
clr = (status & 0xFF) << 24;
dwe_write_reg(dev, INTERRUPT_STATUS, clr);
spin_lock_irqsave(&dev->irqlock, flags);
if (dev->dst) {
vvbuf_ready(dev->src_bctx[dev->index],
dev->dst->pad, dev->dst);
dev->dst = NULL;
}
update_dma_buffer(dev);
spin_unlock_irqrestore(&dev->irqlock, flags);
}
return IRQ_HANDLED;
}
#endif

104
vvcam/dwe/dwe_regs.h Executable file
View File

@@ -0,0 +1,104 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _DWE_REGS_H_
#define _DWE_REGS_H_
#define REGISTER_NUM 100
#define DEWARP_REGISTER_BASE_ADDR 0x00000000
#define DEWARP_CTRL 0x00000004
#define SWAP_CONTROL 0x00000058
#define VERTICAL_SPLIT_LINE 0x0000005C
#define HORIZON_SPLIT_LINE 0x00000060
#define SCALE_FACTOR 0x00000064
#define ROI_START 0x00000068
#define BOUNDRY_PIXEL 0x0000006C
#define INTERRUPT_STATUS 0x00000070
#define INT_FRAME_DONE (1 << 0)
#define INT_ERR_STATUS_MASK 0x000000FE
#define INT_ERR_STATUS_SHIFT 1
#define INT_MSK_STATUS_MASK 0x0000FF00
#define INT_MSK_STATUS_SHIFT 8
#define INT_FRAME_BUSY 0x00010000
#define INT_CLR_MASK 0xFF000000
#define BUS_CTRL 0x00000074
#define DEWRAP_BUS_CTRL_ENABLE_MASK (1 << 31)
#define BUS_CTRL1 0x00000078
#define BUS_TIME_OUT_CYCLE 0x0000007C
#define MAP_LUT_ADDR 0x00000008
#define MAP_LUT_SIZE 0x0000000C
#define SRC_IMG_Y_BASE 0x00000010
#define SRC_IMG_UV_BASE 0x00000014
#define SRC_IMG_SIZE 0x00000018
#define SRC_IMG_STRIDE 0x0000001C
#define MAP_LUT_ADDR2 0x00000020
#define MAP_LUT_SIZE2 0x00000024
#define SRC_IMG_Y_BASE2 0x00000028
#define SRC_IMG_UV_BASE2 0x0000002C
#define SRC_IMG_SIZE2 0x00000030
#define SRC_IMG_STRIDE2 0x00000034
#define DST_IMG_Y_BASE 0x00000038
#define DST_IMG_UV_BASE 0x0000003C
#define DST_IMG_SIZE 0x00000040
#define DST_IMG_STRIDE 0x00000044
#define DST_IMG_Y_BASE2 0x00000048
#define DST_IMG_UV_BASE2 0x0000004C
#define DST_IMG_SIZE2 0x00000050
#define DST_IMG_STRIDE2 0x00000054
#define DST_IMG_Y_SIZE1 0x00000080
#define DST_IMG_UV_SIZE1 0x00000084
#define DST_IMG_Y_SIZE2 0x00000088
#define DST_IMG_UV_SIZE2 0x0000008C
#endif /* _DWE_REGS_H_ */

View File

@@ -0,0 +1,110 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _CAMERA_DEVICE_BUF_DEFS_COMMON_H_
#define _CAMERA_DEVICE_BUF_DEFS_COMMON_H_
enum {
CAMERA_PIX_FMT_YUV422SP = 0,
CAMERA_PIX_FMT_YUV422I,
CAMERA_PIX_FMT_YUV420SP,
CAMERA_PIX_FMT_YUV444,
CAMERA_PIX_FMT_RGB888,
CAMERA_PIX_FMT_RGB888P,
};
typedef enum _ISPCORE_BUFIO_ID_ {
ISPCORE_BUFIO_MP = 0,
ISPCORE_BUFIO_SP1 = 1,
ISPCORE_BUFIO_SP2 = 2,
ISPCORE_BUFIO_RDI = 3, //RAW dump interface
ISPCORE_BUFIO_META = 4, //meta sw delivery port
ISPCORE_BUFIO_WRITEMAX = 5,
ISPCORE_BUFIO_READ = 6,
ISPCORE_BUFIO_MAX = 7,
} ISPCORE_BUFIO_ID;
typedef struct __BufIdentity__ {
uint64_t address_usr; //address in V4l2 application space
uint64_t address_daemon; //address in native stack space
uint64_t address_kernel; //address in kernel space
uint32_t address_reg; //address set to ispcore register
uint32_t buffer_idx; //buffer index
uint32_t buff_size; //biffer size
uint32_t filled;
void *ctx; //memory handle
int width;
int height;
int format;
} BufIdentity;
typedef struct ispcore_meta_kernel_s {
unsigned int data_kernel;
} ispcore_meta_kernel_t;
typedef struct ispcore_meta_kernel_dma_s {
unsigned int data_kernel_dma;
} ispcore_meta_kernel_dma_t;
typedef struct ispcore_meta_user_s {
unsigned int data_user;
} ispcore_meta_user_t;
typedef struct ispcore_meta_s {
ispcore_meta_kernel_t kernel_meta;
ispcore_meta_kernel_dma_t kernel_meta_dma;
ispcore_meta_user_t user_meta;
} ispcore_meta_t;
#endif // _CAMERA_DEVICE_BUF_DEFS_COMMON_H_

1105
vvcam/isp/ic_dev.h Executable file

File diff suppressed because it is too large Load Diff

6
vvcam/isp/insmod.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/bash
modprobe vivid
rmmod vivid
rmmod viv_isp_driver.ko
insmod viv_isp_driver.ko

455
vvcam/isp/isp_3dnr.c Executable file
View File

@@ -0,0 +1,455 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#endif
#include "isp_ioctl.h"
#include "mrv_all_bits.h"
#include "isp_types.h"
#ifdef ISP_3DNR
extern MrvAllRegister_t *all_regs;
static void dnr3_hw_init(struct isp_ic_dev *dev)
{
struct isp_3dnr_context *dnr3 = &dev->dnr3;
u32 regVal = 0;
int i, pos;
/* spacial */
u32 update_spacial = 900;
u32 strength_curve_spacial = 64;
u32 thr_edge_v_inv = 1024;
u32 thr_edge_h_inv = 1024;
u32 thr_range_s_inv = 1024;
/* temperal */
u32 update_temperal = 1020;
u32 strength_curve_temperal = 64;
u32 range_t_h = 2;
u32 range_t_v = 2;
u32 thr_range_t_inv = 41943;
u32 thr_motion_inv = 1024;
u32 range_d = 1;
u32 thr_delta_h_inv = 1023;
u32 thr_delta_v_inv = 1023;
u32 thr_delta_t_inv = 1023;
u32 strength = dnr3->strength;
strength = MIN(MAX(strength, 0), 128);
if (dnr3->init) { //for 3dnr init
u32 isp_denoise3d_ctrl = isp_read_reg(dev, REG_ADDR(isp_denoise3d_ctrl));
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_HORIZONTAL_EN,
dnr3->enable_h);
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_VERTICAL_EN,
dnr3->enable_v);
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_TEMPERAL_EN,
dnr3->enable_temperal);
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_DILATE_EN,
dnr3->enable_dilate);
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_ENABLE, dnr3->enable);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_ctrl), isp_denoise3d_ctrl);
}
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_STRENGTH_CURVE_SPACIAL,
strength_curve_spacial);
REG_SET_SLICE(regVal, DENOISE3D_THR_EDGE_H_INV, thr_edge_h_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_edge_h), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_STRENGTH_CURVE_TEMPERAL,
strength_curve_temperal);
REG_SET_SLICE(regVal, DENOISE3D_THR_EDGE_V_INV, thr_edge_v_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_edge_v), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_RANGE_S_INV, thr_range_s_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_range_s), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_H, range_t_h);
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_V, range_t_v);
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_INV, thr_range_t_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_range_t), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_RANGE_D, range_d);
REG_SET_SLICE(regVal, DENOISE3D_MOTION_INV, thr_motion_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_motion), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_DELTA_H_INV, thr_delta_h_inv);
REG_SET_SLICE(regVal, DENOISE3D_DELTA_V_INV, thr_delta_v_inv);
REG_SET_SLICE(regVal, DENOISE3D_DELTA_T_INV, thr_delta_t_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_delta_inv), regVal);
/* spacial */
for (i = 0; i < 6; i++) {
regVal = 0;
pos = i * 3;
if (i < 5) {
REG_SET_SLICE(regVal, DENOISE3D_SPACIAL_CURVE0,
dnr3->spacial_curve[pos + 0]);
REG_SET_SLICE(regVal, DENOISE3D_SPACIAL_CURVE1,
dnr3->spacial_curve[pos + 1]);
REG_SET_SLICE(regVal, DENOISE3D_SPACIAL_CURVE2,
dnr3->spacial_curve[pos + 2]);
} else {
REG_SET_SLICE(regVal, DENOISE3D_SPACIAL_CURVE1,
dnr3->spacial_curve[pos + 0]);
REG_SET_SLICE(regVal, DENOISE3D_SPACIAL_CURVE2,
dnr3->spacial_curve[pos + 1]);
}
isp_write_reg(dev, REG_ADDR(isp_denoise3d_curve_s[i]), regVal);
regVal = 0;
if (i < 5) {
REG_SET_SLICE(regVal, DENOISE3D_TEMPERAL_CURVE0,
dnr3->temperal_curve[pos + 0]);
REG_SET_SLICE(regVal, DENOISE3D_TEMPERAL_CURVE1,
dnr3->temperal_curve[pos + 1]);
REG_SET_SLICE(regVal, DENOISE3D_TEMPERAL_CURVE2,
dnr3->temperal_curve[pos + 2]);
} else {
REG_SET_SLICE(regVal, DENOISE3D_TEMPERAL_CURVE1,
dnr3->temperal_curve[pos + 0]);
REG_SET_SLICE(regVal, DENOISE3D_TEMPERAL_CURVE2,
dnr3->temperal_curve[pos + 1]);
}
isp_write_reg(dev, REG_ADDR(isp_denoise3d_curve_t[i]), regVal);
}
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_UPDATE_SPACIAL, update_spacial);
REG_SET_SLICE(regVal, DENOISE3D_UPDATE_TEMPERAL, update_temperal);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_strength), regVal);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_dummy_hblank), 0x80);
}
int isp_u_3dnr_strength(struct isp_ic_dev *dev)
{
#ifndef ISP_3DNR
//pr_err("Not supported 3dnr\n");
return -1;
#else
struct isp_3dnr_context *dnr3 = &dev->dnr3;
u32 isp_ctrl;
u32 isp_denoise3d_strength;
isp_denoise3d_strength = isp_read_reg(dev, REG_ADDR(isp_denoise3d_strength));
REG_SET_SLICE(isp_denoise3d_strength, DENOISE3D_STRENGTH, dnr3->strength);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_strength), isp_denoise3d_strength);
isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
return 0;
#endif
}
int isp_s_3dnr(struct isp_ic_dev *dev)
{
#ifndef ISP_3DNR
//pr_err("Not supported 3dnr\n");
return -1;
#else
u32 isp_denoise3d_ctrl;
struct isp_3dnr_context *dnr3 = &dev->dnr3;
u32 isp_denoise3d_strength, isp_denoise3d_motion, isp_denoise3d_delta_inv;
pr_info("enter %s\n", __func__);
if (dnr3->update_bin) {
dnr3_hw_init(dev);
}
isp_denoise3d_motion =
isp_read_reg(dev, REG_ADDR(isp_denoise3d_motion));
REG_SET_SLICE(isp_denoise3d_motion, DENOISE3D_MOTION_INV, dnr3->motion_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_motion),
isp_denoise3d_motion);
isp_denoise3d_delta_inv =
isp_read_reg(dev, REG_ADDR(isp_denoise3d_delta_inv));
REG_SET_SLICE(isp_denoise3d_delta_inv, DENOISE3D_DELTA_T_INV, dnr3->delta_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_delta_inv),
isp_denoise3d_delta_inv);
isp_denoise3d_strength = isp_read_reg(dev, REG_ADDR(isp_denoise3d_strength));
#ifndef NR200
if (!dnr3->enable) {
REG_SET_SLICE(isp_denoise3d_strength, DENOISE3D_STRENGTH, 0);
} else {
REG_SET_SLICE(isp_denoise3d_strength, DENOISE3D_STRENGTH, dnr3->strength);
isp_denoise3d_ctrl = isp_read_reg(dev, REG_ADDR(isp_denoise3d_ctrl));
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_ENABLE, dnr3->enable);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_ctrl), isp_denoise3d_ctrl);
}
isp_write_reg(dev, REG_ADDR(isp_denoise3d_strength), isp_denoise3d_strength);
#else
isp_denoise3d_ctrl = isp_read_reg(dev, REG_ADDR(isp_denoise3d_ctrl));
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_ENABLE, dnr3->enable);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_ctrl), isp_denoise3d_ctrl);
u32 isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
#endif
return 0;
#endif
}
int isp_s_3dnr_motion(struct isp_ic_dev *dev)
{
#ifndef ISP_3DNR
pr_err("Not supported 3dnr\n");
return -1;
#else
struct isp_3dnr_context *dnr3 = &dev->dnr3;
u32 isp_denoise3d_motion;
u32 isp_ctrl;
isp_denoise3d_motion =
isp_read_reg(dev, REG_ADDR(isp_denoise3d_motion));
REG_SET_SLICE(isp_denoise3d_motion, DENOISE3D_MOTION_INV, dnr3->motion_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_motion),
isp_denoise3d_motion);
isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
#endif
return 0;
}
int isp_s_3dnr_delta(struct isp_ic_dev *dev)
{
#ifndef ISP_3DNR
pr_err("Not supported 3dnr\n");
return -1;
#else
struct isp_3dnr_context *dnr3 = &dev->dnr3;
u32 isp_denoise3d_delta_inv;
u32 isp_ctrl;
isp_denoise3d_delta_inv =
isp_read_reg(dev, REG_ADDR(isp_denoise3d_delta_inv));
REG_SET_SLICE(isp_denoise3d_delta_inv, DENOISE3D_DELTA_T_INV, dnr3->delta_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_delta_inv),
isp_denoise3d_delta_inv);
isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
#endif
return 0;
}
int isp_u_3dnr(struct isp_ic_dev *dev, struct isp_3dnr_update *dnr3_update)
{
#ifndef ISP_3DNR
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
u32 regVal = 0;
pr_info("enter %s\n", __func__);
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_strength));
REG_SET_SLICE(regVal, DENOISE3D_STRENGTH, dev->dnr3.strength);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_strength), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_edge_h));
REG_SET_SLICE(regVal, DENOISE3D_THR_EDGE_H_INV,
dnr3_update->thr_edge_h_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_edge_h), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_edge_v));
REG_SET_SLICE(regVal, DENOISE3D_THR_EDGE_V_INV,
dnr3_update->thr_edge_v_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_edge_v), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_range_s));
REG_SET_SLICE(regVal, DENOISE3D_RANGE_S_INV,
dnr3_update->thr_range_s_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_range_s), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_range_t));
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_H, dnr3_update->range_t_h);
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_V, dnr3_update->range_t_v);
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_INV,
dnr3_update->thr_range_t_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_range_t), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_motion));
REG_SET_SLICE(regVal, DENOISE3D_RANGE_D, dnr3_update->range_d);
REG_SET_SLICE(regVal, DENOISE3D_MOTION_INV,
dnr3_update->thr_motion_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_motion), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_delta_inv));
REG_SET_SLICE(regVal, DENOISE3D_DELTA_H_INV,
dnr3_update->thr_delta_h_inv);
REG_SET_SLICE(regVal, DENOISE3D_DELTA_V_INV,
dnr3_update->thr_delta_v_inv);
REG_SET_SLICE(regVal, DENOISE3D_DELTA_T_INV,
dnr3_update->thr_delta_t_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_delta_inv), regVal);
#ifdef NR200
u32 isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
#endif
return 0;
#endif
}
int isp_g_3dnr(struct isp_ic_dev *dev, u32 * avg)
{
if (!dev || !avg) {
return -EINVAL;
}
*avg = isp_read_reg(dev, REG_ADDR(isp_denoise3d_average));
return 0;
}
int isp_r_3dnr(struct isp_ic_dev *dev)
{
#ifndef ISP_3DNR
return -1;
#else
u32 in_width, in_height;
u32 size, lval;
u32 miv2_sp2_bus_id;
u32 miv2_sp2_fmt;
u32 miv2_ctrl = isp_read_reg(dev, REG_ADDR(miv2_ctrl));
u32 miv2_imsc = isp_read_reg(dev, REG_ADDR(miv2_imsc));
u32 miv2_sp2_ctrl = isp_read_reg(dev, REG_ADDR(miv2_sp2_ctrl));
//SP2_RAW_PATH_ENABLE is shadow bit, need set SP2_MI_CFG_UPD to update to shadow.
//So here config before set SP2_MI_CFG_UPD
REG_SET_SLICE(miv2_ctrl, SP2_RAW_RDMA_PATH_ENABLE, 1);
REG_SET_SLICE(miv2_ctrl, SP2_RAW_PATH_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(miv2_ctrl), miv2_ctrl);
#ifndef NR200
in_width = isp_read_reg(dev, REG_ADDR(isp_acq_h_size));
in_height = isp_read_reg(dev, REG_ADDR(isp_acq_v_size));
#else
in_width = isp_read_reg(dev, REG_ADDR(isp_out_h_size));
in_height = isp_read_reg(dev, REG_ADDR(isp_out_v_size));
#endif
lval = (in_width * 12 + 127)/ 128;
lval <<= 4;
size = in_height * lval; //raw12 unaligned
//write reference frame config
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_base_ad_init), dev->dnr3.pa);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_size_init), size);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_offs_cnt_init), 0);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_llength), lval);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_pic_width), in_width);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_pic_height), in_height);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_pic_size), size);
miv2_sp2_bus_id = isp_read_reg(dev, REG_ADDR(miv2_sp2_bus_id));
REG_SET_SLICE(miv2_sp2_bus_id, SP2_WR_ID_EN, 1);
REG_SET_SLICE(miv2_sp2_bus_id, SP2_RD_ID_EN, 1);
REG_SET_SLICE(miv2_sp2_bus_id, SP2_RD_BURST_LEN, 2); //sp2 rd burst lenghth 16
REG_SET_SLICE(miv2_sp2_bus_id, SP2_BUS_SW_EN, 1);
isp_write_reg(dev, REG_ADDR(miv2_sp2_bus_id), miv2_sp2_bus_id);
miv2_sp2_fmt = isp_read_reg(dev, REG_ADDR(miv2_sp2_fmt));
REG_SET_SLICE(miv2_sp2_fmt, SP2_WR_RAW_BIT, 2); //raw12
REG_SET_SLICE(miv2_sp2_fmt, SP2_WR_RAW_ALIGNED, 0); //unaligned
REG_SET_SLICE(miv2_sp2_fmt, SP2_RD_RAW_BIT, 2); //raw12
REG_SET_SLICE(miv2_sp2_fmt, SP2_RD_RAW_ALIGNED, 0); //unaligned
isp_write_reg(dev, REG_ADDR(miv2_sp2_fmt), miv2_sp2_fmt);
//read reference frame config
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_start_ad), dev->dnr3.pa);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_width), in_width);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_llength), lval);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_lval), lval);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_size), size);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_RD_RAW_CFG_UPDATE, 1);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_RD_RAW_AUTO_UPDATE, 1);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_MI_CFG_UPD, 1);
/* we successfully programmed a buffer to marvin, so we need
* to enable updateing of base and offset registers */
miv2_sp2_ctrl |= (SP2_INIT_BASE_EN_MASK | SP2_INIT_OFFSET_EN_MASK);
isp_write_reg(dev, REG_ADDR(miv2_sp2_ctrl), miv2_sp2_ctrl);
miv2_imsc |= SP2_DMA_RAW_READY_MASK;
isp_write_reg(dev, REG_ADDR(miv2_imsc), miv2_imsc);
return 0;
#endif
}
#endif

433
vvcam/isp/isp_3dnr2.c Executable file
View File

@@ -0,0 +1,433 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#endif
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
#ifdef ISP_3DNR_V2
extern MrvAllRegister_t *all_regs;
static void dnr3_hw_init(struct isp_ic_dev *dev)
{
struct isp_3dnr_context *dnr3 = &dev->dnr3;
u32 regVal = 0;
int i, pos;
/* spacial */
u32 update_spacial = 900;
u32 strength_curve_spacial = 64;
u32 thr_edge_v_inv = 1024;
u32 thr_edge_h_inv = 1024;
u32 thr_range_s_inv = 1024;
/* temperal */
u32 update_temperal = 1020;
u32 strength_curve_temperal = 64;
u32 range_t_h = 1;
u32 range_t_v = 1;
u32 thr_range_t_inv = 1024;
u32 thr_motion_inv = 1024;
u32 range_d = 1;
u32 thr_delta_h_inv = 1023;
u32 thr_delta_v_inv = 1023;
u32 thr_delta_t_inv = 1023;
u32 strength = dnr3->strength;
strength = MIN(MAX(strength, 0), 128);
if (dnr3->init) { //for 3dnr init
u32 isp_denoise3d_ctrl = isp_read_reg(dev, REG_ADDR(isp_denoise3d_ctrl));
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_READ_REF_EN, 1);
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_WRITE_REF_EN, 1);
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_HORIZONTAL_EN,
dnr3->enable_h);
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_VERTICAL_EN,
dnr3->enable_v);
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_TEMPERAL_EN,
dnr3->enable_temperal);
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_DILATE_EN,
dnr3->enable_dilate);
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_ENABLE, dnr3->enable);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_ctrl), isp_denoise3d_ctrl);
}
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_STRENGTH_CURVE_SPACIAL,
strength_curve_spacial);
REG_SET_SLICE(regVal, DENOISE3D_THR_EDGE_H_INV, thr_edge_h_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_edge_h), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_STRENGTH_CURVE_TEMPERAL,
strength_curve_temperal);
REG_SET_SLICE(regVal, DENOISE3D_THR_EDGE_V_INV, thr_edge_v_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_edge_v), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_RANGE_S_INV, thr_range_s_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_range_s), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_H, range_t_h);
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_V, range_t_v);
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_INV, thr_range_t_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_range_t), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_RANGE_D, range_d);
REG_SET_SLICE(regVal, DENOISE3D_MOTION_INV, thr_motion_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_motion), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_DELTA_H_INV, thr_delta_h_inv);
REG_SET_SLICE(regVal, DENOISE3D_DELTA_V_INV, thr_delta_v_inv);
REG_SET_SLICE(regVal, DENOISE3D_DELTA_T_INV, thr_delta_t_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_delta_inv), regVal);
/* spacial */
for (i = 0; i < 6; i++) {
regVal = 0;
pos = i * 3;
if (i < 5) {
REG_SET_SLICE(regVal, DENOISE3D_SPACIAL_CURVE0,
dnr3->spacial_curve[pos + 0]);
REG_SET_SLICE(regVal, DENOISE3D_SPACIAL_CURVE1,
dnr3->spacial_curve[pos + 1]);
REG_SET_SLICE(regVal, DENOISE3D_SPACIAL_CURVE2,
dnr3->spacial_curve[pos + 2]);
} else {
REG_SET_SLICE(regVal, DENOISE3D_SPACIAL_CURVE1,
dnr3->spacial_curve[pos + 0]);
REG_SET_SLICE(regVal, DENOISE3D_SPACIAL_CURVE2,
dnr3->spacial_curve[pos + 1]);
}
isp_write_reg(dev, REG_ADDR(isp_denoise3d_curve_s[i]), regVal);
regVal = 0;
if (i < 5) {
REG_SET_SLICE(regVal, DENOISE3D_TEMPERAL_CURVE0,
dnr3->temperal_curve[pos + 0]);
REG_SET_SLICE(regVal, DENOISE3D_TEMPERAL_CURVE1,
dnr3->temperal_curve[pos + 1]);
REG_SET_SLICE(regVal, DENOISE3D_TEMPERAL_CURVE2,
dnr3->temperal_curve[pos + 2]);
} else {
REG_SET_SLICE(regVal, DENOISE3D_TEMPERAL_CURVE1,
dnr3->temperal_curve[pos + 0]);
REG_SET_SLICE(regVal, DENOISE3D_TEMPERAL_CURVE2,
dnr3->temperal_curve[pos + 1]);
}
isp_write_reg(dev, REG_ADDR(isp_denoise3d_curve_t[i]), regVal);
}
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_UPDATE_SPACIAL, update_spacial);
REG_SET_SLICE(regVal, DENOISE3D_UPDATE_TEMPERAL, update_temperal);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_strength), regVal);
}
int isp_s_3dnr_cmp(struct isp_ic_dev *dev) {
struct isp_3dnr_compress_context *compress = &dev->dnr3.compress;
u32 isp_denoise3d_weight1 = 0; // isp_read_reg(dev, REG_ADDR(isp_denoise3d_weight1));
u32 isp_denoise3d_weight2 = 0; // isp_read_reg(dev, REG_ADDR(isp_denoise3d_weight2));
int i = 0;
for (i = 0; i < 4; i++) {
isp_denoise3d_weight1 |= (compress->weight_down[i] & DENOISE3D_WEIGHT_MASK) << (3 - i) * 4;
}
REG_SET_SLICE(isp_denoise3d_weight1, DENOISE3D_WEIGHT_UP_Y0, compress->weight_up_y[0]);
REG_SET_SLICE(isp_denoise3d_weight1, DENOISE3D_WEIGHT_UP_Y1, compress->weight_up_y[1]);
for (i = 0; i < 8; i++) {
isp_denoise3d_weight2 |= (compress->weight_up[i] & DENOISE3D_WEIGHT_MASK) << (7 - i) * 4;
}
isp_write_reg(dev, REG_ADDR(isp_denoise3d_weight1), isp_denoise3d_weight1);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_weight2), isp_denoise3d_weight2);
return 0;
}
int isp_s_3dnr(struct isp_ic_dev *dev)
{
struct isp_3dnr_context *dnr3 = &dev->dnr3;
u32 isp_denoise3d_strength, isp_denoise3d_motion, isp_denoise3d_delta_inv;
u32 isp_denoise3d_ctrl;
pr_info("enter %s\n", __func__);
if (dnr3->update_bin) {
dnr3_hw_init(dev);
}
isp_denoise3d_strength = isp_read_reg(dev, REG_ADDR(isp_denoise3d_strength));
if (!dnr3->enable) {
REG_SET_SLICE(isp_denoise3d_strength, DENOISE3D_STRENGTH, 0);
} else {
REG_SET_SLICE(isp_denoise3d_strength, DENOISE3D_STRENGTH, dnr3->strength);
}
isp_write_reg(dev, REG_ADDR(isp_denoise3d_strength),
isp_denoise3d_strength);
isp_denoise3d_motion =
isp_read_reg(dev, REG_ADDR(isp_denoise3d_motion));
REG_SET_SLICE(isp_denoise3d_motion, DENOISE3D_MOTION_INV, dnr3->motion_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_motion),
isp_denoise3d_motion);
isp_denoise3d_delta_inv =
isp_read_reg(dev, REG_ADDR(isp_denoise3d_delta_inv));
REG_SET_SLICE(isp_denoise3d_delta_inv, DENOISE3D_DELTA_T_INV, dnr3->delta_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_delta_inv),
isp_denoise3d_delta_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_dummy_hblank), 0x80);
isp_denoise3d_ctrl = isp_read_reg(dev, REG_ADDR(isp_denoise3d_ctrl));
if (dnr3->enable) {
isp_s_3dnr_cmp(dev);
REG_SET_SLICE(isp_denoise3d_ctrl, DENOISE3D_ENABLE, 1);
}
isp_write_reg(dev, REG_ADDR(isp_denoise3d_ctrl), isp_denoise3d_ctrl);
return 0;
}
int isp_s_3dnr_motion(struct isp_ic_dev *dev)
{
struct isp_3dnr_context *dnr3 = &dev->dnr3;
u32 isp_denoise3d_motion;
u32 isp_ctrl;
isp_denoise3d_motion =
isp_read_reg(dev, REG_ADDR(isp_denoise3d_motion));
REG_SET_SLICE(isp_denoise3d_motion, DENOISE3D_MOTION_INV, dnr3->motion_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_motion),
isp_denoise3d_motion);
isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
return 0;
}
int isp_s_3dnr_delta(struct isp_ic_dev *dev)
{
struct isp_3dnr_context *dnr3 = &dev->dnr3;
u32 isp_denoise3d_delta_inv;
u32 isp_ctrl;
isp_denoise3d_delta_inv =
isp_read_reg(dev, REG_ADDR(isp_denoise3d_delta_inv));
REG_SET_SLICE(isp_denoise3d_delta_inv, DENOISE3D_DELTA_T_INV, dnr3->delta_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_delta_inv),
isp_denoise3d_delta_inv);
isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
return 0;
}
int isp_u_3dnr(struct isp_ic_dev *dev, struct isp_3dnr_update *dnr3_update)
{
u32 regVal = 0;
pr_info("enter %s\n", __func__);
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_strength));
REG_SET_SLICE(regVal, DENOISE3D_STRENGTH, dev->dnr3.strength);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_strength), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_edge_h));
REG_SET_SLICE(regVal, DENOISE3D_THR_EDGE_H_INV,
dnr3_update->thr_edge_h_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_edge_h), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_edge_v));
REG_SET_SLICE(regVal, DENOISE3D_THR_EDGE_V_INV,
dnr3_update->thr_edge_v_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_edge_v), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_range_s));
REG_SET_SLICE(regVal, DENOISE3D_RANGE_S_INV,
dnr3_update->thr_range_s_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_range_s), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_range_t));
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_H, dnr3_update->range_t_h);
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_V, dnr3_update->range_t_v);
REG_SET_SLICE(regVal, DENOISE3D_RANGE_T_INV,
dnr3_update->thr_range_t_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_range_t), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_motion));
REG_SET_SLICE(regVal, DENOISE3D_RANGE_D, dnr3_update->range_d);
REG_SET_SLICE(regVal, DENOISE3D_MOTION_INV,
dnr3_update->thr_motion_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_motion), regVal);
regVal = 0;
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d_delta_inv));
REG_SET_SLICE(regVal, DENOISE3D_DELTA_H_INV,
dnr3_update->thr_delta_h_inv);
REG_SET_SLICE(regVal, DENOISE3D_DELTA_V_INV,
dnr3_update->thr_delta_v_inv);
REG_SET_SLICE(regVal, DENOISE3D_DELTA_T_INV,
dnr3_update->thr_delta_t_inv);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_delta_inv), regVal);
return 0;
}
int isp_g_3dnr(struct isp_ic_dev *dev, u32 * avg)
{
if (!dev || !avg) {
return -EINVAL;
}
*avg = isp_read_reg(dev, REG_ADDR(isp_denoise3d_average));
return 0;
}
int isp_u_3dnr_strength(struct isp_ic_dev *dev)
{
uint32_t isp_denoise3d_strength;
isp_denoise3d_strength = isp_read_reg(dev, REG_ADDR(isp_denoise3d_strength));
REG_SET_SLICE(isp_denoise3d_strength, DENOISE3D_STRENGTH, dev->dnr3.strength);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_strength), isp_denoise3d_strength);
return 0;
}
int isp_r_3dnr(struct isp_ic_dev *dev)
{
#ifndef ISP_3DNR_V2_V1
return -1;
#else
u32 in_width, in_height;
u32 size, lval;
u32 miv2_sp2_bus_id;
u32 miv2_sp2_fmt;
u32 miv2_ctrl = isp_read_reg(dev, REG_ADDR(miv2_ctrl));
u32 miv2_imsc = isp_read_reg(dev, REG_ADDR(miv2_imsc));
u32 miv2_sp2_ctrl = isp_read_reg(dev, REG_ADDR(miv2_sp2_ctrl));
//SP2_RAW_PATH_ENABLE is shadow bit, need set SP2_MI_CFG_UPD to update to shadow.
//So here config before set SP2_MI_CFG_UPD
REG_SET_SLICE(miv2_ctrl, SP2_RAW_RDMA_PATH_ENABLE, 1);
REG_SET_SLICE(miv2_ctrl, SP2_RAW_PATH_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(miv2_ctrl), miv2_ctrl);
in_width = isp_read_reg(dev, REG_ADDR(isp_out_h_size));
in_height = isp_read_reg(dev, REG_ADDR(isp_out_v_size));
lval = (in_width * 12 + 127)/ 128;
lval <<= 4;
size = in_height * lval; //raw12 unaligned
//write reference frame config
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_base_ad_init), dev->dnr3.pa);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_size_init), size);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_offs_cnt_init), 0);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_llength), lval);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_pic_width), in_width);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_pic_height), in_height);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_pic_size), size);
miv2_sp2_bus_id = isp_read_reg(dev, REG_ADDR(miv2_sp2_bus_id));
REG_SET_SLICE(miv2_sp2_bus_id, SP2_WR_ID_EN, 1);
REG_SET_SLICE(miv2_sp2_bus_id, SP2_RD_ID_EN, 1);
REG_SET_SLICE(miv2_sp2_bus_id, SP2_RD_BURST_LEN, 2); //sp2 rd burst lenghth 16
REG_SET_SLICE(miv2_sp2_bus_id, SP2_BUS_SW_EN, 1);
isp_write_reg(dev, REG_ADDR(miv2_sp2_bus_id), miv2_sp2_bus_id);
miv2_sp2_fmt = isp_read_reg(dev, REG_ADDR(miv2_sp2_fmt));
REG_SET_SLICE(miv2_sp2_fmt, SP2_WR_RAW_BIT, 2); //raw12
REG_SET_SLICE(miv2_sp2_fmt, SP2_WR_RAW_ALIGNED, 0); //unaligned
REG_SET_SLICE(miv2_sp2_fmt, SP2_RD_RAW_BIT, 2); //raw12
REG_SET_SLICE(miv2_sp2_fmt, SP2_RD_RAW_ALIGNED, 0); //unaligned
isp_write_reg(dev, REG_ADDR(miv2_sp2_fmt), miv2_sp2_fmt);
//read reference frame config
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_start_ad), dev->dnr3.pa);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_width), in_width);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_llength), lval);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_lval), lval);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_size), size);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_RD_RAW_CFG_UPDATE, 1);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_RD_RAW_AUTO_UPDATE, 1);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_MI_CFG_UPD, 1);
/* we successfully programmed a buffer to marvin, so we need
* to enable updateing of base and offset registers */
miv2_sp2_ctrl |= (SP2_INIT_BASE_EN_MASK | SP2_INIT_OFFSET_EN_MASK);
isp_write_reg(dev, REG_ADDR(miv2_sp2_ctrl), miv2_sp2_ctrl);
miv2_imsc |= SP2_DMA_RAW_READY_MASK;
isp_write_reg(dev, REG_ADDR(miv2_imsc), miv2_imsc);
return 0;
#endif
}
#endif

155
vvcam/isp/isp_compand.c Executable file
View File

@@ -0,0 +1,155 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#endif
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
extern MrvAllRegister_t *all_regs;
int isp_s_comp(struct isp_ic_dev *dev)
{
#ifndef ISP_COMPAND
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
struct isp_comp_context *comp = &dev->comp;
int ri, valr;
uint32_t x_data;
uint32_t y_data;
u32 isp_compand_ctrl = isp_read_reg(dev, REG_ADDR(isp_compand_ctrl));
/*pr_debug("enter %s\n", __func__);*/
if (comp->bls.enable) {
isp_write_reg(dev, REG_ADDR(isp_compand_bls_a_fixed), comp->bls.a << (20 - comp->bls.bit_width));
isp_write_reg(dev, REG_ADDR(isp_compand_bls_b_fixed), comp->bls.b << (20 - comp->bls.bit_width));
isp_write_reg(dev, REG_ADDR(isp_compand_bls_c_fixed), comp->bls.c << (20 - comp->bls.bit_width));
isp_write_reg(dev, REG_ADDR(isp_compand_bls_d_fixed), comp->bls.d << (20 - comp->bls.bit_width));
}
if (!comp->enable) {
REG_SET_SLICE(isp_compand_ctrl, COMPAND_CTRL_BLS_ENABLE, 0);
REG_SET_SLICE(isp_compand_ctrl, COMPAND_CTRL_COMPRESS_ENABLE, 0);
REG_SET_SLICE(isp_compand_ctrl, COMPAND_CTRL_EXPAND_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_compand_ctrl), isp_compand_ctrl);
return 0;
}
if (comp->expand.enable && comp->expand.update_curve) {
for (ri = 0; ri < 10; ri++) {
valr = (comp->expand.px[ri * 6 + 0] + (20-comp->expand.in_bit)) |
((comp->expand.px[ri * 6 + 1] + (20-comp->expand.in_bit)) << 5) |
((comp->expand.px[ri * 6 + 2] + (20-comp->expand.in_bit)) << 10) |
((comp->expand.px[ri * 6 + 3] + (20-comp->expand.in_bit)) << 15) |
((comp->expand.px[ri * 6 + 4] + (20-comp->expand.in_bit)) << 20) |
((comp->expand.px[ri * 6 + 5] + (20-comp->expand.in_bit)) << 25);
isp_write_reg(dev, REG_ADDR(isp_compand_expand_px_0) + ri * 4, valr);
}
valr = ( comp->expand.px[60] + (20-comp->expand.in_bit)) |
((comp->expand.px[61] + (20-comp->expand.in_bit)) << 5) |
((comp->expand.px[62] + (20-comp->expand.in_bit)) << 10) |
((comp->expand.px[63] + (20-comp->expand.in_bit)) << 15);
isp_write_reg(dev, REG_ADDR(isp_compand_expand_px_10), valr);
isp_write_reg(dev, REG_ADDR(isp_compand_expand_x_addr), 0x0);
for (ri = 0; ri < 63; ri++) {
x_data = (comp->expand.x_data[ri] << (20 - comp->expand.in_bit));
isp_write_reg(dev, REG_ADDR(isp_compand_expand_x_write_data), x_data);
}
isp_write_reg(dev, REG_ADDR(isp_compand_expand_y_addr), 0x0);
for (ri = 0; ri < 64; ri++) {
y_data = (comp->expand.y_data[ri] << (20 - comp->expand.out_bit));
isp_write_reg(dev, REG_ADDR(isp_compand_expand_y_write_data), y_data);
}
}
if (comp->compress.enable && comp->compress.update_curve) {
for (ri = 0; ri < 10; ri++) {
valr = comp->compress.px[ri * 6 + 0] |
(comp->compress.px[ri * 6 + 1] << 5) |
(comp->compress.px[ri * 6 + 2] << 10) |
(comp->compress.px[ri * 6 + 3] << 15) |
(comp->compress.px[ri * 6 + 4] << 20) |
(comp->compress.px[ri * 6 + 5] << 25);
isp_write_reg(dev, REG_ADDR(isp_compand_compress_px_0) + ri * 4, valr);
}
valr = comp->compress.px[60] | (comp->compress.px[61] << 5) | (comp->compress.px[62] << 10) | (comp->compress.px[63] << 15);
isp_write_reg(dev, REG_ADDR(isp_compand_compress_px_10), valr);
isp_write_reg(dev, REG_ADDR(isp_compand_compress_x_addr), 0x0);
for (ri = 0; ri < 63; ri++) {
x_data = (comp->compress.x_data[ri] << (20 - comp->compress.in_bit));
isp_write_reg(dev, REG_ADDR(isp_compand_compress_x_write_data), x_data);
}
isp_write_reg(dev, REG_ADDR(isp_compand_compress_y_addr), 0x0);
for (ri = 0; ri < 64; ri++) {
y_data = (comp->compress.y_data[ri] << (20 - comp->compress.out_bit));
isp_write_reg(dev, REG_ADDR(isp_compand_compress_y_write_data), y_data);
}
}
REG_SET_SLICE(isp_compand_ctrl, COMPAND_CTRL_BLS_ENABLE, comp->bls.enable);
REG_SET_SLICE(isp_compand_ctrl, COMPAND_CTRL_COMPRESS_ENABLE, comp->compress.enable);
REG_SET_SLICE(isp_compand_ctrl, COMPAND_CTRL_EXPAND_ENABLE, comp->expand.enable);
REG_SET_SLICE(isp_compand_ctrl, COMPAND_CTRL_EXPAND_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_compand_ctrl), isp_compand_ctrl);
return 0;
#endif
}

432
vvcam/isp/isp_dmsc2.c Executable file
View File

@@ -0,0 +1,432 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#endif
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
extern MrvAllRegister_t *all_regs;
#ifdef ISP_DEMOSAIC2
int isp_enable_dmsc(struct isp_ic_dev *dev)
{
u32 isp_dmsc_ctrl = isp_read_reg(dev, REG_ADDR(isp_dmsc_ctrl));
u32 isp_dmsc_size_ctrl =
isp_read_reg(dev, REG_ADDR(isp_dmsc_size_ctrl));
pr_info("enter %s\n", __func__);
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_BYPASS, 0U);
REG_SET_SLICE(isp_dmsc_size_ctrl, ISP_DMSC_IMAGE_H_SIZE,
isp_read_reg(dev, REG_ADDR(isp_acq_h_size)));
REG_SET_SLICE(isp_dmsc_size_ctrl, ISP_DMSC_IMAGE_H_BLANK, 0x039c);
isp_write_reg(dev, REG_ADDR(isp_dmsc_size_ctrl), isp_dmsc_size_ctrl);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl_shd), isp_dmsc_ctrl);
return 0;
}
int isp_disable_dmsc(struct isp_ic_dev *dev)
{
u32 isp_dmsc_ctrl = isp_read_reg(dev, REG_ADDR(isp_dmsc_ctrl));
isp_dmsc_ctrl = 0; //clear fpga default bit 3 and 13 to keep the same value with cmodel.
pr_info("enter %s\n", __func__);
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_BYPASS, 1U);
/*clear the reg default val to keep weith cmodel */
isp_write_reg(dev, REG_ADDR(isp_dmsc_shap_fact), 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_shap_clip), 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_shap_filt2), 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_dpul_ctrl), 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_skin_thr_cb), 0);
//isp_write_reg(dev, REG_ADDR(isp_dmsc_cac_a), 0);
//isp_write_reg(dev, REG_ADDR(isp_dmsc_cac_c), 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_dmoi_ctrl), 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_dmoi_thr), 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_skin_thr_cr), 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_skin_thr_y), 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
return 0;
}
int isp_set_dmsc_intp(struct isp_ic_dev *dev)
{
u32 isp_dmsc_intp_thr = isp_read_reg(dev, REG_ADDR(isp_dmsc_intp_thr));
pr_info("enter %s\n", __func__);
REG_SET_SLICE(isp_dmsc_intp_thr, ISP_DMSC_INTERPLATION_DIR_THR_MAX,
dev->demosaic.intp.intp_dir_thr_max);
REG_SET_SLICE(isp_dmsc_intp_thr, ISP_DMSC_INTERPLATION_DIR_THR_MIN,
dev->demosaic.intp.intp_dir_thr_min);
isp_write_reg(dev, REG_ADDR(isp_dmsc_intp_thr), isp_dmsc_intp_thr);
return 0;
}
int isp_set_dmsc_dmoi(struct isp_ic_dev *dev)
{
struct isp_dmoi_context *pDemoire = &dev->demosaic.demoire;
u32 isp_dmsc_dmoi_ctrl =
isp_read_reg(dev, REG_ADDR(isp_dmsc_dmoi_ctrl));
u32 isp_dmsc_dmoi_thr = isp_read_reg(dev, REG_ADDR(isp_dmsc_dmoi_thr));
u32 isp_dmsc_dmoi_patn_thr =
isp_read_reg(dev, REG_ADDR(isp_dmsc_dmoi_patn_thr));
u32 isp_dmsc_ctrl = isp_read_reg(dev, REG_ADDR(isp_dmsc_ctrl));
pr_info("enter %s\n", __func__);
if (!pDemoire->enable) {
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_DEMOIRE_ENABLE, 0U);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
return 0;
}
REG_SET_SLICE(isp_dmsc_dmoi_ctrl, ISP_DMSC_DEMOIRE_AREA_THR,
pDemoire->demoire_area_thr);
REG_SET_SLICE(isp_dmsc_dmoi_ctrl, ISP_DMSC_DEMOIRE_SAT_SHRINK,
pDemoire->demoire_sat_shrink);
REG_SET_SLICE(isp_dmsc_dmoi_thr, ISP_DMSC_DEMOIRE_R2,
pDemoire->demoire_r2);
REG_SET_SLICE(isp_dmsc_dmoi_thr, ISP_DMSC_DEMOIRE_R1,
pDemoire->demoire_r1);
REG_SET_SLICE(isp_dmsc_dmoi_thr, ISP_DMSC_DEMOIRE_T2_SHIFT,
pDemoire->demoire_t2_shift);
REG_SET_SLICE(isp_dmsc_dmoi_thr, ISP_DMSC_DEMOIRE_T1,
pDemoire->demoire_t1);
REG_SET_SLICE(isp_dmsc_dmoi_patn_thr, ISP_DMSC_DEMOIRE_EDGE_R2,
pDemoire->demoire_edge_r2);
REG_SET_SLICE(isp_dmsc_dmoi_patn_thr, ISP_DMSC_DEMOIRE_EDGE_R1,
pDemoire->demoire_edge_r1);
REG_SET_SLICE(isp_dmsc_dmoi_patn_thr, ISP_DMSC_DEMOIRE_EDGE_T2_SHIFT,
pDemoire->demoire_edge_t2_shift);
REG_SET_SLICE(isp_dmsc_dmoi_patn_thr, ISP_DMSC_DEMOIRE_EDGE_T1,
pDemoire->demoire_edge_t1);
isp_write_reg(dev, REG_ADDR(isp_dmsc_dmoi_ctrl), isp_dmsc_dmoi_ctrl);
isp_write_reg(dev, REG_ADDR(isp_dmsc_dmoi_thr), isp_dmsc_dmoi_thr);
isp_write_reg(dev, REG_ADDR(isp_dmsc_dmoi_patn_thr),
isp_dmsc_dmoi_patn_thr);
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_DEMOIRE_ENABLE, 1U);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
return 0;
}
int isp_set_dmsc_sharpen(struct isp_ic_dev *dev)
{
struct isp_shap_context *pSharpen = &dev->demosaic.sharpen;
u32 isp_dmsc_shap_fact =
isp_read_reg(dev, REG_ADDR(isp_dmsc_shap_fact));
u32 isp_dmsc_shap_clip =
isp_read_reg(dev, REG_ADDR(isp_dmsc_shap_clip));
u32 isp_dmsc_shap_thr = isp_read_reg(dev, REG_ADDR(isp_dmsc_shap_thr));
u32 isp_dmsc_shap_ratio =
isp_read_reg(dev, REG_ADDR(isp_dmsc_shap_ratio));
u32 isp_dmsc_ctrl = isp_read_reg(dev, REG_ADDR(isp_dmsc_ctrl));
pr_info("enter %s\n", __func__);
if (!pSharpen->enable) {
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_SHARPEN_ENBALE, 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl_shd), isp_dmsc_ctrl);
return 0;
}
REG_SET_SLICE(isp_dmsc_shap_fact, ISP_DMSC_SHARPEN_FACTOR_BLACK,
pSharpen->sharpen_factor_black);
REG_SET_SLICE(isp_dmsc_shap_fact, ISP_DMSC_SHARPEN_FACTOR_WHITE,
pSharpen->sharpen_factor_white);
REG_SET_SLICE(isp_dmsc_shap_clip, ISP_DMSC_SHARPEN_CLIP_BLACK,
pSharpen->sharpen_clip_black);
REG_SET_SLICE(isp_dmsc_shap_clip, ISP_DMSC_SHARPEN_CLIP_WHITE,
pSharpen->sharpen_clip_white);
REG_SET_SLICE(isp_dmsc_shap_thr, ISP_DMSC_SHARPEN_T4_SHIFT,
pSharpen->sharpen_t4_shift);
REG_SET_SLICE(isp_dmsc_shap_thr, ISP_DMSC_SHARPEN_T3,
pSharpen->sharpen_t3);
REG_SET_SLICE(isp_dmsc_shap_thr, ISP_DMSC_SHARPEN_T2_SHIFT,
pSharpen->sharpen_t2_shift);
REG_SET_SLICE(isp_dmsc_shap_thr, ISP_DMSC_SHARPEN_T1,
pSharpen->sharpen_t1);
REG_SET_SLICE(isp_dmsc_shap_ratio, ISP_DMSC_SHARPEN_R3,
pSharpen->sharpen_r3);
REG_SET_SLICE(isp_dmsc_shap_ratio, ISP_DMSC_SHARPEN_R2,
pSharpen->sharpen_r2);
REG_SET_SLICE(isp_dmsc_shap_ratio, ISP_DMSC_SHARPEN_R1,
pSharpen->sharpen_r1);
isp_write_reg(dev, REG_ADDR(isp_dmsc_shap_fact), isp_dmsc_shap_fact);
isp_write_reg(dev, REG_ADDR(isp_dmsc_shap_clip), isp_dmsc_shap_clip);
isp_write_reg(dev, REG_ADDR(isp_dmsc_shap_thr), isp_dmsc_shap_thr);
isp_write_reg(dev, REG_ADDR(isp_dmsc_shap_ratio), isp_dmsc_shap_ratio);
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_SHARPEN_ENBALE, 1);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
return 0;
}
int isp_set_dmsc_gfilter(struct isp_ic_dev *dev)
{
struct isp_gfilter_context *pgfilter = &dev->demosaic.gFilter;
u32 isp_dmsc_ctrl = isp_read_reg(dev, REG_ADDR(isp_dmsc_ctrl));
u32 isp_dmsc_shap_filt1 =
isp_read_reg(dev, REG_ADDR(isp_dmsc_shap_filt1));
u32 isp_dmsc_shap_filt2 =
isp_read_reg(dev, REG_ADDR(isp_dmsc_shap_filt2));
pr_info("enter %s\n", __func__);
REG_SET_SLICE(isp_dmsc_shap_filt1, ISP_DMSC_HF_FILT_00,
pgfilter->hf_filt_00);
REG_SET_SLICE(isp_dmsc_shap_filt1, ISP_DMSC_HF_FILT_01,
pgfilter->hf_filt_01);
REG_SET_SLICE(isp_dmsc_shap_filt1, ISP_DMSC_HF_FILT_02,
pgfilter->hf_filt_02);
REG_SET_SLICE(isp_dmsc_shap_filt1, ISP_DMSC_HF_FILT_10,
pgfilter->hf_filt_10);
REG_SET_SLICE(isp_dmsc_shap_filt1, ISP_DMSC_HF_FILT_11,
pgfilter->hf_filt_11);
REG_SET_SLICE(isp_dmsc_shap_filt2, ISP_DMSC_HF_FILT_12,
pgfilter->hf_filt_12);
REG_SET_SLICE(isp_dmsc_shap_filt2, ISP_DMSC_HF_FILT_20,
pgfilter->hf_filt_20);
REG_SET_SLICE(isp_dmsc_shap_filt2, ISP_DMSC_HF_FILT_21,
pgfilter->hf_filt_21);
REG_SET_SLICE(isp_dmsc_shap_filt2, ISP_DMSC_HF_FILT_22,
pgfilter->hf_filt_22);
isp_write_reg(dev, REG_ADDR(isp_dmsc_shap_filt1), isp_dmsc_shap_filt1);
isp_write_reg(dev, REG_ADDR(isp_dmsc_shap_filt2), isp_dmsc_shap_filt2);
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_SHARPEN_SIZE, pgfilter->sharpen_size);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
return 0;
}
int isp_set_dmsc_sharpen_line(struct isp_ic_dev *dev)
{
struct isp_shap_line_context *sharpenLine = &dev->demosaic.sharpenLine;
u32 isp_dmsc_shap_line_ctrl =
isp_read_reg(dev, REG_ADDR(isp_dmsc_shap_line_ctrl));
u32 isp_dmsc_shap_line_ratio =
isp_read_reg(dev, REG_ADDR(isp_dmsc_shap_line_ratio));
u32 isp_dmsc_ctrl = isp_read_reg(dev, REG_ADDR(isp_dmsc_ctrl));
pr_info("enter %s\n", __func__);
if (!sharpenLine->enable) {
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_SHARPEN_LINE_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
return 0;
}
REG_SET_SLICE(isp_dmsc_shap_line_ctrl, ISP_DMSC_SHARPEN_LINE_SHIFT2,
sharpenLine->sharpen_line_shift2);
REG_SET_SLICE(isp_dmsc_shap_line_ctrl, ISP_DMSC_SHARPEN_LINE_SHIFT1,
sharpenLine->sharpen_line_shift1);
REG_SET_SLICE(isp_dmsc_shap_line_ctrl, ISP_DMSC_SHARPEN_LINE_T1,
sharpenLine->sharpen_line_t1);
REG_SET_SLICE(isp_dmsc_shap_line_ctrl, ISP_DMSC_SHARPEN_LINE_STRENGTH,
sharpenLine->sharpen_line_strength);
REG_SET_SLICE(isp_dmsc_shap_line_ratio, ISP_DMSC_SHARPEN_LINE_R2,
sharpenLine->sharpen_line_r2);
REG_SET_SLICE(isp_dmsc_shap_line_ratio, ISP_DMSC_SHARPEN_LINE_R1,
sharpenLine->sharpen_line_r1);
isp_write_reg(dev, REG_ADDR(isp_dmsc_shap_line_ctrl),
isp_dmsc_shap_line_ctrl);
isp_write_reg(dev, REG_ADDR(isp_dmsc_shap_line_ratio),
isp_dmsc_shap_line_ratio);
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_SHARPEN_LINE_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
return 0;
}
int isp_set_dmsc_cac(struct isp_ic_dev *dev)
{
struct isp_cac_context *cac = &dev->cac;
u32 val = 0;
u32 isp_dmsc_cac_ctrl = isp_read_reg(dev, REG_ADDR(isp_dmsc_cac_ctrl));
pr_info("enter %s\n", __func__);
if (!cac->enable) {
REG_SET_SLICE(isp_dmsc_cac_ctrl, MRV_CAC_CAC_EN, 0);
isp_write_reg(dev, REG_ADDR(isp_dmsc_cac_ctrl),
isp_dmsc_cac_ctrl);
return 0;
}
REG_SET_SLICE(isp_dmsc_cac_ctrl, MRV_CAC_H_CLIP_MODE, cac->hmode);
REG_SET_SLICE(isp_dmsc_cac_ctrl, MRV_CAC_V_CLIP_MODE, cac->vmode);
isp_write_reg(dev, REG_ADDR(isp_dmsc_cac_count_start),
cac->hstart | (cac->vstart << 16));
isp_write_reg(dev, REG_ADDR(isp_dmsc_cac_a), cac->ar | (cac->ab << 16));
isp_write_reg(dev, REG_ADDR(isp_dmsc_cac_b), cac->br | (cac->bb << 16));
isp_write_reg(dev, REG_ADDR(isp_dmsc_cac_c), cac->cr | (cac->cb << 16));
REG_SET_SLICE(val, MRV_CAC_X_NS, cac->xns);
REG_SET_SLICE(val, MRV_CAC_X_NF, cac->xnf);
isp_write_reg(dev, REG_ADDR(isp_dmsc_cac_x_norm), val);
val = 0;
REG_SET_SLICE(val, MRV_CAC_Y_NS, cac->yns);
REG_SET_SLICE(val, MRV_CAC_Y_NF, cac->ynf);
isp_write_reg(dev, REG_ADDR(isp_dmsc_cac_y_norm), val);
REG_SET_SLICE(isp_dmsc_cac_ctrl, MRV_CAC_CAC_EN, 1);
isp_write_reg(dev, REG_ADDR(isp_dmsc_cac_ctrl), isp_dmsc_cac_ctrl);
return 0;
}
int isp_set_dmsc_depurple(struct isp_ic_dev *dev)
{
struct isp_depurple_context *depurple = &dev->demosaic.depurple;
u32 isp_dmsc_dpul_ctrl =
isp_read_reg(dev, REG_ADDR(isp_dmsc_dpul_ctrl));
u32 isp_dmsc_ctrl = isp_read_reg(dev, REG_ADDR(isp_dmsc_ctrl));
pr_info("enter %s\n", __func__);
if (!depurple->enable) {
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_DEPURPLE_ENABLE, 0U);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
return 0;
}
REG_SET_SLICE(isp_dmsc_dpul_ctrl, ISP_DMSC_DEPURPLE_RED_SAT, depurple->red_sat);
REG_SET_SLICE(isp_dmsc_dpul_ctrl, ISP_DMSC_DEPURPLE_BLUE_SAT, depurple->blue_sat);
REG_SET_SLICE(isp_dmsc_dpul_ctrl, ISP_DMSC_DEPURPLE_SAT_SHRINK,
depurple->depurple_sat_shrink);
REG_SET_SLICE(isp_dmsc_dpul_ctrl, ISP_DMSC_DEPURPLE_THR,
depurple->depurple_thr);
isp_write_reg(dev, REG_ADDR(isp_dmsc_dpul_ctrl), isp_dmsc_dpul_ctrl);
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_DEPURPLE_ENABLE, 1U);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
return 0;
}
int isp_set_dmsc_skin(struct isp_ic_dev *dev)
{
struct isp_skin_context *skin = &dev->demosaic.skin;
u32 isp_dmsc_skin_thr_cb =
isp_read_reg(dev, REG_ADDR(isp_dmsc_skin_thr_cb));
u32 isp_dmsc_skin_thr_cr =
isp_read_reg(dev, REG_ADDR(isp_dmsc_skin_thr_cr));
u32 isp_dmsc_skin_thr_y =
isp_read_reg(dev, REG_ADDR(isp_dmsc_skin_thr_y));
u32 isp_dmsc_ctrl = isp_read_reg(dev, REG_ADDR(isp_dmsc_ctrl));
pr_info("enter %s\n", __func__);
if (!skin->enable) {
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_SKIN_ENABLE, 0U);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
return 0;
}
REG_SET_SLICE(isp_dmsc_skin_thr_cb, ISP_DMSC_SKIN_CB_THR_MAX_2047,
skin->cb_thr_max_2047);
REG_SET_SLICE(isp_dmsc_skin_thr_cb, ISP_DMSC_SKIN_CB_THR_MIN_2047,
skin->cb_thr_min_2047);
REG_SET_SLICE(isp_dmsc_skin_thr_cr, ISP_DMSC_SKIN_CR_THR_MAX_2047,
skin->cr_thr_max_2047);
REG_SET_SLICE(isp_dmsc_skin_thr_cr, ISP_DMSC_SKIN_CR_THR_MIN_2047,
skin->cr_thr_min_2047);
REG_SET_SLICE(isp_dmsc_skin_thr_y, ISP_DMSC_SKIN_Y_THR_MAX,
skin->y_thr_max_2047);
REG_SET_SLICE(isp_dmsc_skin_thr_y, ISP_DMSC_SKIN_Y_THR_MIN,
skin->y_thr_min_2047);
isp_write_reg(dev, REG_ADDR(isp_dmsc_skin_thr_cb),
isp_dmsc_skin_thr_cb);
isp_write_reg(dev, REG_ADDR(isp_dmsc_skin_thr_cr),
isp_dmsc_skin_thr_cr);
isp_write_reg(dev, REG_ADDR(isp_dmsc_skin_thr_y), isp_dmsc_skin_thr_y);
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_SKIN_ENABLE, 1U);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
return 0;
}
int isp_s_dmsc(struct isp_ic_dev *dev)
{
u32 isp_dmsc_ctrl;
/*Clear the cmodel register default value to match the fpga default value */
isp_disable_dmsc(dev);
isp_dmsc_ctrl = isp_read_reg(dev, REG_ADDR(isp_dmsc_ctrl));
pr_info("enter %s\n", __func__);
if (!dev->demosaic.enable) {
isp_disable_dmsc(dev);
return 0;
}
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_THR,
dev->demosaic.demosaic_thr);
REG_SET_SLICE(isp_dmsc_ctrl, ISP_DEMOSAIC_DENOISE_STRENGTH,
dev->demosaic.denoise_stren);
isp_write_reg(dev, REG_ADDR(isp_dmsc_ctrl), isp_dmsc_ctrl);
isp_set_dmsc_intp(dev);
isp_set_dmsc_dmoi(dev);
isp_set_dmsc_skin(dev);
isp_enable_dmsc(dev);
isp_set_dmsc_depurple(dev);
isp_set_dmsc_sharpen_line(dev);
isp_set_dmsc_sharpen(dev);
isp_set_dmsc_gfilter(dev);
return 0;
}
#endif

193
vvcam/isp/isp_dpf.c Executable file
View File

@@ -0,0 +1,193 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#else
#endif
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
extern MrvAllRegister_t *all_regs;
int isp_s_dpf(struct isp_ic_dev *dev)
{
struct isp_dpf_context *dpf = &dev->dpf;
u32 value;
int i = 0;
u32 isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
u32 isp_dpf_mode = isp_read_reg(dev, REG_ADDR(isp_dpf_mode));
//pr_info("enter %s\n", __func__);
if (!dpf->enable) {
isp_write_reg(dev, REG_ADDR(isp_dpf_mode),
isp_dpf_mode & ~MRV_DPF_DPF_ENABLE_MASK);
return 0;
}
isp_dpf_mode &=
(MRV_DPF_DPF_ENABLE_MASK | MRV_DPF_NLL_SEGMENTATION_MASK);
switch (dpf->gain_usage) {
case IC_DPF_GAIN_USAGE_DISABLED:
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_USE_NF_GAIN, 0);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_LSC_GAIN_COMP, 0);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_AWB_GAIN_COMP, 0);
break;
case IC_DPF_GAIN_USAGE_NF_GAINS:
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_USE_NF_GAIN, 1);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_LSC_GAIN_COMP, 0);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_AWB_GAIN_COMP, 1);
break;
case IC_DPF_GAIN_USAGE_LSC_GAINS:
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_USE_NF_GAIN, 0);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_LSC_GAIN_COMP, 1);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_AWB_GAIN_COMP, 0);
break;
case IC_DPF_GAIN_USAGE_NF_LSC_GAINS:
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_USE_NF_GAIN, 1);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_LSC_GAIN_COMP, 1);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_AWB_GAIN_COMP, 1);
break;
case IC_DPF_GAIN_USAGE_AWB_GAINS:
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_USE_NF_GAIN, 0);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_LSC_GAIN_COMP, 0);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_AWB_GAIN_COMP, 1);
break;
case IC_DPF_GAIN_USAGE_AWB_LSC_GAINS:
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_USE_NF_GAIN, 0);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_LSC_GAIN_COMP, 1);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_AWB_GAIN_COMP, 1);
break;
default:
/*pr_err("%s: unsupported gain usage\n", __func__);*/
break;
}
switch (dpf->filter_type) {
case IC_DPF_RB_FILTERSIZE_13x9:
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_RB_FILTER_SIZE, 0U);
break;
case IC_DPF_RB_FILTERSIZE_9x9:
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_RB_FILTER_SIZE, 1U);
break;
default:
/*pr_err
("%s: unsupported filter kernel size for red/blue pixel\n",
__func__);*/
break;
}
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_R_FILTER_OFF, dpf->filter_r_off);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_GR_FILTER_OFF, dpf->filter_gr_off);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_GB_FILTER_OFF, dpf->filter_gb_off);
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_B_FILTER_OFF, dpf->filter_b_off);
value = 0;
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_G1, dpf->weight_g[0]);
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_G2, dpf->weight_g[1]);
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_G3, dpf->weight_g[2]);
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_G4, dpf->weight_g[3]);
isp_write_reg(dev, REG_ADDR(isp_dpf_s_weight_g_1_4), value);
value = 0;
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_G5, dpf->weight_g[4]);
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_G6, dpf->weight_g[5]);
isp_write_reg(dev, REG_ADDR(isp_dpf_s_weight_g_5_6), value);
value = 0;
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_RB1, dpf->weight_rb[0]);
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_RB2, dpf->weight_rb[1]);
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_RB3, dpf->weight_rb[2]);
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_RB4, dpf->weight_rb[3]);
isp_write_reg(dev, REG_ADDR(isp_dpf_s_weight_rb_1_4), value);
value = 0;
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_RB5, dpf->weight_rb[4]);
REG_SET_SLICE(value, MRV_DPF_S_WEIGHT_RB6, dpf->weight_rb[5]);
isp_write_reg(dev, REG_ADDR(isp_dpf_s_weight_rb_5_6), value);
isp_write_reg(dev, REG_ADDR(isp_dpf_nf_gain_r), dpf->nf_gain_r);
isp_write_reg(dev, REG_ADDR(isp_dpf_nf_gain_gr), dpf->nf_gain_gr);
isp_write_reg(dev, REG_ADDR(isp_dpf_nf_gain_gb), dpf->nf_gain_gb);
isp_write_reg(dev, REG_ADDR(isp_dpf_nf_gain_b), dpf->nf_gain_b);
isp_write_reg(dev, REG_ADDR(isp_dpf_strength_r),
(MRV_DPF_INV_WEIGHT_R_MASK & dpf->strength_r));
isp_write_reg(dev, REG_ADDR(isp_dpf_strength_g),
(MRV_DPF_INV_WEIGHT_G_MASK & dpf->strength_g));
isp_write_reg(dev, REG_ADDR(isp_dpf_strength_b),
(MRV_DPF_INV_WEIGHT_B_MASK & dpf->strength_b));
for (i = 0; i < 17; i++) {
if (dpf->denoise_talbe[i] <= MRV_DPF_NLL_COEFF_N_MASK) {
isp_write_reg(dev,
REG_ADDR(nlf_lookup_table_block_arr[i]),
dpf->denoise_talbe[i]);
}
}
switch (dpf->x_scale) {
case IC_NLL_SCALE_LINEAR:
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_NLL_SEGMENTATION, 0);
break;
case IC_NLL_SCALE_LOGARITHMIC:
REG_SET_SLICE(isp_dpf_mode, MRV_DPF_NLL_SEGMENTATION, 1);
break;
default:
break;
}
isp_write_reg(dev, REG_ADDR(isp_dpf_mode), isp_dpf_mode);
isp_write_reg(dev, REG_ADDR(isp_dpf_mode),
isp_dpf_mode | MRV_DPF_DPF_ENABLE_MASK);
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
return 0;
}

186
vvcam/isp/isp_gcmono.c Executable file
View File

@@ -0,0 +1,186 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#else
#endif
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
extern MrvAllRegister_t *all_regs;
int isp_enable_gcmono(struct isp_ic_dev *dev)
{
#ifndef ISP_GCMONO
pr_err("unsupported function %s", __func__);
return -1;
#else
u32 isp_gcmono_ctrl = isp_read_reg(dev, REG_ADDR(isp_gcmono_ctrl));
u32 isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
pr_info("enter %s\n", __func__);
REG_SET_SLICE(isp_gcmono_ctrl, ISP_GCMONO_CFG_DONE, 1);
REG_SET_SLICE(isp_gcmono_ctrl, ISP_GCMONO_SWITCH,
ISP_GCMONO_SWITCH_ENABLE);
isp_write_reg(dev, REG_ADDR(isp_gcmono_ctrl), isp_gcmono_ctrl);
REG_SET_SLICE(isp_ctrl, ISP_GCMONO_MODE, dev->gcmono.mode);
REG_SET_SLICE(isp_ctrl, ISP_GCMONO_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
dev->gcmono.enable = true;
return 0;
#endif
}
int isp_disable_gcmono(struct isp_ic_dev *dev)
{
#ifndef ISP_GCMONO
pr_err("unsupported function %s", __func__);
return -1;
#else
u32 isp_gcmono_ctrl = isp_read_reg(dev, REG_ADDR(isp_gcmono_ctrl));
u32 isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
pr_info("enter %s\n", __func__);
REG_SET_SLICE(isp_gcmono_ctrl, ISP_GCMONO_SWITCH,
ISP_GCMONO_SWITCH_DISABLE);
isp_write_reg(dev, REG_ADDR(isp_gcmono_ctrl), isp_gcmono_ctrl);
REG_SET_SLICE(isp_ctrl, ISP_GCMONO_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
dev->gcmono.enable = false;
return 0;
#endif
}
#ifdef ISP_GCMONO
static int isp_s_gcmonopx(struct isp_ic_dev *dev, struct isp_gcmono_data *data)
{
u32 isp_gc_px_reg = REG_ADDR(isp_gcmono_px_0);
u32 *p_table = NULL;
int i;
u32 gc_px_data = 0;
pr_info("enter %s\n", __func__);
p_table = (u32 *)&data->px;
for (i = 0; i < 64; i++) {
gc_px_data |= (*(p_table + i) << (i % 6 * 5));
if (i % 6 == 5 || i == 63) {
isp_write_reg(dev, isp_gc_px_reg, gc_px_data);
isp_gc_px_reg += 4;
gc_px_data = 0;
}
}
return 0;
}
#endif
#ifdef ISP_GCMONO
static int isp_s_gcmonoWriteData(struct isp_ic_dev *dev, u32 *tblX, u32 *tblY)
{
u32 isp_gc_y_data, isp_gc_x_data;
// u32 *p_table = NULL;
int i;
// u32 gc_px_data = 0;
pr_info("enter %s\n", __func__);
isp_write_reg(dev, REG_ADDR(isp_gcmono_y_addr), 0);
isp_write_reg(dev, REG_ADDR(isp_gcmono_x_addr), 0);
for (i = 0; i < 64; i++) {
isp_gc_y_data = *(tblY + i);
isp_write_reg(dev, REG_ADDR(isp_gcmono_y_write_data),
isp_gc_y_data);
}
for (i = 0; i < 63; i++) {
isp_gc_x_data = *(tblX + i);
isp_write_reg(dev, REG_ADDR(isp_gcmono_x_write_data),
isp_gc_x_data);
}
return 0;
}
#endif
int isp_s_gcmono(struct isp_ic_dev *dev, struct isp_gcmono_data *data)
{
#ifndef ISP_GCMONO
pr_err("unsupported function %s", __func__);
return -1;
#else
u32 isp_gcmono_ctrl = isp_read_reg(dev, REG_ADDR(isp_gcmono_ctrl));
u32 isp_gc_para_base = 0;
u8 *p_table = NULL;
int i;
pr_info("enter %s\n", __func__);
REG_SET_SLICE(isp_gcmono_ctrl, ISP_GCMONO_SWITCH,
ISP_GCMONO_SWITCH_DISABLE);
REG_SET_SLICE(isp_gcmono_ctrl, ISP_GCMONO_CFG_DONE,
ISP_GCMONO_CFG_DONE_SET_CURVE);
isp_write_reg(dev, REG_ADDR(isp_gcmono_ctrl), isp_gcmono_ctrl);
p_table = (u8 *)&data->basePara;
for (i = 0; i < 1024; i++) {
isp_gc_para_base |= (*(p_table + i) << (i % 4 * 8));
if (i % 4 == 3) {
isp_write_reg(dev, REG_ADDR(isp_gcmono_para_base),
isp_gc_para_base);
isp_gc_para_base = 0;
}
}
isp_s_gcmonopx(dev, data);
isp_s_gcmonoWriteData(dev, data->dataX, data->dataY);
if (dev->gcmono.enable) {
isp_enable_gcmono(dev);
}
return 0;
#endif
}

259
vvcam/isp/isp_hdr.c Executable file
View File

@@ -0,0 +1,259 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#endif
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
extern MrvAllRegister_t *all_regs;
int isp_s_hdr(struct isp_ic_dev *dev)
{
struct isp_hdr_context *hdr = &dev->hdr;
u32 isp_stitching_ctrl =
isp_read_reg(dev, REG_ADDR(isp_stitching_ctrl));
u32 val;
int i;
pr_info("enter %s\n", __func__);
val = 0;
#if 0
REG_SET_SLICE(val, STITCHING_FRAME_WIDTH, hdr->width);
isp_write_reg(dev, REG_ADDR(isp_stitching_frame_width), val);
val = 0;
REG_SET_SLICE(val, STITCHING_FRAME_HEIGHT, hdr->height);
isp_write_reg(dev, REG_ADDR(isp_stitching_frame_height), val);
val = 0;
REG_SET_SLICE(val, STITCHING_L_BIT_DEPTH, hdr->l_bit_dep);
REG_SET_SLICE(val, STITCHING_S_BIT_DEPTH, hdr->s_bit_dep);
REG_SET_SLICE(val, STITCHING_VS_BIT_DEPTH, hdr->vs_bit_dep);
REG_SET_SLICE(val, STITCHING_LS_BIT_DEPTH, hdr->ls_bit_dep);
isp_write_reg(dev, REG_ADDR(isp_stitching_exposure_bit), val);
val = 0;
REG_SET_SLICE(val, STITCHING_COLOR_WEIGHT_0, hdr->weight0);
REG_SET_SLICE(val, STITCHING_COLOR_WEIGHT_1, hdr->weight1);
REG_SET_SLICE(val, STITCHING_COLOR_WEIGHT_2, hdr->weight2);
isp_write_reg(dev, REG_ADDR(isp_stitching_color_weight), val);
val = 0;
REG_SET_SLICE(val, STITCHING_TRANS_RANGE_START_LINEAR,
hdr->start_linear);
REG_SET_SLICE(val, STITCHING_TRANS_RANGE_NORM_FACTOR_MUL_LINEAR,
hdr->norm_factor_mul_linear);
isp_write_reg(dev, REG_ADDR(isp_stitching_trans_range_linear), val);
val = 0;
REG_SET_SLICE(val, STITCHING_TRANS_RANGE_START_NONLINEAR,
hdr->start_nonlinear);
REG_SET_SLICE(val, STITCHING_TRANS_RANGE_NORM_FACTOR_MUL_NONLINEAR,
hdr->norm_factor_mul_nonlinear);
isp_write_reg(dev, REG_ADDR(isp_stitching_trans_range_nonlinear), val);
val = 0;
REG_SET_SLICE(val, STITCHING_DUMMY_HBLANK, hdr->dummy_hblank);
REG_SET_SLICE(val, STITCHING_OUT_HBLANK, hdr->out_hblank);
isp_write_reg(dev, REG_ADDR(isp_stitching_out_hblank), val);
val = 0;
REG_SET_SLICE(val, STITCHING_OUT_VBLANK, hdr->out_vblank);
isp_write_reg(dev, REG_ADDR(isp_stitching_out_vblank), val);
val = 0;
REG_SET_SLICE(val, STITCHING_LONG_EXPOSURE_TIME, hdr->long_exp);
isp_write_reg(dev, REG_ADDR(isp_stitching_long_exposure), val);
val = 0;
REG_SET_SLICE(val, STITCHING_SHORT_EXPOSURE_TIME, hdr->short_exp);
isp_write_reg(dev, REG_ADDR(isp_stitching_short_exposure), val);
val = 0;
REG_SET_SLICE(val, STITCHING_VERY_SHORT_EXPOSURE_TIME,
hdr->very_short_exp);
isp_write_reg(dev, REG_ADDR(isp_stitching_very_short_exposure), val);
val = 0;
REG_SET_SLICE(val, STITCHING_LONG_EXPOSURE_TIME, hdr->long_exp);
isp_write_reg(dev, REG_ADDR(isp_stitching_long_exposure), val);
#endif
val = 0;
REG_SET_SLICE(val, STITCHING_RATIO_LONG_SHORT_1, hdr->ls1);
REG_SET_SLICE(val, STITCHING_RATIO_LONG_SHORT_0, hdr->ls0);
isp_write_reg(dev, REG_ADDR(isp_stitching_ratio_ls), val);
val = 0;
REG_SET_SLICE(val, STITCHING_RATIO_VERYSHORT_SHORT_1, hdr->vs1);
REG_SET_SLICE(val, STITCHING_RATIO_VERYSHORT_SHORT_0, hdr->vs0);
isp_write_reg(dev, REG_ADDR(isp_stitching_ratio_vs), val);
val = 0;
REG_SET_SLICE(val, STITCHING_SHORT_EXTEND_BIT, hdr->ext_bit);
REG_SET_SLICE(val, STITCHING_VERYSHORT_VALID_THRESH, hdr->valid_thresh);
REG_SET_SLICE(val, STITCHING_VERYSHORT_OFFSET_VAL, hdr->offset_val);
isp_write_reg(dev, REG_ADDR(isp_stitching_sat_level), val);
for (i = 0; i < 5; i++) {
val = 0;
REG_SET_SLICE(val, STITCHING_COMPRESS_LUT_2,
hdr->compress_lut[i * 3 + 2]);
REG_SET_SLICE(val, STITCHING_COMPRESS_LUT_1,
hdr->compress_lut[i * 3 + 1]);
REG_SET_SLICE(val, STITCHING_COMPRESS_LUT_0,
hdr->compress_lut[i * 3]);
isp_write_reg(dev,
REG_ADDR(isp_stitching_compress_lut_0) + i * 4,
val);
}
val = 0;
REG_SET_SLICE(val, STITCHING_LONG_SAT_THRESH, hdr->sat_thresh);
REG_SET_SLICE(val, STITCHING_LONG_SAT_COMBINE_WEIGHT,
hdr->combine_weight);
isp_write_reg(dev, REG_ADDR(isp_stitching_long_sat_params), val);
REG_SET_SLICE(isp_stitching_ctrl, STITCHING_COMBINE_ENABLE_BIT, 1);
REG_SET_SLICE(isp_stitching_ctrl, STITCHING_CFG_UPD, 1);
REG_SET_SLICE(isp_stitching_ctrl, STITCHING_COMBINATION_MODE, 1);
isp_write_reg(dev, REG_ADDR(isp_stitching_ctrl), 0x4c0221);
return 0;
}
int isp_s_hdr_wb(struct isp_ic_dev *dev)
{
struct isp_hdr_context *hdr = &dev->hdr;
u32 val = 0;
u32 isp_stitching_ctrl =
isp_read_reg(dev, REG_ADDR(isp_stitching_ctrl));
pr_info("enter %s\n", __func__);
REG_SET_SLICE(val, STITCHING_EXP0_AWB_GAIN_GR, hdr->gr);
REG_SET_SLICE(val, STITCHING_EXP0_AWB_GAIN_GB, hdr->gb);
isp_write_reg(dev, REG_ADDR(isp_stitching_exp0_awb_gain_g), val);
isp_write_reg(dev, REG_ADDR(isp_stitching_exp1_awb_gain_g), val);
isp_write_reg(dev, REG_ADDR(isp_stitching_exp2_awb_gain_g), val);
val = 0;
REG_SET_SLICE(val, STITCHING_EXP0_AWB_GAIN_R, hdr->r);
REG_SET_SLICE(val, STITCHING_EXP0_AWB_GAIN_B, hdr->b);
isp_write_reg(dev, REG_ADDR(isp_stitching_exp0_awb_gain_rb), val);
isp_write_reg(dev, REG_ADDR(isp_stitching_exp1_awb_gain_rb), val);
isp_write_reg(dev, REG_ADDR(isp_stitching_exp2_awb_gain_rb), val);
REG_SET_SLICE(isp_stitching_ctrl, STITCHING_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_stitching_ctrl), 0x4c0221);
return 0;
}
int isp_s_hdr_bls(struct isp_ic_dev *dev)
{
struct isp_hdr_context *hdr = &dev->hdr;
u32 isp_stitching_ctrl =
isp_read_reg(dev, REG_ADDR(isp_stitching_ctrl));
u32 val = 0;
int i;
pr_info("enter %s\n", __func__);
for (i = 0; i < 12; i++) {
val = 0;
REG_SET_SLICE(val, STITCHING_BLS_EXP_0_A, hdr->bls[i % 4]);
isp_write_reg(dev, REG_ADDR(isp_stitching_bls_exp_0_a) + i * 4,
val);
}
REG_SET_SLICE(isp_stitching_ctrl, STITCHING_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_stitching_ctrl), 0x4c0221);
return 0;
}
int isp_enable_hdr(struct isp_ic_dev *dev)
{
u32 addr, isp_stitching_ctrl;
u32 dpcl;
int val = 0;
pr_info("enter %s\n", __func__);
addr = REG_ADDR(isp_stitching_ctrl);
isp_stitching_ctrl = isp_read_reg(dev, addr);
REG_SET_SLICE(val, STITCHING_FRAME_WIDTH, dev->ctx.acqWindow.width);
isp_write_reg(dev, REG_ADDR(isp_stitching_frame_width), val);
val = 0;
REG_SET_SLICE(val, STITCHING_FRAME_HEIGHT, dev->ctx.acqWindow.height);
isp_write_reg(dev, REG_ADDR(isp_stitching_frame_height), val);
REG_SET_SLICE(isp_stitching_ctrl, STITCHING_COMBINE_ENABLE_BIT, 0);
isp_write_reg(dev, addr, isp_stitching_ctrl);
dpcl = isp_read_reg(dev, REG_ADDR(vi_dpcl));
REG_SET_SLICE(dpcl, MRV_IF_SELECT, MRV_IF_SELECT_HDR);
isp_write_reg(dev, REG_ADDR(vi_dpcl), dpcl);
dev->mux.if_select = MRV_IF_SELECT_HDR;
return 0;
}
int isp_disable_hdr(struct isp_ic_dev *dev)
{
u32 addr, isp_stitching_ctrl = 0;
pr_info("enter %s\n", __func__);
addr = REG_ADDR(isp_stitching_ctrl);
isp_stitching_ctrl = isp_read_reg(dev, addr);
REG_SET_SLICE(isp_stitching_ctrl, STITCHING_COMBINE_ENABLE_BIT, 1);
isp_write_reg(dev, addr, isp_stitching_ctrl);
return 0;
}

3688
vvcam/isp/isp_ioctl.c Executable file

File diff suppressed because it is too large Load Diff

436
vvcam/isp/isp_ioctl.h Executable file
View File

@@ -0,0 +1,436 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _ISP_IOC_H_
#define _ISP_IOC_H_
#include "ic_dev.h"
#include <linux/ioctl.h>
enum {
ISPIOC_RESET = 0x100,
ISPIOC_WRITE_REG = 0x101,
ISPIOC_READ_REG = 0x102,
ISPIOC_S_INPUT = 0x103,
ISPIOC_ENABLE = 0x104,
ISPIOC_DISABLE = 0x105,
ISPIOC_ISP_STATUS = 0x106,
ISPIOC_ISP_STOP = 0x107,
ISPIOC_START_CAPTURE = 0x108,
ISPIOC_DISABLE_ISP_OFF = 0x109,
ISPIOC_SET_BUFFER = 0x10A,
ISPIOC_SET_BP_BUFFER = 0x10B,
ISPIOC_START_DMA_READ = 0x10C,
ISPIOC_MI_START = 0x10D,
ISPIOC_MI_STOP = 0x10E,
ISPIOC_ENABLE_TPG = 0x10F,
ISPIOC_DISABLE_TPG = 0x110,
ISPIOC_S_TPG = 0x111,
ISPIOC_S_MCM_WR = 0x112,
ISPIOC_ENABLE_BLS = 0x113,
ISPIOC_DISABLE_BLS = 0x114,
ISPIOC_S_BLS = 0x115,
ISPIOC_S_MUX = 0x116,
ISPIOC_ENABLE_AWB = 0x117,
ISPIOC_DISABLE_AWB = 0x118,
ISPIOC_S_AWB = 0x119,
ISPIOC_G_AWBMEAN = 0x11A,
ISPIOC_S_IS = 0x11B,
ISPIOC_S_RAW_IS = 0x11C,
ISPIOC_S_CNR = 0x11D,
ISPIOC_S_CC = 0x11E,
ISPIOC_S_XTALK = 0x11F,
ISPIOC_S_GAMMA_OUT = 0x120,
ISPIOC_ENABLE_LSC = 0x121,
ISPIOC_DISABLE_LSC = 0x122,
ISPIOC_S_LSC_TBL = 0x123,
ISPIOC_S_LSC_SEC = 0x124,
ISPIOC_S_DPF = 0x125,
ISPIOC_S_EE = 0x126,
ISPIOC_S_EXP = 0x127,
ISPIOC_S_HDREXP = 0x128,
ISPIOC_G_EXPMEAN = 0x129,
ISPIOC_G_HDREXPMEAN = 0x12A,
ISPIOC_S_HIST = 0x12B,
ISPIOC_G_HISTMEAN = 0x12C,
ISPIOC_S_HDRHIST = 0x12D,
ISPIOC_G_HDRHISTMEAN = 0x12E,
ISPIOC_S_HIST64 = 0x12F,
ISPIOC_G_HIST64MEAN = 0x130,
ISPIOC_G_HIST64VSTART_STATUS= 0x131,
ISPIOC_U_HIST64 = 0x132,
ISPIOC_S_DPCC = 0x133,
ISPIOC_S_FLT = 0x134,
ISPIOC_S_CAC = 0x135,
ISPIOC_S_DEG = 0x136,
ISPIOC_S_AFM = 0x137,
ISPIOC_G_AFM = 0x138,
ISPIOC_S_VSM = 0x139,
ISPIOC_G_VSM = 0x13A,
ISPIOC_S_IE = 0x13B,
ISPIOC_ENABLE_WDR3 = 0x13C,
ISPIOC_DISABLE_WDR3 = 0x13D,
ISPIOC_U_WDR3 = 0x13E,
ISPIOC_S_WDR3 = 0x13F,
ISPIOC_S_EXP2 = 0x140,
ISPIOC_S_EXP2_INPUTSEL = 0x141,
ISPIOC_S_EXP2_SIZERATIO = 0x142,
ISPIOC_S_2DNR = 0x143,
ISPIOC_S_3DNR = 0x144,
ISPIOC_G_3DNR = 0x145, /* get last avg */
ISPIOC_U_3DNR = 0x146, /* update */
ISPIOC_R_3DNR = 0x147, /* read back 3dnr reference image. */
ISPIOC_S_3DNR_CMP = 0x148, /*config 3dnr compress */
ISPIOC_U_3DNR_STRENGTH = 0x149,
ISPIOC_S_3DNR_MOT = 0x14A, /*config 3dnr motion*/
ISPIOC_S_3DNR_DLT = 0x14B,/*config 3dnr delta*/
ISPIOC_S_HDR = 0x14C,
ISPIOC_S_COMP = 0x14D,
ISPIOC_S_CPROC = 0x14E,
ISPIOC_S_SIMP = 0x14F,
ISPIOC_S_ELAWB = 0x150,
ISPIOC_S_HDR_WB = 0x151,
ISPIOC_S_HDR_BLS = 0x152,
ISPIOC_S_HDR_DIGITAL_GAIN = 0x153,
ISPIOC_ENABLE_WB = 0x154,
ISPIOC_DISABLE_WB = 0x155,
ISPIOC_DISABLE_HDR = 0x156,
ISPIOC_ENABLE_HDR = 0x157,
ISPIOC_ENABLE_GAMMA_OUT = 0x158,
ISPIOC_DISABLE_GAMMA_OUT = 0x159,
ISPIOC_G_STATUS = 0x15A,
ISPIOC_G_FEATURE = 0x15B,
ISPIOC_G_FEATURE_VERSION = 0x15C,
ISPIOC_ENABLE_GCMONO = 0x15D,
ISPIOC_DISABLE_GCMONO = 0x15E,
ISPIOC_S_GCMONO = 0x15F,
ISPIOC_ENABLE_RGBGAMMA = 0x160,
ISPIOC_DISABLE_RGBGAMMA = 0x161,
ISPIOC_S_RGBGAMMA = 0x162,
ISPIOC_S_DEMOSAIC = 0x163,
ISPIOC_S_DMSC_INTP = 0x164,
ISPIOC_S_DMSC_DMOI = 0x165,
ISPIOC_S_DMSC_SKIN = 0x166,
ISPIOC_S_DMSC_CAC = 0x167,
ISPIOC_S_DMSC_SHAP = 0x168,
ISPIOC_S_DMSC_SHAP_LINE = 0x169,
ISPIOC_S_DMSC_DEPURPLE = 0x16A,
ISPIOC_S_DMSC_GFILTER = 0x16B,
ISPIOC_S_DMSC = 0x16C,
ISPIOC_S_GREENEQUILIBRATE = 0x16D,
ISPIOC_S_COLOR_ADJUST = 0x16E,
ISPIOC_S_DIGITAL_GAIN = 0x16F,
ISPIOC_G_QUERY_EXTMEM = 0x170,
#ifdef ISP_WDR_V4
ISPIOC_ENABLE_WDR4 = 0x171,
ISPIOC_DISABLE_WDR4 = 0x172,
ISPIOC_U_WDR4 = 0x173,
ISPIOC_S_WDR4 = 0x174,
#endif
ISPIOC_WDR_CONFIG = 0x175,
ISPIOC_S_WDR_CURVE = 0x176,
ISPIOC_ENABLE_RGBIR = 0x177,
ISPIOC_S_RGBIR = 0x178,
ISPIOC_RGBIR_HW_INIT = 0x179,
ISPIOC_RGBIR_S_IR_DNR = 0x17A,
ISPIOC_RGBIR_S_SHARPEN = 0x17B,
ISPIOC_RGBIR_S_DES = 0x17C,
ISPIOC_RGBIR_S_CC_MATRIX = 0x17D,
ISPIOC_RGBIR_S_DPCC = 0x17E,
ISPIOC_RGBIR_S_GAIN = 0x17F,
ISPIOC_RGBIR_S_BLS = 0x180,
ISPIOC_RGBIR_S_IR_RAW_OUT = 0x181,
ISPIOC_S_TDNR = 0x182,
ISPIOC_TDNR_ENABLE = 0x183,
ISPIOC_TDNR_DISABLE = 0x184,
ISPIOC_TDNR_ENABLE_TDNR = 0x185,
ISPIOC_TDNR_DISABLE_TDNR = 0x186,
ISPIOC_TDNR_ENABLE_2DNR = 0x187,
ISPIOC_TDNR_DISABLE_2DNR = 0x188,
ISPIOC_S_TDNR_CURVE = 0x189,
ISPIOC_G_TDNR = 0x18A,
ISPIOC_S_TDNR_STRENGTH = 0x18B,
ISPIOC_U_TDNR_NOISE = 0x18C,
ISPIOC_U_TDNR_THR = 0x18D,
ISPIOC_S_TDNR_BUF = 0x18E, // refer and motion
ISPIOC_R_TDNR_REFER = 0x18F,
ISPIOC_R_TDNR_MOTION = 0x190,
ISPIOC_GET_MIS = 0x191,
ISPIOC_CFG_DMA = 0x192,
ISPIOC_BYPASS_MCM = 0x193,
ISPIOC_SET_PPW_LINE_NUM = 0x194,
ISPIOC_GET_PPW_LINE_CNT = 0x195,
ISPIOC_CFG_DMA_LINE_ENTRY = 0x196,
ISPIOC_S_CROP = 0x197,
ISPIOC_GET_FRAME_MASK_INFO_ADDR = 0x198,
};
#define ISP_GEN_CFG_UPDATE(dev) { \
uint32_t isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl)); \
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1); \
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl); \
}
#define CONFIG_VSI_ISP_DEBUG 1
#ifdef CONFIG_VSI_ISP_DEBUG
#define isp_info(fmt, ...) pr_info(fmt, ##__VA_ARGS__)
#define isp_debug(fmt, ...) pr_debug(fmt, ##__VA_ARGS__)
#define isp_err(fmt, ...) pr_err(fmt, ##__VA_ARGS__)
#else
#define isp_info(fmt, ...)
#define isp_debug(fmt, ...)
#define isp_err(fmt, ...) pr_err(fmt, ##__VA_ARGS__)
#endif
#define ISP_REG_GAP 4
#define MI_QOS 0x44440444
#define MI_QOS2 0x44
long isp_priv_ioctl(struct isp_ic_dev *dev, unsigned int cmd, void __user *args);
long isp_copy_data(void *dst, void *src, int size);
/* internal functions, can called by v4l2 video device and ioctl */
int isp_reset(struct isp_ic_dev *dev);
int isp_enable_tpg(struct isp_ic_dev *dev);
int isp_disable_tpg(struct isp_ic_dev *dev);
int isp_enable_bls(struct isp_ic_dev *dev);
int isp_disable_bls(struct isp_ic_dev *dev);
int isp_enable(struct isp_ic_dev *dev);
int isp_disable(struct isp_ic_dev *dev);
bool is_isp_enable(struct isp_ic_dev *dev);
int isp_enable_lsc(struct isp_ic_dev *dev);
int isp_disable_lsc(struct isp_ic_dev *dev);
int isp_s_input(struct isp_ic_dev *dev);
int isp_s_digital_gain(struct isp_ic_dev *dev);
int isp_s_demosaic(struct isp_ic_dev *dev);
int isp_s_tpg(struct isp_ic_dev *dev);
int isp_s_mcm_wr(struct isp_ic_dev *dev);
int isp_bypass_mcm(struct isp_ic_dev *dev);
int isp_s_mux(struct isp_ic_dev *dev);
int isp_s_bls(struct isp_ic_dev *dev);
int isp_enable_awb(struct isp_ic_dev *dev);
int isp_disable_awb(struct isp_ic_dev *dev);
int isp_s_awb(struct isp_ic_dev *dev);
int isp_g_awbmean(struct isp_ic_dev *dev, struct isp_awb_mean *mean);
int isp_s_is(struct isp_ic_dev *dev);
int isp_s_raw_is(struct isp_ic_dev *dev);
int isp_s_cnr(struct isp_ic_dev *dev);
int isp_start_stream(struct isp_ic_dev *dev, u32 framenum);
int isp_stop_stream(struct isp_ic_dev *dev);
int isp_s_cc(struct isp_ic_dev *dev);
int isp_s_xtalk(struct isp_ic_dev *dev);
int isp_enable_wb(struct isp_ic_dev *dev, bool bEnable);
int isp_enable_gamma_out(struct isp_ic_dev *dev, bool bEnable);
int isp_s_gamma_out(struct isp_ic_dev *dev);
int isp_s_lsc_sec(struct isp_ic_dev *dev);
int isp_s_lsc_tbl(struct isp_ic_dev *dev);
int isp_ioc_disable_isp_off(struct isp_ic_dev *dev, void __user *args);
int isp_s_dpf(struct isp_ic_dev *dev);
int isp_s_ee(struct isp_ic_dev *dev);
int isp_s_exp(struct isp_ic_dev *dev);
int isp_s_hdrexp(struct isp_ic_dev *dev);
int isp_g_expmean(struct isp_ic_dev *dev, u8 * mean);
int isp_g_hdrexpmean(struct isp_ic_dev *dev, u8 * mean);
int isp_s_hist(struct isp_ic_dev *dev);
int isp_g_histmean(struct isp_ic_dev *dev, u32 * mean);
int isp_s_hdrhist(struct isp_ic_dev *dev);
int isp_g_hdrhistmean(struct isp_ic_dev *dev, u32 * mean);
#ifdef ISP_HIST64
int isp_s_hist64(struct isp_ic_dev *dev);
int isp_g_hist64mean(struct isp_ic_dev *dev, u32 *mean);
int isp_g_hist64_vstart(struct isp_ic_dev *dev, u32 start_line);
int isp_g_hist64_vstart_status(struct isp_ic_dev *dev, u32 *status);
int isp_update_hist64(struct isp_ic_dev *dev);
#endif
int isp_s_dpcc(struct isp_ic_dev *dev);
int isp_s_flt(struct isp_ic_dev *dev);
int isp_s_cac(struct isp_ic_dev *dev);
int isp_s_deg(struct isp_ic_dev *dev);
int isp_s_ie(struct isp_ic_dev *dev);
int isp_s_vsm(struct isp_ic_dev *dev);
int isp_g_vsm(struct isp_ic_dev *dev, struct isp_vsm_result *vsm);
int isp_s_afm(struct isp_ic_dev *dev);
int isp_g_afm(struct isp_ic_dev *dev, struct isp_afm_result *afm);
int isp_enable_wdr3(struct isp_ic_dev *dev);
int isp_disable_wdr3(struct isp_ic_dev *dev);
int isp_u_wdr3(struct isp_ic_dev *dev);
int isp_s_wdr3(struct isp_ic_dev *dev);
#ifdef ISP_WDR_V4
int isp_enable_wdr4(struct isp_ic_dev *dev);
int isp_disable_wdr4(struct isp_ic_dev *dev);
int isp_u_wdr4(struct isp_ic_dev *dev);
int isp_s_wdr4(struct isp_ic_dev *dev);
#endif
int isp_s_exp2(struct isp_ic_dev *dev);
int isp_s_exp2_inputsel(struct isp_ic_dev *dev);
int isp_s_exp2_sizeratio(struct isp_ic_dev *dev, u32 ratio);
int isp_s_hdr(struct isp_ic_dev *dev);
int isp_s_hdr_wb(struct isp_ic_dev *dev);
int isp_s_hdr_bls(struct isp_ic_dev *dev);
//int isp_s_hdr_digal_gain(struct isp_ic_dev *dev);
int isp_enable_hdr(struct isp_ic_dev *dev);
int isp_disable_hdr(struct isp_ic_dev *dev);
#ifdef ISP_2DNR_V5
int isp_tdnr_s_2dnr(struct isp_ic_dev *dev);
#else
int isp_s_2dnr(struct isp_ic_dev *dev);
#endif
#if defined(ISP_3DNR) || defined(ISP_3DNR_V2)
int isp_s_3dnr(struct isp_ic_dev *dev);
int isp_g_3dnr(struct isp_ic_dev *dev, u32 * avg);
int isp_u_3dnr(struct isp_ic_dev *dev, struct isp_3dnr_update *dnr3_update);
int isp_s_3dnr_motion(struct isp_ic_dev *dev);
int isp_s_3dnr_delta(struct isp_ic_dev *dev);
#endif
#if defined(ISP_3DNR) || defined(ISP_3DNR_V2_V1)
int isp_r_3dnr(struct isp_ic_dev *dev);
#endif
#ifdef ISP_3DNR_V2
int isp_s_3dnr_cmp(struct isp_ic_dev *dev);
#endif
int isp_u_3dnr_strength(struct isp_ic_dev *dev);
int isp_s_comp(struct isp_ic_dev *dev);
int isp_s_simp(struct isp_ic_dev *dev);
int isp_s_cproc(struct isp_ic_dev *dev);
int isp_s_elawb(struct isp_ic_dev *dev);
int isp_ioc_qcap(struct isp_ic_dev *dev, void __user *args);
int isp_ioc_g_status(struct isp_ic_dev *dev, void __user *args);
int isp_enable_gcmono(struct isp_ic_dev *dev);
int isp_disable_gcmono(struct isp_ic_dev *dev);
int isp_s_gcmono(struct isp_ic_dev *dev, struct isp_gcmono_data *data); /* set curve */
int isp_enable_rgbgamma(struct isp_ic_dev *dev);
int isp_disable_rgbgamma(struct isp_ic_dev *dev);
int isp_s_rgbgamma(struct isp_ic_dev *dev, struct isp_rgbgamma_data *data);
u32 isp_read_mi_irq(struct isp_ic_dev *dev);
void isp_reset_mi_irq(struct isp_ic_dev *dev, u32 icr);
int isp_ioc_cfg_dma(struct isp_ic_dev *dev, void __user *args);
int isp_ioc_start_dma_read(struct isp_ic_dev *dev, void __user *args);
int isp_mi_start(struct isp_ic_dev *dev);
int isp_mi_stop(struct isp_ic_dev *dev);
int isp_set_buffer(struct isp_ic_dev *dev, struct isp_buffer_context *buf);
int isp_set_bp_buffer(struct isp_ic_dev *dev,
struct isp_bp_buffer_context *buf);
int isp_enable_dmsc(struct isp_ic_dev *dev);
int isp_disable_dmsc(struct isp_ic_dev *dev);
int isp_set_dmsc_intp(struct isp_ic_dev *dev);
int isp_set_dmsc_skin(struct isp_ic_dev *dev);
int isp_set_dmsc_gfilter(struct isp_ic_dev *dev);
int isp_set_dmsc_depurple(struct isp_ic_dev *dev);
int isp_set_dmsc_cac(struct isp_ic_dev *dev);
int isp_set_dmsc_sharpen(struct isp_ic_dev *dev);
int isp_set_dmsc_sharpen_line(struct isp_ic_dev *dev);
int isp_set_dmsc_dmoi(struct isp_ic_dev *dev);
int isp_s_dmsc(struct isp_ic_dev *dev);
int isp_s_ge(struct isp_ic_dev *dev);
int isp_s_ca(struct isp_ic_dev *dev);
int isp_s_color_adjust(struct isp_ic_dev *dev);
int isp_config_dummy_hblank(struct isp_ic_dev *dev);
int isp_s_rgbir(struct isp_ic_dev *dev);
int isp_enable_rgbir(struct isp_ic_dev *dev);
int isp_rgbir_hw_init(struct isp_ic_dev *dev);
int isp_rgbir_s_ir_dnr(struct isp_ic_dev *dev);
int isp_rgbir_s_sharpen(struct isp_ic_dev *dev);
int isp_rgbir_s_des(struct isp_ic_dev *dev);
int isp_rgbir_s_cc_matrix(struct isp_ic_dev *dev);
int isp_rgbir_s_dpcc(struct isp_ic_dev *dev);
int isp_rgbir_s_gain(struct isp_ic_dev *dev);
int isp_rgbir_s_bls(struct isp_ic_dev *dev);
int isp_rgbir_out_ir_raw(struct isp_ic_dev *dev);
#ifdef ISP_3DNR_V3
int isp_tdnr_cfg_gamma(struct isp_ic_dev *dev);
int isp_s_tdnr(struct isp_ic_dev *dev);
int isp_tdnr_set_strength(struct isp_ic_dev *dev);
int isp_tdnr_set_motion(struct isp_ic_dev *dev);
int isp_tdnr_enable(struct isp_ic_dev *dev);
int isp_tdnr_disable(struct isp_ic_dev *dev);
int isp_tdnr_enable_tdnr(struct isp_ic_dev *dev);
int isp_tdnr_disable_tdnr(struct isp_ic_dev *dev);
int isp_tdnr_enable_2dnr(struct isp_ic_dev *dev);
int isp_tdnr_disable_2dnr(struct isp_ic_dev *dev);
int isp_tdnr_g_stats(struct isp_ic_dev *dev, struct isp_tdnr_stats *avg);
int isp_tdnr_u_noise(struct isp_ic_dev *dev);
int isp_r_tdnr_refer(struct isp_ic_dev *dev);
int isp_r_tdnr_motion(struct isp_ic_dev *dev);
int isp_tdnr_u_thr(struct isp_ic_dev *dev);
int isp_tdnr_s_buf(struct isp_ic_dev *dev);
#endif
#ifdef ISP_MI_PP_WRITE
int isp_set_ppw_line_num(struct isp_ic_dev *dev);
int isp_get_ppw_pic_cnt(struct isp_ic_dev *dev, u16* pic_cnt);
#endif
#ifdef ISP_MI_PP_READ
int isp_cfg_pp_dma_line_entry(struct isp_ic_dev *dev);
#endif
#ifdef __KERNEL__
int clean_dma_buffer(struct isp_ic_dev *dev);
irqreturn_t isp_hw_isr(int irq, void *data);
void isp_clear_interrupts(struct isp_ic_dev *dev);
#endif
/*get irq mis value from store array*/
u32 isp_read_mis(struct isp_ic_dev *dev, u32 irq_src);
int isp_ioc_read_mis(struct isp_ic_dev *dev, void __user *args);
/*set scaler*/
int isp_set_scaling(int id, struct isp_ic_dev *dev, bool stabilization, bool crop);
int isp_set_crop(struct isp_ic_dev *dev);
int isp_ioc_g_feature(struct isp_ic_dev *dev, void __user *args);
int isp_ioc_g_feature_veresion(struct isp_ic_dev *dev, void __user *args);
#endif /* _ISP_IOC_H_ */

239
vvcam/isp/isp_irq_queue.c Executable file
View File

@@ -0,0 +1,239 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/debugfs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#else
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#endif
#include "isp_irq_queue.h"
//enqueue
int isp_irq_enqueue(isp_mis_t *new,isp_mis_t* head)
{
#ifdef __KERNEL__
isp_mis_t* new_node = (isp_mis_t*)kmalloc(sizeof(isp_mis_t), GFP_KERNEL); //create new node
if (new == NULL || head == NULL) {
//printk("%s: input wrong parameter\n", __func__);
return -1;
}
new_node->val = new->val;
new_node->irq_src = new->irq_src;
/*printk("%s: new_node %px irq_src %d", __func__, new_node, new->irq_src);*/
INIT_LIST_HEAD(&new_node->list);
list_add_tail(&new_node->list, &head->list); //append to tail
#endif
return 0;
}
//dequeue && release memory
int isp_irq_dequeue(isp_mis_t* data, isp_mis_t* head)
{
#ifdef __KERNEL__
isp_mis_t* entry;
if (data == NULL || head == NULL) {
//printk("%s: input wrong parameter\n", __func__);
return -1;
}
if (list_empty(&head->list)) {
//printk("%s: There is no node\n", __func__);
return -1;
}
entry = list_first_entry(&head->list, isp_mis_t, list);
/*printk("%s: entry %px irq_src %d", __func__, entry, entry->irq_src);*/
data->val = entry->val;
data->irq_src = entry->irq_src;
list_del_init(&entry->list);
kfree(entry);
#endif
return 0;
}
bool isp_irq_is_queue_empty( isp_mis_t* head)
{
#ifdef __KERNEL__
return list_empty(&head->list);
#endif
return 0;
}
int isp_irq_create_circle_queue(isp_mis_list_t* pCList, int number)
{
#ifdef __KERNEL__
int i;
isp_mis_t* pMisNode;
if (pCList == NULL || number <= 0) {
printk("%s: create circle queue failed\n", __func__);
return -1;
}
if (pCList->pHead == NULL) {
pCList->pHead = (isp_mis_t*)kmalloc(sizeof(isp_mis_t), GFP_KERNEL);
INIT_LIST_HEAD(&pCList->pHead->list);
pCList->pRead = pCList->pHead;
pCList->pWrite = pCList->pHead;
}
printk("%s:pHead %px\n", __func__, pCList->pHead);
for (i = 0; i < number - 1; i++) {
pMisNode = (isp_mis_t*)kmalloc(sizeof(isp_mis_t), GFP_KERNEL);
INIT_LIST_HEAD(&pMisNode->list);
list_add_tail(&pMisNode->list, &pCList->pHead->list);
printk("%s:pMisNode %px\n", __func__, pMisNode);
}
#endif
return 0;
}
int isp_irq_destroy_circle_queue(isp_mis_list_t* pCList)
{
#ifdef __KERNEL__
isp_mis_t* pMisNode;
if ((pCList == NULL) || (pCList->pHead == NULL) ) {
printk("%s: destroy circle queue failed. pClist %px\n", __func__, pCList);
return -1;
}
while(!list_empty(&pCList->pHead->list)) {
pMisNode = list_first_entry(&pCList->pHead->list, isp_mis_t, list);
printk("%s:pMisNode %px\n", __func__, pMisNode);
list_del(&pMisNode->list);
kfree(pMisNode);
pMisNode = NULL;
}
printk("%s:pHead %px\n", __func__, pCList->pHead);
kfree(pCList->pHead);
pCList->pHead = NULL;
pCList->pRead = NULL;
pCList->pWrite = NULL;
#endif
return 0;
}
int isp_irq_read_circle_queue(isp_mis_t* data, isp_mis_list_t* pCList)
{
#ifdef __KERNEL__
//isp_mis_t* pReadEntry;
if (pCList == NULL) {
printk("%s: can not read circle queue\n", __func__);
return -1;
}
if (pCList->pRead == pCList->pWrite) {
/*printk("%s: There is no irq mis data\n", __func__);*/
return -1;
}
data->val = pCList->pRead->val;
data->irq_src = pCList->pRead->irq_src;
/*printk("%s: entry %px irq_src %d, msi %08x\n", __func__, pCList->pRead, data->irq_src, data->val);*/
/*Get the next entry that link with read entry list*/
/*Update read pointer to next entry*/
pCList->pRead = list_first_entry(&pCList->pRead->list, isp_mis_t, list);
//pCList->pRead = pReadEntry;
#endif
return 0;
}
int isp_irq_write_circle_queue(isp_mis_t* data, isp_mis_list_t* pCList)
{
#ifdef __KERNEL__
isp_mis_t* pWriteEntry;
if (pCList == NULL) {
printk("%s: can not read circle queue\n", __func__);
return -1;
}
pCList->pWrite->val = data->val;
pCList->pWrite->irq_src = data->irq_src;
/*printk("%s: entry %px irq_src %d, msi %08x\n", __func__, pCList->pWrite, data->irq_src, data->val);*/
/*get the next write entry pointer that link with the write entry list*/
pWriteEntry = list_first_entry(&pCList->pWrite->list, isp_mis_t, list);
/*Update write pointer to point next entry*/
pCList->pWrite = pWriteEntry;
#endif
return 0;
}

98
vvcam/isp/isp_irq_queue.h Executable file
View File

@@ -0,0 +1,98 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _ISP_IRQ_QUEUE_H_
#define _ISP_IRQ_QUEUE_H_
#ifdef __KERNEL__
#include <linux/list.h>
#endif
//#include "isp_ioctl.h"
typedef enum isp_src_e
{
SRC_ISP_IRQ = 0X0000,
SRC_JPE_STATUS_IRQ,
SRC_JPE_ERROR_IRQ,
SRC_MI_IRQ,
SRC_MI1_IRQ,
SRC_MI2_IRQ,
SRC_MIPI_IRQ,
SRC_IRQ_MAX,
} isp_src_t;
typedef struct isp_mis_s {
unsigned int irq_src;
unsigned int val;
#ifdef __KERNEL__
struct list_head list;
#endif
}isp_mis_t;
typedef struct isp_mis_list_s {
isp_mis_t* pHead;
isp_mis_t* pRead;
isp_mis_t* pWrite;
}isp_mis_list_t;
int isp_irq_enqueue(isp_mis_t *new,isp_mis_t* head);
int isp_irq_dequeue(isp_mis_t* data, isp_mis_t* head);
bool isp_irq_is_queue_empty( isp_mis_t* head);
#define QUEUE_NODE_COUNT 15
int isp_irq_create_circle_queue(isp_mis_list_t* pCList, int number);
int isp_irq_destroy_circle_queue(isp_mis_list_t* pCList);
int isp_irq_read_circle_queue(isp_mis_t* data, isp_mis_list_t* pCList);
int isp_irq_write_circle_queue(isp_mis_t* data, isp_mis_list_t* pCList);
#endif

279
vvcam/isp/isp_isr.c Executable file
View File

@@ -0,0 +1,279 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef ENABLE_IRQ
#include "isp_ioctl.h"
#include "isp_types.h"
#include "mrv_all_bits.h"
#include "video/vvbuf.h"
extern MrvAllRegister_t *all_regs;
#ifdef CONFIG_VIDEOBUF2_DMA_CONTIG
static int config_dma_buf(struct isp_mi_data_path_context *path,
dma_addr_t dma, struct isp_buffer_context *buf)
{
u32 size = path->out_width * path->out_height;
buf->addr_y = dma;
switch (path->out_mode) {
case IC_MI_DATAMODE_YUV444:
case IC_MI_DATAMODE_YUV422:
case IC_MI_DATAMODE_YUV420:
if (path->data_layout == IC_MI_DATASTORAGE_PLANAR) {
buf->size_y = size + ISP_BUF_GAP;
buf->addr_cb = buf->addr_y + size;
buf->size_cb = size + ISP_BUF_GAP;
buf->addr_cr = buf->addr_cb + size;
buf->size_cr = size + ISP_BUF_GAP;
} else if (path->data_layout ==
IC_MI_DATASTORAGE_SEMIPLANAR) {
buf->size_y = size + ISP_BUF_GAP;
buf->addr_cb = buf->addr_y + size;
if (path->out_mode == IC_MI_DATAMODE_YUV420)
buf->size_cb = (size >> 1) + ISP_BUF_GAP;
else
buf->size_cb = size + ISP_BUF_GAP;
} else if (path->data_layout ==
IC_MI_DATASTORAGE_INTERLEAVED) {
buf->size_y = (size << 1) + ISP_BUF_GAP;
} else
return -1;
break;
case IC_MI_DATAMODE_RAW8:
buf->size_y = size + ISP_BUF_GAP;
break;
case IC_MI_DATAMODE_RAW10:
case IC_MI_DATAMODE_RAW12:
buf->size_y = (size << 1) + ISP_BUF_GAP;
break;
default:
pr_err("unsupported out mode:%d\n", path->out_mode);
return -1;
}
#ifdef ISP_MP_34BIT
buf->addr_y >>= 2;
buf->addr_cb >>= 2;
buf->addr_cr >>= 2;
#endif
return 0;
}
#endif
static int update_dma_buffer(struct isp_ic_dev *dev)
{
#ifdef CONFIG_VIDEOBUF2_DMA_CONTIG
struct isp_mi_context *mi = &dev->mi;
struct vb2_dc_buf *buf = NULL;
struct isp_buffer_context dmabuf;
int i,dequeued;
for (i = 0; i < MI_PATH_NUM; ++i) {
if (!mi->path[i].enable)
continue;
if (dev->mi_buf[i]) {
vvbuf_ready(dev->bctx, dev->mi_buf[i]->pad,
dev->mi_buf[i]);
dev->mi_buf[i] = NULL;
}
if (dev->state && !(*dev->state & STATE_DRIVER_STARTED))
continue;
dequeued = 1;
buf = vvbuf_try_dqbuf(dev->bctx);
if (!buf) {
buf = dev->mi_buf_shd[i];
if (!buf)
return -ENOMEM;
dev->mi_buf_shd[i] = NULL;
dequeued = 0;
} else if (dev->mi_buf_shd[i]) {
dev->mi_buf[i] = dev->mi_buf_shd[i];
dev->mi_buf_shd[i] = NULL;
}
memset(&dmabuf, 0, sizeof(dmabuf));
dmabuf.path = i;
if (config_dma_buf(&mi->path[i], buf->dma, &dmabuf))
continue;
isp_set_buffer(dev, &dmabuf);
dev->mi_buf_shd[i] = buf;
if (dequeued)
vvbuf_try_dqbuf_done(dev->bctx, buf);
}
#endif
return 0;
}
int clean_dma_buffer(struct isp_ic_dev *dev)
{
#ifdef CONFIG_VIDEOBUF2_DMA_CONTIG
int i;
if (!dev->free)
return 0;
dev->free(dev, NULL);
for (i = 0; i < MI_PATH_NUM; ++i) {
if (dev->mi_buf[i]) {
dev->free(dev, dev->mi_buf[i]);
dev->mi_buf[i] = NULL;
}
if (dev->mi_buf_shd[i]) {
dev->free(dev, dev->mi_buf_shd[i]);
dev->mi_buf_shd[i] = NULL;
}
}
#endif
return 0;
}
void isp_clear_interrupts(struct isp_ic_dev *dev)
{
u32 isp_mis, mi_mis;
isp_mis = isp_read_reg(dev, REG_ADDR(isp_mis));
isp_write_reg(dev, REG_ADDR(isp_icr), isp_mis);
#ifdef ISP_MIV1
mi_mis = isp_read_reg(dev, REG_ADDR(mi_mis));
isp_write_reg(dev, REG_ADDR(mi_icr), mi_mis);
#elif defined(ISP_MIV2)
mi_mis = isp_read_reg(dev, REG_ADDR(miv2_mis));
isp_write_reg(dev, REG_ADDR(miv2_icr), mi_mis);
#else
mi_mis = 0;
#endif
}
irqreturn_t isp_hw_isr(int irq, void *data)
{
struct isp_ic_dev *dev = (struct isp_ic_dev *)data;
static const u32 frameendmask = MRV_MI_MP_FRAME_END_MASK |
#ifdef ISP_MI_BP
MRV_MI_BP_FRAME_END_MASK |
#endif
MRV_MI_SP_FRAME_END_MASK;
static const u32 errormask = MRV_MI_WRAP_MP_Y_MASK |
MRV_MI_WRAP_MP_CB_MASK |
MRV_MI_WRAP_MP_CR_MASK |
#ifdef ISP_MI_BP
MRV_MI_BP_WRAP_R_MASK |
MRV_MI_BP_WRAP_GR_MASK |
MRV_MI_BP_WRAP_GB_MASK |
MRV_MI_BP_WRAP_B_MASK |
#endif
MRV_MI_WRAP_SP_Y_MASK |
MRV_MI_WRAP_SP_CB_MASK |
MRV_MI_WRAP_SP_CR_MASK |
MRV_MI_FILL_MP_Y_MASK;
static const u32 fifofullmask = MRV_MI_MP_Y_FIFO_FULL_MASK |
MRV_MI_MP_CB_FIFO_FULL_MASK |
MRV_MI_MP_CR_FIFO_FULL_MASK |
MRV_MI_SP_Y_FIFO_FULL_MASK |
MRV_MI_SP_CB_FIFO_FULL_MASK |
MRV_MI_SP_CR_FIFO_FULL_MASK;
u32 isp_mis, mi_mis, mi_status;
struct isp_irq_data irq_data;
int rc = 0;
if (!dev)
return IRQ_HANDLED;
isp_mis = isp_read_reg(dev, REG_ADDR(isp_mis));
isp_write_reg(dev, REG_ADDR(isp_icr), isp_mis);
#ifdef ISP_MIV1
mi_mis = isp_read_reg(dev, REG_ADDR(mi_mis));
isp_write_reg(dev, REG_ADDR(mi_icr), mi_mis);
#elif defined(ISP_MIV2)
mi_mis = isp_read_reg(dev, REG_ADDR(miv2_mis));
isp_write_reg(dev, REG_ADDR(miv2_icr), mi_mis);
#else
mi_mis = 0;
#endif
mi_status = isp_read_reg(dev, REG_ADDR(mi_status));
if (mi_status & fifofullmask) {
isp_write_reg(dev, REG_ADDR(mi_status), mi_status);
pr_debug("MI FIFO full: 0x%x\n", mi_status);
}
if (mi_mis & errormask)
pr_debug("MI mis error: 0x%x\n", mi_mis);
if (mi_mis & frameendmask)
rc = update_dma_buffer(dev);
if (isp_mis) {
if(isp_mis & MRV_ISP_MIS_FRAME_MASK) {
if (dev->isp_update_flag & ISP_FLT_UPDATE) {
isp_s_flt(dev);
dev->isp_update_flag &= (~ISP_FLT_UPDATE);
}
if (dev->gamma_out.changed) {
isp_s_gamma_out(dev);
}
}
memset(&irq_data, 0, sizeof(irq_data));
irq_data.val = isp_mis;
if (dev->post_event)
dev->post_event(dev, &irq_data, sizeof(irq_data));
}
return IRQ_HANDLED;
}
#endif

626
vvcam/isp/isp_miv1.c Executable file
View File

@@ -0,0 +1,626 @@
/****************************************************************************
*
* 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

1213
vvcam/isp/isp_miv2.c Executable file

File diff suppressed because it is too large Load Diff

216
vvcam/isp/isp_rgbgamma.c Executable file
View File

@@ -0,0 +1,216 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#else
#endif
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
extern MrvAllRegister_t *all_regs;
int isp_enable_rgbgamma(struct isp_ic_dev *dev)
{
#ifndef ISP_RGBGC
pr_err("unsupported function %s\n", __func__);
return -1;
#else
u32 isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, ISP_RGBGC_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
dev->rgbgamma.enable = true;
return 0;
#endif
}
int isp_disable_rgbgamma(struct isp_ic_dev *dev)
{
#ifndef ISP_RGBGC
pr_err("unsupported function %s\n", __func__);
return -1;
#else
u32 isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, ISP_RGBGC_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
dev->rgbgamma.enable = false;
return 0;
#endif
}
#ifdef ISP_RGBGC
static int isp_s_rgbgammapx(struct isp_ic_dev *dev, struct isp_rgbgamma_data *data)
{
u32 isp_gc_px_reg = REG_ADDR(isp_gcrgb_r_px_0);
u32 *p_table = NULL;
int i;
u32 gc_px_data = 0;
p_table = (u32 *)&data->rgbgc_r_px;
for (i = 0; i < 64; i++) {
gc_px_data |= (*(p_table + i) << (i % 6 * 5));
if (i % 6 == 5 || i == 63) {
isp_write_reg(dev, isp_gc_px_reg, gc_px_data);
isp_gc_px_reg += 4;
gc_px_data = 0;
}
}
isp_gc_px_reg = REG_ADDR(isp_gcrgb_g_px_0);
p_table = (u32 *)&data->rgbgc_g_px;
for (i = 0; i < 64; i++) {
gc_px_data |= (*(p_table + i) << (i % 6 * 5));
if (i % 6 == 5 || i == 63) {
isp_write_reg(dev, isp_gc_px_reg, gc_px_data);
isp_gc_px_reg += 4;
gc_px_data = 0;
}
}
isp_gc_px_reg = REG_ADDR(isp_gcrgb_b_px_0);
p_table = (u32 *)&data->rgbgc_b_px;
for (i = 0; i < 64; i++) {
gc_px_data |= (*(p_table + i) << (i % 6 * 5));
if (i % 6 == 5 || i == 63) {
isp_write_reg(dev, isp_gc_px_reg, gc_px_data);
isp_gc_px_reg += 4;
gc_px_data = 0;
}
}
return 0;
}
#endif
#ifdef ISP_RGBGC
static int isp_s_rgbgammaWriteData(struct isp_ic_dev *dev,
struct isp_rgbgamma_data *data)
{
u32 isp_gc_y_data, isp_gc_x_data;
int i;
u32 *tblX, *tblY;
isp_write_reg(dev, REG_ADDR(isp_gcrgb_r_x_addr), 0);
isp_write_reg(dev, REG_ADDR(isp_gcrgb_r_y_addr), 0);
isp_write_reg(dev, REG_ADDR(isp_gcrgb_g_x_addr), 0);
isp_write_reg(dev, REG_ADDR(isp_gcrgb_g_y_addr), 0);
isp_write_reg(dev, REG_ADDR(isp_gcrgb_b_x_addr), 0);
isp_write_reg(dev, REG_ADDR(isp_gcrgb_b_y_addr), 0);
tblX = data->rgbgc_r_datax;
tblY = data->rgbgc_r_datay;
for (i = 0; i < 64; i++) {
isp_gc_y_data = *(tblY + i);
isp_write_reg(dev, REG_ADDR(isp_gcrgb_r_y_write_data),
isp_gc_y_data);
}
for (i = 0; i < 63; i++) {
isp_gc_x_data = *(tblX + i);
isp_write_reg(dev, REG_ADDR(isp_gcrgb_r_x_write_data),
isp_gc_x_data);
}
tblX = data->rgbgc_g_datax;
tblY = data->rgbgc_g_datay;
for (i = 0; i < 64; i++) {
isp_gc_y_data = *(tblY + i);
isp_write_reg(dev, REG_ADDR(isp_gcrgb_g_y_write_data),
isp_gc_y_data);
}
for (i = 0; i < 63; i++) {
isp_gc_x_data = *(tblX + i);
isp_write_reg(dev, REG_ADDR(isp_gcrgb_g_x_write_data),
isp_gc_x_data);
}
tblX = data->rgbgc_b_datax;
tblY = data->rgbgc_b_datay;
for (i = 0; i < 64; i++) {
isp_gc_y_data = *(tblY + i);
isp_write_reg(dev, REG_ADDR(isp_gcrgb_b_y_write_data),
isp_gc_y_data);
}
for (i = 0; i < 63; i++) {
isp_gc_x_data = *(tblX + i);
isp_write_reg(dev, REG_ADDR(isp_gcrgb_b_x_write_data),
isp_gc_x_data);
}
return 0;
}
#endif
int isp_s_rgbgamma(struct isp_ic_dev *dev, struct isp_rgbgamma_data *data)
{
#ifndef ISP_RGBGC
pr_err("unsupported function %s", __func__);
return -1;
#else
u8 ret;
u32 isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, ISP_RGBGC_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
isp_s_rgbgammapx(dev, data);
isp_s_rgbgammaWriteData(dev, data);
ret = 0;
if (dev->rgbgamma.enable) {
ret = isp_enable_rgbgamma(dev);
}
return ret;
#endif
}

401
vvcam/isp/isp_rgbir.c Executable file
View File

@@ -0,0 +1,401 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#endif
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
extern MrvAllRegister_t *all_regs;
enum {
ISP_RGBIR_OUT_BAT_RGGB = 0,
ISP_RGBIR_OUT_BAT_GRBG,
ISP_RGBIR_OUT_BAT_GBRG,
ISP_RGBIR_OUT_BAT_BGGR
};
enum {
ISP_RGBIR_BAT_BGGIR = 0,
ISP_RGBIR_BAT_GRIRG,
ISP_RGBIR_BAT_RGGIR,
ISP_RGBIR_BAT_GBIRG,
ISP_RGBIR_BAT_GIRRG,
ISP_RGBIR_BAT_IRGGB,
ISP_RGBIR_BAT_GIRBG,
ISP_RGBIR_BAT_IRGGR,
ISP_RGBIR_BAT_RGIRB,
ISP_RGBIR_BAT_GRBIR,
ISP_RGBIR_BAT_IRBRG,
ISP_RGBIR_BAT_BIRGR,
ISP_RGBIR_BAT_BGIRR,
ISP_RGBIR_BAT_GBRIR,
ISP_RGBIR_BAT_IRRBG,
ISP_RGBIR_BAT_RIRGB,
};
int isp_rgbir_s_bls(struct isp_ic_dev *dev)
{
#ifndef ISP_RGBIR
isp_err("unsupported function %s", __func__);
return -1;
#else
struct isp_rgbir_context rgbir = *(&dev->rgbir);
struct isp_rgbir_bls_context* bls = &rgbir.bls;
isp_info("enter %s\n", __func__);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_bls_a), bls->a);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_bls_b), bls->b);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_bls_c), bls->c);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_bls_d), bls->d);
return 0;
#endif
}
int isp_rgbir_s_gain(struct isp_ic_dev *dev)
{
#ifndef ISP_RGBIR
isp_err("unsupported function %s", __func__);
return -1;
#else
struct isp_rgbir_context rgbir = *(&dev->rgbir);
struct isp_rgbir_rgb_gain_context* rgb_gain = &rgbir.rgb_gain;
isp_info("enter %s\n", __func__);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_gain_r), rgb_gain->r);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_gain_g), rgb_gain->g);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_gain_b), rgb_gain->b);
return 0;
#endif
}
int isp_rgbir_s_dpcc(struct isp_ic_dev *dev)
{
#ifndef ISP_RGBIR
isp_err("unsupported function %s", __func__);
return -1;
#else
struct isp_rgbir_dpcc_context *dpcc = &dev->rgbir.dpcc;
int i;
u32 isp_pre_filt_dpc_th_r;
isp_info("enter %s\n", __func__);
for (i = 0; i < 4; i++) {
isp_pre_filt_dpc_th_r = isp_read_reg(dev, REG_ADDR(isp_pre_filt_dpc_th_r) + i * ISP_REG_GAP);
REG_SET_SLICE(isp_pre_filt_dpc_th_r, ISP_PRE_FILT_DPC_TH_MED_R, dpcc->median_thr[i]);
REG_SET_SLICE(isp_pre_filt_dpc_th_r, ISP_PRE_FILT_DPC_TH_AVG_R, dpcc->avg_thr[i]);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_dpc_th_r) + i * ISP_REG_GAP, isp_pre_filt_dpc_th_r);
}
return 0;
#endif
}
int isp_rgbir_s_cc_matrix(struct isp_ic_dev *dev)
{
#ifndef ISP_RGBIR
isp_err("unsupported function %s", __func__);
return -1;
#else
struct isp_rgbir_cc_context *cc = &dev->rgbir.cc; //cc color correct
int i;
const u8 reg_gap = 8;
u32 isp_pre_filt_cc_00_01;
isp_info("enter %s\n", __func__);
for (i = 0; i < 3; i++) {
isp_pre_filt_cc_00_01 = isp_read_reg(dev, REG_ADDR(isp_pre_filt_cc_00_01) + i * reg_gap);
REG_SET_SLICE(isp_pre_filt_cc_00_01, ISP_PRE_FILT_CC_00, (u32)(cc->mtx[i][0] ));
REG_SET_SLICE(isp_pre_filt_cc_00_01, ISP_PRE_FILT_CC_01, (u32)(cc->mtx[i][1] ));
isp_write_reg(dev, REG_ADDR(isp_pre_filt_cc_00_01) + i * reg_gap, isp_pre_filt_cc_00_01);
isp_pre_filt_cc_00_01 = isp_read_reg(dev, REG_ADDR(isp_pre_filt_cc_00_01) + i * reg_gap + ISP_REG_GAP);
REG_SET_SLICE(isp_pre_filt_cc_00_01, ISP_PRE_FILT_CC_02, (u32)(cc->mtx[i][2] ));
REG_SET_SLICE(isp_pre_filt_cc_00_01, ISP_PRE_FILT_CC_03, (u32)(cc->mtx[i][3] ));
isp_write_reg(dev, REG_ADDR(isp_pre_filt_cc_00_01) + (i * reg_gap) + ISP_REG_GAP, isp_pre_filt_cc_00_01);
}
return 0;
#endif
}
int isp_rgbir_s_des(struct isp_ic_dev *dev) //de-saturation
{
#ifndef ISP_RGBIR
isp_err("unsupported function %s", __func__);
return -1;
#else
struct isp_rgbir_des_context *des = &dev->rgbir.des; //cc color correct
int i;
u32 isp_pre_filt_ir_des_pd1; // isp_pre_filt_ir_des_px1, isp_pre_filt_ir_des_py1;
u32 isp_pre_filt_l_des_pd1; // isp_pre_filt_l_des_px1, isp_pre_filt_l_des_py1;
isp_info("enter %s\n", __func__);
//register value
for (i = 0 ; i < 4; i++) {
isp_pre_filt_ir_des_pd1 = isp_read_reg(dev, REG_ADDR(isp_pre_filt_ir_des_pd1) + i * ISP_REG_GAP);
if (i != 3) {
isp_pre_filt_ir_des_pd1 = des->ir_pd[i *4] | des->ir_pd[i *4 + 1] << 8 | des->ir_pd[i * 4 + 2] << 16 |\
des->ir_pd[i*4 + 3] << 24;
} else {
isp_pre_filt_ir_des_pd1 = des->ir_pd[i *4] | des->ir_pd[i *4 + 1] << 8 | des->ir_pd[i*4 + 2] << 16;
}
isp_write_reg(dev, REG_ADDR(isp_pre_filt_ir_des_pd1) + i * ISP_REG_GAP, isp_pre_filt_ir_des_pd1);
}
isp_write_reg(dev, REG_ADDR(isp_pre_filt_ir_des_px1), (des->ir_px1 & 0xffff));
for (i = 0; i < 8; i++)
{
isp_write_reg(dev, REG_ADDR(isp_pre_filt_ir_des_py1) + i * ISP_REG_GAP, des->ir_py[i]);
}
for (i = 0 ; i < 4; i++) {
isp_pre_filt_l_des_pd1 = isp_read_reg(dev, REG_ADDR(isp_pre_filt_l_des_pd1) + i * ISP_REG_GAP);
if (i != 3) {
isp_pre_filt_l_des_pd1 = des->l_pd[i *4] | des->l_pd[i*4 + 1] << 8 | des->l_pd[i*4 + 2] << 16 |\
des->l_pd[i*4 + 3] << 24;
} else {
isp_pre_filt_l_des_pd1 = des->l_pd[i *4] | des->l_pd[i*4 + 1] << 8 | des->l_pd[i*4+2] << 16;
}
isp_write_reg(dev, REG_ADDR(isp_pre_filt_l_des_pd1) + i * ISP_REG_GAP, isp_pre_filt_l_des_pd1);
}
isp_write_reg(dev, REG_ADDR(isp_pre_filt_l_des_px1), (des->l_px1 & 0xffff));
for ( i = 0; i < 8; i++)
{
isp_write_reg(dev, REG_ADDR(isp_pre_filt_l_des_py1) + i * 4, des->l_py[i]);
}
return 0;
#endif
}
int isp_rgbir_s_sharpen(struct isp_ic_dev *dev)
{
#ifndef ISP_RGBIR
isp_err("unsupported function %s", __func__);
return -1;
#else
struct isp_rgbir_sharpen_context *sharpen = &dev->rgbir.sharpen;
u8 sharpl = sharpen->sharpen_lvl;
u32 isp_pre_filt_lum_weight; // isp_pre_filt_thresh_sh0, isp_pre_filt_thresh_sh1;
// u32 isp_pre_filt_thresh_bl0, isp_pre_filt_thresh_bl1;
// u32 isp_pre_filt_fac_sh0, isp_pre_filt_fac_sh1, isp_pre_filt_fac_mid;
// u32 isp_pre_filt_fac_bl0, isp_pre_filt_fac_bl1;
const unsigned int sharplevel[5][11] = {
{ 0x4, 0x08, 0x0C, 0x10, 0x16, 0x1B, 0x20, 0x26, 0x2C, 0x30, 0x3F },
{ 0x4, 0x07, 0x0A, 0x0C, 0x10, 0x14, 0x1A, 0x1E, 0x24, 0x2A, 0x30 },
{ 0x4, 0x06, 0x08, 0x0A, 0x0C, 0x10, 0x13, 0x17, 0x1D, 0x22, 0x28 },
{ 0x2, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x10, 0x15, 0x1A, 0x24 },
{ 0x0, 0x00, 0x00, 0x02, 0x04, 0x04, 0x06, 0x08, 0x0D, 0x14, 0x20 } };
isp_info("enter %s\n", __func__);
//filter factor sharp
isp_pre_filt_lum_weight = isp_read_reg(dev, REG_ADDR(isp_pre_filt_lum_weight));
REG_SET_SLICE(isp_pre_filt_lum_weight, LUM_WEIGHT_GAIN, sharpen->lum_weight_gain);
REG_SET_SLICE(isp_pre_filt_lum_weight, LUM_WEIGHT_KINK, sharpen->lum_weight_kink);
REG_SET_SLICE(isp_pre_filt_lum_weight, LUM_WEIGHT_MIN, sharpen->lum_weight_min);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_lum_weight), isp_pre_filt_lum_weight);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_fac_mid), sharpen->middle);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_thresh_sh0), sharpen->thresh_sh0);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_thresh_sh1), sharpen->thresh_sh1);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_thresh_bl0), sharpen->thresh_bl0);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_thresh_bl1), sharpen->thresh_bl1);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_fac_sh1), (unsigned int)(sharplevel[0][sharpl]));
isp_write_reg(dev, REG_ADDR(isp_pre_filt_fac_sh0), (unsigned int)(sharplevel[1][sharpl]));
isp_write_reg(dev, REG_ADDR(isp_pre_filt_fac_mid), (unsigned int)(sharplevel[2][sharpl]));
isp_write_reg(dev, REG_ADDR(isp_pre_filt_fac_bl0), (unsigned int)(sharplevel[3][sharpl]));
isp_write_reg(dev, REG_ADDR(isp_pre_filt_fac_bl1), (unsigned int)(sharplevel[4][sharpl]));
return 0;
#endif
}
int isp_rgbir_s_ir_dnr(struct isp_ic_dev *dev)
{
#ifndef ISP_RGBIR
isp_err("unsupported function %s", __func__);
return -1;
#else
struct isp_rgbir_ir_dnr_context* ir_dnr = &dev->rgbir.ir_dnr;
//u16 imgwidth, imgheight;
u32 ir_denoise_reg_03;
u32 ir_denoise_reg_45;
ir_denoise_reg_03 = (ir_dnr->winweight[0] | (ir_dnr->winweight[1] << 8) | (ir_dnr->winweight[2] << 16) | (ir_dnr->winweight[3] << 24));
ir_denoise_reg_45 = (ir_dnr->winweight[4] | (ir_dnr->winweight[5] << 8));
isp_write_reg(dev, REG_ADDR(isp_pre_filt_ir_denoise_sw_03), (unsigned int)(ir_denoise_reg_03));
isp_write_reg(dev, REG_ADDR(isp_pre_filt_ir_denoise_sw_45), ((unsigned int)(ir_denoise_reg_45) & 0xffff));
//imgwidth = isp_read_reg(dev, REG_ADDR(isp_out_h_size));
//imgheight = isp_read_reg(dev, REG_ADDR(isp_out_v_size));
isp_write_reg(dev, REG_ADDR(isp_pre_filt_h_size), ir_dnr->width& 0x7fff);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_v_size), ir_dnr->height & 0x3fff);
return 0;
#endif
}
int isp_rgbir_hw_init(struct isp_ic_dev *dev)
{
#ifndef ISP_RGBIR
isp_err("unsupported function %s", __func__);
return -1;
#else
u32 isp_pre_filt_ctrl;
struct isp_rgbir_context *rgbir = &dev->rgbir;
isp_info("enter %s\n", __func__);
isp_rgbir_s_cc_matrix(dev);
isp_rgbir_s_bls(dev);
isp_rgbir_s_dpcc(dev);
isp_rgbir_s_des(dev);
isp_rgbir_s_gain(dev);
isp_rgbir_s_ir_dnr(dev);
isp_rgbir_s_sharpen(dev);
isp_pre_filt_ctrl = isp_read_reg(dev, REG_ADDR(isp_pre_filt_ctrl));//pre filt ctrl
REG_SET_SLICE(isp_pre_filt_ctrl , ISP_PRE_FILT_ENABLE, rgbir->prefilt_enable);
REG_SET_SLICE(isp_pre_filt_ctrl , GREEN_FILT_MODE, rgbir->green_filt_mode);
REG_SET_SLICE(isp_pre_filt_ctrl , GREEN_FILT_ENABLE, rgbir->green_filt_enable);
REG_SET_SLICE(isp_pre_filt_ctrl , RGBIR_BAYER_PATTERN, rgbir->rgbirPattern );
REG_SET_SLICE(isp_pre_filt_ctrl , OUT_RGB_BAYER_PATTERN, rgbir->out_rgb_pattern);
REG_SET_SLICE(isp_pre_filt_ctrl , STAGE1_SELECT, rgbir->green_filt_stage1_select);
REG_SET_SLICE(isp_pre_filt_ctrl , DEMOSAIC_THRESHOLD, rgbir->demosaic_threshold);
REG_SET_SLICE(isp_pre_filt_ctrl , PART_ONE_ENABLE, rgbir->part1_enable);
REG_SET_SLICE(isp_pre_filt_ctrl , PART_TWO_ENABLE,rgbir->part2_enable);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_ctrl), (unsigned int)(isp_pre_filt_ctrl));//pre filt ctrl
return 0;
#endif
}
int isp_enable_rgbir(struct isp_ic_dev *dev)
{
#ifndef ISP_RGBIR
isp_err("unsupported function %s", __func__);
return -1;
#else
struct isp_rgbir_context *rgbir = &dev->rgbir;
u32 isp_pre_filt_ctrl;
isp_info("enter %s\n", __func__);
isp_pre_filt_ctrl = isp_read_reg(dev, REG_ADDR(isp_pre_filt_ctrl));//pre filt ctrl
REG_SET_SLICE(isp_pre_filt_ctrl , ISP_PRE_FILT_ENABLE, rgbir->prefilt_enable);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_ctrl), isp_pre_filt_ctrl);//pre filt ctrl
return 0;
#endif
}
int isp_rgbir_out_ir_raw(struct isp_ic_dev *dev)
{
#ifndef ISP_RGBIR
isp_err("unsupported function %s", __func__);
return -1;
#else
struct isp_rgbir_context *rgbir = &dev->rgbir;
u32 isp_ctrl;
isp_info("enter %s\n", __func__);
isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));//isp ctrl
REG_SET_SLICE(isp_ctrl , ISP_IR_RAW_OUT, rgbir->enable_ir_raw_out);
REG_SET_SLICE(isp_ctrl , MRV_ISP_ISP_MODE, MRV_ISP_ISP_MODE_RGB); //there need to config rgb mode.
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);//isp_ctrl
return 0;
#endif
}
int isp_s_rgbir(struct isp_ic_dev *dev)
{
#ifndef ISP_WDR_V4
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
struct isp_rgbir_context *rgbir = &dev->rgbir;
u32 isp_pre_filt_ctrl;
isp_info("enter %s\n", __func__);
isp_rgbir_s_cc_matrix(dev);
isp_rgbir_s_bls(dev);
isp_rgbir_s_dpcc(dev);
isp_rgbir_s_des(dev);
isp_rgbir_s_gain(dev);
isp_rgbir_s_ir_dnr(dev);
isp_rgbir_s_sharpen(dev);
isp_pre_filt_ctrl = isp_read_reg(dev, REG_ADDR(isp_pre_filt_ctrl));//pre filt ctrl
REG_SET_SLICE(isp_pre_filt_ctrl , ISP_PRE_FILT_ENABLE, rgbir->prefilt_enable);
REG_SET_SLICE(isp_pre_filt_ctrl , GREEN_FILT_MODE, rgbir->green_filt_mode);
REG_SET_SLICE(isp_pre_filt_ctrl , GREEN_FILT_ENABLE, rgbir->green_filt_enable);
REG_SET_SLICE(isp_pre_filt_ctrl , RGBIR_BAYER_PATTERN, rgbir->rgbirPattern );
REG_SET_SLICE(isp_pre_filt_ctrl , OUT_RGB_BAYER_PATTERN, rgbir->out_rgb_pattern);
REG_SET_SLICE(isp_pre_filt_ctrl , STAGE1_SELECT, rgbir->green_filt_stage1_select);
REG_SET_SLICE(isp_pre_filt_ctrl , DEMOSAIC_THRESHOLD, rgbir->demosaic_threshold);
REG_SET_SLICE(isp_pre_filt_ctrl , PART_ONE_ENABLE, rgbir->part1_enable);
REG_SET_SLICE(isp_pre_filt_ctrl , PART_TWO_ENABLE,rgbir->part2_enable);
isp_write_reg(dev, REG_ADDR(isp_pre_filt_ctrl), (unsigned int)(isp_pre_filt_ctrl));//pre filt ctrl
return 0;
#endif
}

646
vvcam/isp/isp_tdnr3.c Executable file
View File

@@ -0,0 +1,646 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#endif
#include "isp_ioctl.h"
#include "mrv_all_bits.h"
#include "isp_types.h"
#ifdef ISP_3DNR_V3
extern MrvAllRegister_t *all_regs;
int isp_tdnr_cfg_gamma(struct isp_ic_dev *dev)
{
//write to regs
struct isp_tdnr_context *tdnr = &dev->tdnr;
u32 regVal;
u8 bit_width;
u8 i;
u16 val_a, val_b;
//const u8 tdnrRegGap = 8;
bit_width = 12;
//pr_info("enter %s\n", __func__);
for (i = 0; i < DENOISE3D_GAMMA_BIN - 3; i += 5)
{
val_a = tdnr->curve.preGamma_y[i + 2] >> 6; val_b = tdnr->curve.preGamma_y[i + 2] & 0x3f;
regVal = (val_a << 24) | ((tdnr->curve.preGamma_y[i + 1] & 0xfff) << bit_width) | (tdnr->curve.preGamma_y[i] & 0xfff);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_pregamma_y_0) + (i / 5) *8 , regVal);
regVal = (val_b << 24) | ((tdnr->curve.preGamma_y[i + 4] & 0xfff) << bit_width) | (tdnr->curve.preGamma_y[i + 3] & 0xfff);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_pregamma_y_1) + (i / 5 ) *8, regVal);
}
val_a = tdnr->curve.preGamma_y[i + 2] >> 6; val_b = tdnr->curve.preGamma_y[i + 2] & 0x3f;
regVal = (val_a << 24) | ((tdnr->curve.preGamma_y[i + 1] & 0xfff) << bit_width) | (tdnr->curve.preGamma_y[i] & 0xfff);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_pregamma_y_12), regVal);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_pregamma_y_13), val_b);
i = 0;
for (i = 0; i < DENOISE3D_GAMMA_BIN - 3; i += 5)
{
val_a = tdnr->curve.invGamma_y[i + 2] >> 6; val_b = tdnr->curve.invGamma_y[i + 2] & 0x3f;
regVal = (val_a << 24) | ((tdnr->curve.invGamma_y[i + 1] & 0xfff) << bit_width) | (tdnr->curve.invGamma_y[i] & 0xfff);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_invgamma_y_0) + (i / 5) *8 , regVal);
regVal = (val_b << 24) | ((tdnr->curve.invGamma_y[i + 4] & 0xfff) << bit_width) | (tdnr->curve.invGamma_y[i + 3] & 0xfff);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_invgamma_y_1) + (i / 5) *8 , regVal);
}
val_a = tdnr->curve.invGamma_y[i + 2] >> 6; val_b = tdnr->curve.invGamma_y[i + 2] & 0x3f;
regVal = (val_a << 24) | ((tdnr->curve.invGamma_y[i + 1] & 0xfff) << bit_width) | (tdnr->curve.invGamma_y[i] & 0xfff);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_invgamma_y_12), regVal);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_invgamma_y_13), val_b);
return 0;
}
int isp_s_tdnr(struct isp_ic_dev *dev)
{
u32 isp_denoise3d2_ctrl;
struct isp_tdnr_context *tdnr = &dev->tdnr;
u32 regVal = 0;
/* spacial */
u32 strength = tdnr->strength;
//pr_info("enter %s\n", __func__);
strength = MIN(MAX(strength, 0), 128);
isp_denoise3d2_ctrl = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_ctrl));
#if 0
if (!tdnr->enable) {
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_ctrl), isp_denoise3d2_ctrl);
return 0;
}
#endif
#if 1
if (dev->tdnr.enable_tnr) {
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_strength), strength);
} else {
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_strength), 0);
if (dev->tdnr.frames == 2)
return 0 ;
}
#endif
//isp_write_reg(dev, REG_ADDR(isp_denoise3d2_strength), strength);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_V20_NOISE_LEVEL, tdnr->noise_level);
REG_SET_SLICE(regVal, DENOISE3D_V20_NOISE_MEAN, tdnr->noise_mean);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_noise), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_V20_NOISE_LEVEL, tdnr->noise_threshold);
REG_SET_SLICE(regVal, DENOISE3D_V20_NOISE_MEAN, tdnr->motion_mean);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_motion), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_V20_TNR_RANGE_H, tdnr->range_h);
REG_SET_SLICE(regVal, DENOISE3D_V20_TNR_RANGE_V, tdnr->range_v);
REG_SET_SLICE(regVal, DENOISE3D_V20_TNR_DILATE_RANGE_H, tdnr->dilate_range_h);
REG_SET_SLICE(regVal, DENOISE3D_V20_TNR_DILATE_RANGE_V, tdnr->dilate_range_v);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_range), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_V20_MOTION_INV, tdnr->motion_inv_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_motion_inv), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_V20_THR_UPDATE, tdnr->update_factor);
REG_SET_SLICE(regVal, DENOISE3D_V20_MOTION_THR_UPDATE, tdnr->motion_update_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_update), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_V20_MOTION_PRE_WEIGHT, tdnr->pre_motion_weight);
REG_SET_SLICE(regVal, DENOISE3D_V20_MOTION_SLOPE, tdnr->motion_slope);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_tnr), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_V20_MOTION_CONV_SHIFT, tdnr->motion_converage_shift);
REG_SET_SLICE(regVal, DENOISE3D_V20_MOTION_CONV_MAX, tdnr->motion_converage_max);
REG_SET_SLICE(regVal, DENOISE3D_V20_TNR_VAL_SHIFT_BIT, tdnr->tnr_val_shift_bit);
REG_SET_SLICE(regVal, DENOISE3D_V20_TNR_DIFF_NORM_SHIFT_BIT, tdnr->tnr_diff_shift_bit);
REG_SET_SLICE(regVal, DENOISE3D_V20_SAD_WEIGHT, tdnr->sad_weight);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_shift), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_V20_PIXEL_VAL_SHIFT, tdnr->luma_pixel_val_shift);
REG_SET_SLICE(regVal, DENOISE3D_V20_PIXEL_SLOP, tdnr->luma_pixel_slope);
REG_SET_SLICE(regVal, DENOISE3D_V20_PIXEL_SLOP_SHIFT_BIT, tdnr->luma_pixel_slope_shift);
REG_SET_SLICE(regVal, DENOISE3D_V20_PIXEL_SLOP_MIN, tdnr->luma_pixel_slope_min);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_luma), regVal);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_dummy_hblank), 0x63);
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_INVGAMMA_EN, tdnr->enable_inv_gamma);
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_PREGAMMA_EN, tdnr->enable_pre_gamma);
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_ERODE_EN, tdnr->enable_motion_erosion);
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_MOTION_CONV_EN, tdnr->enable_motion_converage);
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_INV_DGAIN_EN, 0);
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_INV_AWB_GAIN_EN, 1);
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_COMP_LUMA_EN, 0);
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_MOTION_DILATE_ENABLE, tdnr->enable_motion_dilation);
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_NLM_ENABLE, dev->tdnr.enable_2dnr);
//REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_NLM_ENABLE, 1);
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_TNR_ENABLE, dev->tdnr.enable_tnr);
if (!dev->tdnr.enable_tnr) {
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_REF_RESET, 1);
}
REG_SET_SLICE(isp_denoise3d2_ctrl, DENOISE3D_V20_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_ctrl), isp_denoise3d2_ctrl);
return 0;
}
int isp_tdnr_set_strength(struct isp_ic_dev *dev)
{
u32 isp_denoise3d2_strength;
struct isp_tdnr_context *tdnr = &dev->tdnr;
//pr_info("enter %s\n", __func__);
isp_denoise3d2_strength = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_strength));
REG_SET_SLICE(isp_denoise3d2_strength, DENOISE3D_V20_TNR_STRENGTH, tdnr->strength);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_strength), isp_denoise3d2_strength);
return 0;
}
int isp_tdnr_set_motion(struct isp_ic_dev *dev)
{
struct isp_tdnr_context *tdnr = &dev->tdnr;
u32 isp_denoise3d2_motion_inv;
pr_info("enter %s\n", __func__);
isp_denoise3d2_motion_inv = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_motion_inv));
REG_SET_SLICE(isp_denoise3d2_motion_inv, DENOISE3D_V20_MOTION_INV, tdnr->motion_inv_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_motion_inv), isp_denoise3d2_motion_inv);
return 0;
}
int isp_tdnr_enable(struct isp_ic_dev *dev)
{
u32 regVal = 0;
u32 strength = dev->tdnr.strength;
pr_info("enter %s\n", __func__);
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_ctrl));
REG_SET_SLICE(regVal, DENOISE3D_V20_ENABLE, 1);
// REG_SET_SLICE(regVal, DENOISE3D_V20_REF_RESET, 1);
REG_SET_SLICE(regVal, DENOISE3D_V20_TNR_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_ctrl), regVal);
strength = MIN(MAX(strength, 0), 128);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_strength), strength); //clear strength
dev->tdnr.enable = true;
return 0;
}
int isp_tdnr_disable(struct isp_ic_dev *dev)
{
u32 regVal = 0;
pr_info("enter %s\n", __func__);
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_ctrl));
// REG_SET_SLICE(regVal, DENOISE3D_V20_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_ctrl), regVal);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_strength), 0); //clear strength
dev->tdnr.enable = false;
return 0;
}
int isp_tdnr_enable_tdnr(struct isp_ic_dev *dev)
{
u32 regVal = 0;
pr_info("enter %s\n", __func__);
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_ctrl));
REG_SET_SLICE(regVal, DENOISE3D_V20_TNR_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_ctrl), regVal);
dev->tdnr.enable_tnr= true;
return 0;
}
int isp_tdnr_disable_tdnr(struct isp_ic_dev *dev)
{
u32 regVal = 0;
pr_info("enter %s\n", __func__);
regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_ctrl));
REG_SET_SLICE(regVal, DENOISE3D_V20_TNR_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_ctrl), regVal);
dev->tdnr.enable = false;
return 0;
}
int isp_tdnr_enable_2dnr(struct isp_ic_dev *dev)
{
//u32 regVal = 0;
pr_info("enter %s\n", __func__);
/*regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_ctrl));
REG_SET_SLICE(regVal, DENOISE3D_V20_NLM_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_ctrl), regVal);*/
dev->tdnr.enable_tnr= true;
return 0;
}
int isp_tdnr_disable_2dnr(struct isp_ic_dev *dev)
{
//u32 regVal = 0;
pr_info("enter %s\n", __func__);
/*regVal = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_ctrl));
REG_SET_SLICE(regVal, DENOISE3D_V20_NLM_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_ctrl), regVal);*/
dev->tdnr.enable = false;
return 0;
}
int isp_tdnr_g_stats(struct isp_ic_dev *dev, struct isp_tdnr_stats *stats)
{
//pr_info("enter %s\n", __func__);
if (!dev || !stats) {
return -EINVAL;
}
stats->bg_sum = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_bg_val_sum));
stats->motion_sum = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_mo_val_sum));
stats->bg_pixel_cnt = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_bg_cnt));
stats->motion_pixel_cnt = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_mo_cnt));
stats->frame_avg = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_frame_avg));
return 0;
}
int isp_tdnr_u_noise(struct isp_ic_dev *dev)
{
u32 regVal = 0;
struct isp_tdnr_context *tdnr = &dev->tdnr;
pr_info("enter %s\n", __func__);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_V20_NOISE_LEVEL, tdnr->noise_level);
REG_SET_SLICE(regVal, DENOISE3D_V20_NOISE_MEAN, tdnr->noise_mean);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_noise), regVal);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_V20_NOISE_LEVEL, tdnr->noise_threshold);
REG_SET_SLICE(regVal, DENOISE3D_V20_NOISE_MEAN, tdnr->motion_mean);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_motion), regVal);
return 0;
}
int isp_tdnr_u_thr(struct isp_ic_dev *dev)
{
u32 regVal = 0;
struct isp_tdnr_context *tdnr = &dev->tdnr;
pr_info("enter %s\n", __func__);
regVal = 0;
REG_SET_SLICE(regVal, DENOISE3D_V20_THR_UPDATE, tdnr->update_factor);
REG_SET_SLICE(regVal, DENOISE3D_V20_MOTION_THR_UPDATE, tdnr->motion_update_factor);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_update), regVal);
return 0;
}
int isp_tdnr_s_buf(struct isp_ic_dev *dev)
{
struct isp_tdnr_buffer* buf = &dev->tdnr.buf;
u32 in_width, in_height;
u32 size, lval;
u32 miv2_sp2_bus_id ;
u32 miv2_sp2_fmt;
u32 miv2_imsc2;
u32 miv2_ctrl = isp_read_reg(dev, REG_ADDR(miv2_ctrl));
u32 miv2_imsc = isp_read_reg(dev, REG_ADDR(miv2_imsc));
u32 miv2_sp2_ctrl = isp_read_reg(dev, REG_ADDR(miv2_sp2_ctrl));
u32 isp_mi_sp2_raw2_ctrl = isp_read_reg(dev, REG_ADDR(isp_mi_sp2_raw2_ctrl));
pr_info("enter %s\n", __func__);
/*
ENABLE MIV2 SP2 RAW1 RAW2 WRITE/READ
*/
REG_SET_SLICE(miv2_ctrl, SP2_RAW_RDMA_PATH_ENABLE, 1);
REG_SET_SLICE(miv2_ctrl, SP2_RAW_PATH_ENABLE, 1);
miv2_ctrl |= 0x00100000; // sp2_raw2_path_enable
isp_write_reg(dev, REG_ADDR(miv2_ctrl), miv2_ctrl);
in_width = isp_read_reg(dev, REG_ADDR(isp_out_h_size));
in_height = isp_read_reg(dev, REG_ADDR(isp_out_v_size));
lval = (in_width * 12 + 127)/ 128;
lval <<= 4;
size = in_height * lval; //raw12 unaligned
//write reference frame config
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_base_ad_init), buf->pa_refer);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_size_init), size);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_offs_cnt_init), 0);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_llength), lval);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_pic_width), in_width);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_pic_height), in_height);
isp_write_reg(dev, REG_ADDR(miv2_sp2_raw_pic_size), size);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_start_ad), buf->pa_refer);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_width), in_width);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_llength), lval);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_lval), lval);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_size), size);
in_width /= 2;
in_height /= 2;
lval = (in_width); // RAW8 output
size = in_height * lval;
pr_info("%s 0x%08x\n", __func__, REG_ADDR(isp_mi_sp2_raw2_base_ad_init));
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_raw2_base_ad_init), buf->pa_motion);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_raw2_size_init), size);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_raw2_offs_cnt_init), 0);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_raw2_llength), lval);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_raw2_pic_width), in_width);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_raw2_pic_height), in_height);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_raw2_pic_size), size);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_dma_raw2_pic_start_ad), buf->pa_motion);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_dma_raw2_pic_width), in_width);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_dma_raw2_pic_llength), lval);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_dma_raw2_pic_lval), lval); // align to 128
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_dma_raw2_pic_size), size);
#if 0
isp_write_reg(dev, 0x5620, buf->pa_motion);
isp_write_reg(dev, 0x5624, size);
isp_write_reg(dev, 0x5628, 0);
isp_write_reg(dev, 0x562c, lval);
isp_write_reg(dev, 0x5630, in_width);
isp_write_reg(dev, 0x5634, in_height);
isp_write_reg(dev, 0x5638, size);
isp_write_reg(dev, 0x5660, buf->pa_motion);
isp_write_reg(dev, 0x5664, in_width);
isp_write_reg(dev, 0x5668, lval);
isp_write_reg(dev, 0x5680, lval); // align to 128
isp_write_reg(dev, 0x566c, size);
#endif
miv2_sp2_bus_id = isp_read_reg(dev, REG_ADDR(miv2_sp2_bus_id));
REG_SET_SLICE(miv2_sp2_bus_id, SP2_WR_ID_EN, 1);
REG_SET_SLICE(miv2_sp2_bus_id, SP2_RD_ID_EN, 1);
REG_SET_SLICE(miv2_sp2_bus_id, SP2_RD_BURST_LEN, 2); //sp2 rd burst lenghth 16
REG_SET_SLICE(miv2_sp2_bus_id, SP2_BUS_SW_EN, 1);
isp_write_reg(dev, REG_ADDR(miv2_sp2_bus_id), miv2_sp2_bus_id);
miv2_sp2_fmt = isp_read_reg(dev, REG_ADDR(miv2_sp2_fmt));
REG_SET_SLICE(miv2_sp2_fmt, SP2_WR_RAW_BIT, 2); //raw12
REG_SET_SLICE(miv2_sp2_fmt, SP2_WR_RAW_ALIGNED, 0); //unaligned
REG_SET_SLICE(miv2_sp2_fmt, SP2_RD_RAW_BIT, 2); //raw12
REG_SET_SLICE(miv2_sp2_fmt, SP2_RD_RAW_ALIGNED, 0); //unaligned
isp_write_reg(dev, REG_ADDR(miv2_sp2_fmt), miv2_sp2_fmt);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_raw2_fmt), 0);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_RD_RAW_CFG_UPDATE, 1);
//REG_SET_SLICE(miv2_sp2_ctrl, SP2_RD_RAW_AUTO_UPDATE, 1);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_MI_CFG_UPD, 1);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_AUTO_UPDATE, 1);
miv2_sp2_ctrl |= (SP2_INIT_BASE_EN_MASK | SP2_INIT_OFFSET_EN_MASK);
//miv2_sp2_ctrl |= 0x2fa;
isp_write_reg(dev, REG_ADDR(miv2_sp2_ctrl), miv2_sp2_ctrl);
isp_mi_sp2_raw2_ctrl |= 0x23a;
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_raw2_ctrl), isp_mi_sp2_raw2_ctrl);
miv2_imsc |= SP2_RAW_FRAME_END_MASK|SP2_DMA_RAW_READY_MASK;
isp_write_reg(dev, REG_ADDR(miv2_imsc), miv2_imsc);
miv2_imsc2 = isp_read_reg(dev, REG_ADDR(miv2_imsc2));
miv2_imsc2 |= SP2_RAW2_FRAME_END_MASK | SP2_RAW2_DMA_READY_MASK; //0x41000
isp_write_reg(dev, REG_ADDR(miv2_imsc2), miv2_imsc2);
isp_write_reg(dev, REG_ADDR(isp_denoise3d_ctrl), 0x480);
// isp_write_reg(dev, 0x00000730, 0x00001edf);
//isp_write_reg(dev, 0x000014ec, 0x04b30000);
//isp_write_reg(dev, 0x000014f0, 0x0807e521);
return 0;
}
int isp_r_tdnr_refer(struct isp_ic_dev *dev)
{
struct isp_tdnr_buffer* buf = &dev->tdnr.buf;
u32 miv2_ctrl = isp_read_reg(dev, REG_ADDR(miv2_ctrl));
u32 miv2_imsc = isp_read_reg(dev, REG_ADDR(miv2_imsc));
u32 miv2_sp2_ctrl = isp_read_reg(dev, REG_ADDR(miv2_sp2_ctrl));
u32 isp_mi_sp2_raw2_ctrl = isp_read_reg(dev, REG_ADDR(isp_mi_sp2_raw2_ctrl));
pr_info("enter %s\n", __func__);
isp_write_reg(dev, REG_ADDR(miv2_sp2_dma_raw_pic_start_ad), buf->pa_refer);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_dma_raw2_pic_start_ad), buf->pa_motion);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_RD_RAW_CFG_UPDATE, 1);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_RD_RAW_AUTO_UPDATE, 1);
REG_SET_SLICE(miv2_sp2_ctrl, SP2_MI_CFG_UPD, 1);
miv2_sp2_ctrl |= (SP2_INIT_BASE_EN_MASK | SP2_INIT_OFFSET_EN_MASK);
miv2_sp2_ctrl |= 0xf0;
isp_write_reg(dev, REG_ADDR(miv2_sp2_ctrl), miv2_sp2_ctrl);
isp_mi_sp2_raw2_ctrl |= 0x238;
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_raw2_ctrl), isp_mi_sp2_raw2_ctrl);
REG_SET_SLICE(miv2_ctrl, SP2_RAW_RDMA_PATH_ENABLE, 1);
REG_SET_SLICE(miv2_ctrl, SP2_RAW_RDMA_START_CON, 1);
REG_SET_SLICE(miv2_ctrl, SP2_RAW_RDMA_START, 1);
REG_SET_SLICE(miv2_ctrl, SP2_RAW2_RDMA_START, 1);
REG_SET_SLICE(miv2_ctrl, SP2_RAW2_RDMA_START_CON, 1);
isp_write_reg(dev, REG_ADDR(miv2_ctrl), miv2_ctrl);
miv2_imsc |= SP2_DMA_RAW_READY_MASK;
isp_write_reg(dev, REG_ADDR(miv2_imsc), miv2_imsc);
return 0;
}
int isp_r_tdnr_motion(struct isp_ic_dev *dev)
{
struct isp_tdnr_buffer* buf = &dev->tdnr.buf;
u32 miv2_ctrl = isp_read_reg(dev, REG_ADDR(miv2_ctrl));
u32 isp_mi_sp2_raw2_ctrl = isp_read_reg(dev, REG_ADDR(isp_mi_sp2_raw2_ctrl));
pr_info("enter %s\n", __func__);
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_dma_raw2_pic_start_ad), buf->pa_motion);
REG_SET_SLICE(miv2_ctrl, SP2_RAW2_RDMA_START, 1);
REG_SET_SLICE(miv2_ctrl, SP2_RAW2_RDMA_START_CON, 1);
isp_write_reg(dev, REG_ADDR(miv2_ctrl), miv2_ctrl);
isp_mi_sp2_raw2_ctrl |= 0x238;
isp_write_reg(dev, REG_ADDR(isp_mi_sp2_raw2_ctrl), isp_mi_sp2_raw2_ctrl);
return 0;
}
int isp_tdnr_s_2dnr(struct isp_ic_dev *dev)
{
#ifndef ISP_2DNR_V5
pr_info("unsupported function: %s\n", __func__);
return -EINVAL;
#else
struct isp_2dnr_context *dnr2 = &dev->dnr2;
u32 isp_denoise2d_control =
isp_read_reg(dev, REG_ADDR(isp_denoise2d_control));
u32 value, addr, strength;
u32 isp_ctrl;
int i;
if (!dnr2->enable) {
value = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_ctrl));
REG_SET_SLICE(value, DENOISE3D_V20_NLM_ENABLE, 0);
if((value & DENOISE3D_V20_TNR_ENABLE_MASK) == 0)
REG_SET_SLICE(value, DENOISE3D_V20_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_ctrl),
value);
return 0;
}
strength = isp_read_reg(dev, REG_ADDR(isp_denoise2d_strength));
REG_SET_SLICE(strength, ISP_2DNR_PRGAMMA_STRENGTH, 1);
REG_SET_SLICE(strength, ISP_2DNR_STRENGTH, 0xff);
isp_write_reg(dev, REG_ADDR(isp_denoise2d_strength), strength);
pr_debug("%s: write strength addr =0x%08x value = 0x%08x \n", __func__, REG_ADDR(isp_denoise2d_strength), strength);
addr = REG_ADDR(isp_denoise2d_sigma_y[0]);
for (i = 0; i < 60; i += 5) {
value = 0;
REG_SET_SLICE(value, ISP_2DNR_SIGMAY0, dnr2->sigma[i]);
REG_SET_SLICE(value, ISP_2DNR_SIGMAY1, dnr2->sigma[i + 1]);
REG_SET_SLICE(value, ISP_2DNR_SIGMAY2A,
dnr2->sigma[i + 2] >> 6);
isp_write_reg(dev, addr, value);
value = 0;
addr += 4;
REG_SET_SLICE(value, ISP_2DNR_SIGMAY2B,
dnr2->sigma[i + 2] & 0x3f);
REG_SET_SLICE(value, ISP_2DNR_SIGMAY0, dnr2->sigma[i + 3]);
REG_SET_SLICE(value, ISP_2DNR_SIGMAY1, dnr2->sigma[i + 4]);
isp_write_reg(dev, addr, value);
addr += 4;
}
isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
REG_SET_SLICE(isp_denoise2d_control, ISP_2DNR_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_denoise2d_sigma_sqr), dnr2->sigma_sqr);
isp_write_reg(dev, REG_ADDR(isp_denoise2d_sigma_sqr_shd),
dnr2->sigma_sqr);
isp_write_reg(dev, REG_ADDR(isp_denoise2d_weight_mul_factor),
dnr2->weight);
isp_write_reg(dev, REG_ADDR(isp_denoise2d_weight_mul_factor_shd),
dnr2->weight);
/* refer to HW spec for HBLANK */
//isp_write_reg(dev, REG_ADDR(isp_denoise2d_dummy_hblank), 0);
isp_write_reg(dev, REG_ADDR(isp_denoise2d_strength_shd), strength);
isp_write_reg(dev, REG_ADDR(isp_denoise2d_control_shd),
isp_denoise2d_control);
value = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_blending));
REG_SET_SLICE(value, DENOISE3D_V20_NLM_STRENGTH_OFFSET, dnr2->str_off);
REG_SET_SLICE(value, DENOISE3D_V20_NLM_STRENGTH_MAX, dnr2->str_max);
REG_SET_SLICE(value, DENOISE3D_V20_NLM_STRENGTH_SLOPE, dnr2->str_slope);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_blending), value);
pr_debug("%s:write blending addr = 0x%08x, value = 0x%08x \n", __func__, REG_ADDR(isp_denoise3d2_blending), value);
value = isp_read_reg(dev, REG_ADDR(isp_denoise3d2_ctrl));
REG_SET_SLICE(value, DENOISE3D_V20_NLM_ENABLE, 1);
REG_SET_SLICE(value, DENOISE3D_V20_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_denoise3d2_ctrl),
value);
pr_debug("%s:write isp_denoise3d2_ctrl addr = 0x%08x, value = 0x%08x \n", __func__, REG_ADDR(isp_denoise3d2_ctrl), value);
pr_debug("exit %s\n", __func__);
return 0;
#endif
}
#endif

176
vvcam/isp/isp_types.h Executable file
View File

@@ -0,0 +1,176 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _ISP_TYPES_H_
#define _ISP_TYPES_H_
enum {
IC_MI_PATH_INVALID = -1, /**< lower border (only for an internal evaluation) */
IC_MI_PATH_MAIN = 0, /**< main path index */
IC_MI_PATH_SELF = 1, /**< self path index */
IC_MI_PATH_SELF2 = 2, /**< self path index */
IC_MI_PATH_MAX /**< upper border (only for an internal evaluation) */
};
enum {
IC_MI_DATAMODE_INVALID = 0, /**< lower border (only for an internal evaluation) */
IC_MI_DATAMODE_DISABLED = 1, /**< disables the path */
IC_MI_DATAMODE_JPEG = 2, /**< data output format is JPEG (only valid for mainpath @ref CamerIcMiPath_e) */
IC_MI_DATAMODE_YUV444 = 3, /**< data output format is YUV444 */
IC_MI_DATAMODE_YUV422 = 4, /**< data output format is YUV422 */
IC_MI_DATAMODE_YUV420 = 5, /**< data output format is YUV420 */
IC_MI_DATAMODE_YUV400 = 6, /**< data output format is YUV400 */
IC_MI_DATAMODE_RGB888 = 7, /**< data output format is RGB888 (only valid for selpath @ref CamerIcMiPath_e) */
IC_MI_DATAMODE_RGB666 = 8, /**< data output format is RGB666 (only valid for selpath @ref CamerIcMiPath_e) */
IC_MI_DATAMODE_RGB565 = 9, /**< data output format is RGB565 (only valid for selpath @ref CamerIcMiPath_e) */
IC_MI_DATAMODE_RAW8 = 10, /**< data output format is RAW8 (only valid for mainpath @ref CamerIcMiPath_e) */
IC_MI_DATAMODE_RAW12 = 11, /**< data output format is RAW12 (only valid for mainpath @ref CamerIcMiPath_e) */
IC_MI_DATAMODE_DPCC = 12, /**< path dumps out the current measured defect pixel table */
IC_MI_DATAMODE_RAW10 = 13, /**< data output format is RAW10 (only valid for mainpath @ref CamerIcMiPath_e) */
IC_MI_DATAMODE_RAW14 = 14, /**< data output format is RAW14 (only valid for mainpath @ref CamerIcMiPath_e) */
IC_MI_DATAMODE_RAW16 = 15, /**< data output format is RAW16 (only valid for mainpath @ref CamerIcMiPath_e) */
IC_MI_DATAMODE_MAX /**< upper border (only for an internal evaluation) */
};
enum {
IC_MI_DATASTORAGE_INVALID = 0, /**< lower border (only for an internal evaluation) */
IC_MI_DATASTORAGE_PLANAR = 1, /**< YUV values are packed together as: YYYY......, UVUVUVUV...... */
IC_MI_DATASTORAGE_SEMIPLANAR = 2, /**< YUV values are packed together as: YUV, YUV, YUV, ...... */
IC_MI_DATASTORAGE_INTERLEAVED = 3, /**< Y values for all pixels are put together, as well as U and V,
like: YYYYYY......, UUUUUUU......., VVVVVV...... */
IC_MI_DATASTORAGE_MAX /**< upper border (only for an internal evaluation) */
};
enum {
ISP_PICBUF_TYPE_INVALID = 0x00,
ISP_PICBUF_TYPE_DATA = 0x08, /* just some sequential data */
ISP_PICBUF_TYPE_RAW8 = 0x10,
ISP_PICBUF_TYPE_RAW16 = 0x11, /* includes: 9..16bits, MSBit aligned, LSByte first! */
ISP_PICBUF_TYPE_RAW10 = 0x12, /* includes: 10bits, MSBit aligned, LSByte first! */
ISP_PICBUF_TYPE_RAW12 = 0x13,
ISP_PICBUF_TYPE_RAW14 = 0x14,
ISP_PICBUF_TYPE_JPEG = 0x20,
ISP_PICBUF_TYPE_YCbCr444 = 0x30,
ISP_PICBUF_TYPE_YCbCr422 = 0x31,
ISP_PICBUF_TYPE_YCbCr420 = 0x32,
ISP_PICBUF_TYPE_YCbCr400 = 0x33,
ISP_PICBUF_TYPE_YCbCr32 = 0x3f,
ISP_PICBUF_TYPE_RGB888 = 0x40,
ISP_PICBUF_TYPE_RGB666 = 0x41, /* R, G & B are LSBit aligned! */
ISP_PICBUF_TYPE_RGB565 = 0x42, /* TODO: don't know the memory layout right now, investigate! */
ISP_PICBUF_TYPE_RGB32 = 0x4f,
_ISP_PICBUF_TYPE_DUMMY_
};
enum {
ISP_PICBUF_LAYOUT_INVALID = 0,
ISP_PICBUF_LAYOUT_COMBINED = 0x10, /* ISP_PICBUF_TYPE_DATA: Data: D0 D1 D2... */
/* ISP_PICBUF_TYPE_RAW8: Data: D0 D1 D2... */
/* ISP_PICBUF_TYPE_RAW16/10: Data: D0L D0H D1L D1H... */
/* ISP_PICBUF_TYPE_JPEG: Data: J0 J1 J2... */
/* ISP_PICBUF_TYPE_YCbCr444: Data: Y0 Cb0 Cr0 Y1 Cb1Cr1... */
/* ISP_PICBUF_TYPE_YCbCr422: Data: Y0 Cb0 Y1 Cr0 Y2 Cb1 Y3 Cr1... */
/* ISP_PICBUF_TYPE_YCbCr32: Data: Cr0 Cb0 Y0 A0 Cr1 Cb1 Y1 A1... */
/* ISP_PICBUF_TYPE_RGB888: Data: R0 G0 B0 R1 B2 G1... */
/* ISP_PICBUF_TYPE_RGB666: Data: {00,R0[5:0]} {00,G0[5:0]} {00,B0[5:0]} {00,R1[5:0]} {00,G2[5:0]} {00,B3[5:0]}... */
/* ISP_PICBUF_TYPE_RGB565: Data: {R0[4:0],G0[5:3]} {G0[2:0],B0[4:0]} {R1[4:0],G1[5:3]} {G1[2:0],B1[4:0]}... (is this correct?) */
/* ISP_PICBUF_TYPE_RGB32: Data: B0 G0 R0 A0 B1 G1 R1 A1... */
ISP_PICBUF_LAYOUT_BAYER_RGRGGBGB = 0x11, /* 1st line: RGRG... , 2nd line GBGB... , etc. */
ISP_PICBUF_LAYOUT_BAYER_GRGRBGBG = 0x12, /* 1st line: GRGR... , 2nd line BGBG... , etc. */
ISP_PICBUF_LAYOUT_BAYER_GBGBRGRG = 0x13, /* 1st line: GBGB... , 2nd line RGRG... , etc. */
ISP_PICBUF_LAYOUT_BAYER_BGBGGRGR = 0x14, /* 1st line: BGBG... , 2nd line GRGR... , etc. */
ISP_PICBUF_LAYOUT_SEMIPLANAR = 0x20, /* ISP_PICBUF_TYPE_YCbCr422: Luma: Y0 Y1 Y2 Y3... ; Chroma: Cb0 Cr0 Cb1 Cr1... */
/* ISP_PICBUF_TYPE_YCbCr420: Luma: Y0 Y1 Y2 Y3... ; Chroma: Cb0 Cr0 Cb1 Cr1... */
/* ISP_PICBUF_TYPE_YCbCr400: Luma: Y0 Y1 Y2 Y3... ; Chroma: not used */
ISP_PICBUF_LAYOUT_PLANAR = 0x30, /* ISP_PICBUF_TYPE_YCbCr444: Y: Y0 Y1 Y2 Y3...; Cb: Cb0 Cb1 Cb2 Cb3...; Cr: Cr0 Cr1 Cr2 Cr3... */
/* ISP_PICBUF_TYPE_YCbCr422: Y: Y0 Y1 Y2 Y3...; Cb: Cb0 Cb1 Cb2 Cb3...; Cr: Cr0 Cr1 Cr2 Cr3... */
/* ISP_PICBUF_TYPE_YCbCr420: Y: Y0 Y1 Y2 Y3...; Cb: Cb0 Cb1 Cb2 Cb3...; Cr: Cr0 Cr1 Cr2 Cr3... */
/* ISP_PICBUF_TYPE_YCbCr400: Y: Y0 Y1 Y2 Y3...; Cb: not used; Cr: not used... */
/* ISP_PICBUF_TYPE_RGB888: R: R0 R1 R2 R3...; G: G0 G1 G2 G3...; B: B0 B1 B2 B3... */
/* ISP_PICBUF_TYPE_RGB666: R: {00,R0[5:0]}...; G: {00,G0[5:0]}...; B: {00,B0[5:0]}... */
_ISP_PICBUF_LAYOUT_DUMMY_
};
enum {
IC_DPF_RB_FILTERSIZE_INVALID = 0, /**< lower border (only for an internal evaluation) */
IC_DPF_RB_FILTERSIZE_9x9 = 1, /**< red and blue filter kernel size 9x9 (means 5x5 active pixel) */
IC_DPF_RB_FILTERSIZE_13x9 = 2, /**< red and blue filter kernel size 13x9 (means 7x5 active pixel) */
IC_DPF_RB_FILTERSIZE_MAX /**< upper border (only for an internal evaluation) */
};
enum {
ISP_MI_DATA_ALIGN_MODE_INVALID = -1,
ISP_MI_DATA_UNALIGN_MODE = 0, /* pixel data not aligned. */
ISP_MI_DATA_ALIGN_128BIT_MODE = 1, /* pixel data aligned with 128 bit. */
ISP_MI_DATA_ALIGN_16BIT_MODE = 2, /* pixel data aligned with 16 bit. */
ISP_MI_DATA_ALIGN_MODE_MAX
};
enum {
IC_DPF_GAIN_USAGE_INVALID = 0, /**< lower border (only for an internal evaluation) */
IC_DPF_GAIN_USAGE_DISABLED = 1, /**< don't use any gains in preprocessing stage */
IC_DPF_GAIN_USAGE_NF_GAINS = 2, /**< use only the noise function gains from registers DPF_NF_GAIN_R, ... */
IC_DPF_GAIN_USAGE_LSC_GAINS = 3, /**< use only the gains from LSC module */
IC_DPF_GAIN_USAGE_NF_LSC_GAINS = 4, /**< use the moise function gains and the gains from LSC module */
IC_DPF_GAIN_USAGE_AWB_GAINS = 5, /**< use only the gains from AWB module */
IC_DPF_GAIN_USAGE_AWB_LSC_GAINS = 6, /**< use the gains from AWB and LSC module */
IC_DPF_GAIN_USAGE_MAX /**< upper border (only for an internal evaluation) */
};
enum {
IC_NLL_SCALE_INVALID = 0, /**< lower border (only for an internal evaluation) */
IC_NLL_SCALE_LINEAR = 1, /**< use a linear scaling */
IC_NLL_SCALE_LOGARITHMIC = 2, /**< use a logarithmic scaling */
IC_NLL_SCALE_MAX /**< upper border (only for an internal evaluation) */
};
#endif /* _ISP_TYPES_H_ */

190
vvcam/isp/isp_version.h Executable file
View File

@@ -0,0 +1,190 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _ISP_VERSION_H_
#define _ISP_VERSION_H_
#define ISP_EE_SUPPORT 1
#define ISP_2DNR_SUPPORT (1 << 1)
#define ISP_3DNR_SUPPORT (1 << 2)
#define ISP_WDR3_SUPPORT (1 << 3)
#define ISP_MIV2_SUPPORT (1 << 4)
#define ISP_AEV2_SUPPORT (1 << 5)
#define ISP_COMPAND_SUPPORT (1 << 6)
#define ISP_HDR_STITCH_SUPPORT (1 << 7)
/*****************************************************************************/
/**
* @brief HDR module version type
*/
/*****************************************************************************/
#define VSI_ISP_HDR_NOTSUPPORT 0 //!< Not support HDR
#define VSI_ISP_HDR_V10 1 //!< Version V10
#define VSI_ISP_HDR_V11 2 //!< Version V11
#define VSI_ISP_HDR_V12 3 //!< Version V12
#define VSI_ISP_HDR_V13 4 //!< Version V13
/////////////////////////////////////////
//add Version defines
/////////////////////////////////////////
/* add Version defines(Mrv_all_regs.h)
ISP8000L_V2002、ISP8000_V2003、
ISP8000NANO_V1801、ISP8000NANO_V1802、
ISP8000_V1901、ISP8000L_V1901、ISP8000L_V1902、
ISP8000L_V1903、ISP8000L_V1905、ISP8000L_V2001、ISP8000L_V2006
*/
#define MRV_IMAGE_EFFECTS_VERSION 1
#define MRV_SUPER_IMPOSE_VERSION 1
#define MRV_BLACK_LEVEL_VERSION 1
#define MRV_AUTO_EXPOSURE_VERSION 1
#define MRV_AEV2_VERSION 1
#define MRV_OUTPUT_FORMATTER_VERSION 1
#define MRV_GAMMA_OUT_VERSION 1
#define MRV_FLASH_LIGHT_VERSION 1
#define MRV_SHUTTER_VERSION 1
#define MRV_MAINPATH_SCALER_VERSION 1
#define MRV_SELFPATH_SCALER_VERSION 1
#define MRV_MI_VERSION 1
//#define MRV_JPE_VERSION 1
#define MRV_SMIA_VERSION 1
#define MRV_MIPI_VERSION 1
#define MRV_AUTOFOCUS_VERSION 1
#define MRV_LSC_VERSION 1
#define MRV_IS_VERSION 1
#define MRV_HISTOGRAM_VERSION 1
#define MRV_FILTER_VERSION 1
#define MRV_CAC_VERSION 1
#define MRV_DPF_VERSION 1
#define MRV_DPCC_VERSION 1
#define MRV_WDR_VERSION 1
#define MRV_CSM_VERSION 1
#define MRV_AWB_VERSION 1
#define MRV_ELAWB_VERSION 1
#define MRV_GAMMA_IN_VERSION 1
#define MRV_SHUTTER_CTRL_VERSION 1
#define MRV_CT_VERSION 1
#define MRV_COLOR_PROCESSING_VERSION 1
#define MRV_VSM_VERSION 1
#define MRV_CNR_VERSION 1
#define MRV_WDR2_VERSION 1
#define MRV_WDR3_VERSION 1
#define MRV_CMPD_VERSION 1 /* compand */
#define MRV_TPG_VERSION 1
//#define MRV_STITCHING_VERSION 1
#define MRV_EE_VERSION 1
#define MRV_2DNR_VERSION 1
#ifdef ISP_3DNR
#define MRV_3DNR_VERSION 1
#endif
#ifdef ISP_GCMONO
#define MRV_GCMONO_VERSION 1
#endif
#ifdef ISP_RGBGC
#define MRV_RGBGAMMA_VERSION 1
#endif
#ifdef ISP_DEC
#define MRV_DEC_VERSION 1
#endif
#ifdef ISP_DEMOSAIC2
#define MRV_DEMOSAIC_VERSION 1
#endif
#ifdef ISP_GREENEQUILIBRATE
#define MRV_GREENEQUILIBRATION_VERSION 1
#endif
#ifdef ISP_CA
#define MRV_COLOR_ADJUST_VERSION 1
#endif
#ifdef ISP_SP2
#define MRV_SP2_VERSION 1
#endif
#ifdef ISP_HDR_STITCH_V2
#undef MRV_STITCHING_VERSION
#define MRV_STITCHING_VERSION 2 //1--V11, 2--V12
#elif defined(ISP_HDR_STITCH_V3)
#undef MRV_STITCHING_VERSION
#define MRV_STITCHING_VERSION 3 //1--V11, 2--V12 3--V13
#elif defined(ISP_HDR_STITCH)
#undef MRV_STITCHING_VERSION
#define MRV_STITCHING_VERSION 1 //1--V11, 2--V12 3--V13
#endif
#ifdef ISP_3DNR_V2
#define MRV_3DNR_VERSION 1
#endif
#ifdef ISP_WDR_V4
#define MRV_WDR4_VERSION 1
#endif
#ifdef ISP_3DNR_V3
#define MRV_TDNR3_VERSION 1
#endif
#ifdef ISP_RGBIR
#define MRV_RGBIR_VERSION 1
#endif
#ifdef ISP_HIST64
#define MRV_HISTOGRAM64_VERSION 1
#endif
#endif /* _ISP_VERSION_H_ */

136
vvcam/isp/isp_wdr.c Executable file
View File

@@ -0,0 +1,136 @@
/****************************************************************************
*
* 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 "isp_wdr.h"
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
#include "ic_dev.h"
extern MrvAllRegister_t *all_regs;
int isp_s_wdr(struct isp_ic_dev *dev)
{
isp_wdr_context_t* wdr = &dev->wdr;
pr_info(" enter %s\n", __func__);
/*update wdr configuration after frame end when isp enable*/
if (!is_isp_enable(dev) || wdr->changed) {
uint32_t isp_wdr_offset, isp_wdr_ctrl;
isp_wdr_offset = isp_read_reg(dev, REG_ADDR(isp_wdr_offset));
REG_SET_SLICE( isp_wdr_offset, MRV_WDR_LUM_OFFSET, wdr->LumOffset );
REG_SET_SLICE( isp_wdr_offset, MRV_WDR_RGB_OFFSET, wdr->RgbOffset );
isp_write_reg(dev, REG_ADDR(isp_wdr_offset), isp_wdr_offset);
isp_wdr_ctrl = isp_read_reg(dev, REG_ADDR(isp_wdr_ctrl));
REG_SET_SLICE(isp_wdr_ctrl, MRV_WDR_ENABLE, wdr->enabled);
isp_write_reg(dev, REG_ADDR(isp_wdr_ctrl), isp_wdr_ctrl);
wdr->changed = false;
} else {
wdr->changed = true;
}
pr_info(" %s wdr.changed %d \n", __func__, wdr->changed);
return 0;
}
int isp_s_wdr_curve(struct isp_ic_dev *dev)
{
isp_wdr_context_t* wdr = &dev->wdr;
int i, j;
uint32_t dYi = 0U;
for ( i=0; i<4; i++ )
{
for ( j=8; j>0; j-- )
{
dYi <<= 4;
dYi += wdr->dY[ (i*8 + j) ];
}
if (i == 0)
{
isp_write_reg(dev, REG_ADDR(isp_wdr_tonecurve_1), dYi);
}
else if (i == 1)
{
isp_write_reg(dev, REG_ADDR(isp_wdr_tonecurve_2), dYi);
}
else if (i == 2)
{
isp_write_reg(dev, REG_ADDR(isp_wdr_tonecurve_3), dYi);
}
else /* if (i == 3) */
{
isp_write_reg(dev, REG_ADDR(isp_wdr_tonecurve_4), dYi);
}
}
for ( i=0; i<33; i++ )
{
isp_write_reg(dev, REG_ADDR(wdr_tone_mapping_curve_y_block_arr[i]), wdr->Ym[i]);
}
dYi = 0x00000000;
isp_write_reg(dev, REG_ADDR(isp_wdr_offset), dYi);
isp_write_reg(dev, REG_ADDR(isp_wdr_deltamin), 0x00100000);
return 0;
}

67
vvcam/isp/isp_wdr.h Executable file
View File

@@ -0,0 +1,67 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _ISP_WDR_H
#define _ISP_WDR_H
#include "isp_version.h"
#include "vvdefs.h"
#include "ic_dev.h"
int isp_s_wdr(struct isp_ic_dev *dev);
int isp_s_wdr_curve(struct isp_ic_dev *dev);
#endif

502
vvcam/isp/isp_wdr3.c Executable file
View File

@@ -0,0 +1,502 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#endif
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
#define WDR3_WW (32)
#define WDR3_HH (32)
#define WDR3_MAX_VALUE (1023)
#define WDR3_GAIN_SHIFT (2)
#define WDR3_NORMALIZE (1024)
#define WDR3_NORMALIZE_SHIFT (10)
#ifdef ISP_WDR_V3_20BIT
#define MODULE_INPUT_BIT_DEPTH (20)
#else
#define MODULE_INPUT_BIT_DEPTH (12)
#endif
#define MODULE_OUTPUT_BIT_DEPTH (12)
extern MrvAllRegister_t *all_regs;
#ifdef ISP_WDR_V3
static void wdr3_hw_init(struct isp_ic_dev *dev)
{
struct isp_wdr3_context *wdr3 = &dev->wdr3;
u32 isp_wdr3_shift_0;
u32 isp_wdr3_shift_1;
u32 width, height;
u32 slice_block_area_factor;
u32 slice_value_weight[4];
u32 slice_pixel_slope_merge;
u32 slice_pixel_base_merge;
u32 slice_pixel_slope_adjust;
u32 slice_pixel_base_adjust;
u32 slice_pixel_slope_entropy;
u32 slice_pixel_base_entropy;
u32 slice_sigma_height;
u32 slice_sigma_width;
u32 slice_sigma_value;
u32 slice_block_width;
u32 slice_block_height;
u32 isp_wdr3_block_size;
u32 isp_wdr3_block_area_factor;
u32 isp_wdr3_value_weight;
u32 isp_wdr3_pixel_slope;
u32 isp_wdr3_entropy_slope;
u32 isp_wdr3_sigma_width;
u32 isp_wdr3_sigma_height;
u32 isp_wdr3_sigma_value;
u32 isp_wdr3_block_flag_width;
u32 isp_wdr3_block_flag_height;
u32 isp_wdr3_strength;
u32 width_left;
u32 width_count = 0;
u32 height_left;
u32 height_count = 0;
u32 val;
bool reg_flag = false;
int i, pos;
pr_info("enter %s\n", __func__);
width = isp_read_reg(dev, REG_ADDR(isp_acq_h_size));
height = isp_read_reg(dev, REG_ADDR(isp_acq_v_size));
pr_info("wdr3 res: %d %d \n", width, height);
/* firware initilization */
slice_pixel_slope_merge = 128;
slice_pixel_base_merge = 0;
slice_pixel_slope_adjust = 128;
slice_pixel_base_adjust = 0;
slice_pixel_slope_entropy = 204;
slice_pixel_base_entropy = 716;
slice_value_weight[0] = 6;
slice_value_weight[1] = 5;
slice_value_weight[2] = 5;
slice_value_weight[3] = 16;
slice_block_width = width / WDR3_WW;
slice_block_height = height / WDR3_HH;
slice_block_area_factor =
WDR3_NORMALIZE * WDR3_NORMALIZE / (slice_block_width *
slice_block_height);
slice_sigma_height =
WDR3_NORMALIZE * WDR3_NORMALIZE / slice_block_height;
slice_sigma_width = WDR3_NORMALIZE * WDR3_NORMALIZE / slice_block_width;
slice_sigma_value = WDR3_NORMALIZE * WDR3_NORMALIZE / WDR3_MAX_VALUE;
/* block flag configuration */
width_left = width - slice_block_width * WDR3_WW;
height_left = height - slice_block_height * WDR3_HH;
isp_wdr3_block_flag_width = 0;
isp_wdr3_block_flag_height = 0;
for (i = 0, width_count = 0;
(i < WDR3_WW) && (width_count < width_left); i++, width_count++) {
isp_wdr3_block_flag_width |= (1 << i);
}
for (i = 0, height_count = 0;
(i < WDR3_HH) && (height_count < height_left);
i++, height_count++) {
isp_wdr3_block_flag_height |= (1 << i);
}
slice_pixel_base_adjust += 255;
slice_pixel_base_merge += 255;
#ifndef __KERNEL__
//NOTE: register isp_wdr3_shift is read-only register on fpga, can not write
//NOTE: it is used by cmodel, So it should be config.
u32 slice_pixel_shift;
u32 slice_output_shift;
u32 isp_wdr3_shift;
slice_pixel_shift = MODULE_INPUT_BIT_DEPTH - 5;
slice_output_shift = MODULE_INPUT_BIT_DEPTH - MODULE_OUTPUT_BIT_DEPTH;
isp_wdr3_shift = isp_read_reg(dev, REG_ADDR(isp_wdr3_shift));
REG_SET_SLICE(isp_wdr3_shift, WDR3_PIXEL_SHIFT_BIT, slice_pixel_shift);
REG_SET_SLICE(isp_wdr3_shift, WDR3_OUTPUT_SHIFT_BIT,
slice_output_shift);
isp_write_reg(dev, REG_ADDR(isp_wdr3_shift), isp_wdr3_shift);
#endif
isp_wdr3_block_size = isp_read_reg(dev, REG_ADDR(isp_wdr3_block_size));
REG_SET_SLICE(isp_wdr3_block_size, WDR3_BLOCK_WIDTH, slice_block_width);
REG_SET_SLICE(isp_wdr3_block_size, WDR3_BLOCK_HEIGHT,
slice_block_height);
isp_write_reg(dev, REG_ADDR(isp_wdr3_block_size), isp_wdr3_block_size);
isp_wdr3_block_area_factor =
isp_read_reg(dev, REG_ADDR(isp_wdr3_block_area_factor));
REG_SET_SLICE(isp_wdr3_block_area_factor, WDR3_BLOCK_AREA_INVERSE,
slice_block_area_factor);
isp_write_reg(dev, REG_ADDR(isp_wdr3_block_area_factor),
isp_wdr3_block_area_factor);
isp_wdr3_value_weight =
isp_read_reg(dev, REG_ADDR(isp_wdr3_value_weight));
REG_SET_SLICE(isp_wdr3_value_weight, WDR3_VALUE_WEIGHT_0,
slice_value_weight[0]);
REG_SET_SLICE(isp_wdr3_value_weight, WDR3_VALUE_WEIGHT_1,
slice_value_weight[1]);
REG_SET_SLICE(isp_wdr3_value_weight, WDR3_VALUE_WEIGHT_2,
slice_value_weight[2]);
REG_SET_SLICE(isp_wdr3_value_weight, WDR3_VALUE_WEIGHT_3,
slice_value_weight[3]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_value_weight),
isp_wdr3_value_weight);
isp_wdr3_strength = isp_read_reg(dev, REG_ADDR(isp_wdr3_strength));
REG_SET_SLICE(isp_wdr3_strength, WDR3_MAXIMUM_GAIN, wdr3->max_gain);
REG_SET_SLICE(isp_wdr3_strength, WDR3_GLOBAL_STRENGTH,
wdr3->global_strength);
REG_SET_SLICE(isp_wdr3_strength, WDR3_LOCAL_STRENGTH,
128);
REG_SET_SLICE(isp_wdr3_strength, WDR3_TOTAL_STRENGTH, wdr3->strength);
isp_write_reg(dev, REG_ADDR(isp_wdr3_strength), isp_wdr3_strength);
isp_wdr3_pixel_slope =
isp_read_reg(dev, REG_ADDR(isp_wdr3_pixel_slope));
REG_SET_SLICE(isp_wdr3_pixel_slope, WDR3_PIXEL_ADJUST_BASE,
slice_pixel_base_adjust);
REG_SET_SLICE(isp_wdr3_pixel_slope, WDR3_PIXEL_ADJUST_SLOPE,
slice_pixel_slope_adjust);
REG_SET_SLICE(isp_wdr3_pixel_slope, WDR3_PIXEL_MERGE_BASE,
slice_pixel_base_merge);
REG_SET_SLICE(isp_wdr3_pixel_slope, WDR3_PIXEL_MERGE_SLOPE,
slice_pixel_slope_merge);
isp_write_reg(dev, REG_ADDR(isp_wdr3_pixel_slope),
isp_wdr3_pixel_slope);
isp_wdr3_entropy_slope =
isp_read_reg(dev, REG_ADDR(isp_wdr3_entropy_slope));
REG_SET_SLICE(isp_wdr3_entropy_slope, WDR3_ENTROPY_BASE,
slice_pixel_base_entropy);
REG_SET_SLICE(isp_wdr3_entropy_slope, WDR3_ENTROPY_SLOPE,
slice_pixel_slope_entropy);
isp_write_reg(dev, REG_ADDR(isp_wdr3_entropy_slope),
isp_wdr3_entropy_slope);
isp_wdr3_sigma_width =
isp_read_reg(dev, REG_ADDR(isp_wdr3_sigma_width));
REG_SET_SLICE(isp_wdr3_sigma_width, WDR3_BILITERAL_WIDTH_SIGMA,
slice_sigma_width);
isp_write_reg(dev, REG_ADDR(isp_wdr3_sigma_width),
isp_wdr3_sigma_width);
isp_wdr3_sigma_height =
isp_read_reg(dev, REG_ADDR(isp_wdr3_sigma_height));
REG_SET_SLICE(isp_wdr3_sigma_height, WDR3_BILITERAL_HEIGHT_SIGMA,
slice_sigma_height);
isp_write_reg(dev, REG_ADDR(isp_wdr3_sigma_height),
isp_wdr3_sigma_height);
isp_wdr3_sigma_value =
isp_read_reg(dev, REG_ADDR(isp_wdr3_sigma_value));
REG_SET_SLICE(isp_wdr3_sigma_value, WDR3_BILITERAL_VALUE_SIGMA,
slice_sigma_value);
isp_write_reg(dev, REG_ADDR(isp_wdr3_sigma_value),
isp_wdr3_sigma_value);
isp_write_reg(dev, REG_ADDR(isp_wdr3_block_flag_width),
isp_wdr3_block_flag_width);
isp_write_reg(dev, REG_ADDR(isp_wdr3_block_flag_height),
isp_wdr3_block_flag_height);
for (i = 0; i < 5; i++) {
reg_flag = i < 4;
pos = i * 3;
val =
wdr3->histogram[pos] << (reg_flag ?
WDR3_HISTOGRAM_CURVE0_SHIFT :
WDR3_HISTOGRAM_CURVE1_SHIFT);
val |=
wdr3->histogram[pos +
1] << (reg_flag ?
WDR3_HISTOGRAM_CURVE1_SHIFT :
WDR3_HISTOGRAM_CURVE2_SHIFT);
if (reg_flag)
REG_SET_SLICE(val, WDR3_HISTOGRAM_CURVE2,
wdr3->histogram[pos + 2]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_histogram[i]), val);
val =
wdr3->entropy[pos] << (reg_flag ?
WDR3_ENTROPY_CONVERT0_SHIFT :
WDR3_ENTROPY_CONVERT1_SHIFT);
val |=
wdr3->entropy[pos +
1] << (reg_flag ? WDR3_ENTROPY_CONVERT1_SHIFT
: WDR3_ENTROPY_CONVERT2_SHIFT);
if (reg_flag)
REG_SET_SLICE(val, WDR3_ENTROPY_CONVERT2,
wdr3->entropy[pos + 2]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_entropy[i]), val);
val =
wdr3->gamma_pre[pos] << (reg_flag ?
WDR3_GAMMA_PRE_CURVE0_SHIFT :
WDR3_GAMMA_PRE_CURVE1_SHIFT);
val |=
wdr3->gamma_pre[pos +
1] << (reg_flag ?
WDR3_GAMMA_PRE_CURVE1_SHIFT :
WDR3_GAMMA_PRE_CURVE2_SHIFT);
if (reg_flag)
REG_SET_SLICE(val, WDR3_GAMMA_PRE_CURVE2,
wdr3->gamma_pre[pos + 2]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_gamma_pre[i]), val);
val =
wdr3->gamma_up[pos] << (reg_flag ?
WDR3_GAMMA_UP_CURVE0_SHIFT :
WDR3_GAMMA_UP_CURVE1_SHIFT);
val |=
wdr3->gamma_up[pos +
1] << (reg_flag ? WDR3_GAMMA_UP_CURVE1_SHIFT
: WDR3_GAMMA_UP_CURVE2_SHIFT);
if (reg_flag)
REG_SET_SLICE(val, WDR3_GAMMA_UP_CURVE2,
wdr3->gamma_up[pos + 2]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_gamma_up[i]), val);
val =
wdr3->gamma_down[pos] << (reg_flag ?
WDR3_GAMMA_DOWN_CURVE0_SHIFT :
WDR3_GAMMA_DOWN_CURVE1_SHIFT);
val |=
wdr3->gamma_down[pos +
1] << (reg_flag ?
WDR3_GAMMA_DOWN_CURVE1_SHIFT :
WDR3_GAMMA_DOWN_CURVE2_SHIFT);
if (reg_flag)
REG_SET_SLICE(val, WDR3_GAMMA_DOWN_CURVE2,
wdr3->gamma_down[pos + 2]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_gamma_down[i]), val);
val =
wdr3->distance_weight[pos] << (reg_flag ?
WDR3_DISTANCE_WEIGHT_CURVE0_SHIFT
:
WDR3_DISTANCE_WEIGHT_CURVE1_SHIFT);
val |=
wdr3->distance_weight[pos +
1] << (reg_flag ?
WDR3_DISTANCE_WEIGHT_CURVE1_SHIFT
:
WDR3_DISTANCE_WEIGHT_CURVE2_SHIFT);
if (reg_flag)
REG_SET_SLICE(val, WDR3_DISTANCE_WEIGHT_CURVE2,
wdr3->distance_weight[pos + 2]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_distance_weight[i]), val);
val =
wdr3->difference_weight[pos] << (reg_flag ?
WDR3_DIFFERENCE_WEIGHT_CURVE0_SHIFT
:
WDR3_DIFFERENCE_WEIGHT_CURVE1_SHIFT);
val |=
wdr3->difference_weight[pos +
1] << (reg_flag ?
WDR3_DIFFERENCE_WEIGHT_CURVE1_SHIFT
:
WDR3_DIFFERENCE_WEIGHT_CURVE2_SHIFT);
if (reg_flag)
REG_SET_SLICE(val, WDR3_DIFFERENCE_WEIGHT_CURVE2,
wdr3->difference_weight[pos + 2]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_difference_weight[i]),
val);
}
for (i = 0; i < 7; i++) {
val = 0;
REG_SET_SLICE(val, WDR3_GLOBAL_CURVE_INVERT0,
wdr3->invert_curve[i * 2]);
REG_SET_SLICE(val, WDR3_GLOBAL_CURVE_INVERT1,
wdr3->invert_curve[i * 2 + 1]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_invert_curve[i]), val);
val = 0;
REG_SET_SLICE(val, WDR3_LINEAR_CURVE_INVERT0,
wdr3->invert_linear[i * 2]);
REG_SET_SLICE(val, WDR3_LINEAR_CURVE_INVERT1,
wdr3->invert_linear[i * 2 + 1]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_invert_linear[i]), val);
}
isp_wdr3_shift_0 = 0;
REG_SET_SLICE(isp_wdr3_shift_0, WDR3_HISTOGRAM_SHIFT0, wdr3->shift[0]);
REG_SET_SLICE(isp_wdr3_shift_0, WDR3_HISTOGRAM_SHIFT1, wdr3->shift[1]);
REG_SET_SLICE(isp_wdr3_shift_0, WDR3_HISTOGRAM_SHIFT2, wdr3->shift[2]);
REG_SET_SLICE(isp_wdr3_shift_0, WDR3_HISTOGRAM_SHIFT3, wdr3->shift[3]);
REG_SET_SLICE(isp_wdr3_shift_0, WDR3_HISTOGRAM_SHIFT4, wdr3->shift[4]);
REG_SET_SLICE(isp_wdr3_shift_0, WDR3_HISTOGRAM_SHIFT5, wdr3->shift[5]);
REG_SET_SLICE(isp_wdr3_shift_0, WDR3_HISTOGRAM_SHIFT6, wdr3->shift[6]);
REG_SET_SLICE(isp_wdr3_shift_0, WDR3_HISTOGRAM_SHIFT7, wdr3->shift[7]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_shift_0), isp_wdr3_shift_0);
isp_wdr3_shift_1 = 0;
REG_SET_SLICE(isp_wdr3_shift_1, WDR3_HISTOGRAM_SHIFT8, wdr3->shift[8]);
REG_SET_SLICE(isp_wdr3_shift_1, WDR3_HISTOGRAM_SHIFT9, wdr3->shift[9]);
REG_SET_SLICE(isp_wdr3_shift_1, WDR3_HISTOGRAM_SHIFT10,
wdr3->shift[10]);
REG_SET_SLICE(isp_wdr3_shift_1, WDR3_HISTOGRAM_SHIFT11,
wdr3->shift[11]);
REG_SET_SLICE(isp_wdr3_shift_1, WDR3_HISTOGRAM_SHIFT12,
wdr3->shift[12]);
REG_SET_SLICE(isp_wdr3_shift_1, WDR3_HISTOGRAM_SHIFT13,
wdr3->shift[13]);
isp_write_reg(dev, REG_ADDR(isp_wdr3_shift_1), isp_wdr3_shift_1);
{
uint32_t isp_wdr3_ctrl = isp_read_reg(dev, REG_ADDR(isp_wdr3_ctrl));
REG_SET_SLICE(isp_wdr3_ctrl, WDR3_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_wdr3_ctrl), isp_wdr3_ctrl);
}
}
#endif
int isp_enable_wdr3(struct isp_ic_dev *dev)
{
#ifndef ISP_WDR_V3
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
struct isp_wdr3_context *wdr3 = &dev->wdr3;
int32_t isp_wdr3_ctrl = isp_read_reg(dev, REG_ADDR(isp_wdr3_ctrl));
wdr3->enable = true;
REG_SET_SLICE(isp_wdr3_ctrl, WDR3_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_wdr3_ctrl), isp_wdr3_ctrl);
{
uint32_t isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
}
return 0;
#endif
}
int isp_disable_wdr3(struct isp_ic_dev *dev)
{
#ifndef ISP_WDR_V3
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
struct isp_wdr3_context *wdr3 = &dev->wdr3;
int32_t isp_wdr3_ctrl = isp_read_reg(dev, REG_ADDR(isp_wdr3_ctrl));
wdr3->enable = false;
REG_SET_SLICE(isp_wdr3_ctrl, WDR3_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_wdr3_ctrl), isp_wdr3_ctrl);
{
uint32_t isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
}
return 0;
#endif
}
int isp_u_wdr3(struct isp_ic_dev *dev)
{
#ifndef ISP_WDR_V3
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
wdr3_hw_init(dev);
return 0;
#endif
}
int isp_s_wdr3(struct isp_ic_dev *dev)
{
#ifndef ISP_WDR_V3
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
struct isp_wdr3_context *wdr3 = &dev->wdr3;
u32 isp_wdr3_strength = isp_read_reg(dev, REG_ADDR(isp_wdr3_strength));
u32 width = isp_read_reg(dev, REG_ADDR(isp_acq_h_size));
u32 height = isp_read_reg(dev, REG_ADDR(isp_acq_v_size));
width /= 32;
height /= 32;
REG_SET_SLICE(isp_wdr3_strength, WDR3_MAXIMUM_GAIN, wdr3->max_gain);
REG_SET_SLICE(isp_wdr3_strength, WDR3_GLOBAL_STRENGTH,
wdr3->global_strength);
REG_SET_SLICE(isp_wdr3_strength, WDR3_LOCAL_STRENGTH, 128);
REG_SET_SLICE(isp_wdr3_strength, WDR3_TOTAL_STRENGTH, wdr3->strength);
isp_write_reg(dev, REG_ADDR(isp_wdr3_block_size),
width | (height << 9));
isp_write_reg(dev, REG_ADDR(isp_wdr3_strength), isp_wdr3_strength);
isp_write_reg(dev, REG_ADDR(isp_wdr3_strength_shd), isp_wdr3_strength); /* cmodel use */
{
uint32_t isp_ctrl = isp_read_reg(dev, REG_ADDR(isp_ctrl));
REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, 1);
isp_write_reg(dev, REG_ADDR(isp_ctrl), isp_ctrl);
}
return 0;
#endif
}

515
vvcam/isp/isp_wdr4.c Executable file
View File

@@ -0,0 +1,515 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <linux/io.h>
#include <linux/module.h>
#endif
#include "mrv_all_bits.h"
#include "isp_ioctl.h"
#include "isp_types.h"
#ifdef ISP_WDR_V4
#define WDR4_WW (32)
#define WDR4_HH (32)
#define WDR4_MAX_VALUE (1048575)
#define WDR4_GAIN_SHIFT (2)
#define WDR4_NORMALIZE (1024)
#define WDR4_NORMALIZE_SHIFT (10)
#ifdef ISP_WDR_V4_20BIT
#define MODULE_INPUT_BIT_DEPTH (20)
#else
#define MODULE_INPUT_BIT_DEPTH (12)
#endif
#define MODULE_OUTPUT_BIT_DEPTH (12)
extern MrvAllRegister_t *all_regs;
static void wdr4_config_curve(struct isp_ic_dev *dev)
{
struct isp_wdr4_context *wdr4 = &dev->wdr4;
u32 pos, i , val;
//u32 isp_wdr4_shift_0;
//u32 isp_wdr4_shift0_0;
//initialize the histogram && entropy && gamma_pre && gamma_up && gamma_down && invert_linear
for (i = 0; i < 7; i++) {
u32 val_high_bit, val_low_bit;
pos = i * 3;
//get the curve that combined with high && low data
val_high_bit = (wdr4->histogram[pos] >> 10) & (0x3ff);
val_low_bit = wdr4->histogram[pos] & (0x3ff);
val = val_low_bit << WDR4_HISTOGRAM_CURVE0_0_SHIFT ;
val |= wdr4->histogram[pos +1];
isp_write_reg(dev, REG_ADDR(isp_wdr4_histogram_0) + i * 2 * ISP_REG_GAP, val);
val = val_high_bit << WDR4_HISTOGRAM_CURVE0_0_SHIFT ;
if (pos + 2 < WDR4_BIN) {
val |= wdr4->histogram[pos +2];
}
isp_write_reg(dev, REG_ADDR(isp_wdr4_histogram_0) + (i *2 + 1) * ISP_REG_GAP, val);
//get the value that combined with high && low data
val_high_bit = (wdr4->gamma_pre[pos] >> 10) & 0x3ff;
val_low_bit = (wdr4->gamma_pre[pos] & 0x3ff) ;
val = val_low_bit << WDR4_GAMMA_PRE_CURVE0_1_SHIFT ;
val |= wdr4->gamma_pre[pos +1];
isp_write_reg(dev, REG_ADDR(isp_wdr4_gamma_pre_0) + (i * 2) * ISP_REG_GAP, val);
val = val_high_bit << WDR4_GAMMA_PRE_CURVE0_1_SHIFT ;
if (pos + 2 < WDR4_BIN)
val |= wdr4->gamma_pre[pos +2];
isp_write_reg(dev, REG_ADDR(isp_wdr4_gamma_pre_0) + (i *2 + 1) * ISP_REG_GAP, val);
//get the value that combined with high && low data
val_high_bit = (wdr4->gamma_up[pos] >> 10) & 0x3ff;
val_low_bit = (wdr4->gamma_up[pos] & 0x3ff);
val = val_low_bit <<WDR4_GAMMA_UP_CURVE0_0_SHIFT;
val |= wdr4->gamma_up[pos +1];
isp_write_reg(dev, REG_ADDR(isp_wdr4_gamma_up_0) + (i * 2) * ISP_REG_GAP, val);
val = val_high_bit <<WDR4_GAMMA_UP_CURVE0_1_SHIFT;
if (pos + 2 < WDR4_BIN)
val |= wdr4->gamma_up[pos +2];
isp_write_reg(dev, REG_ADDR(isp_wdr4_gamma_up_0) + (i *2 + 1) * ISP_REG_GAP, val);
//get the value that combined with high && low data
val_high_bit = (wdr4->invert_linear[pos] >> 9) & 0x1ff;
val_low_bit = (wdr4->invert_linear[pos] & 0x1ff);
val = val_low_bit << WDR4_LINEAR_CURVE_INVERT0_0_SHIFT;
val |= wdr4->invert_linear[pos +1];
isp_write_reg(dev, REG_ADDR(isp_wdr4_invert_linear_0) + (i * 2) * ISP_REG_GAP, val);
val = val_high_bit << WDR4_LINEAR_CURVE_INVERT0_0_SHIFT;
if (pos + 2 < WDR4_BIN)
val |= wdr4->invert_linear[pos +2];
isp_write_reg(dev, REG_ADDR(isp_wdr4_invert_linear_0) + (i *2 + 1) * ISP_REG_GAP, val);
if (pos + 2 < WDR4_BIN) {
val = wdr4->entropy[pos] << WDR4_ENTROPY_CONVERT0_SHIFT ;
val |= wdr4->entropy[pos +1] << WDR4_ENTROPY_CONVERT1_SHIFT;
val |= wdr4->entropy[pos +2] << WDR4_ENTROPY_CONVERT2_SHIFT;
} else { //the lasw two entropy
val = wdr4->entropy[pos] << WDR4_ENTROPY_CONVERT18_SHIFT ;
val |= wdr4->entropy[pos +1] << WDR4_ENTROPY_CONVERT19_SHIFT;
}
isp_write_reg(dev, REG_ADDR(isp_wdr4_entropy_0) + i * ISP_REG_GAP, val);
if (pos + 2 < WDR4_BIN) {
val = wdr4->gamma_down[pos] << WDR4_GAMMA_DOWN_CURVE0_SHIFT ;
val |= wdr4->gamma_down[pos +1] << WDR4_GAMMA_DOWN_CURVE1_SHIFT;
val |= wdr4->gamma_down[pos +2] << WDR4_GAMMA_DOWN_CURVE2_SHIFT;
} else { //the lasw two entropy
val = wdr4->gamma_down[pos] << WDR4_GAMMA_DOWN_CURVE18_SHIFT ;
val |= wdr4->gamma_down[pos +1] << WDR4_GAMMA_DOWN_CURVE19_SHIFT;
}
isp_write_reg(dev, REG_ADDR(isp_wdr4_gamma_down_0) + i * ISP_REG_GAP, val);
}
//config the distance weight && different weight && SMOOTH INVERT
for (i = 0 ; i < 5 ; i++) {
pos = i * ISP_REG_GAP;
val = wdr4->distance_weight[pos] << WDR4_DISTANCE_WEIGHT_CURVE0_SHIFT ;
val |= wdr4->distance_weight[pos +1] << WDR4_DISTANCE_WEIGHT_CURVE1_SHIFT;
val |= wdr4->distance_weight[pos +2] << WDR4_DISTANCE_WEIGHT_CURVE2_SHIFT;
val |= wdr4->distance_weight[pos +3] << WDR4_DISTANCE_WEIGHT_CURVE3_SHIFT;
isp_write_reg(dev, REG_ADDR(isp_wdr4_distance_weight_0) + i * ISP_REG_GAP, val);
val = wdr4->difference_weight[pos] << WDR4_DIFFERENCE_WEIGHT_CURVE0_SHIFT ;
val |= wdr4->difference_weight[pos +1] << WDR4_DIFFERENCE_WEIGHT_CURVE1_SHIFT;
val |= wdr4->difference_weight[pos +2] << WDR4_DIFFERENCE_WEIGHT_CURVE2_SHIFT;
val |= wdr4->difference_weight[pos +3] << WDR4_DIFFERENCE_WEIGHT_CURVE3_SHIFT;
isp_write_reg(dev, REG_ADDR(isp_wdr4_difference_weight_0) + i * ISP_REG_GAP, val);
val = wdr4->smooth_invert[pos] << WDR4_SMOOTH_INVERT_CURVE0_SHIFT ;
val |= wdr4->smooth_invert[pos +1] << WDR4_SMOOTH_INVERT_CURVE1_SHIFT;
val |= wdr4->smooth_invert[pos +2] << WDR4_SMOOTH_INVERT_CURVE2_SHIFT;
val |= wdr4->smooth_invert[pos +3] << WDR4_SMOOTH_INVERT_CURVE3_SHIFT;
isp_write_reg(dev, REG_ADDR(isp_wdr4_smooth_invert_0) + i * ISP_REG_GAP, val);
}
for (i = 0; i < 10; i++) {
val = 0;
REG_SET_SLICE(val, WDR4_GLOBAL_CURVE_INVERT0,
wdr4->invert_curve[i * 2]);
REG_SET_SLICE(val, WDR4_GLOBAL_CURVE_INVERT1,
wdr4->invert_curve[i * 2 + 1]);
isp_write_reg(dev, REG_ADDR(isp_wdr4_invert_curve_0) + i * ISP_REG_GAP, val);
}
for (i = 0 ; i < 4; i++) {
val = 0 ;
pos = i * 6;
if (pos + 3 > WDR4_BIN) {
REG_SET_SLICE(val, WDR4_HISTOGRAM_SHIFT18, wdr4->shift[ pos +0]);
REG_SET_SLICE(val, WDR4_HISTOGRAM_SHIFT19, wdr4->shift[ pos +1]);
} else {
REG_SET_SLICE(val, WDR4_HISTOGRAM_SHIFT0, wdr4->shift[ pos +0]);
REG_SET_SLICE(val, WDR4_HISTOGRAM_SHIFT1, wdr4->shift[ pos +1]);
REG_SET_SLICE(val, WDR4_HISTOGRAM_SHIFT2, wdr4->shift[ pos +2]);
REG_SET_SLICE(val, WDR4_HISTOGRAM_SHIFT3, wdr4->shift[ pos +3]);
REG_SET_SLICE(val, WDR4_HISTOGRAM_SHIFT4, wdr4->shift[ pos +4]);
REG_SET_SLICE(val, WDR4_HISTOGRAM_SHIFT5, wdr4->shift[ pos +5]);
}
isp_write_reg(dev, REG_ADDR(isp_wdr4_shift_0) + i * ISP_REG_GAP, val);
}
for (i = 0 ; i < 3; i++) {
val = 0 ;
pos = i * 8;
if (pos + 5 > WDR4_BIN) {
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT16, wdr4->shift0[ pos +0]);
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT17, wdr4->shift0[ pos +1]);
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT18, wdr4->shift0[ pos +2]);
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT19, wdr4->shift0[ pos +3]);
} else {
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT0, wdr4->shift0[ pos +0]);
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT1, wdr4->shift0[ pos +1]);
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT2, wdr4->shift0[ pos +2]);
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT3, wdr4->shift0[ pos +3]);
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT4, wdr4->shift0[ pos +4]);
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT5, wdr4->shift0[ pos +5]);
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT6, wdr4->shift0[ pos +6]);
REG_SET_SLICE(val, WDR4_HISTOGRAM0_SHIFT7, wdr4->shift0[ pos +7]);
}
isp_write_reg(dev, REG_ADDR(isp_wdr4_shift0_0) + i * ISP_REG_GAP, val);
}
}
static void wdr4_hw_init(struct isp_ic_dev *dev)
{
// struct isp_wdr4_context *wdr4 = &dev->wdr4;
u32 width, height;
u32 slice_sigma_height;
u32 slice_sigma_width;
u32 slice_sigma_value;
u32 slice_block_width;
u32 slice_block_height;
u32 isp_wdr4_block_size;
u32 slice_block_area_inverse;
u32 isp_wdr4_value_weight;
u32 isp_wdr4_pixel_slope;
u32 isp_wdr4_entropy_slope;
u32 isp_wdr4_sigma_width;
u32 isp_wdr4_sigma_height;
u32 isp_wdr4_sigma_value;
u32 isp_wdr4_block_flag_width;
u32 isp_wdr4_block_flag_height;
u32 isp_wdr4_strength;
u32 isp_wdr4_block_area_factor;
u32 width_left;
u32 width_count = 0;
u32 height_left;
u32 height_count = 0;
u32 isp_wdr4_strength_0 = 0, isp_wdr4_strength_1 = 0, isp_wdr4_contrast = 0;
int i;
u8 isp_wdr4_low_strength, isp_wdr4_high_strength, isp_wdr4_global_strength;
u8 isp_wdr4_local_strength;
u32 slice_pixel_shift;
u32 slice_output_shift;// isp_wdr4_normalize_shift;
u32 isp_wdr4_shift;// isp_wdr4_gain_shift_bit;
pr_info("enter %s\n", __func__);
width = isp_read_reg(dev, REG_ADDR(isp_acq_h_size));
height = isp_read_reg(dev, REG_ADDR(isp_acq_v_size));
pr_info("isp_wdr4 res: %d %d \n", width, height);
/* firware initilization */
isp_wdr4_strength = 128; // valid values: [0,128]; isp_wdr4 will merge original and enhanced image
// together based on this value.
// 128: use enhanced image completely; 0: use original image completely
isp_wdr4_low_strength = 16; // Valid values: [0,255]; if hdr off, limit the maximum gain for image enhancement
// if hdr on, control low light area information. Higher:haver more low light information
isp_wdr4_high_strength = 60; //valid values:[0, 128]: control high light area information. Higher:have more high
// light information
isp_wdr4_global_strength = 128; // Valid values: [0,128]
// isp_wdr4 will increase global contrast based on this value.
// 128: use strongest contrast; 0: on contrast increasing.
isp_wdr4_local_strength = 128; // valid values: [0,128]
// wdr4 will increase local contrast based on this value.
// 128: use strongest contrast; 0: on contrast increasing.
isp_wdr4_strength_0 = isp_read_reg(dev, REG_ADDR(isp_wdr4_strength_0));
REG_SET_SLICE(isp_wdr4_strength_0, WDR4_LOCAL_STRENGTH, isp_wdr4_local_strength);
REG_SET_SLICE(isp_wdr4_strength_0, WDR4_GLOBAL_STRENGTH, isp_wdr4_global_strength);
REG_SET_SLICE(isp_wdr4_strength_0, WDR4_LOW_STRENGTH, isp_wdr4_low_strength);
REG_SET_SLICE(isp_wdr4_strength_0, WDR4_TOTAL_STRENGTH,isp_wdr4_strength);
isp_write_reg(dev, REG_ADDR(isp_wdr4_strength_0), isp_wdr4_strength_0);
isp_wdr4_strength_1 = isp_read_reg(dev, REG_ADDR(isp_wdr4_strength_1));
REG_SET_SLICE(isp_wdr4_strength_1, WDR4_HIGH_STRENGTH, isp_wdr4_high_strength);
REG_SET_SLICE(isp_wdr4_strength_1, WDR4_DRC_BAYER_RATIO, 14);
REG_SET_SLICE(isp_wdr4_strength_1, WDR4_DRC_BAYER_RATIOLSVS, 14);
isp_write_reg(dev, REG_ADDR(isp_wdr4_strength_1), isp_wdr4_strength_1);
isp_wdr4_contrast = isp_read_reg(dev, REG_ADDR(isp_wdr4_contrast));
REG_SET_SLICE(isp_wdr4_contrast , WDR4_CONTRAST ,0); //valid values:[-1023~1023]:control contrast of image,.higher:image have stronger contrast
REG_SET_SLICE(isp_wdr4_contrast , WDR4_FLAT_STRENGTH ,8);//valid values:[0, 19]:adjust flat area. Higher:flat area stretched more strong
REG_SET_SLICE(isp_wdr4_contrast , WDR4_FLAT_THR ,1); //valid values:[0, 20]:judge flat region.
isp_write_reg(dev, REG_ADDR(isp_wdr4_contrast), isp_wdr4_contrast);
isp_wdr4_pixel_slope = isp_read_reg(dev, REG_ADDR(isp_wdr4_pixel_slope));
REG_SET_SLICE(isp_wdr4_pixel_slope , WDR4_PIXEL_MERGE_SLOPE , 128);
REG_SET_SLICE(isp_wdr4_pixel_slope , WDR4_PIXEL_MERGE_BASE , 128);
REG_SET_SLICE(isp_wdr4_pixel_slope , WDR4_PIXEL_ADJUST_SLOPE ,128);
REG_SET_SLICE(isp_wdr4_pixel_slope , WDR4_PIXEL_ADJUST_BASE , 128);
isp_write_reg(dev, REG_ADDR(isp_wdr4_pixel_slope), isp_wdr4_pixel_slope);
isp_wdr4_entropy_slope = isp_read_reg(dev, REG_ADDR(isp_wdr4_entropy_slope));
REG_SET_SLICE(isp_wdr4_entropy_slope , WDR4_ENTROPY_SLOPE , 0xc8);
REG_SET_SLICE(isp_wdr4_entropy_slope , WDR4_ENTROPY_BASE ,0x02bc);
isp_write_reg(dev, REG_ADDR(isp_wdr4_entropy_slope), isp_wdr4_entropy_slope);
isp_wdr4_value_weight = isp_read_reg(dev, REG_ADDR(isp_wdr4_value_weight));
REG_SET_SLICE(isp_wdr4_value_weight , WDR4_VALUE_WEIGHT_0 , 6);
REG_SET_SLICE(isp_wdr4_value_weight , WDR4_VALUE_WEIGHT_1 , 5);
REG_SET_SLICE(isp_wdr4_value_weight , WDR4_VALUE_WEIGHT_2 , 5);
REG_SET_SLICE(isp_wdr4_value_weight , WDR4_VALUE_WEIGHT_3 , 16);
isp_write_reg(dev, REG_ADDR(isp_wdr4_value_weight), isp_wdr4_value_weight);
slice_block_width = width / WDR4_WW;
slice_block_height = height / WDR4_HH;
isp_wdr4_block_size = 0;
REG_SET_SLICE(isp_wdr4_block_size, WDR4_BLOCK_WIDTH, slice_block_width);
REG_SET_SLICE(isp_wdr4_block_size, WDR4_BLOCK_HEIGHT, slice_block_height);
isp_write_reg(dev, REG_ADDR(isp_wdr4_block_size), isp_wdr4_block_size);
slice_block_area_inverse =
WDR4_NORMALIZE * WDR4_NORMALIZE / (slice_block_width *
slice_block_height);
isp_wdr4_block_area_factor = isp_read_reg(dev, REG_ADDR(isp_wdr4_block_area_factor));
REG_SET_SLICE(isp_wdr4_block_area_factor, WDR4_BLOCK_AREA_INVERSE, slice_block_area_inverse);
isp_write_reg(dev, REG_ADDR(isp_wdr4_block_area_factor), isp_wdr4_block_area_factor);
slice_sigma_height =
WDR4_NORMALIZE * WDR4_NORMALIZE / slice_block_height;
slice_sigma_width = WDR4_NORMALIZE * WDR4_NORMALIZE / slice_block_width;
slice_sigma_value = WDR4_NORMALIZE * WDR4_NORMALIZE/ WDR4_MAX_VALUE;
isp_wdr4_sigma_width =
isp_read_reg(dev, REG_ADDR(isp_wdr4_sigma_width));
REG_SET_SLICE(isp_wdr4_sigma_width, WDR4_BILITERAL_WIDTH_SIGMA,
slice_sigma_width);
isp_write_reg(dev, REG_ADDR(isp_wdr4_sigma_width),
isp_wdr4_sigma_width);
isp_wdr4_sigma_height = isp_read_reg(dev, REG_ADDR(isp_wdr4_sigma_height));
REG_SET_SLICE(isp_wdr4_sigma_height, WDR4_BILITERAL_HEIGHT_SIGMA,
slice_sigma_height);
isp_write_reg(dev, REG_ADDR(isp_wdr4_sigma_height),
isp_wdr4_sigma_height);
isp_wdr4_sigma_value = isp_read_reg(dev, REG_ADDR(isp_wdr4_sigma_value));
REG_SET_SLICE(isp_wdr4_sigma_value, WDR4_BILITERAL_VALUE_SIGMA,
slice_sigma_value);
isp_write_reg(dev, REG_ADDR(isp_wdr4_sigma_value),
isp_wdr4_sigma_value);
/* block flag configuration */
width_left = width - slice_block_width * WDR4_WW;
height_left = height - slice_block_height * WDR4_HH;
// isp_wdr4_gain_shift_bit = 8;
// isp_wdr4_normalize_shift = 10;
slice_pixel_shift = MODULE_INPUT_BIT_DEPTH - 15;
slice_output_shift = MODULE_INPUT_BIT_DEPTH - MODULE_OUTPUT_BIT_DEPTH;
isp_wdr4_shift = isp_read_reg(dev, REG_ADDR(isp_wdr4_shift));
REG_SET_SLICE(isp_wdr4_shift, WDR4_PIXEL_SHIFT_BIT, slice_pixel_shift);
REG_SET_SLICE(isp_wdr4_shift, WDR4_OUTPUT_SHIFT_BIT,
slice_output_shift);
isp_write_reg(dev, REG_ADDR(isp_wdr4_shift), isp_wdr4_shift);
/* block flag configuration */
width_left = width - slice_block_width * WDR4_WW;
height_left = height - slice_block_height * WDR4_HH;
isp_wdr4_block_flag_width = 0;
isp_wdr4_block_flag_height = 0;
for (i = 0, width_count = 0;
(i < WDR4_WW) && (width_count < width_left); i++, width_count++) {
isp_wdr4_block_flag_width |= (1 << i);
}
isp_write_reg(dev, REG_ADDR(isp_wdr4_block_flag_width), isp_wdr4_block_flag_width);
for (i = 0, height_count = 0;
(i < WDR4_HH) && (height_count < height_left);
i++, height_count++) {
isp_wdr4_block_flag_height |= (1 << i);
}
isp_write_reg(dev, REG_ADDR(isp_wdr4_block_flag_height), isp_wdr4_block_flag_height);
isp_wdr4_block_size = isp_read_reg(dev, REG_ADDR(isp_wdr4_block_size));
REG_SET_SLICE(isp_wdr4_block_size, WDR4_BLOCK_WIDTH, slice_block_width);
REG_SET_SLICE(isp_wdr4_block_size, WDR4_BLOCK_HEIGHT,
slice_block_height);
isp_write_reg(dev, REG_ADDR(isp_wdr4_block_size), isp_wdr4_block_size);
wdr4_config_curve(dev);
#if 1
{
uint32_t isp_wdr4_ctrl = isp_read_reg(dev, REG_ADDR(isp_wdr4_ctrl));
REG_SET_SLICE(isp_wdr4_ctrl, WDR4_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_wdr4_ctrl), isp_wdr4_ctrl);
}
#endif
}
int isp_enable_wdr4(struct isp_ic_dev *dev)
{
#ifndef ISP_WDR_V4
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
int32_t isp_wdr4_ctrl;
struct isp_wdr4_context *wdr4 = &dev->wdr4;
isp_read_reg(dev, REG_ADDR(isp_pre_filt_ctrl));
isp_read_reg(dev, REG_ADDR(isp_dmsc_cac_y_norm_shd));
isp_wdr4_ctrl = isp_read_reg(dev, REG_ADDR(isp_wdr4_ctrl));
wdr4->enable = true;
REG_SET_SLICE(isp_wdr4_ctrl, WDR4_ENABLE, 1);
isp_write_reg(dev, REG_ADDR(isp_wdr4_ctrl), isp_wdr4_ctrl);
return 0;
#endif
}
int isp_disable_wdr4(struct isp_ic_dev *dev)
{
#ifndef ISP_WDR_V4
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
struct isp_wdr4_context *wdr4 = &dev->wdr4;
int32_t isp_wdr4_ctrl = isp_read_reg(dev, REG_ADDR(isp_wdr4_ctrl));
wdr4->enable = false;
REG_SET_SLICE(isp_wdr4_ctrl, WDR4_ENABLE, 0);
isp_write_reg(dev, REG_ADDR(isp_wdr4_ctrl), isp_wdr4_ctrl);
return 0;
#endif
}
int isp_u_wdr4(struct isp_ic_dev *dev)
{
#ifndef ISP_WDR_V4
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
wdr4_hw_init(dev);
return 0;
#endif
}
int isp_s_wdr4(struct isp_ic_dev *dev)
{
#ifndef ISP_WDR_V4
pr_err("unsupported function: %s", __func__);
return -EINVAL;
#else
struct isp_wdr4_context *wdr4 = &dev->wdr4;
u32 isp_wdr4_strength_0 = isp_read_reg(dev, REG_ADDR(isp_wdr4_strength_0));
u32 isp_wdr4_strength_1 = isp_read_reg(dev, REG_ADDR(isp_wdr4_strength_1));
u32 isp_wdr4_contrast = isp_read_reg(dev, REG_ADDR(isp_wdr4_contrast));
u32 width = isp_read_reg(dev, REG_ADDR(isp_acq_h_size));
u32 height = isp_read_reg(dev, REG_ADDR(isp_acq_v_size));
width /= 32;
height /= 32;
REG_SET_SLICE(isp_wdr4_strength_0, WDR4_LOW_STRENGTH, wdr4->low_gain);
REG_SET_SLICE(isp_wdr4_strength_0, WDR4_GLOBAL_STRENGTH,
wdr4->global_strength);
REG_SET_SLICE(isp_wdr4_strength_0, WDR4_LOCAL_STRENGTH, 128);
REG_SET_SLICE(isp_wdr4_strength_0, WDR4_TOTAL_STRENGTH, wdr4->strength);
REG_SET_SLICE(isp_wdr4_strength_1, WDR4_HIGH_STRENGTH, wdr4->high_strength);
REG_SET_SLICE(isp_wdr4_contrast , WDR4_CONTRAST, wdr4->contrast); //valid values:[-1023~1023]:control contrast of image,.higher:image have stronger contrast
REG_SET_SLICE(isp_wdr4_contrast , WDR4_FLAT_STRENGTH, wdr4->flat_strength);//valid values:[0, 19]:adjust flat area. Higher:flat area stretched more strong
REG_SET_SLICE(isp_wdr4_contrast , WDR4_FLAT_THR, wdr4->flat_threshold); //valid values:[0, 20]:judge flat region.
isp_write_reg(dev, REG_ADDR(isp_wdr4_contrast), isp_wdr4_contrast);
isp_write_reg(dev, REG_ADDR(isp_wdr4_block_size),
width | (height << 9));
isp_write_reg(dev, REG_ADDR(isp_wdr4_strength_0), isp_wdr4_strength_0);
isp_write_reg(dev, REG_ADDR(isp_wdr4_strength_1), isp_wdr4_strength_1);
isp_write_reg(dev, REG_ADDR(isp_wdr4_strength_0_shd), isp_wdr4_strength_0); /* cmodel use */
isp_write_reg(dev, REG_ADDR(isp_wdr4_strength_1_shd), isp_wdr4_strength_1); /* cmodel use */
return 0;
#endif
}
#endif

10446
vvcam/isp/mrv_all_bits.h Executable file

File diff suppressed because it is too large Load Diff

20364
vvcam/isp/mrv_all_regs.h Executable file

File diff suppressed because it is too large Load Diff

1148
vvcam/isp/mrv_dec_all_regs.h Executable file

File diff suppressed because it is too large Load Diff

24
vvcam/native/Makefile Executable file
View File

@@ -0,0 +1,24 @@
include Param.mk
all:
echo VERSION_CFG = $(VERSION_CFG)
@cd gpio_i2c; make || exit $$?; cp vvcam_i2c.ko ../bin/
@cd sensor; make || exit $$?; cp vvcam_sensor.ko ../bin/
@cd flash_led; make || exit $$?; cp vvcam_flash_led.ko ../bin/
@cd isp; make || exit $$?; cp vvcam_isp.ko ../bin/
@cd soc; make || exit $$?; cp vvcam_soc.ko ../bin/
@cd dw200; make || exit $$?; cp vvcam_dw200.ko ../bin/
@cd dec400; make || exit $$?; cp vvcam_dec400.ko ../bin/
@cd vi_pre; make || exit $$?; cp vi_pre.ko ../bin/
@cd video; make || exit $$?; cp thead_video.ko ../bin/
clean:
@cd gpio_i2c; make clean
@cd csi; make clean
@cd sensor; make clean
@cd flash_led; make clean
@cd isp; make clean
@cd soc; make clean
@cd dw200; make clean
@cd dec400; make clean
@cd vi_pre; make clean
@cd video; make clean
cleanall:

66
vvcam/native/Param.mk Executable file
View File

@@ -0,0 +1,66 @@
#VERSION_CFG := ISP8000NANO_V1802
#KERNEL :=/opt/vsi_isp_kernel_tree/4.8.0-41-generic-x86/build
#KERNEL :=/lib/modules/$(shell uname -r)/build
KERNEL :=$(LINUX_DIR)
KERNEL_SRC :=$(KERNEL)
EXTRA_CFLAGS += -DWITH_VVCAM
EXTRA_CFLAGS += -DWITH_VVCAM_DUAL
EXTRA_CFLAGS += -DVVCSI0_BASE=0xDE200000
EXTRA_CFLAGS += -DVVCSI1_BASE=0xDE300000
EXTRA_CFLAGS += -DVVCSI_SIZE=0x00200000
EXTRA_CFLAGS += -DVVCAM_I2C0_BASE=0xDE3080f0
EXTRA_CFLAGS += -DVVCAM_I2C1_BASE=0xDE3080f4
EXTRA_CFLAGS += -DVVCAM_I2C_SIZE=0x00000004
EXTRA_CFLAGS += -DVVSENSOR_I2C_BUS0=8
EXTRA_CFLAGS += -DVVSENSOR_I2C_BUS1=9
ifeq ($(VERSION_CFG), ISP8000_V2009)
EXTRA_CFLAGS += -DVVISP0_BASE=0xDE600000
EXTRA_CFLAGS += -DVVISP1_BASE=0xDE700000
else
EXTRA_CFLAGS += -DVVISP0_BASE=0xFFE4100000
EXTRA_CFLAGS += -DVVISP1_BASE=0xFFE4110000
endif
EXTRA_CFLAGS += -DISP_REG_SIZE=0x00010000
EXTRA_CFLAGS += -DDWE_REG_BASE=0xFFE4130C00
EXTRA_CFLAGS += -DDWE_REG_SIZE=0x00010000
#EXTRA_CFLAGS += -DDWE_REG_RESET=0xffe4130000
EXTRA_CFLAGS += -DVSE_REG_BASE=0xFFE4130000
EXTRA_CFLAGS += -DVSE_REG_SIZE=0x00010000
#EXTRA_CFLAGS += -DVSE_REG_RESET=0xffe4130000
EXTRA_CFLAGS += -DRESERVED_ISP0_MEM_BASE=0xA0000000
EXTRA_CFLAGS += -DRESERVED_ISP0_MEM_SIZE=0x1000000
EXTRA_CFLAGS += -DRESERVED_ISP1_MEM_BASE=0xB0000000
EXTRA_CFLAGS += -DRESERVED_ISP1_MEM_SIZE=0x1000000
EXTRA_CFLAGS += -DVVCTRL_BASE=0xFFE4040000
EXTRA_CFLAGS += -DVVCTRL_SIZE=0x00001000
EXTRA_CFLAGS += -DISP_HW_NUMBER=1
EXTRA_CFLAGS += -DUSE_FPGA
EXTRA_CFLAGS += -D$(VERSION_CFG)
#SENSR0_TYPE := ov2775
#SENSR1_TYPE := ov2775
#SENSR0_TYPE := imx334
#SENSR1_TYPE := imx334
SENSR0_TYPE := ov5693
SENSR1_TYPE := ov5693
#SENSR0_TYPE := imx290
#SENSR1_TYPE := imx290
PLATFORM := gen6
FLASH_LED_TYPE1 := aw36515
FLASH_LED_TYPE2 := aw36413

56
vvcam/native/Param_base.mk Executable file
View File

@@ -0,0 +1,56 @@
#VERSION_CFG := ISP8000NANO_V1802
#KERNEL :=/opt/vsi_isp_kernel_tree/4.8.0-41-generic-x86/build
KERNEL :=/lib/modules/$(shell uname -r)/build
EXTRA_CFLAGS += -DWITH_VVCAM
EXTRA_CFLAGS += -DWITH_VVCAM_DUAL
EXTRA_CFLAGS += -DVVCSI0_BASE=0xDE200000
EXTRA_CFLAGS += -DVVCSI1_BASE=0xDE300000
EXTRA_CFLAGS += -DVVCSI_SIZE=0x00200000
EXTRA_CFLAGS += -DVVCAM_I2C0_BASE=0xDE3080f0
EXTRA_CFLAGS += -DVVCAM_I2C1_BASE=0xDE3080f4
EXTRA_CFLAGS += -DVVCAM_I2C_SIZE=0x00000004
EXTRA_CFLAGS += -DVVSENSOR_I2C_BUS0=8
EXTRA_CFLAGS += -DVVSENSOR_I2C_BUS1=9
ifeq ($(VERSION_CFG), ISP8000_V2009)
EXTRA_CFLAGS += -DVVISP0_BASE=0xDE600000
EXTRA_CFLAGS += -DVVISP1_BASE=0xDE700000
else
EXTRA_CFLAGS += -DVVISP0_BASE=0xDE000000
EXTRA_CFLAGS += -DVVISP1_BASE=0xDE100000
endif
EXTRA_CFLAGS += -DISP_REG_SIZE=0x00010000
EXTRA_CFLAGS += -DDWE_REG_BASE=0xDE380C00
EXTRA_CFLAGS += -DDWE_REG_SIZE=0x00010000
EXTRA_CFLAGS += -DDWE_REG_RESET=0xDE308250
EXTRA_CFLAGS += -DVSE_REG_BASE=0xDE380000
EXTRA_CFLAGS += -DVSE_REG_SIZE=0x00010000
EXTRA_CFLAGS += -DVSE_REG_RESET=0xDE308250
EXTRA_CFLAGS += -DRESERVED_MEM_BASE=0x10000000
EXTRA_CFLAGS += -DRESERVED_MEM_SIZE=0x10000000
EXTRA_CFLAGS += -DVVCTRL_BASE=0xFFE4040000
EXTRA_CFLAGS += -DVVCTRL_SIZE=0x00001000
EXTRA_CFLAGS += -DISP_HW_NUMBER=1
EXTRA_CFLAGS += -DUSE_FPGA
EXTRA_CFLAGS += -D$(VERSION_CFG)
SENSR0_TYPE := ov2775
SENSR1_TYPE := ov2775
#SENSR0_TYPE := ov5693
#SENSR1_TYPE := ov5693
PLATFORM := gen6
FLASH_LED_TYPE1 : = aw36515
FLASH_LED_TYPE2 : = aw36413

View File

@@ -0,0 +1,62 @@
#VERSION_CFG := ISP8000NANO_V1802
#KERNEL :=/opt/vsi_isp_kernel_tree/4.8.0-41-generic-x86/build
#KERNEL :=/lib/modules/$(shell uname -r)/build
KERNEL :=$(LINUX_DIR)
EXTRA_CFLAGS += -DWITH_VVCAM
EXTRA_CFLAGS += -DWITH_VVCAM_DUAL
EXTRA_CFLAGS += -DVVCSI0_BASE=0xDE200000
EXTRA_CFLAGS += -DVVCSI1_BASE=0xDE300000
EXTRA_CFLAGS += -DVVCSI_SIZE=0x00200000
EXTRA_CFLAGS += -DVVCAM_I2C0_BASE=0xDE3080f0
EXTRA_CFLAGS += -DVVCAM_I2C1_BASE=0xDE3080f4
EXTRA_CFLAGS += -DVVCAM_I2C_SIZE=0x00000004
EXTRA_CFLAGS += -DVVSENSOR_I2C_BUS0=8
EXTRA_CFLAGS += -DVVSENSOR_I2C_BUS1=9
ifeq ($(VERSION_CFG), ISP8000_V2009)
EXTRA_CFLAGS += -DVVISP0_BASE=0xDE600000
EXTRA_CFLAGS += -DVVISP1_BASE=0xDE700000
else
EXTRA_CFLAGS += -DVVISP0_BASE=0xFFE4100000
EXTRA_CFLAGS += -DVVISP1_BASE=0xFFE4110000
endif
EXTRA_CFLAGS += -DISP_REG_SIZE=0x00010000
EXTRA_CFLAGS += -DDWE_REG_BASE=0xFFE4130C00
EXTRA_CFLAGS += -DDWE_REG_SIZE=0x00010000
#EXTRA_CFLAGS += -DDWE_REG_RESET=0xffe4130000
EXTRA_CFLAGS += -DVSE_REG_BASE=0xFFE4130000
EXTRA_CFLAGS += -DVSE_REG_SIZE=0x00010000
#EXTRA_CFLAGS += -DVSE_REG_RESET=0xffe4130000
EXTRA_CFLAGS += -DRESERVED_MEM_BASE=0xC0000000
EXTRA_CFLAGS += -DRESERVED_MEM_SIZE=0x10000000
EXTRA_CFLAGS += -DVVCTRL_BASE=0xDE308000
EXTRA_CFLAGS += -DVVCTRL_SIZE=0x00001000
EXTRA_CFLAGS += -DISP_HW_NUMBER=1
EXTRA_CFLAGS += -DUSE_FPGA
EXTRA_CFLAGS += -D$(VERSION_CFG)
SENSR0_TYPE := ov2775
SENSR1_TYPE := ov2775
#SENSR0_TYPE := imx334
#SENSR1_TYPE := imx334
#SENSR0_TYPE := ov5693
#SENSR1_TYPE := ov5693
#SENSR0_TYPE := imx290
#SENSR1_TYPE := imx290
PLATFORM := gen6
FLASH_LED_TYPE1 : = aw36515
FLASH_LED_TYPE2 : = aw36413

15
vvcam/native/bin/insmod.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
#insmod vvcam_i2c
modprobe vvcam_sensor
#insmod vvcam_csi
modprobe bm_visys
modprobe bm_csi
modprobe vvcam_isp
modprobe vvcam_isp_ry
modprobe vvcam_soc
modprobe vvcam_dw200
modprobe vi_pre
modprobe vvcam_dec400
modprobe thead_video
modprobe vidmem
modprobe vvcam_flash_led

13
vvcam/native/bin/rmmod.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/sh
rmmod vvcam_dw200
rmmod vvcam_soc
rmmod vvcam_isp
rmmod vvcam_isp_ry
rmmod vvcam_sensor
rmmod vvcam_csi
rmmod vvcam_i2c
rmmod vi_pre
rmmod vvcam_dec400
rmmod thead_video
rmmod vidmem
rmmod vvcam_flash_led

23
vvcam/native/csi/Makefile Executable file
View File

@@ -0,0 +1,23 @@
include $(PWD)/../Param.mk
include $(PWD)/../../version/$(VERSION_CFG).mk
TARGET = vvcam_csi
#obj-m +=$(TARGET).o
#
#$(TARGET)-objs += csi_ioctl.o
#$(TARGET)-objs += ./nwl/platform_nwl_csi_driver.o
#$(TARGET)-objs += vvcam_csi_driver.o
EXTRA_CFLAGS += -I$(PWD)/
EXTRA_CFLAGS += -I$(PWD)/nwl/
PWD :=$(shell pwd)
all:
make -C $(KERNEL) M=$(PWD) modules
modules_install:
make -C $(KERNEL_SRC) M=$(SRC) modules_install
clean:
rm -rf $($(TARGET)-objs)
# make -C $(KERNEL) M=`pwd` clean

23
vvcam/native/csi/Makefilee Executable file
View File

@@ -0,0 +1,23 @@
include $(PWD)/../Param.mk
include $(PWD)/../../version/$(VERSION_CFG).mk
TARGET = vvcam_csi
obj-m +=$(TARGET).o
$(TARGET)-objs += csi_ioctl.o
$(TARGET)-objs += ./nwl/platform_nwl_csi_driver.o
$(TARGET)-objs += vvcam_csi_driver.o
EXTRA_CFLAGS += -I$(PWD)/
EXTRA_CFLAGS += -I$(PWD)/nwl/
PWD :=$(shell pwd)
all:
make -C $(KERNEL) M=$(PWD) modules
modules_install:
make -C $(KERNEL_SRC) M=$(SRC) modules_install
clean:
rm -rf $($(TARGET)-objs)
# make -C $(KERNEL) M=`pwd` clean

90
vvcam/native/csi/bm_csi_dphy.c Executable file
View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: liuyitong <yitong.lyt@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/poll.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/debugfs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include "bm_printk.h"
#include "bm_csi_ioctl.h"
#include "bm_csi_hw.h"
#include "bm_csi_dphy.h"
#include "dw-dphy-rx.h"
#define check_retval(x)\
do {\
if ((x))\
return -EIO;\
} while (0)
#define REG_DPHY_OFFSET 0x40
int bm_csi_dphy_write_reg(struct bm_csi_drvdata *drvdata, void *__user args)
{
struct bm_csi_reg_t reg;
check_retval(copy_from_user(&reg, args, sizeof(reg)));
struct dw_dphy_rx *dphy = drvdata->dphy;
writel(reg.value, dphy->base_address + reg.offset);
bm_info("%s addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
}
int bm_csi_dphy_init(struct bm_csi_drvdata *drvdata, void *__user args)
{
struct dw_dphy_rx *dphy = drvdata->dphy;
/*
dphy->dphy_freq = 20000000;
dphy->phy_type = 1;
dphy->dphy_te_len = BIT12;
dphy->lanes_config = CTRL_4_LANES;
dphy->dphy_gen = GEN3;
dphy->max_lanes = CTRL_4_LANES;
dphy->lp_time = 1000; //ns
dphy->base_address = drvdata->base + REG_DPHY_OFFSET;
//dphy->dphy1_if_addr =visysreg
dw_dphy_reset(dphy);
dw_dphy_power_on(dphy);
dw_dphy_init(dphy);
*/
return 0;
}
int bm_csi_dphy_uinit(struct bm_csi_drvdata *drvdata, void *__user args)
{
struct dw_dphy_rx *dphy = &drvdata->dphy;
dw_dphy_reset(dphy);
dw_dphy_power_off(dphy);
}
int bm_csi_dphy_reset(struct bm_csi_drvdata *drvdata, void *__user args)
{
struct dw_dphy_rx *dphy = &drvdata->dphy;
dw_dphy_reset(dphy);
}

19
vvcam/native/csi/bm_csi_dphy.h Executable file
View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: liuyitong <yitong.lyt@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _BM_CSI_DPHY_H_
#define _BM_CSI_DPHY_H_
#include <linux/platform_device.h>
int dw_dphy_rx_probe(struct platform_device *pdev, void __iomem *dphy1_if_addr);
int dw_dphy_rx_remove(struct platform_device *pdev);
#endif /*_BM_CSI_DPHY_H_ */

331
vvcam/native/csi/bm_csi_driver.c Executable file
View File

@@ -0,0 +1,331 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: liuyitong <yitong.lyt@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/poll.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/debugfs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include "bm_printk.h"
#include "bm_csi_ioctl.h"
#include "bm_csi_hw.h"
#include "bm_csi_dphy.h"
//#include "dw-csi-plat.h"
#define BM_DRIVER_NAME "vivcsi"
#define BM_DRIVER_MAXCNT 3
static struct class *bm_driver_class;
static unsigned int bm_driver_major = 0;
static unsigned int bm_driver_minor = 0;
static unsigned int device_register_index = 0;
#define check_retval(x)\
do {\
if ((x))\
return -EIO;\
} while (0)
static unsigned int bm_csi_poll(struct file * filp, poll_table *wait)
{
return 0;
}
void bm_csi_work(struct work_struct *work)
{
}
irqreturn_t bm_csi_irq(int irq, void *dev_id)
{
bm_info("enter %s\n", __func__);
return IRQ_HANDLED;
}
static int bm_csi_open(struct inode * inode, struct file * file)
{
struct bm_csi_drvdata *drvdata;
bm_info("enter %s\n", __func__);
drvdata = container_of(inode->i_cdev, struct bm_csi_drvdata, cdev);
file->private_data = drvdata;
return 0;
};
static long bm_csi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret = 0;
struct bm_csi_drvdata *drvdata;
bm_info("enter %s\n", __func__);
drvdata = file->private_data;
if (drvdata == NULL) {
bm_err("%s:file private is null point error\n", __func__);
return -ENOMEM;
}
mutex_lock(&drvdata->mutex);
switch (cmd) {
case BMCSI_IOC_WRITE_REG:
ret = bm_csi_write_reg(drvdata, (void *)arg);
break;
case BMCSI_IOC_READ_REG:
ret = bm_csi_read_reg(drvdata, (void *)arg);
break;
case BMCSI_IOC_INIT:
ret = bm_csi_init(drvdata, (void *)arg);
break;
case BMCSI_IOC_EXIT:
ret = bm_csi_exit(drvdata, (void *)arg);
break;
case BMCSI_IOC_S_RESET:
ret = bm_csi_reset(drvdata, (void *)arg);
break;
case BMCSI_IOC_S_POWER:
ret = bm_csi_set_power(drvdata, (void *)arg);
break;
case BMCSI_IOC_G_POWER:
ret = bm_csi_get_power(drvdata, (void *)arg);
break;
case BMCSI_IOC_S_CLOCK:
ret = bm_csi_set_clock(drvdata, (void *)arg);
break;
case BMCSI_IOC_G_CLOCK:
ret = bm_csi_get_clock(drvdata, (void *)arg);
break;
case BMCSI_IOC_S_STREAM:
ret = bm_csi_set_stream(drvdata, (void *)arg);
break;
case BMCSI_IOC_G_STREAM:
ret = bm_csi_get_stream(drvdata, (void *)arg);
break;
case BMCSI_IOC_S_FMT:
ret = bm_csi_set_fmt(drvdata, (void *)arg);
break;
case BMCSI_IOC_G_FMT:
ret = bm_csi_get_fmt(drvdata, (void *)arg);
break;
case BMCSI_IOC_S_VC_SELECT:
ret = bm_csi_set_vc_select(drvdata, (void *)arg);
break;
case BMCSI_IOC_G_VC_SELECT:
ret = bm_csi_get_vc_select(drvdata, (void *)arg);
break;
case BMCSI_IOC_S_LANE_CFG:
ret = bm_csi_set_lane_cfg(drvdata, (void *)arg);
break;
case BMCSI_IOC_MAX:
break;
default:
ret = -EPERM;
bm_err("%s: unsupported command %d", __func__, cmd);
break;
}
mutex_unlock(&drvdata->mutex);
return ret;
};
static int bm_csi_release(struct inode * inode, struct file * file)
{
bm_info("enter %s\n", __func__);
return 0;
};
static int bm_csi_mmap(struct file *pFile, struct vm_area_struct *vma)
{
bm_info("enter %s\n", __func__);
return 0;
};
struct file_operations bm_csi_fops = {
.owner = THIS_MODULE,
.open = bm_csi_open,
.release = bm_csi_release,
.unlocked_ioctl = bm_csi_ioctl,
.mmap = bm_csi_mmap,
.poll = bm_csi_poll,
};
static int bm_csi_probe(struct platform_device *pdev)
{
int ret = 0;
struct bm_csi_drvdata *drvdata;
struct resource *iores_mem;
void __iomem *visys_addr;
u32 value;
bm_info("enter %s\n", __func__);
pdev->id = device_register_index;
if (pdev->id >= BM_DRIVER_MAXCNT) {
bm_err("%s:pdev id is %d error\n", __func__, pdev->id);
return -EINVAL;
}
drvdata = devm_kzalloc(&pdev->dev,sizeof(struct bm_csi_drvdata), GFP_KERNEL);
if (drvdata == NULL) {
bm_err("%s:alloc struct drvdata error\n", __func__);
return -ENOMEM;
}
iores_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
drvdata->base = devm_ioremap_resource(&pdev->dev, iores_mem);
bm_info("%s: [%s%d]: drvdata->base=0x%px, phy_addr base=0x%llx\n", __func__,
BM_DRIVER_NAME, pdev->id, drvdata->base, iores_mem->start);
drvdata->device_idx = pdev->id;
mutex_init(&drvdata->mutex);
drvdata->irq_num = platform_get_irq(pdev, 0);
bm_info("%s:[%s%d]: pdriver_dev->irq_num=%d\n", __func__, "BM_CSI", pdev->id, drvdata->irq_num);
platform_set_drvdata(pdev, drvdata);
if (pdev->id == 0) {
if (bm_driver_major == 0) {
ret = alloc_chrdev_region(&drvdata->devt, 0, BM_DRIVER_MAXCNT, BM_DRIVER_NAME);
if (ret != 0) {
bm_err("%s:alloc_chrdev_region error\n", __func__);
return ret;
}
bm_driver_major = MAJOR(drvdata->devt);
bm_driver_minor = MINOR(drvdata->devt);
} else {
drvdata->devt = MKDEV(bm_driver_major, bm_driver_minor);
ret = register_chrdev_region(drvdata->devt, BM_DRIVER_MAXCNT, BM_DRIVER_NAME);
if (ret) {
bm_err("%s:register_chrdev_region error\n", __func__);
return ret;
}
}
bm_driver_class = class_create(THIS_MODULE, BM_DRIVER_NAME);
if (IS_ERR(bm_driver_class)) {
bm_err("%s[%d]:class_create error!\n", __func__, __LINE__);
return -EINVAL;
}
}
drvdata->devt = MKDEV(bm_driver_major, bm_driver_minor + pdev->id);
cdev_init(&drvdata->cdev, &bm_csi_fops);
ret = cdev_add(&drvdata->cdev, drvdata->devt, 1);
if ( ret ) {
bm_err("%s[%d]:cdev_add error!\n", __func__, __LINE__);
return ret;
} else {
bm_info("%s[%d]:cdev_add OK, major=%d, minor=%d\n", __func__, __LINE__,
bm_driver_major, bm_driver_minor + pdev->id);
}
drvdata->class = bm_driver_class;
device_create(drvdata->class, NULL, drvdata->devt,
drvdata, "%s%d", BM_DRIVER_NAME, pdev->id);
/*read version*/
value = readl(drvdata->base + 0x0);
bm_info("offset=04, value is:0x%08x\n", value);
//visys_addr = platform_get_resource(pdev, IORESOURCE_MEM, 1);
visys_addr = devm_platform_ioremap_resource(pdev, 1);
dw_dphy_rx_probe(pdev, visys_addr);
drvdata->reset = visys_addr;
dw_csi_probe(pdev);
device_register_index++;
bm_info("exit %s:[%s%d]\n", __func__, BM_DRIVER_NAME, pdev->id);
return 0;
}
static int bm_csi_remove(struct platform_device *pdev)
{
struct bm_csi_drvdata *drvdata;
bm_info("enter %s\n", __func__);
dw_dphy_rx_remove(pdev);
dw_csi_remove(pdev);
device_register_index--;
drvdata = platform_get_drvdata(pdev);
free_irq(drvdata->irq_num, drvdata);
cdev_del(&drvdata->cdev);
device_destroy(drvdata->class, drvdata->devt);
unregister_chrdev_region(drvdata->devt, BM_DRIVER_MAXCNT);
mutex_destroy(&drvdata->mutex);
if (device_register_index == 0) {
class_destroy(drvdata->class);
}
devm_kfree(&pdev->dev, drvdata);
bm_info("exit %s\n", __func__);
return 0;
}
static const struct of_device_id bm_csi_of_match[] = {
{ .compatible = "thead,light-bm-csi", },
{ /* sentinel */ },
};
static struct platform_driver bm_csi_driver = {
.probe = bm_csi_probe,
.remove = bm_csi_remove,
.driver = {
.name = BM_DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(bm_csi_of_match),
}
};
static int __init bm_csi_init_module(void)
{
int ret = 0;
bm_info("enter %s\n", __func__);
ret = platform_driver_register(&bm_csi_driver);
if (ret) {
bm_err("register platform driver failed.\n");
return ret;
}
return ret;
}
static void __exit bm_csi_exit_module(void)
{
bm_info("enter %s\n", __func__);
platform_driver_unregister(&bm_csi_driver);
}
module_init(bm_csi_init_module);
module_exit(bm_csi_exit_module);
MODULE_AUTHOR("Liu Yitong");
MODULE_DESCRIPTION("BAREMETAL-CSI");
MODULE_LICENSE("GPL");

155
vvcam/native/csi/bm_csi_hw.c Executable file
View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: liuyitong <yitong.lyt@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/poll.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/debugfs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include "bm_printk.h"
#include "bm_csi_ioctl.h"
#include "bm_csi_hw.h"
#include "dw-dphy-rx.h"
#include "bm_csi_dphy.h"
#define check_retval(x)\
do {\
if ((x))\
return -EIO;\
} while (0)
int bm_csi_write_reg(struct bm_csi_drvdata *drvdata, void *__user args)
{
struct bm_csi_reg_t reg;
check_retval(copy_from_user(&reg, args, sizeof(reg)));
writel(reg.value, drvdata->base + reg.offset);
bm_info("%s addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
return 0;
}
int bm_csi_read_reg(struct bm_csi_drvdata *drvdata, void *__user args)
{
struct bm_csi_reg_t reg;
check_retval(copy_from_user(&reg, args, sizeof(reg)));
reg.value = readl(drvdata->base + reg.offset);
check_retval(copy_to_user(args, &reg, sizeof(reg)));
bm_info("%s addr 0x%08x val 0x%08x\n", __func__, reg.offset, reg.value);
return 0;
}
int bm_csi_init(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: csi init\n", __func__);
return 0;
}
int bm_csi_exit(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: csi exit\n", __func__);
return 0;
}
int bm_csi_reset(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: csi reset success\n", __func__);
dw_csi_soc_reset(drvdata->reset);
//bm_csi_dphy_reset();
return 0;
}
static int csi_power_on_sta = 0;
int bm_csi_set_power(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: csi set power\n", __func__);
check_retval(copy_from_user(&csi_power_on_sta, args, sizeof(csi_power_on_sta)));
dw_mipi_csi_s_power(&drvdata->csi_dev, csi_power_on_sta);
return 0;
}
int bm_csi_get_power(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: csi get power\n", __func__);
check_retval(copy_to_user(args, &csi_power_on_sta, sizeof(csi_power_on_sta)));
return 0;
}
int bm_csi_set_clock(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: \n", __func__);
check_retval(copy_to_user(args, &csi_power_on_sta, sizeof(csi_power_on_sta)));
return 0;
}
int bm_csi_get_clock(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: \n", __func__);
return 0;
}
int bm_csi_set_stream(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: \n", __func__);
return 0;
}
int bm_csi_get_stream(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: \n", __func__);
return 0;
}
int bm_csi_set_fmt(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: \n", __func__);
return 0;
}
int bm_csi_get_fmt(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: \n", __func__);
return 0;
}
int bm_csi_set_vc_select(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: \n", __func__);
return 0;
}
int bm_csi_get_vc_select(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: \n", __func__);
return 0;
}
int bm_csi_set_lane_cfg(struct bm_csi_drvdata *drvdata, void *__user args)
{
bm_info("%s: \n", __func__);
return 0;
}

66
vvcam/native/csi/bm_csi_hw.h Executable file
View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: liuyitong <yitong.lyt@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _BM_CSI_HW_H_
#define _BM_CSI_HW_H_
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include "dw-dphy-rx.h"
#include "dw-mipi-csi.h"
#include "dw-csi-data.h"
#include "dw-dphy-data.h"
struct bm_csi_drvdata {
struct cdev cdev;
dev_t devt;
struct class *class;
struct mutex mutex;
unsigned int device_idx;
void __iomem *base;
void __iomem *reset;
struct dw_dphy_rx *dphy;
struct dw_csi csi_dev;
struct dw_csih_pdata csi_pdata;
struct dw_phy_pdata dphy_pdata;
int irq_num;
void *private; // can be bm_csi_drvdata_private, but not use now
};
struct bm_csi_drvdata_private {
int private_tmp;
};
int bm_csi_write_reg(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_read_reg(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_init(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_exit(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_reset(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_set_power(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_get_power(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_set_clock(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_get_clock(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_set_stream(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_get_stream(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_set_fmt(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_get_fmt(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_set_vc_select(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_get_vc_select(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_set_lane_cfg(struct bm_csi_drvdata *drvdata, void *__user args);
/*csi dphy*/
int bm_csi_dphy_write_reg(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_dphy_init(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_dphy_uinit(struct bm_csi_drvdata *drvdata, void *__user args);
int bm_csi_dphy_reset(struct bm_csi_drvdata *drvdata, void *__user args);
void dw_csi_soc_reset(void __iomem *io_mem);
int dw_csi_probe(struct platform_device *pdev);
int dw_csi_remove(struct platform_device *pdev);
#endif /* _BM_CSI_HW_H_*/

39
vvcam/native/csi/bm_csi_ioctl.h Executable file
View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: liuyitong <yitong.lyt@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _BM_CSI_IOCTL_H_
#define _BM_CSI_IOCTL_H_
#include <linux/ioctl.h>
enum {
BMCSI_IOC_S_RESET = 0x100,
BMCSI_IOC_S_POWER,
BMCSI_IOC_G_POWER,
BMCSI_IOC_S_CLOCK,
BMCSI_IOC_G_CLOCK,
BMCSI_IOC_S_STREAM,
BMCSI_IOC_G_STREAM,
BMCSI_IOC_S_FMT,
BMCSI_IOC_G_FMT,
BMCSI_IOC_S_VC_SELECT,
BMCSI_IOC_G_VC_SELECT,
BMCSI_IOC_S_LANE_CFG,
BMCSI_IOC_INIT,
BMCSI_IOC_EXIT,
BMCSI_IOC_WRITE_REG,
BMCSI_IOC_READ_REG,
BMCSI_IOC_MAX,
};
struct bm_csi_reg_t {
unsigned int offset;
unsigned int value;
};
#endif /* _BM_CSI_IOCTL_H_*/

46
vvcam/native/csi/bm_printk.h Executable file
View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2021 Alibaba Group Holding Limited
* Author: LuChongzhi <chongzhi.lcz@alibaba-inc.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __BM_PRINTK__
#define __BM_PRINTK__
#include <stdarg.h>
#include <linux/init.h>
#include <linux/kern_levels.h>
#include <linux/linkage.h>
#include <linux/cache.h>
/*
* These can be used to print at the various log levels.
* All of these will print unconditionally, although note that pr_debug()
* and other debug macros are compiled out unless either DEBUG is defined
* or CONFIG_DYNAMIC_DEBUG is set.
*/
#define bm_emerg(fmt, ...) \
printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
#define bm_alert(fmt, ...) \
printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
#define bm_crit(fmt, ...) \
printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
#define bm_err(fmt, ...) \
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
#define bm_warning(fmt, ...) \
printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
#define bm_warn pr_warning
#ifdef DEBUG
#define bm_notice(fmt, ...) \
printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
#define bm_info(fmt, ...) \
printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
#else
#define bm_notice(fmt, ...)
#define bm_info(fmt, ...)
#endif
#endif /* __BM_PRINTK__ */

64
vvcam/native/csi/csi_common.h Executable file
View File

@@ -0,0 +1,64 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _CSI_COMMON_H_
#define _CSI_COMMON_H_
extern int vvnative_csi_module_init(void * dev);
extern int vvnative_csi_module_exit(void * dev);
extern int vvnative_csi_set_stream_control(void * dev);
extern int vvnative_csi_set_cfg(void * dev);
extern int vvnative_csi_set_bit_shift(void *dev);
#endif

91
vvcam/native/csi/csi_ioctl.c Executable file
View File

@@ -0,0 +1,91 @@
/****************************************************************************
*
* 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 <linux/module.h>
#include <linux/uaccess.h>
#include "csi_ioctl.h"
#include "csi_common.h"
long csi_priv_ioctl(struct vvcam_csi_dev *dev, unsigned int cmd, void __user *args)
{
long ret = 0;
switch (cmd)
{
case VVCSI_IOC_S_STREAM:
copy_from_user(&dev->streaming_enable, args, sizeof(dev->streaming_enable));
ret = vvnative_csi_set_stream_control(dev);
break;
case VVCSI_IOC_S_LANE_CFG:
copy_from_user(&dev->csi_lane_cfg, args, sizeof(dev->csi_lane_cfg));
ret = vvnative_csi_set_cfg(dev);
break;
case VVCSI_IOC_S_BIT_SHIFT:
copy_from_user(&dev->bit_width, args, sizeof(dev->bit_width));
ret = vvnative_csi_set_bit_shift(dev);
break;
default:
ret = 0;
break;
}
return ret;
}

143
vvcam/native/csi/csi_ioctl.h Executable file
View File

@@ -0,0 +1,143 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _CSI_IOC_H_
#define _CSI_IOC_H_
#ifndef __KERNEL__
#include <stdint.h>
#endif
#include <linux/ioctl.h>
enum {
VVCSI_IOC_S_RESET = _IO('r', 0),
VVCSI_IOC_S_POWER,
VVCSI_IOC_G_POWER,
VVCSI_IOC_S_CLOCK,
VVCSI_IOC_G_CLOCK,
VVCSI_IOC_S_STREAM,
VVCSI_IOC_G_STREAM,
VVCSI_IOC_S_FMT,
VVCSI_IOC_G_FMT,
VVCSI_IOC_S_VC_SELECT,
VVCSI_IOC_G_VC_SELECT,
VVCSI_IOC_S_LANE_CFG,
VVCSI_IOC_S_BIT_SHIFT,
VVCSI_IOC_MAX,
};
struct csi_vc_select_context {
uint32_t csi_vc_select_mode;
uint32_t vc_channel;
};
struct csi_format_context {
uint32_t format;
uint32_t width;
uint32_t height;
};
struct vvcam_csi_hardware_function_s
{
int (*init)(void* dev);
int (*exit)(void* dev);
int (*reset)(void* dev);
int (*set_power)(void* dev);
int (*get_power)(void* dev);
int (*set_clock)(void* dev);
int (*get_clock)(void* dev);
int (*set_stream_control)(void* dev);
int (*get_stream_control)(void* dev);
int (*set_fmt)(void* dev);
int (*get_fmt)(void* dev);
int (*set_vc_select)(void* dev);
int (*get_vc_select)(void* dev);
int (*set_lane_cfg)(void* dev);
};
struct vvcam_csi_lane_cfg
{
uint32_t mipi_lane_num;
};
#ifdef __KERNEL__
struct vvcam_csi_dev {
void __iomem *base;
char name[16];
int present;
int device_idx;
uint32_t power_status;
uint32_t clock;
uint32_t bit_width;
uint32_t streaming_enable;
struct csi_vc_select_context csi_vc_select;
struct csi_format_context csi_format;
struct vvcam_csi_hardware_function_s csi_hard_func;
struct vvcam_csi_lane_cfg csi_lane_cfg;
void * csi_private;
};
// internal functions
long csi_priv_ioctl(struct vvcam_csi_dev *dev, unsigned int cmd, void __user *args);
#else
//User space connections
#endif
#endif // _CSI_IOC_H_

0
vvcam/native/csi/dphy_gen Executable file
View File

31
vvcam/native/csi/dw-csi-data.h Executable file
View File

@@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI CSI-2 platform data
*
* Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
*/
#include <linux/kernel.h>
#include "dw-mipi-csi-pltfrm.h"
#ifndef __DW_CSI_DATA__
#define __DW_CSI_DATA__
struct dw_csih_pdata {
u8 eotp_enabled;
u32 hs_freq;
u32 lanes;
u32 pclk;
u32 fps;
u32 bpp;
u8 id;
};
static const struct pdata_names csis[] = {
{ .name = "dw-csi.0", },
{ .name = "dw-csi.1", },
};
#endif /*__DW_CSI_DATA__ */

391
vvcam/native/csi/dw-csi-plat.c Executable file
View File

@@ -0,0 +1,391 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI CSI-2 Host controller driver.
* Platform driver
*
* Author: Luis Oliveira <luis.oliveira@synopsys.com>
*/
#include "dw-csi-data.h"
#include "dw-dphy-data.h"
#include "dw-csi-plat.h"
#include "bm_csi_hw.h"
const struct mipi_dt csi_dt[] = {
{
.hex = CSI_2_YUV420_8,
.name = "YUV420_8bits",
}, {
.hex = CSI_2_YUV420_10,
.name = "YUV420_10bits",
}, {
.hex = CSI_2_YUV420_8_LEG,
.name = "YUV420_8bits_LEGACY",
}, {
.hex = CSI_2_YUV420_8_SHIFT,
.name = "YUV420_8bits_SHIFT",
}, {
.hex = CSI_2_YUV420_10_SHIFT,
.name = "YUV420_10bits_SHIFT",
}, {
.hex = CSI_2_YUV422_8,
.name = "YUV442_8bits",
}, {
.hex = CSI_2_YUV422_10,
.name = "YUV442_10bits",
}, {
.hex = CSI_2_RGB444,
.name = "RGB444",
}, {
.hex = CSI_2_RGB555,
.name = "RGB555",
}, {
.hex = CSI_2_RGB565,
.name = "RGB565",
}, {
.hex = CSI_2_RGB666,
.name = "RGB666",
}, {
.hex = CSI_2_RGB888,
.name = "RGB888",
}, {
.hex = CSI_2_RAW6,
.name = "RAW6",
}, {
.hex = CSI_2_RAW7,
.name = "RAW7",
}, {
.hex = CSI_2_RAW8,
.name = "RAW8",
}, {
.hex = CSI_2_RAW10,
.name = "RAW10",
}, {
.hex = CSI_2_RAW12,
.name = "RAW12",
}, {
.hex = CSI_2_RAW14,
.name = "RAW14",
}, {
.hex = CSI_2_RAW16,
.name = "RAW16",
},
};
static struct mipi_fmt *
find_dw_mipi_csi_format(uint32_t mbus_code)
{
unsigned int i;
pr_info("%s entered mbus: 0x%x\n", __func__, mbus_code);
for (i = 0; i < ARRAY_SIZE(dw_mipi_csi_formats); i++)
if (mbus_code == dw_mipi_csi_formats[i].mbus_code) {
pr_info("Found mbus 0x%x\n", dw_mipi_csi_formats[i].mbus_code);
return &dw_mipi_csi_formats[i];
}
return NULL;
}
static int dw_mipi_csi_enum_mbus_code(int index, uint32_t *code)
{
if (index != 0)
return -EINVAL;
*code = dw_mipi_csi_formats[index].mbus_code;
return 0;
}
static struct mipi_fmt *
dw_mipi_csi_try_format(uint32_t mbus_code)
{
struct mipi_fmt *fmt;
fmt = find_dw_mipi_csi_format(mbus_code);
if (!fmt)
fmt = &dw_mipi_csi_formats[0];
return fmt;
}
struct mipi_fmt *
dw_mipi_csi_get_format(struct dw_csi *dev)
{
dev_info(dev->dev,
"%s got v4l2_mbus_pixelcode. 0x%x\n", __func__,
dev->fmt->mbus_code);
dev_info(dev->dev,
"%s got width. 0x%x\n", __func__,
dev->fmt->width);
dev_info(dev->dev,
"%s got height. 0x%x\n", __func__,
dev->fmt->height);
return dev->fmt;
}
static int
dw_mipi_csi_set_fmt(struct platform_device *pdev,
uint32_t mbus_code, uint32_t width, uint32_t height)
{
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *dev = &drvdata->csi_dev;
struct mipi_fmt *dev_fmt = NULL;
int i;
dev_info(dev->dev,
"%s got mbus_pixelcode. 0x%x\n", __func__,
mbus_code);
dev_fmt = dw_mipi_csi_try_format(mbus_code);
dev_info(dev->dev,
"%s got v4l2_mbus_pixelcode. 0x%x\n", __func__,
dev_fmt->mbus_code);
if (!dev_fmt)
return -EINVAL;
if (dev_fmt) {
dev->fmt->mbus_code = dev_fmt->mbus_code;
dev->fmt->width = width;
dev->fmt->height = height;
dw_mipi_csi_set_ipi_fmt(dev);
}
dev_info(dev->dev, "Width: %d, Height: %d of Demo\n", width, height);
if (width > 0 && height > 0) {
dw_mipi_csi_fill_timings(dev, width, height);
/*
demo_writel(dev,
DEMO_ACTIVE_WIDTH, fmt->format.width);
demo_writel(dev,
DEMO_ACTIVE_HEIGHT, fmt->format.height);
*/
dev_vdbg(dev->dev,
"(core/demosaic) : width=%d/%d, height=%d/%d\n",
dev->hw.htotal - (dev->hw.hbp
+ dev->hw.hsd
+ dev->hw.hsa),
width,
dev->hw.vactive,
height);
dev_info(dev->dev,
"(core/demosaic) : width=%d/%d, height=%d/%d\n",
dev->hw.htotal - (dev->hw.hbp
+ dev->hw.hsd
+ dev->hw.hsa),
width,
dev->hw.vactive,
height);
} else {
dev_vdbg(dev->dev, "%s unacceptable values 0x%x.\n",
__func__, width);
dev_vdbg(dev->dev, "%s unacceptable values 0x%x.\n",
__func__, height);
dev_info(dev->dev, "%s unacceptable values 0x%x.\n",
__func__, width);
dev_info(dev->dev, "%s unacceptable values 0x%x.\n",
__func__, height);
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(csi_dt); i++)
if (csi_dt[i].hex == dev->ipi_dt) {
dev_vdbg(dev->dev, "Using data type %s\n",
csi_dt[i].name);
dev_info(dev->dev, "Using data type %s\n",
csi_dt[i].name);
}
return 0;
}
static int
dw_mipi_csi_get_fmt(struct platform_device *pdev,
struct mipi_fmt *fmt)
{
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *dev = &drvdata->csi_dev;
struct mipi_fmt *mf = dw_mipi_csi_get_format(dev);
if (!mf)
return -EINVAL;
mutex_lock(&dev->lock);
*fmt = *mf;
mutex_unlock(&dev->lock);
return 0;
}
int dw_mipi_csi_s_power(struct dw_csi *dev, int on)
{
dev_info(dev->dev, "%s: on=%d\n", __func__, on);
if (on) {
dw_mipi_csi_hw_stdby(dev);
dw_mipi_csi_start(dev);
} else {
phy_power_off(dev->phy);
dw_mipi_csi_mask_irq_power_off(dev);
/* reset data type */
dev->ipi_dt = 0x0;
}
return 0;
}
int dw_mipi_csi_log_status(struct dw_csi *dev)
{
dw_mipi_csi_dump(dev);
return 0;
}
#if IS_ENABLED(CONFIG_VIDEO_ADV_DEBUG)
int
dw_mipi_csi_g_register(struct v4l2_subdev *sd, uint32_t reg)
{
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *dev = &drvdata->csi_dev;
dev_vdbg(dev->dev, "%s: reg=%llu\n", __func__, reg);
reg->val = dw_mipi_csi_read(dev, reg);
return 0;
}
#endif
#if 0
static int dw_mipi_csi_init_cfg(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg)
{
struct v4l2_mbus_framefmt *format =
v4l2_subdev_get_try_format(sd, cfg, 0);
format->colorspace = V4L2_COLORSPACE_SRGB;
format->code = MEDIA_BUS_FMT_RGB888_1X24;
format->field = V4L2_FIELD_NONE;
return 0;
}
#endif
static irqreturn_t dw_mipi_csi_irq1(int irq, void *dev_id)
{
struct dw_csi *csi_dev = dev_id;
dw_mipi_csi_irq_handler(csi_dev);
return IRQ_HANDLED;
}
void dw_csi_soc_reset(void __iomem *io_mem)
{
#define VISYS_SW_RST 0x100
uint32_t reg_val = 0;
reg_val = readl(io_mem + VISYS_SW_RST);
reg_val &= ~(1 << 16);
writel(reg_val, io_mem + VISYS_SW_RST);
reg_val |= 1 << 16;
writel(reg_val, io_mem + VISYS_SW_RST);
}
static const struct of_device_id dw_mipi_csi_of_match[];
int dw_csi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dw_csi *csi;
struct dw_dphy_rx *dphy;
struct dw_csih_pdata *pdata;
struct bm_csi_drvdata *drvdata;
int ret;
if (!IS_ENABLED(CONFIG_OF))
dev_vdbg(dev, "Probing started\n");
/* Resource allocation */
drvdata = platform_get_drvdata(pdev);
csi = &drvdata->csi_dev;
dphy = drvdata->dphy;
pdata = &drvdata->csi_pdata;
mutex_init(&csi->lock);
spin_lock_init(&csi->slock);
csi->dev = dev;
/*set csi phy*/
csi->phy = dphy->phy;
csi->base_address = drvdata->base;
if (IS_ERR(csi->base_address)) {
dev_err(dev, "base address not set.\n");
return PTR_ERR(csi->base_address);
}
csi->ctrl_irq_number = drvdata->irq_num;
if (csi->ctrl_irq_number < 0) {
dev_err(dev, "irq number %d not set.\n", csi->ctrl_irq_number);
ret = csi->ctrl_irq_number;
goto end;
}
ret = devm_request_irq(dev, csi->ctrl_irq_number,
dw_mipi_csi_irq1, IRQF_SHARED,
dev_name(dev), csi);
if (ret) {
dev_err(dev, "irq csi %d failed\n", pdata->id);
goto end;
}
csi->fmt = &dw_mipi_csi_formats[0];
csi->fmt->mbus_code = dw_mipi_csi_formats[0].mbus_code;
/*
to do pad init
*/
csi->hw.num_lanes = pdata->lanes;
csi->hw.pclk = pdata->pclk;
csi->hw.fps = pdata->fps;
csi->hw.dphy_freq = pdata->hs_freq;
//csi soc reset
dw_csi_soc_reset(drvdata->reset);
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
dw_csi_create_capabilities_sysfs(pdev);
#endif
dw_mipi_csi_get_version(csi);
dw_mipi_csi_specific_mappings(csi);
dw_mipi_csi_mask_irq_power_off(csi);
dev_info(dev, "DW MIPI CSI-2 Host registered successfully HW v%u.%u\n",
csi->hw_version_major, csi->hw_version_minor);
ret = phy_init(csi->phy);
if (ret) {
dev_err(&csi->phy->dev, "phy init failed --> %d\n", ret);
goto end;
}
return 0;
end:
return ret;
}
int dw_csi_remove(struct platform_device *pdev)
{
struct bm_csi_drvdata *drvdata;
drvdata = platform_get_drvdata(pdev);
dw_csi_remove_capabilities_sysfs(pdev);
//struct dw_csi *mipi_csi = &drvdata->csi_dev;
//csi soc reset
dw_csi_soc_reset(drvdata->reset);
dev_info(&pdev->dev, "DW MIPI CSI-2 Host module removed\n");
return 0;
}
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Luis Oliveira <luis.oliveira@synopsys.com>");
MODULE_DESCRIPTION("Synopsys DesignWare MIPI CSI-2 Host Platform driver");

146
vvcam/native/csi/dw-csi-plat.h Executable file
View File

@@ -0,0 +1,146 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018 Synopsys, Inc.
*
* Synopsys DesignWare MIPI CSI-2 Host controller driver.
* Supported bus formats
*
* Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
*/
#ifndef _DW_CSI_PLAT_H__
#define _DW_CSI_PLAT_H__
#include "dw-mipi-csi.h"
/** Color Space Converter Block **/
#define CSC_UNIT_NR 1
#define CSC_COREID 0x0000
#define CSC_CFG 0x0004
#define CSC_COEF_A(x) (0x0008 + ((x) * 4))
#define CSC_COEF_B(x) (0x0018 + ((x) * 4))
#define CSC_COEF_C(x) (0x0028 + ((x) * 4))
#define CSC_LIMIT_DN 0x0038
#define CSC_LIMIT_UP 0x003C
#define CSC_VID_CFG 0x0040
/** Demosaic Block **/
#define DEMO_CONTROL 0x0
#define DEMO_GLOBAL_INT_EN 0x4
#define DEMO_IP_INT_EN_REG 0x8
#define DEMO_IP_INT_SATUS_REG 0xC
#define DEMO_ACTIVE_WIDTH 0x10
#define DEMO_ACTIVE_HEIGHT 0x18
#define DEMO_BAYER_PHASE 0x28//0x20
#define BAYER_RGGB 0x0
#define BAYER_GRBG 0x1
#define BAYER_GBRG 0x2
#define BAYER_BGGR 0x3
/* Video formats supported by the MIPI CSI-2 */
static struct mipi_fmt dw_mipi_csi_formats[] = {
{
/* RAW 8 */
.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
.depth = 8,
}, {
/* RAW 6 */
.mbus_code = MEDIA_BUS_FMT_SBGGR6_1X8,
.depth = 8,
}, {
/* RAW 7 */
.mbus_code = MEDIA_BUS_FMT_SBGGR7_1X8,
.depth = 8,
}, {
/* RAW 10 */
.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
.depth = 10,
}, {
/* RAW 8 */
.mbus_code = 0x3001,
.depth = 8,
}, {
/* RAW 12 */
.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
.depth = 12,
}, {
/* RAW 14 */
.mbus_code = MEDIA_BUS_FMT_SBGGR14_1X14,
.depth = 14,
}, {
/* RAW 16 */
.mbus_code = MEDIA_BUS_FMT_SBGGR16_1X16,
.depth = 16,
}, {
/* RGB 666 */
.mbus_code = MEDIA_BUS_FMT_RGB666_1X18,
.depth = 18,
}, {
/* RGB 565 */
.mbus_code = MEDIA_BUS_FMT_RGB565_2X8_BE,
.depth = 16,
}, {
/* BGR 565 */
.mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE,
.depth = 16,
}, {
/* RGB 555 */
.mbus_code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
.depth = 16,
}, {
/* BGR 555 */
.mbus_code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
.depth = 16,
}, {
/* RGB 444 */
.mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE,
.depth = 16,
}, {
/* RGB 444 */
.mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE,
.depth = 16,
}, {
/* RGB 888 */
.mbus_code = MEDIA_BUS_FMT_RGB888_2X12_LE,
.depth = 24,
}, {
/* BGR 888 */
.mbus_code = MEDIA_BUS_FMT_RGB888_2X12_BE,
.depth = 24,
}, {
/* BGR 888 */
.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
.depth = 24,
}, {
/* YUV 422 8-bit */
.mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
.depth = 16,
}, {
/* YUV 422 10-bit */
.mbus_code = MEDIA_BUS_FMT_UYVY10_1X20,
.depth = 24,
}, {
/* YUV 420 8-bit LEGACY */
.mbus_code = MEDIA_BUS_FMT_Y8_1X8,
.depth = 8,
}, {
/* YUV 420 8-bit LEGACY */
.mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
.depth = 24,
}, {
/* YUV 420 10-bit */
.mbus_code = MEDIA_BUS_FMT_VUY8_1X24,
.depth = 24,
}, {
/* YUV 420 8-bit */
.mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
.depth = 24,
}, {
/* YUV 420 10-bit */
.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
.depth = 10,
},
};
#endif /* _DW_CSI_PLAT_H__ */

673
vvcam/native/csi/dw-csi-sysfs.c Executable file
View File

@@ -0,0 +1,673 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI CSI-2 Host controller driver.
* SysFS components for the platform driver
*
* Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
*/
#include "dw-mipi-csi.h"
#include "bm_csi_hw.h"
static ssize_t core_version_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "v.%d.%d*\n", csi_dev->hw_version_major,
csi_dev->hw_version_minor);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t n_lanes_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long lanes;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 10, &lanes);
if (ret < 0)
return ret;
if (lanes > 8) {
dev_err(dev, "Invalid number of lanes %lu\n", lanes);
return count;
}
dev_info(dev, "Lanes %lu\n", lanes);
csi_dev->hw.num_lanes = lanes;
return count;
}
static ssize_t n_lanes_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%d\n", csi_dev->hw.num_lanes);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t core_reset_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
/* Reset Controller and DPHY */
phy_reset(csi_dev->phy);
dw_mipi_csi_reset(csi_dev);
snprintf(buffer, 10, "Reset\n");
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t data_type_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long dt;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 16, &dt);
if (ret < 0)
return ret;
if (dt < 0x18 || dt > 0x2F) {
dev_err(dev, "Invalid data type %lx\n", dt);
return count;
}
dev_info(dev, "Data type 0x%lx\n", dt);
csi_dev->ipi_dt = dt;
dw_mipi_csi_set_ipi_fmt(csi_dev);
return count;
}
static ssize_t data_type_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%x\n", csi_dev->ipi_dt);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t hsa_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long hsa;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 16, &hsa);
if (ret < 0)
return ret;
if (hsa > 0xFFF) {
dev_err(dev, "Invalid HSA time %lx\n", hsa);
return count;
}
dev_info(dev, "HSA time 0x%lx\n", hsa);
csi_dev->hw.hsa = hsa;
return count;
}
static ssize_t hsa_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%x\n", csi_dev->hw.hsa);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t hbp_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long hbp;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 16, &hbp);
if (ret < 0)
return ret;
if (hbp > 0xFFF) {
dev_err(dev, "Invalid HBP time %lx\n", hbp);
return count;
}
dev_info(dev, "HBP time 0x%lx\n", hbp);
csi_dev->hw.hbp = hbp;
return count;
}
static ssize_t hbp_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%x\n", csi_dev->hw.hbp);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t hsd_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long hsd;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 16, &hsd);
if (ret < 0)
return ret;
if (hsd > 0xFFF) {
dev_err(dev, "Invalid HSD time %lx\n", hsd);
return count;
}
dev_info(dev, "HSD time 0x%lx\n", hsd);
csi_dev->hw.hsd = hsd;
return count;
}
static ssize_t hsd_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%x\n", csi_dev->hw.hsd);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t vsa_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long vsa;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 16, &vsa);
if (ret < 0)
return ret;
if (vsa > 0x3FF) {
dev_err(dev, "Invalid VSA period %lx\n", vsa);
return count;
}
dev_info(dev, "VSA period 0x%lx\n", vsa);
csi_dev->hw.vsa = vsa;
return count;
}
static ssize_t vsa_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%x\n", csi_dev->hw.vsa);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t vbp_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long vbp;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 16, &vbp);
if (ret < 0)
return ret;
if (vbp > 0x2FF) {
dev_err(dev, "Invalid VBP period %lx\n", vbp);
return count;
}
dev_info(dev, "VBP period 0x%lx\n", vbp);
csi_dev->hw.vbp = vbp;
return count;
}
static ssize_t vbp_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%x\n", csi_dev->hw.vbp);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t vfp_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long vfp;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 16, &vfp);
if (ret < 0)
return ret;
if (vfp > 0x3ff) {
dev_err(dev, "Invalid VFP period %lx\n", vfp);
return count;
}
dev_info(dev, "VFP period 0x%lx\n", vfp);
csi_dev->hw.vfp = vfp;
return count;
}
static ssize_t vfp_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%x\n", csi_dev->hw.vfp);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t virtual_channel_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long virtual_ch;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 10, &virtual_ch);
if (ret < 0)
return ret;
if ((signed int)virtual_ch < 0 || (signed int)virtual_ch > 8) {
dev_err(dev, "Invalid Virtual Channel %lu\n", virtual_ch);
return count;
}
dev_info(dev, "Virtual Channel %lu\n", virtual_ch);
csi_dev->hw.virtual_ch = virtual_ch;
return count;
}
static ssize_t virtual_channel_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%d\n", csi_dev->hw.virtual_ch);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t ipi_color_mode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long ipi_color_mode;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 10, &ipi_color_mode);
if (ret < 0)
return ret;
if ((signed int)ipi_color_mode < 0 || (signed int)ipi_color_mode > 1) {
dev_err(dev,
"Wrong Color Mode %lu, (48 bits -> 0 or 16 bits -> 1\n",
ipi_color_mode);
return count;
}
dev_info(dev, "IPI Color mode %lu\n", ipi_color_mode);
csi_dev->hw.ipi_color_mode = ipi_color_mode;
return count;
}
static ssize_t ipi_color_mode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%d\n", csi_dev->hw.ipi_color_mode);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t ipi_auto_flush_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long ipi_auto_flush;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 10, &ipi_auto_flush);
if (ret < 0)
return ret;
if ((signed int)ipi_auto_flush < 0 || (signed int)ipi_auto_flush > 1) {
dev_err(dev,
"Invalid Auto Flush Mode %lu, (No -> 0 or Yes -> 1\n",
ipi_auto_flush);
return count;
}
dev_info(dev, "IPI Auto Flush %lu\n", ipi_auto_flush);
csi_dev->hw.ipi_auto_flush = ipi_auto_flush;
return count;
}
static ssize_t ipi_auto_flush_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%d\n", csi_dev->hw.ipi_auto_flush);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t ipi_timings_mode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long ipi_mode;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 10, &ipi_mode);
if (ret < 0)
return ret;
if ((signed int)ipi_mode < 0 || (signed int)ipi_mode > 1) {
dev_err(dev,
"Invalid Timing Source %lu (Camera:0|Controller:1)\n",
ipi_mode);
return count;
}
dev_info(dev, "IPI Color mode %lu\n", ipi_mode);
csi_dev->hw.ipi_mode = ipi_mode;
return count;
}
static ssize_t ipi_timings_mode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%d\n", csi_dev->hw.ipi_mode);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t output_type_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long output;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 10, &output);
if (ret < 0)
return ret;
if ((signed int)output < 0 || (signed int)output > 1) {
dev_err(dev,
"Invalid Core output %lu to be used \
(IPI-> 0 or IDI->1 or BOTH- 2\n",
output);
return count;
}
dev_info(dev, "IPI Color mode %lu\n", output);
csi_dev->hw.output = output;
return count;
}
static ssize_t output_type_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
char buffer[10];
snprintf(buffer, 10, "%d\n", csi_dev->hw.output);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t csi_power_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned long on;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_csi *csi_dev = &drvdata->csi_dev;
ret = kstrtoul(buf, 10, &on);
if (ret < 0)
return ret;
dw_mipi_csi_s_power(csi_dev, on);
printk("csi set power: %lu\n", on);
return count;
}
static DEVICE_ATTR_RO(core_version);
static DEVICE_ATTR_RO(core_reset);
static DEVICE_ATTR_RW(n_lanes);
static DEVICE_ATTR_RW(data_type);
static DEVICE_ATTR_RW(hsa);
static DEVICE_ATTR_RW(hbp);
static DEVICE_ATTR_RW(hsd);
static DEVICE_ATTR_RW(vsa);
static DEVICE_ATTR_RW(vbp);
static DEVICE_ATTR_RW(vfp);
static DEVICE_ATTR_RW(virtual_channel);
static DEVICE_ATTR_RW(ipi_color_mode);
static DEVICE_ATTR_RW(ipi_auto_flush);
static DEVICE_ATTR_RW(ipi_timings_mode);
static DEVICE_ATTR_RW(output_type);
static DEVICE_ATTR_WO(csi_power);
int dw_csi_create_capabilities_sysfs(struct platform_device *pdev)
{
device_create_file(&pdev->dev, &dev_attr_core_version);
device_create_file(&pdev->dev, &dev_attr_core_reset);
device_create_file(&pdev->dev, &dev_attr_n_lanes);
device_create_file(&pdev->dev, &dev_attr_data_type);
device_create_file(&pdev->dev, &dev_attr_hsa);
device_create_file(&pdev->dev, &dev_attr_hbp);
device_create_file(&pdev->dev, &dev_attr_hsd);
device_create_file(&pdev->dev, &dev_attr_vsa);
device_create_file(&pdev->dev, &dev_attr_vbp);
device_create_file(&pdev->dev, &dev_attr_vfp);
device_create_file(&pdev->dev, &dev_attr_virtual_channel);
device_create_file(&pdev->dev, &dev_attr_ipi_color_mode);
device_create_file(&pdev->dev, &dev_attr_ipi_auto_flush);
device_create_file(&pdev->dev, &dev_attr_ipi_timings_mode);
device_create_file(&pdev->dev, &dev_attr_output_type);
device_create_file(&pdev->dev, &dev_attr_csi_power);
return 0;
}
int dw_csi_remove_capabilities_sysfs(struct platform_device *pdev)
{
device_remove_file(&pdev->dev, &dev_attr_core_version);
device_remove_file(&pdev->dev, &dev_attr_core_reset);
device_remove_file(&pdev->dev, &dev_attr_n_lanes);
device_remove_file(&pdev->dev, &dev_attr_data_type);
device_remove_file(&pdev->dev, &dev_attr_hsa);
device_remove_file(&pdev->dev, &dev_attr_hbp);
device_remove_file(&pdev->dev, &dev_attr_hsd);
device_remove_file(&pdev->dev, &dev_attr_vsa);
device_remove_file(&pdev->dev, &dev_attr_vbp);
device_remove_file(&pdev->dev, &dev_attr_vfp);
device_remove_file(&pdev->dev, &dev_attr_virtual_channel);
device_remove_file(&pdev->dev, &dev_attr_ipi_color_mode);
device_remove_file(&pdev->dev, &dev_attr_ipi_auto_flush);
device_remove_file(&pdev->dev, &dev_attr_ipi_timings_mode);
device_remove_file(&pdev->dev, &dev_attr_output_type);
device_remove_file(&pdev->dev, &dev_attr_csi_power);
return 0;
}

36
vvcam/native/csi/dw-dphy-data.h Executable file
View File

@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI D-PHY platform data
*
* Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
*/
#include <linux/phy/phy.h>
#include <linux/kernel.h>
#include <dw-mipi-csi-pltfrm.h>
#ifndef __DW_DPHY_DATA_H__
#define __DW_DPHY_DATA_H__
struct dw_phy_pdata {
u32 dphy_frequency;
u8 dphy_te_len;
u32 config_8l;
u8 dphy_gen;
u8 phy_type;
u8 id;
};
static const struct pdata_names phys[] = {
{ .name = "phy-dw-dphy.0.0", },
{ .name = "phy-dw-dphy.1.1", },
};
struct dw_dphy_rx;
struct plat_dw_dphy {
int (*get_resources)(struct device *dev, struct dw_dphy_rx *dphy);
};
#endif /*__DW_DPHY_DATA_H__ */

148
vvcam/native/csi/dw-dphy-plat.c Executable file
View File

@@ -0,0 +1,148 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI D-PHY controller driver.
* Platform driver
*
* Author: Luis Oliveira <luis.oliveira@synopsys.com>
*/
#include <dw-dphy-data.h>
#include <dw-csi-data.h>
#include "dw-dphy-rx.h"
#include "bm_csi_hw.h"
/* Global variable for compatibility mode, this could be override later */
static int phy_type = 1; //Changed to fit single phy 0 - single | 1 - 8 lanes phy
module_param(phy_type, int, 0664);
MODULE_PARM_DESC(phy_type, "Disable compatibility mode for D-PHY G128");
static struct phy_ops dw_dphy_ops = {
.init = dw_dphy_init,
.reset = dw_dphy_reset,
.power_on = dw_dphy_power_on,
.power_off = dw_dphy_power_off,
.owner = THIS_MODULE,
};
static int get_resources(struct device *dev, struct dw_dphy_rx *dphy)
{
int ret = 0;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_phy_pdata *pdata = &drvdata->dphy_pdata;
dphy->dphy_freq = pdata->dphy_frequency;
dphy->dphy_te_len = pdata->dphy_te_len;
dphy->dphy_gen = pdata->dphy_gen;
drvdata->dphy = dphy;
return ret;
}
static int phy_register(struct device *dev)
{
int ret = 0;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
struct dw_phy_pdata *pdata = &drvdata->dphy_pdata;
ret = phy_create_lookup(dphy->phy,
phys[pdata->id].name,
csis[pdata->id].name);
if (ret)
dev_err(dev, "Failed to create dphy lookup\n");
else
dev_warn(dev, "Created dphy lookup [%s] --> [%s]\n",
phys[pdata->id].name, csis[pdata->id].name);
return ret;
}
static void phy_unregister(struct device *dev)
{
if (!dev->of_node) {
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
struct dw_phy_pdata *pdata = &drvdata->dphy_pdata;
phy_remove_lookup(dphy->phy,
phys[pdata->id].name, csis[pdata->id].name);
dev_warn(dev, "Removed dphy lookup [%s] --> [%s]\n",
phys[pdata->id].name, csis[pdata->id].name);
}
}
#define REG_DPHY_OFFSET 0x40
int dw_dphy_rx_probe(struct platform_device *pdev, void __iomem *dphy1_if_addr)
{
struct device *dev = &pdev->dev;
struct dw_dphy_rx *dphy;
struct bm_csi_drvdata *drvdata;
dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
if (!dphy)
return -ENOMEM;
drvdata = platform_get_drvdata(pdev);
dphy->base_address = drvdata->base + REG_DPHY_OFFSET;
drvdata->dphy= dphy;
dphy->dphy1_if_addr = dphy1_if_addr;
if (IS_ERR(dphy->base_address)) {
dev_err(&pdev->dev, "error requesting base address\n");
return PTR_ERR(dphy->base_address);
}
if (get_resources(dev, dphy)) {
dev_err(dev, "failed to parse PHY resources\n");
return -EINVAL;
}
dphy->phy = devm_phy_create(dev, NULL, &dw_dphy_ops);
if (IS_ERR(dphy->phy)) {
dev_err(dev, "failed to create PHY\n");
return PTR_ERR(dphy->phy);
}
phy_set_drvdata(dphy->phy, dphy);
if (phy_register(dev)) {
dev_err(dev, "failed to register PHY\n");
return -EINVAL;
}
dphy->lp_time = 1000; /* 1000 ns */
dphy->lanes_config = dw_dphy_setup_config(dphy);
dev_info(&dphy->phy->dev, "Probing dphy finished\n");
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
dw_dphy_create_capabilities_sysfs(pdev);
#endif
return 0;
}
int dw_dphy_rx_remove(struct platform_device *pdev)
{
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
dev_info(&dphy->phy->dev, "phy removed\n");
phy_unregister(&pdev->dev);
dw_dphy_remove_capabilities_sysfs(pdev);
return 0;
}
MODULE_DESCRIPTION("Synopsys DesignWare MIPI DPHY Rx driver");
MODULE_AUTHOR("Luis Oliveira <lolivei@synopsys.com>");
MODULE_LICENSE("GPL v2");

622
vvcam/native/csi/dw-dphy-rx.c Executable file
View File

@@ -0,0 +1,622 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI D-PHY controller driver
* Core functions
*
* Author: Luis Oliveira <luis.oliveira@synopsys.com>
*/
#include "dw-dphy-rx.h"
#include "bm_csi_dphy.h"
#include "bm_printk.h"
struct range_dphy_gen2 {
u32 freq;
u8 hsfregrange;
};
struct range_dphy_gen2 range_gen2[] = {
{ 80, 0x00 }, { 90, 0x10 }, { 100, 0x20 }, { 110, 0x30 },
{ 120, 0x01 }, { 130, 0x11 }, { 140, 0x21 }, { 150, 0x31 },
{ 160, 0x02 }, { 170, 0x12 }, { 180, 0x22 }, { 190, 0x32 },
{ 205, 0x03 }, { 220, 0x13 }, { 235, 0x23 }, { 250, 0x33 },
{ 275, 0x04 }, { 300, 0x14 }, { 325, 0x05 }, { 350, 0x15 },
{ 400, 0x25 }, { 450, 0x06 }, { 500, 0x16 }, { 550, 0x07 },
{ 600, 0x17 }, { 650, 0x08 }, { 700, 0x18 }, { 750, 0x09 },
{ 800, 0x19 }, { 850, 0x29 }, { 900, 0x39 }, { 950, 0x0A },
{ 1000, 0x1A }, { 1050, 0x2A }, { 1100, 0x3A }, { 1150, 0x0B },
{ 1200, 0x1B }, { 1250, 0x2B }, { 1300, 0x3B }, { 1350, 0x0C },
{ 1400, 0x1C }, { 1450, 0x2C }, { 1500, 0x3C }, { 1550, 0x0D },
{ 1600, 0x1D }, { 1650, 0x2D }, { 1700, 0x0E }, { 1750, 0x1E },
{ 1800, 0x2E }, { 1850, 0x3E }, { 1900, 0x0F }, { 1950, 0x1F },
{ 2000, 0x2F },
};
struct range_dphy_gen3 {
u32 freq;
u8 hsfregrange;
u32 osc_freq_target;
};
struct range_dphy_gen3 range_gen3[] = {
{ 80, 0x00, 0x1B6 }, { 90, 0x10, 0x1B6 }, { 100, 0x20, 0x1B6 },
{ 110, 0x30, 0x1B6 }, { 120, 0x01, 0x1B6 }, { 130, 0x11, 0x1B6 },
{ 140, 0x21, 0x1B6 }, { 150, 0x31, 0x1B6 }, { 160, 0x02, 0x1B6 },
{ 170, 0x12, 0x1B6 }, { 180, 0x22, 0x1B6 }, { 190, 0x32, 0x1B6 },
{ 205, 0x03, 0x1B6 }, { 220, 0x13, 0x1B6 }, { 235, 0x23, 0x1B6 },
{ 250, 0x33, 0x1B6 }, { 275, 0x04, 0x1B6 }, { 300, 0x14, 0x1B6 },
{ 325, 0x25, 0x1B6 }, { 350, 0x35, 0x1B6 }, { 400, 0x05, 0x1B6 },
{ 450, 0x16, 0x1B6 }, { 500, 0x26, 0x1B6 }, { 550, 0x37, 0x1B6 },
{ 600, 0x07, 0x1B6 }, { 650, 0x18, 0x1B6 }, { 700, 0x28, 0x1B6 },
{ 750, 0x39, 0x1B6 }, { 800, 0x09, 0x1B6 }, { 850, 0x19, 0x1B6 },
{ 900, 0x29, 0x1B6 }, { 950, 0x3A, 0x1B6 }, { 1000, 0x0A, 0x1B6 },
{ 1050, 0x1A, 0x1B6 }, { 1100, 0x2A, 0x1B6 }, { 1150, 0x3B, 0x1B6 },
{ 1200, 0x0B, 0x1B6 }, { 1250, 0x1B, 0x1B6 }, { 1300, 0x2B, 0x1B6 },
{ 1350, 0x3C, 0x1B6 }, { 1400, 0x0C, 0x1B6 }, { 1450, 0x1C, 0x1B6 },
{ 1500, 0x2C, 0x1B6 }, { 1550, 0x3D, 0x10F }, { 1600, 0x0D, 0x118 },
{ 1650, 0x1D, 0x121 }, { 1700, 0x2E, 0x12A }, { 1750, 0x3E, 0x132 },
{ 1800, 0x0E, 0x13B }, { 1850, 0x1E, 0x144 }, { 1900, 0x2F, 0x14D },
{ 1950, 0x3F, 0x155 }, { 2000, 0x0F, 0x15E }, { 2050, 0x40, 0x167 },
{ 2100, 0x41, 0x170 }, { 2150, 0x42, 0x178 }, { 2200, 0x43, 0x181 },
{ 2250, 0x44, 0x18A }, { 2300, 0x45, 0x193 }, { 2350, 0x46, 0x19B },
{ 2400, 0x47, 0x1A4 }, { 2450, 0x48, 0x1AD }, { 2500, 0x49, 0x1B6 }
};
u8 dw_dphy_setup_config(struct dw_dphy_rx *dphy)
{
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
#if 0
int ret;
if (dphy->max_lanes == CTRL_4_LANES) {
dev_vdbg(&dphy->phy->dev, "CONFIG 4L\n");
return CTRL_4_LANES;
}
if (IS_ENABLED(CONFIG_OF)) {
ret = gpio_request(dphy->config_8l, "config");
if (ret < 0) {
dev_vdbg(&dphy->phy->dev,
"could not acquire config (err=%d)\n", ret);
return ret;
}
ret = gpio_get_value(dphy->config_8l);
gpio_free(dphy->config_8l);
} else {
ret = dphy->config_8l;
}
dev_vdbg(&dphy->phy->dev,
"Booting in [%s] mode\n",
ret == CTRL_8_LANES ? "8L" : "4+4L");
return ret;
#endif
#endif /* CONFIG_DWC_MIPI_TC_DPHY_GEN3 */
return CTRL_4_LANES;
}
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
//extern int k_bm_visys_write_reg(uint32_t offset, uint32_t value);
//extern int k_bm_visys_read_reg(uint32_t offset, uint32_t *value);
void dw_dphy_if_write(struct dw_dphy_rx *dphy, u32 address, u32 data)
{
writel(data, dphy->dphy1_if_addr + address);
//k_bm_visys_write_reg(address, data);
}
u32 dw_dphy_if_read(struct dw_dphy_rx *dphy, u32 address)
{
u32 if1 = 0;
if1 = readl(dphy->dphy1_if_addr + address);
//k_bm_visys_read_reg(address, &if1);
return if1;
}
#endif
void dw_dphy_write(struct dw_dphy_rx *dphy, u32 address, u32 data)
{
iowrite32(data, dphy->base_address + address);
if (dphy->lanes_config == CTRL_4_LANES)
return;
return;
if (address == R_CSI2_DPHY_TST_CTRL0)
iowrite32(data, dphy->base_address + R_CSI2_DPHY2_TST_CTRL0);
else if (address == R_CSI2_DPHY_TST_CTRL1)
iowrite32(data, dphy->base_address + R_CSI2_DPHY2_TST_CTRL1);
}
u32 dw_dphy_read(struct dw_dphy_rx *dphy, u32 address)
{
int dphy1 = 0, dphy2 = 0;
dphy1 = ioread32(dphy->base_address + address);
if (dphy->lanes_config == CTRL_4_LANES)
goto end;
goto end;
if (address == R_CSI2_DPHY_TST_CTRL0)
dphy2 = ioread32(dphy->base_address + R_CSI2_DPHY2_TST_CTRL0);
else if (address == R_CSI2_DPHY_TST_CTRL1)
dphy2 = ioread32(dphy->base_address + R_CSI2_DPHY2_TST_CTRL1);
else
return -ENODEV;
end:
return dphy1;
}
void dw_dphy_write_msk(struct dw_dphy_rx *dev, u32 address, u32 data, u8 shift,
u8 width)
{
u32 temp = dw_dphy_read(dev, address);
u32 mask = (1 << width) - 1;
temp &= ~(mask << shift);
temp |= (data & mask) << shift;
dw_dphy_write(dev, address, temp);
}
static void dw_dphy_te_12b_write(struct dw_dphy_rx *dphy, u16 addr, u8 data)
{
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0x00, PHY_TESTDIN, 8);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, (u8)(addr >> 8),
PHY_TESTDIN, 8);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, (u8)addr, PHY_TESTDIN,
8);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, (u8)data, PHY_TESTDIN,
8);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
}
static void dw_dphy_te_8b_write(struct dw_dphy_rx *dphy, u8 addr, u8 data)
{
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
dw_dphy_write(dphy, R_CSI2_DPHY_TST_CTRL1, addr);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
dw_dphy_write(dphy, R_CSI2_DPHY_TST_CTRL1, data);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
}
static void dw_dphy_te_write(struct dw_dphy_rx *dphy, u16 addr, u8 data)
{
dphy->dphy_te_len = BIT12;
if (dphy->dphy_te_len == BIT12)
dw_dphy_te_12b_write(dphy, addr, data);
else
dw_dphy_te_8b_write(dphy, addr, data);
}
static int dw_dphy_te_12b_read(struct dw_dphy_rx *dphy, u32 addr)
{
u8 ret;
dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 1);
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0x00, PHY_TESTDIN, 8);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, (u8)(addr >> 8),
PHY_TESTDIN, 8);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, (u8)addr, PHY_TESTDIN,
8);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0x00, 0, PHY_TESTDIN);
ret = dw_dphy_read_msk(dphy, R_CSI2_DPHY_TST_CTRL1, PHY_TESTDOUT, 8);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 1);
return ret;
}
static int dw_dphy_te_8b_read(struct dw_dphy_rx *dphy, u32 addr)
{
u8 ret;
dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 0);
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 1, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, addr, PHY_TESTDIN, 8);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTEN, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL1, 0, PHY_TESTDIN, 8);
ret = dw_dphy_read_msk(dphy, R_CSI2_DPHY_TST_CTRL1, PHY_TESTDOUT, 8);
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 1);
return ret;
}
int dw_dphy_te_read(struct dw_dphy_rx *dphy, u32 addr)
{
int ret;
if (dphy->dphy_te_len == BIT12)
ret = dw_dphy_te_12b_read(dphy, addr);
else
ret = dw_dphy_te_12b_read(dphy, addr);
//ret = dw_dphy_te_8b_read(dphy, addr);
return ret;
}
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
static void dw_dphy_if_init(struct dw_dphy_rx *dphy)
{
bm_info("enter %s\n", __func__);
//dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, RESET);
//dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, TX_PHY);
//dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLR, 1);
//dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLR, 1);
//dw_dphy_if_write(dphy, DPHYZCALCTRL, 0);
//dw_dphy_if_write(dphy, DPHYZCALCTRL, 1);
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, RESET);
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, GLUELOGIC);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLR, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLR, 1);
//dw_dphy_if_write(dphy, DPHYZCALCTRL, 0);
//dw_dphy_if_write(dphy, DPHYZCALCTRL, 1);
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, RESET);
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, RX_PHY);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLR, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLR, 1);
//dw_dphy_if_write(dphy, DPHYZCALCTRL, 0);
//dw_dphy_if_write(dphy, DPHYZCALCTRL, 1);
}
#endif
static void dw_dphy_gen3_12bit_tc_power_up(struct dw_dphy_rx *dphy, uint8_t hsfregrange)
{
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, RESET);
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, GLUELOGIC);
#endif
dw_dphy_te_write(dphy, CFGCLKFREQRANGE_RX, 0x1C);
dw_dphy_te_write(dphy, 0x6, hsfregrange);
/* CLKSEL | UPDATEPLL | SHADOW_CLEAR | SHADOW_CTRL | FORCEPLL */
//dw_dphy_te_write(dphy, BYPASS, 0x3F);
/* IO_DS3 | IO_DS2 | IO_DS1 | IO_DS0 */
if (dphy->dphy_freq > 1500)
dw_dphy_te_write(dphy, IO_DS, 0x0F);
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, RESET);
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, RX_PHY | 0x2);
#endif
}
static void dw_dphy_gen3_8bit_tc_power_up(struct dw_dphy_rx *dphy)
{
u32 input_freq = dphy->dphy_freq / 1000;
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, RESET);
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, GLUELOGIC);
dw_dphy_te_write(dphy, CFGCLKFREQRANGE_RX, 0x1C);
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, RESET);
dw_dphy_if_write(dphy, DPHYGLUEIFTESTER, RX_PHY);
#endif
dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX0_MSB, 0x03);
dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX0_LSB, 0x02);
dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX1_MSB, 0x03);
dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX1_LSB, 0x02);
dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX2_MSB, 0x03);
dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX2_LSB, 0x02);
dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX3_MSB, 0x03);
dw_dphy_te_write(dphy, OSC_FREQ_TARGET_RX3_LSB, 0x02);
dw_dphy_te_write(dphy, BANDGAP_CTRL, 0x80);
if (input_freq < 2000)
dw_dphy_te_write(dphy, HS_RX_CTRL_LANE0, 0xC0);
if (input_freq < 1000) {
dw_dphy_te_write(dphy, HS_RX_CTRL_LANE1, 0xC0);
dw_dphy_te_write(dphy, HS_RX_CTRL_LANE2, 0xC0);
dw_dphy_te_write(dphy, HS_RX_CTRL_LANE3, 0xC0);
}
}
int dw_dphy_g118_settle(struct dw_dphy_rx *dphy)
{
u32 input_freq, total_settle, settle_time, byte_clk, lp_time;
lp_time = dphy->lp_time;
input_freq = dphy->dphy_freq / 1000;
settle_time = (8 * (1000000 / (input_freq))) + 115000;
byte_clk = (8000000 / (input_freq));
total_settle = (settle_time + lp_time * 1000) / byte_clk;
if (total_settle > 0xFF)
total_settle = 0xFF;
return total_settle;
}
static void dw_dphy_pwr_down(struct dw_dphy_rx *dphy)
{
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLK, 1);
if (dphy->lanes_config == CTRL_8_LANES)
dw_dphy_write_msk(dphy, R_CSI2_DPHY2_TST_CTRL0, 0, PHY_TESTCLK,
1);
dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 0);
}
static void dw_dphy_pwr_up(struct dw_dphy_rx *dphy)
{
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLK, 1);
if (dphy->lanes_config == CTRL_8_LANES)
dw_dphy_write_msk(dphy, R_CSI2_DPHY2_TST_CTRL0, 1, PHY_TESTCLK,
1);
dev_vdbg(&dphy->phy->dev, "DPHY power up.\n");
dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 1);
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
}
static int dw_dphy_gen3_12bit_configure(struct dw_dphy_rx *dphy)
{
u32 input_freq = dphy->dphy_freq;
u8 range = 0;
dev_vdbg(&dphy->phy->dev, "12bit: PHY GEN 3: Freq: %u\n", input_freq);
for (range = 0; (range < ARRAY_SIZE(range_gen3) - 1) &&
((input_freq / 1000) > range_gen3[range].freq);
range++)
;
dw_dphy_gen3_12bit_tc_power_up(dphy, range_gen3[range].hsfregrange);
uint8_t lp_time = dphy->lp_time;
dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_17, lp_time);//SET SETTLE TIME
dw_dphy_te_write(dphy, RX_SYS_1, range_gen3[range].hsfregrange);
dw_dphy_te_write(dphy, RX_SYS_0, 0x20);
dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_2,
(u8)range_gen3[range].osc_freq_target);
dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_3,
(u8)(range_gen3[range].osc_freq_target >> 8));
dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_4, 0x01);
if (dphy->phy_type) {
dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_1, 0x01);
dw_dphy_te_write(dphy, RX_RX_STARTUP_OVR_0, 0x80);
}
if (dphy->phy_type || input_freq <= 1500)
dw_dphy_te_write(dphy, RX_SYS_7, 0x38);
return 0;
}
static int dw_dphy_gen3_8bit_configure(struct dw_dphy_rx *dphy)
{
u32 input_freq = dphy->dphy_freq;
u8 data;
u8 range = 0;
dev_vdbg(&dphy->phy->dev, "8bit: PHY GEN 3: Freq: %u\n", input_freq);
for (range = 0; (range < ARRAY_SIZE(range_gen3) - 1) &&
((input_freq / 1000) > range_gen3[range].freq);
range++)
;
dw_dphy_te_write(dphy, RX_SKEW_CAL, dw_dphy_g118_settle(dphy));
data = 1 << 7 | range_gen3[range].hsfregrange;
dw_dphy_te_write(dphy, HSFREQRANGE_8BIT, data);
dw_dphy_gen3_8bit_tc_power_up(dphy);
return 0;
}
static int dw_dphy_gen2_configure(struct dw_dphy_rx *dphy)
{
u32 input_freq = dphy->dphy_freq;
u8 data;
u8 range = 0;
/* provide an initial active-high test clear pulse in TESTCLR */
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLR, 1);
dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLR, 1);
dev_vdbg(&dphy->phy->dev, "PHY GEN 2: Freq: %u\n", input_freq);
for (range = 0; (range < ARRAY_SIZE(range_gen2) - 1) &&
((input_freq / 1000) > range_gen2[range].freq); range++)
;
data = range_gen2[range].hsfregrange << 1;
dw_dphy_te_write(dphy, HSFREQRANGE_8BIT, data);
return 0;
}
static int dw_dphy_configure(struct dw_dphy_rx *dphy)
{
bm_info("enter %s\n", __func__);
dw_dphy_pwr_down(dphy);
dphy->dphy_gen = GEN3;
if (dphy->dphy_gen == GEN3) {
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
dw_dphy_if_init(dphy);
#endif
dphy->dphy_te_len = BIT12;
if (dphy->dphy_te_len == BIT12)
dw_dphy_gen3_12bit_configure(dphy);
else
dw_dphy_gen3_8bit_configure(dphy);
} else {
dw_dphy_gen2_configure(dphy);
}
dw_dphy_pwr_up(dphy);
return 0;
}
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
#if 0
int dw_dphy_if_set_idelay(struct dw_dphy_rx *dphy, u8 dly, u8 cells)
{
u32 val = 0;
dw_dphy_if_write(dphy, IDLYCFG, 0);
dw_dphy_if_write(dphy, IDLYSEL, cells);
dw_dphy_if_write(dphy, IDLYCNTINVAL, dly);
/* Pulse Value Set */
dw_dphy_if_write(dphy, IDLYCFG, 1);
usleep_range(10, 20);
dw_dphy_if_write(dphy, IDLYCFG, 0);
/* Pulse IDELAY CTRL Reset */
dw_dphy_if_write(dphy, DPHY1REGRSTN, 0);
usleep_range(10, 20);
dw_dphy_if_write(dphy, DPHY1REGRSTN, 1);
/* Get Value*/
val = dw_dphy_if_read(dphy, IDLYCNTOUTVAL);
if (val != dly) {
dev_vdbg(&dphy->phy->dev,
"odelay config failed, set %d get %d", dly, val);
return -EINVAL;
}
return 0;
}
int dw_dphy_if_get_idelay(struct dw_dphy_rx *dphy)
{
return dw_dphy_if_read(dphy, IDLYCNTOUTVAL);
}
int dw_dphy_if_set_idelay_lane(struct dw_dphy_rx *dphy, u8 dly, u8 lane)
{
int cell;
switch (lane) {
case 0:
for (cell = 3; cell <= 10; cell++)
dw_dphy_if_set_idelay(dphy, dly, cell);
break;
case 1:
for (cell = 14; cell <= 21; cell++)
dw_dphy_if_set_idelay(dphy, dly, cell);
break;
case 2:
for (cell = 24; cell <= 31; cell++)
dw_dphy_if_set_idelay(dphy, dly, cell);
break;
case 3:
for (cell = 34; cell <= 41; cell++)
dw_dphy_if_set_idelay(dphy, dly, cell);
break;
case 4: /* ALL */
dw_dphy_if_set_idelay(dphy, dly, 0x7F);
break;
default:
dev_err(&dphy->phy->dev, "Lane Value not recognized\n");
return -1;
}
return 0;
}
#endif
#endif
int dw_dphy_init(struct phy *phy)
{
struct dw_dphy_rx *dphy = phy_get_drvdata(phy);
dev_warn(&dphy->phy->dev, "Init DPHY.\n");
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 0);
return 0;
}
static int dw_dphy_set_phy_state(struct dw_dphy_rx *dphy, u32 on)
{
u8 hs_freq;
bm_info("enter %s\n", __func__);
dphy->lanes_config = dw_dphy_setup_config(dphy);
if (dphy->dphy_te_len == BIT12)
hs_freq = RX_SYS_1;
else
hs_freq = HSFREQRANGE_8BIT;
if (on) {
dw_dphy_configure(dphy);
dev_info(&dphy->phy->dev,
"HS Code: 0X%x\n", dw_dphy_te_read(dphy, hs_freq));
} else {
dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 0);
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
}
return 0;
}
int dw_dphy_power_on(struct phy *phy)
{
struct dw_dphy_rx *dphy = phy_get_drvdata(phy);
dev_info(&dphy->phy->dev, "DPHY Power ON\n");
bm_info("enter %s\n", __func__);
return dw_dphy_set_phy_state(dphy, 1);
}
int dw_dphy_power_off(struct phy *phy)
{
struct dw_dphy_rx *dphy = phy_get_drvdata(phy);
return dw_dphy_set_phy_state(dphy, 0);
}
int dw_dphy_reset(struct phy *phy)
{
struct dw_dphy_rx *dphy = phy_get_drvdata(phy);
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
usleep_range(100, 200);
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
return 0;
}

215
vvcam/native/csi/dw-dphy-rx.h Executable file
View File

@@ -0,0 +1,215 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI D-PHY controller driver
*
* Author: Luis Oliveira <luis.oliveira@synopsys.com>
*/
#ifndef __PHY_SNPS_DPHY_RX_H__
#define __PHY_SNPS_DPHY_RX_H__
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/phy/phy.h>
#include <linux/phy/phy-mipi-dphy.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
/* DPHY interface register bank*/
#define R_CSI2_DPHY_SHUTDOWNZ 0x0
#define R_CSI2_DPHY_RSTZ 0x4
#define R_CSI2_DPHY_RX 0x8
#define R_CSI2_DPHY_STOPSTATE 0xC
#define R_CSI2_DPHY_TST_CTRL0 0x10
#define R_CSI2_DPHY_TST_CTRL1 0x14
#define R_CSI2_DPHY2_TST_CTRL0 0x18
#define R_CSI2_DPHY2_TST_CTRL1 0x1C
enum dphy_id_mask {
DPHY_ID_LANE_SUPPORT = 0,
DPHY_ID_IF = 4,
DPHY_ID_GEN = 8,
};
enum dphy_gen_values {
GEN1,
GEN2,
GEN3,
};
enum dphy_interface_length {
BIT8 = 8,
BIT12 = 12,
};
enum tst_ctrl0 {
PHY_TESTCLR,
PHY_TESTCLK,
};
enum tst_ctrl1 {
PHY_TESTDIN = 0,
PHY_TESTDOUT = 8,
PHY_TESTEN = 16,
};
enum lanes_config_values {
CTRL_4_LANES,
CTRL_8_LANES,
};
enum dphy_tc {
CFGCLKFREQRANGE_TX = 0x02,
CFGCLKFREQRANGE_RX = 0x05,
BYPASS = 0x20,
IO_DS = 0x30,
};
enum dphy_8bit_interface_addr {
BANDGAP_CTRL = 0x24,
HS_RX_CTRL_LANE0 = 0x42,
HSFREQRANGE_8BIT = 0x44,
OSC_FREQ_TARGET_RX0_LSB = 0x4e,
OSC_FREQ_TARGET_RX0_MSB = 0x4f,
HS_RX_CTRL_LANE1 = 0x52,
OSC_FREQ_TARGET_RX1_LSB = 0x5e,
OSC_FREQ_TARGET_RX1_MSB = 0x5f,
RX_SKEW_CAL = 0x7e,
HS_RX_CTRL_LANE2 = 0x82,
OSC_FREQ_TARGET_RX2_LSB = 0x8e,
OSC_FREQ_TARGET_RX2_MSB = 0x8f,
HS_RX_CTRL_LANE3 = 0x92,
OSC_FREQ_TARGET_RX3_LSB = 0x9e,
OSC_FREQ_TARGET_RX3_MSB = 0x9f,
};
enum dphy_12bit_interface_addr {
RX_SYS_0 = 0x01,
RX_SYS_1 = 0x02,
RX_SYS_7 = 0x08,
RX_RX_STARTUP_OVR_0 = 0xe0,
RX_RX_STARTUP_OVR_1 = 0xe1,
RX_RX_STARTUP_OVR_2 = 0xe2,
RX_RX_STARTUP_OVR_3 = 0xe3,
RX_RX_STARTUP_OVR_4 = 0xe4,
RX_RX_STARTUP_OVR_17 = 0xf1,
};
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
/* Testchip interface register bank */
#define IDLYCFG 0x00
#define IDLYSEL 0x04
#define IDLYCNTINVAL 0x08
#define IDLYCNTOUTVAL 0x0c
#define DPHY1REGRSTN 0x10
#define DPHYZCALSTAT 0x14
#define DPHYZCALCTRL 0x18
#define DPHYLANE0STAT 0x1c
#define DPHYLANE1STAT 0x20
#define DPHYLANE2STAT 0x24
#define DPHYLANE3STAT 0x28
#define DPHYCLKSTAT 0x2c
#define DPHYZCLKCTRL 0x30
#define TCGENPURPOSOUT 0x34
#define TCGENPURPOSIN 0x38
#define DPHYGENERICOUT 0x3c
#define DPHYGENERICIN 0x40
#define DPHYGLUEIFTESTER 0x180
#define DPHYID 0x100
#define DPHY_DEFAULT_FREQ 300000
enum glueiftester {
RESET = 0,
TX_PHY = 0x100 | (0x1 << 4),
RX_PHY = 0x100 | (0x2 << 4),
GLUELOGIC = 0x100 | (0x4 << 4),
};
#endif
/**
* struct phy specifies associated phy component
* struct cfg to pass mipi dphy specific configurations
* @lanes_config lanes configuration
* @dphy_freq operating frequency of the d-phy (mbps)
* @phy_type dphy can be of two types, passed here
* @dphy_gen dphy can be of three generations, passed here
* @dphy_te_len bus width
* @max_lanes maximum number of lanes
* @lp_time time in low-power
* @base_address memmory address of dphy test interface
* @dphy1_if_addr gluelogic dphy 1 memmory address of interface
* @dphy2_if_addr gluelogic dphy 2 memmory address of interface
* @config_8l eight lanes configuration
*/
struct dw_dphy_rx {
struct phy *phy;
struct phy_configure_opts_mipi_dphy *cfg;
u32 lanes_config;
u32 dphy_freq; //MBPS
u32 phy_type;
u32 dphy_gen;
u32 dphy_te_len;
u32 max_lanes;
u32 lp_time;
void __iomem *base_address;
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
void __iomem *dphy1_if_addr;
void __iomem *dphy2_if_addr;
u8 config_8l;
u8 (*get_config_8l)(struct device *dev, struct dw_dphy_rx *dphy);
#endif
u8 (*phy_register)(struct device *dev);
void (*phy_unregister)(struct device *dev);
};
int dw_dphy_init(struct phy *phy);
int dw_dphy_reset(struct phy *phy);
int dw_dphy_power_off(struct phy *phy);
int dw_dphy_power_on(struct phy *phy);
u8 dw_dphy_setup_config(struct dw_dphy_rx *dphy);
void dw_dphy_write(struct dw_dphy_rx *dphy, u32 address, u32 data);
u32 dw_dphy_read(struct dw_dphy_rx *dphy, u32 address);
int dw_dphy_te_read(struct dw_dphy_rx *dphy, u32 addr);
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
u32 dw_dphy_if_read(struct dw_dphy_rx *dphy, u32 address);
int dw_dphy_if_get_idelay(struct dw_dphy_rx *dphy);
int dw_dphy_if_set_idelay_lane(struct dw_dphy_rx *dphy, u8 dly, u8 lane);
int dw_dphy_create_capabilities_sysfs(struct platform_device *pdev);
int dw_dphy_remove_capabilities_sysfs(struct platform_device *pdev);
static inline
u32 dw_dphy_if_read_msk(struct dw_dphy_rx *dphy,
u32 address, u8 shift, u8 width)
{
return (dw_dphy_if_read(dphy, address) >> shift) & ((1 << width) - 1);
}
#endif /*IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)*/
static inline struct phy *dw_dphy_xlate(struct device *dev,
struct of_phandle_args *args)
{
struct dw_dphy_rx *dphy = dev_get_drvdata(dev);
return dphy->phy;
}
static inline
u32 dw_dphy_read_msk(struct dw_dphy_rx *dev, u32 address, u8 shift, u8 width)
{
return (dw_dphy_read(dev, address) >> shift) & ((1 << width) - 1);
}
#endif /*__PHY_SNPS_DPHY_RX_H__*/

264
vvcam/native/csi/dw-dphy-sysfs.c Executable file
View File

@@ -0,0 +1,264 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI D-PHY controller driver.
* SysFS components for the platform driver
*
* Author: Luis Oliveira <luis.oliveira@synopsys.com>
*/
//#define DEBUG 1
#include "dw-dphy-rx.h"
#include "bm_csi_hw.h"
static ssize_t dphy_reset_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
char buffer[15];
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
usleep_range(100, 200);
dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t dphy_freq_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
int ret;
unsigned long freq;
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
ret = kstrtoul(buf, 10, &freq);
if (ret < 0)
return ret;
if (freq > 2500) {
dev_info(dev, "Freq must be under 2500 Mhz\n");
return count;
}
if (freq < 80) {
dev_info(dev, "Freq must be over 80 Mhz\n");
return count;
}
dev_vdbg(dev, "Data Rate %lu Mbps\n", freq);
dphy->dphy_freq = freq*1000;
return count;
}
static ssize_t dphy_freq_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
char buffer[15];
snprintf(buffer,
sizeof(buffer),
"Freq %d\n", dphy->dphy_freq);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t dphy_addr_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
unsigned long addr;
int ret;
ret = kstrtoul(buf, 10, &addr);
if (ret < 0)
return ret;
//payload = (u16)val;
//addr = (u16)(val >> 16);
//dev_vdbg(dev, "addr 0x%lX\n", val);
//dev_vdbg(dev, "payload: 0x%X\n", addr);
//dev_vdbg(dev, "Addr [0x%x] -> 0x%x\n", (unsigned int)addr,
// dw_dphy_te_read(dphy, addr));
printk("<0>""addr 0x%lX\n", addr);
printk("<0>""Addr [0x%x] -> 0x%x\n", (unsigned int)addr,
dw_dphy_te_read(dphy, addr));
return count;
}
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
#if 0
static ssize_t idelay_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
char buffer[15];
snprintf(buffer,
sizeof(buffer), "idelay %d\n", dw_dphy_if_get_idelay(dphy));
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t idelay_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
unsigned long val;
u8 lane, delay;
int ret;
ret = kstrtoul(buf, 16, &val);
if (ret < 0)
return ret;
lane = (u8)val;
delay = (u8)(val >> 8);
dev_vdbg(dev, "Lanes %u\n", lane);
dev_vdbg(dev, "Delay %u\n", delay);
dw_dphy_if_set_idelay_lane(dphy, delay, lane);
return count;
}
#endif
#endif
static ssize_t len_config_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
unsigned long length;
int ret;
ret = kstrtoul(buf, 10, &length);
if (ret < 0)
return ret;
if (length == BIT8)
dev_vdbg(dev, "Configured for 8-bit interface\n");
else if (length == BIT12)
dev_vdbg(dev, "Configured for 12-bit interface\n");
else
return count;
dphy->dphy_te_len = length;
return count;
}
static ssize_t len_config_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
char buffer[20];
snprintf(buffer, sizeof(buffer), "Length %d\n", dphy->dphy_te_len);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static ssize_t dw_dphy_g118_settle_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
unsigned long lp_time;
int ret;
ret = kstrtoul(buf, 10, &lp_time);
if (ret < 0)
return ret;
if (lp_time > 1 && lp_time < 10000) {
dphy->lp_time = lp_time;
} else {
dev_vdbg(dev, "Invalid Value configuring for 1000 ns\n");
dphy->lp_time = 1000;
}
dphy->lp_time = lp_time;
return count;
}
static ssize_t dw_dphy_g118_settle_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
struct dw_dphy_rx *dphy = drvdata->dphy;
char buffer[10];
snprintf(buffer, sizeof(buffer), "Settle %d ns\n", dphy->lp_time);
return strlcpy(buf, buffer, PAGE_SIZE);
}
static DEVICE_ATTR_RO(dphy_reset);
static DEVICE_ATTR_RW(dphy_freq);
static DEVICE_ATTR_WO(dphy_addr);
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
//static DEVICE_ATTR_RW(idelay);
#endif
static DEVICE_ATTR_RW(len_config);
static DEVICE_ATTR_RW(dw_dphy_g118_settle);
int dw_dphy_create_capabilities_sysfs(struct platform_device *pdev)
{
device_create_file(&pdev->dev, &dev_attr_dphy_reset);
device_create_file(&pdev->dev, &dev_attr_dphy_freq);
device_create_file(&pdev->dev, &dev_attr_dphy_addr);
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
// device_create_file(&pdev->dev, &dev_attr_idelay);
#endif
device_create_file(&pdev->dev, &dev_attr_len_config);
device_create_file(&pdev->dev, &dev_attr_dw_dphy_g118_settle);
return 0;
}
int dw_dphy_remove_capabilities_sysfs(struct platform_device *pdev)
{
device_remove_file(&pdev->dev, &dev_attr_dphy_reset);
device_remove_file(&pdev->dev, &dev_attr_dphy_freq);
device_remove_file(&pdev->dev, &dev_attr_dphy_addr);
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
// device_create_file(&pdev->dev, &dev_attr_idelay);
#endif
device_remove_file(&pdev->dev, &dev_attr_len_config);
device_remove_file(&pdev->dev, &dev_attr_dw_dphy_g118_settle);
return 0;
}

View File

@@ -0,0 +1,104 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI CSI-2 Host media entities
*
* Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
*/
#ifndef __DW_MIPI_CSI_PLTFRM_INCLUDES_H_
#define __DW_MIPI_CSI_PLTFRM_INCLUDES_H_
#include <media/media-entity.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-mediabus.h>
#include <media/v4l2-subdev.h>
#define MAX_WIDTH 3280
#define MAX_HEIGHT 1852
/* The subdevices' group IDs. */
#define GRP_ID_SENSOR (10)
#define GRP_ID_CSI (20)
#define GRP_ID_VIF (30)
#define GRP_ID_VIDEODEV (40)
#define CSI_MAX_ENTITIES (2)
#define VIF_MAX_ENTITIES (2)
#define PLAT_MAX_SENSORS (2)
struct pdata_names {
char *name;
};
enum video_dev_pads {
VIDEO_DEV_SD_PAD_SINK_VIF1,
VIDEO_DEV_SD_PAD_SINK_VIF2,
VIDEO_DEV_SD_PAD_SOURCE_DMA,
VIDEO_DEV_SD_PADS_NUM,
};
enum vif_pads {
VIF_PAD_SINK_CSI,
VIF_PAD_SOURCE_DMA,
VIF_PADS_NUM,
};
enum mipi_csi_pads {
CSI_PAD_SINK,
CSI_PAD_SOURCE,
CSI_PADS_NUM,
};
struct plat_csi_source_info {
u16 flags;
u16 mux_id;
};
struct plat_csi_fmt {
char *name;
u32 mbus_code;
u32 fourcc;
u8 depth;
};
struct plat_csi_media_pipeline;
/*
* Media pipeline operations to be called from within a video node, i.e. the
* last entity within the pipeline. Implemented by related media device driver.
*/
struct plat_csi_media_pipeline_ops {
int (*prepare)(struct plat_csi_media_pipeline *p,
struct media_entity *me);
int (*unprepare)(struct plat_csi_media_pipeline *p);
int (*open)(struct plat_csi_media_pipeline *p, struct media_entity *me,
bool resume);
int (*close)(struct plat_csi_media_pipeline *p);
int (*set_stream)(struct plat_csi_media_pipeline *p, bool state);
int (*set_format)(struct plat_csi_media_pipeline *p,
struct v4l2_subdev_format *fmt);
};
struct plat_csi_video_entity {
struct video_device vdev;
struct plat_csi_media_pipeline *pipe;
};
struct plat_csi_media_pipeline {
struct media_pipeline mp;
const struct plat_csi_media_pipeline_ops *ops;
};
static inline struct plat_csi_video_entity
*vdev_to_plat_csi_video_entity(struct video_device *vdev)
{
return container_of(vdev, struct plat_csi_video_entity, vdev);
}
#define plat_csi_pipeline_call(ent, op, args...) \
(!(ent) ? -ENOENT : (((ent)->pipe->ops && (ent)->pipe->ops->op) ? \
(ent)->pipe->ops->op(((ent)->pipe), ##args) : -ENOIOCTLCMD)) \
#endif /* __DW_MIPI_CSI_PLTFRM_INCLUDES_H_ */

590
vvcam/native/csi/dw-mipi-csi.c Executable file
View File

@@ -0,0 +1,590 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI CSI-2 Host controller driver
* Core MIPI CSI-2 functions
*
* Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
*/
#include "dw-mipi-csi.h"
static struct R_CSI2 reg = {
.VERSION = 0x00,
.N_LANES = 0x04,
.CTRL_RESETN = 0x08,
.INTERRUPT = 0x0C,
.DATA_IDS_1 = 0x10,
.DATA_IDS_2 = 0x14,
.IPI_MODE = 0x80,
.IPI_VCID = 0x84,
.IPI_DATA_TYPE = 0x88,
.IPI_MEM_FLUSH = 0x8C,
.IPI_HSA_TIME = 0x90,
.IPI_HBP_TIME = 0x94,
.IPI_HSD_TIME = 0x98,
.IPI_HLINE_TIME = 0x9C,
.IPI_SOFTRSTN = 0xA0,
.IPI_ADV_FEATURES = 0xAC,
.IPI_VSA_LINES = 0xB0,
.IPI_VBP_LINES = 0xB4,
.IPI_VFP_LINES = 0xB8,
.IPI_VACTIVE_LINES = 0xBC,
.INT_PHY_FATAL = 0xe0,
.MASK_INT_PHY_FATAL = 0xe4,
.FORCE_INT_PHY_FATAL = 0xe8,
.INT_PKT_FATAL = 0xf0,
.MASK_INT_PKT_FATAL = 0xf4,
.FORCE_INT_PKT_FATAL = 0xf8,
.INT_PHY = 0x110,
.MASK_INT_PHY = 0x114,
.FORCE_INT_PHY = 0x118,
.INT_LINE = 0x130,
.MASK_INT_LINE = 0x134,
.FORCE_INT_LINE = 0x138,
.INT_IPI = 0x140,
.MASK_INT_IPI = 0x144,
.FORCE_INT_IPI = 0x148,
};
struct interrupt_type csi_int = {
.PHY_FATAL = BIT(0),
.PKT_FATAL = BIT(1),
.PHY = BIT(16),
};
#define dw_print(VAR) \
dev_info(csi_dev->dev, "%s: 0x%x: %X\n", "##VAR##",\
VAR, dw_mipi_csi_read(csi_dev, VAR))
void dw_mipi_csi_write_part(struct dw_csi *dev, u32 address, u32 data,
u8 shift, u8 width)
{
u32 mask = (1 << width) - 1;
u32 temp = dw_mipi_csi_read(dev, address);
temp &= ~(mask << shift);
temp |= (data & mask) << shift;
dw_mipi_csi_write(dev, address, temp);
}
void dw_mipi_csi_reset(struct dw_csi *csi_dev)
{
dw_mipi_csi_write(csi_dev, reg.CTRL_RESETN, 0);
usleep_range(100, 200);
dw_mipi_csi_write(csi_dev, reg.CTRL_RESETN, 1);
}
int dw_mipi_csi_mask_irq_power_off(struct dw_csi *csi_dev)
{
if (csi_dev->hw_version_major == 1) {
/* set only one lane (lane 0) as active (ON) */
dw_mipi_csi_write(csi_dev, reg.N_LANES, 0);
dw_mipi_csi_write(csi_dev, reg.MASK_INT_PHY_FATAL, 0);
dw_mipi_csi_write(csi_dev, reg.MASK_INT_PKT_FATAL, 0);
dw_mipi_csi_write(csi_dev, reg.MASK_INT_PHY, 0);
dw_mipi_csi_write(csi_dev, reg.MASK_INT_LINE, 0);
dw_mipi_csi_write(csi_dev, reg.MASK_INT_IPI, 0);
/* only for version 1.30 */
if (csi_dev->hw_version_minor == 30)
dw_mipi_csi_write(csi_dev,
reg.MASK_INT_FRAME_FATAL, 0);
dw_mipi_csi_write(csi_dev, reg.CTRL_RESETN, 0);
/* only for version 1.40 */
if (csi_dev->hw_version_minor == 40) {
dw_mipi_csi_write(csi_dev,
reg.MSK_BNDRY_FRAME_FATAL, 0);
dw_mipi_csi_write(csi_dev,
reg.MSK_SEQ_FRAME_FATAL, 0);
dw_mipi_csi_write(csi_dev,
reg.MSK_CRC_FRAME_FATAL, 0);
dw_mipi_csi_write(csi_dev, reg.MSK_PLD_CRC_FATAL, 0);
dw_mipi_csi_write(csi_dev, reg.MSK_DATA_ID, 0);
dw_mipi_csi_write(csi_dev, reg.MSK_ECC_CORRECT, 0);
}
}
return 0;
}
int dw_mipi_csi_hw_stdby(struct dw_csi *csi_dev)
{
if (csi_dev->hw_version_major == 1) {
/* set only one lane (lane 0) as active (ON) */
dw_mipi_csi_reset(csi_dev);
dw_mipi_csi_write(csi_dev, reg.N_LANES, 0);
phy_init(csi_dev->phy);
/* only for version 1.30 */
if (csi_dev->hw_version_minor == 30)
dw_mipi_csi_write(csi_dev,
reg.MASK_INT_FRAME_FATAL,
GENMASK(31, 0));
/* common */
dw_mipi_csi_write(csi_dev, reg.MASK_INT_PHY_FATAL,
GENMASK(8, 0));
dw_mipi_csi_write(csi_dev, reg.MASK_INT_PKT_FATAL,
GENMASK(1, 0));
dw_mipi_csi_write(csi_dev, reg.MASK_INT_PHY, GENMASK(23, 0));
dw_mipi_csi_write(csi_dev, reg.MASK_INT_LINE, GENMASK(23, 0));
dw_mipi_csi_write(csi_dev, reg.MASK_INT_IPI, GENMASK(5, 0));
/* only for version 1.40 */
if (csi_dev->hw_version_minor == 40) {
dw_mipi_csi_write(csi_dev,
reg.MSK_BNDRY_FRAME_FATAL,
GENMASK(31, 0));
dw_mipi_csi_write(csi_dev,
reg.MSK_SEQ_FRAME_FATAL,
GENMASK(31, 0));
dw_mipi_csi_write(csi_dev,
reg.MSK_CRC_FRAME_FATAL,
GENMASK(31, 0));
dw_mipi_csi_write(csi_dev,
reg.MSK_PLD_CRC_FATAL,
GENMASK(31, 0));
dw_mipi_csi_write(csi_dev,
reg.MSK_DATA_ID, GENMASK(31, 0));
dw_mipi_csi_write(csi_dev,
reg.MSK_ECC_CORRECT, GENMASK(31, 0));
}
}
return 0;
}
void dw_mipi_csi_set_ipi_fmt(struct dw_csi *csi_dev)
{
struct device *dev = csi_dev->dev;
if (csi_dev->ipi_dt) {
dw_mipi_csi_write(csi_dev, reg.IPI_DATA_TYPE, csi_dev->ipi_dt);
/*switch (csi_dev->ipi_dt) {
case CSI_2_YUV420_8:
//case CSI_2_YUV420_8_LEG:
case CSI_2_YUV420_8_SHIFT:
break;
case CSI_2_YUV420_10:
case CSI_2_YUV420_10_SHIFT:
break;
}*/
} else {
switch (csi_dev->fmt->mbus_code) {
case MEDIA_BUS_FMT_RGB666_1X18:
csi_dev->ipi_dt = CSI_2_RGB666;
break;
case MEDIA_BUS_FMT_RGB565_2X8_BE:
case MEDIA_BUS_FMT_RGB565_2X8_LE:
csi_dev->ipi_dt = CSI_2_RGB565;
break;
case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
csi_dev->ipi_dt = CSI_2_RGB555;
break;
case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
csi_dev->ipi_dt = CSI_2_RGB444;
break;
break;
case MEDIA_BUS_FMT_RGB888_2X12_LE:
case MEDIA_BUS_FMT_RGB888_2X12_BE:
csi_dev->ipi_dt = CSI_2_RGB888;
break;
case MEDIA_BUS_FMT_SBGGR10_1X10:
case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
csi_dev->ipi_dt = CSI_2_RAW10;
break;
case MEDIA_BUS_FMT_SBGGR12_1X12:
csi_dev->ipi_dt = CSI_2_RAW12;
break;
case MEDIA_BUS_FMT_SBGGR14_1X14:
csi_dev->ipi_dt = CSI_2_RAW14;
break;
case MEDIA_BUS_FMT_SBGGR16_1X16:
csi_dev->ipi_dt = CSI_2_RAW16;
break;
case MEDIA_BUS_FMT_SBGGR8_1X8:
csi_dev->ipi_dt = CSI_2_RAW8;
break;
case MEDIA_BUS_FMT_YVYU8_1X16:
csi_dev->ipi_dt = CSI_2_YUV422_8;
break;
case MEDIA_BUS_FMT_VYUY8_1X16:
csi_dev->ipi_dt = CSI_2_YUV422_8;
break;
case MEDIA_BUS_FMT_UYVY10_1X20:
csi_dev->ipi_dt = CSI_2_YUV422_10;
break;
case MEDIA_BUS_FMT_YUYV8_1X16:
csi_dev->ipi_dt = CSI_2_YUV420_8_LEG;
break;
case MEDIA_BUS_FMT_UYVY8_1X16:
csi_dev->ipi_dt = CSI_2_YUV420_8;
break;
case MEDIA_BUS_FMT_VUY8_1X24:
csi_dev->ipi_dt = CSI_2_YUV420_10;
break;
case MEDIA_BUS_FMT_Y8_1X8:
csi_dev->ipi_dt = CSI_2_RAW8;
break;
case MEDIA_BUS_FMT_Y10_1X10:
csi_dev->ipi_dt = CSI_2_RAW8;
break;
case MEDIA_BUS_FMT_SBGGR6_1X8:
csi_dev->ipi_dt = CSI_2_RAW6;
break;
case MEDIA_BUS_FMT_SBGGR7_1X8:
csi_dev->ipi_dt = CSI_2_RAW7;
break;
default:
break;
}
dw_mipi_csi_write(csi_dev, reg.IPI_DATA_TYPE, csi_dev->ipi_dt);
}
dev_info(dev, "Selected IPI Data Type 0x%X\n", csi_dev->ipi_dt);
}
void dw_mipi_csi_fill_timings(struct dw_csi *dev, uint32_t width, uint32_t height)
{
dev->hw.virtual_ch = 0;
dev->hw.ipi_color_mode = COLOR48;
dev->hw.ipi_auto_flush = 1;
dev->hw.ipi_mode = CAMERA_TIMING;
dev->hw.ipi_cut_through = CTINACTIVE;
dev->hw.ipi_adv_features = LINE_EVENT_SELECTION(EVSELAUTO);
dev->hw.htotal = width + dev->hw.hsa +
dev->hw.hbp + dev->hw.hsd;
dev->hw.vactive = height;
dev->hw.output = 2;
dev_dbg(dev->dev, "*********** timings *********\n");
dev_dbg(dev->dev, "Horizontal Sync Active: %d\n", dev->hw.hsa);
dev_dbg(dev->dev, "Horizontal Back Porch: %d\n", dev->hw.hbp);
dev_dbg(dev->dev, "Horizontal Width: %d\n", width);
dev_dbg(dev->dev, "Horizontal Total: %d\n", dev->hw.htotal);
dev_dbg(dev->dev, "Vertical Sync Active: %d\n", dev->hw.vsa);
dev_dbg(dev->dev, "Vertical Back Porch: %d\n", dev->hw.vbp);
dev_dbg(dev->dev, "Vertical Front Porch: %d\n", dev->hw.vfp);
dev_dbg(dev->dev, "Vertical Active: %d\n", dev->hw.vactive);
}
void dw_mipi_csi_start(struct dw_csi *csi_dev)
{
struct device *dev = csi_dev->dev;
dw_mipi_csi_write(csi_dev, reg.N_LANES, (csi_dev->hw.num_lanes - 1));
dev_info(dev, "number of lanes: %d\n", csi_dev->hw.num_lanes);
/* IPI Related Configuration */
if (csi_dev->hw.output == IPI_OUT || csi_dev->hw.output == BOTH_OUT) {
if (csi_dev->hw_version_major >= 1) {
if (csi_dev->hw_version_minor >= 20)
dw_mipi_csi_write(csi_dev,
reg.IPI_ADV_FEATURES,
csi_dev->hw.ipi_adv_features);
if (csi_dev->hw_version_minor >= 30)
dw_mipi_csi_write(csi_dev,
reg.IPI_SOFTRSTN, 0x1);
}
/* address | data, | shift | width */
dw_mipi_csi_write_part(csi_dev, reg.IPI_MODE, 1, 24, 1);
dw_mipi_csi_write_part(csi_dev,
reg.IPI_MODE,
csi_dev->hw.ipi_mode,
0, 1);
if (csi_dev->hw.ipi_mode == CAMERA_TIMING) {
dw_mipi_csi_write(csi_dev,
reg.IPI_ADV_FEATURES,
LINE_EVENT_SELECTION(EVSELPROG) |
EN_VIDEO |
EN_LINE_START |
EN_NULL |
EN_BLANKING |
EN_EMBEDDED);
}
dw_mipi_csi_write_part(csi_dev,
reg.IPI_MODE,
csi_dev->hw.ipi_color_mode,
8, 1);
dw_mipi_csi_write_part(csi_dev,
reg.IPI_MODE,
csi_dev->hw.ipi_cut_through,
16, 1);
dw_mipi_csi_write_part(csi_dev,
reg.IPI_VCID,
csi_dev->hw.virtual_ch,
0, 2);
dw_mipi_csi_write_part(csi_dev,
reg.IPI_MEM_FLUSH,
csi_dev->hw.ipi_auto_flush,
8, 1);
dev_vdbg(dev, "*********** config *********\n");
dev_vdbg(dev, "IPI enable: %s\n",
csi_dev->hw.output ? "YES" : "NO");
dev_vdbg(dev, "video mode transmission type: %s timming\n",
csi_dev->hw.ipi_mode ? "controller" : "camera");
dev_vdbg(dev, "Color Mode: %s\n",
csi_dev->hw.ipi_color_mode ? "16 bits" : "48 bits");
dev_vdbg(dev, "Cut Through Mode: %s\n",
csi_dev->hw.ipi_cut_through ? "enable" : "disable");
dev_vdbg(dev, "Virtual Channel: %d\n",
csi_dev->hw.virtual_ch);
dev_vdbg(dev, "Auto-flush: %d\n",
csi_dev->hw.ipi_auto_flush);
dw_mipi_csi_write(csi_dev, reg.IPI_SOFTRSTN, 1);
if (csi_dev->hw.ipi_mode == AUTO_TIMING)
phy_power_on(csi_dev->phy);
dw_mipi_csi_write(csi_dev,
reg.IPI_HSA_TIME, csi_dev->hw.hsa);
dw_mipi_csi_write(csi_dev,
reg.IPI_HBP_TIME, csi_dev->hw.hbp);
dw_mipi_csi_write(csi_dev,
reg.IPI_HSD_TIME, csi_dev->hw.hsd);
dw_mipi_csi_write(csi_dev,
reg.IPI_HLINE_TIME, csi_dev->hw.htotal);
dw_mipi_csi_write(csi_dev,
reg.IPI_VSA_LINES, csi_dev->hw.vsa);
dw_mipi_csi_write(csi_dev,
reg.IPI_VBP_LINES, csi_dev->hw.vbp);
dw_mipi_csi_write(csi_dev,
reg.IPI_VFP_LINES, csi_dev->hw.vfp);
dw_mipi_csi_write(csi_dev,
reg.IPI_VACTIVE_LINES, csi_dev->hw.vactive);
}
phy_power_on(csi_dev->phy);
}
int dw_mipi_csi_irq_handler(struct dw_csi *csi_dev)
{
struct device *dev = csi_dev->dev;
u32 global_int_status, i_sts;
unsigned long flags;
spin_lock_irqsave(&csi_dev->slock, flags);
global_int_status = dw_mipi_csi_read(csi_dev, reg.INTERRUPT);
if (global_int_status & csi_int.PHY_FATAL) {
i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PHY_FATAL);
dev_err_ratelimited(dev, "int %08X: PHY FATAL: %08X\n",
reg.INT_PHY_FATAL, i_sts);
}
if (global_int_status & csi_int.PKT_FATAL) {
i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PKT_FATAL);
dev_err_ratelimited(dev, "int %08X: PKT FATAL: %08X\n",
reg.INT_PKT_FATAL, i_sts);
}
if (global_int_status & csi_int.FRAME_FATAL &&
csi_dev->hw_version_major == 1 &&
csi_dev->hw_version_minor == 30) {
i_sts = dw_mipi_csi_read(csi_dev, reg.INT_FRAME_FATAL);
dev_err_ratelimited(dev, "int %08X: FRAME FATAL: %08X\n",
reg.INT_FRAME_FATAL, i_sts);
}
if (global_int_status & csi_int.PHY) {
i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PHY);
dev_err_ratelimited(dev, "int %08X: PHY: %08X\n",
reg.INT_PHY, i_sts);
}
if (global_int_status & csi_int.PKT &&
csi_dev->hw_version_major == 1 &&
csi_dev->hw_version_minor <= 30) {
i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PKT);
dev_err_ratelimited(dev, "int %08X: PKT: %08X\n",
reg.INT_PKT, i_sts);
}
if (global_int_status & csi_int.LINE) {
i_sts = dw_mipi_csi_read(csi_dev, reg.INT_LINE);
dev_err_ratelimited(dev, "int %08X: LINE: %08X\n",
reg.INT_LINE, i_sts);
}
if (global_int_status & csi_int.IPI) {
i_sts = dw_mipi_csi_read(csi_dev, reg.INT_IPI);
dev_err_ratelimited(dev, "int %08X: IPI: %08X\n",
reg.INT_IPI, i_sts);
}
if (global_int_status & csi_int.BNDRY_FRAME_FATAL) {
i_sts = dw_mipi_csi_read(csi_dev, reg.ST_BNDRY_FRAME_FATAL);
dev_err_ratelimited(dev,
"int %08X: ST_BNDRY_FRAME_FATAL: %08X\n",
reg.ST_BNDRY_FRAME_FATAL, i_sts);
}
if (global_int_status & csi_int.SEQ_FRAME_FATAL) {
i_sts = dw_mipi_csi_read(csi_dev, reg.ST_SEQ_FRAME_FATAL);
dev_err_ratelimited(dev,
"int %08X: ST_SEQ_FRAME_FATAL: %08X\n",
reg.ST_SEQ_FRAME_FATAL, i_sts);
}
if (global_int_status & csi_int.CRC_FRAME_FATAL) {
i_sts = dw_mipi_csi_read(csi_dev, reg.ST_CRC_FRAME_FATAL);
dev_err_ratelimited(dev,
"int %08X: ST_CRC_FRAME_FATAL: %08X\n",
reg.ST_CRC_FRAME_FATAL, i_sts);
}
if (global_int_status & csi_int.PLD_CRC_FATAL) {
i_sts = dw_mipi_csi_read(csi_dev, reg.ST_PLD_CRC_FATAL);
dev_err_ratelimited(dev,
"int %08X: ST_PLD_CRC_FATAL: %08X\n",
reg.ST_PLD_CRC_FATAL, i_sts);
}
if (global_int_status & csi_int.DATA_ID) {
i_sts = dw_mipi_csi_read(csi_dev, reg.ST_DATA_ID);
dev_err_ratelimited(dev, "int %08X: ST_DATA_ID: %08X\n",
reg.ST_DATA_ID, i_sts);
}
if (global_int_status & csi_int.ECC_CORRECTED) {
i_sts = dw_mipi_csi_read(csi_dev, reg.ST_ECC_CORRECT);
dev_err_ratelimited(dev, "int %08X: ST_ECC_CORRECT: %08X\n",
reg.ST_ECC_CORRECT, i_sts);
}
spin_unlock_irqrestore(&csi_dev->slock, flags);
return 1;
}
void dw_mipi_csi_get_version(struct dw_csi *csi_dev)
{
u32 hw_version;
hw_version = dw_mipi_csi_read(csi_dev, reg.VERSION);
csi_dev->hw_version_major = (u8)((hw_version >> 24) - '0');
csi_dev->hw_version_minor = (u8)((hw_version >> 16) - '0');
csi_dev->hw_version_minor = csi_dev->hw_version_minor * 10;
csi_dev->hw_version_minor += (u8)((hw_version >> 8) - '0');
}
int dw_mipi_csi_specific_mappings(struct dw_csi *csi_dev)
{
struct device *dev = csi_dev->dev;
if (csi_dev->hw_version_major == 1) {
if (csi_dev->hw_version_minor == 30) {
/*
* Hardware registers that were
* exclusive to version < 1.40
*/
reg.INT_FRAME_FATAL = 0x100;
reg.MASK_INT_FRAME_FATAL = 0x104;
reg.FORCE_INT_FRAME_FATAL = 0x108;
reg.INT_PKT = 0x120;
reg.MASK_INT_PKT = 0x124;
reg.FORCE_INT_PKT = 0x128;
/* interrupt source present until this release */
csi_int.PKT = BIT(17);
csi_int.LINE = BIT(18);
csi_int.IPI = BIT(19);
csi_int.FRAME_FATAL = BIT(2);
} else if (csi_dev->hw_version_minor == 40) {
/*
* HW registers that were added
* to version 1.40
*/
reg.ST_BNDRY_FRAME_FATAL = 0x280;
reg.MSK_BNDRY_FRAME_FATAL = 0x284;
reg.FORCE_BNDRY_FRAME_FATAL = 0x288;
reg.ST_SEQ_FRAME_FATAL = 0x290;
reg.MSK_SEQ_FRAME_FATAL = 0x294;
reg.FORCE_SEQ_FRAME_FATAL = 0x298;
reg.ST_CRC_FRAME_FATAL = 0x2a0;
reg.MSK_CRC_FRAME_FATAL = 0x2a4;
reg.FORCE_CRC_FRAME_FATAL = 0x2a8;
reg.ST_PLD_CRC_FATAL = 0x2b0;
reg.MSK_PLD_CRC_FATAL = 0x2b4;
reg.FORCE_PLD_CRC_FATAL = 0x2b8;
reg.ST_DATA_ID = 0x2c0;
reg.MSK_DATA_ID = 0x2c4;
reg.FORCE_DATA_ID = 0x2c8;
reg.ST_ECC_CORRECT = 0x2d0;
reg.MSK_ECC_CORRECT = 0x2d4;
reg.FORCE_ECC_CORRECT = 0x2d8;
reg.DATA_IDS_VC_1 = 0x0;
reg.DATA_IDS_VC_2 = 0x0;
reg.VC_EXTENSION = 0x0;
/* interrupts map were changed */
csi_int.LINE = BIT(17);
csi_int.IPI = BIT(18);
csi_int.BNDRY_FRAME_FATAL = BIT(2);
csi_int.SEQ_FRAME_FATAL = BIT(3);
csi_int.CRC_FRAME_FATAL = BIT(4);
csi_int.PLD_CRC_FATAL = BIT(5);
csi_int.DATA_ID = BIT(6);
csi_int.ECC_CORRECTED = BIT(7);
} else {
dev_info(dev, "Version minor not supported.");
}
} else {
dev_info(dev, "Version major not supported.");
}
return 0;
}
void dw_mipi_csi_dump(struct dw_csi *csi_dev)
{
dw_print(reg.VERSION);
dw_print(reg.N_LANES);
dw_print(reg.CTRL_RESETN);
dw_print(reg.INTERRUPT);
dw_print(reg.DATA_IDS_1);
dw_print(reg.DATA_IDS_2);
dw_print(reg.IPI_MODE);
dw_print(reg.IPI_VCID);
dw_print(reg.IPI_DATA_TYPE);
dw_print(reg.IPI_MEM_FLUSH);
dw_print(reg.IPI_HSA_TIME);
dw_print(reg.IPI_HBP_TIME);
dw_print(reg.IPI_HSD_TIME);
dw_print(reg.IPI_HLINE_TIME);
dw_print(reg.IPI_SOFTRSTN);
dw_print(reg.IPI_ADV_FEATURES);
dw_print(reg.IPI_VSA_LINES);
dw_print(reg.IPI_VBP_LINES);
dw_print(reg.IPI_VFP_LINES);
dw_print(reg.IPI_VACTIVE_LINES);
dw_print(reg.IPI_DATA_TYPE);
dw_print(reg.VERSION);
dw_print(reg.IPI_ADV_FEATURES);
}

285
vvcam/native/csi/dw-mipi-csi.h Executable file
View File

@@ -0,0 +1,285 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
*
* Synopsys DesignWare MIPI CSI-2 Host controller driver
*
* Author: Luis Oliveira <Luis.Oliveira@synopsys.com>
*/
#ifndef _DW_MIPI_CSI_H__
#define _DW_MIPI_CSI_H__
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/phy/phy.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/ratelimit.h>
#include <linux/reset.h>
#include <linux/videodev2.h>
#include <linux/wait.h>
#include <dw-mipi-csi-pltfrm.h>
/* Advanced features */
#define IPI_DT_OVERWRITE BIT(0)
#define DATA_TYPE_OVERWRITE(dt) (((dt) & GENMASK(5, 0)) << 8)
#define LINE_EVENT_SELECTION(n) ((n) << 16)
enum line_event {
EVSELAUTO = 0,
EVSELPROG = 1,
};
#define EN_VIDEO BIT(17)
#define EN_LINE_START BIT(18)
#define EN_NULL BIT(19)
#define EN_BLANKING BIT(20)
#define EN_EMBEDDED BIT(21)
#define IPI_SYNC_EVENT_MODE(n) ((n) << 24)
enum sync_event {
SYNCEVFSN = 0,
SYNCEVFS = 1,
};
/* DW MIPI CSI-2 register addresses*/
struct R_CSI2 {
u16 VERSION;
u16 N_LANES;
u16 CTRL_RESETN;
u16 INTERRUPT;
u16 DATA_IDS_1;
u16 DATA_IDS_2;
u16 DATA_IDS_VC_1;
u16 DATA_IDS_VC_2;
u16 IPI_MODE;
u16 IPI_VCID;
u16 IPI_DATA_TYPE;
u16 IPI_MEM_FLUSH;
u16 IPI_HSA_TIME;
u16 IPI_HBP_TIME;
u16 IPI_HSD_TIME;
u16 IPI_HLINE_TIME;
u16 IPI_SOFTRSTN;
u16 IPI_ADV_FEATURES;
u16 IPI_VSA_LINES;
u16 IPI_VBP_LINES;
u16 IPI_VFP_LINES;
u16 IPI_VACTIVE_LINES;
u16 VC_EXTENSION;
u16 INT_PHY_FATAL;
u16 MASK_INT_PHY_FATAL;
u16 FORCE_INT_PHY_FATAL;
u16 INT_PKT_FATAL;
u16 MASK_INT_PKT_FATAL;
u16 FORCE_INT_PKT_FATAL;
u16 INT_FRAME_FATAL;
u16 MASK_INT_FRAME_FATAL;
u16 FORCE_INT_FRAME_FATAL;
u16 INT_PHY;
u16 MASK_INT_PHY;
u16 FORCE_INT_PHY;
u16 INT_PKT;
u16 MASK_INT_PKT;
u16 FORCE_INT_PKT;
u16 INT_LINE;
u16 MASK_INT_LINE;
u16 FORCE_INT_LINE;
u16 INT_IPI;
u16 MASK_INT_IPI;
u16 FORCE_INT_IPI;
u16 ST_BNDRY_FRAME_FATAL;
u16 MSK_BNDRY_FRAME_FATAL;
u16 FORCE_BNDRY_FRAME_FATAL;
u16 ST_SEQ_FRAME_FATAL;
u16 MSK_SEQ_FRAME_FATAL;
u16 FORCE_SEQ_FRAME_FATAL;
u16 ST_CRC_FRAME_FATAL;
u16 MSK_CRC_FRAME_FATAL;
u16 FORCE_CRC_FRAME_FATAL;
u16 ST_PLD_CRC_FATAL;
u16 MSK_PLD_CRC_FATAL;
u16 FORCE_PLD_CRC_FATAL;
u16 ST_DATA_ID;
u16 MSK_DATA_ID;
u16 FORCE_DATA_ID;
u16 ST_ECC_CORRECT;
u16 MSK_ECC_CORRECT;
u16 FORCE_ECC_CORRECT;
};
/* Interrupt Masks */
struct interrupt_type {
u32 PHY_FATAL;
u32 PKT_FATAL;
u32 FRAME_FATAL;
u32 PHY;
u32 PKT;
u32 LINE;
u32 IPI;
u32 BNDRY_FRAME_FATAL;
u32 SEQ_FRAME_FATAL;
u32 CRC_FRAME_FATAL;
u32 PLD_CRC_FATAL;
u32 DATA_ID;
u32 ECC_CORRECTED;
};
/* IPI Data Types */
enum data_type {
CSI_2_YUV420_8 = 0x18,
CSI_2_YUV420_10 = 0x19,
CSI_2_YUV420_8_LEG = 0x1A,
CSI_2_YUV420_8_SHIFT = 0x1C,
CSI_2_YUV420_10_SHIFT = 0x1D,
CSI_2_YUV422_8 = 0x1E,
CSI_2_YUV422_10 = 0x1F,
CSI_2_RGB444 = 0x20,
CSI_2_RGB555 = 0x21,
CSI_2_RGB565 = 0x22,
CSI_2_RGB666 = 0x23,
CSI_2_RGB888 = 0x24,
CSI_2_RAW6 = 0x28,
CSI_2_RAW7 = 0x29,
CSI_2_RAW8 = 0x2A,
CSI_2_RAW10 = 0x2B,
CSI_2_RAW12 = 0x2C,
CSI_2_RAW14 = 0x2D,
CSI_2_RAW16 = 0x2E,
CSI_2_RAW20 = 0x2F,
USER_DEFINED_1 = 0x30,
USER_DEFINED_2 = 0x31,
USER_DEFINED_3 = 0x32,
USER_DEFINED_4 = 0x33,
USER_DEFINED_5 = 0x34,
USER_DEFINED_6 = 0x35,
USER_DEFINED_7 = 0x36,
USER_DEFINED_8 = 0x37,
};
/* DWC MIPI CSI-2 output types */
enum output {
IPI_OUT = 0,
IDI_OUT = 1,
BOTH_OUT = 2
};
/* IPI color components */
enum color_mode {
COLOR48 = 0,
COLOR16 = 1
};
/* IPI cut through */
enum cut_through {
CTINACTIVE = 0,
CTACTIVE = 1
};
/* IPI output types */
enum ipi_output {
CAMERA_TIMING = 0,
AUTO_TIMING = 1
};
/* Format template */
struct mipi_fmt {
u32 mbus_code;
u8 depth;
u32 width;
u32 height;
};
struct mipi_dt {
u32 hex;
char *name;
};
/* CSI specific configuration */
struct csi_data {
u32 num_lanes;
u32 dphy_freq; //MBPS
u32 pclk;
u32 fps;
u32 bpp;
u32 output;
u32 ipi_mode;
u32 ipi_adv_features;
u32 ipi_cut_through;
u32 ipi_color_mode;
u32 ipi_auto_flush;
u32 virtual_ch;
u32 hsa;
u32 hbp;
u32 hsd;
u32 htotal;
u32 vsa;
u32 vbp;
u32 vfp;
u32 vactive;
};
/* Structure to embed device driver information */
struct dw_csi {
//struct v4l2_subdev sd;
//struct video_device vdev;
//struct v4l2_device v4l2_dev;
struct device *dev;
//struct media_pad pads[CSI_PADS_NUM];
struct mipi_fmt *fmt;
//struct v4l2_mbus_framefmt format;
void __iomem *base_address;
void __iomem *demo;
void __iomem *csc;
int ctrl_irq_number;
int demosaic_irq;
struct csi_data hw;
struct reset_control *rst;
struct phy *phy;
struct dw_csih_pdata *config;
struct mutex lock; /* protect resources sharing */
spinlock_t slock; /* interrupt handling lock */
u8 ipi_dt;
u8 index;
u8 hw_version_major;
u16 hw_version_minor;
};
void dw_mipi_csi_reset(struct dw_csi *csi_dev);
int dw_mipi_csi_mask_irq_power_off(struct dw_csi *csi_dev);
int dw_mipi_csi_hw_stdby(struct dw_csi *csi_dev);
void dw_mipi_csi_set_ipi_fmt(struct dw_csi *csi_dev);
void dw_mipi_csi_start(struct dw_csi *csi_dev);
int dw_mipi_csi_irq_handler(struct dw_csi *csi_dev);
void dw_mipi_csi_get_version(struct dw_csi *csi_dev);
int dw_mipi_csi_specific_mappings(struct dw_csi *csi_dev);
void dw_mipi_csi_fill_timings(struct dw_csi *dev, uint32_t width, uint32_t height);
void dw_mipi_csi_dump(struct dw_csi *csi_dev);
#if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
int dw_csi_create_capabilities_sysfs(struct platform_device *pdev);
int dw_csi_remove_capabilities_sysfs(struct platform_device *pdev);
#endif
int dw_mipi_csi_s_power(struct dw_csi *dev, int on);
int dw_mipi_csi_log_status(struct dw_csi *dev);
static inline void dw_mipi_csi_write(struct dw_csi *dev,
u32 address, u32 data)
{
writel(data, dev->base_address + address);
}
static inline u32 dw_mipi_csi_read(struct dw_csi *dev, u32 address)
{
return readl(dev->base_address + address);
}
#endif /*_DW_MIPI_CSI_H__ */

115
vvcam/native/csi/nwl/nwl_regs.h Executable file
View File

@@ -0,0 +1,115 @@
/****************************************************************************
*
* 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.
*
*****************************************************************************/
#ifndef _NWL_REGS_H_
#define _NWL_REGS_H_
/*
* MRV_MIPICSI1_NUM_LANES
* Config num lanes register [3:0] rw
* 0000b - controller off
* 0001b - 1 Lane
* 0010b - 2 Lanes
* 0011b - 3 Lanes
* 0100b - 4 Lanes
*/
#define MRV_MIPICSI_NUM_LANES 0x0
/*
* MRV_MIPICSI1_LANES_CLK
* Configure lanes clock [0]
* 0b - disable
* 1b - enable
*/
#define MRV_MIPICSI_LANES_CLK 0x4
/*
* MRV_MIPICSI1_LANES_DATA
* enable/disable lanes data [7:0]
* setting bits to a '1' value enable data lane
*/
#define MRV_MIPICSI_LANES_DATA 0x8
/*
* MRV_MIPICSI1_IGNORE_VC
* enable/disable lanes clock [0]
* setting bits to a '1' value enable data value
*/
#define MRV_MIPICSI_IGNORE_VC 0x80
/*
* MRV_MIPICSI1_OUT_SHIFT
* Configure csi_vid_out register
*/
#define MRV_MIPICSI_FIFO_SENSD_LEVEL 0x88
#define MRV_MIPICSI_VID_VSYNC 0x8c
#define MRV_MIPICSI_VID_HSYNC_FP 0x90
#define MRV_MIPICSI_VID_HSYNC 0x94
#define MRV_MIPICSI_VID_HSYNC_BP 0x98
#ifdef ISP8000L_V1801
#define MRV_MIPICSI0_CTRL 0x8240 //0x308240
#else
#define MRV_MIPICSI0_CTRL 0x108240 //0x308240
#endif
#define MRV_MIPICSI1_CTRL 0x8244 //0x308244
#endif /* _NWL_REGS_H_ */

View File

@@ -0,0 +1,216 @@
/****************************************************************************
*
* 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 <linux/module.h>
#include <linux/uaccess.h>
#ifdef ISP8000L_V2008
#include <linux/io.h> //Fix thead compile error.
#endif
#include "nwl_regs.h"
#include "csi_ioctl.h"
int vvnative_csi_module_init(void * dev);
int vvnative_csi_module_exit(void * dev);
int vvnative_csi_set_stream_control(void * dev);
int vvnative_csi_set_cfg(void * dev);
int vvnative_csi_set_bit_shift(void *dev);
static int nwl_register_write(void * dev,unsigned int addr, unsigned int data)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
writel(data, base_addr + addr);
return 0;
}
#if 0
static int nwl_register_read(void * dev,unsigned int addr, unsigned int *data)
{
void __iomem *base_addr;
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
base_addr = nwl_csi_dev->base;
*data = readl(base_addr + addr);
return 0;
}
#endif
int vvnative_csi_set_stream_control(void * dev)
{
struct vvcam_csi_dev *nwl_csi_dev;
u32 clock_status;
u32 data_status;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
if (nwl_csi_dev->streaming_enable)
{
clock_status = 0x01;
data_status = 0xFF;
}
else
{
clock_status = 0x00;
data_status = 0x00;
}
nwl_register_write(dev,MRV_MIPICSI_LANES_CLK, clock_status);
nwl_register_write(dev,MRV_MIPICSI_LANES_DATA, data_status);
return 0;
}
int vvnative_csi_set_cfg(void * dev)
{
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
nwl_register_write(dev,MRV_MIPICSI_NUM_LANES, nwl_csi_dev->csi_lane_cfg.mipi_lane_num);
switch (nwl_csi_dev->csi_lane_cfg.mipi_lane_num)
{
case 1:
nwl_register_write(dev,MRV_MIPICSI_LANES_DATA, 0x01);
break;
case 2:
nwl_register_write(dev,MRV_MIPICSI_LANES_DATA, 0x03);
break;
case 4:
nwl_register_write(dev,MRV_MIPICSI_LANES_DATA, 0x0F);
break;
default:
break;
}
return 0;
}
int vvnative_csi_set_bit_shift(void * dev)
{
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
if (nwl_csi_dev->device_idx == 0)
{
#ifndef INPUT_SIGNAL_12_BIT
nwl_register_write(dev,MRV_MIPICSI0_CTRL, 16 - nwl_csi_dev->bit_width); //16bit high-aligned
#else
nwl_register_write(dev,MRV_MIPICSI0_CTRL, 0x0); //input signal 12 bit does not need to shift
#endif
}else
{
#ifndef INPUT_SIGNAL_12_BIT
nwl_register_write(dev,MRV_MIPICSI1_CTRL, 16 - nwl_csi_dev->bit_width); //16bit high-aligned
#else
nwl_register_write(dev,MRV_MIPICSI0_CTRL, 0x0); //input signal 12 bit does not need to shift
#endif
}
return 0;
}
int vvnative_csi_module_init(void * dev)
{
struct vvcam_csi_dev *nwl_csi_dev;
if (dev == NULL)
return -1;
nwl_csi_dev = dev;
nwl_register_write(dev,MRV_MIPICSI_NUM_LANES, 0x04);
nwl_register_write(dev,MRV_MIPICSI_LANES_CLK, 0x01);
nwl_register_write(dev,MRV_MIPICSI_LANES_DATA, 0x0F);
nwl_register_write(dev,MRV_MIPICSI_IGNORE_VC, 0x01);
nwl_register_write(dev,MRV_MIPICSI_FIFO_SENSD_LEVEL, 0x41);
nwl_register_write(dev,MRV_MIPICSI_VID_VSYNC, 0x20);
nwl_register_write(dev,MRV_MIPICSI_VID_HSYNC_FP, 0x20);
nwl_register_write(dev,MRV_MIPICSI_VID_HSYNC, 0x01);
nwl_register_write(dev,MRV_MIPICSI_VID_HSYNC_BP, 0x20);
if (nwl_csi_dev->device_idx == 0)
{
nwl_register_write(dev,MRV_MIPICSI0_CTRL, 0);
}else
{
nwl_register_write(dev,MRV_MIPICSI1_CTRL, 0);
}
return 0;
}
int vvnative_csi_module_exit(void * dev)
{
return 0;
}

View File

@@ -0,0 +1,367 @@
/****************************************************************************
*
* 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 <asm/io.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/debugfs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include "csi_ioctl.h"
#include "csi_common.h"
#define VIVCAM_CSI_NAME "vivcsi"
#define VIVCAM_CSI_MAXCNT 2
struct vvcam_csi_driver_dev
{
struct cdev cdev;
dev_t devt;
struct class *class;
struct mutex vvmutex;
void *private;
};
static unsigned int vvcam_csi_major = 0;
static unsigned int vvcam_csi_minor = 0;
static struct class *vvcam_csi_class;
static unsigned int devise_register_index = 0;
static int vvcam_csi_open(struct inode * inode, struct file * file)
{
struct vvcam_csi_driver_dev *pdriver_dev;
pdriver_dev = container_of(inode->i_cdev, struct vvcam_csi_driver_dev, cdev);
file->private_data = pdriver_dev;
return 0;
};
static long vvcam_csi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct vvcam_csi_driver_dev *pdriver_dev;
struct vvcam_csi_dev * pcsi_dev;
long ret;
pdriver_dev = file->private_data;
if (pdriver_dev == NULL)
{
pr_err("%s:file private is null point error\n", __func__);
return -ENOMEM;
}
pcsi_dev = pdriver_dev->private;
pr_info("%s:pdriver_dev =0x%px\n", __func__,pdriver_dev);
pr_info("%s:csi[%d] pcsi_dev =0x%px\n", __func__,pcsi_dev->device_idx,pcsi_dev);
mutex_lock(&pdriver_dev->vvmutex);
ret = csi_priv_ioctl(pcsi_dev, cmd, (void __user *)arg);
mutex_unlock(&pdriver_dev->vvmutex);
return ret;
};
static int vvcam_csi_release(struct inode * inode, struct file * file)
{
return 0;
};
static struct file_operations vvcam_csi_fops = {
.owner = THIS_MODULE,
.open = vvcam_csi_open,
.release = vvcam_csi_release,
.unlocked_ioctl = vvcam_csi_ioctl,
};
static int vvcam_csi_probe(struct platform_device *pdev)
{
int ret = 0;
struct vvcam_csi_driver_dev *pdriver_dev;
struct vvcam_csi_dev * pcsi_dev;
pr_info("enter %s\n", __func__);
if (pdev->id >= VIVCAM_CSI_MAXCNT)
{
pr_err("%s:pdev id is %d error\n", __func__,pdev->id);
return -EINVAL;
}
pdriver_dev = devm_kzalloc(&pdev->dev,sizeof(struct vvcam_csi_driver_dev), GFP_KERNEL);
if (pdriver_dev == NULL)
{
pr_err("%s:alloc struct vvcam_csi_driver_dev error\n", __func__);
return -ENOMEM;
}
memset(pdriver_dev,0,sizeof(struct vvcam_csi_driver_dev ));
pr_info("%s:csi[%d]: pdriver_dev =0x%px\n", __func__,pdev->id,pdriver_dev);
pcsi_dev = devm_kzalloc(&pdev->dev,sizeof(struct vvcam_csi_dev), GFP_KERNEL);
if (pcsi_dev == NULL)
{
pr_err("%s:alloc struct vvcam_csi_dev error\n", __func__);
return -ENOMEM;
}
memset(pcsi_dev,0,sizeof(struct vvcam_csi_dev ));
pr_info("%s:csi[%d]: pcsi_dev =0x%px\n", __func__,pdev->id,pcsi_dev);
pcsi_dev->device_idx = pdev->id;
//mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
//pcsi_dev->base = devm_ioremap_resource(&pdev->dev, mem);
if (pcsi_dev->device_idx == 0)
{
pcsi_dev->base = ioremap(VVCSI0_BASE, VVCSI_SIZE);
}else
{
pcsi_dev->base = ioremap(VVCSI1_BASE, VVCSI_SIZE);
}
if (IS_ERR(pcsi_dev->base))
return PTR_ERR(pcsi_dev->base);
pdriver_dev->private = pcsi_dev;
mutex_init(&pdriver_dev->vvmutex);
platform_set_drvdata(pdev, pdriver_dev);
ret = vvnative_csi_module_init(pcsi_dev);
if (ret != 0)
{
pr_err("%s:vvnative_csi_module_init error\n", __func__);
return -ENOMEM;
}
if (devise_register_index == 0)
{
if (vvcam_csi_major == 0)
{
ret = alloc_chrdev_region(&pdriver_dev->devt, 0, VIVCAM_CSI_MAXCNT, VIVCAM_CSI_NAME);
if (ret != 0)
{
pr_err("%s:alloc_chrdev_region error\n", __func__);
return ret;
}
vvcam_csi_major = MAJOR(pdriver_dev->devt);
vvcam_csi_minor = MINOR(pdriver_dev->devt);
}
else
{
pdriver_dev->devt = MKDEV(vvcam_csi_major, vvcam_csi_minor);
ret = register_chrdev_region(pdriver_dev->devt, VIVCAM_CSI_MAXCNT, VIVCAM_CSI_NAME);
if (ret)
{
pr_err("%s:register_chrdev_region error\n", __func__);
return ret;
}
}
vvcam_csi_class = class_create(THIS_MODULE, VIVCAM_CSI_NAME);
if (IS_ERR(vvcam_csi_class))
{
pr_err("%s[%d]:class_create error!\n", __func__, __LINE__);
return -EINVAL;
}
}
pdriver_dev->devt = MKDEV(vvcam_csi_major, vvcam_csi_minor + pdev->id);
cdev_init(&pdriver_dev->cdev, &vvcam_csi_fops);
ret = cdev_add(&pdriver_dev->cdev, pdriver_dev->devt, 1);
if ( ret )
{
pr_err("%s[%d]:cdev_add error!\n", __func__, __LINE__);
return ret;
}
pdriver_dev->class = vvcam_csi_class;
device_create(pdriver_dev->class, NULL, pdriver_dev->devt,
pdriver_dev, "%s%d", VIVCAM_CSI_NAME, pdev->id);
devise_register_index++;
pr_info("exit %s\n", __func__);
return ret;
}
static int vvcam_csi_remove(struct platform_device *pdev)
{
struct vvcam_csi_driver_dev *pdriver_dev;
struct vvcam_csi_dev * pcsi_dev;
pr_info("enter %s\n", __func__);
devise_register_index--;
pdriver_dev = platform_get_drvdata(pdev);
pcsi_dev = pdriver_dev->private;
iounmap(pcsi_dev->base);
cdev_del(&pdriver_dev->cdev);
device_destroy(pdriver_dev->class, pdriver_dev->devt);
unregister_chrdev_region(pdriver_dev->devt, VIVCAM_CSI_MAXCNT);
if (devise_register_index == 0)
{
class_destroy(pdriver_dev->class);
}
return 0;
}
static struct platform_driver vvcam_csi_driver = {
.probe = vvcam_csi_probe,
.remove = vvcam_csi_remove,
.driver = {
.name = VIVCAM_CSI_NAME,
.owner = THIS_MODULE,
}
};
static void vvcam_csi_pdev_release(struct device *dev)
{
pr_info("enter %s\n", __func__);
}
#ifdef WITH_VVCAM
static struct resource vvcam_csi0_resource[] = {
[0] = {
.start = VVCSI0_BASE,
.end = VVCSI0_BASE + VVCSI_SIZE - 1,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device vvcam_csi_pdev = {
.name = VIVCAM_CSI_NAME,
.id = 0,
.resource = vvcam_csi0_resource,
.num_resources = 0,
.dev.release = vvcam_csi_pdev_release,
};
#endif
#ifdef WITH_VVCAM_DUAL
static struct resource vvcam_csi1_resource[] = {
[0] = {
.start = VVCSI1_BASE,
.end = VVCSI1_BASE + VVCSI_SIZE - 1,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device vvcam_csi_dual_pdev = {
.name = VIVCAM_CSI_NAME,
.id = 1,
.resource = vvcam_csi1_resource,
.num_resources = 0,
.dev.release = vvcam_csi_pdev_release,
};
#endif
static int __init vvcam_csi_init_module(void)
{
int ret = 0;
pr_info("enter %s\n", __func__);
#ifdef WITH_VVCAM
ret = platform_device_register(&vvcam_csi_pdev);
if (ret)
{
pr_err("register platform device failed.\n");
return ret;
}
#endif
#ifdef WITH_VVCAM_DUAL
ret = platform_device_register(&vvcam_csi_dual_pdev);
if (ret)
{
pr_err("register platform device failed.\n");
return ret;
}
#endif
ret = platform_driver_register(&vvcam_csi_driver);
if (ret)
{
pr_err("register platform driver failed.\n");
return ret;
}
return ret;
}
static void __exit vvcam_csi_exit_module(void)
{
pr_info("enter %s\n", __func__);
platform_driver_unregister(&vvcam_csi_driver);
#ifdef WITH_VVCAM
platform_device_unregister(&vvcam_csi_pdev);
#endif
#ifdef WITH_VVCAM_DUAL
platform_device_unregister(&vvcam_csi_dual_pdev);
#endif
}
module_init(vvcam_csi_init_module);
module_exit(vvcam_csi_exit_module);
MODULE_DESCRIPTION("CSI");
MODULE_LICENSE("GPL");

19
vvcam/native/dec400/Makefile Executable file
View File

@@ -0,0 +1,19 @@
include $(PWD)/../Param.mk
include $(PWD)/../../version/$(VERSION_CFG).mk
TARGET = vvcam_dec400
obj-m +=$(TARGET).o
$(TARGET)-objs += dec400.o
$(TARGET)-objs += dec400_ioctl.o
EXTRA_CFLAGS += -I$(PWD)/../../common
PWD :=$(shell pwd)
all:
make -C $(KERNEL) M=$(PWD) modules
modules_install:
make -C $(KERNEL_SRC) M=$(SRC) modules_install
clean:
rm -rf $($(TARGET)-objs)
make -C $(KERNEL) M=`pwd` clean

Some files were not shown because too many files have changed in this diff Show More