Navigation

    全志在线开发者论坛

    • Register
    • Login
    • Search
    • Categories
    • Tags
    • 在线文档
    • 社区主页
    1. Home
    2. awwwwa
    3. Best
    A
    • Profile
    • Following 0
    • Followers 19
    • my integral 14982
    • Topics 12
    • Posts 565
    • Best 154
    • Groups 1

    Best posts made by awwwwa

    • Reply: T527烧写安全固件后无法启动

      烧写安全固件和rotpk.bin之后就再也无法烧录非安全固件了,似乎是KeystoreService未能正常启动

      posted in T Series
      A
      awwwwa
    • Reply: V853 DDR原理图问题

      AW平台的DRAM控制器支持地址线REMAP,可以通过REMAP简化外部不同种类的DRAM的连接。

      这个REAMP是固定在芯片里的不能自己修改,在电路原理图可以看到REMAP的引脚。

      如图,如果需要挂DDR3内存,需要接DDR3的REAMP,如果需要接DDR2,可以接默认的REMAP

      07d2327d-bde1-4367-97e2-5b4b770b35e7-image.png

      举个其他平台的例子:
      这里接的是 LPDDR4,使用LPDDR4的REMAP
      84281c99-eb73-4892-b50d-bf3132389541-image.png

      这里接的是DDR4,使用DDR4的REMAP
      b14dfa2e-9a5f-4ba1-98bb-8f7d8541fc3b-image.png

      posted in V Series
      A
      awwwwa
    • Reply: 哪吒D1-H 通过bootargs来静态设置ip

      OpenWRT会重写kernel部分的配置,具体请参考OpenWRT文档

      posted in MR Series
      A
      awwwwa
    • Reply: 为什么t527的设备树uart0没有配置引脚

      为了兼容卡打印的问题,UART的引脚在boot0&Uboot中初始化,如不需要卡打印可以配置上需要的引脚

      posted in T Series
      A
      awwwwa
    • Reply: V851S SPI2 死机

      对照手册:

      • SPI2 地址 0x04027000, 没问题
        0f2f1b97-2298-4112-923a-c25db5428943-image.png

      • SPI2 中断号 49,配置时需要减掉SIG和PPI的数量32,也就是17
        eeb6838d-b14f-441f-870b-badb6672796a-lQLPJxe-6SonLpDM2s0B87B4X1hs1FJTtAUq12ehL88A_499_218.png

      中断号配置错误,应该为17不是18

      		spi2: spi@04027000 {
      			#address-cells = <1>;
      			#size-cells = <0>;
      			compatible = "allwinner,sun8i-spi";
      			device_type = "spi2";
      			reg = <0x0 0x04027000 0x0 0x1000>;
      			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
      			clocks = <&clk_pll_periph0300m>, <&clk_spi2>;
      			status = "disabled";
      		};
      
      posted in V Series
      A
      awwwwa
    • Reply: R128S2 SDK 编译错误

      @yilan7805 看上去解压工具链压缩文件有损坏,重新下载一下?

      posted in MR Series
      A
      awwwwa
    • Reply: T113S3双路 dual lvds驱动不起来

      uboot和dtsi里面添加dual link IO的配置

      demo:
      
      lvds2link_pins_a: lvds2link@0 {
           allwinner,pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD8", "PD9", "PD6", "PD7", \
           "PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PD18", "PD19", "PD16", "PD17";
           allwinner,pname = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD8", "PD9", "PD6", "PD7", \
           "PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PD18", "PD19", "PD16", "PD17";
           allwinner,function = "lvds1";
           allwinner,muxsel = <3>;
           allwinner,drive = <3>;
           allwinner,pull = <0>;
       };
      
      lvds2link_pins_b: lvds2link@1 {
           allwinner,pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD8", "PD9", "PD6", "PD7", \
           "PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PD18", "PD19", "PD16", "PD17";
           allwinner,pname = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD8", "PD9", "PD6", "PD7", \
           "PD10", "PD11", "PD12", "PD13", "PD14", "PD15", "PD18", "PD19", "PD16", "PD17";
           allwinner,function = "lvds1_suspend";
           allwinner,muxsel = <7>;
           allwinner,drive = <3>;
           allwinner,pull = <0>;
       };
      

      dts中 修改为lvds dual link模式,并引用dtsi里配好的dual link IO

      &lcd0{
      ...
       lcd_lvds_if          = <1>;
      ...
      ...
      pinctrl-0 = <&lvds2link_pins_a>;
      pinctrl-1 = <&lvds2link_pins_b>;
      ...
      }
      

      其他和single link的配置方法无异,如果点不亮请检查时序

      53899931-a632-431e-ac3a-5826278b35e9-LCDTiming.jpg

      这里看到dclk配置是80

      ac38a30a-5d44-4530-a265-33d443cddda7-image.png

      但是手册需求的是54

      1b0f929a-658a-4d7a-b097-ea05513595e5-image.png

      这里提供一套1920x720的时序作为参考

      &lcd0 {
      	lcd_used            = <1>;
      
      	lcd_driver_name     = "default_lcd";
      	lcd_backlight       = <50>;
      	lcd_if              = <3>;
      
      	lcd_x               = <1920>;
      	lcd_y               = <720>;
      	lcd_width           = <150>;
      	lcd_height          = <94>;
      	lcd_dclk_freq       = <94>;
      
      	lcd_pwm_used        = <1>;
      	lcd_pwm_ch          = <3>;
      	lcd_pwm_freq        = <50000>;
      	lcd_pwm_pol         = <1>;
      	lcd_pwm_max_limit   = <255>;
      
      	lcd_hbp             = <64>;
      	lcd_ht              = <2064>;
      	lcd_hspw            = <20>;
      	lcd_vbp             = <30>;
      	lcd_vt              = <760>;
      	lcd_vspw            = <10>;
      
      	lcd_lvds_if         = <1>;
      	lcd_lvds_colordepth = <0>;
      	lcd_lvds_mode       = <0>;
      	lcd_frm             = <1>;
      	lcd_hv_clk_phase    = <0>;
      	lcd_hv_sync_polarity= <0>;
      	lcd_gamma_en        = <0>;
      	lcd_bright_curve_en = <0>;
      	lcd_cmap_en         = <0>;
      
      	deu_mode            = <0>;
      	lcdgamma4iep        = <22>;
      	smart_color         = <90>;
      
      	pinctrl-0 = <&lvds2link_pins_a>;
      	pinctrl-1 = <&lvds2link_pins_b>;
      };
      
      posted in T Series
      A
      awwwwa
    • Reply: V853使用MIPI CSI接口是否只支持RAW格式像素?

      @xjy_5 一般来说配置sensor0_isp_used = <0>; 就不会调用ISP,虽然会配置但是不会处理。需要再跟踪一下调用

      posted in V Series
      A
      awwwwa
    • Reply: 尝试使用D1-H开发板集成区块链轻节点

      @zoone https://www.xrvm.cn/community/download?id=4382928864901402624

      posted in MR Series
      A
      awwwwa
    • Reply: T113S3 I2C异常

      engine-mode开了,配置 下twi_drv_used = <1>;

      posted in T Series
      A
      awwwwa
    • Reply: V851S I2C/TWI 损坏(xfer 错误)

      @kanken6174 上拉是1.8V吗,还是上拉到3.3v了

      posted in V Series
      A
      awwwwa
    • Reply: 有没有大佬知道这个f1c100s和stm32去通信,配置好烧到板子上串口走不下去了

      Linux都没启动,先检查为什么Linux没启动

      posted in Linux
      A
      awwwwa
    • Reply: 全志哪些芯片是DRM驱动?哪些是fb+de驱动?

      26665a6e-0997-4480-bc12-e0ceab685467-image.png

      posted in T Series
      A
      awwwwa
    • Reply: V853 SDK : PMU TWI

      @alb702 在 V853 SDK : PMU TWI 中说:

      [267]ic cant match axp, please check...

      V853 和 V853s 的芯片安全系统验证不一样,SDK不能通用,这行输出表示芯片型号验证失败,跳过初始化DRAM

      posted in V Series
      A
      awwwwa
    • Reply: UDSIK分区表的大小和实际系统挂载的大小不对应

      UDISK属性写错了

      posted in Linux
      A
      awwwwa
    • Reply: t113-s3 SMHC模块的校准延时链是个什么技术啊?怎么使用呢?

      @zm960406 这个是用于优化采样的,具体用法可以参考bsp驱动

      posted in T Series
      A
      awwwwa
    • Reply: 测试编译不过

      打入这个补丁试一下:de88083d-a6c8-403e-947c-81ccd05dc849-0001-fix-add-ENABLE_HARDFP-options.patch

      0001-feat-Support-e907-core-boot-up.patch

      可能是不同编译器导致的

      posted in V Series
      A
      awwwwa
    • Reply: 关于PhoenixCardv4.2.7

      377391af-878f-4a41-b29a-7c50b6faad29-image.png

      NOR固件不能烧卡

      posted in Linux
      A
      awwwwa
    • Reply: T527下载SDK出错

      @chaogai 请使用python2进行下载

      posted in T Series
      A
      awwwwa
    • Reply: 测试编译不过
      • helloworld_fel 使用了 VFP 寄存器参数,但是某个库文件(libgcc.a(_udivmoddi4.o))却不支持。

      • 缺少 .note.GNU-stack 段,暗示可执行栈缺失。

      • 对于具有 RWX 权限的 LOAD 段,给出了警告。

      • 在链接时,出现了对 raise 函数的未定义引用。

      posted in V Series
      A
      awwwwa
    • busybox init 简介

      一、简介

      tina 使用busybox init方式启动,首先调用执行pseudo_init(挂载文件系统,如/proc、/tmp、/sys /etc、/usr),接着会调用/sbin/init进程,而init进程调用的第一个启动脚本为/etc/init.d/rcS。


      二、平台的自定义
      不同的平台文件系统具有其共性与特殊性。tina/packge/busybox-init-base-files/files下提供了所有平台的基础文件。而在tina/target/allwinner/XXX/busybox-init-base-files下存放的是平台特性文件,其优先级高于前者,即当前者目录和后者存在有相同文件时,以后者为准。如有以下两个文件:

      A:tina/target/allwinner/r11-R11_pref1/busybox-init-base-files/etc/banner
      B:tina/package/busybox-init-base-files/files/etc/banner

      最终拷贝到文件系统中的为A。


      三、pseudo_init与rcS
      pseudo_init与rcS文件中存在很多平台共性的代码,避免系统充斥大量冗余代码,以及方便基础文件的维护和开发。所以不允许在特定平台下自定义pseudo_init、rcS文件(必须使用tina/packge/busybox-init-base-files/files下的pseudo_init、rcS)。
      如果需要添加平台特定配置(pseudo_init,rcS没有配置),可将其写到rc.preboot,rc.final中,参考第四节。


      四、rcS脚本
      1.功能描述
      (1)执行/etc/init.d/rc.preboot。
      为了满足开机快速启动的需求,提供了用户可自定义rc.preboot文件,即在tina/target/allwinner/XXX/busybox-init-base-files/etc/init.d/目录下创建rc.preboot脚本文件,将会被rcS最先调用执行。
      (2)配置打印级别,主机名称。
      (3)执行/etc/init.d/rc.log,配置系统log信息。
      系统默认使用的是tina/package/busybox-init-base-files/files/etc/init.d/rc.log脚本进行配置系统log信息。用户可在tina/target/allwinner/XXX/busybox-init-base-files/etc/init.d/下创建rc.log,自定义rc.log。
      如果需要使用默认rc.log,需要在make menuconfig配置。

      	Base system  --->
      	 busybox-init-base-files......................... Busybox init base system  --->
      	  [*]   Use the rc.log
      

      (4)挂载UDISK。
      (5)执行/etc/init.d/rc.modules,加载内核模块。
      系统默认使用的是tina/package/busybox-init-base-files/files/etc/init.d/rc.modules脚本进行内核模块自加载,用户可在tina/target/allwinner/XXX/busybox-init-base-files/etc/init.d/下创建rc.modules,自定义rc.modules。
      如果需要使用默认rc.modules,需要在make menuconfig配置如下。

      	Base system  --->
      	 busybox-init-base-files......................... Busybox init base system  --->
      	   [*]   Use the rc.modules
      

      (6)启动/etc/rc.d下的脚本。

      关于执行rc.d下的启动脚本,目的为兼容procd式的应用脚本。/etc/rc.d下的脚本是链接到/etc/init.d/下,默认情况下只执行adbd,如果需要执行其他脚本,需要在tina/target/allwinner/XXX/busybox-init-base-files/etc/init.d/下,自定义load_script.conf文件,文件内容中写上要启动的应用,如adbd(注意,每一个应用占一行)。可参考:tina/packge/busybox-init-base-files/files/etc/init.d/load_script.conf。
      
      	如果需要执行rc.d下的启动脚本,需要在make menuconfig做如下配置。
      	Base system  --->
      	 busybox-init-base-files......................... Busybox init base system  --->
      	   [*]   Auto load the script in /etc/rc.d
      

      (7)ota初始化。

      (8)执行/etc/init.d/rc.final,用户自定义启动脚本。
      用户可在tina/packge/busybox-init-base-files/files/etc/init.d/下创建一个rc.final脚本,自定义启动应用程序,该脚本将会被rcS最后调用执行。

      2.rc.preboot与rc.final的区别?
      rc.preboot比rc.final先运行,在执行rc.preboot脚本的时候,系统的一些初始化操作还没完成,如挂载UDISK、内核模块自加载、ota等等操作。而rc.final执行的时候,以上的初始化操作已经完成。

      五.如何写应用的启动脚本

      example:开机自启动smartlinkd(tina/package/allwinner/smartlinkd/files/smartlinkd.init)
      1.方法一(特定格式要求)

      详细的格式参考:
      https://wiki.openwrt.org/inbox/procd-init-scripts
      https://wiki.openwrt.org/doc/techref/initscripts

      (1)procd式

      #!/bin/sh /etc/rc.common   #本质为script脚本,以#!开头, 之后执行/etc/rc.common
      START=98		#开机启动优先级(序列) [数值越小, 越先启动]
      STOP=98			#关机停止优先级(序列) [数值越小, 越先关闭]
      
      USE_PROCD=1
      PROG=smartlinkd
      
      start_service() {    #启动函数
          procd_open_instance
          procd_set_param command $PROG -d
          procd_close_instance
      }
      
      shutdown() {
          echo shutdown
      }
      

      (2)Sys式

      #!/bin/sh /etc/rc.common
      START=98
      STOP=98
      
      PROG=smartlinkd
      
      start() {
        smartlinkd -d &
      }
      
      

      使用上述procd式和sys式脚本,既能兼容procd init启动和busybox init的启动方式。
      另外如果使用的是busybox init的启动方式,还需要在load_script.conf文件中换行添加内容:smartlinkd

      2.方法二(无特定格式要求)
      创建rc.preboot或者rc.final脚本,添加启动smartlinkd的内容。

      posted in Linux
      A
      awwwwa
    • Reply: 关于opkg包管理器的一些问题,恳请各位大佬关注帮助一下!

      opkg 数据源默认裁剪
      872272e2-088d-4219-b5e3-912f9b301472-image.png

      posted in T Series
      A
      awwwwa
    • Reply: v853 vin通路配置

      (1)在线模式:四个vipp和dma实体,最大缩小比例为16*16,每路最多可支持16个orl
      (2)离线模式:每个vipp和dma可分时复用为4个vipp和dma虚拟体,四个vipp和dma实体相互独立,在线模式和离线模式开关也是相互独立的;
      (3)VIPP和DAM的分时复用(离线模式)与isp和tdm的分时复用(离线模式)是绑定关系,即tdm和isp开启了离线模式,vipp和dma的输入端如果是isp,那么vipp和dma也需要开启离线模式;
      (4)只有VIPP0和dma0实体支持VE在线编码,而vipp0在线,如果vipp00的输入端为isp,那么tdm和isp也只能配置在线模式,而isp在线,那么四个vipp和dma实体都只能配置在线模式;

      online 和 offline 配 置 方 式 在 board.dts , 所 以 需 要 在 对 应 版 型 的 board.dts 中 找 到 vind0 节 点 配 置 列 表 , 对 应 关 系 为 tdm 对 应 节 点 , isp 对 应 isp00 节 点 , vipp 对 应 scaler00 、 scaler10 、 scaler20 和 scaler30 节 点 , dma 对 , 应 vinc00 、 vinc10 、 vinc20 和 vinc30 节 点 。

      • 在线模式,单路3输出

      18ca36be-ad38-4813-9032-065baa08e803-image.png

      • 离线模式,2路8输出

      7c83156e-caa3-4a20-b0cb-cbb1546d1931-image.png

      posted in V Series
      A
      awwwwa
    • T113 busybox init 配置 overlayfs 为 UDISK 分区而不是 rootfs_data
      1. 先确定挂载overlayfs

      查看 pseudo_init 中 MOUNT_OVERLAY 是不是 1,如果不是配置为 1

      package/busybox-init-base-files/files/pseudo_init
      

      9a131c14-2a2c-493d-8acc-b623cce5a138-image.png

      1. 修改挂载分区

      找到文件末尾,吧 rootfs_data 改成UDISK

      c3474e4a-e208-4549-9a82-9d9cc7372300-image.png

      posted in Linux
      A
      awwwwa
    • T527 使用 DRM 驱动 edp 屏幕

      进入 menuconfig 勾选 drm 驱动

      ./build.sh menuconfig
      

      先勾选 DRM

      cb61de74-4427-4634-ad9a-7fb0355f0c2c-image.png

      再勾选 DRM 驱动

      d5bfe0b4-9c31-4685-9f5a-edf9a314ecc8-image.png

      选择驱动的phy

      cd43edeb-294c-4e54-bca2-02fcd83870d6-image.png

      选择屏幕

      3296da2b-cc7e-4440-9379-c538a52c59e1-image.png

      选择 general 屏幕面板驱动

      c6048ab0-44cc-4889-a0b4-8c6ef4d76cb3-image.png

      关闭原来的 disp2 fbdev 驱动

      f8db1009-4b34-4d8e-839d-3c7a358126d6-image.png

      配置设备树

      	edp_panel_backlight: edp_backlight {
      		compatible = "pwm-backlight";
      		status = "okay";
      		brightness-levels = <
      			  0   1   2   3   4   5   6   7
      			  8   9  10  11  12  13  14  15
      			 16  17  18  19  20  21  22  23
      			 24  25  26  27  28  29  30  31
      			 32  33  34  35  36  37  38  39
      			 40  41  42  43  44  45  46  47
      			 48  49  50  51  52  53  54  55
      			 56  57  58  59  60  61  62  63
      			 64  65  66  67  68  69  70  71
      			 72  73  74  75  76  77  78  79
      			 80  81  82  83  84  85  86  87
      			 88  89  90  91  92  93  94  95
      			 96  97  98  99 100 101 102 103
      			104 105 106 107 108 109 110 111
      			112 113 114 115 116 117 118 119
      			120 121 122 123 124 125 126 127
      			128 129 130 131 132 133 134 135
      			136 137 138 139 140 141 142 143
      			144 145 146 147 148 149 150 151
      			152 153 154 155 156 157 158 159
      			160 161 162 163 164 165 166 167
      			168 169 170 171 172 173 174 175
      			176 177 178 179 180 181 182 183
      			184 185 186 187 188 189 190 191
      			192 193 194 195 196 197 198 199
      			200 201 202 203 204 205 206 207
      			208 209 210 211 212 213 214 215
      			216 217 218 219 220 221 222 223
      			224 225 226 227 228 229 230 231
      			232 233 234 235 236 237 238 239
      			240 241 242 243 244 245 246 247
      			248 249 250 251 252 253 254 255>;
      		default-brightness-level = <200>;
      		enable-gpios = <&pio PI 5 GPIO_ACTIVE_HIGH>;
      		/* power-supply = <&reg_backlight_12v>; */
      		pwms = <&a_pwm 5 5000000 0>;
      	};
      
      	edp_panel: edp_panel {
      		compatible = "edp-general-panel";
      		status = "okay";
      		power0-supply = <&reg_dcdc4>;
      
      		backlight = <&edp_panel_backlight>;
      
      		panel-timing {
      			clock-frequency = <348577920>; /* pixel clock */
      			hactive = <2560>;
      			hback-porch = <120>;
      			hfront-porch = <88>;
      			hsync-len = <32>;
      			vactive = <1600>;
      			vback-porch = <71>;
      			vfront-porch = <28>;
      			vsync-len = <5>;
      			/* hor_sync_polarity */
      			hsync-active = <1>;
      			/* ver_sync_polarity */
      			vsync-active = <1>;
      
      			// unused now
      			/*
      			de-active = <1>;
      			pixelclk-active = <1>;
      			syncclk-active = <0>;
      			interlaced;
      			doublescan;
      			doubleclk;
      			*/
      		};
      		ports {
      			#address-cells = <1>;
      			#size-cells = <0>;
      			panel_in: port@0 {
      				#address-cells = <1>;
      				#size-cells = <0>;
      				reg = <0>;
      				edp_panel_in: endpoint@0 {
      					reg = <0>;
      					remote-endpoint = <&edp_panel_out>;
      				};
      			};
      		};
      	};
      

      和 drm_edp 的配置

      &drm_edp {
      	status = "okay";
      
      	edp_ssc_en = <0>;
      	edp_ssc_mode = <0>;
      	edp_psr_support = <0>;
      	edp_colordepth = <8>; /* 6/8/10/12/16 */
      	edp_color_fmt = <0>; /* 0:RGB  1: YUV444  2: YUV422 */
      
      	lane1_sw = <0>;
      	lane1_pre = <0>;
      	lane2_sw = <0>;
      	lane2_pre = <0>;
      	lane3_sw = <0>;
      	lane3_pre = <0>;
      	efficient_training = <0>;
      
      	sink_capacity_prefer = <1>;
      	edid_timings_prefer = <1>;
      	timings_fixed = <1>;
      
      	vcc-edp-supply = <&reg_bldo3>;
      	vdd-edp-supply = <&reg_dcdc2>;
      	panel = <&edp_panel>;
      	ports {
      		edp_out: port@1 {
      			edp_panel_out: endpoint@0 {
      				reg = <0>;
      				remote-endpoint = <&edp_panel_in>;
      			};
      		};
      	};
      };
      posted in T Series
      A
      awwwwa
    • Reply: TinyVision 制作的高清 1080P USB 摄像头

      @bardi4567 what is the error log

      posted in V Series
      A
      awwwwa
    • Reply: t113使用sd卡启动卡住了

      @xingxing8 在 t113使用sd卡启动卡住了 中说:

      先看这行

      VFS: Cannot open root device "mmcblk0p5" or unknown-block(0,0): error -6

      这行表示没有挂载上mmc设备

      再往上找

      [ 4.002919] sunxi-mmc 4020000.sdmmc: Got CD GPIO
      [ 4.008458] sunxi-mmc 4020000.sdmmc: set cd-gpios as 24M fail
      [ 4.018859] sunxi-mmc 4020000.sdmmc: sdc set ios:clk 0Hz bm PP pm UP vdd 21 width 1 timing LEGACY(SDR12) dt B

      CD卡检测GPIO检测不到卡,关闭MMC驱动

      Linux中的驱动为了省电会根据CD引脚检测卡是否存在,不存在则关闭MMC驱动,U-boot驱动没有这个逻辑

      解决方法:

      1. 正向解决法
      • 根据实物硬件查看CD引脚配置,上下拉状态是否正常,是否反转CD
        83a89a3e-cad1-4bd7-9ad4-7d8caa3f582f-image.png
      1. 软件规避法
      • 直接关闭CD检测功能,取消注释 broken-cd;
        8fb933a9-17ad-4ed8-b25a-ac7d1e157945-image.png
      posted in Linux
      A
      awwwwa
    • Reply: T113如何移植RT补丁包

      联系板卡提供商,目前几家都已经提供rt补丁

      posted in Special
      A
      awwwwa
    • Reply: 关于V851S的opencv问题

      提供了Patch:https://github.com/YuzukiHD/TinyVision/blob/main/tina/openwrt/package/thirdparty/vision/opencv/patches/0004-support-sunxi-vin-camera.patch

      posted in V Series
      A
      awwwwa
    • Reply: AXP313A搭配H618开发板使用

      1, 如果是套片,默认三路0.9v
      2, 不会保存

      posted in H/F/TV Series
      A
      awwwwa
    • Reply: A133驱动 st7701s[480x480]问题

      uboot的设备树和kernel的设备树都需要配置

      posted in Linux
      A
      awwwwa
    • Reply: V851S tina linux ov5647 驱动程序没有 dmesg

      使用 V3s SDK 提供VFE框架的驱动移植到VIN框架下抓图成功。但是图像非常暗,并且撕裂,抓raw数据查看也是一样,考虑可能mclk不同步导致。

      sensor0:sensor@0 {
      	device_type = "sensor0";
      	sensor0_mname = "ov5648_mipi";
      	sensor0_twi_cci_id = <0>;
      	sensor0_twi_addr = <0x6c>;
      	sensor0_mclk_id = <0>;
      	sensor0_pos = "rear";
      	sensor0_isp_used = <1>;
      	sensor0_fmt = <1>;
      	sensor0_stby_mode = <0>;
      	sensor0_vflip = <0>;
      	sensor0_hflip = <0>;
      	sensor0_iovdd-supply = <>;
      	sensor0_iovdd_vol = <1800000>;
      	sensor0_avdd-supply = <>;
      	sensor0_avdd_vol = <2800000>;
      	sensor0_dvdd-supply = <>;
      	sensor0_dvdd_vol = <1200000>;
      	sensor0_power_en = <>;
      	sensor0_reset = <&pio PA 18 1 0 1 0>;
      	sensor0_pwdn = <&pio PA 19 1 0 1 0>;
      	sensor0_sm_hs = <>;
      	sensor0_sm_vs = <>;
      	flash_handle = <>;
      	act_handle = <>;
      	status	= "okay";
      };
      
      /*
       * A V4L2 driver for ov5647 Raw cameras.
       *
       * Copyright (c) 2022 by YuzukiTsuru  <gloomyghost@gloomyghost.com>
       * Copyright (c) 2018 by Allwinnertech Co., Ltd.  http://www.allwinnertech.com
       *
       * Authors:  Zheng ZeQun <zequnzheng@allwinnertech.com>
       *    	   Liang WeiJie <liangweijie@allwinnertech.com>
       *          YuzukiTsuru <gloomyghost@gloomyghost.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 <linux/init.h>
      #include <linux/module.h>
      #include <linux/slab.h>
      #include <linux/i2c.h>
      #include <linux/delay.h>
      #include <linux/videodev2.h>
      #include <linux/clk.h>
      #include <media/v4l2-device.h>
      #include <media/v4l2-mediabus.h>
      #include <linux/io.h>
      
      #include "camera.h"
      #include "sensor_helper.h"
      
      MODULE_AUTHOR("YuzukiTsuru");
      MODULE_DESCRIPTION("A low-level driver for ov5647 sensors");
      MODULE_LICENSE("GPL");
      
      #define MCLK              (24*1000*1000)
      #define V4L2_IDENT_SENSOR 0x5648
      
      /*
       * Our nominal (default) frame rate.
       */
      
      #define SENSOR_FRAME_RATE 30
      
      /*
       * The GC0310 i2c address
       */
      #define I2C_ADDR 0x6c
      
      #define SENSOR_NAME "ov5648_mipi"
      
      
      /*
       * The default register settings
       */
      
      static struct regval_list sensor_default_regs[] = {
      	//Slave_ID=0x6c;
      	{0x0100, 0x00},// ; software standby
      	{0x0103, 0x01},// ; software reset
      	{REG_DLY, 0x25},
      	{0x370c, 0x03},// ; analog control
      	{0x5000, 0x06},// ; lens off, bpc on, wpc on
      	{0x5003, 0x08},// ; buf_en
      	{0x5a00, 0x08},//
      	{0x3000, 0xff},// ; D[9:8] output
      	{0x3001, 0xff},// ; D[7:0] output
      	{0x3002, 0xff},// ; Vsync, Href, PCLK, Frex, Strobe, SDA, GPIO1, GPIO0 output
      	{0x301d, 0xf0},//
      	{0x3a18, 0x00},// ; gain ceiling = 15.5x
      	{0x3a19, 0xf8},// ; gain ceiling
      	{0x3c01, 0x80},// ; band detection manual mode
      	{0x3b07, 0x0c},// ; strobe frex mode
      	//; analog control
      	{0x3630, 0x2e},
      	{0x3632, 0xe2},
      	{0x3633, 0x23},
      	
      	{0x3634, 0x44},
      	{0x3620, 0x64},
      	{0x3621, 0xe0},
      	{0x3600, 0x37},
      	{0x3704, 0xa0},
      	{0x3703, 0x5a},
      	{0x3715, 0x78},
      	{0x3717, 0x01},
      	{0x3731, 0x02},
      	{0x370b, 0x60},
      	{0x3705, 0x1a},
      	{0x3f05, 0x02},
      	{0x3f06, 0x10},
      	{0x3f01, 0x0a},
      	//; AG/AE target
      	{0x3a0f, 0x58},// ; stable in high
      	{0x3a10, 0x50},// ; stable in low
      	{0x3a1b, 0x58},// ; stable out high
      	{0x3a1e, 0x50},// ; stable out low
      	{0x3a11, 0x60},// ; fast zone high
      	{0x3a1f, 0x28},// ; fast zone low
      	{0x4001, 0x02},// ; BLC start line
      	{0x4000, 0x09},// ; BLC enable
      	{0x3000, 0x00},// ; D[9:8] input
      	{0x3001, 0x00},// ; D[7:0] input
      	{0x3002, 0x00},// ; Vsync, Href, PCLK, Frex, Strobe, SDA, GPIO1, GPIO0 input
      	{0x3017, 0xe0},// ; MIPI PHY
      	{0x301c, 0xfc},//
      	{0x3636, 0x06},// ; analog control
      	{0x3016, 0x08},// ; MIPI pad enable
      	{0x3827, 0xec},//
      	{0x3018, 0x44},// ; MIPI 2 lane, MIPI enable
      	{0x3035, 0x21},// ; PLL
      	{0x3106, 0xf5},// ; PLL 
      	{0x3034, 0x1a},// ; PLL
      	{0x301c, 0xf8},//
      	{0x3503, 0x03},// ; Gain has no latch delay, AGC manual, AEC 
      			
      	{0x3501, 0x10},// ; exposure[15:8]
      	{0x3502, 0x80},// ; exposure[7:0]
      	{0x350a, 0x00},// ; gain[9:8]
      	{0x350b, 0x7f},// ; gain[7:0]
      	{0x5001, 0x01},// ; AWB on
      	{0x5180, 0x08},// ; AWB manual gain enable
      	
      	{0x5186, 0x04},// ; manual red gain high
      	{0x5187, 0x00},// ; manual red gain low
      	{0x5188, 0x04},// ; manual green gain high
      	{0x5189, 0x00},// ; manual green gain low
      	{0x518a, 0x04},// ; manual blue gain high
      	{0x518b, 0x00},// ; manual blue gain low
      	{0x5000, 0x06},// ; lenc off, bpc on, wpc on
      };
      
      static struct regval_list sensor_qsxga_regs[] = { //qsxga: 2592*1936@15fps
      	{0x0100, 0x00},// ; software standby
      	{0x3035, 0x21},// ; PLL
      	{0x3036, 0x66},// ; PLL
      	{0x303c, 0x11},// ; PLL
      	{0x3821, 0x06},// ; ISP mirror on, Sensor mirror on
      	{0x3820, 0x00},// ; ISP flip off, Sensor flip off
      	{0x3612, 0x5b},// ; analog control
      	{0x3618, 0x04},// ; analog control
      	{0x380c, 0x0a},// ; HTS = 2752
      	{0x380d, 0xc0},// ; HTS
      	{0x380e, 0x07},// ; VTS = 1974
      	{0x380f, 0xb6},// ; VTS
      	{0x3814, 0x11},// ; X INC
      	{0x3815, 0x11},// ; X INC
      	{0x3708, 0x64},// ; analog control
      	{0x3709, 0x12},// ; analog control
      	{0x3808, 0x0a},// ; X OUTPUT SIZE = 2592
      	{0x3809, 0x20},// ; X OUTPUT SIZE
      	{0x380a, 0x07},// ; Y OUTPUT SIZE = 1944
      	{0x380b, 0x98},// ; Y OUTPUT SIZE
      	{0x3800, 0x00},// ; X Start
      	{0x3801, 0x0c},// ; X Start
      	{0x3802, 0x00},// ; Y Start
      	{0x3803, 0x02},// ; Y Start
      	{0x3804, 0x0a},// ; X End
      	{0x3805, 0x33},// ; X End
      	{0x3806, 0x07},// ; Y End
      	{0x3807, 0xa1},// ; Y End
      	///////////; Banding filter
      	{0x3a08, 0x01},// ; B50
      	{0x3a09, 0x28},// ; B50
      	{0x3a0a, 0x00},// ; B60
      	{0x3a0b, 0xf6},// ; B60
      	{0x3a0d, 0x07},// ; B60 max
      	{0x3a0e, 0x06},// ; B50 max
      	{0x4004, 0x04},// ; black line number
      	{0x4837, 0x19},// ; MIPI pclk period
      	{0x0100, 0x01},// ; wake up from software standby
      };
      
      static struct regval_list sensor_720p_regs[] = { //720: 1280*720@30fps
      	{0x0100, 0x00},// ; software standby
      	{0x3035, 0x21},// ; PLL
      	{0x3036, 0x46},// ; PLL
      	{0x303c, 0x11},// ; PLL
      	{0x3821, 0x07},// ; ISP mirror on, Sensor mirror on, bin on
      	{0x3820, 0x41},// ; ISP flip off, Sensor flip off, bin on
      	{0x3612, 0x59},// ; analog control
      	{0x3618, 0x00},// ; analog control
      	{0x380c, 0x07},// ; HTS = 1896
      	{0x380d, 0x68},// ; HTS
      	{0x380e, 0x03},// ; VTS = 984
      	{0x380f, 0xd8},// ; VTS
      	{0x3814, 0x31},// ; X INC
      	{0x3815, 0x31},// ; Y INC
      	{0x3708, 0x64},// ; analog control
      	{0x3709, 0x52},// ; analog control
      	{0x3808, 0x05},// ; X OUTPUT SIZE = 1280
      	{0x3809, 0x00},// ; X OUTPUT SIZE
      	{0x380a, 0x03},// ; Y OUTPUT SIZE = 960
      	{0x380b, 0xc0},// ; Y OUTPUT SIZE
      	{0x3800, 0x00},// ; X Start
      	{0x3801, 0x18},// ; X Start
      	{0x3802, 0x00},// ; Y Start
      	{0x3803, 0x0e},// ; Y Start
      	{0x3804, 0x0a},// ; X End
      	{0x3805, 0x27},// ; X End
      	{0x3806, 0x07},// ; Y End
      	{0x3807, 0x95},// ; Y End
      	// banding filter
      	{0x3a08, 0x01},// ; B50
      	{0x3a09, 0x27},// ; B50
      	{0x3a0a, 0x00},// ; B60
      	{0x3a0b, 0xf6},// ; B60
      	{0x3a0d, 0x04},// ; B50 max
      	{0x3a0e, 0x03},// ; B60 max
      	{0x4004, 0x02},// ; black line number
      	{0x4837, 0x24},// ; MIPI pclk period
      	{0x0100, 0x01},// ; wake up from software standby
      };
      
      static struct regval_list sensor_fmt_raw[] = {
      
      };
      
      /*
       * Code for dealing with controls.
       * fill with different sensor module
       * different sensor module has different settings here
       * if not support the follow function ,retrun -EINVAL
       */
      
      static int sensor_g_exp(struct v4l2_subdev *sd, __s32 *value)
      {
      	struct sensor_info *info = to_state(sd);
      
      	*value = info->exp;
      	sensor_print("sensor_get_exposure = %d\n", info->exp);
      	return 0;
      }
      
      static int sensor_s_exp(struct v4l2_subdev *sd, unsigned int exp_val)
      {
      	unsigned char explow, expmid, exphigh;
      	struct sensor_info *info = to_state(sd);
      
      	if(exp_val>0xfffff)
      		exp_val=0xfffff;
        
      	sensor_write(sd, 0x3208, 0x00);//enter group write
      	sensor_write(sd, 0x3503, 0x13);
          exphigh = (unsigned char) ( (0x0f0000&exp_val)>>16);
          expmid  = (unsigned char) ( (0x00ff00&exp_val)>>8);
          explow  = (unsigned char) ( (0x0000ff&exp_val)   );
      	
      	//sensor_write(sd, 0x3208, 0x00);//enter group write
      	sensor_write(sd, 0x3502, explow);
      	sensor_write(sd, 0x3501, expmid);
      	sensor_write(sd, 0x3500, exphigh);	
      	sensor_write(sd, 0x3208, 0x10);//end group write
      	sensor_write(sd, 0x3208, 0xa0);//init group write
      	sensor_print("ov5647_mipi sensor_set_exp = %d, Done!\n", exp_val);
      	
      	info->exp = exp_val;
      	return 0;
      }
      
      static int sensor_g_gain(struct v4l2_subdev *sd, __s32 *value)
      {
      	struct sensor_info *info = to_state(sd);
      	*value = info->gain;
      	sensor_print("sensor_get_gain = %d\n", info->gain);
      	return 0;
      }
      
      static int sensor_s_gain(struct v4l2_subdev *sd, unsigned int gain_val)
      {
      	struct sensor_info *info = to_state(sd);
      	unsigned char gainlow=0;
      	unsigned char gainhigh=0;
      	
      	if(gain_val<1*16)
      		gain_val=16;
      	if(gain_val>64*16-1)
      		gain_val=64*16-1;
      	
      	gainlow=(unsigned char)(gain_val&0xff);
      	gainhigh=(unsigned char)((gain_val>>8)&0x3);
      	
      	sensor_write(sd, 0x3208, 0x00);//enter group write
      	
      	sensor_write(sd, 0x3503, 0x13);
      	sensor_write(sd, 0x350b, gainlow);
      	sensor_write(sd, 0x350a, gainhigh);
      	sensor_write(sd, 0x3208, 0x10);//end group write
      	sensor_write(sd, 0x3208, 0xa0);//init group write
      	
      	//printk("ov5647_mipi sensor_set_gain = %d, Done!\n", gain_val);
      	info->gain = gain_val;
      	
      	return 0;
      }
      
      static int ov5648_sensor_vts;
      static int sensor_s_exp_gain(struct v4l2_subdev *sd,
      				struct sensor_exp_gain *exp_gain)
      {
      	int exp_val, gain_val,frame_length,shutter;
      	unsigned char explow=0,expmid=0,exphigh=0;
      	unsigned char gainlow=0,gainhigh=0;  
      	struct sensor_info *info = to_state(sd);
      
      	exp_val = exp_gain->exp_val;
      	gain_val = exp_gain->gain_val;
      
      	if(gain_val<1*16)
      		gain_val=16;
      	if(gain_val>64*16-1)
      		gain_val=64*16-1;
      	
      	if(exp_val>0xfffff)
      		exp_val=0xfffff;
      	
      	gainlow=(unsigned char)(gain_val&0xff);
      	gainhigh=(unsigned char)((gain_val>>8)&0x3);
      	
      	exphigh	= (unsigned char) ( (0x0f0000&exp_val)>>16);
      	expmid	= (unsigned char) ( (0x00ff00&exp_val)>>8);
      	explow	= (unsigned char) ( (0x0000ff&exp_val)	 );
      	shutter = exp_val/16;
      	sensor_print("ov5648_sensor_vts = %d\n",ov5648_sensor_vts);
      	
      	if(shutter  > ov5648_sensor_vts- 4)
      			frame_length = shutter + 4;
      	else
      			frame_length = ov5648_sensor_vts;
      	sensor_write(sd, 0x3503, 0x07);
      	sensor_write(sd, 0x380f, (frame_length & 0xff));
      	sensor_write(sd, 0x380e, (frame_length >> 8));
      
      	sensor_print("exp_val = %d,gain_val = %d\n",exp_val,gain_val);
      	sensor_write(sd, 0x3208, 0x00);//enter group write
      	
      	sensor_write(sd, 0x350b, gainlow);
      	sensor_write(sd, 0x350a, gainhigh);
      	
      	sensor_write(sd, 0x3502, explow);
      	sensor_write(sd, 0x3501, expmid);
      	sensor_write(sd, 0x3500, exphigh);	
      	sensor_write(sd, 0x3208, 0x10);//end group write
      	sensor_write(sd, 0x3208, 0xa0);//init group write
      
      	info->exp = exp_val;
      	info->gain = gain_val;
      	return 0;
      }
      
      static void sensor_s_sw_stby(struct v4l2_subdev *sd, int on_off)
      {
      	int ret = 0;
      	return ret;
      }
      
      /*
       * Stuff that knows about the sensor.
       */
      static int sensor_power(struct v4l2_subdev *sd, int on)
      {
      	int ret = 0;
      	sensor_print("ov5648 sensor_power\n");
      	switch (on) {
      	case STBY_ON:
      		sensor_print("STBY_ON!\n");
      		cci_lock(sd);
      		sensor_s_sw_stby(sd, STBY_ON);
      		usleep_range(1000, 1200);
      		cci_unlock(sd);
      		break;
      	case STBY_OFF:
      		sensor_print("STBY_OFF!\n");
      		cci_lock(sd);
      		usleep_range(1000, 1200);
      		sensor_s_sw_stby(sd, STBY_OFF);
      		cci_unlock(sd);
      		break;
      	case PWR_ON:
      		sensor_print("PWR_ON!100\n");
      		cci_lock(sd);
      		vin_gpio_set_status(sd, PWDN, 1);
      		vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
      		vin_gpio_set_status(sd, POWER_EN, 1);
      		vin_gpio_write(sd, PWDN, CSI_GPIO_LOW);
      		vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
      		vin_gpio_write(sd, POWER_EN, CSI_GPIO_HIGH);
      		usleep_range(7000, 8000);
      		vin_set_pmu_channel(sd, IOVDD, ON);
      		usleep_range(7000, 8000);
      		vin_set_pmu_channel(sd, AVDD, ON);
      		vin_set_pmu_channel(sd, AFVDD, ON);
      		usleep_range(7000, 8000);
      		vin_set_pmu_channel(sd, DVDD, ON);
      		usleep_range(7000, 8000);
      		vin_set_mclk_freq(sd, MCLK);
      		vin_set_mclk(sd, ON);
      		usleep_range(10000, 12000);
      		vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
      		vin_gpio_write(sd, PWDN, CSI_GPIO_HIGH);
      		vin_set_pmu_channel(sd, CAMERAVDD, ON);/*AFVCC ON*/
      		usleep_range(10000, 12000);
      		cci_unlock(sd);
      		break;
      	case PWR_OFF:
      		sensor_print("PWR_OFF!\n");
      		cci_lock(sd);
      		vin_gpio_write(sd, PWDN, CSI_GPIO_HIGH);
      		vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
      		vin_set_mclk(sd, OFF);
      		usleep_range(7000, 8000);
      		vin_set_pmu_channel(sd, DVDD, OFF);
      		vin_gpio_write(sd, PWDN, CSI_GPIO_LOW);
      		vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
      		vin_gpio_write(sd, POWER_EN, CSI_GPIO_LOW);
      		vin_set_pmu_channel(sd, AVDD, OFF);
      		vin_set_pmu_channel(sd, IOVDD, OFF);
      		vin_set_pmu_channel(sd, AFVDD, OFF);
      		vin_set_pmu_channel(sd, CAMERAVDD, OFF);/*AFVCC ON*/
      		cci_unlock(sd);
      		break;
      	default:
      		return -EINVAL;
      	}
      
      	return 0;
      }
      
      static int sensor_reset(struct v4l2_subdev *sd, u32 val)
      {
      	switch (val) {
      	case 0:
      		vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
      		usleep_range(10000,12000);
      		break;
      	case 1:
      		vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
      		usleep_range(10000,12000);
      		break;
      	default:
      		return -EINVAL;
      	}
      	return 0;
      }
      
      static int sensor_detect(struct v4l2_subdev *sd)
      {
      	data_type rdval;
      	unsigned int SENSOR_ID = 0;
      	sensor_read(sd, 0x300A, &rdval);
      	SENSOR_ID |= rdval;
      	SENSOR_ID |= (rdval << 8);
      	sensor_read(sd, 0x300B, &rdval);
      	SENSOR_ID |= (rdval);
      	sensor_print("V4L2_IDENT_SENSOR = 0x%x\n", SENSOR_ID);
      	if (SENSOR_ID != V4L2_IDENT_SENSOR) {
      		sensor_print("ov5648 %s error, chip found is not an target chip", __func__);
      		//return -ENODEV;
      	}
      	return 0;
      }
      
      static int sensor_init(struct v4l2_subdev *sd, u32 val)
      {
      	int ret;
      	struct sensor_info *info = to_state(sd);
      
      	sensor_print("sensor_init\n");
      
      	/*Make sure it is a target sensor */
      	ret = sensor_detect(sd);
      	if (ret) {
      		sensor_err("chip found is not an target chip.\n");
      		return ret;
      	}
      
      	info->focus_status = 0;
      	info->low_speed = 0;
      	info->width = QSXGA_WIDTH;
      	info->height = QSXGA_HEIGHT;
      	info->hflip = 0;
      	info->vflip = 0;
      	info->gain = 0;
      
      	info->tpf.numerator = 1;
      	info->tpf.denominator = 30;	/* 30fps */
      
      	info->preview_first_flag = 1;
      
      	return 0;
      }
      
      static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
      {
      	int ret = 0;
      	struct sensor_info *info = to_state(sd);
      
      	switch (cmd) {
      	case GET_CURRENT_WIN_CFG:
      		if (info->current_wins != NULL) {
      			memcpy(arg, info->current_wins,
      				sizeof(struct sensor_win_size));
      			ret = 0;
      		} else {
      			sensor_err("empty wins!\n");
      			ret = -1;
      		}
      		break;
      	case SET_FPS:
      		ret = 0;
      		break;
      	case VIDIOC_VIN_SENSOR_EXP_GAIN:
      		ret = sensor_s_exp_gain(sd, (struct sensor_exp_gain *)arg);
      		break;
      	case VIDIOC_VIN_SENSOR_CFG_REQ:
      		sensor_cfg_req(sd, (struct sensor_config *)arg);
      		break;
      	case VIDIOC_VIN_ACT_INIT:
      		ret = actuator_init(sd, (struct actuator_para *)arg);
      		break;
      	case VIDIOC_VIN_ACT_SET_CODE:
      		ret = actuator_set_code(sd, (struct actuator_ctrl *)arg);
      		break;
      	default:
      		return -EINVAL;
      	}
      	return ret;
      }
      
      /*
       * Store information about the video data format.
       */
      static struct sensor_format_struct sensor_formats[] = {
      	{
      		.desc = "Raw RGB Bayer",
      		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
      		.regs = sensor_fmt_raw,
      		.regs_size = ARRAY_SIZE(sensor_fmt_raw),
      		.bpp = 1
      	},
      };
      #define N_FMTS ARRAY_SIZE(sensor_formats)
      
      /*
       * Then there is the issue of window sizes.  Try to capture the info here.
       */
      
      static struct sensor_win_size sensor_win_sizes[] = {
      	{
            .width      = QSXGA_WIDTH,
            .height     = QSXGA_HEIGHT,
            .hoffset    = 0,
            .voffset    = 4,
            .hts        = 2752,
            .vts        = 1974,
            .pclk       = 81486720,
            .mipi_bps	  = 408*1000*1000,
            .fps_fixed  = 2,
            .bin_factor = 1,
            .intg_min   = 1,
            .intg_max   = (1974)<<4,
            .gain_min   = 1<<4,
            .gain_max   = 12<<4,
            .regs       = sensor_qsxga_regs,
            .regs_size  = ARRAY_SIZE(sensor_qsxga_regs),
            .set_size   = NULL,
          },
      	{
            .width      = HD720_WIDTH,
            .height     = HD720_HEIGHT,
            .hoffset    = 0,
            .voffset    = 120,
            .hts        = 1896,
            .vts        = 984,
            .pclk       = 56*1000*1000,      
            .mipi_bps	  = 280*1000*1000,
            .fps_fixed  = 1,
            .bin_factor = 1,
            .intg_min   = 1,
            .intg_max   = 984<<4,
            .gain_min   = 1<<4,
            .gain_max   = 12<<4,
            .regs		  = sensor_720p_regs,//
            .regs_size  = ARRAY_SIZE(sensor_720p_regs),//
            .set_size	  = NULL,
          },
      };
      
      #define N_WIN_SIZES (ARRAY_SIZE(sensor_win_sizes))
      
      static int sensor_reg_init(struct sensor_info *info)
      {
      	int ret;
      	struct v4l2_subdev *sd = &info->sd;
      	struct sensor_format_struct *sensor_fmt = info->fmt;
      	struct sensor_win_size *wsize = info->current_wins;
      
      	ret = sensor_write_array(sd, sensor_default_regs,
      				ARRAY_SIZE(sensor_default_regs));
      	if (ret < 0) {
      		sensor_err("write sensor_default_regs error\n");
      		return ret;
      	}
      
      	sensor_print("sensor_reg_init\n");
      
      	sensor_write_array(sd, sensor_fmt->regs, sensor_fmt->regs_size);
      
      	if (wsize->regs)
      		sensor_write_array(sd, wsize->regs, wsize->regs_size);
      
      	if (wsize->set_size)
      		wsize->set_size(sd);
      
      	info->width = wsize->width;
      	info->height = wsize->height;
      	info->exp = 0;
      	info->gain = 0;
      	ov5648_sensor_vts = wsize->vts;
      	sensor_print("s_fmt set width = %d, height = %d\n", wsize->width,
      				wsize->height);
      
      	return 0;
      }
      
      static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
      {
      	struct sensor_info *info = to_state(sd);
      
      	sensor_print("%s on = %d, %d*%d fps: %d code: %x\n", __func__, enable,
      			info->current_wins->width, info->current_wins->height,
      			info->current_wins->fps_fixed, info->fmt->mbus_code);
      
      	if (!enable)
      		return 0;
      
      	return sensor_reg_init(info);
      }
      
      static int sensor_g_mbus_config(struct v4l2_subdev *sd,
      				struct v4l2_mbus_config *cfg)
      {
      	cfg->type = V4L2_MBUS_CSI2;
      	cfg->flags = 0 | V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0;
      
      	return 0;
      }
      
      static int sensor_g_ctrl(struct v4l2_ctrl *ctrl)
      {
      	struct sensor_info *info = container_of(ctrl->handler,
      			struct sensor_info, handler);
      	struct v4l2_subdev *sd = &info->sd;
      
      	switch (ctrl->id) {
      	case V4L2_CID_GAIN:
      		return sensor_g_gain(sd, &ctrl->val);
      	case V4L2_CID_EXPOSURE:
      		return sensor_g_exp(sd, &ctrl->val);
      	}
      	return -EINVAL;
      }
      
      static int sensor_s_ctrl(struct v4l2_ctrl *ctrl)
      {
      	struct sensor_info *info = container_of(ctrl->handler,
      			struct sensor_info, handler);
      	struct v4l2_subdev *sd = &info->sd;
      
      	switch (ctrl->id) {
      	case V4L2_CID_GAIN:
      		return sensor_s_gain(sd, ctrl->val);
      	case V4L2_CID_EXPOSURE:
      		return sensor_s_exp(sd, ctrl->val);
      	}
      	return -EINVAL;
      }
      
      /* ----------------------------------------------------------------------- */
      
      static const struct v4l2_ctrl_ops sensor_ctrl_ops = {
      	.g_volatile_ctrl = sensor_g_ctrl,
      	.s_ctrl = sensor_s_ctrl,
      };
      
      static const struct v4l2_subdev_core_ops sensor_core_ops = {
      	.reset = sensor_reset,
      	.init = sensor_init,
      	.s_power = sensor_power,
      	.ioctl = sensor_ioctl,
      #ifdef CONFIG_COMPAT
      	.compat_ioctl32 = sensor_compat_ioctl32,
      #endif
      };
      
      static const struct v4l2_subdev_video_ops sensor_video_ops = {
      	.s_parm = sensor_s_parm,
      	.g_parm = sensor_g_parm,
      	.s_stream = sensor_s_stream,
      	.g_mbus_config = sensor_g_mbus_config,
      };
      
      static const struct v4l2_subdev_pad_ops sensor_pad_ops = {
      	.enum_mbus_code = sensor_enum_mbus_code,
      	.enum_frame_size = sensor_enum_frame_size,
      	.get_fmt = sensor_get_fmt,
      	.set_fmt = sensor_set_fmt,
      };
      
      static const struct v4l2_subdev_ops sensor_ops = {
      	.core = &sensor_core_ops,
      	.video = &sensor_video_ops,
      	.pad = &sensor_pad_ops,
      };
      
      /* ----------------------------------------------------------------------- */
      static struct cci_driver cci_drv = {
      		.name = SENSOR_NAME,
      		.addr_width = CCI_BITS_16,
      		.data_width = CCI_BITS_8,
      };
      
      static const struct v4l2_ctrl_config sensor_custom_ctrls[] = {
      	{
      		.ops = &sensor_ctrl_ops,
      		.id = V4L2_CID_FRAME_RATE,
      		.name = "frame rate",
      		.type = V4L2_CTRL_TYPE_INTEGER,
      		.min = 15,
      		.max = 120,
      		.step = 1,
      		.def = 120,
      	},
      };
      
      static int sensor_init_controls(struct v4l2_subdev *sd,
      			const struct v4l2_ctrl_ops *ops)
      {
      	struct sensor_info *info = to_state(sd);
      	struct v4l2_ctrl_handler *handler = &info->handler;
      	struct v4l2_ctrl *ctrl;
      	int i;
      	int ret = 0;
      
      	v4l2_ctrl_handler_init(handler, 2 + ARRAY_SIZE(sensor_custom_ctrls));
      
      	v4l2_ctrl_new_std(handler, ops, V4L2_CID_GAIN, 1 * 1600,
      				256 * 1600, 1, 1 * 1600);
      	ctrl = v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 0,
      				65536 * 16, 1, 0);
      	if (ctrl != NULL)
      		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
      	for (i = 0; i < ARRAY_SIZE(sensor_custom_ctrls); i++)
      		v4l2_ctrl_new_custom(handler, &sensor_custom_ctrls[i], NULL);
      
      	if (handler->error) {
      		ret = handler->error;
      		v4l2_ctrl_handler_free(handler);
      	}
      
      	sd->ctrl_handler = handler;
      
      	return ret;
      }
      
      static int sensor_probe(struct i2c_client *client,
      			const struct i2c_device_id *id)
      {
      	struct v4l2_subdev *sd;
      	struct sensor_info *info;
      
      	info = kzalloc(sizeof(struct sensor_info), GFP_KERNEL);
      	if (info == NULL)
      		return -ENOMEM;
      	sd = &info->sd;
      
      	cci_dev_probe_helper(sd, client, &sensor_ops, &cci_drv);
      	sensor_init_controls(sd, &sensor_ctrl_ops);
      
      	mutex_init(&info->lock);
      #ifdef CONFIG_SAME_I2C
      	info->sensor_i2c_addr = I2C_ADDR >> 1;
      #endif
      	info->fmt = &sensor_formats[0];
      	info->fmt_pt = &sensor_formats[0];
      	info->win_pt = &sensor_win_sizes[0];
      	info->fmt_num = N_FMTS;
      	info->win_size_num = N_WIN_SIZES;
      	info->sensor_field = V4L2_FIELD_NONE;
      	info->stream_seq = MIPI_BEFORE_SENSOR;
      	info->af_first_flag = 1;
      	info->exp = 0;
      	info->gain = 0;
      
      	return 0;
      }
      
      static int sensor_remove(struct i2c_client *client)
      {
      	struct v4l2_subdev *sd;
      
      	sd = cci_dev_remove_helper(client, &cci_drv);
      
      	kfree(to_state(sd));
      	return 0;
      }
      
      static const struct i2c_device_id sensor_id[] = {
      	{SENSOR_NAME, 0},
      	{}
      };
      
      MODULE_DEVICE_TABLE(i2c, sensor_id);
      
      static struct i2c_driver sensor_driver = {
      		.driver = {
      				.owner = THIS_MODULE,
      				.name = SENSOR_NAME,
      				},
      		.probe = sensor_probe,
      		.remove = sensor_remove,
      		.id_table = sensor_id,
      };
      static __init int init_sensor(void)
      {
      	return cci_dev_init_helper(&sensor_driver);
      }
      
      static __exit void exit_sensor(void)
      {
      	cci_dev_exit_helper(&sensor_driver);
      }
      
      module_init(init_sensor);
      module_exit(exit_sensor);
      

      另外建议使用支持列表中的摄像头,例如gc2053,gc2063,这些摄像头已经适配量产完成并且调整ISP后画质更佳,也支持aiisp实现低照度全彩画质,树莓派的摄像头不推荐使用,因为他是外挂mclk的会引起芯片处于错误的模式,另外原厂也没有相应的支持(2017年前的芯片才有这个支持)

      IMX219 同样可以使用,但是请注意4lane的摄像头不可适配2lane的数据

      posted in V Series
      A
      awwwwa
    • Reply: 请教如何排查 linux kernel 启动卡主的问题

      @xsyr1024 在 请教如何排查 linux kernel 启动卡主的问题 中说:

      [ 0.969253] 000: printk: console [ttyS0] enabled
      [ 0.973945] 000: printk: bootconsole [earlycon0] disabled

      看着是earlycon0作为串口输出驱动正常,但是切换到ttyS0作为串口输出的时候ttyS0没有输出,先检查uart部分

      另外这个是LinuxRT内核吗

      posted in Linux
      A
      awwwwa
    • Reply: 全志v536 4k编解码

      @zhangerhu 硬件只是同编同解可以试一下,瓶颈估计在带宽上

      posted in V Series
      A
      awwwwa
    • Reply: 全志提供的交叉编译环境头文件的问题

      @arnis

      obj-m  := hello.o
      KERNEL := ../lichee/linux-5.4/
      PWD    := $(shell pwd)
      
      modules :
              $(MAKE) -C $(KERNEL) M=$(PWD) modules
      
      .PHONEY:clean
      clean :
              rm -f *.o *.ko
      

      这是一个基本的内核模块Makefile。下面是各个变量和命令的含义:

      obj-m  := hello.o
      

      定义要编译的内核模块的目标文件名为hello.o。这里使用了obj-m变量,它是一个特殊的变量,用于编译内核模块。

      KERNEL := ../lichee/linux-5.4/
      

      定义内核源代码目录的位置,这里是../lichee/linux-5.4/。根据实际情况修改该路径。

      PWD    := $(shell pwd)
      

      定义当前目录的路径为PWD。这里使用了shell命令来获取当前目录的路径。

      modules :
              $(MAKE) -C $(KERNEL) M=$(PWD) modules
      

      定义一个名为modules的伪目标,它的依赖关系为空。执行该目标时,会进入内核源代码目录$(KERNEL),并使用M=$(PWD)选项告诉内核Makefile,模块源代码在当前目录中。最后执行modules目标,编译内核模块。

      .PHONEY:clean
      clean :
              rm -f *.o *.ko
      

      定义一个伪目标clean,它的依赖关系为空。执行该目标时,会删除当前目录下的所有.o和.ko文件。

      如果需要编译多个内核模块,可以将obj-m变量中的目标文件名替换为多个目标文件名,如obj-m := hello.o world.o another.o。此外,还可以在Makefile中定义其他命令,比如安装、卸载等命令,以更方便地管理内核模块。

      编译指令如下:

      make ARCH=arm CROSS_COMPILE=$(pwd)/../prebuilt/gcc/linux-x86/arm/toolchain-sunxi-glibc/toolchain/bin/arm-openwrt-linux-gnueabi-
      

      这是一个编译ARM架构的程序的Makefile命令。下面是各个参数的含义:

      ARCH=arm
      

      指定目标架构为ARM。

      CROSS_COMPILE=$(pwd)/../prebuilt/gcc/linux-x86/arm/toolchain-sunxi-glibc/toolchain/bin/arm-openwrt-linux-gnueabi-
      

      指定交叉编译器的路径及前缀。这里使用了$(pwd)变量获取当前工作目录的路径,并拼接上交叉编译器的路径及前缀。根据实际情况修改该路径。

      使用交叉编译器可以在x86主机上编译ARM平台的程序。arm-openwrt-linux-gnueabi-是交叉编译器的前缀,表示编译出来的可执行文件适用于OpenWrt系统。

      在执行该命令之前,需要确保已经安装了相应的交叉编译工具链,并将其加入环境变量中。如果没有安装,请参考相关文档进行安装。

      posted in Linux
      A
      awwwwa
    • Reply: V853 和 V853S NPU算力差了0.2,这个0.2在具体应用上会有明显的性能差距吗?主要用来做目标检测,静态场景。

      根据具体的模型和需求的规格来看,实际感觉差不多

      posted in V Series
      A
      awwwwa
    • Reply: T113-S3芯片使用Tina5.0,开机小企鹅boot能显示但跳转到kernel后无显示

      @pandali 检查LCD的rst引脚是否配置错误导致屏幕被rst

      posted in Linux
      A
      awwwwa
    • Reply: V853s如何实现UI图层和视频图层同时用

      参考libuapi,tplayerdemo,将UI和视频放置于不同图层即可

      posted in V Series
      A
      awwwwa
    • Reply: tina SDK ERROR: Dependence broken. Firmware maybe incorrect & cannot booting up...

      @hgs1975 This is not a error, you can normal boot up while showing this error. What's your hardware and how to configure it

      posted in Linux
      A
      awwwwa
    • Reply: V853s如何实现UI图层和视频图层同时用

      @hzhy1234 tplayerdemo就调用了

      posted in V Series
      A
      awwwwa
    • Reply: 只用的全志的板子,怎么才能往rootfs中添加文件

      target/allwinner/t113-nezha/base-files
      target/allwinner/t113-nezha/busybox-init-base-files

      根据选择的overlay方式而定

      posted in Linux
      A
      awwwwa
    • Reply: SPI 驱动 ST7789VW 2.4 寸 LCD发生Label or path lcd_fb not found

      文档提供的驱动为新版本,需要更新,补丁如下,进入 bsp 文件夹打入:
      0003-K1-sunxi-P2-lcd_fb-add-support-for-qspi-lcd.patch
      0002-K1-sunxi-P2-lcd_fb-optimize-code-and-directory-struc.patch
      0001-K1-sunxi-P2-disp-lcd_fb-fix-build-fail-when-enable-D.patch

      posted in V Series
      A
      awwwwa
    • Reply: 请问docker pull registry.cn-hangzhou.aliyuncs.com/cld1994/tina-sdk:5.0-nori拉取docker镜像没有问题,配置后,运行code ~/workspace/nori进入vscode,Reopen in Container却报错是为什么呢

      docker 没有正确安装配置

      posted in Linux
      A
      awwwwa
    • Reply: V821 STANBY相关休眠唤醒功能

      已刷新文档内容,感谢反馈

      posted in V Series
      A
      awwwwa
    • Reply: t113-s3 lvgl仪表盘指针转动如何处理

      旋转需要大量的计算,会导致出现帧率问题,可以尝试关闭抗锯齿,使用NEON加速计算

      posted in Linux
      A
      awwwwa
    • Reply: v821切换到spi nand flash(XT26G01CWSIG) 系统无法启动

      使用quick_config 配置的吗

      posted in V Series
      A
      awwwwa
    • Reply: A133 Linux GPU 测试例程

      @liangzhicheng 可以用glmark2测试

      posted in Linux
      A
      awwwwa
    • Reply: v821切换到spi nand flash(XT26G01CWSIG) 系统无法启动

      看日志是内核整套ubi都没开起来,可以再次运行quick_config,重新编译SDK测试下

      posted in V Series
      A
      awwwwa
    • Reply: V821如何实现VIPP的分时复用?

      使用多个vipp通道即可,不需要分时复用

      posted in V Series
      A
      awwwwa
    • Reply: V853使用MIPI CSI接口是否只支持RAW格式像素?

      @xjy_5 RGB888_1X24 我感觉是直出RGB信号的吧

      这个DTSI是在T507上配置的,可以参考一下

      		vind0:vind@0 {
      			compatible = "allwinner,sunxi-vin-media", "simple-bus";
      			#address-cells = <2>;
      			#size-cells = <2>;
      			ranges;
      			device_id = <0>;
      			vind0_clk = <384000000>;
      			reg = <0x0 0x06600800 0x0 0x200>,
      				<0x0 0x06600000 0x0 0x800>;
      			clocks = <&clk_csi_top>, <&clk_pll_csi>,
      				 <&clk_csi_master0>, <&clk_hosc>, <&clk_pll_csi>,
      				 <&clk_csi_master1>, <&clk_hosc>, <&clk_pll_csi>;
      			pinctrl-names = "mclk0-default","mclk0-sleep","mclk1-default","mclk1-sleep";
      			pinctrl-0 = <&csi_mclk0_pins_a>;
      			pinctrl-1 = <&csi_mclk0_pins_b>;
      			pinctrl-2 = <&csi_mclk1_pins_a>;
      			pinctrl-3 = <&csi_mclk1_pins_b>;
      			status = "okay";
      
      
      			csi_cci0:cci@0 {
      				compatible = "allwinner,sunxi-csi_cci";
      				reg = <0x0 0x06614000 0x0 0x400>;
      				interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
      				pinctrl-names = "default","sleep";
      				pinctrl-0 = <&csi_cci0_pins_a>;
      				pinctrl-1 = <&csi_cci0_pins_b>;
      				device_id = <0>;
      				status = "okay";
      			};
      			csi_cci1:cci@1 {
      				compatible = "allwinner,sunxi-csi_cci";
      				reg = <0x0 0x06614400 0x0 0x400>;
      				interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
      				pinctrl-names = "default","sleep";
      				pinctrl-0 = <&csi_cci1_pins_a>;
      				pinctrl-1 = <&csi_cci1_pins_b>;
      				device_id = <1>;
      				status = "okay";
      			};
      			csi0:csi@0 {
      				device_type = "csi0";
      				compatible = "allwinner,sunxi-csi";
      				reg = <0x0 0x06601000 0x0 0x1000>;
      				interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
      				device_id = <0>;
      				iommus = <&mmu_aw 4 1>;
      				status = "okay";
      			};
      			csi1:csi@1 {
      				device_type = "csi1";
      				compatible = "allwinner,sunxi-csi";
      				reg = <0x0 0x06602000 0x0 0x1000>;
      				interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
      				pinctrl-names = "default","sleep";
      				pinctrl-0 = <&csi1_pins_a>;
      				pinctrl-1 = <&csi1_pins_b>;
      				device_id = <1>;
      				iommus = <&mmu_aw 4 1>;
      				status = "okay";
      			};
      			mipi0:mipi@0 {
      				compatible = "allwinner,sunxi-mipi";
      				reg = <0x0 0x0660C000 0x0 0x1000>;
      				interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
      				device_id = <0>;
      				status = "okay";
      			};
      			isp0:isp@0 {
      				compatible = "allwinner,sunxi-isp";
      				device_id = <0>;
      				status = "okay";
      			};
      			isp1:isp@1 {
      				compatible = "allwinner,sunxi-isp";
      				device_id = <1>;
      				status = "okay";
      			};
      			scaler0:scaler@0 {
      				compatible = "allwinner,sunxi-scaler";
      				device_id = <0>;
      				iommus = <&mmu_aw 4 1>;
      				status = "okay";
      			};
      			scaler1:scaler@1 {
      				compatible = "allwinner,sunxi-scaler";
      				device_id = <1>;
      				iommus = <&mmu_aw 4 1>;
      				status = "okay";
      			};
      			scaler2:scaler@2 {
      				compatible = "allwinner,sunxi-scaler";
      				device_id = <2>;
      				iommus = <&mmu_aw 4 1>;
      				status = "okay";
      			};
      			scaler3:scaler@3 {
      				compatible = "allwinner,sunxi-scaler";
      				device_id = <3>;
      				iommus = <&mmu_aw 4 1>;
      				status = "okay";
      			};
      			scaler4:scaler@4 {
      				compatible = "allwinner,sunxi-scaler";
      				device_id = <4>;
      				iommus = <&mmu_aw 4 1>;
      				status = "okay";
      			};
      			scaler5:scaler@5 {
      				compatible = "allwinner,sunxi-scaler";
      				device_id = <5>;
      				iommus = <&mmu_aw 4 1>;
      				status = "okay";
      			};
      			actuator0:actuator@0 {
      				device_type = "actuator0";
      				compatible = "allwinner,sunxi-actuator";
      				actuator0_name = "ad5820_act";
      				actuator0_slave = <0x18>;
      				actuator0_af_pwdn = <>;
      				actuator0_afvdd = "afvcc-csi";
      				actuator0_afvdd_vol = <2800000>;
      				status = "disabled";
      			};
      			flash0:flash@0 {
      				device_type = "flash0";
      				compatible = "allwinner,sunxi-flash";
      				flash0_type = <2>;
      				flash0_en = <>;
      				flash0_mode = <>;
      				flash0_flvdd = "";
      				flash0_flvdd_vol = <>;
      				device_id = <0>;
      				status = "disabled";
      			};
      			sensor0:sensor@0 {
      				device_type = "sensor0";
      				compatible = "allwinner,sunxi-sensor";
      				sensor0_mname = "tc358743_mipi";
      				sensor0_twi_cci_id = <2>;
      				sensor0_twi_addr = <0x1f>;
      				sensor0_mclk_id = <0>;
      				sensor0_pos = "rear";
      				sensor0_isp_used = <0>;
      				sensor0_fmt = <0>;
      				sensor0_stby_mode = <0>;
      				sensor0_vflip = <0>;
      				sensor0_hflip = <0>;
      				sensor0_cameravdd-supply = <>;
      				sensor0_cameravdd_vol = <2800000>;
      				sensor0_iovdd-supply = <&reg_cldo4>;
      				sensor0_iovdd_vol = <1800000>;
      				sensor0_avdd-supply = <>;
      				sensor0_avdd_vol = <>;
      				sensor0_dvdd-supply = <>;
      				sensor0_dvdd_vol = <>;
      				sensor0_power_en = <>;
      				sensor0_reset = <&pio PI 8 1 0 1 0>;
      				sensor0_pwdn = <>;
      				sensor0_sm_vs = <>;
      				flash_handle = <&flash0>;
      				act_handle = <&actuator0>;
      				device_id = <0>;
      				status	= "okay";
      			};
      			sensor1:sensor@1 {
      				device_type = "sensor1";
      				compatible = "allwinner,sunxi-sensor";
      				sensor1_mname = "ov5647";
      				sensor1_twi_cci_id = <1>;
      				sensor1_twi_addr = <0x6c>;
      				sensor1_mclk_id = <1>;
      				sensor1_pos = "front";
      				sensor1_isp_used = <0>;
      				sensor1_fmt = <0>;
      				sensor1_stby_mode = <0>;
      				sensor1_vflip = <0>;
      				sensor1_hflip = <0>;
      				sensor1_cameravdd-supply = <>;
      				sensor1_cameravdd_vol = <2800000>;
      				sensor1_iovdd-supply = <>;
      				sensor1_iovdd_vol = <2800000>;
      				sensor1_avdd-supply = <>;
      				sensor1_avdd_vol = <2800000>;
      				sensor1_dvdd-supply = <>;
      				sensor1_dvdd_vol = <1500000>;
      				sensor1_power_en = <>;
      				sensor1_reset = <&pio PE 14 1 0 1 0>;
      				sensor1_pwdn = <&pio PE 15 1 0 1 0>;
      				sensor1_sm_vs = <>;
      				flash_handle = <>;
      				act_handle = <>;
      				device_id = <1>;
      				status	= "disable";
      			};
      			vinc0:vinc@0 {
      				device_type = "vinc0";
      				compatible = "allwinner,sunxi-vin-core";
      				reg = <0x0 0x06609000 0x0 0x200>;
      				interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
      				vinc0_csi_sel = <0>;
      				vinc0_mipi_sel = <0>;
      				vinc0_isp_sel = <0>;
      				vinc0_isp_tx_ch = <0>;
      				vinc0_rear_sensor_sel = <0>;
      				vinc0_front_sensor_sel = <0>;
      				vinc0_sensor_list = <0>;
      				device_id = <0>;
      				iommus = <&mmu_aw 4 1>;
      				status = "okay";
      			};
      			vinc1:vinc@1 {
      				device_type = "vinc1";
      				compatible = "allwinner,sunxi-vin-core";
      				reg = <0x0 0x06609200 0x0 0x200>;
      				interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
      				vinc1_csi_sel = <0>;
      				vinc1_mipi_sel = <0>;
      				vinc1_isp_sel = <0>;
      				vinc1_isp_tx_ch = <0>;
      				vinc1_rear_sensor_sel = <0>;
      				vinc1_front_sensor_sel = <0>;
      				vinc1_sensor_list = <0>;
      				device_id = <1>;
      				iommus = <&mmu_aw 4 1>;
      				status = "okay";
      			};
      			vinc2:vinc@2 {
      				device_type = "vinc2";
      				compatible = "allwinner,sunxi-vin-core";
      				reg = <0x0 0x06609400 0x0 0x200>;
      				interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
      				vinc2_csi_sel = <0>;
      				vinc2_mipi_sel = <0>;
      				vinc2_isp_sel = <0>;
      				vinc2_isp_tx_ch = <0>;
      				vinc2_rear_sensor_sel = <0>;
      				vinc2_front_sensor_sel = <0>;
      				vinc2_sensor_list = <0>;
      				device_id = <2>;
      				iommus = <&mmu_aw 4 1>;
      				status = "disabled";
      			};
      			vinc3:vinc@3 {
      				device_type = "vinc3";
      				compatible = "allwinner,sunxi-vin-core";
      				reg = <0x0 0x06609600 0x0 0x200>;
      				interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
      				vinc3_csi_sel = <0>;
      				vinc3_mipi_sel = <0>;
      				vinc3_isp_sel = <0>;
      				vinc3_isp_tx_ch = <0>;
      				vinc3_rear_sensor_sel = <0>;
      				vinc3_front_sensor_sel = <0>;
      				vinc3_sensor_list = <0>;
      				device_id = <3>;
      				iommus = <&mmu_aw 4 1>;
      				status = "disabled";
      			};
      			vinc4:vinc@4 {
      				device_type = "vinc4";
      				compatible = "allwinner,sunxi-vin-core";
      				reg = <0x0 0x06609800 0x0 0x200>;
      				interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
      				vinc4_csi_sel = <1>;
      				vinc4_mipi_sel = <0xff>;
      				vinc4_isp_sel = <1>;
      				vinc4_isp_tx_ch = <0>;
      				vinc4_rear_sensor_sel = <1>;
      				vinc4_front_sensor_sel = <1>;
      				vinc4_sensor_list = <0>;
      				device_id = <4>;
      				iommus = <&mmu_aw 5 1>;
      				status = "disabled";
      			};
      			vinc5:vinc@5 {
      				device_type = "vinc5";
      				compatible = "allwinner,sunxi-vin-core";
      				reg = <0x0 0x06609A00 0x0 0x200>;
      				interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
      				vinc5_csi_sel = <1>;
      				vinc5_mipi_sel = <0xff>;
      				vinc5_isp_sel = <1>;
      				vinc5_isp_tx_ch = <0>;
      				vinc5_rear_sensor_sel = <1>;
      				vinc5_front_sensor_sel = <1>;
      				vinc5_sensor_list = <0>;
      				device_id = <5>;
      				iommus = <&mmu_aw 5 1>;
      				status = "disabled";
      			};
      		};
      
      posted in V Series
      A
      awwwwa
    • Reply: V853使用MIPI CSI接口是否只支持RAW格式像素?

      @awwwwa

      sensor0:sensor@0 {                                      
            device_type = "sensor0";                        
            sensor0_mname = "gc2053_mipi";      /* 必须要和驱动的 SENSOR_NAME 一致 */   
            sensor0_twi_cci_id = <1>;           /* 所使用的twi id号,本例中使用的是twi1,故填写为1 */               
            sensor0_twi_addr = <0x6e>;          /* sensor 设备ID地址,必须与驱动中的I2C_ADDR一致 */                           
            sensor0_mclk_id = <0>;              /* 所使用的mclk id号,本例中使用的是MCLK0,故填写为0 */                        
            sensor0_pos = "rear";                           
            sensor0_isp_used = <1>;             /* 所使用的sensor为raw sensor,需要过ISP处理,故填写为1 */                      
            sensor0_fmt = <1>;                  /* sensor输出的图像格式,YUV:0,RAW:1 */            
            sensor0_stby_mode = <0>;                        
            sensor0_vflip = <0>;                /* VIPP 图像垂直翻转 */                
            sensor0_hflip = <0>;                /* VIPP 图像水平翻转 */                  
            sensor0_iovdd-supply = <&reg_aldo2>;/* sensor iovdd 连接的 ldo,根据硬件原理图的连接来决定(在硬件原理图中搜索aldo,然后找到CSI-iovdd对应的										   是哪一个aldo即可) */
            sensor0_iovdd_vol = <1800000>;	  /* iovdd的电压 */
            sensor0_avdd-supply = <&reg_bldo2>; /* sensor avdd连接的 ldo,根据硬件原理图的连接来决定 */
            sensor0_avdd_vol = <2800000>;		  /* 同上 */
            sensor0_dvdd-supply = <&reg_dldo2>;  /* 同上 */
            sensor0_dvdd_vol = <1200000>;        /* 同上 */                
            sensor0_power_en = <>;          										
            sensor0_reset = <&pio PA 11 1 0 1 0>; /* GPIO 信息配置:pio 端口 组内序号 功能分配 内部电阻状态 驱动能力 输出电平状态,本例中使用的是PA11*/   
            sensor0_pwdn = <&pio PA 9 1 0 1 0>;   /* GPIO 信息配置:pio 端口 组内序号 功能分配 内部电阻状态 驱动能力 输出电平状态,本例中使用的是PA9*/   
            flash_handle = <&flash0>;                       
            act_handle = <&actuator0>;                      
            status  = "okay";                               
      };       
      

      填写Sensor输出图像格式

      ​ sensor输出图像格式定义在sensor_format_struct结构体中,vin v4l2驱动框架通过获取sensor_format_struct结构体成员信息来获取当前sensor输出图像格式,sensor_formats结构体中需要填写的成员是.desc和 .mbus_code。

      ​ .desc是描述sensor输出的图像格式,本例中gc2053是RGB Raw sensor,故.desc成员填写为"Raw RGB Bayer" 。.mbus_code 为sensor图像数据输出顺序,sensor RAW图像是以Bayer格式传输的(每个像素只表示RGB其中一个分量),常见的Bayer格式为:RGGB、BGGR、GRBG、GBRG,这个可以询问一下sensor原厂或者翻阅sensor datasheet进行查找。.mbus_code 若填错, 会导致色彩偏紫红和出现网格状纹理。

      ​ 本例中gc2053图像输出格式为RGGB,且当前的配置是10bit mipi接口,故.mbus_code填写为
      MEDIA_BUS_FMT_SRGGB10_1X10,若当前调试的sensor配置是8bit输出,
      则.mbus_code填写为MEDIA_BUS_FMT_SRGGB8_1X8,按照这种规则进行填写。

      static struct sensor_format_struct sensor_formats[] = {
          {
              .desc      = "Raw RGB Bayer", 
              /* 填写 Sensor 初始化时默认的 Bayer 格式,目的是告知主控端ISP当前图像的 Bayer 格式,ISP需要以同样的格式来接收和处理图像数据 */
              .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
              .regs      = sensor_fmt_raw,		
              .regs_size = ARRAY_SIZE(sensor_fmt_raw),		
              .bpp       = 1
          },
      };
      

      ​ 如果sensor输出图像格式是YUV的话,则需要根据sensor图像数据输出顺序选择YUYV/VYUY/UYVY/YVYU 其中一种,如下:

      static struct sensor_format_struct sensor_formats[] = {
      	{
      		.desc = "YUYV 4:2:2",
      		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
      		.regs = sensor_fmt_raw,
      		.regs_size = ARRAY_SIZE(sensor_fmt_raw),
      		.bpp = 2,
      	},
      };
      

      ​ 同时,sensor_get_fmt_mbus_core函数也要将当前sensor的图像输出格式赋值给函数参数*code,有些sensor在翻转后RGB顺序不会自动进行调整,需要主控端ISP需要按照当前sensor翻转后的图像格式更新RGB顺序,避免翻转后出现图像色彩异常的问题,如下,gc2053支持翻转后sensor内部自动调整RGB顺序,所以函数参数*code仍赋值为MEDIA_BUS_FMT_SRGGB10_1X10。

      static int sensor_get_fmt_mbus_core(struct v4l2_subdev *sd, int *code)
      {
      	*code = MEDIA_BUS_FMT_SRGGB10_1X10; // gc2053 support change the rgb format by itself
      }
      
      static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
      {
          int ret = 0;
          struct sensor_info *info = to_state(sd);
      	switch (cmd) { 
              case VIDIOC_VIN_GET_SENSOR_CODE:    /* vin v4l2框架层在sensor翻转接口被调用后,
              								    通过VIDIOC_VIN_GET_SENSOR_CODE获取当前sensor的RGB顺序 */
                  sensor_get_fmt_mbus_core(sd, (int *)arg);  
                  break;
              default:
                  return -EINVAL;
      	}
      	return ret;
      }
      
      posted in V Series
      A
      awwwwa
    • Reply: V821平台如何修改文件系统分区大小

      https://docs.aw-ol.com/docs/soc/v821/software/configure#分区表

      posted in V Series
      A
      awwwwa
    • Reply: V853无法烧写SPI Nand

      @haaland

      [05.750]sunxi-spinand-phy: read id failed : -110
      try nand fail
      

      nand找不到,确认一下sys_config.fex的spi引脚配置对不对

      posted in V Series
      A
      awwwwa
    • V853点亮d320fpc2403

      设备树配置

      &lcd0 {
      	base_config_start   = <1>;
      	lcd_used            = <1>;
      
      	lcd_driver_name     = "d320fpc2403";
      
      	lcd_backlight       = <50>;
      	lcd_if              = <4>;
      
      	lcd_x               = <1024>;
      	lcd_y               = <768>;
      	lcd_width           = <64>;
      	lcd_height          = <48>;
      	lcd_dclk_freq       = <54>;
      
      	lcd_pwm_used        = <1>;
      	lcd_pwm_ch          = <9>;
      	lcd_pwm_freq        = <5000>;
      	lcd_pwm_pol         = <1>;
      	lcd_pwm_max_limit   = <255>;
      
      	lcd_hbp             = <50>;
      	lcd_ht              = <1114>;
      	lcd_hspw            = <10>;
      	lcd_vbp             = <29>;
      	lcd_vt              = <809>;
      	lcd_vspw            = <8>;
      
      	lcd_dsi_if          = <0>;
      	lcd_dsi_lane        = <4>;
      	lcd_dsi_format      = <0>;
      	lcd_dsi_te          = <0>;
      	lcd_dsi_eotp        = <0>;
      	lcd_frm             = <0>;
      	lcd_io_phase        = <0x0000>;
      	lcd_hv_clk_phase    = <0>;
      	lcd_hv_sync_polarity= <0>;
      	lcd_gamma_en        = <0>;
      	lcd_bright_curve_en = <0>;
      	lcd_cmap_en         = <0>;
      	lcdgamma4iep        = <22>;
      
      	lcd_gpio_0          = <&pio PE 17 1 0 3 1>;
      	pinctrl-0           = <&dsi4lane_pins_a>;
      	pinctrl-1           = <&dsi4lane_pins_b>;
      	base_config_end     = <1>;
      };
      

      驱动

      /* drivers/video/sunxi/disp2/disp/lcd/d320fpc2403.c
       *
       * Copyright (c) 2025 Weidongshan <weidongshan@qq.com>
       *
       * d320fpc2403 panel driver
       *
       * 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 "d320fpc2403.h"
      
      static void lcd_power_on(u32 sel);
      static void lcd_power_off(u32 sel);
      static void lcd_bl_open(u32 sel);
      static void lcd_bl_close(u32 sel);
      
      static void lcd_panel_init(u32 sel);
      static void lcd_panel_exit(u32 sel);
      
      #define panel_reset(sel, val) sunxi_lcd_gpio_set_value(sel, 0, val)
      
      static void lcd_cfg_panel_info(struct panel_extend_para *info)
      {
      	u32 i = 0, j = 0;
      	u32 items;
      	u8 lcd_gamma_tbl[][2] = {
      		{ 0, 0 },     { 15, 15 },   { 30, 30 },	  { 45, 45 },
      		{ 60, 60 },   { 75, 75 },   { 90, 90 },	  { 105, 105 },
      		{ 120, 120 }, { 135, 135 }, { 150, 150 }, { 165, 165 },
      		{ 180, 180 }, { 195, 195 }, { 210, 210 }, { 225, 225 },
      		{ 240, 240 }, { 255, 255 },
      	};
      
      	u32 lcd_cmap_tbl[2][3][4] = {
      		{
      			{ LCD_CMAP_G0, LCD_CMAP_B1, LCD_CMAP_G2, LCD_CMAP_B3 },
      			{ LCD_CMAP_B0, LCD_CMAP_R1, LCD_CMAP_B2, LCD_CMAP_R3 },
      			{ LCD_CMAP_R0, LCD_CMAP_G1, LCD_CMAP_R2, LCD_CMAP_G3 },
      		},
      		{
      			{ LCD_CMAP_B3, LCD_CMAP_G2, LCD_CMAP_B1, LCD_CMAP_G0 },
      			{ LCD_CMAP_R3, LCD_CMAP_B2, LCD_CMAP_R1, LCD_CMAP_B0 },
      			{ LCD_CMAP_G3, LCD_CMAP_R2, LCD_CMAP_G1, LCD_CMAP_R0 },
      		},
      	};
      
      	items = sizeof(lcd_gamma_tbl) / 2;
      	for (i = 0; i < items - 1; i++) {
      		u32 num = lcd_gamma_tbl[i + 1][0] - lcd_gamma_tbl[i][0];
      
      		for (j = 0; j < num; j++) {
      			u32 value = 0;
      
      			value = lcd_gamma_tbl[i][1] +
      				((lcd_gamma_tbl[i + 1][1] -
      				  lcd_gamma_tbl[i][1]) *
      				 j) / num;
      			info->lcd_gamma_tbl[lcd_gamma_tbl[i][0] + j] =
      				(value << 16) + (value << 8) + value;
      		}
      	}
      	info->lcd_gamma_tbl[255] = (lcd_gamma_tbl[items - 1][1] << 16) +
      				   (lcd_gamma_tbl[items - 1][1] << 8) +
      				   lcd_gamma_tbl[items - 1][1];
      
      	memcpy(info->lcd_cmap_tbl, lcd_cmap_tbl, sizeof(lcd_cmap_tbl));
      }
      
      static s32 lcd_open_flow(u32 sel)
      {
      	LCD_OPEN_FUNC(sel, lcd_power_on, 120);
      	LCD_OPEN_FUNC(sel, lcd_panel_init, 10);
      	LCD_OPEN_FUNC(sel, sunxi_lcd_tcon_enable, 10);
      	LCD_OPEN_FUNC(sel, lcd_bl_open, 0);
      	return 0;
      }
      
      static s32 lcd_close_flow(u32 sel)
      {
      	LCD_CLOSE_FUNC(sel, lcd_bl_close, 0);
      	LCD_CLOSE_FUNC(sel, lcd_panel_exit, 200);
      	LCD_CLOSE_FUNC(sel, sunxi_lcd_tcon_disable, 0);
      	LCD_CLOSE_FUNC(sel, lcd_power_off, 500);
      	return 0;
      }
      
      static void lcd_power_on(u32 sel)
      {
      	/* reset lcd by gpio */
      	panel_reset(sel, 1);
      	sunxi_lcd_delay_ms(100);
      	panel_reset(sel, 0);
      	sunxi_lcd_delay_ms(500);
      	panel_reset(sel, 1);
      	sunxi_lcd_delay_ms(500);
      	sunxi_lcd_pin_cfg(sel, 1);
      }
      
      static void lcd_power_off(u32 sel)
      {
      	sunxi_lcd_pin_cfg(sel, 0);
      	sunxi_lcd_delay_ms(20);
      	panel_reset(sel, 0);
      	sunxi_lcd_delay_ms(5);
      }
      
      static void lcd_bl_open(u32 sel)
      {
      	sunxi_lcd_pwm_enable(sel);
      }
      
      static void lcd_bl_close(u32 sel)
      {
      	sunxi_lcd_backlight_disable(sel);
      }
      
      #define REGFLAG_DELAY 0XFC
      #define REGFLAG_END_OF_TABLE 0xFD /* END OF REGISTERS MARKER */
      
      struct LCM_setting_table {
      	u8 cmd;
      	u32 count;
      	u8 para_list[64];
      };
      
      static struct LCM_setting_table lcm_initialization_setting[] = {
      	{ 0xdf, 3, { 0x91, 0x68, 0xf9 } },
      	{ 0xde, 1, { 0x00 } },
      	// {0xc2, 1, {0x30}},
      	{ 0xb2, 2, { 0x00, 0x7e } },
      	{ 0xb3, 2, { 0x00, 0x7e } },
      	{ 0xc1, 6, { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 } },
      	{ 0xbb, 7, { 0x02, 0x24, 0x07, 0x61, 0x19, 0x44, 0x44 } },
      	{ 0xbe, 2, { 0x1a, 0xf2 } },
      	{ 0xc3,
      	  14,
      	  { 0x10, 0x17, 0x5a, 0x17, 0x5a, 0x05, 0x05, 0x05, 0x05, 0x15, 0x15,
      	    0x31, 0x05, 0xdf } },
      	{ 0xc4, 7, { 0x11, 0x80, 0x00, 0xdf, 0x09, 0x06, 0x14 } },
      	{ 0xce, 23, { 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
      		      0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
      		      0x03, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x03 } },
      	{ 0xcf, 9, { 0x00, 0x01, 0x40, 0x01, 0xca, 0x01, 0xca, 0x01, 0xca } },
      	{ 0xd0, 23, { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
      		      0x1f, 0x1f, 0x1f, 0x03, 0x01, 0x05, 0x07, 0x09,
      		      0x0b, 0x1e, 0x15, 0x1f, 0x1f, 0x15, 0x1f } },
      	{ 0xd1, 23, { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
      		      0x1f, 0x1f, 0x1f, 0x02, 0x00, 0x04, 0x06, 0x08,
      		      0x0a, 0x1e, 0x15, 0x1f, 0x1f, 0x15, 0x1f } },
      	{ 0xd2, 23, { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
      		      0x1f, 0x1f, 0x1f, 0x00, 0x02, 0x0a, 0x08, 0x06,
      		      0x04, 0x1f, 0x15, 0x1f, 0x1f, 0x15, 0x1e } },
      	{ 0xd3, 23, { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
      		      0x1f, 0x1f, 0x1f, 0x01, 0x03, 0x0b, 0x09, 0x07,
      		      0x05, 0x1f, 0x15, 0x1f, 0x1f, 0x15, 0x1e } },
      	{ 0xd4, 37, { 0x30, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00,
      		      0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x11, 0x00,
      		      0x01, 0xc0, 0x04, 0x01, 0x01, 0x11, 0x80, 0x01,
      		      0xc0, 0x05, 0x01, 0x01, 0x00, 0x00, 0x00, 0x04,
      		      0x00, 0x06, 0x18, 0x02, 0xe3 } },
      	{ 0xd5, 8, { 0x68, 0x73, 0x00, 0x08, 0x08, 0x00, 0x03, 0x00 } },
      	{ 0xb7, 6, { 0x00, 0xd8, 0x00, 0x00, 0xd8, 0x00 } },
      	{ 0xc8, 38, { 0x7f, 0x69, 0x5a, 0x4e, 0x4a, 0x3b, 0x40, 0x2a,
      		      0x44, 0x43, 0x44, 0x63, 0x51, 0x59, 0x4c, 0x48,
      		      0x3a, 0x28, 0x0f, 0x7f, 0x69, 0x5a, 0x4e, 0x4a,
      		      0x3b, 0x40, 0x2a, 0x44, 0x43, 0x44, 0x63, 0x51,
      		      0x59, 0x4c, 0x48, 0x3a, 0x28, 0x0f } },
      	{ 0xde, 1, { 0x02 } },
      	{ 0xbb, 4, { 0x00, 0x5b, 0x5c, 0x41 } },
      	{ 0xb5, 3, { 0x00, 0x5a, 0x0a } },
      	{ 0xc6, 1, { 0x22 } },
      	{ 0xd7, 1, { 0x12 } },
      	{ 0xe7, 2, { 0x00, 0x00 } },
      	{ 0xde, 1, { 0x04 } },
      	{ 0xcc, 1, { 0x02 } },
      	{ 0xe7, 1, { 0x01 } },
      	{ 0xde, 1, { 0x00 } },
      	{ 0x35, 1, { 0x00 } },
      	{ 0x11, 0, { 0x00 } },
      	{ REGFLAG_DELAY, REGFLAG_DELAY, { 120 } },
      	{ 0x29, 0, { 0x00 } },
      	{ REGFLAG_DELAY, REGFLAG_DELAY, { 20 } },
      	{ REGFLAG_END_OF_TABLE, REGFLAG_END_OF_TABLE, {} },
      };
      
      static void lcd_panel_init(u32 sel)
      {
      	u32 i = 0;
      
      	sunxi_lcd_dsi_clk_enable(sel);
      	sunxi_lcd_delay_ms(100);
      	for (i = 0;; i++) {
      		if (lcm_initialization_setting[i].cmd == REGFLAG_END_OF_TABLE)
      			break;
      		else if (lcm_initialization_setting[i].cmd == REGFLAG_DELAY)
      			sunxi_lcd_delay_ms(lcm_initialization_setting[i].count);
      		else {
      			dsi_dcs_wr(0, lcm_initialization_setting[i].cmd,
      				   lcm_initialization_setting[i].para_list,
      				   lcm_initialization_setting[i].count);
      		}
      	}
      }
      
      static void lcd_panel_exit(u32 sel)
      {
      	sunxi_lcd_dsi_dcs_write_0para(sel, 0x28);
      	sunxi_lcd_delay_ms(80);
      	sunxi_lcd_dsi_dcs_write_0para(sel, 0x10);
      	sunxi_lcd_delay_ms(50);
      }
      
      /*sel: 0:lcd0; 1:lcd1*/
      static s32 lcd_user_defined_func(u32 sel, u32 para1, u32 para2, u32 para3)
      {
      	return 0;
      }
      
      struct __lcd_panel d320fpc2403_panel = {
          /* panel driver name, must mach the name of
           * lcd_drv_name in sys_config.fex
           */
          .name = "d320fpc2403",
          .func =
              {
                  .cfg_panel_info = lcd_cfg_panel_info,
                  .cfg_open_flow = lcd_open_flow,
                  .cfg_close_flow = lcd_close_flow,
                  .lcd_user_defined_func = lcd_user_defined_func,
              },
      };
      
      posted in V Series
      A
      awwwwa
    • 1
    • 2
    • 2 / 2