@eestr 在 T113主机副屏项目(mipi屏幕) 中说:
7c3e4650-19b1-4dcb-9d20-43320e150f0f-mipi转接板原理图.pdf 目前使用的主板加转接板的模式,原理图是这样的,现在LCD的电源不是很好用,测了下LCD背光的电源输出不正常,有没有搞硬件的兄弟指导一下
![]()
从原理图看没有啥问题。你测了输出电压了吗?应该是24v左右,你的电解电容耐压是多少v?
@eestr 在 T113主机副屏项目(mipi屏幕) 中说:
7c3e4650-19b1-4dcb-9d20-43320e150f0f-mipi转接板原理图.pdf 目前使用的主板加转接板的模式,原理图是这样的,现在LCD的电源不是很好用,测了下LCD背光的电源输出不正常,有没有搞硬件的兄弟指导一下
![]()
从原理图看没有啥问题。你测了输出电压了吗?应该是24v左右,你的电解电容耐压是多少v?
@feitian227 在 用T113-S4搭建一个8.8寸长条屏HMI开发平台 中说:
@laocai 这个是走屏幕扩展的吗?玩需要全屏但不能分屏的游戏时会有影响吗?
走不走Windows分屏功能,选择权在屏的使用者手上。走Windows分屏功能,是要安装专门的IddCx驱动程序的,如果怕占用显卡掉帧率,不要安装IddCx驱动程序即可。
@wangyn 在 用T113-S4搭建一个8.8寸长条屏HMI开发平台 中说:
@laocai 你好,我最近也在找T113平台做一些HMI开发,你这个平台现在可以卖我2块吗?什么价格?包括长条LCD屏
如果想购买驱动板,可以通过此
淘宝链接
新的驱动板打样回来了。USB设备模式支持Type-C和MX1.25mm两种接口,方便用户把长条屏集成到台式机机箱中去,作为设备监控面板使用。
@wangyn 在 用T113-S4搭建一个8.8寸长条屏HMI开发平台 中说:
@laocai 你好,我最近也在找T113平台做一些HMI开发,你这个平台现在可以卖我2块吗?什么价格?包括长条LCD屏
改版中,大概1周以后新的驱动板加工回来。
@eestr 楼主你的项目进展如何了?我做了一个8.8寸mipi屏的驱动板,是用T113-S4做的。你有没有兴趣一起来做上位机的应用开发?
板子已经打样回来,BSP也调试通过。下面是1080p硬解的资源占用情况。

解码用的VE,颜色空间转换用的arm核。

