s5pv210 HDMI 1080P 高清显示

来源:互联网 发布:新浪邮箱smtp端口号 编辑:程序博客网 时间:2024/04/29 04:51

s5pv210 HDMI 1920x1080P@60Hz 显示 高清图片



s5pv210 可以设置成1920x1080P@60Hz显示,虽然datasheet并没有提供这种配置,因为1080P@60hz,需要 148500000的Pixel Clock,但是datasheet给出最高的是74250000。


在hdmiphy_drv.c 添加148500000的clock配置(linux3.9.7)


这个数据最终会通过调用 hdmiphy_s_dv_preset函数,hdmi的专用i2c,写入的hdmi模块中

static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd,struct v4l2_dv_preset *preset){const u8 *data;u8 buffer[32];int ret;struct hdmiphy_ctx *ctx = sd_to_ctx(sd);struct i2c_client *client = v4l2_get_subdevdata(sd);struct device *dev = &client->dev;dev_info(dev, "s_dv_preset(preset = %d)\n", preset->preset);data = hdmiphy_find_conf(preset->preset, ctx->conf_tab);if (!data) {dev_err(dev, "format not supported\n");return -EINVAL;}/* storing configuration to the device */memcpy(buffer, data, 32);ret = i2c_master_send(client, buffer, 32);if (ret != 32) {dev_err(dev, "failed to configure HDMIPHY via I2C\n");return -EIO;}return 0;}

测试源码(自己可以制作1080P的bmp图片)

