imx6 视频多层分屏显示

别来无恙 提交于 2019-12-23 18:15:15

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

//main.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdint.h>
#include <sys/types.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <unistd.h>
#include <asm/types.h>
#include <linux/videodev2.h>
#include <sys/mman.h>
#include <math.h>
#include <string.h>
#include <malloc.h>
#include <sys/time.h>
#include <signal.h>


#include "mxcfb.h"
#include "ipu.h"
#include "g2d.h"

#define G2D_CACHEABLE    1

#define TFAIL -1
#define TPASS 0

#define NUMBER_BUFFERS    3

char v4l_capture_dev[100] = "/dev/video0";
#ifdef BUILD_FOR_ANDROID
char fb_display_dev[100] = "/dev/graphics/fb1";
char fb_display_bg_dev[100] = "/dev/graphics/fb0";
#else
char fb_display_dev[100] = "/dev/fb1";
char fb_display_bg_dev[100] = "/dev/fb0";
#endif
int fd_capture_v4l = 0;
int fd_fb_display = 0;
int fd_ipu = 0;
unsigned char * g_fb_display = NULL;
int g_input = 1;
int g_display_num_buffers = 3;
int g_capture_num_buffers = NUMBER_BUFFERS;
int g_in_width = 1920;
int g_in_height = 720;
int g_in_fmt = V4L2_PIX_FMT_RGB565;
int g_display_width = 1920;
int g_display_height = 720;
int g_display_top = 0;
int g_display_left = 0;
int g_display_fmt = V4L2_PIX_FMT_RGB24;
int g_display_base_phy;
int g_display_size;
int g_display_fg = 1;
int g_display_id = 1;
struct fb_var_screeninfo g_screen_info;
int g_frame_count = 0x7FFFFFFF;
int g_frame_size;
bool g_g2d_render = 0;
int g_g2d_fmt;
int g_mem_type = V4L2_MEMORY_MMAP;

int g_in_mode = 0;

struct testbuffer
{
    unsigned char *start;
    size_t offset;
    unsigned int length;
};

struct testbuffer display_buffers[3];
struct testbuffer capture_buffers[NUMBER_BUFFERS];

int start_capturing(void)
{
    unsigned int i;
    struct v4l2_buffer buf;
    enum v4l2_buf_type type;

    for (i = 0; i < g_capture_num_buffers; i++) {
        memset(&buf, 0, sizeof (buf));
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = g_mem_type;
        buf.index = i;
        if (g_mem_type == V4L2_MEMORY_USERPTR) {
            buf.length = capture_buffers[i].length;
            buf.m.userptr = (unsigned long)capture_buffers[i].offset;
        }
        if (ioctl(fd_capture_v4l, VIDIOC_QUERYBUF, &buf) < 0) {
            printf("VIDIOC_QUERYBUF error\n");
            return TFAIL;
        }

        if (g_mem_type == V4L2_MEMORY_MMAP) {
            capture_buffers[i].length = buf.length;
            capture_buffers[i].offset = (size_t) buf.m.offset;
            capture_buffers[i].start = mmap(NULL, capture_buffers[i].length,
                                            PROT_READ | PROT_WRITE, MAP_SHARED,
                                            fd_capture_v4l, capture_buffers[i].offset);
            memset(capture_buffers[i].start, 0xFF, capture_buffers[i].length);
        }
    }

    for (i = 0; i < g_capture_num_buffers; i++) {
        memset(&buf, 0, sizeof (buf));
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = g_mem_type;
        buf.index = i;
        if (g_mem_type == V4L2_MEMORY_USERPTR)
            buf.m.offset = (unsigned int)capture_buffers[i].start;
        else
            buf.m.offset = capture_buffers[i].offset;
        buf.length = capture_buffers[i].length;
        if (ioctl(fd_capture_v4l, VIDIOC_QBUF, &buf) < 0) {
            printf("VIDIOC_QBUF error\n");
            return TFAIL;
        }
    }

    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl (fd_capture_v4l, VIDIOC_STREAMON, &type) < 0) {
        printf("VIDIOC_STREAMON error\n");
        return TFAIL;
    }
    return TPASS;
}

int prepare_display_buffers(void)
{
    int i;

    g_fb_display = (unsigned short *)mmap(0, g_display_size * g_display_num_buffers,
                                          PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb_display, 0);
    if (g_fb_display == NULL) {
        printf("v4l2 tvin test: display mmap failed\n");
        return TFAIL;
    }

    for (i = 0; i < g_display_num_buffers; i++) {
        display_buffers[i].length = g_display_size;
        display_buffers[i].offset = g_display_base_phy + g_display_size * i;
        display_buffers[i].start = g_fb_display + (g_display_size * i);
    }
    return TPASS;
}

