S3C2416 2D加速

http://blog.csdn.net/zanget/archive/2010/11/18/6019528.aspx

最近调试2D一忙就是2周,现在终于忙完了,要将之前的调试信息全部都写下来,可是不大可能的。

当然,主要还是要驱动程序和 应用程序结合调试才能达到效果。

最开始一直使用光栅(ROP),希望能达到想要的效果,结果却一直是出现颜色混合。。

后来发现自己居然只使用到了FB0。。至于FB1....默认是关闭的;

而2416上的关键色,要求是两个窗口叠加才能出现效果;这个主要是集中在处理OSD的时候,没能开启。汗一个先。。。

关于加速显示的测试程序,在网上找到了几篇,比如

 http://apps.hi.baidu.com/share/detail/17513859

虽然貌似不上架,很难使用,但是基本上思路还有的。

根据需要,改成我自己驱动的情况:

00001: #include <stdlib.h>

00002: #include <stdio.h>

00003: #include <string.h>

00004: #include <unistd.h>

00005: #include <fcntl.h>

00006: #include <sys/ioctl.h>

00007: #include <sys/types.h>

00008: #include <sys/mman.h>

00010: #include <errno.h>

00012: #include <stdint.h> //uint32_t uint8_t

00013: #include "s3c_g2d.h"

00014: #include <linux/fb.h>

00015:

00016: #include <sys/stat.h>

00017: #include <unistd.h>

00018:

00019: #include <sys/time.h>

00020:

00021: #include "def.h"

00022:

00023: /***********************************************************

00024: * Global image file descriptor

00025: ***********************************************************/

00026: int g2d_fd;

00027:

00028: #ifdef FB0_OPERATION

00029: int fb0_fd;

00030: #endif

00031:

00032: int fb1_fd;

00033:

00034: struct fb_fix_screeninfo finfo;

00035: struct fb_var_screeninfo info;

00036:

00037: void printHex(char * p, unsigned char * data, int len)

00038: {

00039:     int i;

00040:     if(p)

00041:     {

00042:         printf("|%s|:[addr=%p][len=%d]:\n",p,data,len);

00043:     }

00044:     len = len>128 ? 128: len;

00045:     for(i=0;i<len;i++)

00046:     {

00047:         printf("%02x,",data[i]);

00048:         if((i+1)%16 ==0)

00049:         printf("\n");

00050:     }

00051:     printf("|%s|\n\n",p);

00052: }

00053:

00054: /*********************************************

00055: * file operaton

00056: **********************************************/

00057: int open_file_image(char* file_name,int * file_fd,int * file_len)

00058: {

00059:     int rv;

00060:     struct stat buf;

00061:

00062:     rv = stat (file_name,&buf);

00063:     if(rv != 0 || buf.st_size < 1)

00064:     {

00065:        perror("stat");

00066:     return -1;

00067:     }

00068:

00069:     *file_len = buf.st_size;

00070:

00071:     *file_fd = open(file_name,O_RDWR);

00072:     if((*file_fd) < 0)

00073:     {

00074:         perror("fopen");

00075:         return -1;

00076:     }

00078:     return 0;

00079: } ? end open_file_image ?

00080:

00081:

00082: void fb_info()

00083: {

00084:     printf("using (fd=%d)\n"

00085:     "id = %s\n"

00086:     "xres = %d px\n"

00087:     "yres = %d px\n"

00088:     "xres_virtual = %d px\n"

00089:     "yres_virtual = %d px\n"

00090:     "bpp = %d\n"

00091:     "r = %2u:%u\n"

00092:     "g = %2u:%u\n"

00093:     "b = %2u:%u\n"

00094:     "smem_start = 0x%lx\n",

00095:     fb1_fd ,

00096:     finfo .id,

00097:     info .xres,

00098:     info .yres,

00099:     info .xres_virtual,

00100:     info .yres_virtual,

00101:     info .bits_per_pixel,

00102:     info .red.offset, info .red.length,

00103:     info .green.offset, info .green.length,

00104:     info .blue.offset, info .blue.length,

00105:     finfo .smem_start

00107:     );

00108:

00109: } ? end fb_info ?