#include <errno.h>#include <fcntl.h>#include <linux/videodev2.h>#include <math.h>#include <stdio.h>#include <stdint.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <sys/stat.h>#include <sys/types.h>#define ERRSTR strerror(errno)#define debug#define BYE_ON(cond, ...) \do { \if (cond) { \int errsv = errno; \fprintf(stderr, "ERROR(%s:%d) : ", \__FILE__, __LINE__); \errno = errsv; \fprintf(stderr,  __VA_ARGS__); \abort(); \} \} while(0)#define ReqButNum 3//#define HDMI480P//#define HDMI720P#define HDMI1080P#ifdef HDMI480P#define hdmi_width 720#define hdmi_height 480#endif#ifdef HDMI720P#define hdmi_width 1280#define hdmi_height 720#endif #ifdef HDMI1080P#define hdmi_width 1920#define hdmi_height 1080#endif #define CLEAR(x)    memset(&(x), 0, sizeof(x))#define BYE_ON(cond, ...) \do { \if (cond) { \int errsv = errno; \fprintf(stderr, "ERROR(%s:%d) : ", \__FILE__, __LINE__); \errno = errsv; \fprintf(stderr,  __VA_ARGS__); \abort(); \} \} while(0)struct hdmibuffer {int index;void *data;size_t size;size_t width;size_t height;/* buffer state */double t;};struct hdmibuffer hdmi_buffer[ReqButNum];struct buffer {int index;void *data;size_t size;size_t width;size_t height;/* buffer state */double t;};struct context {int fd;struct hdmibuffer *buffer;size_t buffer_cnt;};char hdmi_path[] = "/dev/video10";static int hdmi_fd;int open_hdmi_device(){int fd;if((fd = open(hdmi_path,O_RDWR)) < 0){perror("Fail to open");exit(EXIT_FAILURE);} hdmi_fd = fd;printf("open hdmi success %d\n",fd);return fd;}int hdmi_setfmt(){int ret;/* configure desired image size */struct v4l2_format fmt;struct v4l2_fmtdesc fmtdesc;memset(&fmtdesc,0,sizeof(fmtdesc));fmtdesc.index = 0;fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;while((ret = ioctl(hdmi_fd,VIDIOC_ENUM_FMT,&fmtdesc)) == 0){fmtdesc.index ++ ;printf("{pixelformat = %c%c%c%c},description = '%s'\n",fmtdesc.pixelformat & 0xff,(fmtdesc.pixelformat >> 8)&0xff,(fmtdesc.pixelformat >> 16) & 0xff,(fmtdesc.pixelformat >> 24)&0xff,fmtdesc.description);}memset(&fmt,0,sizeof(fmt));fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;fmt.fmt.pix.width = hdmi_width;fmt.fmt.pix.height = hdmi_height;fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;//V4L2_FIELD_NONE;//V4L2_FIELD_INTERLACED;printf("%s: +\n", __func__);/* format is hardcoded: draw procedures work only in 32-bit mode */fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR32;ret = ioctl(hdmi_fd, VIDIOC_S_FMT, &fmt);BYE_ON(ret < 0, "VIDIOC_S_FMT failed: %s\n", ERRSTR);/* update format struct to values adjusted by a driver */ret = ioctl(hdmi_fd, VIDIOC_G_FMT, &fmt);BYE_ON(ret < 0, "VIDIOC_G_FMT failed: %s\n", ERRSTR);printf("getfmt:%d,%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height);BYE_ON((fmt.fmt.pix.width < hdmi_width) | (fmt.fmt.pix.height < hdmi_height), "VIDIOC_G_FMT failed: %s\n", ERRSTR);/* crop output area on display */struct v4l2_crop crop;crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;crop.c.left = 0;crop.c.top = 0;crop.c.width = hdmi_width;crop.c.height = hdmi_height;ret = ioctl(hdmi_fd, VIDIOC_S_CROP, &crop);BYE_ON(ret < 0, "VIDIOC_S_CROP failed: %s\n", ERRSTR);printf("%s: -\n", __func__);return 0;}int hdmi_reqbufs(){int ret;int i,j;struct v4l2_requestbuffers rqbufs;struct v4l2_plane plane;struct v4l2_buffer buf;struct v4l2_format fmt;rqbufs.count = ReqButNum;rqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;rqbufs.memory = V4L2_MEMORY_MMAP;printf("%s +\n", __func__);ret = ioctl(hdmi_fd, VIDIOC_REQBUFS, &rqbufs);printf("reqbuf:%d\n", rqbufs.count);BYE_ON(ret < 0, "VIDIOC_REQBUFS failed: %s\n", ERRSTR);BYE_ON(rqbufs.count < ReqButNum, "failed to get %d buffers\n",ReqButNum);//ret = ioctl(hdmi_fd, VIDIOC_G_FMT, &fmt);//BYE_ON(ret < 0, "VIDIOC_G_FMT failed: %s\n", ERRSTR);/* buffers initalization */for (i = 0; i < ReqButNum; ++i) {buf.index = i;buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;buf.memory = V4L2_MEMORY_MMAP;buf.m.planes = &plane;buf.length = 1;/* get buffer properties from a driver */ret = ioctl(hdmi_fd, VIDIOC_QUERYBUF, &buf);BYE_ON(ret < 0, "VIDIOC_QUERYBUF for buffer %d failed: %s\n",buf.index, ERRSTR);hdmi_buffer[i].index = i;/* mmap buffer to user space */hdmi_buffer[i].data = mmap(NULL, plane.length, PROT_READ | PROT_WRITE,MAP_SHARED, hdmi_fd, plane.m.mem_offset);BYE_ON(hdmi_buffer[i].data == MAP_FAILED, "mmap failed: %s\n",ERRSTR);hdmi_buffer[i].size = plane.length;hdmi_buffer[i].width = hdmi_width;hdmi_buffer[i].height = hdmi_height;/* fill buffer with black */for (j = 0; 4 * j < hdmi_buffer[i].size; ++j)((unsigned int *)hdmi_buffer[i].data)[j] = 0xff000000;}printf("%s -\n", __func__);return 0;}int init_device(){hdmi_setfmt();hdmi_reqbufs();printf("%s -\n", __func__);}int hdmi_streamon(){enum v4l2_buf_type type;int ret;//hdmi_qbuf(2);struct timeval tv;gettimeofday(&tv, NULL);type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;ret = ioctl(hdmi_fd, VIDIOC_STREAMON, &type);BYE_ON(ret, "VIDIOC_STREAMON failed: %s\n", ERRSTR);return 0;}int hdmi_qbuf(int index){struct v4l2_buffer buf;struct v4l2_plane plane;debug("queue +\n");memset(&buf, 0, sizeof(buf));memset(&plane, 0, sizeof(plane));buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;buf.index = index;buf.memory = V4L2_MEMORY_MMAP;buf.m.planes = &plane;buf.length = 1;int ret;ret = ioctl(hdmi_fd, VIDIOC_QBUF, &buf);BYE_ON(ret, "VIDIOC_QBUF(index = %d) failed: %s\n",index, ERRSTR);//sem_post(&lcd_sem);return 0;}int hdmi_dbuf(int *index){int ret;struct v4l2_buffer buf;struct v4l2_plane plane;debug("dequeue +\n");memset(&buf, 0, sizeof(buf));buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;buf.memory = V4L2_MEMORY_MMAP;buf.m.planes = &plane;buf.length = 1;ret = ioctl(hdmi_fd, VIDIOC_DQBUF, &buf);BYE_ON(ret, "VIDIOC_DQBUF failed: %s\n", ERRSTR);*index = buf.index;return 0;}unsigned int *display_bmp_image(){unsigned int *img_buf;    FILE *fp;    int count = 0, i = 0, j=0, r, g, b;    char ch;    char *pch;    int buf_size = hdmi_width * hdmi_height;    img_buf = (unsigned int *)malloc(buf_size * sizeof(int));    memset(img_buf, 0, sizeof(img_buf));    if(NULL == (fp = fopen("./test.bmp", "r")))    {        printf("open the image file %s failed!\n", "test.bmp");        return;    }    for(i = 0 ; i < 54 ; i++)        ch=fgetc(fp);for(i = 0; i < hdmi_height; i++){for(j = 0; j < hdmi_width; j++){  r = fgetc(fp);  g = fgetc(fp);  b = fgetc(fp);  img_buf[(hdmi_height - i - 1) * hdmi_width + j] = (unsigned int)(0xff000000 | (b << 16) | (g << 8) | r);}}    fclose(fp);return (void *)img_buf;}int main(){int static i = 0;intj = 0;int k = 0;int r, g, b;unsigned int *bmp_buf;bmp_buf = display_bmp_image();open_hdmi_device();hdmi_setfmt();hdmi_reqbufs();hdmi_qbuf(0);hdmi_qbuf(1);hdmi_qbuf(2);hdmi_streamon();while(1){hdmi_dbuf(&i);k = (k + 8)%24;printf("i=%d, %lx\n",i, 0xff000000 | (0xff << k));memcpy((void *)hdmi_buffer[i].data, (void *)bmp_buf, hdmi_width * hdmi_height * 4);hdmi_qbuf(i);getchar();for(j = 0; j < hdmi_width * hdmi_height; j ++)((unsigned int *)hdmi_buffer[i].data)[j] = 0xff000000 | (0xff << k);}}