int v4l_capture_setup(void)
{

    struct v4l2_capability cap;
    struct v4l2_cropcap cropcap;
    struct v4l2_control ctl;
    struct v4l2_crop crop;
    struct v4l2_format fmt;
    struct v4l2_requestbuffers req;
    struct v4l2_dbg_chip_ident chip;
    struct v4l2_streamparm parm;
    v4l2_std_id id;
    unsigned int min;

    if (ioctl (fd_capture_v4l, VIDIOC_QUERYCAP, &cap) < 0) {
        if (EINVAL == errno) {
            fprintf (stderr, "%s is no V4L2 device\n",
                     v4l_capture_dev);
            return TFAIL;
        } else {
            fprintf (stderr, "%s isn not V4L device,unknow error\n",
                     v4l_capture_dev);
            return TFAIL;
        }
    }

    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
        fprintf (stderr, "%s is no video capture device\n",
                 v4l_capture_dev);
        return TFAIL;
    }

    if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
        fprintf (stderr, "%s does not support streaming i/o\n",
                 v4l_capture_dev);
        return TFAIL;
    }

    if (ioctl(fd_capture_v4l, VIDIOC_S_INPUT, &g_input) < 0) {
        printf("VIDIOC_S_INPUT failed\n");
        close(fd_capture_v4l);
        return TFAIL;
    }

    memset(&cropcap, 0, sizeof(cropcap));
    cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl (fd_capture_v4l, VIDIOC_CROPCAP, &cropcap) < 0) {
        crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        crop.c = cropcap.defrect; /* reset to default */

        if (ioctl (fd_capture_v4l, VIDIOC_S_CROP, &crop) < 0) {
            switch (errno) {
            case EINVAL:
                /* Cropping not supported. */
                fprintf (stderr, "%s  doesn't support crop\n",
                         v4l_capture_dev);
                break;
            default:
                /* Errors ignored. */
                break;
            }
        }
    } else {
        /* Errors ignored. */
    }

    parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    parm.parm.capture.timeperframe.numerator = 1;
    parm.parm.capture.timeperframe.denominator = 0;
    parm.parm.capture.capturemode = 0;
    parm.parm.capture.extendedmode = g_in_mode;
    if (ioctl(fd_capture_v4l, VIDIOC_S_PARM, &parm) < 0) {
        printf("VIDIOC_S_PARM failed\n");
        close(fd_capture_v4l);
        return TFAIL;
    }

    memset(&fmt, 0, sizeof(fmt));

    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width = 0;
    fmt.fmt.pix.height = 0;
    fmt.fmt.pix.pixelformat = g_in_fmt;
    //fmt.fmt.pix.field = V4L2_FIELD_ANY;//V4L2_FIELD_INTERLACED
    fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
    if (ioctl (fd_capture_v4l, VIDIOC_S_FMT, &fmt) < 0) {
        fprintf(stderr, "%s iformat not supported \n",
                v4l_capture_dev);
        return TFAIL;
    }

    /* Note VIDIOC_S_FMT may change width and height. */

    /* Buggy driver paranoia. */
    min = fmt.fmt.pix.width * 2;
    if (fmt.fmt.pix.bytesperline < min)
        fmt.fmt.pix.bytesperline = min;

    min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
    if (fmt.fmt.pix.sizeimage < min)
        fmt.fmt.pix.sizeimage = min;

    if (ioctl(fd_capture_v4l, VIDIOC_G_FMT, &fmt) < 0) {
        printf("VIDIOC_G_FMT failed\n");
        close(fd_capture_v4l);
        return TFAIL;
    }

    g_in_width = fmt.fmt.pix.width;
    g_in_height = fmt.fmt.pix.height;
    printf("g_in_width = %d, g_in_height = %d.\r\n", g_in_width, g_in_height);

    memset(&req, 0, sizeof (req));
    req.count = g_capture_num_buffers;
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory = g_mem_type;
    if (ioctl (fd_capture_v4l, VIDIOC_REQBUFS, &req) < 0) {
        if (EINVAL == errno) {
            fprintf (stderr, "%s does not support "
                             "memory mapping\n", v4l_capture_dev);
            return TFAIL;
        } else {
            fprintf (stderr, "%s does not support "
                             "memory mapping, unknow error\n", v4l_capture_dev);
            return TFAIL;
        }
    }

    if (req.count < 2) {
        fprintf (stderr, "Insufficient buffer memory on %s\n",
                 v4l_capture_dev);
        return TFAIL;
    }

    return TPASS;
}

