首页 > 代码库 > s5pv210 linux hdmi tv输出

s5pv210 linux hdmi tv输出

原来本来说是不公开源码的 现在发现也没什么价值了 以下公布的源码支持linux3.0 linux2.6内核 linux3.1内核v4l2构架发生了变化 同时支持hdmi输出与tv输出 使用的板子是 斯道icool210

源码是根据android里的libhdmi库进行整理的 这里是基于linux2.6.35内核测试成功

/*
 * hidmitest.c
 *
 * hclydao<hclydao@163.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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h>  
#include <fcntl.h>  
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <linux/videodev2.h>
#include <linux/fb.h>
#include "videodev2_samsung.h"

#define HDMI_DEV	"/dev/video14"
#define TVOUT_DEV0	"/dev/video22"
#define FIMC_DEV	"/dev/video2"

#define CLEAR(x) memset (&(x), 0, sizeof (x))
#define ALIGN(x, a)    (((x) + (a) - 1) & ~((a) - 1))
static int fd = -1;
v4l2_std_id std_id = 0;
static int m_width = 0;
static int m_height = 0;
#define LCD_DEV		"/dev/fb0"
#define S3CFB_GET_LCD_ADDR              _IOR ('F', 311, int)

unsigned int phyLCDAddr = 0;
unsigned int physYAddr = 0;
static int lcd_fd = -1;
static int ov_fd = -1;
static int fimc_fd = -1;
unsigned int mFimcRrvedPhysMemAddr;
unsigned int hwver;
static int out_w = 0;
static int out_h = 0;

struct overlay_param {
	struct v4l2_framebuffer 		overlay_frame;
	struct v4l2_window_s5p_tvout 	overlay_rect;
	struct v4l2_rect				overlay_dst;
};

typedef unsigned int dma_addr_t;
struct fimc_buf {
	dma_addr_t	base[3];
 	size_t		length[3];
};

int lcd_open()
{
	lcd_fd = open(LCD_DEV,O_RDWR, 0);
	if(lcd_fd < 0) {
		printf("++++++open tvout dev error\n");
		return -1;
	}
	return lcd_fd;
}

int lcd_getaddr()
{
	struct fb_var_screeninfo info;
	if (ioctl(lcd_fd, S3CFB_GET_LCD_ADDR, &phyLCDAddr) == -1) {
		printf("%s:ioctl(S3CFB_GET_LCD_ADDR) fail\n", __func__);
		return -1;
	}
	if(phyLCDAddr == 0) {
		printf("%s::S3CFB_GET_LCD_ADDR fail \n", __func__);
		return -1;
	}
           
    if (ioctl(lcd_fd, FBIOGET_VSCREENINFO, &info) == -1) {
    	printf("%s:ioctl(FBIOGET_VSCREENINFO) fail\n", __func__);
        return -1;
    } 
    m_width   =  info.xres;
    m_height  =  info.yres;
	return 0;
}

int hdmi_open()
{
	fd = open(HDMI_DEV, O_RDWR);
	if(fd < 0) {
		printf("++++++open tvout dev error\n");
		return fd;
	}
	return fd;
}

int tvout_v4l2_querycap(void)
{
    struct v4l2_capability cap;
    int ret;

    ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);

    if (ret < 0) {
	    printf("tvout_v4l2_querycap VIDIOC_QUERYCAP failed %d\n", errno);
	    return ret;
    }

    //printf("tvout_v4l2_querycap DRIVER : %s, CARD : %s, CAP.: 0x%08x\n",
		//    cap.driver, cap.card, cap.capabilities);
    return ret;
}

int tvout_v4l2_s_std(void)
{
    int ret;

    ret = ioctl(fd, VIDIOC_S_STD, &std_id);
    if (ret < 0) {
	    printf("tvout_v4l2_s_std" "VIDIOC_S_STD failed %d\n", errno);
	    return ret;
    }
    return ret;
}

int tvout_v4l2_enum_output(struct v4l2_output *output)
{
    int ret;

    ret = ioctl(fd, VIDIOC_ENUMOUTPUT, output);

    return ret;
}

int tvout_v4l2_s_output(int index)
{
    int ret;

    ret = ioctl(fd, VIDIOC_S_OUTPUT, &index);
    if (ret < 0) {
	    printf("tvout_v4l2_s_output" "VIDIOC_S_OUTPUT failed %d\n", errno);
	    return ret;
    }

    return ret;
}

int overlay_open()
{
	ov_fd = open(TVOUT_DEV0, O_RDWR);
	if(ov_fd < 0) {
		printf("++++++open tv out 0 dev error\n");
		return ov_fd;
	}
	return ov_fd;
}

int tvout_ov_s_parm(int fp, int buf_type, void *ptr)
{
    struct v4l2_streamparm parm;
    struct v4l2_window_s5p_tvout *vparm = (struct v4l2_window_s5p_tvout*)ptr;
    int ret;

    parm.type = (enum v4l2_buf_type)buf_type;
    memcpy(parm.parm.raw_data, vparm, sizeof(struct v4l2_window_s5p_tvout));

    ret = ioctl(fp, VIDIOC_S_PARM, &parm);
    if (ret < 0) {
	    printf("tvout_v4l2_s_parm" "VIDIOC_S_PARM failed %d\n", errno);
	    return ret;
    }

    return 0;
}

int tvout_v4l2_s_fbuf(int fp, struct v4l2_framebuffer *frame)
{
    int ret;

    ret = ioctl(fp, VIDIOC_S_FBUF, frame);
    if (ret < 0) {
	    printf("tvout_v4l2_s_fbuf" "VIDIOC_STREAMON failed %d\n", errno);
	    return ret;
    }
    return 0;
}

int tvout_v4l2_cropcap(int fp, struct v4l2_cropcap *a)
{
    struct v4l2_cropcap *cropcap = a;
    int ret;

    ret = ioctl(fp, VIDIOC_CROPCAP, cropcap);

    if (ret < 0) {
        printf("tvout_v4l2_cropcap" "VIDIOC_CROPCAP failed %d\n", errno);
        return ret;
    }

    printf("tvout_v4l2_cropcap" "bound width : %d, bound height : %d,\n",
		    cropcap->bounds.width, cropcap->bounds.height);
    return ret;
}

int tvout_ov_s_crop(int fp, unsigned int type, struct v4l2_rect *rect)
{
    struct v4l2_crop crop;
    int ret;

    crop.type 	= (enum v4l2_buf_type)type;

    crop.c.left 	= rect->left;
    crop.c.top 	    = rect->top;
    crop.c.width 	= rect->width;
    crop.c.height 	= rect->height;

    ret = ioctl(fp, VIDIOC_S_CROP, &crop);
    if (ret < 0) {
	    printf("tvout_v4l2_s_crop" "VIDIOC_S_CROP failed %d\n", errno);
	    return ret;
    }

    return 0;
}

int tvout_v4l2_set_overlay(int fp)
{
    struct overlay_param ov_param;
	struct v4l2_cropcap cropcap;

	int dst_w,dst_h;

	dst_w = out_w;
	dst_h = out_h;

    ov_param.overlay_frame.fmt.pixelformat = V4L2_PIX_FMT_RGB32;
    ov_param.overlay_frame.base            = (void *)mFimcRrvedPhysMemAddr;

    ov_param.overlay_rect.flags            = 0;
    ov_param.overlay_rect.priority         = 0x02;
    ov_param.overlay_rect.win.w.left       = 0;
    ov_param.overlay_rect.win.w.top        = 0;
    ov_param.overlay_rect.win.w.width      = dst_w;
    ov_param.overlay_rect.win.w.height     = dst_h;
    ov_param.overlay_rect.win.global_alpha = 0;

	ov_param.overlay_dst.left   = 0;
    ov_param.overlay_dst.top    = 0;

    ov_param.overlay_dst.width  = dst_w;
    ov_param.overlay_dst.height = dst_h;

	tvout_v4l2_s_fbuf(fp, &(ov_param.overlay_frame));
	tvout_ov_s_parm(fp,V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, &(ov_param.overlay_rect));

    cropcap.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
    tvout_v4l2_cropcap(fp, &cropcap);

    if(    ov_param.overlay_dst.width  <= cropcap.bounds.width
        && ov_param.overlay_dst.height <= cropcap.bounds.height)
    {
	    tvout_ov_s_crop(fp, V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,&(ov_param.overlay_dst));
    }
    else
    {
	    printf("[%s] invalid crop size dst.w=%d dst.h=%d bounds.w=%d bounds.h=%d\n", __func__,
                ov_param.overlay_dst.width,
                ov_param.overlay_dst.height,
                cropcap.bounds.width,
                cropcap.bounds.height);
	    return -1;
    }

	return 0;
}

int tvout_v4l2_streamon(int fp, unsigned int type)
{
    int ret;

    ret = ioctl(fp, VIDIOC_STREAMON, &type);
    if (ret < 0) {
	    printf("tvout_v4l2_streamon" "VIDIOC_STREAMON failed %d\n", errno);
	    return ret;
    }

    return 0;
}

int tvout_v4l2_start_overlay(int fp)
{
    int ret, start = 1;

    ret = ioctl(fp, VIDIOC_OVERLAY, &start);
    if (ret < 0) {
	    printf("tvout_v4l2_start_overlay" "VIDIOC_OVERLAY failed\n");
	    return ret;
    }

    return ret;
}

int fimc_open()
{
	fimc_fd = open(FIMC_DEV, O_RDWR);
	if(fimc_fd < 0) {
		printf("++++++open tvout dev error\n");
		return -1;
	}
	return fimc_fd;
}

int fimc_querycap(int fp)
{
    struct v4l2_capability cap;
    int ret;

    ret = ioctl(fp, VIDIOC_QUERYCAP, &cap);

    if (ret < 0) {
	    printf("%s VIDIOC_QUERYCAP failed %d\n",__func__, errno);
	    return ret;
    }

    if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
        printf("%s::%s has no streaming support\n", __func__, FIMC_DEV);
        return -1;
    }

    if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
        printf("%s::%s is no video output\n", __func__, FIMC_DEV);
        return -1;
    }
    return ret;
}

int fimc_gfmt(int fp)
{
	struct v4l2_format fmt;
	int ret;
    fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
    ret = ioctl(fp, VIDIOC_G_FMT, &fmt);
    if (ret < 0) {
        printf("%s:: Error in video VIDIOC_G_FMT\n", __func__);
        return -1;
    }
	return ret;
}

int fimc_gctrl(int fp)
{
	struct v4l2_control vc;
	int ret;
    vc.id = V4L2_CID_RESERVED_MEM_BASE_ADDR;
    vc.value = http://www.mamicode.com/0;>编译生成二进制后 执行

hdmitest 480是输出480p

hdmitest 720输出720p

hdmitest 1080输出1080p

hdmitest tv是tv输出 这是默认就是tv输出

时间过的比较久了具体原理也没有完全整明白 大致原理就是获取fb数据后通过fimc转换然后进行overlay(希望没有说错)

整个源码下载地址:http://download.csdn.net/detail/hclydao/8360065

============================================
作者:hclydao
http://blog.csdn.net/hclydao
版权没有,但是转载请保留此段声明

============================================


s5pv210 linux hdmi tv输出