00110:

00111: /*********************************************************

00112: * g2d & fb init & mmap

00113: **********************************************************/

00114: unsigned int g2d_fb_init()

00115: {

00116:     s3c_color_key_info_t ckey;

00117:     s3c_color_val_info_t cvalue;

00118:     // s3c_win_info_t osd; //set for win0,win1, SET_OSD_INFO

00119:

00120:     int rv;

00121:

00122: ////////////////////////////////////////////////////////////////////////////////////

00123:

00124:     g2d_fd = open(S3C_G2D_DEV_NAME, O_RDWR);//open g2d

00125:     if(g2d_fd <0)

00126:     {

00127:         perror("open S3C_G2D_DEV_NAME:");

00128:         return -1;

00129:     }

00130:

00131: #ifdef G2D_CUSTOMED

00132: /*************************************************************

00133: * G2D: color key and alpha

00134: *************************************************************/

00135: // G2D_NO_ALPHA = 0,

00136: // G2D_PLANE_ALPHA,//fixed..

00137: // G2D_PIXEL_ALPHA // with fallback to plane alpha

00138:     rv = ioctl(g2d_fd , S3C_G2D_SET_BLENDING, G2D_PIXEL_ALPHA); //光栅 先于 S3C_G2D_SET_RASTER_OP

00139:     if (rv != 0)

00140:     {

00141:        DBG("S3C_G2D_SET_BLENDING failed rv = %d, %s \n",rv, strerror(errno));

00142:        return -2;

00143:     }

00144:

00145:

00146: //alpha = (ALPHA+1) / 256, blended: ALPHA_REG = 0xf

00147: //win 1 透明度 //max 0xff

00148:     rv = ioctl(g2d_fd , S3C_G2D_SET_ALPHA_VAL, 0xf);

00149:     if (rv != 0)

00150:     {

00151:        DBG("set color key info error rv = %d, %s \n",rv, strerror(errno));

00152:        return rv;

00153:     }

00154:

00155: // #define G2D_ROP_SRC_ONLY (0xf0)

00156: // #define G2D_ROP_3RD_OPRND_ONLY (0xaa) //make the screen black

00157: // #define G2D_ROP_DST_ONLY (0xcc) //nothing.

00158: // #define G2D_ROP_SRC_OR_DST (0xfc) //覆盖 以前的画面

00159: // #define G2D_ROP_SRC_OR_3RD_OPRND (0xfa) // same as G2D_ROP_SRC_ONLY

00160: // #define G2D_ROP_SRC_AND_DST (0xc0) //覆盖 以前的画面,但是更透明

00161: // #define G2D_ROP_SRC_AND_3RD_OPRND (0xa0) //黑屏

00162: // #define G2D_ROP_SRC_XOR_3RD_OPRND (0x5a) // same as G2D_ROP_SRC_ONLY

00163: // #define G2D_ROP_DST_OR_3RD_OPRND (0xee) // nothing ?? same as G2D_ROP_SRC_ONLY ?

00163: ?

00164:

00165: //G2D_ROP_SRC_OR_DST

00166: //G2D_ROP_SRC_AND_DST

00167:

00168:     rv = ioctl(g2d_fd , S3C_G2D_SET_RASTER_OP, G2D_ROP_SRC_ONLY);//rop

00169:     if (rv != 0)

00170:     {

00171:        DBG("S3C_G2D_SET_RASTER_OP failed rv = %d, %s \n",rv, strerror(errno));

00172:        return -2;

00173:     }

00174:     #ifdef G2D_SET_TRANSFORM_90

00175:     rv = ioctl(g2d_fd , S3C_G2D_SET_TRANSFORM, G2D_ROT_90);

00176:     if (rv != 0)

00177:     {

00178:        DBG("g2d TRANSFORM error rv = %d, %s \n",rv, strerror(errno));

00179:        return -1;

00180:     }

00181: #endif //G2D_SET_TRANSFORM_90

00182:

00183: #endif //G2D_CUSTOMED

00184:

00185: ////////////////////////////////////////////////////////////////////////////////////

00186:

00187:

00188: #ifdef FB0_OPERATION

00189: /*************************************************

00190: * fb0 info

00191: *************************************************/

00192:     fb0_fd = open(S3C_FB0_DEV_NAME, O_RDWR);//open fb0

00193:     if(fb0_fd <0)

00194:     {

00195:        DBG("open framebuffer device %s \n", strerror(errno));

00196:        return -1;

00197:     }

00198: #endif //FB0_OPERATION

00199:

00200: ////////////////////////////////////////////////////////////////////////////////////

00201:

00202: /*************************************************

00203: * fb1 info

00204: *************************************************/

00205:     fb1_fd = open(S3C_FB1_DEV_NAME, O_RDWR);//open fb1

00206:     if(fb1_fd <0)

00207:     {

00208:         DBG("open framebuffer device %s \n", strerror(errno));

00209:         return -1;

00210:     }

00211:     rv = ioctl(fb1_fd , FBIOGET_FSCREENINFO, &finfo );

00212:     if (rv != 0)

00213:     {

00214:         DBG("%s get fix info error rv = %d, %s \n",__FUNCTION__,rv, strerror(errno));

00215:         return -1;

00216:     }

00217:     rv = ioctl(fb1_fd , FBIOGET_VSCREENINFO, &info );

00218:     if (rv != 0)

00219:     {

00220:         DBG("get var info error rv = %d, %s \n",rv, strerror(errno));

00221:         return -1;

00222:     }

00223:

00224: #ifdef FB1_CUSTOMED

00225: /*************************************************

00226: * OSD for fb1

00227: *************************************************/

00228:

00229:     rv = ioctl(fb1_fd , SET_OSD_START);

00230:     if (rv != 0)

00231:     {

00232:         DBG("set OSD Start error rv = %d, %s \n",rv, strerror(errno));

00233:         return rv;

00234:     }

00235:

00236:

00237: /***********************************************************

00238: * configure the color key to black and bg display

00239: ************************************************************/

00240:

00241: /**

00242: * set the blending mode and alpha1_R/G/B

00243: */

00244:     //0 Plane Blending & 1 Pixel Blending & chroma(color) key

00245:     rv = ioctl(fb1_fd , SET_COLOR_ALPHA_MODE, 1);//Pixel Blending & chroma(color) key

00246:     if (rv != 0)

00247:     {

00248:         DBG("set color alpha mode error rv = %d, %s \n",rv, strerror(errno));

00249:         return rv;

00250:     }

00251:

00252:     //color for win 1

00253:     cvalue.colval_red = 0;

00254:     cvalue.colval_green = 0;

00255:     cvalue.colval_blue = 0;

00256:     rv = ioctl(fb1_fd , SET_COLOR_ALPHA0_VALUE, &cvalue);

00256:     //Pixel Blending & chroma(color) key

00257:     if (rv != 0)

00258:     {

00259:        DBG("set color alpha mode error rv = %d, %s \n",rv, strerror(errno));

00260:        return rv;

00261:     }

00262:

00263:     //color for win 0

00264:     cvalue.colval_red = 0xf;

00265:     cvalue.colval_green = 0xf;

00266:     cvalue.colval_blue = 0xf;

00267:     rv = ioctl(fb1_fd , SET_COLOR_ALPHA1_VALUE, &cvalue);

00267:     //Pixel Blending & chroma(color) key

00268:     if (rv != 0)

00269:     {

00270:         DBG("set color alpha mode error rv = %d, %s \n",rv, strerror(errno));

00271:         return rv;

00272:     }

00273:

00274:     // direction = 0 means win1 is breen compared with color value

00275:     ckey.direction = COLOR_KEY_DIR_FG_DISPLAY;

00275:     //COLOR_KEY_DIR_BG_DISPLAY COLOR_KEY_DIR_FG_DISPLAY

00276:     //each bit is set to 0 means that each bit in colval is been compared

00277:     ckey.compkey_red = 0;

00278:     ckey.compkey_green = 0;

00279:     ckey.compkey_blue = 0;

00280:     //set color key info to be compared in color value

00281:     rv = ioctl(fb1_fd , SET_COLOR_KEY_INFO, &ckey);

00282:     if (rv != 0)

00283:     {

00284:        DBG("set color key info error rv = %d, %s \n",rv, strerror(errno));

00285:        return rv;

00286:     }

00287:

00288:     cvalue.colval_red = 0;

00289:     cvalue.colval_green = 0;

00290:     cvalue.colval_blue = 0;

00291:     //set color value

00292:     rv = ioctl(fb1_fd , SET_COLOR_KEY_COLVAL, &cvalue);

00293:     if (rv != 0)

00294:     {

00295:         DBG("set color key value error rv = %d, %s \n",rv, strerror(errno));

00296:         return rv;

00297:     }

00298:

00299:

00300:     //没用?????????????????????????????????????????????//

00301:     //start color key KEYEN_F[25] Color Key Chroma Key( 浓度 色度 ) Enable control

00302:     rv = ioctl(fb1_fd , SET_COLOR_KEY_START);

00303:     if (rv != 0)

00304:     {

00305:         DBG("set color key value error rv = %d, %s \n",rv, strerror(errno));

00306:         return rv;

00307:     }

00308:

00309:

00310:     //start alpha of color key KEYBLEN D [26]=1:alpha value selected by

00311:     // non-key area: alpha0_r/g/b

00312:     // key area : alpha1_r/g/b

00313:     rv = ioctl(fb1_fd , SET_COLOR_KEY_ALPHA_START);

00314:     if (rv != 0)

00315:     {

00316:     DBG("set color key value error rv = %d, %s \n",rv, strerror(errno));

00317:     return rv;

00318:     }

00319:

00320:     #endif //FB1_CUSTOMED

00321:

00322:     return 0;

00323: } ? end g2d_fb_init ?