int fb_display_setup(void)
{
    int fd_fb_bg = 0;
    struct mxcfb_gbl_alpha alpha;
    char node[8];
    int retval = TPASS;
    struct fb_fix_screeninfo fb_fix;
    struct mxcfb_pos pos;

    if (ioctl(fd_fb_display, FBIOGET_VSCREENINFO, &g_screen_info) < 0) {
        printf("fb_display_setup FBIOGET_VSCREENINFO failed\n");
        return TFAIL;
    }

    if (ioctl(fd_fb_display, FBIOGET_FSCREENINFO, &fb_fix) < 0) {
        printf("fb_display_setup FBIOGET_FSCREENINFO failed\n");
        return TFAIL;
    }

    printf("fb_fix.id = %s.\r\n", fb_fix.id);
    if ((strcmp(fb_fix.id, "DISP4 FG") == 0) || (strcmp(fb_fix.id, "DISP3 FG") == 0))
    {
        g_display_fg = 1;

        pos.x = g_display_left;
        pos.y = g_display_top;

        if (ioctl(fd_fb_display, MXCFB_SET_OVERLAY_POS, &pos) < 0) {
            printf("fb_display_setup MXCFB_SET_OVERLAY_POS failed\n");
            return TFAIL;
        }

        if (!g_g2d_render) {
            g_screen_info.xres = g_display_width;
            g_screen_info.yres = g_display_height;
            //g_screen_info.xres = 1920;
            //g_screen_info.yres = 720;
            g_screen_info.yres_virtual = g_screen_info.yres * g_display_num_buffers;
            g_screen_info.xres_virtual = g_screen_info.xres ;
            g_screen_info.nonstd = g_display_fmt;
            if (ioctl(fd_fb_display, FBIOPUT_VSCREENINFO, &g_screen_info) < 0) {
                printf("fb_display_setup FBIOPUET_VSCREENINFO failed\n");
                return TFAIL;
            }

            ioctl(fd_fb_display, FBIOGET_FSCREENINFO, &fb_fix);
            ioctl(fd_fb_display, FBIOGET_VSCREENINFO, &g_screen_info);
        }

        sprintf(node, "%d", g_display_id - 1);	//for iMX6
#ifdef BUILD_FOR_ANDROID
        strcpy(fb_display_bg_dev, "/dev/graphics/fb");
#else
        strcpy(fb_display_bg_dev, "/dev/fb");
#endif
        strcat(fb_display_bg_dev, node);
        if ((fd_fb_bg = open(fb_display_bg_dev, O_RDWR )) < 0) {
            printf("Unable to open bg frame buffer\n");
            return TFAIL;
        }

        /* Overlay setting */
        alpha.alpha = 0;
        alpha.enable = 1;
        if (ioctl(fd_fb_bg, MXCFB_SET_GBL_ALPHA, &alpha) < 0) {
            printf("Set global alpha failed\n");
            close(fd_fb_bg);
            return TFAIL;
        }

    }

    ioctl(fd_fb_display, FBIOBLANK, FB_BLANK_UNBLANK);

    g_display_base_phy = fb_fix.smem_start;
    printf("fb: smem_start = 0x%x, smem_len = 0x%x.\r\n", (unsigned int)fb_fix.smem_start, (unsigned int)fb_fix.smem_len);

    g_display_size = g_screen_info.xres * g_screen_info.yres * g_screen_info.bits_per_pixel / 8;
    printf("fb: frame buffer size = 0x%x bytes.\r\n", g_display_size);

    printf("fb: g_screen_info.xres = %d, g_screen_info.yres = %d.\r\n", g_screen_info.xres, g_screen_info.yres);
    printf("fb: g_display_left = %d.\r\n", g_display_left);
    printf("fb: g_display_top = %d.\r\n", g_display_top);
    printf("fb: g_display_width = %d.\r\n", g_display_width);
    printf("fb: g_display_height = %d.\r\n", g_display_height);

    return TPASS;
}

int mxc_v4l_tvin_test(void)
{
    struct v4l2_buffer capture_buf;
    int i, j;
    enum v4l2_buf_type type;
    struct ipu_task task;
    int total_time;
    struct timeval tv_start, tv_current;
    int display_buf_count = 0;


    if (prepare_display_buffers() < 0) {
        printf("prepare_display_buffers failed\n");
        return TFAIL;
    }


    if (start_capturing() < 0) {
        printf("start_capturing failed\n");
        return TFAIL;
    }

        if (!g_g2d_render) {
            memset(&task, 0, sizeof(struct ipu_task));
            task.output.width = g_display_width;
            task.output.height = g_display_height;
            task.output.crop.w = g_display_width;
            task.output.crop.h = g_display_height;
            task.output.format = g_display_fmt;

            task.input.width  = g_in_width;
            task.input.height = g_in_height;
            task.input.crop.w = g_in_width;
            task.input.crop.h = g_in_height;
            task.input.format = g_in_fmt;

            task.input.paddr = capture_buffers[0].offset;
            task.output.paddr = display_buffers[0].offset;

            if (ioctl(fd_ipu, IPU_CHECK_TASK, &task) != IPU_CHECK_OK) {
                printf("IPU_CHECK_TASK failed.\r\n");
                return TFAIL;
            }
        }

    gettimeofday(&tv_start, 0);
    printf("start time = %d s, %d us\n", (unsigned int) tv_start.tv_sec,
           (unsigned int) tv_start.tv_usec);



    for (i = 0; i < g_frame_count; i++)
    {
        memset(&capture_buf, 0, sizeof(capture_buf));
        capture_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        capture_buf.memory = g_mem_type;
        if (ioctl(fd_capture_v4l, VIDIOC_DQBUF, &capture_buf) < 0) {
            printf("VIDIOC_DQBUF failed.\n");
            return TFAIL;
        }


                task.input.paddr = capture_buffers[capture_buf.index].offset;
                task.output.paddr = display_buffers[display_buf_count].offset;
                if ((task.input.paddr != 0) && (task.output.paddr != 0))
                {
                    if (ioctl(fd_ipu, IPU_QUEUE_TASK, &task) < 0) {
                        printf("IPU_QUEUE_TASK failed\n");
                        return TFAIL;
                    }
                }


        if (ioctl(fd_capture_v4l, VIDIOC_QBUF, &capture_buf) < 0) {
            printf("VIDIOC_QBUF failed\n");
            return TFAIL;
        }

        if (!g_g2d_render)
        {
//            g_screen_info.xoffset = 0;
//            g_screen_info.yoffset = display_buf_count * g_display_height;
//            if (ioctl(fd_fb_display, FBIOPAN_DISPLAY, &g_screen_info) < 0) {
//                printf("FBIOPAN_DISPLAY failed, count = %d\n", i);
//                break;
//            }
            display_buf_count ++;
            if (display_buf_count >= g_display_num_buffers)
                display_buf_count = 0;

            display_buffers[0].start = display_buffers[(display_buf_count+1)%3].start;

        }
    }

    gettimeofday(&tv_current, 0);
    total_time = (tv_current.tv_sec - tv_start.tv_sec) * 1000000L;
    total_time += tv_current.tv_usec - tv_start.tv_usec;
    printf("total time for %u frames = %u us =  %lld fps\n", i, total_time, (i * 1000000ULL) / total_time);

    return TPASS;
}