通过测试,发现

只能运行逐行扫描模式,即1080P,720P,480P,不能运行隔行扫描,即1080i,

提示错误:

[   31.609709] s5p-mixer s5p-mixer: no vsync detected - timeout[   31.609758] ------------[ cut here ]------------[   31.609817] WARNING: at drivers/media/platform/s5p-tv/mixer_drv.c:83 mxr_streamer_get+0x148/0x1c4()[   31.609887] failed to get vsync (-62) from output[   31.611366] Modules linked in:[   31.614429] [<c0018d30>] (unwind_backtrace+0x0/0xf0) from [<c0023158>] (warn_slowpath_common+0x4c/0x68)[   31.623787] [<c0023158>] (warn_slowpath_common+0x4c/0x68) from [<c0023208>] (warn_slowpath_fmt+0x30/0x40)[   31.633314] [<c0023208>] (warn_slowpath_fmt+0x30/0x40) from [<c0318a44>] (mxr_streamer_get+0x148/0x1c4)[   31.642672] [<c0318a44>] (mxr_streamer_get+0x148/0x1c4) from [<c03191d4>] (start_streaming+0x80/0xb0)[   31.651858] [<c03191d4>] (start_streaming+0x80/0xb0) from [<c02f5d44>] (vb2_streamon+0x74/0x160)[   31.660616] [<c02f5d44>] (vb2_streamon+0x74/0x160) from [<c02e3ff8>] (v4l_streamon+0x18/0x1c)[   31.669103] [<c02e3ff8>] (v4l_streamon+0x18/0x1c) from [<c02e671c>] (__video_do_ioctl+0x25c/0x33c)[   31.678027] [<c02e671c>] (__video_do_ioctl+0x25c/0x33c) from [<c02e7938>] (video_usercopy+0xac/0x3f4)[   31.687212] [<c02e7938>] (video_usercopy+0xac/0x3f4) from [<c02e2774>] (v4l2_ioctl+0xe0/0x144)[   31.695802] [<c02e2774>] (v4l2_ioctl+0xe0/0x144) from [<c00bae44>] (do_vfs_ioctl+0x80/0x618)[   31.704199] [<c00bae44>] (do_vfs_ioctl+0x80/0x618) from [<c00bb418>] (sys_ioctl+0x3c/0x60)[   31.712437] [<c00bb418>] (sys_ioctl+0x3c/0x60) from [<c0013940>] (ret_fast_syscall+0x0/0x30)[   31.720829] ---[ end trace f6f0c2e97ef6ff7e ]---


DELL S2340L显示器只能配置到1080P@60HZ,  不能显示50HZ和30HZ,所以只能配置到60Hz,在运行动画时,刷屏有点闪烁,以后在分析

1 0
原创粉丝点击