00324:

00325:

00326: /*********************************************

00327: * g2d implement

00328: **********************************************/

00329: int s3c_g2d_copy_buffer(struct s3c_g2d_req * req, unsigned long buffer_base, unsigned

00329: long fb_base/*,

00330: int x, int y, int w, int h*/)

00331: {

00332:     int rv;

00333:     memset(req, 0, sizeof(struct s3c_g2d_req));

00334:

00335:

00336:     req->src.w = SOURCE_WIDTH;

00337:     req->src.h = SOURCE_HEIGHT;

00338:     req->src.offs = 0;

00339:     req->src.base = buffer_base;

00340:     req->src.fmt = SOURCE_FMT;

00341:

00342:     req->src.l = 0;

00343:     req->src.t = 0;

00344:     req->src.r = req->src.w;

00345:     req->src.b = req->src.h;

00346:

00347:     req->dst.w = DEST_WIDTH;

00348:     req->dst.h = DEST_HEIGHT;

00349:     req->dst.offs = 0;

00350:     req->dst.base = fb_base;

00351:     req->dst.fmt = DST_FMT;

00352:

00353:     req->dst.l = DST_LEFT_X;

00354:     req->dst.t = DST_TOP_Y;

00355:

00356:     req->dst.r = DST_RIGHT_X;

00357:     req->dst.b = DST_DOWN_Y;

00358:

00359:     rv = ioctl(g2d_fd , S3C_G2D_BITBLT, req);

00360:     if (rv != 0)

00361:     {

00362:         DBG("S3C_G2D_BITBLT failed = %d", -errno);

00363:         return -2;

00364:     }

00365:     // DBG("src base:0xx%u dst:base:0x%x\n",req->src.base,req->dst.base);

00366:     return 0;

00367: } ? end s3c_g2d_copy_buffer ?