int process_cmdline(int argc, char **argv)
{
    int i, val;
    char node[8];

    for (i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-ow") == 0) {
            g_display_width = atoi(argv[++i]);
        }
        else if (strcmp(argv[i], "-oh") == 0) {
            g_display_height = atoi(argv[++i]);
        }
        else if (strcmp(argv[i], "-ot") == 0) {
            g_display_top = atoi(argv[++i]);
        }
        else if (strcmp(argv[i], "-ol") == 0) {
            g_display_left = atoi(argv[++i]);
        }
        else if (strcmp(argv[i], "-c") == 0) {
            g_frame_count = atoi(argv[++i]);
        }
        else if (strcmp(argv[i], "-g2d") == 0) {
            g_g2d_render = 1;
            g_mem_type = V4L2_MEMORY_USERPTR;
        }
        else if (strcmp(argv[i], "-im") == 0) {
            g_in_mode = atoi(argv[++i]);
        }
        else if (strcmp(argv[i], "-x") == 0) {
            val = atoi(argv[++i]);
            sprintf(node, "%d", val);
            strcpy(v4l_capture_dev, "/dev/video");
            strcat(v4l_capture_dev, node);
        }
        else if (strcmp(argv[i], "-d") == 0) {
            val = atoi(argv[++i]);
            g_display_id = val;
            sprintf(node, "%d", val);
#ifdef BUILD_FOR_ANDROID
            strcpy(fb_display_dev, "/dev/graphics/fb");
#else
            strcpy(fb_display_dev, "/dev/fb");
#endif
            strcat(fb_display_dev, node);
        }
        else if (strcmp(argv[i], "-if") == 0) {
            i++;
            g_in_fmt = v4l2_fourcc(argv[i][0], argv[i][1],argv[i][2],argv[i][3]);
            if ((g_in_fmt != V4L2_PIX_FMT_NV12) &&
                    (g_in_fmt != V4L2_PIX_FMT_UYVY) &&
                    (g_in_fmt != V4L2_PIX_FMT_YUYV) &&
                    (g_in_fmt != V4L2_PIX_FMT_YUV420)) {
                printf("Default capture format is used: UYVY\n");
                g_in_fmt = V4L2_PIX_FMT_UYVY;
            }
        }
        else if (strcmp(argv[i], "-of") == 0) {
            i++;
            g_display_fmt = v4l2_fourcc(argv[i][0], argv[i][1],argv[i][2],argv[i][3]);
            if ((g_display_fmt != V4L2_PIX_FMT_RGB565) &&
                    (g_display_fmt != V4L2_PIX_FMT_RGB24) &&
                    (g_display_fmt != V4L2_PIX_FMT_RGB32) &&
                    (g_display_fmt != V4L2_PIX_FMT_BGR32) &&
                    (g_display_fmt != V4L2_PIX_FMT_UYVY) &&
                    (g_display_fmt != V4L2_PIX_FMT_YUYV)) {
                printf("Default display format is used: UYVY\n");
                g_display_fmt = V4L2_PIX_FMT_UYVY;
            }
        }
        else if (strcmp(argv[i], "-help") == 0) {
            printf("MXC Video4Linux TVin Test\n\n" \
                   "Syntax: mxc_v4l2_tvin.out\n" \
                   " -ow <capture display width>\n" \
                   " -oh <capture display height>\n" \
                   " -ot <display top>\n" \
                   " -ol <display left>\n" \
                   " -g2d <GPU g2d render> \n" \
                   " -c <capture counter> \n" \
                   " -x <capture device> 0 = /dev/video0; 1 = /dev/video1 ...>\n" \
                   " -d <output frame buffer> 0 = /dev/fb0; 1 = /dev/fb1 ...>\n" \
                   " -if <capture format, only YU12, YUYV, UYVY and NV12 are supported> \n" \
                   " -of <display format, only RGBP, RGB3, RGB4, BGR4, YUYV, and UYVY are supported> \n");
            return TFAIL;
        }
    }

    if ((g_display_width == 0) || (g_display_height == 0)) {
        printf("Zero display width or height\n");
        return TFAIL;
    }

    return TPASS;
}