中秋节快乐!
愿景就是用最流行的硬件元素搭建一个通用的HMI开发平台,方便广大工程师朋友和电子发烧友验证和拓展自己的想法。SOC选用T113-S4,是当红的全志SOC平台,双A7自带256MB内存,足够支撑Qt之类的图形应用开发;屏幕选用8.8寸MIPI长条屏,国内众多厂家都有出品,淘宝上早卖成了白菜价。最后希望这个平台能够做到5年之内不过时,不停产。
板子已经画好了。带一个USB Type A和一个Type C接口,液晶屏和触摸屏接口在左侧。SOC多余的引脚通过下方的双排针引出。板子比较紧凑84mmx50mm。
我会在这里更新后续的开发调试进展,有问题欢迎一起讨论。大家一起出力把论坛建设好。
参考资料
whycan的长条屏开发板
楼主的排错笔记真的很有用。我在100ask的bbs上看到有相同的提问,但是没有答案。
看下来,似乎是全志usb的驱动程序里把端点类型写死了,找不到中断类型的端点导致配置hid小机的时候bind失败。是这样吗?
我知道的,只有v3s和f1c100主线有drm驱动,而且都是支持不完整的。你可以到挖坑网上去搜索一下,那上面信息多一些。
@yteraa 我补充一点,Tina默认是用的procd,如果要切换到busybox-init, Base system里面要确保procd package被关闭。否则编译的时候会出现如下错误:
Configuring canutils-candump.
Collected errors:
* check_data_file_clashes: Package busybox wants to install file /opt/tina5sdk-bsp/out/t113_i/maple/openwrt/build_dir/target/root-t113_i-maple/sbin/init
But that file is already provided by package * procd
* opkg_install_cmd: Cannot install package busybox.
package/Makefile:66: recipe for target 'package/install' failed
make[2]: *** [package/install] Error 255
make[2]: Leaving directory '/opt/tina5sdk-bsp/openwrt/openwrt'
package/Makefile:111: recipe for target '/opt/tina5sdk-bsp/openwrt/openwrt/staging_dir/target/stamp/.package_install' failed
make[1]: *** [/opt/tina5sdk-bsp/openwrt/openwrt/staging_dir/target/stamp/.package_install] Error 2
make[1]: Leaving directory '/opt/tina5sdk-bsp/openwrt/openwrt'
/opt/tina5sdk-bsp/openwrt/openwrt/include/toplevel.mk:238: recipe for target 'world' failed
make: *** [world] Error 2
make: Leaving directory '/opt/tina5sdk-bsp/openwrt/openwrt'
INFO: build_openwrt_rootfs failed
现在有两个图层,它们由其他app生成,我希望通过编程的方法,简单的进行切换:显示图层1-->显示图层2-->再显示图层1-- >以此类推。如果通过DISP_LAYER_SET_CONFIG调用的话,似乎要把图层所有的参数,包括缓冲区地址等统统设置一遍,而我只想简单的切换两个图层,并不知道也不关心这些图层的详细参数。请问我该怎么做?
# cat /sys/class/disp/disp/attr/sys | more
screen 0:
de_rate 300000000 hz, ref_fps:62
mgr0: 480x480 fmt[rgb] cs[0x204] range[full] eotf[0x4] bits[8bits] err[0] force_
sync[0] unblank direct_show[false] iommu[1]
dmabuf: cache[0] cache max[0] umap skip[0] umap skip max[18]
lcd output backlight(229) fps:62.1 480x 480
err:11428 skip:90 irq:14361 vsync:0 vsync_skip:0
BUF enable ch[0] lyr[0] z[0] prem[N] a[globl 255] fmt[ 11] fb[ 480, 480;
0, 0; 0, 0] crop[ 0, 0, 0, 0] frame[ 0, 0, 480, 480] addr[ 2
80000, 0, 0] flags[0x 0] trd[0,0]
depth[ 0] BUF enable ch[1] lyr[0] z[16] prem[N] a[pixel 255] fmt[ 0] fb[
480, 480; 480, 480; 480, 480] crop[ 0, 0, 480, 480] frame[ 0, 0, 480, 48
0] addr[ 0, 0, 0] flags[0x 0] trd[0,0]
depth[ 0]
@ddrddr 可能你的framebuffer支持alpha通道,但是填充图像数据的时候没有填写相应alpha数值。检查一下framebuffer格式即可。
@laocai 官方文档里也到处都是错误。

红线处正确的代码应该是这样的:
memset(&config, 0, sizeof(struct disp_layer_config));
config.channel = 0;//blending channel
config.layer_id = 0;//layer index in the blending channel
config.enable = 1;
config.info.mode = LAYER_MODE_BUFFER;
@zheng1 在 关于sunxi图层设置DISP_LAYER_SET_CONFIG的一个问题 中说:
@laocai tina的sdk有一个libuapi库是对这部分接口的封装,我在v851s上用DISP_LAYER_SET_CONFIG2会导致内核内存泄漏,你可以试试有没有同样的问题
我猜你遇到的问题可能和这段代码有关:
#if defined(CONF_KERNEL_IOMMU)
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REL, 0);
if (ret)
logv("ENGINE_REL failed\n");
struct user_iommu_param iommu_param;
memset(&iommu_param, 0, sizeof(iommu_param));
iommu_param.fd = tmp->fd_data.aw_fd;
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_FREE_IOMMU_ADDR, &iommu_param);
if (ret)
logv("FREE_IOMMU_ADDR err, ret %d\n", ret);
#endif
/*close dma buffer fd*/
close(tmp->fd_data.aw_fd);
/* free buffer */
handle_data.handle = tmp->fd_data.handle;
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_FREE, &handle_data);
if (ret)
logv("TON_IOC_FREE failed\n");
aw_mem_list_del(&tmp->i_list);
free(tmp);
flag = 1;
handle_data.handle = tmp->fd_data.handle;
内核版本为高版本(5.4)的时候,libuapi库在申请内存时根本没有初始化这个handle。然后释放内存的时候,却又用这个空的handle去调用释放的系统调用,内存根本不可能真正释放。换句话说,这个libuapi库只有在低版本内核上才有可能正常工作;高版本内核上,内存只能申请,无法释放。
@laocai 另外关于sunxi_display2.h文件,我在tina sdk的package中发现了七个路径下有这个文件,前面三个文件的内容各不相同,和内核使用的sunxi_display2.h文件也不同。
allwinner/libAWIspApi/src/isp522/libisp/include/device/sunxi_display2.h
allwinner/tina_multimedia/libcedarx/demo/xplayerdemo/sunxi_display2.h
allwinner/tina_multimedia/libcedarx/demo/recoderdemo/sunxi_display2.h
allwinner/libuapi/src/sunxi_display_v2.h
testtools/tinatest/testcase/base/production/displaytester/common/sunxi_display_v2.h
allwinner/tinacvr/src/middle_ware/sunxi_display_v2.h
gui/minigui/multimedia-test/src/middle_ware/sunxi_display_v2.h
比较了一下,和内核头文件最接近的是allwinner/libAWIspApi/src/isp522/libisp/include/device/sunxi_display2.h