00368:

00369: int main(int argc, char *argv[])

00370: {

00371:     u32 fb_phy;

00372:     struct s3c_g2d_req params;

00373:     int file_len,frame=0,rv,image_fd,times = 10;

00374:

00375:     struct timeval start,end;

00376:     double timeuse;

00377:     void * pmem_base /*, *fb_mem_map */;

00378:     char * file_name = YUV_FILE;

00379:

00380:     if(argc >= 2)

00381:     {

00382:         file_name = argv[1];

00383:         if(argc >= 3)

00384:         times = atoi(argv[2]);

00385:        DBG("Request Play times %d \n",times);

00386:     }

00387:

00388: /* get framebuffer phyaddr */

00389:     if(g2d_fb_init() != 0)

00390:        return -3;

00391:     fb_phy = finfo .smem_start;

00392:

00393: /* get pmem source addr */

00394:     pmem_base = mmap(NULL, G2D_SFR_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, g2d_fd , 0);

00395:     if(pmem_base == MAP_FAILED)

00396:     {

00397:        perror("mmap");

00398:        return -1;

00399:     }

00400:     memset(pmem_base,0, G2D_SFR_SIZE);

00401:

00402:     DBG("pmem_base = %p\n",pmem_base);

00403:

00404:

00405:     /* get image file */

00406:     rv = open_file_image(file_name,&image_fd,&file_len);

00407:     if(rv < 0)

00408:     {

00409:         return rv;

00410:     }

00411:

00412:     DBG("File[%s], size[%d], Frame[%d]\n",file_name,file_len,file_len/G2D_SFR_SIZE);

00413:

00414:     sleep(1);

00415:

00416:

00417:     gettimeofday(&start, NULL);

00418:     while(1)

00419:     {

00420:     /* Start: read the content of the image file to the mem */

00421:         rv = read(image_fd,pmem_base,G2D_SFR_SIZE);

00422:         if(rv > 0)

00423:         {

00424:

00425:             rv = s3c_g2d_copy_buffer(&params, (unsigned long)pmem_base, fb_phy);

00426:             if(rv)

00427:            break;

00428:        }

00429:        else

00430:         {

00431:            if(--times <= 0)

00432:            break;

00433:            lseek(image_fd,0,SEEK_SET);//seek to begin

00434:        }

00435:         frame++;

00436:     // DBG("times=%d, frame=%d\n",times,frame);

00437:     usleep(50000);

00438:     } ? end while 1 ?

00439:     gettimeofday(&end, NULL);

00440:     timeuse = 1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec - start.tv_usec;

00441:     timeuse/=1000;

00442:

00443:     DBG("Total Frame[%d], Total Time[%2.1f] ms,Time Pre Frame[%2.1f] ms\n",frame,timeuse,timeuse/frame);

00444:

00445:

00446:     //fb_info();

00447:

00448:     // printHex(file_name, pmem_base,128);

00449:     close(image_fd);

00450:     munmap(pmem_base,G2D_SFR_SIZE);

00451:

00452:

00453:     close(g2d_fd );

00454:     #ifdef FB0_OPERATION

00455:     close(fb0_fd );

00456:     #endif

00457:     close(fb1_fd );

00458:     return 0;

00459:} ? end main ?

