blob: eeacb4d50e1f51f83977168c2b8e9b1e8e2d9a79 [file] [log] [blame]
Petr Havlenac9288142012-11-15 14:07:10 +05301/*
2 * Copyright 2011, Havlena Petr <havlenapetr@gmail.com>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_NDEBUG 0
18#include <utils/Log.h>
19
20#include <string.h>
21#include <stdlib.h>
22#include <sys/poll.h>
23
24#include <sec_lcd.h>
25
26#include "SecHDMI.h"
27#include "fimd.h"
28
29using namespace android;
30
31#define RETURN_IF(return_value) \
32 if (return_value < 0) { \
33 ALOGE("%s::%d fail. errno: %s", \
34 __func__, __LINE__, strerror(errno)); \
35 return -1; \
36 }
37
38#define ALOG_IF(return_value) \
39 if (return_value < 0) { \
40 ALOGE("%s::%d fail. errno: %s", \
41 __func__, __LINE__, strerror(errno)); \
42 }
43
44#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5)
45#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7)
46#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13)
47
48struct s5p_tv_standart_internal {
49 int index;
50 unsigned long value;
51} s5p_tv_standards[] = {
52 {
53 S5P_TV_STD_NTSC_M,
54 V4L2_STD_NTSC_M,
55 }, {
56 S5P_TV_STD_PAL_BDGHI,
57 V4L2_STD_PAL_BDGHI,
58 }, {
59 S5P_TV_STD_PAL_M,
60 V4L2_STD_PAL_M,
61 }, {
62 S5P_TV_STD_PAL_N,
63 V4L2_STD_PAL_N,
64 }, {
65 S5P_TV_STD_PAL_Nc,
66 V4L2_STD_PAL_Nc,
67 }, {
68 S5P_TV_STD_PAL_60,
69 V4L2_STD_PAL_60,
70 }, {
71 S5P_TV_STD_NTSC_443,
72 V4L2_STD_NTSC_443,
73 }, {
74 S5P_TV_STD_480P_60_16_9,
75 V4L2_STD_480P_60_16_9,
76 }, {
77 S5P_TV_STD_480P_60_4_3,
78 V4L2_STD_480P_60_4_3,
79 }, {
80 S5P_TV_STD_576P_50_16_9,
81 V4L2_STD_576P_50_16_9,
82 }, {
83 S5P_TV_STD_576P_50_4_3,
84 V4L2_STD_576P_50_4_3,
85 }, {
86 S5P_TV_STD_720P_60,
87 V4L2_STD_720P_60,
88 }, {
89 S5P_TV_STD_720P_50,
90 V4L2_STD_720P_50,
91 },
92};
93
94static inline int calcFrameSize(int format, int width, int height)
95{
96 int size = 0;
97
98 switch (format) {
99 case V4L2_PIX_FMT_YUV420:
100 case V4L2_PIX_FMT_NV12:
101 case V4L2_PIX_FMT_NV21:
102 size = (width * height * 3 / 2);
103 break;
104
105 case V4L2_PIX_FMT_NV12T:
106 size = ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height)) +
107 ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height / 2));
108 break;
109
110 case V4L2_PIX_FMT_YUV422P:
111 case V4L2_PIX_FMT_YUYV:
112 case V4L2_PIX_FMT_UYVY:
113 size = (width * height * 2);
114 break;
115
116 default :
117 ALOGE("ERR(%s):Invalid V4L2 pixel format(%d)\n", __func__, format);
118 case V4L2_PIX_FMT_RGB565:
119 size = (width * height * 2);
120 break;
121 }
122 return size;
123}
124
125static int get_pixel_depth(unsigned int fmt)
126{
127 int depth = 0;
128
129 switch (fmt) {
130 case V4L2_PIX_FMT_NV12:
131 depth = 12;
132 break;
133 case V4L2_PIX_FMT_NV12T:
134 depth = 12;
135 break;
136 case V4L2_PIX_FMT_NV21:
137 depth = 12;
138 break;
139 case V4L2_PIX_FMT_YUV420:
140 depth = 12;
141 break;
142
143 case V4L2_PIX_FMT_RGB565:
144 case V4L2_PIX_FMT_YUYV:
145 case V4L2_PIX_FMT_YVYU:
146 case V4L2_PIX_FMT_UYVY:
147 case V4L2_PIX_FMT_VYUY:
148 case V4L2_PIX_FMT_NV16:
149 case V4L2_PIX_FMT_NV61:
150 case V4L2_PIX_FMT_YUV422P:
151 depth = 16;
152 break;
153
154 case V4L2_PIX_FMT_RGB32:
155 depth = 32;
156 break;
157 }
158
159 return depth;
160}
161
162// ======================================================================
163// Video ioctls
164
165static int tv20_v4l2_querycap(int fp)
166{
167 struct v4l2_capability cap;
168
169 int ret = ioctl(fp, VIDIOC_QUERYCAP, &cap);
170 if (ret < 0) {
171 ALOGE("ERR(%s):VIDIOC_QUERYCAP failed", __func__);
172 return -1;
173 }
174
175 if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
176 ALOGE("ERR(%s):no output devices\n", __func__);
177 return -1;
178 }
179 ALOGV("Name of cap driver is %s", cap.driver);
180
181 return ret;
182}
183
184static const __u8* tv20_v4l2_enum_output(int fp, int index)
185{
186 static struct v4l2_output output;
187
188 output.index = index;
189 if (ioctl(fp, VIDIOC_ENUMOUTPUT, &output) != 0) {
190 ALOGE("ERR(%s):No matching index found", __func__);
191 return NULL;
192 }
193 ALOGV("Name of output channel[%d] is %s", output.index, output.name);
194
195 return output.name;
196}
197
198static const __u8* tv20_v4l2_enum_standarts(int fp, int index)
199{
200 static struct v4l2_standard standart;
201
202 standart.index = index;
203 if (ioctl(fp, VIDIOC_ENUMSTD, &standart) != 0) {
204 ALOGE("ERR(%s):No matching index found\n", __func__);
205 return NULL;
206 }
207 ALOGV("Name of output standart[%d] is %s\n", standart.index, standart.name);
208
209 return standart.name;
210}
211
212static int tv20_v4l2_s_output(int fp, int index)
213{
214 struct v4l2_output output;
215 int ret;
216
217 output.index = index;
218
219 ret = ioctl(fp, VIDIOC_S_OUTPUT, &output);
220 if (ret < 0) {
221 ALOGE("ERR(%s):VIDIOC_S_OUPUT failed\n", __func__);
222 return ret;
223 }
224 return ret;
225}
226
227static int tv20_v4l2_s_std(int fp, unsigned long id)
228{
229 v4l2_std_id std;
230 int ret;
231
232 std = id;
233
234 ret = ioctl(fp, VIDIOC_S_STD, &std);
235 if (ret < 0) {
236 ALOGE("ERR(%s):VIDIOC_S_OUPUT failed\n", __func__);
237 return ret;
238 }
239 return ret;
240}
241
242static int tv20_v4l2_enum_fmt(int fp, unsigned int fmt)
243{
244 struct v4l2_fmtdesc fmtdesc;
245 int found = 0;
246
247 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
248 fmtdesc.index = 0;
249
250 while (ioctl(fp, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
251 if (fmtdesc.pixelformat == fmt) {
252 ALOGV("passed fmt = %#x found pixel format[%d]: %s\n", fmt, fmtdesc.index, fmtdesc.description);
253 found = 1;
254 break;
255 }
256
257 fmtdesc.index++;
258 }
259
260 if (!found) {
261 ALOGE("unsupported pixel format\n");
262 return -1;
263 }
264
265 return 0;
266}
267
268static int tv20_v4l2_s_fmt(int fp, int width, int height,
269 unsigned int fmt, unsigned int yAddr, unsigned int cAddr)
270{
271 struct v4l2_format v4l2_fmt;
272 struct v4l2_pix_format_s5p_tvout pixfmt;
273 int ret;
274
275 v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
276#if 0
277 ret = ioctl(fp, VIDIOC_G_FMT, &v4l2_fmt);
278 if (ret < 0) {
279 ALOGE("ERR(%s):VIDIOC_G_FMT failed", __func__);
280 return -1;
281 }
282#endif
283
284 memset(&pixfmt, 0, sizeof(pixfmt));
285 pixfmt.pix_fmt.width = width;
286 pixfmt.pix_fmt.height = height;
287 pixfmt.pix_fmt.pixelformat = fmt;
288 pixfmt.pix_fmt.sizeimage = (width * height * get_pixel_depth(fmt)) / 8;
289 pixfmt.pix_fmt.field = V4L2_FIELD_NONE;
290
291 // here we must set addresses of our memory for video out
292 pixfmt.base_y = (void *)yAddr;
293 pixfmt.base_c = (void* )cAddr;
294
295 v4l2_fmt.fmt.pix = pixfmt.pix_fmt;
296 memcpy(v4l2_fmt.fmt.raw_data, &pixfmt,
297 sizeof(struct v4l2_pix_format_s5p_tvout));
298
299 /* Set up for capture */
300 ret = ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt);
301 if (ret < 0) {
302 ALOGE("ERR(%s):VIDIOC_S_FMT failed\n", __func__);
303 return -1;
304 }
305 return 0;
306}
307
308static int tv20_v4l2_streamon(int fp)
309{
310 enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
311 int ret;
312
313 ret = ioctl(fp, VIDIOC_STREAMON, &type);
314 if (ret < 0) {
315 ALOGE("ERR(%s):VIDIOC_STREAMON failed\n", __func__);
316 return ret;
317 }
318
319 return ret;
320}
321
322static int tv20_v4l2_streamoff(int fp)
323{
324 enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
325 int ret;
326
327 ALOGV("%s :", __func__);
328 ret = ioctl(fp, VIDIOC_STREAMOFF, &type);
329 if (ret < 0) {
330 ALOGE("ERR(%s):VIDIOC_STREAMOFF failed\n", __func__);
331 return ret;
332 }
333
334 return ret;
335}
336
337static int tv20_v4l2_g_parm(int fp, struct v4l2_streamparm *streamparm)
338{
339 int ret;
340
341 streamparm->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
342
343 ret = ioctl(fp, VIDIOC_G_PARM, streamparm);
344 if (ret < 0) {
345 ALOGE("ERR(%s):VIDIOC_G_PARM failed\n", __func__);
346 return -1;
347 }
348
349 ALOGV("%s : timeperframe: numerator %d, denominator %d\n", __func__,
350 streamparm->parm.capture.timeperframe.numerator,
351 streamparm->parm.capture.timeperframe.denominator);
352
353 return 0;
354}
355
356static int tv20_v4l2_s_parm(int fp, struct v4l2_streamparm *streamparm)
357{
358 int ret;
359
360 streamparm->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
361
362 ret = ioctl(fp, VIDIOC_S_PARM, streamparm);
363 if (ret < 0) {
364 ALOGE("ERR(%s):VIDIOC_S_PARM failed\n", __func__);
365 return ret;
366 }
367 return 0;
368}
369
370static int tv20_v4l2_s_crop(int fp, int offset_x, int offset_y, int width, int height)
371{
372 struct v4l2_crop crop;
373
374 crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
375 crop.c.left = offset_x;
376 crop.c.top = offset_y;
377 crop.c.width = width;
378 crop.c.height = height;
379
380 int ret = ioctl(fp, VIDIOC_S_CROP, &crop);
381 if (ret < 0) {
382 ALOGE("ERR(%s):VIDIOC_S_PARM failed\n", __func__);
383 return ret;
384 }
385 return 0;
386}
387
388static int tv20_v4l2_start_overlay(int fp)
389{
390 int ret, start = 1;
391
392 ret = ioctl(fp, VIDIOC_OVERLAY, &start);
393 if (ret < 0) {
394 ALOGE("ERR(%s): VIDIOC_OVERLAY start failed\n", __func__);
395 return ret;
396 }
397
398 return ret;
399}
400
401static int tv20_v4l2_stop_overlay(int fp)
402{
403 int ret, stop = 0;
404
405 ret = ioctl(fp, VIDIOC_OVERLAY, &stop);
406 if (ret < 0) {
407 ALOGE("ERR(%s): VIDIOC_OVERLAY stop failed\n", __func__);
408 return ret;
409 }
410
411 return ret;
412}
413
414static int tv20_v4l2_s_baseaddr(int fp, void *base_addr)
415{
416 int ret;
417
418 ret = ioctl(fp, S5PTVFB_WIN_SET_ADDR, base_addr);
419 if (ret < 0) {
420 ALOGE("ERR(%s): VIDIOC_S_BASEADDR failed %d", __func__, ret);
421 return ret;
422 }
423
424 return 0;
425}
426
427static int tv20_v4l2_s_position(int fp, int x, int y)
428{
429 int ret;
430 struct s5ptvfb_user_window window;
431
432 memset(&window, 0, sizeof(struct s5ptvfb_user_window));
433 window.x = x;
434 window.y = y;
435
436 ret = ioctl(fp, S5PTVFB_WIN_POSITION, &window);
437 if (ret < 0) {
438 ALOGE("ERR(%s): VIDIOC_S_WIN_POSITION failed %d", __func__, ret);
439 return ret;
440 }
441
442 return 0;
443}
444
445// ======================================================================
446// Audio ioctls
447
448static int tv20_v4l2_audio_enable(int fp)
449{
450 return ioctl(fp, VIDIOC_INIT_AUDIO, 1);
451}
452
453static int tv20_v4l2_audio_disable(int fp)
454{
455 return ioctl(fp, VIDIOC_INIT_AUDIO, 0);
456}
457
458static int tv20_v4l2_audio_mute(int fp)
459{
460 return ioctl(fp, VIDIOC_AV_MUTE, 1);
461}
462
463static int tv20_v4l2_audio_unmute(int fp)
464{
465 return ioctl(fp, VIDIOC_AV_MUTE, 0);
466}
467
468static int tv20_v4l2_audio_get_mute_state(int fp)
469{
470 return ioctl(fp, VIDIOC_G_AVMUTE, 0);
471}
472
473// ======================================================================
474// Class which comunicate with kernel driver
475
476SecHDMI::SecHDMI()
477 : mTvOutFd(-1),
478 mTvOutVFd(-1),
479 mLcdFd(-1),
480 mHdcpEnabled(0),
481 mFlagConnected(false)
482{
483 ALOGV("%s", __func__);
484
485 memset(&mParams, 0, sizeof(struct v4l2_streamparm));
486 memset(&mFlagLayerEnable, 0, sizeof(bool) * S5P_TV_LAYER_MAX);
487
488 int ret = ioctl(mTvOutFd, VIDIOC_HDCP_ENABLE, &mHdcpEnabled);
489 ALOG_IF(ret);
490}
491
492SecHDMI::~SecHDMI()
493{
494 destroy();
495}
496
497/* static */
498int SecHDMI::getCableStatus()
499{
500 int fd = 0;
501 char value[8] = {0};
502
503 ALOGV("%s", __func__);
504
505 fd = open("/sys/class/switch/h2w/state", O_RDWR);
506 if(fd < 0) {
507 goto close;
508 }
509
510 if(read(fd, &value, 8) <= 0) {
511 goto close;
512 }
513
514close:
515 close(fd);
516 return strtol(value, NULL, 10);
517}
518
519const __u8* SecHDMI::getName(int index)
520{
521 ALOGV("%s", __func__);
522 return tv20_v4l2_enum_output(mTvOutFd, index);
523}
524
525int SecHDMI::destroy()
526{
527 ALOGV("%s", __func__);
528
529 if(mFlagConnected) {
530 disconnect();
531 }
532 if(mTvOutFd > 0) {
533 close(mTvOutFd);
534 mTvOutFd = -1;
535 }
536 if(mFimc.dev_fd > 0) {
537 fimc_close(&mFimc);
538 mFimc.dev_fd = -1;
539 }
540 if (mLcdFd > 0) {
541 fb_close(mLcdFd);
542 mLcdFd = -1;
543 }
544
545 return 0;
546}
547
548int SecHDMI::startLayer(s5p_tv_layer layer)
549{
550 int ret;
551
552 if (mFlagLayerEnable[layer]) {
553 return 0;
554 }
555
556 switch (layer) {
557 case S5P_TV_LAYER_VIDEO:
558 if(mTvOutVFd < 0) {
559 mTvOutVFd = open(TVOUT_DEV_V, O_RDWR);
560 RETURN_IF(mTvOutVFd);
561 }
562 ret = tv20_v4l2_start_overlay(mTvOutVFd);
563 RETURN_IF(ret);
564 break;
565 case S5P_TV_LAYER_GRAPHIC_0 :
566 ret = ioctl(0/*fp_tvout_g0*/, FBIOBLANK, (void *)FB_BLANK_UNBLANK);
567 RETURN_IF(ret);
568 break;
569 case S5P_TV_LAYER_GRAPHIC_1 :
570 ret = ioctl(0/*fp_tvout_g1*/, FBIOBLANK, (void *)FB_BLANK_UNBLANK);
571 RETURN_IF(ret);
572 break;
573 default :
574 RETURN_IF(-1);
575 }
576
577 mFlagLayerEnable[layer] = true;
578
579 return 0;
580}
581
582int SecHDMI::stopLayer(s5p_tv_layer layer)
583{
584 int ret;
585
586 if (!mFlagLayerEnable[layer]) {
587 return 0;
588 }
589
590 switch (layer) {
591 case S5P_TV_LAYER_VIDEO:
592 ret = tv20_v4l2_stop_overlay(mTvOutVFd);
593 RETURN_IF(ret);
594 close(mTvOutVFd);
595 mTvOutVFd = -1;
596 break;
597 case S5P_TV_LAYER_GRAPHIC_0 :
598 ret = ioctl(0/*fp_tvout_g0*/, FBIOBLANK, (void *)FB_BLANK_POWERDOWN);
599 RETURN_IF(ret);
600 break;
601 case S5P_TV_LAYER_GRAPHIC_1 :
602 ret = ioctl(0/*fp_tvout_g1*/, FBIOBLANK, (void *)FB_BLANK_POWERDOWN);
603 RETURN_IF(ret);
604 break;
605 default :
606 RETURN_IF(-1);
607 }
608
609 mFlagLayerEnable[layer] = false;
610
611 return 0;
612}
613
614int SecHDMI::create(int width, int height)
615{
616 int ret, y_size;
617 unsigned int addr;
618
619 ALOGV("%s", __func__);
620
621 mTvOutFd = open(TVOUT_DEV, O_RDWR);
622 RETURN_IF(mTvOutFd);
623
624 memset(&mFimc, 0, sizeof(s5p_fimc_t));
625 mFimc.dev_fd = -1;
626 ret = fimc_open(&mFimc, "/dev/video2");
627 RETURN_IF(ret);
628
629 ALOGV("query capabilities");
630 ret = tv20_v4l2_querycap(mTvOutFd);
631 RETURN_IF(ret);
632
633 struct s5p_tv_standart_internal std =
634 s5p_tv_standards[(int) S5P_TV_STD_PAL_BDGHI];
635
636 ALOGV("searching for standart: %i", std.index);
637 if(!tv20_v4l2_enum_standarts(mTvOutFd, std.index))
638 return -1;
639
640 ret = tv20_v4l2_s_std(mTvOutFd, std.value);
641 RETURN_IF(ret);
642
643 ALOGV("searching for output: %i", S5P_TV_OUTPUT_TYPE_COMPOSITE);
644 if (!tv20_v4l2_enum_output(mTvOutFd, S5P_TV_OUTPUT_TYPE_COMPOSITE))
645 return -1;
646
647 ret = tv20_v4l2_s_output(mTvOutFd, S5P_TV_OUTPUT_TYPE_COMPOSITE);
648 RETURN_IF(ret);
649
650 struct v4l2_window_s5p_tvout* p =
651 (struct v4l2_window_s5p_tvout*)&mParams.parm.raw_data;
652 p->win.w.top = 0;
653 p->win.w.left = 0;
654 p->win.w.width = width;
655 p->win.w.height = height;
656
657 ALOGV("searching for format: %i", V4L2_PIX_FMT_NV12);
658 ret = tv20_v4l2_enum_fmt(mTvOutFd, V4L2_PIX_FMT_NV12);
659 RETURN_IF(ret);
660
661 addr = (unsigned int) mFimc.out_buf.phys_addr;
662 y_size = ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height));
663 ret = tv20_v4l2_s_fmt(mTvOutFd, width, height, V4L2_PIX_FMT_NV12,
664 (unsigned int) addr,
665 (unsigned int) addr + y_size);
666 RETURN_IF(ret);
667
668 return 0;
669}
670
671int SecHDMI::connect()
672{
673 int ret;
674
675 ALOGV("%s", __func__);
676
677 RETURN_IF(mTvOutFd);
678
679 if(mFlagConnected) {
680 return 0;
681 }
682
683#if 0
684 ret = getCableStatus() <= 0 ? -1 : 0;
685 RETURN_IF(ret);
686#endif
687
688 ret = tv20_v4l2_s_parm(mTvOutFd, &mParams);
689 RETURN_IF(ret);
690
691 ret = tv20_v4l2_streamon(mTvOutFd);
692 RETURN_IF(ret);
693
694#if 0
695 ret = startLayer(S5P_TV_LAYER_VIDEO);
696 RETURN_IF(ret);
697#endif
698
699 mFlagConnected = true;
700
701 return 0;
702}
703
704int SecHDMI::disconnect()
705{
706 int ret;
707
708 ALOGV("%s", __func__);
709
710 RETURN_IF(mTvOutFd);
711
712 if(!mFlagConnected) {
713 return 0;
714 }
715
716 ret = tv20_v4l2_streamoff(mTvOutFd);
717 RETURN_IF(ret);
718
719#if 0
720 ret = stopLayer(S5P_TV_LAYER_VIDEO);
721 RETURN_IF(ret);
722#endif
723
724 mFlagConnected = false;
725
726 return 0;
727}
728
729int SecHDMI::flush(int srcW, int srcH, int srcColorFormat,
730 unsigned int srcYAddr, unsigned int srcCbAddr, unsigned int srcCrAddr,
731 int dstX, int dstY,
732 int layer,
733 int num_of_hwc_layer)
734{
735 int ret;
736
737#if 0
738 usleep(1000 * 10);
739#else
740 sec_img src_img;
741 sec_img dst_img;
742 sec_rect src_rect;
743 sec_rect dst_rect;
744 unsigned int phyAddr[3/*MAX_NUM_PLANES*/];
745
746 if(!srcYAddr) {
747 struct s3cfb_next_info fb_info;
748
749 if (mLcdFd < 0) {
750 mLcdFd = fb_open(0);
751 }
752
753 RETURN_IF(mLcdFd);
754
755 ret = ioctl(mLcdFd, S3CFB_GET_CURR_FB_INFO, &fb_info);
756 RETURN_IF(ret);
757
758 srcYAddr = fb_info.phy_start_addr;
759 srcCbAddr = srcYAddr;
760 }
761
762 memset(&src_img, 0, sizeof(src_img));
763 memset(&dst_img, 0, sizeof(src_img));
764 memset(&src_rect, 0, sizeof(src_rect));
765 memset(&dst_rect, 0, sizeof(src_rect));
766 memset(&phyAddr, 0, sizeof(int) * sizeof(phyAddr));
767
768 phyAddr[0] = srcYAddr;
769 phyAddr[1] = srcCbAddr;
770 phyAddr[2] = srcCrAddr;
771
772 src_img.w = srcW;
773 src_img.h = srcH;
774 src_img.format = HAL_PIXEL_FORMAT_YCbCr_420_SP/*srcColorFormat*/;
775 src_img.base = 0;
776 src_img.offset = 0;
777 src_img.mem_id = 0;
778 src_img.mem_type = FIMC_MEM_TYPE_PHYS;
779 src_img.w = (src_img.w + 15) & (~15);
780 src_img.h = (src_img.h + 1) & (~1) ;
781
782 src_rect.x = 0;
783 src_rect.y = 0;
784 src_rect.w = src_img.w;
785 src_rect.h = src_img.h;
786
787 struct v4l2_window_s5p_tvout* p =
788 (struct v4l2_window_s5p_tvout*)&mParams.parm.raw_data;
789 if (!p) {
790 return -1;
791 }
792
793 dst_img.w = p->win.w.width;
794 dst_img.h = p->win.w.height;
795 dst_img.format = HAL_PIXEL_FORMAT_YCbCr_420_SP;
796 dst_img.base = (unsigned int) mFimc.out_buf.phys_addr;
797 dst_img.offset = 0;
798 dst_img.mem_id = 0;
799 dst_img.mem_type = FIMC_MEM_TYPE_PHYS;
800
801 dst_rect.x = p->win.w.top;
802 dst_rect.y = p->win.w.left;
803 dst_rect.w = dst_img.w;
804 dst_rect.h = dst_img.h;
805
806 ALOGV("%s::sr_x %d sr_y %d sr_w %d sr_h %d dr_x %d dr_y %d dr_w %d dr_h %d ",
807 __func__, src_rect.x, src_rect.y, src_rect.w, src_rect.h,
808 dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
809
810 ret = fimc_flush(&mFimc, &src_img, &src_rect, &dst_img, &dst_rect,
811 phyAddr, 0);
812 RETURN_IF(ret);
813
814/*
815 struct fb_var_screeninfo var;
816 var.xres = srcW;
817 var.yres = srcH;
818 var.xres_virtual = var.xres;
819 var.yres_virtual = var.yres;
820 var.xoffset = 0;
821 var.yoffset = 0;
822 var.width = srcW;
823 var.height = srcH;
824 var.activate = FB_ACTIVATE_FORCE;
825 if (srcColorFormat == HAL_PIXEL_FORMAT_RGB_565) {
826 var.bits_per_pixel = 16;
827 var.transp.length = 0;
828 }
829 else {
830 var.bits_per_pixel = 32;
831 var.transp.length = 8;
832 }
833
834 ret = tv20_v4l2_s_baseaddr(mTvOutFd, (void *)srcYAddr);
835 RETURN_IF(ret);
836
837 ret = fb_put_vscreeninfo(mLcdFd, &var);
838 RETURN_IF(ret);
839
840 ret = tv20_v4l2_s_position(mTvOutFd, dstX, dstY);
841 RETURN_IF(ret);
842*/
843#endif
844
845 return 0;
846}