void signal_handle(int signal)
{
    printf("Signal : %d", signal);
    exit(1);
}

int main(int argc, char **argv)
{
    int i;
    enum v4l2_buf_type type;
    signal(SIGKILL, signal_handle);

    if (process_cmdline(argc, argv) < 0) {
        return TFAIL;
    }

    if ((fd_capture_v4l = open(v4l_capture_dev, O_RDWR, 0)) < 0) {
        printf("Unable to open %s\n", v4l_capture_dev);
        return TFAIL;
    }

    if (v4l_capture_setup() < 0) {
        printf("Setup v4l capture failed.\n");
        return TFAIL;
    }

    if (!g_g2d_render) {
        if ((fd_ipu = open("/dev/mxc_ipu", O_RDWR, 0)) < 0) {
            printf("open ipu dev fail\n");
            close(fd_capture_v4l);
            return TFAIL;
        }
    }

    if ((fd_fb_display = open(fb_display_dev, O_RDWR, 0)) < 0) {
        printf("Unable to open %s\n", fb_display_dev);
        close(fd_ipu);
        close(fd_capture_v4l);
        return TFAIL;
    }

    if (fb_display_setup() < 0) {
        printf("Setup fb display failed.\n");
        close(fd_ipu);
        close(fd_capture_v4l);
        close(fd_fb_display);
        return TFAIL;
    }

    mxc_v4l_tvin_test();

    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ioctl(fd_capture_v4l, VIDIOC_STREAMOFF, &type);

    if (g_display_fg)
        ioctl(fd_fb_display, FBIOBLANK, FB_BLANK_NORMAL);


    munmap(g_fb_display, g_display_size * g_display_num_buffers);

    for (i = 0; i < g_capture_num_buffers; i++) {
        munmap(capture_buffers[i].start, capture_buffers[i].length);
    }


    close(fd_ipu);
    close(fd_capture_v4l);
    close(fd_fb_display);
    return 0;
}


//iph.h


#ifndef __ASM_ARCH_IPU_H__
#define __ASM_ARCH_IPU_H__

#include <linux/types.h>
#include <linux/videodev2.h>

#ifndef __KERNEL__
#ifndef __cplusplus
typedef unsigned char bool;
#endif
#define irqreturn_t int
#define dma_addr_t int
#define uint32_t unsigned int
#define uint16_t unsigned short
#define uint8_t unsigned char
#define u32 unsigned int
#define u8 unsigned char
#define __u32 u32
#endif

/*!
 * Enumeration of IPU rotation modes
 */
typedef enum {
	/* Note the enum values correspond to BAM value */
	IPU_ROTATE_NONE = 0,
	IPU_ROTATE_VERT_FLIP = 1,
	IPU_ROTATE_HORIZ_FLIP = 2,
	IPU_ROTATE_180 = 3,
	IPU_ROTATE_90_RIGHT = 4,
	IPU_ROTATE_90_RIGHT_VFLIP = 5,
	IPU_ROTATE_90_RIGHT_HFLIP = 6,
	IPU_ROTATE_90_LEFT = 7,
} ipu_rotate_mode_t;

/*!
 * Enumeration of VDI MOTION select
 */
typedef enum {
	MED_MOTION = 0,
	LOW_MOTION = 1,
	HIGH_MOTION = 2,
} ipu_motion_sel;

/*!
 * Enumeration of DI ports for ADC.
 */
typedef enum {
	DISP0,
	DISP1,
	DISP2,
	DISP3
} display_port_t;

/*  IPU Pixel format definitions */
/*  Four-character-code (FOURCC) */
#define fourcc(a, b, c, d)\
	 (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))

/*!
 * @name IPU Pixel Formats
 *
 * Pixel formats are defined with ASCII FOURCC code. The pixel format codes are
 * the same used by V4L2 API.
 */