00460:

最终测试的效果,当然要 上传一张啦。。

横着的条纹是win0, 竖着的条文是win1,COLVAL是黑色

win0是显示整屏幕,win1只有1/2屏幕,也可想成是win0旋转+缩放后得到的。

参考网站:

http://lxr.post-tech.com/source/drivers/media/video/samsung/g2d/?v=linux-2.6.29-eclairhttp://apps.hi.baidu.com/share/detail/17513887http://blogold.chinaunix.net/u3/111323/showart_2200014.htmlhttp://apps.hi.baidu.com/share/detail/17513859

http://apps.hi.baidu.com/share/detail/17513887

http://blogold.chinaunix.net/u3/111323/showart_2200014.html

http://apps.hi.baidu.com/share/detail/17513859

下面是常见问题的总结:

鱼 19:43:35

请问你的测试代码里面 SOURCE_FMT 与 DST_FMT 颜色模式 是什么?

鱼 19:43:45

6410手册里面讲的太不清楚,有几个寄存器的设置他就没讲清楚甚至没讲!

    1、DST_BASE_ADDR和SRC_BASE_ADDR要设置物理地址。不能是内核的虚拟地址或者应用程序中的地址。对于FB,要使用 dma_alloc_writecombine 第三个参数返回的物理地址 fbi->fix.smem_start。