allwinner/tinacvr/src/middle_ware/sunxi_display_v2.h和allwinner/libuapi/src/sunxi_display_v2.h比较接近,后者像是在前者基础上修改而来。
@laocai 如果要获得framebuffer的物理地址,就采用这个方法
void* sunxifb_mem_get_phyaddr(void *data) {
if (data != NULL)
return SunxiMemGetPhysicAddressCpu(memops, data);
else
return NULL;
}
@laocai 我找到了一个简单使用libuapi库的例子,在tina-package/blob/main/gui/littlevgl-8/lv_drivers/display/sunximem.c
/**
* @file sunximem.c
*
*/
/*********************
* INCLUDES
*********************/
#include "sunximem.h"
#if USE_SUNXIFB_G2D
#include <stdio.h>
#include <ion_mem_alloc.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STRUCTURES
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static struct SunxiMemOpsS *memops;
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
bool sunxifb_mem_init() {
if (memops)
return true;
memops = GetMemAdapterOpsS();
if (SunxiMemOpen(memops) < 0) {
perror("Error: cannot open ion device");
return false;
}
return true;
}
void sunxifb_mem_deinit() {
if (memops) {
SunxiMemClose(memops);
memops = NULL;
}
}
void* sunxifb_mem_alloc(size_t size, char *label) {
if (size == 0) {
printf("size illegal.");
return NULL;
}
void *alloc = SunxiMemPalloc(memops, size);
if (alloc == NULL) {
printf("couldn't allocate memory (%lu bytes).", (unsigned long) size);
return NULL;
}
#ifdef LV_USE_SUNXIFB_DEBUG
printf("%s: sunxifb_mem_alloc=%p size=%lu bytes\n", label, alloc, (unsigned long) size);
#endif /* LV_USE_SUNXIFB_DEBUG */
return alloc;
}
void sunxifb_mem_free(void **data, char *label) {
if (*data != NULL) {
#ifdef LV_USE_SUNXIFB_DEBUG
printf("%s: sunxifb_mem_free=%p\n", label, *data);
#endif /* LV_USE_SUNXIFB_DEBUG */
SunxiMemPfree(memops, *data);
*data = NULL;
} else {
printf("couldn't free memory.\n");
}
}
void* sunxifb_mem_get_phyaddr(void *data) {
if (data != NULL)
return SunxiMemGetPhysicAddressCpu(memops, data);
else
return NULL;
}
void sunxifb_mem_flush_cache(void *data, size_t size) {
SunxiMemFlushCache(memops, data, size);
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif
@laocai 而选择ion设备还是cedar设备,是由编译选项决定的。如果要采用DISP_LAYER_SET_CONFIG2,必须编译的时候选择SUNXI_ALLOC_IOMMU,不知道我的理解是否正确?我找到的关于全志disp的讨论
choice
prompt "Choose alloc method"
default SUNXI_ALLOC_CMA
help
Select how to apply for memory.
config SUNXI_ALLOC_CMA
bool "sunxi_alloc_cma"
config SUNXI_ALLOC_IOMMU
bool "sunxi_alloc_iommu"
endchoice
choice
prompt "Choose layer alloc method"
default LUAPI_LAYER_ALLOC_CHN
help
Select how to apply for layer.
config LUAPI_LAYER_ALLOC_CHN
bool "luapi_layer_alloc_chn"
config LUAPI_LAYER_ALLOC_LAY
bool "luapi_layer_alloc_lay"
endchoice
choice
prompt "Choose display rendering mode"
default SUNXI_DISPLAY_DE
help
Choose display rendering mode, DE or GPU.
config SUNXI_DISPLAY_DE
bool "DE"
config SUNXI_DISPLAY_GPU
bool "GPU"
help
Define the macro SUNXI_DISPLAY_GPU, use GPU rendering, send the RGBA data
after rendering to fb1 display, execute export FRAMEBUFFER=/dev/fb1
before executing the program, no longer support DispSetEnable, DispSetSrcRect,
DispSetZorder and DispSetIoctl functions.
Define the macro SUNXI_DISPLAY_GPU and SUNXI_DISPLAY_GPU_BUF, use GPU rendering,
send the RGBA data after rendering to layer. No longer support DispSetSrcRect functions.
Default use.
endchoice
endif
endef
define Build/Prepare
$(INSTALL_DIR) $(PKG_BUILD_DIR)/
$(CP) ./src $(PKG_BUILD_DIR)/
endef
define Build/Configure
endef
ifeq ($(CONFIG_SUNXI_DISPLAY_TWO),y)
TARGET_CFLAGS+=-D__SUNXI_DISPLAY2__
TARGET_CFLAGS+=-D$(KERNEL_VERSION)
endif
ifeq ($(CONFIG_SUNXI_DISPLAY_ONE),y)
TARGET_CFLAGS+=-D__SUNXI_DISPLAY__
TARGET_CFLAGS+=-D$(KERNEL_VERSION)
endif
ifeq ($(CONFIG_SUNXI_ALLOC_CMA),y)
TARGET_CFLAGS+=-DCONF_KERNEL_CMA
endif
ifeq ($(CONFIG_SUNXI_ALLOC_IOMMU),y)
TARGET_CFLAGS+=-DCONF_KERNEL_IOMMU
endif
另外我还发现,linux 内核5.4版本的时候,libuapi库无法使用ion设备来分配framebuffer,原因就是代码里面根本没有实现alloc_data的赋值。
#if CONF_KERNEL_VERSION_OLD
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_ALLOC, &alloc_data);
if (ret) {
loge("ION_IOC_ALLOC error\n");
goto ALLOC_OUT;
}
/* get dmabuf fd */
fd_data.handle = alloc_data.handle;
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_MAP, &fd_data);
if (ret) {
loge("ION_IOC_MAP err, ret %d, dmabuf fd 0x%08x\n",
ret, (unsigned int)fd_data.aw_fd);
goto ALLOC_OUT;
}
#else
struct aw_ion_new_alloc_data data = {
.len = alloc_data.aw_len,
.heap_id_mask = alloc_data.aw_heap_id_mask,
.flags = alloc_data.flags,
};
ret = ioctl(g_ion_alloc_context->fd, AW_ION_IOC_NEW_ALLOC, &data);
if (ret < 0) {
loge("AW_ION_IOC_NEW_ALLOC error\n");
goto ALLOC_OUT;
}
fd_data.aw_fd = data.fd;
#endif
/* get phy address */
#if defined(CONF_KERNEL_IOMMU)
memset(&iommu_param, 0, sizeof(iommu_param));
iommu_param.fd = fd_data.aw_fd;
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REQ, 0);
if (ret) {
loge("ENGINE_REQ err, ret %d\n", ret);
addr_phy = 0;
addr_vir = 0;
goto ALLOC_OUT;
}
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_GET_IOMMU_ADDR, &iommu_param);
if (ret) {
loge("GET_IOMMU_ADDR err, ret %d\n", ret);
addr_phy = 0;
addr_vir = 0;
goto ALLOC_OUT;
}
addr_phy = iommu_param.iommu_addr;
#else
memset(&phys_data, 0, sizeof(phys_data));
phys_data.handle = alloc_data.handle;
phys_data.size = size;
custom_data.aw_cmd = ION_IOC_SUNXI_PHYS_ADDR;
custom_data.aw_arg = (unsigned long)&phys_data;
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_CUSTOM, &custom_data);
if (ret) {
loge("ION_IOC_CUSTOM err, ret %d\n", ret);
addr_phy = 0;
addr_vir = 0;
goto ALLOC_OUT;
}
addr_phy = phys_data.phys_addr;
#endif
@laocai 找到了libuapi\src\ion_alloc.c中的代码
/* return virtual address: 0 failed */
void* sunxi_ion_alloc_palloc(int size)
{
aw_ion_allocation_info_t alloc_data;
ion_fd_data_t fd_data;
struct ion_handle_data handle_data;
struct aw_ion_custom_info custom_data;
sunxi_phys_data phys_data;
struct user_iommu_param iommu_param;
int rest_size = 0;
unsigned long addr_phy = 0;
unsigned long addr_vir = 0;
buffer_node * alloc_buffer = NULL;
int ret = 0;
char *cache_flag;
pthread_mutex_lock(&g_ion_mutex_alloc);
if (g_ion_alloc_context == NULL) {
loge("call ion_alloc_open\n");
goto ALLOC_OUT;
}
if (size <= 0) {
loge("can not alloc size 0\n");
goto ALLOC_OUT;
}
memset(&alloc_data, 0, sizeof(alloc_data));
memset(&fd_data, 0, sizeof(fd_data));
alloc_data.aw_len = (size_t)size;
alloc_data.aw_align = ION_ALLOC_ALIGN ;
#if defined(CONF_KERNEL_IOMMU)
alloc_data.aw_heap_id_mask = AW_ION_SYSTEM_HEAP_MASK | AW_ION_CARVEOUT_HEAP_MASK;
#else
alloc_data.aw_heap_id_mask = AW_ION_DMA_HEAP_MASK | AW_ION_CARVEOUT_HEAP_MASK;
#endif
cache_flag = getenv("MG_IONBUFFER");
if(cache_flag == NULL || strcmp(cache_flag, "1") != 0){
alloc_data.flags = AW_ION_CACHED_FLAG | AW_ION_CACHED_NEEDS_SYNC_FLAG;
}
#if CONF_KERNEL_VERSION_OLD
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_ALLOC, &alloc_data);
if (ret) {
loge("ION_IOC_ALLOC error\n");
goto ALLOC_OUT;
}
/* get dmabuf fd */
fd_data.handle = alloc_data.handle;
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_MAP, &fd_data);
if (ret) {
loge("ION_IOC_MAP err, ret %d, dmabuf fd 0x%08x\n",
ret, (unsigned int)fd_data.aw_fd);
goto ALLOC_OUT;
}
#else
struct aw_ion_new_alloc_data data = {
.len = alloc_data.aw_len,
.heap_id_mask = alloc_data.aw_heap_id_mask,
.flags = alloc_data.flags,
};
ret = ioctl(g_ion_alloc_context->fd, AW_ION_IOC_NEW_ALLOC, &data);
if (ret < 0) {
loge("AW_ION_IOC_NEW_ALLOC error\n");
goto ALLOC_OUT;
}
fd_data.aw_fd = data.fd;
#endif
/* mmap to user */
addr_vir = (unsigned long)mmap(NULL, alloc_data.aw_len, \
PROT_READ|PROT_WRITE, MAP_SHARED, fd_data.aw_fd, 0);
if ((unsigned long)MAP_FAILED == addr_vir) {
loge("mmap err, ret %u\n", (unsigned int)addr_vir);
addr_vir = 0;
goto ALLOC_OUT;
}
/* get phy address */
#if defined(CONF_KERNEL_IOMMU)
memset(&iommu_param, 0, sizeof(iommu_param));
iommu_param.fd = fd_data.aw_fd;
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REQ, 0);
if (ret) {
loge("ENGINE_REQ err, ret %d\n", ret);
addr_phy = 0;
addr_vir = 0;
goto ALLOC_OUT;
}
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_GET_IOMMU_ADDR, &iommu_param);
if (ret) {
loge("GET_IOMMU_ADDR err, ret %d\n", ret);
addr_phy = 0;
addr_vir = 0;
goto ALLOC_OUT;
}
addr_phy = iommu_param.iommu_addr;
#else
memset(&phys_data, 0, sizeof(phys_data));
phys_data.handle = alloc_data.handle;
phys_data.size = size;
custom_data.aw_cmd = ION_IOC_SUNXI_PHYS_ADDR;
custom_data.aw_arg = (unsigned long)&phys_data;
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_CUSTOM, &custom_data);
if (ret) {
loge("ION_IOC_CUSTOM err, ret %d\n", ret);
addr_phy = 0;
addr_vir = 0;
goto ALLOC_OUT;
}
addr_phy = phys_data.phys_addr;
#endif
alloc_buffer = (buffer_node *)malloc(sizeof(buffer_node));
if (alloc_buffer == NULL) {
loge("malloc buffer node failed");
/* unmmap */
ret = munmap((void*)addr_vir, alloc_data.aw_len);
if (ret) {
loge("munmap err, ret %d\n", ret);
}
#if defined(CONF_KERNEL_IOMMU)
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REL, 0);
if (ret)
logv("ENGINE_REL failed\n");
ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_FREE_IOMMU_ADDR, &iommu_param);
if (ret)
logv("FREE_IOMMU_ADDR err, ret %d\n", ret);
#endif
/* close dmabuf fd */
close(fd_data.aw_fd);
/* free buffer */
handle_data.handle = alloc_data.handle;
ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_FREE, &handle_data);
if(ret)
loge("ION_IOC_FREE err, ret %d\n", ret);
addr_phy = 0;
addr_vir = 0; /* value of MAP_FAILED is -1, should return 0*/
goto ALLOC_OUT;
}
alloc_buffer->phy = addr_phy;
alloc_buffer->vir = addr_vir;
alloc_buffer->user_virt = addr_vir;
alloc_buffer->size = size;
alloc_buffer->fd_data.handle = fd_data.handle;
alloc_buffer->fd_data.aw_fd = fd_data.aw_fd;
aw_mem_list_add_tail(&alloc_buffer->i_list, &g_ion_alloc_context->list);
#if DEBUG_ION_REF==1
cdx_use_mem += size;
int i = 0;
for (i = 0; i < ION_BUF_LEN; i++) {
if (ion_buf_nodes_test[i].addr == 0
&& ion_buf_nodes_test[i].size == 0) {
ion_buf_nodes_test[i].addr = addr_vir;
ion_buf_nodes_test[i].size = size;
break;
}
}
if (i>= ION_BUF_LEN) {
loge("error, ion buf len is large than [%d]", ION_BUF_LEN);
}
#endif
ALLOC_OUT:
pthread_mutex_unlock(&g_ion_mutex_alloc);
return (void*)addr_vir;
}
根据配置不同,libuapi使用ion设备或者cedar设备来分配内存。
@zheng1 之前我只用了tina linux内核,没有安装tina sdk。
等我把tina sdk安装了看看,全志要能提供更详细的使用说明就好了。
另外全志的文档中提到sunxi_display2.h,我发现这个头文件不能直接用于应用程序开发。原因是它引用了很多只有内核中才用到的c语言类型,如s32等。请问全志的sunxi应用程序开发到底要使用什么样的开发环境呢?
这是我网上搜到的一张图片,这段代码使用了android的ion库来创建framebuffer。sunxi图层创建必须要用ion库吗?
PS,这段代码是采用DISP_LAYER_SET_CONFIG2配置,所以是用ion memory,那么DISP_LAYER_SET_CONFIG配置呢,DISP_LAYER_SET_CONFIG配置的时候,应用程序该如何准备图层的framebuffer?有没有大神能解释一下
通过ioctl函数传递的图层参数,framebuffer地址(即下面的add[0])到底是物理地址还是虚拟地址?这个framebuffer由应用层提供,有没有什么特别要求?比如地址对齐要求、连续内存要求等等。另外哪里能找到说明文档或者参考代码?
/* 选择图层所需的通道以及本图层参数 */
config.channel = 0;
config.layer_id = 0;
config.info.enable = 1;
config.info.mode = LAYER_MODE_BUFFER;
config.info.fb.addr[0] = (unsigned long long)mem_in; //FB物理地址
config.info.fb.size[0].width = width;
config.info.fb.size[0].height = height;
config.info.fb.align[0] = 4; //4bytes align
config.info.fb.format = DISP_FORMAT_ARGB_8888;
/* 上层调用DE显示引擎所用的ioctl接口 */
arg[0] = 0; //screen_id 0表示选择通路0
arg[1] = (unsigned long)&config;
arg[2] = 1;//表示设置图层数量为1
ret = ioctl(disphd, DISP_LAYER_SET_CONFIG, (void *)arg);
@houxiaoni 全志对gstreamer做了适配支持,怎么tina的开发文档里都没有提及?还是我漏看了什么重要内容?我看到的文档,多媒体开发只有tplayer工具这一种,楼主能否澄清一下?
规划中一个产品,主要用gstreamer做h264硬解,然后显示到lcd上。是基于tina linux开发好,还是主线linux开发好?要求就是资料多,坑少一点。能够快一点做出来。
另外,这个产品规划生命周期5年,总产量1000台。请问全志会为这样的产品提供技术支持吗?