/*! @{ */
/*! @name Generic or Raw Data Formats */
/*! @{ */
#define IPU_PIX_FMT_GENERIC fourcc('I', 'P', 'U', '0')	/*!< IPU Generic Data */
#define IPU_PIX_FMT_GENERIC_32 fourcc('I', 'P', 'U', '1')	/*!< IPU Generic Data */
#define IPU_PIX_FMT_GENERIC_16 fourcc('I', 'P', 'U', '2')	/*!< IPU Generic Data */
#define IPU_PIX_FMT_LVDS666 fourcc('L', 'V', 'D', '6')	/*!< IPU Generic Data */
#define IPU_PIX_FMT_LVDS888 fourcc('L', 'V', 'D', '8')	/*!< IPU Generic Data */
/*! @} */
/*! @name RGB Formats */
/*! @{ */
#define IPU_PIX_FMT_RGB332  fourcc('R', 'G', 'B', '1')	/*!<  8  RGB-3-3-2    */
#define IPU_PIX_FMT_RGB555  fourcc('R', 'G', 'B', 'O')	/*!< 16  RGB-5-5-5    */
#define IPU_PIX_FMT_RGB565  fourcc('R', 'G', 'B', 'P')	/*!< 1 6  RGB-5-6-5   */
#define IPU_PIX_FMT_RGB666  fourcc('R', 'G', 'B', '6')	/*!< 18  RGB-6-6-6    */
#define IPU_PIX_FMT_BGR666  fourcc('B', 'G', 'R', '6')	/*!< 18  BGR-6-6-6    */
#define IPU_PIX_FMT_BGR24   fourcc('B', 'G', 'R', '3')	/*!< 24  BGR-8-8-8    */
#define IPU_PIX_FMT_RGB24   fourcc('R', 'G', 'B', '3')	/*!< 24  RGB-8-8-8    */
#define IPU_PIX_FMT_GBR24   fourcc('G', 'B', 'R', '3')	/*!< 24  GBR-8-8-8    */
#define IPU_PIX_FMT_BGR32   fourcc('B', 'G', 'R', '4')	/*!< 32  BGR-8-8-8-8  */
#define IPU_PIX_FMT_BGRA32  fourcc('B', 'G', 'R', 'A')	/*!< 32  BGR-8-8-8-8  */
#define IPU_PIX_FMT_RGB32   fourcc('R', 'G', 'B', '4')	/*!< 32  RGB-8-8-8-8  */
#define IPU_PIX_FMT_RGBA32  fourcc('R', 'G', 'B', 'A')	/*!< 32  RGB-8-8-8-8  */
#define IPU_PIX_FMT_ABGR32  fourcc('A', 'B', 'G', 'R')	/*!< 32  ABGR-8-8-8-8 */
/*! @} */
/*! @name YUV Interleaved Formats */
/*! @{ */
#define IPU_PIX_FMT_YUYV    fourcc('Y', 'U', 'Y', 'V')	/*!< 16 YUV 4:2:2 */
#define IPU_PIX_FMT_UYVY    fourcc('U', 'Y', 'V', 'Y')	/*!< 16 YUV 4:2:2 */
#define IPU_PIX_FMT_YVYU    fourcc('Y', 'V', 'Y', 'U')  /*!< 16 YVYU 4:2:2 */
#define IPU_PIX_FMT_VYUY    fourcc('V', 'Y', 'U', 'Y')  /*!< 16 VYYU 4:2:2 */
#define IPU_PIX_FMT_Y41P    fourcc('Y', '4', '1', 'P')	/*!< 12 YUV 4:1:1 */
#define IPU_PIX_FMT_YUV444  fourcc('Y', '4', '4', '4')	/*!< 24 YUV 4:4:4 */
#define IPU_PIX_FMT_VYU444  fourcc('V', '4', '4', '4')	/*!< 24 VYU 4:4:4 */
/* two planes -- one Y, one Cb + Cr interleaved  */
#define IPU_PIX_FMT_NV12    fourcc('N', 'V', '1', '2') /* 12  Y/CbCr 4:2:0  */
/* two planes -- 12  tiled Y/CbCr 4:2:0  */
#define IPU_PIX_FMT_TILED_NV12    fourcc('T', 'N', 'V', 'P')
#define IPU_PIX_FMT_TILED_NV12F   fourcc('T', 'N', 'V', 'F')

/*! @} */
/*! @name YUV Planar Formats */
/*! @{ */
#define IPU_PIX_FMT_GREY    fourcc('G', 'R', 'E', 'Y')	/*!< 8  Greyscale */
#define IPU_PIX_FMT_YVU410P fourcc('Y', 'V', 'U', '9')	/*!< 9  YVU 4:1:0 */
#define IPU_PIX_FMT_YUV410P fourcc('Y', 'U', 'V', '9')	/*!< 9  YUV 4:1:0 */
#define IPU_PIX_FMT_YVU420P fourcc('Y', 'V', '1', '2')	/*!< 12 YVU 4:2:0 */
#define IPU_PIX_FMT_YUV420P fourcc('I', '4', '2', '0')	/*!< 12 YUV 4:2:0 */
#define IPU_PIX_FMT_YUV420P2 fourcc('Y', 'U', '1', '2')	/*!< 12 YUV 4:2:0 */
#define IPU_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6')	/*!< 16 YVU 4:2:2 */
#define IPU_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P')	/*!< 16 YUV 4:2:2 */
/* non-interleaved 4:4:4 */
#define IPU_PIX_FMT_YUV444P fourcc('4', '4', '4', 'P')	/*!< 24 YUV 4:4:4 */
/*! @} */
#define IPU_PIX_FMT_TILED_NV12_MBALIGN	(16)
#define TILED_NV12_FRAME_SIZE(w, h)	\
		(ALIGN((w) * (h), SZ_4K) + ALIGN((w) * (h) / 2, SZ_4K))
/* IPU device */
typedef enum {
	RGB_CS,
	YUV_CS,
	NULL_CS
} cs_t;

struct ipu_pos {
	u32 x;
	u32 y;
};

struct ipu_crop {
	struct ipu_pos pos;
	u32 w;
	u32 h;
};