鱼 19:56:26

怎么要设置成物理地址啊?

鱼 19:56:56

目的地址是framebuff 地址 而源地址怎么设置啊?

典当七秒的魚 08:55:36

是 颜色模式。

DST_FMT 是你驱动里使用的格式。像rgb565等。

 SOURCE_FMT  是你要显示的(在内存里)image的格式。

至于硬件支持哪几种 可转换的,你要看看数据手册了。

典当七秒的魚 08:57:37

硬件能处理的只有物理地址吧。我想。

因为你写进去的到下面寄存器的

DST_BASE_ADDR和SRC_BASE_ADDR

只能是物理 地址吧。。。这个地址是硬件能去访问的。

硬件的搬运负责吧原地址SRC_BASE_ADDR的数据 经过6步转换后,显示在DST_BASE_ADDR里面。

典当七秒的魚 08:58:45

我想着就是为何要用物理地址的原因。

你能找到 这个说明真的相当不错了

我当时可是在这里郁闷了好几天。。

因为 一直将虚拟地址写到  源地址。。

操作完成后一直黑屏 。。

鱼 09:09:59

就是这个帖子啊

http://blog.chinaunix.net/u3/111323/showart_2200014.html

鱼 09:10:24

那src_base 物理地址是怎么确定的呢?

典当七秒的魚 09:15:54

我是这样做的

在初始化的时候就分配好可用的,共享的内存。和显存差不多大, 主要用于 应用层 放src Image

驱动记录这个地址,并将其转换得到物理地址,用于src_base(其实,应用层会再次将此地址对应的虚拟地址写入,而驱动层将会舍弃此地址,因为是虚拟地址嘛),将虚拟地址传给应用层,应用层使用这个地址将src image写到这里地址(应用层能操作的就只能是虚拟地址,并且和内核层的不同。),因此对应的物理地址 的内容也相应的被应用填充了。

鱼 09:17:21

完全明白了 非常感谢

鱼 09:18:17

注:因为不知道如何将用户空间的虚拟地址转换为物理地址,只好在内核里面alloc了一块buffer s3c_g2d_userFB,每次都要用copy_from_user把图片先拷贝到s3c_g2d_userFB,再由2D搬到屏幕。

大概测试过一下,一张800*600的图片 copy_from_user 用了大概 4ms。2D搬到屏幕上用了大概5~6ms。还是想把copy_from_user给剩了!

鱼 09:18:39

这是刚才那个帖子里面提到的 方法估计和你一样的

典当七秒的魚 09:18:46

一样

典当七秒的魚 09:19:12

每次都要用copy_from_user把图片先拷贝到s3c_g2d_userFB  这个不用 。

鱼~BOBO 09:27:22

昨晚我也尝试把mmap 返回的虚拟地址在内核空间转换成物理地址 也是不行 我想说的是在内核空间分配的buff(虚拟地址) 与 mmap 映射返回到用户空间的虚拟地址有何不同 如果相同的话 昨晚的尝试就应该是成功的 谢谢

典当七秒的魚 09:31:40

使用setpagereserved就行了吧。。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zanget/archive/2010/11/18/6019528.aspx

原文地址:https://www.cnblogs.com/leaven/p/2079933.html