struct ipu_deinterlace {
	bool	enable;
	u8	motion; /*see ipu_motion_sel*/
#define IPU_DEINTERLACE_FIELD_TOP	0
#define IPU_DEINTERLACE_FIELD_BOTTOM	1
#define IPU_DEINTERLACE_FIELD_MASK	\
		(IPU_DEINTERLACE_FIELD_TOP | IPU_DEINTERLACE_FIELD_BOTTOM)
	/* deinterlace frame rate double flags */
#define IPU_DEINTERLACE_RATE_EN		0x80
#define IPU_DEINTERLACE_RATE_FRAME1	0x40
#define IPU_DEINTERLACE_RATE_MASK	\
		(IPU_DEINTERLACE_RATE_EN | IPU_DEINTERLACE_RATE_FRAME1)
#define IPU_DEINTERLACE_MAX_FRAME	2
	u8	field_fmt;
};

struct ipu_input {
	u32 width;
	u32 height;
	u32 format;
	struct ipu_crop crop;
	dma_addr_t paddr;

	struct ipu_deinterlace deinterlace;
	dma_addr_t paddr_n; /*valid when deinterlace enable*/
};

struct ipu_alpha {
#define IPU_ALPHA_MODE_GLOBAL	0
#define IPU_ALPHA_MODE_LOCAL	1
	u8 mode;
	u8 gvalue; /* 0~255 */
	dma_addr_t loc_alp_paddr;
};

struct ipu_colorkey {
	bool enable;
	u32 value; /* RGB 24bit */
};

struct ipu_overlay {
	u32	width;
	u32	height;
	u32	format;
	struct ipu_crop crop;
	struct ipu_alpha alpha;
	struct ipu_colorkey colorkey;
	dma_addr_t paddr;
};

struct ipu_output {
	u32	width;
	u32	height;
	u32	format;
	u8	rotate;
	struct ipu_crop crop;
	dma_addr_t paddr;
};

struct ipu_task {
	struct ipu_input input;
	struct ipu_output output;

	bool overlay_en;
	struct ipu_overlay overlay;

#define IPU_TASK_PRIORITY_NORMAL 0
#define IPU_TASK_PRIORITY_HIGH	1
	u8	priority;

#define	IPU_TASK_ID_ANY	0
#define	IPU_TASK_ID_VF	1
#define	IPU_TASK_ID_PP	2
#define	IPU_TASK_ID_MAX 3
	u8	task_id;

	int	timeout;
};

enum {
	IPU_CHECK_OK = 0,
	IPU_CHECK_WARN_INPUT_OFFS_NOT8ALIGN = 0x1,
	IPU_CHECK_WARN_OUTPUT_OFFS_NOT8ALIGN = 0x2,
	IPU_CHECK_WARN_OVERLAY_OFFS_NOT8ALIGN = 0x4,
	IPU_CHECK_ERR_MIN,
	IPU_CHECK_ERR_INPUT_CROP,
	IPU_CHECK_ERR_OUTPUT_CROP,
	IPU_CHECK_ERR_OVERLAY_CROP,
	IPU_CHECK_ERR_INPUT_OVER_LIMIT,
	IPU_CHECK_ERR_OV_OUT_NO_FIT,
	IPU_CHECK_ERR_OVERLAY_WITH_VDI,
	IPU_CHECK_ERR_PROC_NO_NEED,
	IPU_CHECK_ERR_SPLIT_INPUTW_OVER,
	IPU_CHECK_ERR_SPLIT_INPUTH_OVER,
	IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER,
	IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER,
	IPU_CHECK_ERR_SPLIT_WITH_ROT,
	IPU_CHECK_ERR_NOT_SUPPORT,
	IPU_CHECK_ERR_NOT16ALIGN,
	IPU_CHECK_ERR_W_DOWNSIZE_OVER,
	IPU_CHECK_ERR_H_DOWNSIZE_OVER,
};

/* IOCTL commands */
#define IPU_CHECK_TASK		_IOWR('I', 0x1, struct ipu_task)
#define IPU_QUEUE_TASK		_IOW('I', 0x2, struct ipu_task)
#define IPU_ALLOC		_IOWR('I', 0x3, int)
#define IPU_FREE		_IOW('I', 0x4, int)

#endif




//mxcfb.h


#ifndef __ASM_ARCH_MXCFB_H__
#define __ASM_ARCH_MXCFB_H__

#include <linux/fb.h>

#define FB_SYNC_OE_LOW_ACT	0x80000000
#define FB_SYNC_CLK_LAT_FALL	0x40000000
#define FB_SYNC_DATA_INVERT	0x20000000
#define FB_SYNC_CLK_IDLE_EN	0x10000000
#define FB_SYNC_SHARP_MODE	0x08000000
#define FB_SYNC_SWAP_RGB	0x04000000
#define FB_ACCEL_TRIPLE_FLAG	0x00000000
#define FB_ACCEL_DOUBLE_FLAG	0x00000001

struct mxcfb_gbl_alpha {
	int enable;
	int alpha;
};

struct mxcfb_loc_alpha {
	int enable;
	int alpha_in_pixel;
	unsigned long alpha_phy_addr0;
	unsigned long alpha_phy_addr1;
};

struct mxcfb_color_key {
	int enable;
	__u32 color_key;
};

struct mxcfb_pos {
	__u16 x;
	__u16 y;
};

struct mxcfb_gamma {
	int enable;
	int constk[16];
	int slopek[16];
};

struct mxcfb_rect {
	__u32 top;
	__u32 left;
	__u32 width;
	__u32 height;
};

#define GRAYSCALE_8BIT				0x1
#define GRAYSCALE_8BIT_INVERTED			0x2
#define GRAYSCALE_4BIT                          0x3
#define GRAYSCALE_4BIT_INVERTED                 0x4

#define AUTO_UPDATE_MODE_REGION_MODE		0
#define AUTO_UPDATE_MODE_AUTOMATIC_MODE		1

#define UPDATE_SCHEME_SNAPSHOT			0
#define UPDATE_SCHEME_QUEUE			1
#define UPDATE_SCHEME_QUEUE_AND_MERGE		2

#define UPDATE_MODE_PARTIAL			0x0
#define UPDATE_MODE_FULL			0x1

#define WAVEFORM_MODE_AUTO			257

#define TEMP_USE_AMBIENT			0x1000

#define EPDC_FLAG_ENABLE_INVERSION		0x01
#define EPDC_FLAG_FORCE_MONOCHROME		0x02
#define EPDC_FLAG_USE_CMAP			0x04
#define EPDC_FLAG_USE_ALT_BUFFER		0x100
#define EPDC_FLAG_TEST_COLLISION		0x200
#define EPDC_FLAG_GROUP_UPDATE			0x400
#define EPDC_FLAG_USE_DITHERING_Y1		0x2000
#define EPDC_FLAG_USE_DITHERING_Y4		0x4000

#define FB_POWERDOWN_DISABLE			-1

struct mxcfb_alt_buffer_data {
	__u32 phys_addr;
	__u32 width;	/* width of entire buffer */
	__u32 height;	/* height of entire buffer */
	struct mxcfb_rect alt_update_region;	/* region within buffer to update */
};

struct mxcfb_update_data {
	struct mxcfb_rect update_region;
	__u32 waveform_mode;
	__u32 update_mode;
	__u32 update_marker;
	int temp;
	unsigned int flags;
	struct mxcfb_alt_buffer_data alt_buffer_data;
};

struct mxcfb_update_marker_data {
	__u32 update_marker;
	__u32 collision_test;
};

/*
 * Structure used to define waveform modes for driver
 * Needed for driver to perform auto-waveform selection
 */
struct mxcfb_waveform_modes {
	int mode_init;
	int mode_du;
	int mode_gc4;
	int mode_gc8;
	int mode_gc16;
	int mode_gc32;
};

/*
 * Structure used to define a 5*3 matrix of parameters for
 * setting IPU DP CSC module related to this framebuffer.
 */
struct mxcfb_csc_matrix {
	int param[5][3];
};

#define MXCFB_WAIT_FOR_VSYNC	_IOW('F', 0x20, u_int32_t)
#define MXCFB_SET_GBL_ALPHA     _IOW('F', 0x21, struct mxcfb_gbl_alpha)
#define MXCFB_SET_CLR_KEY       _IOW('F', 0x22, struct mxcfb_color_key)
#define MXCFB_SET_OVERLAY_POS   _IOWR('F', 0x24, struct mxcfb_pos)
#define MXCFB_GET_FB_IPU_CHAN 	_IOR('F', 0x25, u_int32_t)
#define MXCFB_SET_LOC_ALPHA     _IOWR('F', 0x26, struct mxcfb_loc_alpha)
#define MXCFB_SET_LOC_ALP_BUF    _IOW('F', 0x27, unsigned long)
#define MXCFB_SET_GAMMA	       _IOW('F', 0x28, struct mxcfb_gamma)
#define MXCFB_GET_FB_IPU_DI 	_IOR('F', 0x29, u_int32_t)
#define MXCFB_GET_DIFMT	       _IOR('F', 0x2A, u_int32_t)
#define MXCFB_GET_FB_BLANK     _IOR('F', 0x2B, u_int32_t)
#define MXCFB_SET_DIFMT		_IOW('F', 0x2C, u_int32_t)
#define MXCFB_CSC_UPDATE	_IOW('F', 0x2D, struct mxcfb_csc_matrix)

/* IOCTLs for E-ink panel updates */
#define MXCFB_SET_WAVEFORM_MODES	_IOW('F', 0x2B, struct mxcfb_waveform_modes)
#define MXCFB_SET_TEMPERATURE		_IOW('F', 0x2C, int32_t)
#define MXCFB_SET_AUTO_UPDATE_MODE	_IOW('F', 0x2D, __u32)
#define MXCFB_SEND_UPDATE		_IOW('F', 0x2E, struct mxcfb_update_data)
#define MXCFB_WAIT_FOR_UPDATE_COMPLETE	_IOWR('F', 0x2F, struct mxcfb_update_marker_data)
#define MXCFB_SET_PWRDOWN_DELAY		_IOW('F', 0x30, int32_t)
#define MXCFB_GET_PWRDOWN_DELAY		_IOR('F', 0x31, int32_t)
#define MXCFB_SET_UPDATE_SCHEME		_IOW('F', 0x32, __u32)
#define MXCFB_GET_WORK_BUFFER		_IOWR('F', 0x34, unsigned long)
#define MXCFB_DISABLE_EPDC_ACCESS	_IO('F', 0x35)
#define MXCFB_ENABLE_EPDC_ACCESS	_IO('F', 0x36)
#endif

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!