From beda705b782a651d7142757611360cc95fe66fd5 Mon Sep 17 00:00:00 2001 From: Jinkun Jang Date: Wed, 13 Mar 2013 01:37:03 +0900 Subject: [PATCH] Tizen 2.1 base --- AUTHORS | 3 + COPYING | 24 + ChangeLog | 5 + Makefile.am | 22 + autogen.sh | 12 + configure.ac | 116 ++++ man/Makefile.am | 57 ++ man/emulfb.man | 63 ++ packaging/xorg-x11-drv-emulfb.spec | 70 +++ src/Makefile.am | 80 +++ src/crtcconfig/fbdev_crtc.c | 250 ++++++++ src/crtcconfig/fbdev_crtc_priv.h | 45 ++ src/crtcconfig/fbdev_crtcconfig.c | 139 +++++ src/crtcconfig/fbdev_crtcconfig.h | 37 ++ src/crtcconfig/fbdev_mode.c | 173 ++++++ src/crtcconfig/fbdev_mode.h | 44 ++ src/crtcconfig/fbdev_output_priv.h | 46 ++ src/crtcconfig/lcd_output.c | 300 ++++++++++ src/debug/fbdev_event_trace.c | 100 ++++ src/debug/fbdev_event_trace.h | 38 ++ src/fb/fbdev_fb.c | 298 ++++++++++ src/fb/fbdev_fb.h | 54 ++ src/fbdev.c | 763 ++++++++++++++++++++++++ src/fbdev.h | 107 ++++ src/fbdev_dpms.c | 140 +++++ src/fbdev_dpms.h | 45 ++ src/fbdevhw/fbdev_hw.c | 196 ++++++ src/fbdevhw/fbdev_hw.h | 51 ++ src/util/fbdev_pixman.c | 170 ++++++ src/util/fbdev_pixman.h | 64 ++ src/util/fbdev_util.c | 255 ++++++++ src/util/fbdev_util.h | 82 +++ src/xv/arm/fbdev_video_v4l2.c | 1111 ++++++++++++++++++++++++++++++++++ src/xv/fbdev_v4l2.c | 511 ++++++++++++++++ src/xv/fbdev_v4l2.h | 84 +++ src/xv/fbdev_video.c | 1157 ++++++++++++++++++++++++++++++++++++ src/xv/fbdev_video.h | 76 +++ src/xv/fbdev_video_fourcc.h | 196 ++++++ src/xv/fbdev_video_types.h | 107 ++++ src/xv/fbdev_video_v4l2.h | 73 +++ src/xv/fbdev_video_virtual.c | 683 +++++++++++++++++++++ src/xv/fbdev_video_virtual.h | 37 ++ src/xv/i386/fbdev_video_v4l2.c | 834 ++++++++++++++++++++++++++ src/xv/xv_types.h | 80 +++ 44 files changed, 8798 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 man/Makefile.am create mode 100644 man/emulfb.man create mode 100644 packaging/xorg-x11-drv-emulfb.spec create mode 100644 src/Makefile.am create mode 100644 src/crtcconfig/fbdev_crtc.c create mode 100644 src/crtcconfig/fbdev_crtc_priv.h create mode 100644 src/crtcconfig/fbdev_crtcconfig.c create mode 100644 src/crtcconfig/fbdev_crtcconfig.h create mode 100644 src/crtcconfig/fbdev_mode.c create mode 100644 src/crtcconfig/fbdev_mode.h create mode 100644 src/crtcconfig/fbdev_output_priv.h create mode 100644 src/crtcconfig/lcd_output.c create mode 100755 src/debug/fbdev_event_trace.c create mode 100644 src/debug/fbdev_event_trace.h create mode 100644 src/fb/fbdev_fb.c create mode 100644 src/fb/fbdev_fb.h create mode 100644 src/fbdev.c create mode 100644 src/fbdev.h create mode 100644 src/fbdev_dpms.c create mode 100644 src/fbdev_dpms.h create mode 100644 src/fbdevhw/fbdev_hw.c create mode 100644 src/fbdevhw/fbdev_hw.h create mode 100644 src/util/fbdev_pixman.c create mode 100644 src/util/fbdev_pixman.h create mode 100644 src/util/fbdev_util.c create mode 100644 src/util/fbdev_util.h create mode 100644 src/xv/arm/fbdev_video_v4l2.c create mode 100644 src/xv/fbdev_v4l2.c create mode 100644 src/xv/fbdev_v4l2.h create mode 100644 src/xv/fbdev_video.c create mode 100644 src/xv/fbdev_video.h create mode 100644 src/xv/fbdev_video_fourcc.h create mode 100644 src/xv/fbdev_video_types.h create mode 100644 src/xv/fbdev_video_v4l2.h create mode 100644 src/xv/fbdev_video_virtual.c create mode 100644 src/xv/fbdev_video_virtual.h create mode 100644 src/xv/i386/fbdev_video_v4l2.c create mode 100644 src/xv/xv_types.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..edf3b5c --- /dev/null +++ b/AUTHORS @@ -0,0 +1,3 @@ +SooChan Lim +SangJin Lee +Boram Park diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..05596fe --- /dev/null +++ b/COPYING @@ -0,0 +1,24 @@ +Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved. +Copyright (C) 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is fur- +nished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- +NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON- +NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the XFree86 Project shall not +be used in advertising or otherwise to promote the sale, use or other deal- +ings in this Software without prior written authorization from the XFree86 +Project. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..181a903 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,5 @@ +2010-08-30 SooChan Lim + + Initial version of xserver-xorg-video-emulfb + + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..7052905 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,22 @@ +# Copyright 2005 Adam Jackson. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +AUTOMAKE_OPTIONS = foreign +SUBDIRS = src man diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..218197d --- /dev/null +++ b/autogen.sh @@ -0,0 +1,12 @@ +#! /bin/sh + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +autoreconf -v --install || exit 1 +cd $ORIGDIR || exit $? + +#$srcdir/configure --enable-maintainer-mode "$@" diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..8bebed3 --- /dev/null +++ b/configure.ac @@ -0,0 +1,116 @@ +# Copyright 2005 Adam Jackson. +# Copyright (C) 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Process this file with autoconf to produce a configure script + +AC_PREREQ(2.57) +AC_INIT([xserver-xorg-video-emulfb], + 0.1.0, + [https://], + xserver-xorg-video-emulfb) + +AC_CONFIG_SRCDIR([Makefile.am]) +AM_CONFIG_HEADER([config.h]) +AC_CONFIG_AUX_DIR(.) + +AM_INIT_AUTOMAKE([dist-bzip2]) + +AM_MAINTAINER_MODE + +# Checks for programs. +AC_DISABLE_STATIC +AC_PROG_LIBTOOL +AC_PROG_CC +AM_PROG_AS + +AH_TOP([#include "xorg-server.h"]) + +AC_ARG_WITH(xorg-module-dir, + AC_HELP_STRING([--with-xorg-module-dir=DIR], + [Default xorg module directory [[default=$libdir/xorg/modules]]]), + [moduledir="$withval"], + [moduledir="$libdir/xorg/modules"]) + +AC_ARG_ENABLE(pciaccess, + AS_HELP_STRING([--enable-pciaccess], + [Enable use of libpciaccess (default: disabled)]), + [PCIACCESS=$enableval], [PCIACCESS=no]) + +AC_ARG_ENABLE(arm, + AS_HELP_STRING([--enable-arm], + [Enable arm (default: enabled)]), + [ARM=$enableval], [ARM=no]) + +# Checks for extensions +XORG_DRIVER_CHECK_EXT(RANDR, randrproto) +XORG_DRIVER_CHECK_EXT(RENDER, renderproto) +XORG_DRIVER_CHECK_EXT(XV, videoproto) + +# Checks for pkg-config packages +PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.99.901 xproto fontsproto $REQUIRED_MODULES]) +sdkdir=$(pkg-config --variable=sdkdir xorg-server) + +# check the conditions +EMULFB_CFALGS="" +EMULFB_LIBS="" + +PKG_CHECK_MODULES(DLOG, dlog) +PKG_CHECK_MODULES(DRM, libdrm) +PKG_CHECK_MODULES(PIXMAN, pixman-1) + +EMULFB_CFLAGS="$EMULFB_CFLAGS $DLOG_CFLAGS $PIXMAN_CFLAGS $DRM_CFLAGS " +EMULFB_LIBS="$EMULFB_LIBS $DLOG_LIBS $PIXMAN_LIBS $DRM_LIBS " + + +AM_CONDITIONAL(ENABLE_ARM, [test "x$ARM" = xyes]) +if test "x$ARM" = xyes; then + AC_DEFINE(ENABLE_ARM, 1, [Enable arm]) +fi + +AM_CONDITIONAL(PCIACCESS, [test "x$PCIACCESS" = xyes]) +if test "x$PCIACCESS" = xyes; then + AC_DEFINE(PCIACCESS, 1, [Use libpciaccess]) + PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0]) + XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS " +fi + +# Checks for libraries. + +# Checks for header files. +AC_HEADER_STDC + +AC_SUBST([EMULFB_CFLAGS]) +AC_SUBST([EMULFB_LIBS]) + +AC_SUBST([XORG_CFLAGS]) +AC_SUBST([moduledir]) + +DRIVER_NAME=emulfb +AC_SUBST([DRIVER_NAME]) + +XORG_MANPAGE_SECTIONS +XORG_RELEASE_VERSION + +AC_OUTPUT([ + Makefile + src/Makefile + man/Makefile +]) diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 0000000..ecd9bb8 --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1,57 @@ +# $Id$ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright (C) 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +drivermandir = $(DRIVER_MAN_DIR) + +driverman_PRE = @DRIVER_NAME@.man + +driverman_DATA = $(driverman_PRE:man=@DRIVER_MAN_SUFFIX@) + +EXTRA_DIST = @DRIVER_NAME@.man + +CLEANFILES = $(driverman_DATA) + +SED = sed + +# Strings to replace in man pages +XORGRELSTRING = @PACKAGE_STRING@ + XORGMANNAME = X Version 11 + +MAN_SUBSTS = \ + -e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ + -e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ + -e 's|__xservername__|Xorg|g' \ + -e 's|__xconfigfile__|xorg.conf|g' \ + -e 's|__projectroot__|$(prefix)|g' \ + -e 's|__appmansuffix__|$(APP_MAN_SUFFIX)|g' \ + -e 's|__drivermansuffix__|$(DRIVER_MAN_SUFFIX)|g' \ + -e 's|__adminmansuffix__|$(ADMIN_MAN_SUFFIX)|g' \ + -e 's|__miscmansuffix__|$(MISC_MAN_SUFFIX)|g' \ + -e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g' + +SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man + +.man.$(DRIVER_MAN_SUFFIX): + sed $(MAN_SUBSTS) < $< > $@ diff --git a/man/emulfb.man b/man/emulfb.man new file mode 100644 index 0000000..aed60ce --- /dev/null +++ b/man/emulfb.man @@ -0,0 +1,63 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/fbdev/fbdev.man,v 1.2 2001/01/27 18:20:47 dawes Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH FBDEV __drivermansuffix__ __vendorversion__ +.SH NAME +fbdev \- video driver for framebuffer device +.SH SYNOPSIS +.nf +.B "Section \*qDevice\*q" +.BI " Identifier \*q" devname \*q +.B " Driver \*qfbdev\*q" +.BI " BusID \*qpci:" bus : dev : func \*q +\ \ ... +.B EndSection +.fi +.SH DESCRIPTION +.B fbdev +is an __xservername__ driver for framebuffer devices. This is a non-accelerated +driver, the following framebuffer depths are supported: 8, 15, 16, 24. +All visual types are supported for depth 8, and TrueColor visual is +supported for the other depths. Multi-head configurations are supported. +.SH SUPPORTED HARDWARE +The +.B fbdev +driver supports all hardware where a framebuffer driver is available. +fbdev uses the os-specific submodule fbdevhw(__drivermansuffix__) to talk +to the kernel +device driver. Currently a fbdevhw module is available for linux. +.SH CONFIGURATION DETAILS +Please refer to __xconfigfile__(__filemansuffix__) for general configuration +details. This section only covers configuration details specific to +this driver. +.PP +For this driver it is not required to specify modes in the screen +section of the config file. The +.B fbdev +driver can pick up the currently used video mode from the framebuffer +driver and will use it if there are no video modes configured. +.PP +For PCI boards you might have to add a BusID line to the Device +section. See above for a sample line. You can use \*q\__xservername__ +-scanpci\*q +to figure out the correct values. +.PP +The following driver +.B Options +are supported: +.TP +.BI "Option \*qfbdev\*q \*q" string \*q +The framebuffer device to use. Default: /dev/fb0. +.TP +.BI "Option \*qShadowFB\*q \*q" boolean \*q +Enable or disable use of the shadow framebuffer layer. Default: on. +.TP +.BI "Option \*qRotate\*q \*q" string \*q +Enable rotation of the display. The supported values are "CW" (clockwise, +90 degrees), "UD" (upside down, 180 degrees) and "CCW" (counter clockwise, +270 degrees). Implies use of the shadow framebuffer layer. Default: off. +.SH "SEE ALSO" +__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), +X(__miscmansuffix__), fbdevhw(__drivermansuffix__) +.SH AUTHORS +Authors include: Gerd Knorr, Michel D\(:anzer, Geert Uytterhoeven diff --git a/packaging/xorg-x11-drv-emulfb.spec b/packaging/xorg-x11-drv-emulfb.spec new file mode 100644 index 0000000..5677862 --- /dev/null +++ b/packaging/xorg-x11-drv-emulfb.spec @@ -0,0 +1,70 @@ +# >> macros +# << macros + +Name: xorg-x11-drv-emulfb +Summary: X.Org X server driver for sdk emulation +Version: 0.5.6 +Release: 1 +#ExclusiveArch: %arm +Group: System/X Hardware Support +License: Samsung +Source0: %{name}-%{version}.tar.gz + +BuildRequires: prelink +BuildRequires: xorg-x11-xutils-dev +BuildRequires: pkgconfig(xorg-server) +BuildRequires: pkgconfig(randrproto) +BuildRequires: pkgconfig(renderproto) +BuildRequires: pkgconfig(fontsproto) +BuildRequires: pkgconfig(xproto) +BuildRequires: pkgconfig(videoproto) +BuildRequires: pkgconfig(resourceproto) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(libdrm) +BuildRequires: pkgconfig(pixman-1) + +%description +This package provides the driver for sdk emulation + +%prep +%setup -q + +# >> setup +# << setup + +%build +# >> build pre +# << build pre + +%ifarch %{arm} +%define ENABLE_ARM --enable-arm +%else +%define ENABLE_ARM --disable-arm +%endif + +%reconfigure --disable-static %{ENABLE_ARM} \ + CFLAGS="-Wall -Werror ${CFLAGS}" LDFLAGS="${LDFLAGS} -Wl,--hash-style=both -Wl,--as-needed" + +make %{?jobs:-j%jobs} + +# >> build post +# << build post +%install +rm -rf %{buildroot} +# >> install pre +# << install pre +mkdir -p %{buildroot}/usr/share/license +cp -af COPYING %{buildroot}/usr/share/license/%{name} +%make_install + +# >> install post +execstack -c %{buildroot}%{_libdir}/xorg/modules/drivers/emulfb_drv.so +# << install post + +%files +%defattr(-,root,root,-) +# >> files emulfb +%{_libdir}/xorg/modules/drivers/*.so +%{_datadir}/man/man4/* +# << files emulfb +/usr/share/license/%{name} diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..7eaedb7 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,80 @@ +# Copyright 2005 Adam Jackson. +# Copyright (C) 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# this is obnoxious: +# -module lets us name the module exactly how we want +# -avoid-version prevents gratuitous .0.0.0 version numbers on the end +# _ladir passes a dummy rpath to libtool so the thing will actually link +# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. + +AM_CFLAGS = -I@top_srcdir@/src @XORG_CFLAGS@ @EMULFB_CFLAGS@ +emulfb_drv_la_LTLIBRARIES = emulfb_drv.la +#emulfb_drv_la_LDFLAGS = -module -avoid-version @EMULFB_LIBS@ +emulfb_drv_la_LDFLAGS = -module -avoid-version +emulfb_drv_la_LIBADD = @EMULFB_LIBS@ +emulfb_drv_ladir = @moduledir@/drivers + +# common +emulfb_drv_la_SOURCES = \ + fbdev.c \ + fb/fbdev_fb.c \ + fbdev_dpms.c +AM_CFLAGS += -I@top_srcdir@/src/fb + +if ENABLE_ARM + xvtarget = arm +else + xvtarget = i386 +endif + +# xv +emulfb_drv_la_SOURCES += \ + xv/fbdev_video.c \ + xv/fbdev_video_virtual.c \ + xv/fbdev_v4l2.c \ + xv/${xvtarget}/fbdev_video_v4l2.c +AM_CFLAGS += -I@top_srcdir@/src/xv +AM_CFLAGS += -I@top_srcdir@/src/xv/${xvtarget} + +# fbdevhw +emulfb_drv_la_SOURCES += \ + fbdevhw/fbdev_hw.c +AM_CFLAGS += -I@top_srcdir@/src/fbdevhw + +# util +emulfb_drv_la_SOURCES += \ + util/fbdev_util.c \ + util/fbdev_pixman.c +AM_CFLAGS += -I@top_srcdir@/src/util + +# crtcconfig +emulfb_drv_la_SOURCES += \ + crtcconfig/fbdev_crtcconfig.c \ + crtcconfig/fbdev_crtc.c \ + crtcconfig/lcd_output.c \ + crtcconfig/fbdev_mode.c +AM_CFLAGS += -I@top_srcdir@/src/crtcconfig + +# crtcconfig +emulfb_drv_la_SOURCES += \ + debug/fbdev_event_trace.c +AM_CFLAGS += -I@top_srcdir@/src/debug + diff --git a/src/crtcconfig/fbdev_crtc.c b/src/crtcconfig/fbdev_crtc.c new file mode 100644 index 0000000..478836d --- /dev/null +++ b/src/crtcconfig/fbdev_crtc.c @@ -0,0 +1,250 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "xace.h" +#include "xacestr.h" +#include + +#include "fbdev.h" +#include "fbdevhw.h" +#include "fbdev_hw.h" +#include "fbdev_crtc_priv.h" +#include "fbdev_util.h" + +#include "xf86Crtc.h" +#include "xf86Xinput.h" +#include "exevents.h" + +/********************************************************************************************/ +/* Implementation of Crtc entry points */ +/********************************************************************************************/ +/** + * Turns the crtc on/off, or sets intermediate power levels if available. + * + * Unsupported intermediate modes drop to the lower power setting. If the + * mode is DPMSModeOff, the crtc must be disabled sufficiently for it to + * be safe to call mode_set. + */ +static void fbdev_crtc_dpms(xf86CrtcPtr crtc, int mode) +{ + return; +} + +/** + * Lock CRTC prior to mode setting, mostly for DRI. + * Returns whether unlock is needed + */ +static Bool fbdev_crtc_lock(xf86CrtcPtr crtc) +{ + + /* check whether unlock is needed */ + return TRUE; +} + +/** + * Lock CRTC prior to mode setting, mostly for DRI. + * Returns whether unlock is needed + */ +static void fbdev_crtc_unlock(xf86CrtcPtr crtc) +{ + return; +} + + +/** + * Callback to adjust the mode to be set in the CRTC. + * + * This allows a CRTC to adjust the clock or even the entire set of + * timings, which is used for panels with fixed timings or for + * buses with clock limitations. + */ +static Bool fbdev_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +/** + * Prepare CRTC for an upcoming mode set. + */ +static void fbdev_crtc_prepare(xf86CrtcPtr crtc) +{ + +} + +/** + * Callback for setting up a video mode after fixups have been made. + */ +static void fbdev_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode, int x, int y) +{ + +} + +/** + * Commit mode changes to a CRTC + */ +static void fbdev_crtc_commit(xf86CrtcPtr crtc) +{ + +} + +/* Set the color ramps for the CRTC to the given values. */ +static void fbdev_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, + CARD16 * blue, int size) +{ + +} + +/** + * Set cursor colors + */ +void fbdev_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) +{ + return; +} + +/** + * Set cursor position + */ +void fbdev_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) +{ + + return; +} + +/** + * Show cursor + */ +void fbdev_crtc_show_cursor(xf86CrtcPtr crtc) +{ + + return; +} + +/** + * Hide cursor + */ +void fbdev_crtc_hide_cursor(xf86CrtcPtr crtc) +{ + + return; +} + +/** + * Load ARGB image + */ +void fbdev_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) +{ + + return; +} + +/** + * Less fine-grained mode setting entry point for kernel modesetting + */ +Bool fbdev_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, + Rotation rotation, int x, int y) +{ + return TRUE; +} + + +/** + * Callback for panning. Doesn't change the mode. + * Added in ABI version 2 + */ +static void fbdev_crtc_set_origin(xf86CrtcPtr crtc, int x, int y) +{ + xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "set_origin: unimplemented"); + return; /* XXX implement */ +} + +/* crtc funcs */ +static const xf86CrtcFuncsRec fbdev_crtc_funcs = +{ + .dpms = fbdev_crtc_dpms, + .save = NULL, /* XXX */ + .restore = NULL, /* XXX */ + .lock = fbdev_crtc_lock, + .unlock = fbdev_crtc_unlock, + .mode_fixup = fbdev_crtc_mode_fixup, + + .prepare = fbdev_crtc_prepare, + .mode_set = fbdev_crtc_mode_set, + .commit = fbdev_crtc_commit, + .gamma_set = fbdev_crtc_gamma_set, + + .shadow_create = NULL, + .shadow_allocate = NULL, + .shadow_destroy = NULL, + + .set_cursor_colors = fbdev_crtc_set_cursor_colors, + .set_cursor_position = fbdev_crtc_set_cursor_position, + .show_cursor = fbdev_crtc_show_cursor, + .hide_cursor = fbdev_crtc_hide_cursor, + .load_cursor_argb = fbdev_crtc_load_cursor_argb, + .destroy = NULL, /* XXX */ + .set_mode_major = NULL, /*???*/ +#if RANDR_13_INTERFACE + .set_origin = fbdev_crtc_set_origin, +#endif +}; + +void FBDevCrtcInit(ScrnInfoPtr pScrn, int num) +{ + xf86CrtcPtr crtc; + FBDevCrtcPrivPtr fbdev_crtc; + + crtc = xf86CrtcCreate (pScrn, &fbdev_crtc_funcs); + if (crtc == NULL) + return; + + fbdev_crtc = xnfcalloc (sizeof (FBDevCrtcPriv), 1); + if (!fbdev_crtc) + { + xf86CrtcDestroy (crtc); + return; + } + + crtc->driver_private = fbdev_crtc; + +} + + diff --git a/src/crtcconfig/fbdev_crtc_priv.h b/src/crtcconfig/fbdev_crtc_priv.h new file mode 100644 index 0000000..7919fab --- /dev/null +++ b/src/crtcconfig/fbdev_crtc_priv.h @@ -0,0 +1,45 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef _FBDEV_CRTC_PRIV_H_ +#define _FBDEV_CRTC_PRIV_H_ + +#include "fbdev.h" + +/* fbdev crtc private infomation */ +typedef struct _fbdevCrtcPriv +{ + int type; + +} FBDevCrtcPriv, *FBDevCrtcPrivPtr; +#define FBDEVCRTCPTR(o) ((FBDevCrtcPrivPtr)((o)->driver_private)) + +void FBDevCrtcInit(ScrnInfoPtr pScrn, int num); +#endif // _FBDEV_CRTC_PRIV_H_ diff --git a/src/crtcconfig/fbdev_crtcconfig.c b/src/crtcconfig/fbdev_crtcconfig.c new file mode 100644 index 0000000..412162b --- /dev/null +++ b/src/crtcconfig/fbdev_crtcconfig.c @@ -0,0 +1,139 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "fbdev.h" +#include "fbdevhw.h" +#include "fbdev_crtcconfig.h" +#include "fbdev_crtc_priv.h" +#include "fbdev_output_priv.h" + +#include "xf86Crtc.h" + +#define MIN_CRTC_DPY_WIDTH 320 +#define MAX_CRTC_DPY_WIDTH 1024 +#define MIN_CRTC_DPY_HEIGHT 200 +#define MAX_CRTC_DPY_HEIGHT 1024 + +#define NUM_CRTCS 1 + +/** + * Requests that the driver resize the screen. + * + * The driver is responsible for updating scrn->virtualX and scrn->virtualY. + * If the requested size cannot be set, the driver should leave those values + * alone and return FALSE. + * + * A naive driver that cannot reallocate the screen may simply change + * virtual[XY]. A more advanced driver will want to also change the + * devPrivate.ptr and devKind of the screen pixmap, update any offscreen + * pixmaps it may have moved, and change pScrn->displayWidth. + */ +static Bool fbdev_crtc_config_resize (ScrnInfoPtr scrn, int width, int height) +{ + + scrn->virtualX = width; + scrn->virtualY = height; + + return TRUE; +} + + +/* crtc_config_func */ +static const xf86CrtcConfigFuncsRec fbdev_crtc_config_funcs = +{ + .resize = fbdev_crtc_config_resize, +}; + + +/* + * Initialize the CrtcConfig. + * And initialize the mode setting throught create the avaliable crtcs and outputs + * then Initialize the Configuration of Crtc + */ +Bool FBDevCrtcConfigInit(ScrnInfoPtr pScrn) +{ + int min_width, max_width, min_height, max_height; + xf86CrtcConfigPtr crtc_config; + int i, o, c; + FBDevPtr pFBDev = FBDEVPTR(pScrn); + /* TODO: check this routines later whether it is right setting */ + { + + fbdevHWUseBuildinMode(pScrn); /* sets pScrn->modes */ + pScrn->modes = xf86DuplicateMode(pScrn->modes); /* well done, fbdevhw. */ + pScrn->modes->name = NULL; /* fbdevhw string can't be freed */ + pScrn->modes->type = M_T_DRIVER | M_T_PREFERRED; + pScrn->currentMode = pScrn->modes; + pFBDev->builtin = xf86DuplicateMode(pScrn->modes); + + } + + /* allocate an xf86CrtcConfig */ + xf86CrtcConfigInit(pScrn, &fbdev_crtc_config_funcs); + crtc_config = XF86_CRTC_CONFIG_PTR (pScrn); + + min_width = pScrn->modes->HDisplay; + max_width = pScrn->modes->HDisplay; + min_height = pScrn->modes->VDisplay; + max_height = pScrn->modes->VDisplay; + + xf86CrtcSetSizeRange(pScrn, min_width, min_height, max_width, max_height); + + /* set up the crtcs */ + for( i = 0; i < NUM_CRTCS; i++) + FBDevCrtcInit(pScrn, i); + + /* set up the outputs */ + LcdOutputInit(pScrn); + + /* [TODO]: set the crtc to the output in some manner ???? */ + for (o = 0; o < crtc_config->num_output; o++) + { + xf86OutputPtr output = crtc_config->output[o]; + int crtc_mask; + + crtc_mask = 0; + for (c = 0; c < crtc_config->num_crtc; c++) + { + crtc_mask |= (1 << c); + } + output->possible_crtcs = crtc_mask; + output->possible_clones = FALSE; + } + + /* initialize the configuration */ + if(!xf86InitialConfiguration(pScrn, TRUE)) + { + return FALSE; + } + + return TRUE; + +} diff --git a/src/crtcconfig/fbdev_crtcconfig.h b/src/crtcconfig/fbdev_crtcconfig.h new file mode 100644 index 0000000..d84928a --- /dev/null +++ b/src/crtcconfig/fbdev_crtcconfig.h @@ -0,0 +1,37 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef _FBDEV_CRTCCONFIG_H_ +#define _FBDEV_CRTCCONFIG_H_ + +Bool FBDevCrtcConfigInit(ScrnInfoPtr pScrn); + + +#endif // _FBDEV_CRTCCONFIG_H_ diff --git a/src/crtcconfig/fbdev_mode.c b/src/crtcconfig/fbdev_mode.c new file mode 100644 index 0000000..446417d --- /dev/null +++ b/src/crtcconfig/fbdev_mode.c @@ -0,0 +1,173 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + +#include "fbdev.h" + +#include +#include "fbdev_hw.h" +#include "fbdev_mode.h" + +typedef struct _FBDevDisplayModeRec +{ + char name[32]; /* identifier for the mode */ + + /* These are the values that the user sees/provides */ + int Clock; /* pixel clock freq (kHz) */ + int HDisplay; /* horizontal timing */ + int HSyncStart; + int HSyncEnd; + int HTotal; + int HSkew; + int VDisplay; /* vertical timing */ + int VSyncStart; + int VSyncEnd; + int VTotal; + int VScan; + int Flags; + +} FBDevDisplayModeRec, *FBDevDisplayModePtr; + +/* [soolim: 20100206][TODO] : it has to be recalculated when it comes to change the target framebuffer + * The display mode data has to be changed whenever the target is changed + * Always check it out. + */ +const FBDevDisplayModeRec fbdevDisplayModes[] = +{ + /* CGA ( 320 x 200 ) */ + {"320x200", 38, 320, 336, 338, 354, 0, 200, 203, 205, 233, 0, 0,}, + /* QVGA ( 320 x 240 ) */ + {"320x240", 38, 320, 336, 338, 354, 0, 240, 243, 245, 273, 0, 0,}, + /* XX ( 240 x 400 ) */ + {"240x400", 38, 240, 256, 258, 274, 0, 400, 428, 430, 433, 0, 0,}, + /* HVGA (320 x 480 ) */ + {"320x480", 38, 320, 336, 338, 354, 0, 480, 483, 485, 513, 0, 0,}, + /* WVGA ( 480 x 720 ) */ + {"480x720", 38, 480, 496, 498, 514, 0, 720, 723, 725, 753, 0, 0}, + /* WVGA ( 480 x 800 ) */ + {"480x800", 38, 480, 496, 498, 514, 0, 800, 803, 805, 833, 0, 0}, + /* VGA ( 640 x 480 ) */ + {"640x480", 19, 640, 840, 880, 959, 0, 480, 491, 501, 511, 0, 0,}, + /* NTSC ( 720 x 480 ) */ + {"720x480", 19, 720, 920, 960, 1039, 0, 480, 491, 501, 511, 0, 0,}, + /* PAL ( 768 x 576 ) */ + {"768x576", 19, 768, 968, 1008, 1087, 0, 576, 587, 597, 607, 0, 0,}, + /* WVGA ( 800 x 480 ) */ + {"800x480", 19, 800, 1000, 1040, 1119, 0, 480, 491, 501, 511, 0, 0}, + /* WVGA ( 854 x 480 ) */ + {"854x480", 19, 854, 1054, 1094, 1173, 0, 480, 491, 501, 511, 0, 0,}, + /* WSVGA ( 600 x 1024 ) */ + {"600x1024", 19, 600, 611, 621, 631, 0, 1024, 1224, 1264, 1343, 0, 0}, + /* WSVGA ( 1024 x 600 ) */ + {"1024x600", 19, 1024, 1224, 1264, 1343, 0, 600, 611, 621, 631, 0, 0}, +#if 0 + /* XGA ( 1024 x 768 ) */ + {"1024x768", 19, 1024, 1224, 1264, 1343, 600, 611, 621, 631, 0,}, +#endif +}; + + +#define NUM_DISPLAY_MODES (sizeof(fbdevDisplayModes)/sizeof(fbdevDisplayModes[0])) + +const int fbdevNumDisplayModes = NUM_DISPLAY_MODES; + + +DisplayModePtr +FBDevGetSupportModes(DisplayModePtr builtin_mode) +{ + DisplayModePtr pMode = NULL; + DisplayModePtr prev_pMode = NULL; + DisplayModePtr ret_pMode = NULL; + int i; + int clock = 0; + if(builtin_mode) + clock = builtin_mode->Clock; + else + clock = 0; + + for(i=0; i< fbdevNumDisplayModes; i++) + { + pMode = calloc(1, sizeof(DisplayModeRec)); + pMode->next = NULL; + pMode->prev = NULL; + pMode->name = calloc(1, sizeof(char)*32); + sprintf(pMode->name,"%s", fbdevDisplayModes[i].name); + pMode->status = MODE_OK; + pMode->type = M_T_DRIVER | M_T_PREFERRED; + + pMode->Clock = clock; + pMode->HDisplay = fbdevDisplayModes[i].HDisplay; + pMode->HSyncStart = fbdevDisplayModes[i].HSyncStart; + pMode->HSyncEnd = fbdevDisplayModes[i].HSyncEnd; + pMode->HTotal = fbdevDisplayModes[i].HTotal; + pMode->HSkew = fbdevDisplayModes[i].HSkew; + pMode->VDisplay = fbdevDisplayModes[i].VDisplay; + pMode->VSyncStart = fbdevDisplayModes[i].VSyncStart; + pMode->VSyncEnd = fbdevDisplayModes[i].VSyncEnd; + pMode->VTotal = fbdevDisplayModes[i].VTotal; + pMode->VScan = fbdevDisplayModes[i].VScan; + pMode->Flags = fbdevDisplayModes[i].Flags; + + if(prev_pMode) + { + pMode->prev = prev_pMode; + prev_pMode->next = pMode; + prev_pMode = prev_pMode->next; + } + else + { + prev_pMode = pMode; + ret_pMode = pMode; + } + + pMode = NULL; + } + + return ret_pMode; +} + +#define OPTION_PREFERRED_MODE 0 + +char * +FBDevCheckPreferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + char *preferred_mode = NULL; + + /* Check for a configured preference for a particular mode */ + preferred_mode = xf86GetOptValString (output->options, + OPTION_PREFERRED_MODE); + if (preferred_mode) + return preferred_mode; + + if (pScrn->display->modes && *pScrn->display->modes) + preferred_mode = *pScrn->display->modes; + + return preferred_mode; +} diff --git a/src/crtcconfig/fbdev_mode.h b/src/crtcconfig/fbdev_mode.h new file mode 100644 index 0000000..3cd7417 --- /dev/null +++ b/src/crtcconfig/fbdev_mode.h @@ -0,0 +1,44 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef FBDEV_MODE_H +#define FBDEV_MODE_H + +#include "xf86Crtc.h" + +DisplayModePtr +FBDevGetSupportModes(DisplayModePtr builtin_mode); + +char * +FBDevCheckPreferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output); + +#endif //FBDEV_MODE_H + + diff --git a/src/crtcconfig/fbdev_output_priv.h b/src/crtcconfig/fbdev_output_priv.h new file mode 100644 index 0000000..ade694b --- /dev/null +++ b/src/crtcconfig/fbdev_output_priv.h @@ -0,0 +1,46 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef _FBDEV_OUTPUT_PRIV_H_ +#define _FBDEV_OUTPUT_PRIV_H_ + +/* fbdev output private infomation */ +typedef struct _fbdevOutputPriv +{ + int type; + void *devPrivate; +} FBDevOutputPriv, *FBDevOutputPrivPtr; +#define FBDEVOUTPUTPTR(o) ((FBDevOutputPrivPtr)((o)->driver_private)) + +void LcdOutputInit(ScrnInfoPtr pScrn); + +#endif // _FBDEV_OUTPUT_PRIV_H_ + + diff --git a/src/crtcconfig/lcd_output.c b/src/crtcconfig/lcd_output.c new file mode 100644 index 0000000..b47f333 --- /dev/null +++ b/src/crtcconfig/lcd_output.c @@ -0,0 +1,300 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "fbdev.h" +#include "fbdev_output_priv.h" +#include "fbdev_mode.h" +#include "fbdev_util.h" +#include "fbdev_video.h" + +#include + +#define STR_XRR_VIDEO_OFFSET_PROPERTY "XRR_PROPERTY_VIDEO_OFFSET" + +static Bool g_video_offset_prop_init = FALSE; + +static Atom xrr_property_video_offset_atom; + +static Bool +_lcd_output_prop_video_offset (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value) +{ + int x, y; + char str[128]; + char *p; + + if (g_video_offset_prop_init == FALSE) + { + xrr_property_video_offset_atom = MakeAtom (STR_XRR_VIDEO_OFFSET_PROPERTY, + strlen (STR_XRR_VIDEO_OFFSET_PROPERTY), TRUE); + g_video_offset_prop_init = TRUE; + } + + if (xrr_property_video_offset_atom != property) + return FALSE; + + if (!value || !value->data || value->size == 0) + return TRUE; + + if (value->format != 8) + return TRUE; + + snprintf (str, sizeof(str), "%s", (char*)value->data); + + p = strtok (str, ","); + return_val_if_fail (p != NULL, FALSE); + x = atoi (p); + + p = strtok (NULL, ","); + return_val_if_fail (p != NULL, FALSE); + y = atoi (p); + + DRVLOG ("%s : offset(%d,%d) \n", __FUNCTION__, x, y); + + fbdevVideoSetOffset (pOutput->scrn, x, y); + + return TRUE; +} + + +/********************************************************************************************/ +/* Implementation of Output entry points */ +/********************************************************************************************/ +static void lcd_output_create_resources(xf86OutputPtr output) +{ +} + +static void lcd_output_dpms(xf86OutputPtr output, int mode) +{ + return; +} + +static void lcd_output_save(xf86OutputPtr output) +{ + return; +} + +static void lcd_output_restore(xf86OutputPtr output) +{ + return; +} + +static int lcd_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode) +{ + FBDevPtr pFBDev = FBDEVPTR(output->scrn); + + if(pFBDev->builtin->HDisplay < mode->HDisplay) + return MODE_HSYNC; + + if(pFBDev->builtin->VDisplay < mode->VDisplay) + return MODE_VSYNC; + + output->scrn->currentMode = mode; + + return MODE_OK; + +} + +static Bool lcd_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +static void lcd_output_prepare(xf86OutputPtr output) +{ + return; +} + +static void lcd_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output ->scrn; + FBDevPtr pFBDev = FBDEVPTR(pScrn); + + /* have to set the physical size of the output */ + output->mm_width = pFBDev->var.width; + output->mm_height = pFBDev->var.height; + output->conf_monitor->mon_width = pFBDev->var.width; + output ->conf_monitor->mon_height = pFBDev->var.height; + + return; +} + +static void lcd_output_commit(xf86OutputPtr output) +{ + return; +} + +static xf86OutputStatus lcd_output_detect(xf86OutputPtr output) +{ + return XF86OutputStatusConnected; +} + + + +/** + * Name : lcd_output_get_modes + * Input : xf86OutputPtr + * Return : DisplayModePtr + * Description : Query the device for the modes it provides. + This function may also update MonInfo, mm_width, and mm_height. + return singly-linked list of modes or NULL if no modes found. + + */ +static int first_time_rotated = TRUE; +static DisplayModePtr lcd_output_get_modes(xf86OutputPtr output) +{ + FBDevPtr pFBDev = FBDEVPTR(output->scrn); + + /* [soolim:20100205] : if there is no mode name in xorg.conf, use the builtin mode */ + char *preferred_mode; + preferred_mode = FBDevCheckPreferredMode(output->scrn, output); + if(!preferred_mode) + { + int HDisplay, VDisplay; + + Bool rotated = (pFBDev->rotate & (RR_Rotate_90|RR_Rotate_270)) != 0; + + if(rotated) + { + if(first_time_rotated) + { + memcpy(&pFBDev->builtin_saved, pFBDev->builtin, sizeof(*pFBDev->builtin)); + VDisplay = pFBDev->builtin->VDisplay; + HDisplay = pFBDev->builtin->HDisplay; + pFBDev->builtin->HDisplay = VDisplay; + pFBDev->builtin->VDisplay = HDisplay; + pFBDev->builtin->name = "fake_mode"; + first_time_rotated = FALSE; + } + return xf86DuplicateMode(pFBDev->builtin); + } + else + { + return xf86DuplicateMode(pFBDev->builtin); + } + } + + /* [soolim:20100205] : gets the supported modes from framebuffer and makes the list */ + DisplayModePtr support_modes = NULL; + + if(!pFBDev->support_modes) + { + support_modes = FBDevGetSupportModes(pFBDev->builtin); + if(pFBDev->builtin != NULL) + { + if(!pFBDev->builtin->next) + { + support_modes->prev = pFBDev->builtin; + pFBDev->builtin->next = support_modes; + pFBDev->builtin->prev = NULL; + } + } + else + { + pFBDev->builtin = support_modes; + } + } + + return support_modes; +} + +static Bool lcd_output_set_property(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value) +{ + if (_lcd_output_prop_video_offset (output, property, value)) + return TRUE; + + return TRUE; +} + +static Bool lcd_output_get_property(xf86OutputPtr output, Atom property) +{ + return TRUE; +} + +static xf86CrtcPtr lcd_output_crtc_get(xf86OutputPtr output) +{ + return 0; +} + +static void lcd_output_destroy(xf86OutputPtr output) +{ + return; +} + + +/* output funcs */ +static const xf86OutputFuncsRec lcd_output_funcs = +{ + .create_resources = lcd_output_create_resources, + .destroy = lcd_output_destroy, + .dpms = lcd_output_dpms, + .save = lcd_output_save, + .restore = lcd_output_restore, + .mode_valid = lcd_output_mode_valid, + + .mode_fixup = lcd_output_mode_fixup, + .prepare = lcd_output_prepare, + .mode_set = lcd_output_mode_set, + .commit = lcd_output_commit, + .detect = lcd_output_detect, + .get_modes = lcd_output_get_modes, +#ifdef RANDR_12_INTERFACE + .set_property = lcd_output_set_property, +#endif +#ifdef RANDR_13_INTERFACE /* not a typo */ + .get_property = lcd_output_get_property, +#endif +#ifdef RANDR_GET_CRTC_INTERFACE + .get_crtc = lcd_output_crtc_get, +#endif +}; + +void LcdOutputInit(ScrnInfoPtr pScrn) +{ + xf86OutputPtr output; + FBDevOutputPrivPtr lcd_output; + + output = xf86OutputCreate (pScrn, &lcd_output_funcs, "LVDS1"); + if (!output) + return; + lcd_output = xnfcalloc (sizeof (FBDevOutputPriv), 1); + if (!lcd_output) + { + xf86OutputDestroy (output); + return; + } + + output->driver_private = lcd_output; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; + +} diff --git a/src/debug/fbdev_event_trace.c b/src/debug/fbdev_event_trace.c new file mode 100755 index 0000000..120633a --- /dev/null +++ b/src/debug/fbdev_event_trace.c @@ -0,0 +1,100 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "fbdev.h" +#include "xace.h" +#include "xacestr.h" + +#if 0 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "windowstr.h" + +#define XREGISTRY +#include "registry.h" + +#define __USE_GNU +#include +#include + +#ifdef HAS_GETPEERUCRED +# include +#endif +#endif + +static void +_traceReceive (CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceReceiveAccessRec *rec = calldata; + + if (rec->events->u.u.type != VisibilityNotify) + return; + + rec->status = BadAccess; +} + +Bool +fbdevTraceInstallHooks (void) +{ + int ret = TRUE; + + /*Disable Visibility Event*/ + ret &= XaceRegisterCallback (XACE_RECEIVE_ACCESS, _traceReceive, NULL); + + if (!ret) + { + ErrorF ("fbdevInstallHooks: Failed to register one or more callbacks\n"); + return BadAlloc; + } + + return Success; +} + + +Bool +fbdevTraceUninstallHooks (void) +{ + XaceDeleteCallback (XACE_RECEIVE_ACCESS, _traceReceive, NULL); + + return Success; +} + diff --git a/src/debug/fbdev_event_trace.h b/src/debug/fbdev_event_trace.h new file mode 100644 index 0000000..1b0dbbd --- /dev/null +++ b/src/debug/fbdev_event_trace.h @@ -0,0 +1,38 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef __HEADER_FBDEV_EVENT_TRACE +#define __HEADER_FBDEV_EVENT_TRACE + +Bool fbdevTraceInstallHooks (void); +Bool fbdevTraceUninstallHooks (void); + +#endif /* __HEADER_FBDEV_EVENT_TRACE */ + diff --git a/src/fb/fbdev_fb.c b/src/fb/fbdev_fb.c new file mode 100644 index 0000000..7cd4e05 --- /dev/null +++ b/src/fb/fbdev_fb.c @@ -0,0 +1,298 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "fbdev.h" +#include "fbdev_util.h" +#include "fbdev_fb.h" + +struct s3cfb_user_window +{ + int x; + int y; +}; + +#define S3CFB_WIN_ON _IOW('F', 305, uint) +#define S3CFB_WIN_OFF _IOW('F', 306, uint) +#define S3CFB_WIN_POSITION _IOW('F', 203, struct s3cfb_user_window) +#define S3CFB_WIN_SET_PIXEL_ALPHA _IOW('F', 211, struct fb_var_screeninfo) + +Bool +fbdevFbGetVarScreenInfo (int fd, struct fb_var_screeninfo *fbVarInfo) +{ + int ret; + + return_val_if_fail (fd >= 0, FALSE); + return_val_if_fail (fbVarInfo != NULL, FALSE); + + ret = ioctl (fd, FBIOGET_VSCREENINFO, (void*)fbVarInfo); + + if (ret) + { + xf86DrvMsg (0, X_ERROR, "FBIOGET_VSCREENINFO failed.\n"); + return FALSE; + } + + return TRUE; +} + +Bool +fbdevFbSetVarScreenInfo (int fd, struct fb_var_screeninfo *fbVarInfo) +{ + int ret; + + return_val_if_fail (fd >= 0, FALSE); + return_val_if_fail (fbVarInfo != NULL, FALSE); + + ret = ioctl (fd, FBIOPUT_VSCREENINFO, (void*)fbVarInfo); + + if (ret) + { + xf86DrvMsg (0, X_ERROR, "FBIOPUT_VSCREENINFO failed.\n"); + return FALSE; + } + + return TRUE; +} + +Bool +fbdevFbGetFixScreenInfo (int fd, struct fb_fix_screeninfo *fbFixInfo) +{ + int ret; + + return_val_if_fail (fd >= 0, FALSE); + return_val_if_fail (fbFixInfo != NULL, FALSE); + + ret = ioctl (fd, FBIOGET_FSCREENINFO, (void*)fbFixInfo); + + if (ret) + { + xf86DrvMsg (0, X_ERROR, "FBIOGET_FSCREENINFO failed.\n"); + return FALSE; + } + + return TRUE; +} + +Bool +fbdevFbSetWinPosition (int fd, int x, int y) +{ + struct s3cfb_user_window pos; + int ret; + + return_val_if_fail (fd >= 0, FALSE); + + pos.x = x; + pos.y = y; + + ret = ioctl (fd, S3CFB_WIN_POSITION, &pos); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "S3CFB_WIN_POSITION failed. pos(%d,%d)\n", x, y); + return FALSE; + } + + return TRUE; +} + +Bool +fbdevFbScreenAlphaInit (int fd) +{ + struct fb_var_screeninfo var; + int ret; + + ret = ioctl (fd, FBIOGET_VSCREENINFO, &var); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "failed to get fb_var\n"); + return FALSE; + } + + if (var.bits_per_pixel != 32) + { + xf86DrvMsg (0, X_ERROR, "per pixel overlay alpha is supported with 32 bpp mode\n"); + return FALSE; + } + var.transp.length = 8; + var.activate = FB_ACTIVATE_FORCE; + ret = ioctl (fd, FBIOPUT_VSCREENINFO, &var); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "failed to set fb_var\n"); + return FALSE; + } + + return TRUE; +} + +Bool +fbdevFbScreenAlphaDeinit (int fd) +{ + struct fb_var_screeninfo var; + int ret; + + ret = ioctl (fd, FBIOGET_VSCREENINFO, &var); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "failed to get fb_var\n"); + return FALSE; + } + + var.transp.length = 0; + ret = ioctl (fd, FBIOPUT_VSCREENINFO, &var); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "failed to set fb_var\n"); + return FALSE; + } + + return TRUE; +} + +#include +void +fbdevFbResetLCDModule() +{ + char rmmod[255]; + char insmod[255]; + struct utsname name; + + if (uname (&name)) + { + ErrorF ("Fail get umane\n"); + } + sprintf (rmmod, "/sbin/rmmod s3c_lcd"); + sprintf (insmod, "/sbin/insmod /opt/driver/s3c_lcd.ko"); + + if (system (rmmod)) + ErrorF ("%s failed.\n", rmmod); + if (system (insmod)) + ErrorF ("%s failed.\n", insmod); +} + + +/* activate fb */ +Bool +fbdevFbActivate (int fd) +{ + struct fb_var_screeninfo var; + int ret; + + ret = ioctl (fd, FBIOGET_VSCREENINFO, &var); + if (ret < 0) + { + ErrorF ("failed to get fb_var\n"); + return FALSE; + } + + var.activate = FB_ACTIVATE_FORCE; + + ret = ioctl (fd, FBIOPUT_VSCREENINFO, &var); + if (ret < 0) + { + ErrorF ("failed to set fb_var.activate\n"); + return FALSE; + } + + ret = ioctl (fd, FBIOBLANK, FB_BLANK_UNBLANK); + if (ret < 0) + { + ErrorF ("failed to set FBIOBLANK : FB_BLANK_UNBLANK\n"); + return FALSE; + } + + return TRUE; +} + +/* deactivate fb3 */ +Bool +fbdevFbDeActivate (int fd) +{ + int ret; + + ret = ioctl (fd, FBIOBLANK, FB_BLANK_NORMAL); + if (ret < 0) + { + ErrorF ("failed to set FBIOBLANK : FB_BLANK_NORMAL\n"); + return FALSE; + } + + return TRUE; +} + +Bool +fbdevFbSetBase (int fd) +{ + struct fb_var_screeninfo var; + int ret; + + ret = ioctl (fd, FBIOGET_VSCREENINFO, &var); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "failed to get fb_var\n"); + return FALSE; + } + + var.yoffset = 0; + ret = ioctl (fd, FBIOPAN_DISPLAY,&var); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "failed to set fb_var\n"); + return FALSE; + } + return TRUE; +} + + +void +fbdevFbHWPanDisplay (int fd, int x, int y) +{ + struct fb_var_screeninfo var; + int ret; + + ret = ioctl (fd, FBIOGET_VSCREENINFO, &var); + if (ret < 0) + { + xf86DrvMsg (0, X_WARNING, "!!WARNING::%s::fail to get vscreen_info\n", + __func__); + return; + } + + var.xoffset = x; + var.yoffset = y; + ret = ioctl (fd, FBIOPAN_DISPLAY, &var); + if (ret < 0) + { + xf86DrvMsg (0, X_WARNING, "!!WARNING::%s::fail to pandisplay(xoff,%d)(yoff,%d)\n", + __func__, + var.xoffset, + var.yoffset); + return; + } +} diff --git a/src/fb/fbdev_fb.h b/src/fb/fbdev_fb.h new file mode 100644 index 0000000..6fa8c15 --- /dev/null +++ b/src/fb/fbdev_fb.h @@ -0,0 +1,54 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef __FBDEV_FB_H__ +#define __FBDEV_FB_H__ + +#include +#include +#include +#include +#include + +Bool fbdevFbGetVarScreenInfo (int fd, struct fb_var_screeninfo *fbVarInfo); +Bool fbdevFbSetVarScreenInfo (int fd, struct fb_var_screeninfo *fbVarInfo); +Bool fbdevFbGetFixScreenInfo (int fd, struct fb_fix_screeninfo *fbFixInfo); + +Bool fbdevFbSetWinPosition (int fd, int x, int y); + +Bool fbdevFbScreenAlphaInit (int fd); +Bool fbdevFbScreenAlphaDeinit (int fd); +void fbdevFbResetLCDModule (void); +Bool fbdevFbActivate (int fd); +Bool fbdevFbDeActivate (int fd); +Bool fbdevFbSetBase (int fd); +void fbdevFbHWPanDisplay (int fd, int x, int y); + +#endif //__FBDEV_FB_H__ \ No newline at end of file diff --git a/src/fbdev.c b/src/fbdev.c new file mode 100644 index 0000000..5225a01 --- /dev/null +++ b/src/fbdev.c @@ -0,0 +1,763 @@ +/* + * Authors: Alan Hourihane, + * Michel Dänzer, + */ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved. +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* all driver need this */ +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "fb.h" +#include "mipointer.h" +#include "mibstore.h" +#include "micmap.h" +#include "colormapst.h" +#include "xf86cmap.h" +#include "xf86xv.h" +#include "xf86Crtc.h" + +#include "fbdev.h" +#include "fbdevhw.h" +#include "fbdev_hw.h" +#include "fbdev_video.h" +#include "fbdev_crtcconfig.h" +#include "fbdev_dpms.h" +#include "fbdev_event_trace.h" + +#include +#include +#include + +/* prototypes */ +static const OptionInfoRec * FBDevAvailableOptions(int chipid, int busid); +static void FBDevIdentify(int flags); +static Bool FBDevProbe(DriverPtr drv, int flags); +static Bool FBDevPreInit(ScrnInfoPtr pScrn, int flags); +static Bool FBDevScreenInit(ScreenPtr pScreen, int argc, char **argv); +static Bool FBDevEnterVT(ScrnInfoPtr pScrn); +static void FBDevLeaveVT(ScrnInfoPtr pScrn); +static Bool FBDevCloseScreen(ScreenPtr pScreen); +static void FBDevSaveCurrent(ScrnInfoPtr pScrn); + +/* This DriverRec must be defined in the driver for Xserver to load this driver */ +_X_EXPORT DriverRec FBDEV = +{ + FBDEV_VERSION, + FBDEV_DRIVER_NAME, + FBDevIdentify, + FBDevProbe, + FBDevAvailableOptions, + NULL, + 0, + NULL, +}; + +/* Supported "chipsets" */ +static SymTabRec FBDevChipsets[] = +{ + {-1, NULL } +}; + +/* Supported options */ +typedef enum +{ + OPTION_SWCURSOR, + OPTION_FBDEV +} FBDevOpts; + +static const OptionInfoRec FBDevOptions[] = +{ + { OPTION_SWCURSOR, "swcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_FBDEV, "fbdev", OPTV_STRING, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +/* -------------------------------------------------------------------- */ + + +#ifdef XFree86LOADER + +MODULESETUPPROTO(FBDevSetup); + +static XF86ModuleVersionInfo FBDevVersRec = +{ + "emulfb", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + PACKAGE_VERSION_MAJOR, + PACKAGE_VERSION_MINOR, + PACKAGE_VERSION_PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + NULL, + {0,0,0,0} +}; + +_X_EXPORT XF86ModuleData emulfbModuleData = { &FBDevVersRec, FBDevSetup, NULL }; + +pointer +FBDevSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + if (!setupDone) + { + setupDone = TRUE; + xf86AddDriver(&FBDEV, module, HaveDriverFuncs); + return (pointer)1; + } + else + { + if (errmaj) *errmaj = LDR_ONCEONLY; + return NULL; + } +} + +#endif /* XFree86LOADER */ + +static Bool +FBDevGetRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate != NULL) + return TRUE; + + pScrn->driverPrivate = xnfcalloc(sizeof(FBDevRec), 1); + return TRUE; +} + +static void +FBDevFreeRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate == NULL) + return; + free(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + +/* -------------------------------------------------------------------- */ + +static const OptionInfoRec * +FBDevAvailableOptions(int chipid, int busid) +{ + return FBDevOptions; +} + +static void +FBDevIdentify(int flags) +{ + xf86PrintChipsets(FBDEV_NAME, "driver for framebuffer", FBDevChipsets); +} + +/* + * Probing the device with the device node, this probing depend on the specific hw. + * This function just verify whether the display hw is avaliable or not. + */ +static Bool +FBDevHWProbe(struct pci_device * pPci, const char *device,char **namep) +{ + return fbdevHWProbe(pPci, (char *)device,namep); +} + +/* The purpose of this function is to identify all instances of hardware supported + * by the driver. The probe must find the active device sections that match the driver + * by calling xf86MatchDevice(). + */ +static Bool +FBDevProbe(DriverPtr drv, int flags) +{ + int i; + ScrnInfoPtr pScrn; + GDevPtr *devSections; + int numDevSections; + const char *dev; + int entity; + Bool foundScreen = FALSE; + const char * drv_name = "fbdev"; + const char * module_name = "fbdevhw"; + + /* For now, just bail out for PROBE_DETECT. */ + if (flags & PROBE_DETECT) + return FALSE; + + if ((numDevSections = xf86MatchDevice(FBDEV_DRIVER_NAME, &devSections)) <= 0) + return FALSE; + + if (!xf86LoadDrvSubModule (drv, module_name)) + return FALSE; + + for (i = 0; i < numDevSections; i++) + { + dev = xf86FindOptionValue (devSections[i]->options, drv_name); + if (FBDevHWProbe(NULL,dev,NULL)) + { + pScrn = NULL; + entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE); + pScrn = xf86ConfigFbEntity(pScrn,0,entity, NULL,NULL,NULL,NULL); + + if (pScrn) + { + foundScreen = TRUE; + + pScrn->driverVersion = FBDEV_VERSION; + pScrn->driverName = FBDEV_DRIVER_NAME; + pScrn->name = FBDEV_NAME; + pScrn->Probe = FBDevProbe; + pScrn->PreInit = FBDevPreInit; + pScrn->ScreenInit = FBDevScreenInit; + pScrn->SwitchMode = fbdevHWSwitchModeWeak(); + pScrn->AdjustFrame = fbdevHWAdjustFrameWeak(); + pScrn->EnterVT = FBDevEnterVT; + pScrn->LeaveVT = FBDevLeaveVT; + pScrn->ValidMode = fbdevHWValidModeWeak(); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO + ,"using %s\n", dev ? dev : "default device"); + } + } + } + free(devSections); + + return foundScreen; +} + +/* + * Return the default depth and bits per pixel. + * Determine the depth and the bpp supported by hw with the hw color format. + */ +static int +FBDevGetDefaultDepth(ScrnInfoPtr pScrn, int *bitsPerPixel) +{ + int defaultDepth; + + /* finding out the valid default_depth */ + defaultDepth = fbdevHWGetDepth(pScrn,bitsPerPixel); + + /* the default depth is not more than 24 */ + defaultDepth = ((*bitsPerPixel)==32)?24:*bitsPerPixel; + + return defaultDepth; +} + +/* + * Initialize the device Probing the device with the device node, + * this probing depend on the specific hw. + * This function just verify whether the display hw is avaliable or not. + */ +static Bool +FBDevHWInit(ScrnInfoPtr pScrn, struct pci_device *pPci, const char *device) +{ + /* open device : open the framebuffer device */ + if (!fbdevHWInit(pScrn, NULL, (char *)device)) + { + return FALSE; + } + + return TRUE; +} + +/* + * DeInitialize the hw + */ +static void +FBDevHWDeInit(ScrnInfoPtr pScrn) +{ + /* close the fd of the fb device ??? */ + + return; +} + +/* + * Check the driver option. + * Set the option flags to the driver private + */ +static void +FBDevCheckDriverOptions(ScrnInfoPtr pScrn) +{ + FBDevPtr pFBDev = FBDEVPTR(pScrn); + + /* sw cursor */ + if (xf86ReturnOptValBool(pFBDev->Options, OPTION_SWCURSOR, FALSE)) + pFBDev->bSWCursorEnbled = TRUE; +} + + + +/* + * This is called before ScreenInit to probe the screen configuration. + * The main tasks to do in this funtion are probing, module loading, option handling, + * card mapping, and Crtcs setup. + */ +static Bool +FBDevPreInit(ScrnInfoPtr pScrn, int flags) +{ + FBDevPtr pFBDev; + int default_depth, fbbpp; + const char *path; + Gamma defualt_gamma = {0.0, 0.0, 0.0}; + rgb default_weight = { 0, 0, 0 }; + int flag24; + const char * fb_name = "fbdev"; + + if (flags & PROBE_DETECT) return FALSE; + + /* Check the number of entities, and fail if it isn't one. */ + if (pScrn->numEntities != 1) + return FALSE; + + pScrn->monitor = pScrn->confScreen->monitor; + + /* allocate private */ + FBDevGetRec(pScrn); + pFBDev = FBDEVPTR(pScrn); + + pFBDev->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + + /* can set the path with fbdev option */ + path = xf86FindOptionValue(pFBDev->pEnt->device->options, fb_name); + + /* Init HW */ + if(!FBDevHWInit(pScrn,NULL,path)) + { + xf86DrvMsg(pScrn->scrnIndex, X_Error + , "fail to initialize hardware\n"); + goto bail1; + } + + /* finding out the valid default_depth */ + default_depth = FBDevGetDefaultDepth(pScrn,&fbbpp); + + /* set the depth and the bpp to pScrn */ + flag24 = Support24bppFb | Support32bppFb; + if (!xf86SetDepthBpp(pScrn, default_depth, default_depth, fbbpp, flag24)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR + , "fail to find the depth\n"); + goto bail1; + } + xf86PrintDepthBpp(pScrn); /* just print out the depth and the bpp */ + + /* color weight */ + if (!xf86SetWeight(pScrn, default_weight, default_weight)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR + , "fail to set the color weight of RGB\n"); + goto bail1; + } + + /* visual init, make a TrueColor, -1 */ + if (!xf86SetDefaultVisual(pScrn, -1)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR + , "fail to initialize the default visual\n"); + goto bail1; + } + + /* set gamma */ + if (!xf86SetGamma(pScrn,defualt_gamma)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR + , "fail to set the gamma\n"); + goto bail1; + } + + pScrn->progClock = TRUE; + pScrn->rgbBits = 8; + pScrn->chipset = "fbdev"; + pScrn->videoRam = fbdevHWGetVidmem(pScrn); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO + , "hardware: %s (video memory: %dkB)\n" + , fbdevHWGetName(pScrn) + , pScrn->videoRam/1024); + + /* Collect all the option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + + /* + * Process the options based on the information S5POptions. + * The results are written to pS5P->Options. If all the options + * processing is done within this fuction a local variable "options" + * can be used instead of pS5P->Options + */ + if (!(pFBDev->Options = malloc(sizeof(FBDevOptions)))) + goto bail1; + memcpy(pFBDev->Options, FBDevOptions, sizeof(FBDevOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pFBDev->pEnt->device->options, pFBDev->Options); + + /* Check with the driver options */ + FBDevCheckDriverOptions(pScrn); + + /* Set the Crtc, the default Output, and the current Mode */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO + , "checking modes against framebuffer device and creating crtc and ouput...\n"); + if(!FBDevCrtcConfigInit(pScrn)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR + , "Fail to init the CrtcConfig\n"); + goto bail1; + } + FBDevSaveCurrent(pScrn); + + /* TODO::soolim:: re-confirm this condition */ + if(pScrn->currentMode->HDisplay == pFBDev->var.xres_virtual + && pScrn->currentMode->VDisplay <= pFBDev->var.yres_virtual) + { + pScrn->virtualX = pFBDev->var.xres_virtual; + pScrn->virtualY = pFBDev->var.yres_virtual; + } + else + { + pScrn->virtualX = pScrn->currentMode->HDisplay; + pScrn->virtualY = pScrn->currentMode->VDisplay; + } + pScrn->displayWidth = pScrn->virtualX; + xf86PrintModes(pScrn); /* just print the current mode */ + + /* Set display resolution */ + if(pFBDev->var.width && pFBDev->var.height) + { + pScrn->monitor->widthmm = pFBDev->var.width; + pScrn->monitor->heightmm = pFBDev->var.height; + } + xf86SetDpi(pScrn, 0, 0); + + /* Load fb submodule */ + if (!xf86LoadSubModule(pScrn, "fb")) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "fail to load fb module\n"); + goto bail1; + } + + return TRUE; + +bail1: + FBDevFreeRec(pScrn); + FBDevHWDeInit(pScrn); + return FALSE; +} + +static void +FBDevAdjustFrame(ScrnInfoPtr pScrn, int x, int y) +{ + fbdevHWAdjustFrame(pScrn, x, y); +} + + +/* Save the hw information */ +static void +FBDevSave(ScrnInfoPtr pScrn) +{ + FBDevPtr pFBDev = FBDEVPTR(pScrn); + + FBDevGetVarScreenInfo(fbdevHWGetFD(pScrn), &pFBDev->saved_var); +} + +/* Restore the hw information */ +static void +FBDevRestore(ScrnInfoPtr pScrn) +{ + FBDevPtr pFBDev = FBDEVPTR(pScrn); + + FBDevSetVarScreenInfo(fbdevHWGetFD(pScrn), &pFBDev->saved_var); +} + +/* Save the current hw information */ +static void +FBDevSaveCurrent(ScrnInfoPtr pScrn) +{ + FBDevPtr pFBDev = FBDEVPTR(pScrn); + + FBDevGetVarScreenInfo(fbdevHWGetFD(pScrn), &pFBDev->var); + FBDevGetFixScreenInfo(fbdevHWGetFD(pScrn), &pFBDev->fix); +} + +static Bool +FBDevModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + if (!fbdevHWModeInit(pScrn, mode)) + return FALSE; + + return TRUE; +} + +/* Get the address of the framebuffer */ +static unsigned char * +FBDevGetFbAddr(ScrnInfoPtr pScrn) +{ + FBDevPtr pFBDev = FBDEVPTR(pScrn); + return pFBDev->fbstart; +} + +static Bool +FBDevScreenInit(ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + FBDevPtr pFBDev = FBDEVPTR(pScrn); + VisualPtr visual; + int init_picture = 0; + unsigned char * pFbAddr; + pFBDev->rotate = RR_Rotate_0; + Bool rotated = (pFBDev->rotate & (RR_Rotate_90|RR_Rotate_270)) != 0; + + xf86DrvMsg(pScrn->scrnIndex,X_INFO, + "Infomation of Visual is \n\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n" + "\tmask: %x,%x,%x, offset: %d,%d,%d\n", + pScrn->bitsPerPixel, + pScrn->depth, + xf86GetVisualName(pScrn->defaultVisual), + (unsigned int) pScrn->mask.red, + (unsigned int) pScrn->mask.green, + (unsigned int) pScrn->mask.blue, + (int)pScrn->offset.red, + (int)pScrn->offset.green, + (int)pScrn->offset.blue); + + pFBDev->fbmem = fbdevHWMapVidmem(pScrn); /* mmap memory pointer */ + if (!pFBDev->fbmem) + { + xf86DrvMsg(pScrn->scrnIndex,X_ERROR + ,"mapping of video memory failed\n"); + return FALSE; + } + pFBDev->fboff = fbdevHWLinearOffset(pScrn); + + /* save fb information */ + FBDevSave(pScrn); + + /* set mode and set fb info */ + DisplayModePtr tmpMode; + + if(rotated) + tmpMode = &pFBDev->builtin_saved; + else + tmpMode = pScrn->currentMode; + + if (!FBDevModeInit(pScrn, tmpMode)) + { + xf86DrvMsg(pScrn->scrnIndex,X_ERROR + ,"mode initialization failed\n"); + return FALSE; + } + + fbdevHWSaveScreen(pScreen, SCREEN_SAVER_ON); + FBDevAdjustFrame(pScrn,0,0); + + FBDevSaveCurrent(pScrn); + + /* mi layer */ + miClearVisualTypes(); + if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits, TrueColor)) + { + xf86DrvMsg(pScrn->scrnIndex,X_ERROR + ,"visual type setup failed for %d bits per pixel [1]\n" + , pScrn->bitsPerPixel); + return FALSE; + } + if (!miSetPixmapDepths()) + { + xf86DrvMsg(pScrn->scrnIndex,X_ERROR + ,"pixmap depth setup failed\n"); + return FALSE; + } + + /* set the starting point of the framebuffer */ + pFBDev->fbstart = pFBDev->fbmem + pFBDev->fboff; + + /* Get the screen address */ + pFbAddr = FBDevGetFbAddr(pScrn); + + switch (pScrn->bitsPerPixel) + { + case 16: + case 24: + case 32: + if(! fbScreenInit(pScreen, pFbAddr, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->virtualX, /*Pixel width for framebuffer*/ + pScrn->bitsPerPixel)) + return FALSE; + + init_picture = 1; + + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR + , "internal error: invalid number of bits per pixel (%d) encountered\n" + , pScrn->bitsPerPixel); + break; + } + + if (pScrn->bitsPerPixel > 8) + { + /* Fixup RGB ordering */ + visual = pScreen->visuals + pScreen->numVisuals; + while (--visual >= pScreen->visuals) + { + if ((visual->class | DynamicClass) == DirectColor) + { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } + + /* must be after RGB ordering fixed */ + if (init_picture && !fbPictureInit(pScreen, NULL, 0)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING + , "Render extension initialisation failed\n"); + + /* XVideo Initiailization here */ +#ifdef XV + if (!fbdevVideoInit(pScreen)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "XVideo extention initialization failed\n"); +#endif + + xf86SetBlackWhitePixels(pScreen); + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + + /* Check whether the SWCURSOR option is enbled */ + if(pFBDev->bSWCursorEnbled) + { + /* use software cursor */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + } + else + { + /* use dummy hw_cursro instead of sw_cursor */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + xf86DrvMsg(pScrn->scrnIndex, X_INFO + , "Initializing HW Cursor\n"); + + if(!xf86_cursors_init(pScreen, SEC_CURSOR_W, SEC_CURSOR_H, (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + HARDWARE_CURSOR_INVERT_MASK | + HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | + HARDWARE_CURSOR_ARGB))) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR + , "Hardware cursor initialization failed\n"); + } + } + + /* crtc init */ + if (!xf86CrtcScreenInit(pScreen)) + return FALSE; + + /* set the desire mode : set the mode to xf86crtc here */ + xf86SetDesiredModes(pScrn); + + /* colormap */ + if (!miCreateDefColormap(pScreen)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR + , "internal error: miCreateDefColormap failed \n"); + return FALSE; + } + + if(!xf86HandleColormaps(pScreen, 256, 8, fbdevHWLoadPaletteWeak(), NULL, CMAP_PALETTED_TRUECOLOR)) + return FALSE; + + xf86DPMSInit(pScreen, FBDevDPMSSet(), 0); + pScreen->SaveScreen = FBDevSaveScreen(); + pFBDev->isLcdOff = FALSE; + + /* Wrap the current CloseScreen function */ + pFBDev->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = FBDevCloseScreen; + + /* register the event hook */ + fbdevTraceInstallHooks (); + + return TRUE; +} + + +static Bool +FBDevEnterVT(ScrnInfoPtr pScrn) +{ + xf86DrvMsg(pScrn->scrnIndex, X_INFO + , "EnterVT::Hardware state at EnterVT:\n"); + return TRUE; +} + +static void +FBDevLeaveVT(ScrnInfoPtr pScrn) +{ + xf86DrvMsg(pScrn->scrnIndex, X_INFO + , "LeaveVT::Hardware state at LeaveVT:\n"); +} + +static Bool +FBDevCloseScreen(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + FBDevPtr pFBDev = FBDEVPTR(pScrn); + + fbdevTraceUninstallHooks (); + + FBDevRestore(pScrn); + + fbdevHWUnmapVidmem(pScrn); + pScrn->vtSema = FALSE; + + if(!pFBDev->bLockScreen) + FBDevRestore(pScrn); + else + ErrorF("Screen closed but LCD was locked\n"); + + FBDevHWDeInit(pScrn); + + pScreen->CreateScreenResources = pFBDev->CreateScreenResources; + pScreen->CloseScreen = pFBDev->CloseScreen; + + return (*pScreen->CloseScreen)(pScreen); +} + + + + diff --git a/src/fbdev.h b/src/fbdev.h new file mode 100644 index 0000000..c79d5be --- /dev/null +++ b/src/fbdev.h @@ -0,0 +1,107 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef FBDEV_H +#define FBDEV_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "fbdevhw.h" +#include "xf86xv.h" +#include + +#define PAGE_SIZE 4096 + +#define FBDEV_VERSION 1000 /* the version of the driver */ +#define FBDEV_NAME "FBDEV" /* the name used to prefix messages */ +#define FBDEV_DRIVER_NAME "emulfb" /* the driver name as used in config file. + * This name should match the name of the driver module binary + * In this driver, the name of the driver libary module is emulfb_drv.so. + */ +#define SWAPINT(i, j) \ +{ int _t = i; i = j; j = _t; } + +#define SEC_CURSOR_W 64 +#define SEC_CURSOR_H 64 + +#define ADAPTOR_NUM 2 + +/* FBDev driver private data structure to hold the driver's screen-specific data */ +typedef struct { + unsigned char *fbstart; /* start memory point of framebuffer: (fbmem + fboff) */ + unsigned char *fbmem; /* mmap memory pointer of framebuffer */ + int fboff; /* fb offset */ + int lineLength; + CloseScreenProcPtr CloseScreen; + CreateScreenResourcesProcPtr CreateScreenResources; + void (*PointerMoved)(int index, int x, int y); + EntityInfoPtr pEnt; + + /* driver options */ + OptionInfoPtr Options; + Bool bSWCursorEnbled; /* software cursor enabled */ + int rotate; + + /* saved video mode */ + struct fb_var_screeninfo saved_var; + + /* Current information of Framebuffer */ + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + + /* mode infos */ + DisplayModePtr builtin; + DisplayModeRec builtin_saved; /* original mode to send the fake mode when the screen rotates */ + DisplayModePtr support_modes; + + /* xv */ +#ifdef XV + XF86VideoAdaptorPtr pAdaptor[ADAPTOR_NUM]; + void **v4l2_owner; + int v4l2_num; + Bool bFbAlphaEnabled; +#endif + + Bool bLockScreen; + + /* dpms - flag for the control of lcd onoff*/ + Bool isLcdOff; + + /* Cursor */ + Bool enableCursor; +} FBDevRec, *FBDevPtr; +#define FBDEVPTR(p) ((FBDevPtr)((p)->driverPrivate)) + +#endif //FBDEV_H + diff --git a/src/fbdev_dpms.c b/src/fbdev_dpms.c new file mode 100644 index 0000000..d9e0806 --- /dev/null +++ b/src/fbdev_dpms.c @@ -0,0 +1,140 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "fbdev.h" +#include +#include +#include +#include +#include +#include "fbdev.h" +#include "fbdevhw.h" +#include "fbdev_hw.h" +#include + +#include "misc.h" +#include "fbdev_dpms.h" + +CallbackListPtr DPMSCallback; + +static void +_dpmsCallCallback (ScrnInfoPtr pScrn, int mode, int flags) +{ + FBDevDPMSRec dpmsinfo; + + if (!DPMSCallback) + return; + + dpmsinfo.pScrn = pScrn; + dpmsinfo.mode = mode; + dpmsinfo.flags = flags; + + CallCallbacks (&DPMSCallback, (pointer) &dpmsinfo); +} + +static void +fbdevDPMSSetFunc(ScrnInfoPtr pScrn, int mode, int flags) +{ + FBDevPtr pFBDev = FBDEVPTR(pScrn); + int call_before; + + call_before = (DPMSPowerLevel == DPMSModeSuspend || + DPMSPowerLevel == DPMSModeOff) ? 1 : 0; + + if (call_before) + _dpmsCallCallback (pScrn, mode, flags); + + switch(DPMSPowerLevel) + { + case DPMSModeSuspend: + break; + case DPMSModeOn: + case DPMSModeStandby: + if(pFBDev->isLcdOff == FALSE) break; + + /* lcd on */ + if (-1 == ioctl(fbdevHWGetFD(pScrn), FBIOBLANK, FB_BLANK_UNBLANK)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FBIOBLANK: %s\n", strerror(errno)); + } + + pFBDev->isLcdOff = FALSE; + break; + case DPMSModeOff: + if(pFBDev->isLcdOff == TRUE) break; + + /* lcd off */ + if (-1 == ioctl(fbdevHWGetFD(pScrn), FBIOBLANK, FB_BLANK_POWERDOWN)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FBIOBLANK: %s\n", strerror(errno)); + } + + pFBDev->isLcdOff = TRUE; + break; + default: + return; + } + + if (!call_before) + _dpmsCallCallback (pScrn, mode, flags); +} + +xf86DPMSSetProc* +FBDevDPMSSet(void) +{ + return fbdevDPMSSetFunc; +} + +static Bool first_savescreen = FALSE; + +static Bool +fbdevSaveScreenFunc(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if(!first_savescreen) + { + first_savescreen = TRUE; + if (-1 == ioctl(fbdevHWGetFD(pScrn), FBIOBLANK, (void *)(0))) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FBIOBLANK: %s\n", strerror(errno)); + } + } + + return TRUE; +} + + +SaveScreenProcPtr +FBDevSaveScreen(void) +{ + return fbdevSaveScreenFunc; +} + diff --git a/src/fbdev_dpms.h b/src/fbdev_dpms.h new file mode 100644 index 0000000..9633efc --- /dev/null +++ b/src/fbdev_dpms.h @@ -0,0 +1,45 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef FBDEV_DPMS_H +#define FBDEV_DPMS_H + +typedef struct +{ + ScrnInfoPtr pScrn; + int mode; + int flags; +} FBDevDPMSRec, *FBDevDPMSPtr; + +xf86DPMSSetProc* FBDevDPMSSet(void); +SaveScreenProcPtr FBDevSaveScreen(void); + +#endif /* FBDEV_DPMS_H */ + diff --git a/src/fbdevhw/fbdev_hw.c b/src/fbdevhw/fbdev_hw.c new file mode 100644 index 0000000..fd5c0d4 --- /dev/null +++ b/src/fbdevhw/fbdev_hw.c @@ -0,0 +1,196 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "fbdev.h" +#include "fbdev_hw.h" + +void +FBDevGetVarScreenInfo(int fd, struct fb_var_screeninfo *fbVarInfo) +{ + if (0 != ioctl(fd,FBIOGET_VSCREENINFO, (void*)fbVarInfo)) + fprintf(stderr, "Error : fail to get FBIOGET_VSCREENINFO\n"); +} + +void +FBDevSetVarScreenInfo(int fd, struct fb_var_screeninfo *fbVarInfo) +{ + if (0 != ioctl(fd,FBIOPUT_VSCREENINFO,(void*)fbVarInfo)) + fprintf(stderr, "Error : fail to get FBIOPUT_VSCREENINFO\n"); +} + +void +FBDevGetFixScreenInfo(int fd, struct fb_fix_screeninfo *fbFixInfo) +{ + if (0 != ioctl(fd,FBIOGET_FSCREENINFO,(void*)fbFixInfo)) + fprintf(stderr, "Error : fail to get FBIOGET_FSCREENINFO\n"); +} + +Bool +FBDevScreenAlphaInit(int fd) +{ + struct fb_var_screeninfo var; + int ret; + + ret = ioctl(fd, FBIOGET_VSCREENINFO, &var); + if (ret < 0) + { + return FALSE; + } + + if (var.bits_per_pixel != 32) + { + return FALSE; + } + var.transp.length = 8; + var.activate = FB_ACTIVATE_FORCE; + ret = ioctl(fd, FBIOPUT_VSCREENINFO, &var); + if (ret < 0) + { + return FALSE; + } + + return TRUE; +} + +Bool +FBDevScreenAlphaDeinit(int fd) +{ + struct fb_var_screeninfo var; + int ret; + + ret = ioctl(fd, FBIOGET_VSCREENINFO, &var); + if (ret < 0) + { + return FALSE; + } + + var.transp.length = 0; + ret = ioctl(fd, FBIOPUT_VSCREENINFO, &var); + if (ret < 0) + { + return FALSE; + } + + return TRUE; +} + +#include + +/* activate fb */ +Bool +FBDevActivateFB(int fd) +{ + struct fb_var_screeninfo var; + int ret; + + ret = ioctl(fd, FBIOGET_VSCREENINFO, &var); + if (ret < 0) + { + ErrorF("failed to get fb_var\n"); + return FALSE; + } + + var.activate = FB_ACTIVATE_FORCE; + + ret = ioctl (fd, FBIOPUT_VSCREENINFO, &var); + if (ret < 0) + { + ErrorF("failed to set fb_var.activate\n"); + return FALSE; + } + + ret = ioctl (fd, FBIOBLANK, FB_BLANK_UNBLANK); + if (ret < 0) + { + ErrorF("failed to set FBIOBLANK : FB_BLANK_UNBLANK\n"); + return FALSE; + } + + return TRUE; +} + +/* deactivate fb3 */ +Bool +FBDevDeActivateFB(int fd) +{ + int ret; + + ret = ioctl (fd, FBIOBLANK, FB_BLANK_POWERDOWN); + if (ret < 0) + { + ErrorF("failed to set FBIOBLANK : FB_BLANK_POWERDOWN\n"); + return FALSE; + } + + return TRUE; +} + +Bool +FBDevSetBaseFrameBuffer(int fd) +{ + struct fb_var_screeninfo var; + int ret; + + ret = ioctl(fd, FBIOGET_VSCREENINFO, &var); + if (ret < 0) + { + return FALSE; + } + + var.yoffset = 0; + ret = ioctl (fd, FBIOPAN_DISPLAY,&var); + if (ret < 0) + { + return FALSE; + } + return TRUE; +} + + +void +FBDevHWPanDisplay(int fd, int x, int y) +{ + struct fb_var_screeninfo var; + int ret; + + ret = ioctl(fd, FBIOGET_VSCREENINFO, &var); + if(ret < 0) + { + return; + } + + var.xoffset = x; + var.yoffset = y; + ret = ioctl(fd, FBIOPAN_DISPLAY, &var); + if(ret < 0) + { + return; + } +} diff --git a/src/fbdevhw/fbdev_hw.h b/src/fbdevhw/fbdev_hw.h new file mode 100644 index 0000000..1f83443 --- /dev/null +++ b/src/fbdevhw/fbdev_hw.h @@ -0,0 +1,51 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef FBDEV_HW_H +#define FBDEV_HW_H + +#include +#include +#include +#include + +void FBDevGetVarScreenInfo(int fd, struct fb_var_screeninfo *fbVarInfo); +void FBDevSetVarScreenInfo(int fd, struct fb_var_screeninfo *fbVarInfo); +void FBDevGetFixScreenInfo(int fd, struct fb_fix_screeninfo *fbFixInfo); + +Bool FBDevScreenAlphaInit(int fd); +Bool FBDevScreenAlphaDeinit(int fd); +Bool FBDevActivateFB(int fd); +Bool FBDevDeActivateFB(int fd); +Bool FBDevSetBaseFrameBuffer(int fd); +void FBDevHWPanDisplay(int fd, int x, int y); + +#endif //FBDEV_HW_H + diff --git a/src/util/fbdev_pixman.c b/src/util/fbdev_pixman.c new file mode 100644 index 0000000..8455cb8 --- /dev/null +++ b/src/util/fbdev_pixman.c @@ -0,0 +1,170 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "fbdev_util.h" +#include "fbdev_pixman.h" + +int +fbdev_pixman_convert_image (pixman_op_t op, + unsigned char *srcbuf, + unsigned char *dstbuf, + pixman_format_code_t src_format, + pixman_format_code_t dst_format, + xRectangle *img, + xRectangle *pxm, + xRectangle *src, + xRectangle *dst, + RegionPtr clip_region, + int rotate, + int hflip, + int vflip) +{ + pixman_image_t *src_img; + pixman_image_t *dst_img; + struct pixman_f_transform ft; + pixman_transform_t transform; + int src_stride, dst_stride; + int src_bpp; + int dst_bpp; + double scale_x, scale_y; + int rotate_step; + int ret = FALSE; + + return_val_if_fail (srcbuf != NULL, FALSE); + return_val_if_fail (dstbuf != NULL, FALSE); + return_val_if_fail (img != NULL, FALSE); + return_val_if_fail (pxm != NULL, FALSE); + return_val_if_fail (src != NULL, FALSE); + return_val_if_fail (dst != NULL, FALSE); + return_val_if_fail (rotate <= 360 && rotate >= -360, FALSE); + + DRVLOG ("[Convert] img(%d,%d %dx%d) src(%d,%d %dx%d) pxm(%d,%d %dx%d) dst(%d,%d %dx%d) sflip(%d,%d), r(%d)\n", + img->x, img->y, img->width, img->height, + src->x, src->y, src->width, src->height, + pxm->x, pxm->y, pxm->width, pxm->height, + dst->x, dst->y, dst->width, dst->height, + hflip, vflip, rotate); + + src_bpp = PIXMAN_FORMAT_BPP (src_format) / 8; + return_val_if_fail (src_bpp > 0, FALSE); + + dst_bpp = PIXMAN_FORMAT_BPP (dst_format) / 8; + return_val_if_fail (dst_bpp > 0, FALSE); + + rotate_step = (rotate + 360) / 90 % 4; + + src_stride = img->width * src_bpp; + dst_stride = pxm->width * dst_bpp; + + src_img = pixman_image_create_bits (src_format, img->width, img->height, (uint32_t*)srcbuf, src_stride); + dst_img = pixman_image_create_bits (dst_format, pxm->width, pxm->height, (uint32_t*)dstbuf, dst_stride); + + goto_if_fail (src_img != NULL, CANT_CONVERT); + goto_if_fail (dst_img != NULL, CANT_CONVERT); + + pixman_f_transform_init_identity (&ft); + + if (hflip) + { + pixman_f_transform_scale (&ft, NULL, -1, 1); + pixman_f_transform_translate (&ft, NULL, dst->width, 0); + } + + if (vflip) + { + pixman_f_transform_scale (&ft, NULL, 1, -1); + pixman_f_transform_translate (&ft, NULL, 0, dst->height); + } + + if (rotate_step > 0) + { + int c, s, tx = 0, ty = 0; + switch (rotate_step) + { + case 1: + /* 90 degrees */ + c = 0; + s = -1; + tx = -dst->width; + break; + case 2: + /* 180 degrees */ + c = -1; + s = 0; + tx = -dst->width; + ty = -dst->height; + break; + case 3: + /* 270 degrees */ + c = 0; + s = 1; + ty = -dst->height; + break; + default: + /* 0 degrees */ + c = 0; + s = 0; + break; + } + + pixman_f_transform_translate (&ft, NULL, tx, ty); + pixman_f_transform_rotate (&ft, NULL, c, s); + } + + if (rotate_step % 2 == 0) + { + scale_x = (double)src->width / dst->width; + scale_y = (double)src->height / dst->height; + } + else + { + scale_x = (double)src->width / dst->height; + scale_y = (double)src->height / dst->width; + } + + pixman_f_transform_scale (&ft, NULL, scale_x, scale_y); + pixman_f_transform_translate (&ft, NULL, src->x, src->y); + + pixman_transform_from_pixman_f_transform (&transform, &ft); + pixman_image_set_transform (src_img, &transform); + + pixman_image_composite (op, src_img, NULL, dst_img, + 0, 0, 0, 0, dst->x, dst->y, dst->width, dst->height); + + ret = TRUE; + +CANT_CONVERT: + if (src_img) + pixman_image_unref (src_img); + if (dst_img) + pixman_image_unref (dst_img); + + return ret; +} \ No newline at end of file diff --git a/src/util/fbdev_pixman.h b/src/util/fbdev_pixman.h new file mode 100644 index 0000000..a746ea8 --- /dev/null +++ b/src/util/fbdev_pixman.h @@ -0,0 +1,64 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef __FBDEV_PIXMAN_H__ +#define __FBDEV_PIXMAN_H__ + +#include +#include +#include + +#include + +#ifndef FALSE +#define FALSE 0 +#define TRUE (!FALSE) +#endif + +#ifndef NULL +#define NULL (void*)0 +#endif + +int +fbdev_pixman_convert_image (pixman_op_t op, + unsigned char *srcbuf, + unsigned char *dstbuf, + pixman_format_code_t src_format, + pixman_format_code_t dst_format, + xRectangle *img, + xRectangle *pxm, + xRectangle *src, + xRectangle *dst, + RegionPtr clip_region, + int rotate, + int hflip, + int vflip); + +#endif /* __FBDEV_PIXMAN_H__ */ diff --git a/src/util/fbdev_util.c b/src/util/fbdev_util.c new file mode 100644 index 0000000..92136df --- /dev/null +++ b/src/util/fbdev_util.c @@ -0,0 +1,255 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: YoungHoon Jung + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include +#include +#include +#include +#include + +#include "X11/XWDFile.h" +#include "fbdev.h" +#include "fbdev_util.h" + +int fbdev_util_dump_raw(const char * file, const void * data, int width, int height) +{ + unsigned int * blocks; + + FILE * fp = fopen(file, "w+"); + if (fp == NULL) + return 0; + + blocks = (unsigned int *) data; + fwrite(blocks, 4, width*height, fp); + + fclose(fp); + + return 1; +} + +#ifndef RR_Rotate_All +#define RR_Rotate_All (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270) +#endif + +int fbdev_util_degree_to_rotate(int degree) +{ + int rotate; + + switch(degree) + { + case 0: + rotate = RR_Rotate_0; + break; + case 90: + rotate = RR_Rotate_90; + break; + case 180: + rotate = RR_Rotate_180; + break; + case 270: + rotate = RR_Rotate_270; + break; + default: + rotate = 0; /* ERROR */ + break; + } + + return rotate; +} + +int fbdev_util_rotate_to_degree(int rotate) +{ + int degree; + + switch(rotate & RR_Rotate_All) + { + case RR_Rotate_0: + degree = 0; + break; + case RR_Rotate_90: + degree = 90; + break; + case RR_Rotate_180: + degree = 180; + break; + case RR_Rotate_270: + degree = 270; + break; + default: + degree = -1; /* ERROR */ + break; + } + + return degree; +} + +static int +_fbdev_util_rotate_to_int(int rot) +{ + switch(rot & RR_Rotate_All) + { + case RR_Rotate_0: + return 0; + case RR_Rotate_90: + return 1; + case RR_Rotate_180: + return 2; + case RR_Rotate_270: + return 3; + } + + return 0; +} + +int fbdev_util_rotate_add(int rot_a, int rot_b) +{ + int a = _fbdev_util_rotate_to_int(rot_a); + int b = _fbdev_util_rotate_to_int(rot_b); + + return (int)((1 << ((a+b)%4))&RR_Rotate_All); +} + +const PropertyPtr +fbdev_util_get_window_property(WindowPtr pWin, const char* prop_name) +{ + int rc; + Mask prop_mode = DixReadAccess; + Atom property; + PropertyPtr pProp; + + property = MakeAtom(prop_name, strlen(prop_name), FALSE); + if(property == None) + return NULL; + + rc = dixLookupProperty(&pProp, pWin, property, serverClient, prop_mode); + if (rc == Success && pProp->data) + { + return pProp; + } + + return NULL; +} + + +void +fbdev_util_rotate_rect (int xres, + int yres, + int src_rot, + int dst_rot, + xRectangle *src) +{ + int diff; + xRectangle temp; + + return_if_fail (src != NULL); + + if (src_rot == dst_rot) + return; + + diff = (dst_rot - src_rot); + if (diff < 0) + diff = 360 + diff; + + if (src_rot % 180 && diff % 180) + SWAP (xres, yres); + + switch (diff) + { + case 270: + temp.x = yres - (src->y + src->height); + temp.y = src->x; + temp.width = src->height; + temp.height = src->width; + break; + case 180: + temp.x = xres - (src->x + src->width); + temp.y = yres - (src->y + src->height); + temp.width = src->width; + temp.height = src->height; + break; + case 90: + temp.x = src->y; + temp.y = xres - (src->x + src->width); + temp.width = src->height; + temp.height = src->width; + break; + default: + temp.x = src->x; + temp.y = src->y; + temp.width = src->width; + temp.height = src->height; + break; + } + + *src = temp; +} + +void +fbdev_util_align_rect (int src_w, int src_h, int dst_w, int dst_h, xRectangle *fit, Bool hw) +{ + int fit_width; + int fit_height; + float rw, rh, max; + + if (!fit) + return; + + return_if_fail (src_w > 0 && src_h > 0); + return_if_fail (dst_w > 0 && dst_h > 0); + + rw = (float)src_w / dst_w; + rh = (float)src_h / dst_h; + max = MAX (rw, rh); + + fit_width = src_w / max; + fit_height = src_h / max; + + if (hw) + fit_width &= (~0x3); + + fit->x = (dst_w - fit_width) / 2; + fit->y = (dst_h - fit_height) / 2; + fit->width = fit_width; + fit->height = fit_height; +} + + +void +drvlog (const char * f, ...) +{ + va_list args; + char temp[1024]; + + va_start (args, f); + vsnprintf (temp, sizeof (temp), f, args); + va_end (args); + + fwrite (temp, strlen (temp), 1, stderr); +} diff --git a/src/util/fbdev_util.h b/src/util/fbdev_util.h new file mode 100644 index 0000000..206daeb --- /dev/null +++ b/src/util/fbdev_util.h @@ -0,0 +1,82 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: YoungHoon Jung + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef __FBDEV_UTIL_H__ +#define __FBDEV_UTIL_H__ + +#include "property.h" + +#ifndef CLEAR +#define CLEAR(x) memset(&(x), 0, sizeof (x)) +#endif + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef SWAP +#define SWAP(a, b) ({int t; t = a; a = b; b = t;}) +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +void drvlog (const char * f, ...); + +//#define ENABLE_DEBUG 1 + +#if ENABLE_DEBUG +#define DRVLOG(fmt, arg...) drvlog(fmt, ##arg) +#else +#define DRVLOG(fmt, arg...) {;} +#endif + +#define return_if_fail(cond) {if (!(cond)) { ErrorF ("%s : '%s' failed.\n", __FUNCTION__, #cond); return; }} +#define return_val_if_fail(cond, val) {if (!(cond)) { ErrorF ("%s : '%s' failed.\n", __FUNCTION__, #cond); return val; }} +#define goto_if_fail(cond, dst) {if (!(cond)) { ErrorF ("%s : '%s' failed.\n", __FUNCTION__, #cond); goto dst; }} + +int fbdev_util_degree_to_rotate(int degree); +int fbdev_util_rotate_to_degree(int rotate); +int fbdev_util_rotate_add(int rot_a, int rot_b); + +void fbdev_util_rotate_rect (int xres, int yres, int src_rot, int dst_rot, xRectangle *src); + +const PropertyPtr fbdev_util_get_window_property(WindowPtr pWin, const char* prop_name); +void fbdev_util_align_rect (int src_w, int src_h, int dst_w, int dst_h, xRectangle *fit, Bool hw); + +#endif /* __FBDEV_UTIL_H__ */ \ No newline at end of file diff --git a/src/xv/arm/fbdev_video_v4l2.c b/src/xv/arm/fbdev_video_v4l2.c new file mode 100644 index 0000000..69ea300 --- /dev/null +++ b/src/xv/arm/fbdev_video_v4l2.c @@ -0,0 +1,1111 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fbdev_util.h" +#include "fbdev_video_v4l2.h" + +#include "fbdev.h" +#include "fbdev_fb.h" +#include "fbdev_util.h" +#include "fbdev_video.h" +#include "fbdev_video_fourcc.h" + +typedef struct _DeviceInfo +{ + char *video; /* video */ + char *fb; /* output frame buffer */ + int type; + int bOpened; +} DeviceInfo; + +typedef struct _FormatInfo +{ + int id; + int type; + uint pixelformat; + FBDevV4l2Memory memory; +} FormatInfo; + +typedef struct +{ + int index; + + ScreenPtr pScreen; + + int video_fd; + + int fb_fd; + char *fb_base_phy; + char *fb_base_vir; + Bool fb_shown; + + struct fb_fix_screeninfo fix; + + struct + { + int init; + xRectangle img; + xRectangle crop; + xRectangle pxm; + xRectangle dst; + int id; + int hw_rotate; + int scn_rotate; + int hflip; + int vflip; + int requestbuffer; + int streamon; + int cur_idx; + + void* last_buffer; + int queued_index; + + void* backup; + Bool sync; + } status; + + int size; + unsigned int pixfmt; + FBDevV4l2FimcBuffer fimcbuf; + FBDevV4l2SrcBuffer *src_buf; + FBDevV4l2Memory memory; + + int initial_dequeued_buf; + int re_setting; +} FBDevDispHandle; + +enum +{ + TYPE_RGB, + TYPE_YUV444, + TYPE_YUV422, + TYPE_YUV420, +}; + +static FormatInfo format_infos [] = +{ + { FOURCC_RGB565, TYPE_RGB, V4L2_PIX_FMT_RGB565, V4L2_MEMORY_MMAP }, + { FOURCC_RGB32, TYPE_RGB, V4L2_PIX_FMT_RGB32, V4L2_MEMORY_MMAP }, + { FOURCC_I420, TYPE_YUV420, V4L2_PIX_FMT_YUV420, V4L2_MEMORY_MMAP }, + { FOURCC_S420, TYPE_YUV420, V4L2_PIX_FMT_YUV420, V4L2_MEMORY_USERPTR }, + { FOURCC_ST12, TYPE_YUV420, V4L2_PIX_FMT_NV12T, V4L2_MEMORY_USERPTR }, + { FOURCC_NV12, TYPE_YUV420, V4L2_PIX_FMT_NV12, V4L2_MEMORY_MMAP }, + { FOURCC_SN12, TYPE_YUV420, V4L2_PIX_FMT_NV12, V4L2_MEMORY_USERPTR }, + { FOURCC_YUY2, TYPE_YUV422, V4L2_PIX_FMT_YUYV, V4L2_MEMORY_MMAP }, + { FOURCC_SUYV, TYPE_YUV422, V4L2_PIX_FMT_YUYV, V4L2_MEMORY_USERPTR }, +}; + +static XF86ImageRec Images[] = +{ + XVIMAGE_YUY2, + XVIMAGE_SUYV, + XVIMAGE_I420, + XVIMAGE_S420, + XVIMAGE_ST12, + XVIMAGE_NV12, + XVIMAGE_SN12, + XVIMAGE_RGB32, + XVIMAGE_RGB565, +}; + +static DeviceInfo device_infos[] = +{ + { "/dev/video2", "/dev/fb1", OUTPUT_PATH_DMA, FALSE }, + { "/dev/video3", "/dev/fb2", OUTPUT_PATH_DMA, FALSE }, +}; + +#define NUM_IMAGES (sizeof(Images) / sizeof(XF86ImageRec)) +#define DEVICE_NUMS (sizeof (device_infos) / sizeof (DeviceInfo)) + +static Bool +_fbdevVideoV4l2SetSrc (int fd, + xRectangle *src_rect, + xRectangle *crop_rect, + uint pixelformat) +{ + struct v4l2_format format = {0,}; + struct v4l2_crop crop = {0,}; + int capabilities; + + return_val_if_fail (fd >= 0, FALSE); + + DRVLOG ("[SetSrc] src_r(%d,%d %dx%d) crop_r(%d,%d %dx%d) pixfmt(0x%08x) \n", + src_rect->x, src_rect->y, src_rect->width, src_rect->height, + crop_rect->x, crop_rect->y, crop_rect->width, crop_rect->height, + pixelformat); + + /* check if capabilities is valid */ + capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OVERLAY; + if (!fbdev_v4l2_querycap (fd, capabilities)) + return FALSE; + + /* set format */ + CLEAR (format); + format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + if (!fbdev_v4l2_g_fmt (fd, &format)) + return FALSE; + + format.fmt.pix.width = src_rect->width; + format.fmt.pix.height = src_rect->height; + format.fmt.pix.pixelformat = pixelformat; + format.fmt.pix.field = V4L2_FIELD_NONE; + if (!fbdev_v4l2_s_fmt (fd, &format)) + return FALSE; + + /* set crop_rect */ + CLEAR (crop); + crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + crop.c.left = crop_rect->x; + crop.c.top = crop_rect->y; + crop.c.width = crop_rect->width; + crop.c.height = crop_rect->height; + if (!fbdev_v4l2_cropcap (fd, crop.type, &crop.c)) + return FALSE; + + if (!fbdev_v4l2_s_crop (fd, &crop)) + return FALSE; + + return TRUE; +} + +static Bool +_fbdevVideoV4l2SetDst (int fd, + xRectangle *dst_rect, + xRectangle *win_rect, + int rotation, + int hflip, + int vflip, + int path, + uint addr) +{ + struct v4l2_format format = {0,}; + struct v4l2_control ctrl = {0,}; + struct v4l2_framebuffer fbuf = {0,}; + + return_val_if_fail (fd >= 0, FALSE); + + DRVLOG ("[SetDst] dst_r(%d,%d %dx%d) win_r(%d,%d %dx%d) rot(%d) flip(%d,%d) path(%d) addr(%p) \n", + dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height, + win_rect->x, win_rect->y, win_rect->width, win_rect->height, + rotation, hflip, vflip, path, (void*)addr); + + /* set rotation */ + CLEAR (ctrl); + ctrl.id = V4L2_CID_ROTATION; + ctrl.value = rotation; + if (!fbdev_v4l2_s_ctrl (fd, &ctrl)) + return FALSE; + + CLEAR (ctrl); + ctrl.id = V4L2_CID_HFLIP; + ctrl.value = hflip; + if (!fbdev_v4l2_s_ctrl (fd, &ctrl)) + return FALSE; + + CLEAR (ctrl); + ctrl.id = V4L2_CID_VFLIP; + ctrl.value = vflip; + if (!fbdev_v4l2_s_ctrl (fd, &ctrl)) + return FALSE; + + ctrl.id = V4L2_CID_OVLY_MODE; + ctrl.value = 0x4; //single buffer + if (!fbdev_v4l2_s_ctrl (fd, &ctrl)) + return FALSE; + + /* set framebuffer */ + CLEAR (fbuf); + if (!fbdev_v4l2_g_fbuf (fd, &fbuf)) + return FALSE; + + if (path == OUTPUT_PATH_DMA) + fbuf.base = (void*)addr; + + fbuf.fmt.width = dst_rect->width; + fbuf.fmt.height = dst_rect->height; + fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB32; + if (!fbdev_v4l2_s_fbuf (fd, &fbuf)) + return FALSE; + + /* set format */ + CLEAR (format); + format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + if (!fbdev_v4l2_g_fmt (fd, &format)) + return FALSE; + + format.fmt.win.w.left = win_rect->x; + format.fmt.win.w.top = win_rect->y; + format.fmt.win.w.width = win_rect->width; + format.fmt.win.w.height = win_rect->height; + if (!fbdev_v4l2_s_fmt (fd, &format)) + return FALSE; + + return TRUE; +} + +static Bool +_fbdevVideoV4l2SetBuffer (int fd, + FBDevV4l2BufType type, + FBDevV4l2Memory memory, + int num_buf, + FBDevV4l2SrcBuffer **mem_buf) +{ + struct v4l2_requestbuffers req = {0,}; + + return_val_if_fail (fd >= 0, FALSE); + + DRVLOG ("[SetBuffer] num_buf(%d) mem_buf(%p) memory(%d)\n", + num_buf, mem_buf, memory); + + CLEAR (req); + req.count = num_buf; + req.type = type; + req.memory = memory; + if (!fbdev_v4l2_reqbuf (fd, &req)) + return FALSE; + + if (memory == V4L2_MEMORY_MMAP) + { + FBDevV4l2SrcBuffer *out_buf; + int i; + + return_val_if_fail (mem_buf != NULL, FALSE); + + out_buf = calloc (req.count, sizeof (FBDevV4l2SrcBuffer)); + return_val_if_fail (out_buf != NULL, FALSE); + + for (i = 0; i < num_buf; i++) + { + struct v4l2_buffer buffer = {0,}; + + CLEAR (buffer); + buffer.index = i; + buffer.type = type; + buffer.memory = V4L2_MEMORY_MMAP; + if (!fbdev_v4l2_querybuf (fd, &buffer)) + { + free (out_buf); + return FALSE; + } + + out_buf[i].index = buffer.index; + out_buf[i].size = buffer.length; + out_buf[i].buf = mmap (NULL, buffer.length, + PROT_READ | PROT_WRITE , \ + MAP_SHARED , fd, buffer.m.offset); + if (out_buf[i].buf == MAP_FAILED) + { + xf86DrvMsg (0, X_ERROR, "[SetBuffer] mmap failed. index(%d)\n", i); + free (out_buf); + return FALSE; + } + } + + *mem_buf = out_buf; + } + + return TRUE; +} + +static Bool +_fbdevVideoV4l2ClearBuffer (int fd, + FBDevV4l2BufType type, + FBDevV4l2Memory memory, + int num_buf, + FBDevV4l2SrcBuffer *mem_buf) +{ + struct v4l2_requestbuffers req = {0,}; + + return_val_if_fail (fd >= 0, FALSE); + + DRVLOG ("[ClearBuffer] memory(%d) num_buf(%d) mem_buf(%p)\n", + num_buf, mem_buf, memory); + + if (memory == V4L2_MEMORY_MMAP && mem_buf) + { + int i; + + for (i = 0; i < num_buf; i++) + if (mem_buf[i].buf) + if (munmap (mem_buf[i].buf, mem_buf[i].size) == -1) + xf86DrvMsg (0, X_WARNING, "[ClearBuffer] Failed to unmap v4l2 buffer at index %d\n", i); + + free (mem_buf); + } + + CLEAR (req); + req.count = 0; + req.type = type; + req.memory = memory; + if (!fbdev_v4l2_reqbuf (fd, &req)) + return FALSE; + + return TRUE; +} + +static Bool +_fbdevVideoV4l2StreamOn (int fd, FBDevV4l2BufType type) +{ + return_val_if_fail (fd >= 0, FALSE); + + DRVLOG ("[StreamOn] type(%d) \n", type); + + if (!fbdev_v4l2_streamon (fd, type)) + return FALSE; + + return TRUE; +} + + +static Bool +_fbdevVideoV4l2StreamOff (int fd, FBDevV4l2BufType type) +{ + return_val_if_fail (fd >= 0, FALSE); + + DRVLOG ("[StreamOff] type(%d) \n", type); + + if (!fbdev_v4l2_streamoff (fd, type)) + return FALSE; + + return TRUE; +} + +static int +_fbdevVideoV4l2Dequeue (int fd, FBDevV4l2BufType type, FBDevV4l2Memory memory) +{ + struct v4l2_buffer buf = {0,}; + + return_val_if_fail (fd >= 0, -1); + + CLEAR (buf); + buf.type = type; + buf.memory = memory; + + if (!fbdev_v4l2_dequeue (fd, &buf)) + return FALSE; + + DRVLOG ("[Dequeue] index(%d) type(%d) memory(%d)\n", + buf.index, type, memory); + + return buf.index; +} + +static int +_fbdevVideoV4l2Queue (int fd, FBDevV4l2BufType type, FBDevV4l2Memory memory, int index, FBDevV4l2FimcBuffer *fimc_buf) +{ + struct v4l2_buffer buf = {0,}; + + return_val_if_fail (fd >= 0, -1); + + CLEAR (buf); + buf.index = index; + buf.type = type; + buf.memory = memory; + + if (memory == V4L2_MEMORY_USERPTR) + buf.m.userptr = (unsigned long) fimc_buf; + + if (!fbdev_v4l2_queue (fd, &buf)) + return FALSE; + + DRVLOG ("[Queue] index(%d) type(%d) memory(%d)\n", + index, type, memory); + + return index; +} + +static int +_open_device (char *device) +{ + int fd; + + return_val_if_fail (device != NULL, -1); + + fd = open (device, O_RDWR); + if (fd < 0) + { + xf86DrvMsg (0, X_ERROR, "Cannot open '%s'. fd(%d)\n", device, fd); + return -1; + } + + DRVLOG ("'%s' opened. fd(%d) \n", device, fd); + + return fd; +} + +static void +_close_device (int fd) +{ + int ret; + + return_if_fail (fd >= 0); + + ret = close (fd); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "Cannot close fd(%d)\n", fd); + return; + } + + DRVLOG ("fd(%d) closed. \n", fd); +} + +static Bool +_move_resize_fb (FBDevDispHandle *hdisp, int x, int y, int width, int height) +{ + struct fb_var_screeninfo var; + + return_val_if_fail (hdisp->fb_fd >= 0, FALSE); + + DRVLOG ("[MoveResize] '%s' to (%d,%d %dx%d) \n", + device_infos[hdisp->index].fb, x, y, width, height); + + if (!fbdevFbGetVarScreenInfo (hdisp->fb_fd, &var)) + return FALSE; + + var.xres = var.xres_virtual = width; + var.yres = var.yres_virtual = height; + var.transp.length = 0; + var.activate = FB_ACTIVATE_FORCE; + if (!fbdevFbSetVarScreenInfo (hdisp->fb_fd, &var)) + return FALSE; + + if (!fbdevFbGetFixScreenInfo (hdisp->fb_fd, &hdisp->fix)) + return FALSE; + + if (hdisp->fix.smem_len == 0) + return FALSE; + + hdisp->fb_base_phy = (void*)hdisp->fix.smem_start; /* Physical address */ + if (!hdisp->fb_base_phy) + return FALSE; + + hdisp->fb_base_vir = mmap (NULL, hdisp->fix.smem_len, + PROT_READ | PROT_WRITE, MAP_SHARED, hdisp->fb_fd, 0); + if (!hdisp->fb_base_vir) + return FALSE; + + if (!fbdevFbSetWinPosition (hdisp->fb_fd, x, y)) /* 1 : auto */ + { + munmap ((void*)hdisp->fb_base_vir, hdisp->fix.smem_len); + return FALSE; + } + + return TRUE; +} + +static Bool +_fbdevVideoV4l2EnsureStreamOff (FBDevDispHandle *hdisp) +{ + if (!hdisp->status.streamon) + return TRUE; + + if (!_fbdevVideoV4l2StreamOff (hdisp->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT)) + return FALSE; + + hdisp->status.streamon = FALSE; + + return TRUE; +} + +static Bool +_fbdevVideoV4l2OpenDevice (FBDevDispHandle *hdisp, int index, int requestbuffer) +{ + if (device_infos[index].bOpened) + { + DRVLOG ("[OpenDevice, %p] Already opened : %s\n", hdisp, device_infos[index].video); + return FALSE; + } + + hdisp->video_fd = _open_device (device_infos[index].video); + if (hdisp->video_fd < 0) + return FALSE; + + if (device_infos[index].type == OUTPUT_PATH_DMA) + { + hdisp->fb_fd = _open_device (device_infos[index].fb); + if (hdisp->fb_fd < 0) + { + _close_device (hdisp->video_fd); + hdisp->video_fd = -1; + return FALSE; + } + } + + device_infos[index].bOpened = TRUE; + + return TRUE; +} + +/* This function never failed. + * If failed, it means kernel has some problems. + * Then a device should be rebooted. + */ +static void +_fbdevVideoV4l2CloseDevice (FBDevDispHandle *hdisp) +{ + if (!_fbdevVideoV4l2EnsureStreamOff (hdisp)) // We will consider this as a LCD Off case. + xf86DrvMsg (0, X_WARNING, "[CloseDevice, %p] Warning : Cannot stream off!! \n", hdisp); + + if (hdisp->status.requestbuffer > 0) + { + if (hdisp->video_fd >= 0) + if (!_fbdevVideoV4l2ClearBuffer (hdisp->video_fd, + V4L2_BUF_TYPE_VIDEO_OUTPUT, + hdisp->memory, + hdisp->status.requestbuffer, + hdisp->src_buf)) + xf86DrvMsg (0, X_WARNING, "[CloseDevice, %p] Warning : Cannot clear buffer!! \n", hdisp); + + hdisp->status.requestbuffer = 0; + hdisp->src_buf = NULL; + } + + if (hdisp->video_fd >= 0) + { + _close_device (hdisp->video_fd); + hdisp->video_fd = -1; + } + + if (hdisp->fb_fd >= 0) + { + fbdevFbDeActivate (hdisp->fb_fd); + if (hdisp->fb_base_vir) + { + munmap ((void*)hdisp->fb_base_vir, hdisp->fix.smem_len); + hdisp->fb_base_vir = NULL; + } + + _close_device (hdisp->fb_fd); + hdisp->fb_fd = -1; + hdisp->fb_base_phy = NULL; + hdisp->fb_shown = FALSE; + } + + device_infos[hdisp->index].bOpened = FALSE; +} + +int +fbdevVideoV4l2GetHandleNums (void) +{ + return DEVICE_NUMS; +} + +Bool +fbdevVideoV4l2HandleOpened (int index) +{ + return_val_if_fail (index < DEVICE_NUMS, FALSE); + + return device_infos[index].bOpened; +} + +void * +fbdevVideoV4l2OpenHandle (ScreenPtr pScreen, int index, int requestbuffer) +{ + FBDevDispHandle *handle; + + return_val_if_fail (pScreen != NULL, NULL); + return_val_if_fail (index < DEVICE_NUMS, NULL); + + handle = (FBDevDispHandle*)calloc (sizeof (FBDevDispHandle), 1); + + return_val_if_fail (handle != NULL, NULL); + + handle->pScreen = pScreen; + handle->index = index; + handle->status.hw_rotate = -1; + handle->status.id = 0; + handle->status.cur_idx = -1; + handle->status.init = 0; + handle->memory = V4L2_MEMORY_MMAP; + handle->initial_dequeued_buf = requestbuffer; + handle->video_fd = -1; + handle->fb_fd = -1; + + if (!_fbdevVideoV4l2OpenDevice (handle, index, requestbuffer)) + { + free (handle); + return NULL; + } + + DRVLOG ("[OpenHandle, %p] Handle(%d) opened. \n", handle, index); + + return handle; +} + +void +fbdevVideoV4l2CloseHandle (void *handle) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + + return_if_fail (handle != NULL); + + _fbdevVideoV4l2CloseDevice ((FBDevDispHandle*)handle); + + if (hdisp->status.backup) + { + free (hdisp->status.backup); + hdisp->status.backup = NULL; + } + + DRVLOG ("[CloseHandle, %p] Handle(%d) closed. \n", hdisp, hdisp->index); + + free (handle); +} + +Bool +fbdevVideoV4l2StreamOn (void *handle) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + uint phy_addrs[3]; + + return_val_if_fail (hdisp != NULL, FALSE); + + hdisp->re_setting = TRUE; + + if (!_fbdevVideoV4l2OpenDevice (hdisp, hdisp->index, hdisp->status.requestbuffer)) + return FALSE; + + fbdevVideoV4l2SetFormat (handle, + &hdisp->status.img, + &hdisp->status.crop, + &hdisp->status.dst, + hdisp->status.id, + hdisp->status.scn_rotate, + hdisp->status.hw_rotate, + hdisp->status.hflip, + hdisp->status.vflip, + hdisp->status.requestbuffer, + hdisp->status.sync); + + phy_addrs[0] = hdisp->fimcbuf.base[0]; + phy_addrs[1] = hdisp->fimcbuf.base[1]; + phy_addrs[2] = hdisp->fimcbuf.base[2]; + + fbdevVideoV4l2Draw (handle, hdisp->status.backup, phy_addrs); + + if (hdisp->status.backup) + { + free (hdisp->status.backup); + hdisp->status.backup = NULL; + } + + hdisp->re_setting = FALSE; + + DRVLOG ("%s \n", __FUNCTION__); + + return TRUE; +} + +void +fbdevVideoV4l2StreamOff (void *handle) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + int requestbuffer; + + return_if_fail (hdisp != NULL); + + if (hdisp->memory == V4L2_MEMORY_MMAP) + { + int size; + + if (hdisp->status.backup) + { + free (hdisp->status.backup); + hdisp->status.backup = NULL; + } + + size = fbdevVideoQueryImageAttributes (NULL, hdisp->status.id, + (unsigned short*)&hdisp->status.img.width, + (unsigned short*)&hdisp->status.img.height, + NULL, NULL); + + if (size > 0) + hdisp->status.backup = malloc (size); + + if (hdisp->status.backup && + hdisp->src_buf && + hdisp->src_buf[hdisp->status.queued_index].buf) + memcpy (hdisp->status.backup, + hdisp->src_buf[hdisp->status.queued_index].buf, + size); + } + + requestbuffer = hdisp->status.requestbuffer; + + _fbdevVideoV4l2CloseDevice (hdisp); + + hdisp->status.requestbuffer = requestbuffer; + + DRVLOG ("%s \n", __FUNCTION__); +} + +/* img->x, img->y : not used. */ +Bool +fbdevVideoV4l2SetFormat (void *handle, + xRectangle *img, xRectangle *crop, xRectangle *dst, + uint id, + int scn_rotate, + int hw_rotate, + int hflip, + int vflip, + int requestbuffer, + Bool sync) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + Bool src_changed = FALSE; + Bool dst_changed = FALSE; + Bool buf_changed = FALSE; + + return_val_if_fail (handle != NULL, FALSE); + return_val_if_fail (img != NULL, FALSE); + return_val_if_fail (crop != NULL, FALSE); + return_val_if_fail (dst != NULL, FALSE); + + DRVLOG ("[SetFormat, %p] try to set : img(%d,%d %dx%d) crop(%d,%d %dx%d) dst(%d,%d %dx%d) id(%x), rot(%d), flip(%d,%d) req(%d)\n", hdisp, + img->x, img->y, img->width, img->height, + crop->x, crop->y, crop->width, crop->height, + dst->x, dst->y, dst->width, dst->height, + id, hw_rotate, hflip, vflip, requestbuffer); + + if (memcmp (&hdisp->status.img, img, sizeof (xRectangle)) || + memcmp (&hdisp->status.crop, crop, sizeof (xRectangle)) || + hdisp->status.id != id) + src_changed = TRUE; + + if (memcmp (&hdisp->status.dst, dst, sizeof (xRectangle)) || + hdisp->status.hw_rotate != hw_rotate || + hdisp->status.hflip != hflip || + hdisp->status.vflip != vflip) + dst_changed = TRUE; + + if (hdisp->status.requestbuffer != requestbuffer) + buf_changed = TRUE; + + if (hdisp->status.init && (src_changed || dst_changed || buf_changed)) + { + _fbdevVideoV4l2CloseDevice (hdisp); + _fbdevVideoV4l2OpenDevice (hdisp, hdisp->index, requestbuffer); + + DRVLOG ("[SetFormat, %p] changed : img(%d) dst(%d) buf(%d) \n", hdisp, + src_changed, dst_changed, buf_changed); + + /* After close device, below all steps should be done. */ + src_changed = dst_changed = buf_changed = TRUE; + hdisp->status.init = 0; + } + + if (hdisp->re_setting) + src_changed = dst_changed = buf_changed = TRUE; + + if (src_changed) + { + fbdevVideoV4l2GetFormatInfo (id, NULL, &hdisp->pixfmt, &hdisp->memory); + + DRVLOG ("[SetFormat, %p] id(%c%c%c%c) => pixfmt(%d) memory(%d) \n", hdisp, + id & 0xFF, (id & 0xFF00) >> 8, (id & 0xFF0000) >> 16, (id & 0xFF000000) >> 24, + hdisp->pixfmt, hdisp->memory); + + if (img->width % 16) + xf86DrvMsg (0, X_WARNING, "img->width(%d) is not multiple of 16!!!\n", img->width); + + if (!_fbdevVideoV4l2SetSrc (hdisp->video_fd, img, crop, hdisp->pixfmt)) + { + xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _fbdevVideoV4l2SetSrc is failed. \n", hdisp); + return FALSE; + } + + hdisp->status.img = *img; + hdisp->status.crop = *crop; + hdisp->status.id = id; + hdisp->status.sync = sync; + + hdisp->status.requestbuffer = 0; + hdisp->status.init = 1; + } + + if (dst_changed) + { + hdisp->status.cur_idx = 0; + hdisp->status.hw_rotate = hw_rotate; + hdisp->status.scn_rotate = scn_rotate; + hdisp->status.hflip = hflip; + hdisp->status.vflip = vflip; + hdisp->status.dst = *dst; + + if (hdisp->fb_fd >= 0) + { + xRectangle fb_rect = *dst; + if (!_move_resize_fb (hdisp, fb_rect.x, fb_rect.y, fb_rect.width, fb_rect.height)) + { + xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _move_resize_fb is failed. \n", hdisp); + return FALSE; + } + } + + fbdev_util_rotate_rect ((int)hdisp->pScreen->width, + (int)hdisp->pScreen->height, + 0, (hw_rotate + (360 - scn_rotate)) % 360, dst); + if (hdisp->fb_base_phy) + { + xRectangle win_rect = {0, 0, dst->width, dst->height}; + + if (!_fbdevVideoV4l2SetDst (hdisp->video_fd, dst, &win_rect, hw_rotate, hflip, vflip, OUTPUT_PATH_DMA, (uint)hdisp->fb_base_phy)) + { + xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _fbdevVideoV4l2SetDst is failed. \n", hdisp); + return FALSE; + } + } + else + { + if (!_fbdevVideoV4l2SetDst (hdisp->video_fd, dst, dst, hw_rotate, hflip, vflip, OUTPUT_PATH_FIMD, 0)) + { + xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _fbdevVideoV4l2SetDst is failed. \n", hdisp); + return FALSE; + } + } + } + + if (buf_changed) + { + if (!_fbdevVideoV4l2SetBuffer (hdisp->video_fd, + V4L2_BUF_TYPE_VIDEO_OUTPUT, + hdisp->memory, + requestbuffer, + &hdisp->src_buf)) + { + xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _fbdevVideoV4l2SetBuffer is failed. \n", hdisp); + return FALSE; + } + + hdisp->status.cur_idx = 0; + hdisp->status.requestbuffer = requestbuffer; + hdisp->initial_dequeued_buf = requestbuffer; + } + + if (!hdisp->status.streamon) + { + _fbdevVideoV4l2StreamOn (hdisp->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT); + hdisp->status.streamon = TRUE; + } + + return TRUE; +} + +XF86ImagePtr +fbdevVideoV4l2SupportImages (int *count) +{ + if (count) + *count = NUM_IMAGES; + + return Images; +} + +int +fbdevVideoV4l2Draw (void *handle, uchar *buf, uint *phy_addrs) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + int idx; + + return_val_if_fail (handle != NULL, FALSE); +// return_val_if_fail (phy_addrs != NULL, FALSE); + + if (!hdisp->status.sync) + { + if (hdisp->initial_dequeued_buf > 0) + { + idx = hdisp->status.requestbuffer - hdisp->initial_dequeued_buf; + hdisp->initial_dequeued_buf--; + } + else + { + if ((idx = _fbdevVideoV4l2Dequeue (hdisp->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, hdisp->memory)) < 0) + { + xf86DrvMsg (0, X_ERROR, "[Draw, %p] _fbdevVideoV4l2Dequeue is failed. \n", hdisp); + return FALSE; + } + } + } + else + idx = hdisp->status.queued_index; + + if (hdisp->memory == V4L2_MEMORY_MMAP) + { + uchar *destbuf = hdisp->src_buf[idx].buf; + int size; + + return_val_if_fail (buf != NULL, FALSE); + + hdisp->status.last_buffer = destbuf; + + size = fbdevVideoQueryImageAttributes (NULL, hdisp->status.id, + (unsigned short*)&hdisp->status.img.width, + (unsigned short*)&hdisp->status.img.height, + NULL, NULL); + memcpy (destbuf, buf, size); + } + + hdisp->fimcbuf.base[0] = phy_addrs[0]; + hdisp->fimcbuf.base[1] = phy_addrs[1]; + hdisp->fimcbuf.base[2] = phy_addrs[2]; + hdisp->fimcbuf.length[0] = hdisp->status.img.width * hdisp->status.img.height; + hdisp->fimcbuf.length[1] = hdisp->fimcbuf.length[0] >> 1; + hdisp->fimcbuf.length[2] = hdisp->fimcbuf.base[1] + hdisp->fimcbuf.length[1]; + + if ((idx = _fbdevVideoV4l2Queue (hdisp->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, + hdisp->memory, idx, &hdisp->fimcbuf)) < 0) + { + xf86DrvMsg (0, X_ERROR, "[Draw, %p] _fbdevVideoV4l2Queue is failed. \n", hdisp); + return FALSE; + } + + if (hdisp->status.sync) + { + if ((idx = _fbdevVideoV4l2Dequeue (hdisp->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, hdisp->memory)) < 0) + { + xf86DrvMsg (0, X_ERROR, "[Draw, %p] _fbdevVideoV4l2Dequeue is failed. \n", hdisp); + return FALSE; + } + } + + if (hdisp->fb_fd >= 0 && !hdisp->fb_shown) + { + if (!fbdevFbActivate (hdisp->fb_fd)) + { + xf86DrvMsg (0, X_ERROR, "[%s, %p] %d failed. \n", __FUNCTION__, hdisp, __LINE__); + return FALSE; + } + + hdisp->fb_shown = TRUE; + } + + hdisp->status.queued_index = idx + 1; + if (hdisp->status.queued_index > hdisp->status.requestbuffer - 1) + hdisp->status.queued_index = 0; + + return TRUE; +} + +Bool +fbdevVideoV4l2GetFormatInfo (int id, int *type, uint *pixelformat, FBDevV4l2Memory *memory) +{ + int i; + + for (i = 0; i < sizeof (format_infos) / sizeof (FormatInfo); i++) + if (format_infos[i].id == id) + { + if (type) + *type = format_infos[i].type; + if (pixelformat) + *pixelformat = format_infos[i].pixelformat; + if (memory) + *memory = format_infos[i].memory; + return TRUE; + } + + return FALSE; +} + +/* img : original src size + * src : real src size (cropped area inside img) + * dst : real dst size + * original dst size (in case that image is drawn on opened framebuffer) + */ +Bool +fbdevVideoV4l2CheckSize (void *handle, uint pixelformat, + xRectangle *img, xRectangle *src, xRectangle *dst, + int type, int memory) +{ + /* img */ + if (img) + { + if (img->width % 16) + xf86DrvMsg (0, X_WARNING, "img's width(%d) is not multiple of 16!!!\n", img->width); + + if (type == TYPE_YUV420 && img->height % 2) + xf86DrvMsg (0, X_WARNING, "img's height(%d) is not multiple of 2!!!\n", img->height); + + return_val_if_fail (img->width >= 16, FALSE); + return_val_if_fail (img->height >= 16, FALSE); + } + + /* src */ + if (src) + { + if (type == TYPE_YUV420 || type == TYPE_YUV422) + { + src->x = src->x & (~0x1); + src->width = src->width & (~0x1); + } + + if (type == TYPE_YUV420) + src->height = src->height & (~0x1); + + return_val_if_fail (src->width >= 16, FALSE); + return_val_if_fail (src->height >= 16, FALSE); + } + + /* dst */ + if (dst) + { + dst->width = dst->width & (~0x1); + dst->height = dst->height & (~0x1); + + return_val_if_fail (dst->width >= 8, FALSE); + return_val_if_fail (dst->height >= 8, FALSE); + } + + return TRUE; +} + +void +fbdevVideoGetFBInfo (void *handle, void **base, xRectangle *pos) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + + if (!hdisp) + return; + + if (pos) + *pos = hdisp->status.dst; + if (base) + *base = hdisp->fb_base_vir; +} diff --git a/src/xv/fbdev_v4l2.c b/src/xv/fbdev_v4l2.c new file mode 100644 index 0000000..a49305e --- /dev/null +++ b/src/xv/fbdev_v4l2.c @@ -0,0 +1,511 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include +#include +#include +#include + +#include "xf86.h" + +#include "fbdev_v4l2.h" +#include "fbdev_util.h" + +typedef struct _CapInfo +{ + int value; + char *name; +} CapInfo; + +static CapInfo cap_infos [] = +{ + {V4L2_CAP_VIDEO_CAPTURE, "VIDEO_CAPTURE"}, + {V4L2_CAP_VIDEO_OUTPUT, "VIDEO_OUTPUT"}, + {V4L2_CAP_VIDEO_OVERLAY, "VIDEO_OVERLAY"}, + {V4L2_CAP_VBI_CAPTURE, "VBI_CAPTURE"}, + {V4L2_CAP_VBI_OUTPUT, "VBI_OUTPUT"}, + {V4L2_CAP_SLICED_VBI_CAPTURE, "SLICED_VBI_CAPTURE"}, + {V4L2_CAP_SLICED_VBI_OUTPUT, "SLICED_VBI_OUTPUT"}, + {V4L2_CAP_RDS_CAPTURE, "RDS_CAPTURE"}, + {V4L2_CAP_VIDEO_OUTPUT_OVERLAY, "VIDEO_OUTPUT_OVERLAY"}, + {V4L2_CAP_HW_FREQ_SEEK, "HW_FREQ_SEEK"}, + {V4L2_CAP_RDS_OUTPUT, "RDS_OUTPUT"}, + {V4L2_CAP_TUNER, "TUNER"}, + {V4L2_CAP_AUDIO, "AUDIO"}, + {V4L2_CAP_RADIO, "RADIO"}, + {V4L2_CAP_MODULATOR, "MODULATOR"}, + {V4L2_CAP_READWRITE, "READWRITE"}, + {V4L2_CAP_ASYNCIO, "ASYNCIO"}, + {V4L2_CAP_STREAMING, "STREAMING"} +}; + +static Bool _fbdev_v4l2_ioctl (int fd, int cmd, void *data, char *debug) +{ + int retry = 0; + int ret; + +try_again: + ret = ioctl (fd, cmd, data); + if (ret < 0) + { + if (errno == EINTR || errno == EAGAIN) + { + if (retry < 100) + { + retry++; + goto try_again; + } + } + + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_querycap (int fd, int capabilities) +{ + struct v4l2_capability cap; + int ret; + + CLEAR (cap); + ret = ioctl (fd, VIDIOC_QUERYCAP, &cap); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[QUERYCAP] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + if (~(cap.capabilities) & capabilities) + { + int unsupport = ~(cap.capabilities) & capabilities; + int i; + + for (i = 0; i < sizeof (cap_infos) / sizeof (CapInfo); i++) + if (unsupport & cap_infos[i].value) + xf86DrvMsg (0, X_ERROR, "[QUERYCAP] %s not support.\n", cap_infos[i].name); + + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_cropcap (int fd, FBDevV4l2BufType type, struct v4l2_rect *crop) +{ + struct v4l2_cropcap cropcap; + int ret; + + CLEAR(cropcap); + cropcap.type = type; + ret = ioctl (fd, VIDIOC_CROPCAP, &cropcap); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[CROPCAP] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + /* check if crop_rect si valid */ + if ((crop->left < cropcap.bounds.left) && + (crop->top < cropcap.bounds.top) && + (crop->width > cropcap.bounds.width) && + (crop->height > cropcap.bounds.height)) + { + xf86DrvMsg (0, X_ERROR, "(%d,%d %dx%d) is out of bound(%d,%d %dx%d)\n", + crop->left, crop->top, crop->width, crop->height, + cropcap.bounds.left, cropcap.bounds.top, + cropcap.bounds.width, cropcap.bounds.height); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_enum_std (int fd, struct v4l2_standard *std, v4l2_std_id std_id) +{ + std->index = 0; + + while (0 == ioctl (fd, VIDIOC_ENUMSTD, std)) + { + /* return TRUE if std_id found */ + if (std->id & std_id) + { + xf86DrvMsg (0, X_ERROR, "[ENUMSTD] name(%s). (%s)\n", std->name, strerror(errno)); + return TRUE; + } + + std->index++; + } + + return FALSE; +} + +Bool fbdev_v4l2_enum_output (int fd, struct v4l2_output *output, FBDevV4l2BufType type) +{ + output->index = 0; + + while (0 == ioctl (fd, VIDIOC_ENUMOUTPUT, output)) + { + /* return TRUE if type found */ + if (output->type & type) + { + xf86DrvMsg (0, X_ERROR, "[ENUMOUTPUT] index(%d) type(0x%08x) name(%s). (%s)\n", + output->index,output->type,output->name, strerror(errno)); + return TRUE; + } + + output->index++; + } + + return FALSE; +} + +Bool fbdev_v4l2_enum_fmt (int fd, struct v4l2_fmtdesc *desc, FBDevV4l2BufType type) +{ + desc->index = 0; + + while (0 == ioctl (fd, VIDIOC_ENUM_FMT, desc)) + { + /* return TRUE if type found */ + if (desc->type & type) + { + xf86DrvMsg (0, X_ERROR, "[ENUM_FMT] index(%d) type(0x%08x) desc(%s) pxlfmt(0x%08x). (%s)\n", + desc->index, desc->type, desc->description, desc->pixelformat, strerror(errno)); + return TRUE; + } + + desc->index++; + } + + return FALSE; +} + +Bool fbdev_v4l2_g_std (int fd, v4l2_std_id *std_id) +{ + int ret; + + ret = ioctl (fd, VIDIOC_G_STD, std_id); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[G_STD] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_s_std (int fd, v4l2_std_id std_id) +{ + int ret; + + ret = ioctl (fd, VIDIOC_S_STD, &std_id); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[S_STD] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_g_output (int fd, int *index) +{ + int ret; + + ret = ioctl (fd, VIDIOC_G_OUTPUT, index); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[G_OUTPUT] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_s_output (int fd, int index) +{ + int ret; + + ret = ioctl (fd, VIDIOC_S_OUTPUT, &index); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[S_OUTPUT] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_try_fmt (int fd, struct v4l2_format *format) +{ + int ret; + + ret = ioctl (fd, VIDIOC_TRY_FMT, format); + if (ret < 0) + return FALSE; + + return TRUE; +} + +Bool fbdev_v4l2_g_fmt (int fd, struct v4l2_format *format) +{ + int ret; + + ret = ioctl (fd, VIDIOC_G_FMT, format); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[G_FMT] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_s_fmt (int fd, struct v4l2_format *format) +{ + int ret; + + ret = ioctl (fd, VIDIOC_S_FMT, format); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[S_FMT] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_g_parm (int fd, struct v4l2_streamparm *parm) +{ + int ret; + + ret = ioctl (fd, VIDIOC_G_PARM, parm); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[G_PARM] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_s_parm (int fd, struct v4l2_streamparm *parm) +{ + int ret; + + ret = ioctl (fd, VIDIOC_S_PARM, parm); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[S_PARM] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_g_fbuf (int fd, struct v4l2_framebuffer *frame) +{ + int ret; + + ret = ioctl (fd, VIDIOC_G_FBUF, frame); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[G_FBUF] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_s_fbuf (int fd, struct v4l2_framebuffer *frame) +{ + int ret; + + ret = ioctl (fd, VIDIOC_S_FBUF, frame); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[S_FBUF] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_g_crop (int fd, struct v4l2_crop *crop) +{ + int ret; + + ret = ioctl (fd, VIDIOC_G_CROP, crop); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[G_CROP] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_s_crop (int fd, struct v4l2_crop *crop) +{ + int ret; + + ret = ioctl (fd, VIDIOC_S_CROP, crop); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[S_CROP] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_g_ctrl (int fd, struct v4l2_control *ctrl) +{ + int ret; + + ret = ioctl (fd, VIDIOC_G_CTRL, ctrl); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[G_CTRL] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_s_ctrl (int fd, struct v4l2_control *ctrl) +{ + int ret; + + ret = ioctl (fd, VIDIOC_S_CTRL, ctrl); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "[S_CTRL] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_streamon (int fd, FBDevV4l2BufType type) +{ + if (!_fbdev_v4l2_ioctl (fd, VIDIOC_STREAMON, (void*)&type, "STREAMON")) + { + xf86DrvMsg (0, X_ERROR, "[STREAMON] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_streamoff (int fd, FBDevV4l2BufType type) +{ + if (!_fbdev_v4l2_ioctl (fd, VIDIOC_STREAMOFF, (void*)&type, "STREAMOFF")) + { + xf86DrvMsg (0, X_ERROR, "[STREAMOFF] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + + +Bool fbdev_v4l2_start_overlay (int fd) +{ + int start = 1; + + if (!_fbdev_v4l2_ioctl (fd, VIDIOC_OVERLAY, (void*)&start, "OVERLAY (start)")) + { + xf86DrvMsg (0, X_ERROR, "[OVERLAY] (start) failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_stop_overlay (int fd) +{ + int stop = 0; + + if (!_fbdev_v4l2_ioctl (fd, VIDIOC_OVERLAY, (void*)&stop, "OVERLAY (stop)")) + { + xf86DrvMsg (0, X_ERROR, "[OVERLAY] (stop) failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_reqbuf (int fd, struct v4l2_requestbuffers *req) +{ + if (!_fbdev_v4l2_ioctl (fd, VIDIOC_REQBUFS, (void*)req, "REQBUFS")) + { + xf86DrvMsg (0, X_ERROR, "[REQBUFS] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_querybuf (int fd, struct v4l2_buffer *set_buf) +{ + if (!_fbdev_v4l2_ioctl (fd, VIDIOC_QUERYBUF, (void*)set_buf, "QUERYBUF")) + { + xf86DrvMsg (0, X_ERROR, "[QUERYBUF] failed. (%s)\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + + +Bool fbdev_v4l2_queue (int fd, struct v4l2_buffer *buf) +{ + if (!_fbdev_v4l2_ioctl (fd, VIDIOC_QBUF, (void*)buf, "QBUF")) + { + xf86DrvMsg (0, X_ERROR, "[QBUF] failed. (%s)\n", strerror(errno)); + + return FALSE; + } + + return TRUE; +} + +Bool fbdev_v4l2_dequeue (int fd, struct v4l2_buffer *buf) +{ + if (!_fbdev_v4l2_ioctl (fd, VIDIOC_DQBUF, (void*)buf, "DQBUF")) + { + xf86DrvMsg (0, X_ERROR, "[DQBUF] failed. (%s)\n", strerror(errno)); + + return FALSE; + } + + return TRUE; +} diff --git a/src/xv/fbdev_v4l2.h b/src/xv/fbdev_v4l2.h new file mode 100644 index 0000000..931da95 --- /dev/null +++ b/src/xv/fbdev_v4l2.h @@ -0,0 +1,84 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef __FBDEV_V4L2_H__ +#define __FBDEV_V4L2_H__ + +#include "fbdev_video_types.h" + + +#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */ +#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_PADDR_Y (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_PADDR_CB (V4L2_CID_PRIVATE_BASE + 2) +#define V4L2_CID_PADDR_CR (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_PADDR_CBCR (V4L2_CID_PRIVATE_BASE + 4) +#define V4L2_CID_OVERLAY_AUTO (V4L2_CID_PRIVATE_BASE + 5) +#define V4L2_CID_OVERLAY_VADDR0 (V4L2_CID_PRIVATE_BASE + 6) +#define V4L2_CID_OVERLAY_VADDR1 (V4L2_CID_PRIVATE_BASE + 7) +#define V4L2_CID_OVERLAY_VADDR2 (V4L2_CID_PRIVATE_BASE + 8) +#define V4L2_CID_OVLY_MODE (V4L2_CID_PRIVATE_BASE + 9) + + +Bool fbdev_v4l2_querycap (int fd, int capabilities); +Bool fbdev_v4l2_cropcap (int fd, FBDevV4l2BufType type, struct v4l2_rect *crop); + +Bool fbdev_v4l2_enum_std (int fd, struct v4l2_standard *std, v4l2_std_id std_id); +Bool fbdev_v4l2_enum_output (int fd, struct v4l2_output *output, FBDevV4l2BufType type); +Bool fbdev_v4l2_enum_fmt (int fd, struct v4l2_fmtdesc *desc, FBDevV4l2BufType type); + +Bool fbdev_v4l2_g_std (int fd, v4l2_std_id *std_id); +Bool fbdev_v4l2_s_std (int fd, v4l2_std_id std_id); +Bool fbdev_v4l2_g_output (int fd, int *index); +Bool fbdev_v4l2_s_output (int fd, int index); +Bool fbdev_v4l2_try_fmt (int fd, struct v4l2_format *format); +Bool fbdev_v4l2_g_fmt (int fd, struct v4l2_format *format); +Bool fbdev_v4l2_s_fmt (int fd, struct v4l2_format *format); +Bool fbdev_v4l2_g_parm (int fd, struct v4l2_streamparm *parm); +Bool fbdev_v4l2_s_parm (int fd, struct v4l2_streamparm *parm); +Bool fbdev_v4l2_g_fbuf (int fd, struct v4l2_framebuffer *frame); +Bool fbdev_v4l2_s_fbuf (int fd, struct v4l2_framebuffer *frame); +Bool fbdev_v4l2_g_crop (int fd, struct v4l2_crop *crop); +Bool fbdev_v4l2_s_crop (int fd, struct v4l2_crop *crop); +Bool fbdev_v4l2_g_ctrl (int fd, struct v4l2_control *ctrl); +Bool fbdev_v4l2_s_ctrl (int fd, struct v4l2_control *ctrl); + +Bool fbdev_v4l2_reqbuf (int fd, struct v4l2_requestbuffers *req); +Bool fbdev_v4l2_querybuf (int fd, struct v4l2_buffer *set_buf); +Bool fbdev_v4l2_queue (int fd, struct v4l2_buffer *buf); +Bool fbdev_v4l2_dequeue (int fd, struct v4l2_buffer *buf); + +Bool fbdev_v4l2_streamon (int fd, FBDevV4l2BufType type); +Bool fbdev_v4l2_streamoff (int fd, FBDevV4l2BufType type); +Bool fbdev_v4l2_start_overlay (int fd); +Bool fbdev_v4l2_stop_overlay (int fd); + + +#endif diff --git a/src/xv/fbdev_video.c b/src/xv/fbdev_video.c new file mode 100644 index 0000000..1864e08 --- /dev/null +++ b/src/xv/fbdev_video.c @@ -0,0 +1,1157 @@ +/* + * xserver-xorg-video-emulfb + * + * Copyright 2004 Keith Packard + * Copyright 2005 Eric Anholt + * Copyright 2006 Nokia Corporation + * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: Boram Park + * + * Permission to use, copy, modify, distribute and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of the authors and/or copyright holders + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. The authors and + * copyright holders make no representations about the suitability of this + * software for any purpose. It is provided "as is" without any express + * or implied warranty. + * + * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "fourcc.h" + +#include "fb.h" +#include "fbdevhw.h" +#include "damage.h" + +#include "xf86xv.h" + +#include "fbdev.h" + +#include "fbdev_dpms.h" +#include "fbdev_video.h" +#include "fbdev_util.h" +#include "fbdev_util.h" +#include "fbdev_pixman.h" +#include "fbdev_fb.h" +#include "fbdev_video_fourcc.h" +#include "fbdev_video_v4l2.h" +#include "fbdev_video_virtual.h" + +#include "xv_types.h" + +extern CallbackListPtr DPMSCallback; + +static XF86VideoEncodingRec DummyEncoding[] = +{ + { 0, "XV_IMAGE", -1, -1, { 1, 1 } }, + { 1, "XV_IMAGE", 2560, 2560, { 1, 1 } }, +}; + +static XF86VideoFormatRec Formats[] = +{ + { 16, TrueColor }, + { 24, TrueColor }, + { 32, TrueColor }, +}; + +static XF86AttributeRec Attributes[] = +{ + { 0, -1, 270, "_USER_WM_PORT_ATTRIBUTE_ROTATION" }, + { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_HFLIP" }, + { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_VFLIP" }, + { 0, -1, 1, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION" }, + { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_DRAWING_MODE" }, + { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF" }, +}; + +typedef enum +{ + PAA_MIN, + PAA_ROTATION, + PAA_HFLIP, + PAA_VFLIP, + PAA_PREEMPTION, + PAA_DRAWINGMODE, + PAA_STREAMOFF, + PAA_MAX +} FBDevPortAttrAtom; + +enum +{ + ON_NONE, + ON_FB, + ON_WINDOW, + ON_PIXMAP +}; + +static struct +{ + FBDevPortAttrAtom paa; + const char *name; + Atom atom; +} atom_list[] = +{ + { PAA_ROTATION, "_USER_WM_PORT_ATTRIBUTE_ROTATION", None }, + { PAA_HFLIP, "_USER_WM_PORT_ATTRIBUTE_HFLIP", None }, + { PAA_VFLIP, "_USER_WM_PORT_ATTRIBUTE_VFLIP", None }, + { PAA_PREEMPTION, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION", None }, + { PAA_DRAWINGMODE, "_USER_WM_PORT_ATTRIBUTE_DRAWING_MODE", None }, + { PAA_STREAMOFF, "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", None }, +}; + +static int registered_handler; +extern CallbackListPtr DPMSCallback; + +#define FBDEV_MAX_PORT 16 +#define REQ_BUF_NUM 3 + +#define NUM_FORMATS (sizeof(Formats) / sizeof(Formats[0])) +#define NUM_ATTRIBUTES (sizeof(Attributes) / sizeof(Attributes[0])) +#define NUM_ATOMS (sizeof(atom_list) / sizeof(atom_list[0])) + +static PixmapPtr +_fbdevVideoGetPixmap (DrawablePtr pDraw) +{ + if (pDraw->type == DRAWABLE_WINDOW) + return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw); + else + return (PixmapPtr) pDraw; +} + +static void +_fbdevVideoGetRotation (ScreenPtr pScreen, + FBDevPortPrivPtr pPortPriv, + DrawablePtr pDraw, + int *scn_rotate, + int *rotate, + int *hw_rotate) +{ + ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum]; + FBDevPtr pFBDev = FBDEVPTR (pScrnInfo); + + *scn_rotate = 0; + *rotate = 0; + *hw_rotate = 0; + +#ifdef RANDR + switch (pFBDev->rotate) + { + case RR_Rotate_90: + *scn_rotate = 270; + break; + case RR_Rotate_180: + *scn_rotate = 180; + break; + case RR_Rotate_270: + *scn_rotate = 90; + break; + case RR_Rotate_0: + break; + } +#endif + + if (pPortPriv->rotate >= 0) + *rotate = pPortPriv->rotate; + + *hw_rotate = (*rotate + *scn_rotate + 360) % 360; +} + +static void +_fbdevVideoCloseV4l2Handle (ScrnInfoPtr pScrnInfo, FBDevPortPrivPtr pPortPriv) +{ + FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate; + + if (!pPortPriv->v4l2_handle) + return; + + fbdevVideoV4l2CloseHandle (pPortPriv->v4l2_handle); + + pFBDev->v4l2_owner[pPortPriv->v4l2_index] = NULL; + + pPortPriv->v4l2_handle = NULL; + pPortPriv->v4l2_index = -1; +} + +static Atom +_fbdevVideoGetPortAtom (FBDevPortAttrAtom paa) +{ + int i; + + return_val_if_fail (paa > PAA_MIN && paa < PAA_MAX, None); + + for (i = 0; i < NUM_ATOMS; i++) + { + if (paa == atom_list[i].paa) + { + if (atom_list[i].atom == None) + atom_list[i].atom = MakeAtom (atom_list[i].name, strlen (atom_list[i].name), TRUE); + + return atom_list[i].atom; + } + } + + ErrorF ("Error: Unknown Port Attribute Name!\n"); + + return None; +} + +static int +_fbdevVideoInterfbdevtXRects (xRectangle *dest, xRectangle *src1, xRectangle *src2) +{ + int dest_x, dest_y; + int dest_x2, dest_y2; + int return_val; + + return_val_if_fail (src1 != NULL, FALSE); + return_val_if_fail (src2 != NULL, FALSE); + + return_val = FALSE; + + dest_x = MAX (src1->x, src2->x); + dest_y = MAX (src1->y, src2->y); + dest_x2 = MIN (src1->x + src1->width, src2->x + src2->width); + dest_y2 = MIN (src1->y + src1->height, src2->y + src2->height); + + if (dest_x2 > dest_x && dest_y2 > dest_y) + { + if (dest) + { + dest->x = dest_x; + dest->y = dest_y; + dest->width = dest_x2 - dest_x; + dest->height = dest_y2 - dest_y; + } + return_val = TRUE; + } + else if (dest) + { + dest->width = 0; + dest->height = 0; + } + + return return_val; +} + +static int +_fbdevVideodrawingOn (FBDevPortPrivPtr pPortPriv, DrawablePtr pDraw) +{ + if (pDraw->type == DRAWABLE_PIXMAP) + return ON_PIXMAP; + else if (pDraw->type == DRAWABLE_WINDOW) + { + PropertyPtr prop = fbdev_util_get_window_property ((WindowPtr)pDraw, + "XV_ON_DRAWABLE"); + if (prop && *(int*)prop->data > 0) + return ON_WINDOW; + } + + return ON_FB; +} + +static int +_fbdevVideoParseFormatBuffer (uchar *buf, uint *phy_addrs) +{ + XV_PUTIMAGE_DATA_PTR data = (XV_PUTIMAGE_DATA_PTR) buf; + + int valid = XV_PUTIMAGE_VALIDATE_DATA (data); + if (valid < 0) + return valid; + + phy_addrs[0] = data->YPhyAddr; + phy_addrs[1] = data->CbPhyAddr; + phy_addrs[2] = data->CrPhyAddr; + + return 0; +} + +static XF86ImageRec * +_fbdevVideoGetImageInfo (int id) +{ + XF86ImagePtr pImages; + int i, count = 0; + + pImages = fbdevVideoV4l2SupportImages (&count); + + for (i = 0; i < count; i++) + { + if (pImages[i].id == id) + return &pImages[i]; + } + + return NULL; +}; + +static Bool +_fbdevVideoSetMode (ScrnInfoPtr pScrnInfo, FBDevPortPrivPtr pPortPriv, int *index) +{ + FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate; + Bool full = TRUE; + int i = 0; + + *index = -1; + + if (pPortPriv->preemption == -1) + { + pPortPriv->mode = PORT_MODE_WAITING; + return TRUE; + } + + for (i = 0; i < pFBDev->v4l2_num; i++) + if (!fbdevVideoV4l2HandleOpened (i)) + { + full = FALSE; + break; + } + + if (!full) + { + *index = i; + pPortPriv->mode = PORT_MODE_V4L2; + return TRUE; + } + + /* All handles are occupied. So we need to steal one of them. */ + + if (pPortPriv->preemption == 0) + { + pPortPriv->mode = PORT_MODE_WAITING; + return TRUE; + } + + for (i = 0; i < pFBDev->v4l2_num; i++) + { + FBDevPortPrivPtr pOwnerPort = (FBDevPortPrivPtr) pFBDev->v4l2_owner[i]; + + if (pOwnerPort && pOwnerPort->preemption == 0) + { + _fbdevVideoCloseV4l2Handle (pScrnInfo, pOwnerPort); + + pOwnerPort->mode = PORT_MODE_WAITING; + pPortPriv->mode = PORT_MODE_V4L2; + *index = i; + return TRUE; + } + } + + xf86DrvMsg (0, X_ERROR, "fbdev/put_image: Three or more preemptive ports were requested\n"); + + return FALSE; +} + +static int +_fbdevVideoPutImageV4l2 (ScrnInfoPtr pScrnInfo, + FBDevPortPrivPtr pPortPriv, + xRectangle *img, + xRectangle *src, + xRectangle *dst, + RegionPtr clip_boxes, + int scn_rotate, + int rotate, + int hw_rotate, + XF86ImageRec *image_info, + uchar *buf, + FBDevPortMode modeBefore, + int v4l2_index, + DrawablePtr pDraw) +{ + FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate; + uint phy_addrs[4] = {0,}; + FBDevV4l2Memory memory; + uint pixelformat; + int fmt_type = 0; + + if (!fbdevVideoV4l2GetFormatInfo (image_info->id, &fmt_type, &pixelformat, &memory)) + { + xf86DrvMsg (0, X_ERROR, "ID(%c%c%c%c) is not in 'format_infos'.\n", + image_info->id & 0xFF, (image_info->id & 0xFF00) >> 8, + (image_info->id & 0xFF0000) >> 16, (image_info->id & 0xFF000000) >> 24); + return BadRequest; + } + + if (memory == V4L2_MEMORY_USERPTR) + { + int ret; + if ((ret = _fbdevVideoParseFormatBuffer (buf, phy_addrs)) < 0) + { + if (ret == XV_HEADER_ERROR) + xf86DrvMsg (0, X_ERROR, "XV_HEADER_ERROR\n"); + else if (ret == XV_VERSION_MISMATCH) + xf86DrvMsg (0, X_ERROR, "XV_VERSION_MISMATCH\n"); + + return BadRequest; + } + + /* Skip frame */ + if (phy_addrs[0] == 0) + return Success; + } + + if (!pPortPriv->v4l2_handle) + { + pPortPriv->v4l2_handle = fbdevVideoV4l2OpenHandle (pScrnInfo->pScreen, v4l2_index, REQ_BUF_NUM); + if (!pPortPriv->v4l2_handle) + { + int other_index = (v4l2_index == 0) ? 1 : 0; + if (fbdevVideoV4l2HandleOpened (other_index)) + { + xf86DrvMsg (0, X_ERROR, "fbdevVideoV4l2OpenHandle failed. no empty.\n"); + return BadRequest; + } + else + { + pPortPriv->v4l2_handle = fbdevVideoV4l2OpenHandle (pScrnInfo->pScreen, other_index, REQ_BUF_NUM); + if (!pPortPriv->v4l2_handle) + { + xf86DrvMsg (0, X_ERROR, "fbdevVideoV4l2OpenHandle failed. fail open.\n"); + return BadRequest; + } + } + + v4l2_index = other_index; + } + + pFBDev->v4l2_owner[v4l2_index] = (void*)pPortPriv; + pPortPriv->v4l2_index = v4l2_index; + } + + if (!fbdevVideoV4l2CheckSize (pPortPriv->v4l2_handle, pixelformat, img, src, dst, fmt_type, V4L2_MEMORY_MMAP)) + return BadRequest; + + if (fbdevVideoV4l2SetFormat (pPortPriv->v4l2_handle, img, src, dst, + image_info->id, scn_rotate, hw_rotate, + pPortPriv->hflip, pPortPriv->vflip, + REQ_BUF_NUM, FALSE)) + { + fbdevVideoV4l2Draw (pPortPriv->v4l2_handle, buf, phy_addrs); + + if (modeBefore == PORT_MODE_WAITING) + pScrnInfo->pScreen->WindowExposures ((WindowPtr) pDraw, clip_boxes, NULL); + +#if ENABLE_ARM + /* update cliplist */ + if (!REGION_EQUAL (pScrnInfo->pScreen, &pPortPriv->clip, clip_boxes)) + { + /* setting transparency length to 8 */ + if (!pFBDev->bFbAlphaEnabled) + { + fbdevFbScreenAlphaInit (fbdevHWGetFD (pScrnInfo)); + pFBDev->bFbAlphaEnabled = TRUE; + } + } +#endif + + return Success; + } + + _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv); + + pPortPriv->mode = PORT_MODE_WAITING; + + return Success; +} + +static int +_fbdevVideoPutImageOnDrawable (ScrnInfoPtr pScrnInfo, + FBDevPortPrivPtr pPortPriv, + xRectangle *img, + xRectangle *src, + xRectangle *dst, + RegionPtr clip_boxes, + int scn_rotate, + int rotate, + XF86ImageRec *image_info, + uchar *buf, + DrawablePtr pDraw) +{ + pixman_format_code_t src_format, dst_format; + xRectangle pxm = {0,}; + + PixmapPtr pPixmap = _fbdevVideoGetPixmap (pDraw); + + pxm.width = pPixmap->drawable.width; + pxm.height = pPixmap->drawable.height; + + switch (image_info->id) + { + case FOURCC_I420: + case FOURCC_YV12: + src_format = PIXMAN_yv12; + break; + case FOURCC_YUY2: + src_format = PIXMAN_yuy2; + break; + case FOURCC_RGB565: + src_format = PIXMAN_r5g6b5; + break; + case FOURCC_RGB32: + src_format = PIXMAN_a8r8g8b8; + break; + default: + return FALSE; + } + + switch (image_info->id) + { + case FOURCC_I420: + dst_format = PIXMAN_x8b8g8r8; + break; + default: + dst_format = PIXMAN_x8r8g8b8; + break; + } + + /* support only RGB */ + fbdev_pixman_convert_image (PIXMAN_OP_SRC, + buf, pPixmap->devPrivate.ptr, + src_format, dst_format, + img, &pxm, src, dst, + NULL, rotate, + pPortPriv->hflip, pPortPriv->vflip); + + DamageDamageRegion (pDraw, clip_boxes); + + return Success; +} + +static Bool +_fbdevVideoSetHWPortsProperty (ScreenPtr pScreen, int nums) +{ + WindowPtr pWin = pScreen->root; + Atom atom_hw_ports; + + if (!pWin || !serverClient) + return FALSE; + + atom_hw_ports = MakeAtom ("X_HW_PORTS", strlen ("X_HW_PORTS"), TRUE); + + dixChangeWindowProperty (serverClient, + pWin, atom_hw_ports, XA_CARDINAL, 32, + PropModeReplace, 1, (unsigned int*)&nums, FALSE); + + return TRUE; +} + +static void +_fbdevVideoDPMSHandler(CallbackListPtr *list, pointer closure, pointer calldata) +{ + FBDevDPMSPtr pDPMSInfo = (FBDevDPMSPtr) calldata; + + if(!pDPMSInfo || !pDPMSInfo->pScrn) + { + xf86DrvMsg (0, X_ERROR, "[%s] DPMS info or screen info is invalid !\n", __FUNCTION__); + return; + } + + switch(DPMSPowerLevel) + { + case DPMSModeOn: + break; + + case DPMSModeSuspend: + break; + + case DPMSModeStandby://LCD on + { + ScrnInfoPtr pScrnInfo = pDPMSInfo->pScrn; + FBDevPtr pFBDev = FBDEVPTR (pScrnInfo); + XF86VideoAdaptorPtr pAdaptor = pFBDev->pAdaptor[0]; + int i; + + DRVLOG ("%s : DPMSModeStandby \n", __FUNCTION__); + + for (i = 0; i < FBDEV_MAX_PORT; i++) + { + FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; + if (!pPortPriv->v4l2_handle || !pPortPriv->need_streamon) + continue; + + if (!fbdevVideoV4l2StreamOn (pPortPriv->v4l2_handle)) + { + /* will re-open if failed */ + _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv); + pPortPriv->v4l2_handle = NULL; + } + pPortPriv->need_streamon = FALSE; + } + break; + } + case DPMSModeOff://LCD off + { + ScrnInfoPtr pScrnInfo = pDPMSInfo->pScrn; + FBDevPtr pFBDev = FBDEVPTR (pScrnInfo); + XF86VideoAdaptorPtr pAdaptor = pFBDev->pAdaptor[0]; + int i; + + DRVLOG ("%s : DPMSModeOff \n", __FUNCTION__); + + for (i = 0; i < FBDEV_MAX_PORT; i++) + { + FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; + if (!pPortPriv->v4l2_handle || pPortPriv->need_streamon) + continue; + + fbdevVideoV4l2StreamOff (pPortPriv->v4l2_handle); + pPortPriv->need_streamon = TRUE; + } + + break; + } + default: + return; + } +} + +static void +_fbdevVideoBlockHandler (pointer data, OSTimePtr pTimeout, pointer pRead) +{ + ScrnInfoPtr pScrnInfo = (ScrnInfoPtr)data; + FBDevPtr pFBDev = FBDEVPTR (pScrnInfo); + ScreenPtr pScreen = pScrnInfo->pScreen; + + if(registered_handler && _fbdevVideoSetHWPortsProperty (pScreen, pFBDev->v4l2_num)) + { + RemoveBlockAndWakeupHandlers(_fbdevVideoBlockHandler, (WakeupHandlerProcPtr)NoopDDA, data); + registered_handler = FALSE; + } +} + +static int +FBDevVideoGetPortAttribute (ScrnInfoPtr pScrnInfo, + Atom attribute, + INT32 *value, + pointer data) +{ + DRVLOG ("[GetPortAttribute] \n"); + + FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) data; + + if (attribute == _fbdevVideoGetPortAtom (PAA_ROTATION)) + { + *value = pPortPriv->rotate; + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_HFLIP)) + { + *value = pPortPriv->hflip; + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_VFLIP)) + { + *value = pPortPriv->vflip; + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_PREEMPTION)) + { + *value = pPortPriv->preemption; + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_DRAWINGMODE)) + { + *value = (pPortPriv->mode == PORT_MODE_WAITING); + return Success; + } + return BadMatch; +} + +static int +FBDevVideoSetPortAttribute (ScrnInfoPtr pScrnInfo, + Atom attribute, + INT32 value, + pointer data) +{ + FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) data; + + if (attribute == _fbdevVideoGetPortAtom (PAA_ROTATION)) + { + pPortPriv->rotate = value; + DRVLOG ("[SetPortAttribute] rotate(%d) \n", value); + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_HFLIP)) + { + pPortPriv->hflip = value; + DRVLOG ("[SetPortAttribute] hflip(%d) \n", value); + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_VFLIP)) + { + pPortPriv->vflip = value; + DRVLOG ("[SetPortAttribute] vflip(%d) \n", value); + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_PREEMPTION)) + { + pPortPriv->preemption = value; + DRVLOG ("[SetPortAttribute] preemption(%d) \n", value); + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_STREAMOFF)) + { + DRVLOG ("[SetPortAttribute] STREAMOFF \n"); + _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv); + return Success; + } + return BadMatch; +} + +static void +FBDevVideoQueryBestSize (ScrnInfoPtr pScrnInfo, + Bool motion, + short vid_w, short vid_h, + short dst_w, short dst_h, + uint *p_w, uint *p_h, + pointer data) +{ + DRVLOG ("%s (%s:%d)\n", __FUNCTION__, __FILE__, __LINE__); + + *p_w = dst_w; + *p_h = dst_h; +} + +static void +FBDevVideoStop (ScrnInfoPtr pScrnInfo, pointer data, Bool exit) +{ + DRVLOG ("%s (%s:%d) exit(%d)\n", __FUNCTION__, __FILE__, __LINE__, exit); + + FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) data; + + if (pPortPriv->mode == PORT_MODE_V4L2) + { + _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv); + +#if ENABLE_ARM + FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate; + + if (pFBDev->bFbAlphaEnabled) + { + fbdevFbScreenAlphaDeinit (fbdevHWGetFD (pScrnInfo)); + pFBDev->bFbAlphaEnabled = FALSE; + } +#endif + } + + pPortPriv->mode = PORT_MODE_INIT; + pPortPriv->preemption = 0; + pPortPriv->rotate = -1; + pPortPriv->need_streamon = FALSE; + + if (exit) + REGION_EMPTY (pScrnInfo, &pPortPriv->clip); +} + +static int +FBDevVideoReputImage (ScrnInfoPtr pScrn, short src_x, short src_y, + short drw_x, short drw_y, short src_w, + short src_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data, + DrawablePtr pDraw) + +{ + return Success; +} + +int +fbdevVideoQueryImageAttributes (ScrnInfoPtr pScrnInfo, + int id, + unsigned short *w, + unsigned short *h, + int *pitches, + int *offsets) +{ + int size = 0, tmp = 0; + + *w = (*w + 1) & ~1; + if (offsets) + offsets[0] = 0; + + switch (id) + { + case FOURCC_RGB565: + size += (*w << 1); + if (pitches) + pitches[0] = size; + size *= *h; + break; + case FOURCC_RGB24: + size += (*w << 1) + *w; + if (pitches) + pitches[0] = size; + size *= *h; + break; + case FOURCC_RGB32: + size += (*w << 2); + if (pitches) + pitches[0] = size; + size *= *h; + break; + case FOURCC_I420: + case FOURCC_S420: + case FOURCC_YV12: + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if (pitches) + pitches[0] = size; + + size *= *h; + if (offsets) + offsets[1] = size; + + tmp = ((*w >> 1) + 3) & ~3; + if (pitches) + pitches[1] = pitches[2] = tmp; + + tmp *= (*h >> 1); + size += tmp; + if (offsets) + offsets[2] = size; + + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_SUYV: + case FOURCC_YUY2: + case FOURCC_ST12: + case FOURCC_SN12: + size = *w << 1; + if (pitches) + pitches[0] = size; + + size *= *h; + break; + case FOURCC_NV12: + size = *w; + if (pitches) + pitches[0] = size; + + size *= *h; + if (offsets) + offsets[1] = size; + + tmp = *w; + if (pitches) + pitches[1] = tmp; + + tmp *= (*h >> 1); + size += tmp; + break; + default: + return BadIDChoice; + } + + return size; +} + +static int +FBDevVideoPutImage (ScrnInfoPtr pScrnInfo, + short src_x, short src_y, short dst_x, short dst_y, + short src_w, short src_h, short dst_w, short dst_h, + int id, + uchar *buf, + short width, short height, + Bool sync, + RegionPtr clip_boxes, + pointer data, + DrawablePtr pDraw) +{ + ScreenPtr pScreen = pScrnInfo->pScreen; + FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) data; + XF86ImageRec *image_info; + FBDevPortMode modeBefore = pPortPriv->mode; + xRectangle img = {0, 0, width, height}; + xRectangle src = {src_x, src_y, src_w, src_h}; + xRectangle dst = {dst_x, dst_y, dst_w, dst_h}; + int scn_rotate, rotate, hw_rotate; + int v4l2_index = 0; + FBDevPtr pFBDev = FBDEVPTR (pScrnInfo); + int drawing; + + if (pFBDev->isLcdOff) + return Success; + + pPortPriv->pDraw = pDraw; + drawing = _fbdevVideodrawingOn (pPortPriv, pDraw); + + image_info = _fbdevVideoGetImageInfo (id); + if (!image_info) + { + xf86DrvMsg (0, X_ERROR, "ID(%c%c%c%c) not supported.\n", + id & 0xFF, (id & 0xFF00) >> 8, + (id & 0xFF0000) >> 16, (id & 0xFF000000) >> 24); + return BadRequest; + } + + _fbdevVideoGetRotation (pScreen, pPortPriv, pDraw, &scn_rotate, &rotate, &hw_rotate); + + DRVLOG ("[PutImage] buf(%p) ID(%c%c%c%c) mode(%s) preem(%d) handle(%p) rot(%d+%d=%d) res(%dx%d) drawing(%d)\n", + buf, id & 0xFF, (id & 0xFF00) >> 8, (id & 0xFF0000) >> 16, (id & 0xFF000000) >> 24, + pPortPriv->mode == PORT_MODE_WAITING ? "waiting" : "V4L2", + pPortPriv->preemption, + pPortPriv->v4l2_handle, + scn_rotate, rotate, hw_rotate, + pScreen->width, pScreen->height, drawing); + + DRVLOG ("[PutImage] \t img(%d,%d %dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d) \n", + img.x, img.y, img.width, img.height, + src.x, src.y, src.width, src.height, + dst.x, dst.y, dst.width, dst.height); + + _fbdevVideoInterfbdevtXRects (&src, &src, &img); + + DRVLOG ("[PutImage] \t=> img(%d,%d %dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d) \n", + img.x, img.y, img.width, img.height, + src.x, src.y, src.width, src.height, + dst.x, dst.y, dst.width, dst.height); + + if (drawing == ON_PIXMAP || drawing == ON_WINDOW) + return _fbdevVideoPutImageOnDrawable (pScrnInfo, pPortPriv, &img, &src, &dst, clip_boxes, + scn_rotate, hw_rotate, image_info, buf, pDraw); + + if (pPortPriv->need_streamon && pPortPriv->v4l2_handle) + { + _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv); + pPortPriv->need_streamon = FALSE; + pPortPriv->v4l2_handle = NULL; + } + + if (!pPortPriv->v4l2_handle) + if (!_fbdevVideoSetMode (pScrnInfo, pPortPriv, &v4l2_index)) + return BadRequest; + + if (pPortPriv->mode != PORT_MODE_V4L2) + return Success; + + return _fbdevVideoPutImageV4l2 (pScrnInfo, pPortPriv, &img, &src, &dst, clip_boxes, + scn_rotate, rotate, hw_rotate, + image_info, buf, modeBefore, v4l2_index, pDraw); +} + +/** + * Set up all our internal structures. + */ +static XF86VideoAdaptorPtr +fbdevVideoSetupImageVideo (ScreenPtr pScreen) +{ + DRVLOG ("%s (%s:%d)\n", __FUNCTION__, __FILE__, __LINE__); + + XF86VideoAdaptorPtr pAdaptor; + FBDevPortPrivPtr pPortPriv; + XF86ImagePtr pImages; + int i, count = 0; + + pAdaptor = calloc (1, sizeof (XF86VideoAdaptorRec) + + (sizeof (DevUnion) + sizeof (FBDevPortPriv)) * FBDEV_MAX_PORT); + if (pAdaptor == NULL) + return NULL; + + DummyEncoding[0].width = pScreen->width; + DummyEncoding[0].height = pScreen->height; + + pAdaptor->type = XvWindowMask | XvPixmapMask | XvInputMask | XvImageMask; + pAdaptor->flags = (VIDEO_CLIP_TO_VIEWPORT | VIDEO_OVERLAID_IMAGES); + pAdaptor->name = "FBDEV supporting Software Video Conversions"; + pAdaptor->nEncodings = sizeof (DummyEncoding) / sizeof (XF86VideoEncodingRec); + pAdaptor->pEncodings = DummyEncoding; + pAdaptor->nFormats = NUM_FORMATS; + pAdaptor->pFormats = Formats; + pAdaptor->nPorts = FBDEV_MAX_PORT; + pAdaptor->pPortPrivates = (DevUnion*)(&pAdaptor[1]); + + pPortPriv = + (FBDevPortPrivPtr) (&pAdaptor->pPortPrivates[FBDEV_MAX_PORT]); + + for (i=0; ipPortPrivates[i].ptr = &pPortPriv[i]; + + pPortPriv[i].index = i; + pPortPriv[i].rotate = -1; + pPortPriv[i].v4l2_index = -1; + + REGION_INIT (pScreen, &pPortPriv[i].clipBoxes, NullBox, 0); + } + + pImages = fbdevVideoV4l2SupportImages (&count); + + pAdaptor->nAttributes = NUM_ATTRIBUTES; + pAdaptor->pAttributes = Attributes; + pAdaptor->nImages = count; + pAdaptor->pImages = pImages; + + pAdaptor->PutImage = FBDevVideoPutImage; + pAdaptor->ReputImage = FBDevVideoReputImage; + pAdaptor->StopVideo = FBDevVideoStop; + pAdaptor->GetPortAttribute = FBDevVideoGetPortAttribute; + pAdaptor->SetPortAttribute = FBDevVideoSetPortAttribute; + pAdaptor->QueryBestSize = FBDevVideoQueryBestSize; + pAdaptor->QueryImageAttributes = fbdevVideoQueryImageAttributes; + + return pAdaptor; +} + +#ifdef XV +/** + * Set up everything we need for Xv. + */ +Bool fbdevVideoInit (ScreenPtr pScreen) +{ + DRVLOG ("%s (%s:%d)\n", __FUNCTION__, __FILE__, __LINE__); + + ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum]; + FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate; + + pFBDev->pAdaptor[0] = fbdevVideoSetupImageVideo (pScreen); + if (!pFBDev->pAdaptor[0]) + return FALSE; + + pFBDev->pAdaptor[1] = fbdevVideoSetupVirtualVideo (pScreen); + if (!pFBDev->pAdaptor[1]) + { + free (pFBDev->pAdaptor[0]); + return FALSE; + } + + xf86XVScreenInit (pScreen, pFBDev->pAdaptor, ADAPTOR_NUM); + + pFBDev->v4l2_num = fbdevVideoV4l2GetHandleNums (); + pFBDev->v4l2_owner = (void**)calloc (sizeof (void*), pFBDev->v4l2_num); + + if(registered_handler == FALSE) + { + RegisterBlockAndWakeupHandlers(_fbdevVideoBlockHandler, (WakeupHandlerProcPtr)NoopDDA, pScrnInfo); + registered_handler = TRUE; + } + + if (AddCallback (&DPMSCallback, _fbdevVideoDPMSHandler, NULL) != TRUE) + { + xf86DrvMsg (pScrnInfo->scrnIndex, X_ERROR, "Failed to register _fbdevVideoDPMSHandler. \n"); + return FALSE; + } + + return TRUE; +} + +/** + * Shut down Xv, used on regeneration. + */ +void fbdevVideoFini (ScreenPtr pScreen) +{ + DRVLOG ("%s (%s:%d)\n", __FUNCTION__, __FILE__, __LINE__); + + ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum]; + FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate; + + XF86VideoAdaptorPtr pAdaptor = pFBDev->pAdaptor[0]; + int i; + + if (!pAdaptor) + return; + + DeleteCallback (&DPMSCallback, _fbdevVideoDPMSHandler, NULL); + + for (i = 0; i < FBDEV_MAX_PORT; i++) + { + FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pAdaptor->pPortPrivates[i].ptr; + + REGION_UNINIT (pScreen, &pPortPriv->clipBoxes); + + _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv); + } + + free (pFBDev->pAdaptor[0]); + pFBDev->pAdaptor[0] = NULL; + + free (pFBDev->pAdaptor[1]); + pFBDev->pAdaptor[1] = NULL; + + if (pFBDev->v4l2_owner) + { + free (pFBDev->v4l2_owner); + pFBDev->v4l2_owner = NULL; + pFBDev->v4l2_num = 0; + } +} + +#endif + +void +fbdevVideoSetOffset (ScrnInfoPtr pScrnInfo, int x, int y) +{ + FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate; + int i; + for (i = 0; i < pFBDev->v4l2_num; i++) + { + FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pFBDev->v4l2_owner[i]; + + if (pPortPriv) + { + if (!pPortPriv->v4l2_handle) + continue; + + fbdevVideoV4l2VideoOffset (pPortPriv->v4l2_handle, x , y); + } + } +} + +void +fbdevVideoGetV4l2Handles (ScrnInfoPtr pScrnInfo, void ***handles, int *cnt) +{ + FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate; + void **ret; + int i, j; + + *cnt = 0; + + for (i = 0; i < pFBDev->v4l2_num; i++) + { + FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pFBDev->v4l2_owner[i]; + if (pPortPriv && pPortPriv->v4l2_handle) + (*cnt)++; + } + + if (*cnt == 0) + { + *handles = NULL; + return; + } + + ret = (void**)calloc (*cnt, sizeof (void*)); + *handles = ret; + + j = 0; + + for (i = 0; i < pFBDev->v4l2_num; i++) + { + FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pFBDev->v4l2_owner[i]; + if (pPortPriv && pPortPriv->v4l2_handle) + { + ret[j] = pPortPriv->v4l2_handle; + j++; + } + } +} diff --git a/src/xv/fbdev_video.h b/src/xv/fbdev_video.h new file mode 100644 index 0000000..5e13562 --- /dev/null +++ b/src/xv/fbdev_video.h @@ -0,0 +1,76 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ +#ifndef FBDEV_VIDEO_H +#define FBDEV_VIDEO_H + +typedef enum +{ + PORT_MODE_INIT, + PORT_MODE_V4L2, + PORT_MODE_WAITING +} FBDevPortMode; + +/* FBDEV port information structure */ +typedef struct +{ + int index; + FBDevPortMode mode; + int drawing; + int size; + + RegionRec clip; + + int rotate; + int hflip; + int vflip; + xRectangle dst; + RegionRec clipBoxes; + int preemption; /* 1:high, 0:default, -1:low */ + DrawablePtr pDraw; + + int v4l2_index; + void *v4l2_handle; + + int need_streamon; +} FBDevPortPriv, *FBDevPortPrivPtr; + +extern Bool fbdevVideoInit (ScreenPtr pScreen); +extern void fbdevVideoFini (ScreenPtr pScreen); +int fbdevVideoQueryImageAttributes (ScrnInfoPtr pScrnInfo, + int id, + unsigned short *w, + unsigned short *h, + int *pitches, + int *offsets); + +void fbdevVideoSetOffset (ScrnInfoPtr pScrnInfo, int x, int y); +void fbdevVideoGetV4l2Handles (ScrnInfoPtr pScrnInfo, void ***handles, int *cnt); + +#endif // FBDEV_VIDEO_H diff --git a/src/xv/fbdev_video_fourcc.h b/src/xv/fbdev_video_fourcc.h new file mode 100644 index 0000000..8c5f0e2 --- /dev/null +++ b/src/xv/fbdev_video_fourcc.h @@ -0,0 +1,196 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef __FBDEV_VIDEO_FOURCC_H__ +#define __FBDEV_VIDEO_FOURCC_H__ + +#include + +#define B(c,s) ((((unsigned int)(c)) & 0xff) << (s)) +#define FOURCC(a,b,c,d) (B(d,24) | B(c,16) | B(b,8) | B(a,0)) + +/* http://www.fourcc.org/yuv.php + * http://en.wikipedia.org/wiki/YUV + */ +#define FOURCC_RGB565 FOURCC('R','G','B','P') +#define XVIMAGE_RGB565 \ + { \ + FOURCC_RGB565, \ + XvRGB, \ + LSBFirst, \ + {'R','G','B','P', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 16, \ + XvPacked, \ + 1, \ + 16, 0x0000F800, 0x000007E0, 0x0000001F, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + {'R','G','B',0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_RGB24 FOURCC('R','G','B','3') +#define XVIMAGE_RGB24 \ + { \ + FOURCC_RGB24, \ + XvRGB, \ + LSBFirst, \ + {'R','G','B',0, \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 24, \ + XvPacked, \ + 1, \ + 24, 0x00FF0000, 0x0000FF00, 0x000000FF, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + {'R','G','B',0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_RGB32 FOURCC('R','G','B','4') +#define XVIMAGE_RGB32 \ + { \ + FOURCC_RGB32, \ + XvRGB, \ + LSBFirst, \ + {'R','G','B',0, \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 32, \ + XvPacked, \ + 1, \ + 24, 0x00FF0000, 0x0000FF00, 0x000000FF, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + {'X','R','G','B', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_ST12 FOURCC('S','T','1','2') +#define XVIMAGE_ST12 \ + { \ + FOURCC_ST12, \ + XvYUV, \ + LSBFirst, \ + {'S','T','1','2', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 12, \ + XvPlanar, \ + 3, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 2, 2, \ + {'Y','U','V', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_SN12 FOURCC('S','N','1','2') +#define XVIMAGE_SN12 \ + { \ + FOURCC_SN12, \ + XvYUV, \ + LSBFirst, \ + {'S','N','1','2', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 12, \ + XvPlanar, \ + 3, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 2, 2, \ + {'Y','U','V', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_NV12 FOURCC('N','V','1','2') +#define XVIMAGE_NV12 \ + { \ + FOURCC_NV12, \ + XvYUV, \ + LSBFirst, \ + {'N','V','1','2', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 12, \ + XvPacked, \ + 1, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 2, 2, \ + {'Y','U','V', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_S420 FOURCC('S','4','2','0') +#define XVIMAGE_S420 \ + { \ + FOURCC_S420, \ + XvYUV, \ + LSBFirst, \ + {'S','4','2','0', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 12, \ + XvPlanar, \ + 3, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 2, 2, \ + {'Y','U','V', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } +#define FOURCC_SUYV FOURCC('S','U','Y','V') +#define XVIMAGE_SUYV \ + { \ + FOURCC_SUYV, \ + XvYUV, \ + LSBFirst, \ + {'S','U','Y','V', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 16, \ + XvPacked, \ + 1, \ + 0, 0, 0, 0, \ + 8, 8, 8, \ + 1, 2, 2, \ + 1, 1, 1, \ + {'Y','U','Y','V', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + + +#endif // __FBDEV_VIDEO_FOURCC_H__ diff --git a/src/xv/fbdev_video_types.h b/src/xv/fbdev_video_types.h new file mode 100644 index 0000000..3f9f48b --- /dev/null +++ b/src/xv/fbdev_video_types.h @@ -0,0 +1,107 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef __FBDEV_V4L2_TYPES_H__ +#define __FBDEV_V4L2_TYPES_H__ + +#include +#include + +#include + +enum +{ + OUTPUT_PATH_DMA, /* FrameBuffer */ + OUTPUT_PATH_FIMD, /* LCD */ +}; + +/************************************************************ + * TYPE DEFINITION + ************************************************************/ +typedef enum v4l2_buf_type FBDevV4l2BufType; +typedef enum v4l2_memory FBDevV4l2Memory; + +#ifndef uint +typedef unsigned int uint; +#endif + +#ifndef uchar +typedef unsigned char uchar; +#endif + +#ifndef ushort +typedef unsigned short ushort; +#endif + +/************************************************************ + * STRUCTURE + ************************************************************/ +typedef struct _FBDevV4l2Data +{ + __u32 path; + __u32 in_format; + __u32 out_format; + __u32 field; + char in_file_name[50]; + + struct v4l2_rect src; + struct v4l2_rect crop; + struct v4l2_rect dst; + struct v4l2_rect win; + + __u32 s_size[3]; + __u32 src_size; + __u32 d_size[3]; + __u32 dst_size; + + int rotation; +} FBDevV4l2Data; + +typedef struct _FBDevV4l2FimcBuffer +{ + uint base[3]; + size_t length[3]; +} FBDevV4l2FimcBuffer; + +typedef struct _FBDevV4l2SrcBuffer +{ + int index; + int size; + uchar *buf; +} FBDevV4l2SrcBuffer; + +typedef struct _FBDevV4l2DstBuffer +{ + int index; + int size; + uchar *buf; +} FBDevV4l2DstBuffer; + +#endif diff --git a/src/xv/fbdev_video_v4l2.h b/src/xv/fbdev_video_v4l2.h new file mode 100644 index 0000000..04c9b58 --- /dev/null +++ b/src/xv/fbdev_video_v4l2.h @@ -0,0 +1,73 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef __FBDEV_VIDEO_V4L2_H__ +#define __FBDEV_VIDEO_V4L2_H__ + +#include +#include + +#include "fbdev_v4l2.h" + +XF86ImagePtr fbdevVideoV4l2SupportImages (int *count); + +Bool fbdevVideoV4l2GetFormatInfo (int id, int *type, uint *pixelformat, FBDevV4l2Memory *memory); +Bool fbdevVideoV4l2CheckSize (void *handle, uint pixelformat, + xRectangle *img, xRectangle *src, xRectangle *dst, + int type, int memory); + +int fbdevVideoV4l2GetHandleNums (void); +Bool fbdevVideoV4l2HandleOpened (int index); + +void* fbdevVideoV4l2OpenHandle (ScreenPtr pScreen, int index, int requestbuffer); +void fbdevVideoV4l2CloseHandle (void *handle); + +Bool fbdevVideoV4l2StreamOn (void *handle); +void fbdevVideoV4l2StreamOff (void *handle); + +void fbdevVideoV4l2VideoOffset (void *handle, int x, int y); + +int fbdevVideoV4l2SetFormat (void *handle, + xRectangle *img, /* src->x, src->y : not used. */ + xRectangle *crop, + xRectangle *dest, + uint id, + int scn_rotate, + int hw_rotate, + int hflip, + int vflip, + int requestbuffer, + Bool sync); + +int fbdevVideoV4l2Draw (void *handle, uchar *buf, uint *phy_addrs); + +void fbdevVideoGetFBInfo (void *handle, void **base, xRectangle *pos); + +#endif diff --git a/src/xv/fbdev_video_virtual.c b/src/xv/fbdev_video_virtual.c new file mode 100644 index 0000000..f399250 --- /dev/null +++ b/src/xv/fbdev_video_virtual.c @@ -0,0 +1,683 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "fbdev.h" +#include "fbdev_util.h" +#include "fbdev_video.h" +#include "fbdev_video_fourcc.h" +#include "fbdev_video_virtual.h" +#include "fbdev_video_v4l2.h" +#include "fbdev_pixman.h" + +#include "xv_types.h" + +#define BUF_NUM 3 + +enum +{ + COMP_SRC, + COMP_OVER, + COMP_MAX, +}; + +enum +{ + DATA_TYPE_UI, + DATA_TYPE_VIDEO, + DATA_TYPE_MAX, +}; + +static unsigned int support_formats[] = +{ + FOURCC_RGB32, +}; + +static XF86VideoEncodingRec dummy_encoding[] = +{ + { 0, "XV_IMAGE", -1, -1, { 1, 1 } }, + { 1, "XV_IMAGE", 2560, 2560, { 1, 1 } }, +}; + +static XF86ImageRec images[] = +{ + XVIMAGE_RGB32, + XVIMAGE_SN12, + XVIMAGE_ST12, +}; + +static XF86VideoFormatRec formats[] = +{ + { 16, TrueColor }, + { 24, TrueColor }, + { 32, TrueColor }, +}; + +static XF86AttributeRec attributes[] = +{ + { 0, 0, 0x7fffffff, "_USER_WM_PORT_ATTRIBUTE_FORMAT" }, + { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_CAPTURE" }, + { 0, 0, DATA_TYPE_MAX, "_USER_WM_PORT_ATTRIBUTE_DATA_TYPE" }, + { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF" }, +}; + +typedef enum +{ + PAA_MIN, + PAA_FORMAT, + PAA_CAPTURE, + PAA_DATA_TYPE, + PAA_STREAMOFF, + PAA_MAX +} FBDEVPortAttrAtom; + +static struct +{ + FBDEVPortAttrAtom paa; + const char *name; + Atom atom; +} atoms[] = +{ + { PAA_FORMAT, "_USER_WM_PORT_ATTRIBUTE_FORMAT", None }, + { PAA_CAPTURE, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", None }, + { PAA_DATA_TYPE, "_USER_WM_PORT_ATTRIBUTE_DATA_TYPE", None }, + { PAA_STREAMOFF, "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", None }, +}; + +/* FBDEV port information structure */ +typedef struct +{ + /* index */ + int index; + + /* port attribute */ + int id; + Bool capture; + + /* information from outside */ + ScrnInfoPtr pScrn; + DrawablePtr pDraw; + RegionPtr clipBoxes; + + void *black; + int black_w; + int black_h; + + struct xorg_list link; +} FBDEVPortPriv, *FBDEVPortPrivPtr; + +static RESTYPE event_drawable_type; + +typedef struct _FBDEVVideoResource +{ + XID id; + RESTYPE type; + FBDEVPortPrivPtr pPort; + ScrnInfoPtr pScrn; +} FBDEVVideoResource; + +#define FBDEV_MAX_PORT 1 + +#define NUM_IMAGES (sizeof(images) / sizeof(images[0])) +#define NUM_FORMATS (sizeof(formats) / sizeof(formats[0])) +#define NUM_ATTRIBUTES (sizeof(attributes) / sizeof(attributes[0])) +#define NUM_ATOMS (sizeof(atoms) / sizeof(atoms[0])) + +static void FBDEVVirtualVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit); + +static PixmapPtr +_fbdevVirtualVideoGetPixmap (DrawablePtr pDraw) +{ + if (pDraw->type == DRAWABLE_WINDOW) + return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw); + else + return (PixmapPtr) pDraw; +} + +static Bool +_fbdevVirtualVideoIsSupport (unsigned int id) +{ + int i; + + for (i = 0; i < sizeof (support_formats) / sizeof (unsigned int); i++) + if (support_formats[i] == id) + return TRUE; + + return FALSE; +} + +static Atom +_fbdevVideoGetPortAtom (FBDEVPortAttrAtom paa) +{ + int i; + + return_val_if_fail (paa > PAA_MIN && paa < PAA_MAX, None); + + for (i = 0; i < NUM_ATOMS; i++) + { + if (paa == atoms[i].paa) + { + if (atoms[i].atom == None) + atoms[i].atom = MakeAtom (atoms[i].name, + strlen (atoms[i].name), TRUE); + + return atoms[i].atom; + } + } + + ErrorF ("Error: Unknown Port Attribute Name!\n"); + + return None; +} + +static void +_fbdevVirtualVideoStreamOff (FBDEVPortPrivPtr pPort) +{ + DRVLOG ("STREAM_OFF!\n"); + + if (pPort->clipBoxes) + { + RegionDestroy (pPort->clipBoxes); + pPort->clipBoxes = NULL; + } + + if (pPort->black) + { + free (pPort->black); + pPort->black = NULL; + } + + pPort->black_w = 0; + pPort->black_h = 0; + + pPort->pScrn = NULL; + pPort->pDraw = NULL; + pPort->capture = FALSE; + pPort->id = FOURCC_RGB32; +} + +static int +_fbdevVirtualVideoPreProcess (ScrnInfoPtr pScrn, FBDEVPortPrivPtr pPort, + RegionPtr clipBoxes, DrawablePtr pDraw) +{ + if (pPort->pScrn == pScrn && pPort->pDraw == pDraw && + pPort->clipBoxes && clipBoxes && RegionEqual (pPort->clipBoxes, clipBoxes)) + return Success; + + pPort->pScrn = pScrn; + pPort->pDraw = pDraw; + + if (clipBoxes) + { + if (pPort->clipBoxes) + { + RegionDestroy (pPort->clipBoxes); + pPort->clipBoxes = NULL; + } + + if (!pPort->clipBoxes) + pPort->clipBoxes = RegionCreate (NULL, 1); + + return_val_if_fail (pPort->clipBoxes != NULL, BadAlloc); + + RegionCopy (pPort->clipBoxes, clipBoxes); + } + + DRVLOG ("[%s] pDraw(0x%x, %dx%d). \n", __FUNCTION__, pDraw->id, pDraw->width, pDraw->height); + + return Success; +} + +static int +_fbdevVirtualVideoAddDrawableEvent (FBDEVPortPrivPtr pPort) +{ + FBDEVVideoResource *resource; + void *ptr; + int ret; + + return_val_if_fail (pPort->pScrn != NULL, BadImplementation); + return_val_if_fail (pPort->pDraw != NULL, BadImplementation); + + ptr = NULL; + ret = dixLookupResourceByType (&ptr, pPort->pDraw->id, + event_drawable_type, NULL, DixWriteAccess); + if (ret == Success && ptr) + return Success; + + resource = malloc (sizeof (FBDEVVideoResource)); + if (resource == NULL) + return BadAlloc; + + if (!AddResource (pPort->pDraw->id, event_drawable_type, resource)) + { + free (resource); + return BadAlloc; + } + + DRVLOG ("[%s] id(%ld). \n", __FUNCTION__, pPort->pDraw->id); + + resource->id = pPort->pDraw->id; + resource->type = event_drawable_type; + resource->pPort = pPort; + resource->pScrn = pPort->pScrn; + + return Success; +} + +static int +_fbdevVirtualVideoRegisterEventDrawableGone (void *data, XID id) +{ + FBDEVVideoResource *resource = (FBDEVVideoResource*)data; + + DRVLOG ("[%s] id(%ld). \n", __FUNCTION__, id); + + if (!resource) + return Success; + + if (!resource->pPort || !resource->pScrn) + return Success; + + resource->pPort->pDraw = NULL; + + FBDEVVirtualVideoStop (resource->pScrn, (pointer)resource->pPort, 1); + + free(resource); + + return Success; +} + +static void +_fbdevVideoEnsureBlackBuffer (FBDEVPortPrivPtr pPort, int width, int height) +{ + int i, size, *byte; + + if (pPort->black_w != width || pPort->black_w != height) + { + if (pPort->black) + { + free (pPort->black); + pPort->black = NULL; + } + } + + if (pPort->black) + return; + + size = width * height; + + pPort->black = (void*)malloc (size * 4); + pPort->black_w = width; + pPort->black_h = height; + + byte = (int*)pPort->black; + for (i = 0; i < size; i++) + byte[i] = 0xff000000; +} + +static Bool +_fbdevVirtualVideoRegisterEventResourceTypes (void) +{ + event_drawable_type = CreateNewResourceType (_fbdevVirtualVideoRegisterEventDrawableGone, + "Fbdev Virtual Video Drawable"); + + if (!event_drawable_type) + return FALSE; + + return TRUE; +} + +static int +_fbdevVirtualVideoCompositeLayers (FBDEVPortPrivPtr pPort) +{ + ScreenPtr pScreen = pPort->pScrn->pScreen; + PixmapPtr screen_pixmap; + PixmapPtr pPixmap; + void **handles = NULL; + int handle_cnt = 0; + void *srcbuf = NULL, *dstbuf = NULL; + xRectangle src = {0,}, dst = {0,}, pxm = {0,}; + pixman_format_code_t format; + pixman_op_t op; + Bool over = FALSE; + PropertyPtr rotate_prop; + int rotate = 0; + + screen_pixmap = (*pScreen->GetScreenPixmap) (pScreen); + return_val_if_fail (screen_pixmap != NULL, BadRequest); + return_val_if_fail (screen_pixmap->devPrivate.ptr != NULL, BadRequest); + + pPixmap = _fbdevVirtualVideoGetPixmap (pPort->pDraw); + return_val_if_fail (pPixmap != NULL, BadRequest); + return_val_if_fail (pPixmap->devPrivate.ptr != NULL, BadRequest); + + dstbuf = calloc (1, screen_pixmap->drawable.width * screen_pixmap->drawable.height * 4); + pxm.width = screen_pixmap->drawable.width; + pxm.height = screen_pixmap->drawable.height; + + format = PIXMAN_a8r8g8b8; + + fbdevVideoGetV4l2Handles (pPort->pScrn, &handles, &handle_cnt); + if (handles) + { + int i; + for (i = 0; i < handle_cnt; i++) + { + srcbuf = NULL; + CLEAR (src); + CLEAR (dst); + + fbdevVideoGetFBInfo (handles[i], &srcbuf, &dst); + if (!srcbuf || dst.width == 0 || dst.height == 0) + continue; + src = dst; + src.x = src.y = 0; + + if (!over) + { + op = PIXMAN_OP_SRC; + over = TRUE; + } + else + op = PIXMAN_OP_OVER; + + fbdev_pixman_convert_image (op, + srcbuf, dstbuf, + format, format, + &src, &pxm, &src, &dst, + NULL, 0, 0, 0); + } + + free (handles); + } + + srcbuf = screen_pixmap->devPrivate.ptr; + src = dst = pxm; + + if (!over) + { + op = PIXMAN_OP_SRC; + over = TRUE; + } + else + op = PIXMAN_OP_OVER; + + fbdev_pixman_convert_image (op, + srcbuf, dstbuf, + format, format, + &src, &pxm, &src, &dst, + NULL, 0, 0, 0); + + + rotate_prop = fbdev_util_get_window_property (pScreen->root, + "_E_ILLUME_ROTATE_ROOT_ANGLE"); + if (rotate_prop) + rotate = *(int*)rotate_prop->data; + + if (rotate != 0 || + pxm.width != pPort->pDraw->width || + pxm.height != pPort->pDraw->height) + { + xRectangle rect; + int width, height; + + width = pxm.width; + height = pxm.height; + + if (rotate % 180) + SWAP (width, height); + + fbdev_util_align_rect (width, height, + pPort->pDraw->width, pPort->pDraw->height, + &rect, FALSE); + + src = pxm; + pxm.width = pPort->pDraw->width; + pxm.height = pPort->pDraw->height; + dst = rect; + + fbdev_pixman_convert_image (PIXMAN_OP_SRC, + dstbuf, pPixmap->devPrivate.ptr, + format, format, + &src, &pxm, &src, &dst, + NULL, rotate, 0, 0); + } + else + memcpy (pPixmap->devPrivate.ptr, dstbuf, + pPort->pDraw->width * pPort->pDraw->height * 4); + + free (dstbuf); + + DamageDamageRegion (pPort->pDraw, pPort->clipBoxes); + + return Success; +} + +static int +FBDEVVirtualVideoGetPortAttribute (ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value, + pointer data) +{ + FBDEVPortPrivPtr pPort = (FBDEVPortPrivPtr) data; + + if (attribute == _fbdevVideoGetPortAtom (PAA_FORMAT)) + { + *value = pPort->id; + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_CAPTURE)) + { + *value = pPort->capture; + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_DATA_TYPE)) + { + *value = DATA_TYPE_UI; + return Success; + } + + return BadMatch; +} + +static int +FBDEVVirtualVideoSetPortAttribute (ScrnInfoPtr pScrn, + Atom attribute, + INT32 value, + pointer data) +{ + FBDEVPortPrivPtr pPort = (FBDEVPortPrivPtr) data; + + if (attribute == _fbdevVideoGetPortAtom (PAA_FORMAT)) + { + if (!_fbdevVirtualVideoIsSupport ((unsigned int)value)) + { + DRVLOG ("[%s] id(%c%c%c%c) not supported.\n", __FUNCTION__, + value & 0xFF, (value & 0xFF00) >> 8, + (value & 0xFF0000) >> 16, (value & 0xFF000000) >> 24); + return BadRequest; + } + + pPort->id = (unsigned int)value; + DRVLOG ("[%s] id(%d) \n", __FUNCTION__, value); + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_CAPTURE)) + { + pPort->capture = (value > 0) ? TRUE : FALSE; + DRVLOG ("[%s] capture(%d) \n", __FUNCTION__, pPort->capture); + return Success; + } + else if (attribute == _fbdevVideoGetPortAtom (PAA_STREAMOFF)) + { + DRVLOG ("[%s] STREAM_OFF! \n", __FUNCTION__); + _fbdevVirtualVideoStreamOff (pPort); + return Success; + } + + return BadMatch; +} + +/* vid_w, vid_h : no meaning for us. not using. + * dst_w, dst_h : size to hope for GetStill. + * p_w, p_h : real size for GetStill. + */ +static void +FBDEVVirtualVideoQueryBestSize (ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short dst_w, short dst_h, + unsigned int *p_w, unsigned int *p_h, + pointer data) +{ + if (p_w) + *p_w = (unsigned int)dst_w; + if (p_h) + *p_h = (unsigned int)dst_h; +} + +/* vid_x, vid_y, vid_w, vid_h : no meaning for us. not using. + * drw_x, drw_y, dst_w, dst_h : no meaning for us. not using. + * Only pDraw's size is used. + */ +static int +FBDEVVirtualVideoGetStill (ScrnInfoPtr pScrn, + short vid_x, short vid_y, short drw_x, short drw_y, + short vid_w, short vid_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data, DrawablePtr pDraw ) +{ + FBDEVPortPrivPtr pPort = (FBDEVPortPrivPtr) data; + int ret = BadRequest; + PixmapPtr pPixmap; + + _fbdevVideoEnsureBlackBuffer (pPort, pDraw->width, pDraw->height); + + goto_if_fail (pPort->id > 0, get_still_fail); + + ret = _fbdevVirtualVideoPreProcess (pScrn, pPort, clipBoxes, pDraw); + goto_if_fail (ret == Success, get_still_fail); + + ret = _fbdevVirtualVideoAddDrawableEvent (pPort); + goto_if_fail (ret == Success, get_still_fail); + + if (!pPort->capture) + { + DRVLOG ("[%s] emulfb supports only capture mode. \n", __FUNCTION__); + goto get_still_fail; + } + + /* check drawable */ + return_val_if_fail (pDraw->type == DRAWABLE_PIXMAP, BadPixmap); + + ret = _fbdevVirtualVideoCompositeLayers (pPort); + goto_if_fail (ret == Success, get_still_fail); + + return Success; + +get_still_fail: + pPixmap = _fbdevVirtualVideoGetPixmap (pDraw); + + if (pPixmap->devPrivate.ptr && pPort->black) + memcpy (pPixmap->devPrivate.ptr, pPort->black, + pPort->pDraw->width * pPort->pDraw->height * 4); + + DamageDamageRegion (pPort->pDraw, clipBoxes); + + return ret; +} + +static void +FBDEVVirtualVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit) +{ + FBDEVPortPrivPtr pPort = (FBDEVPortPrivPtr) data; + + _fbdevVirtualVideoStreamOff (pPort); +} + +XF86VideoAdaptorPtr +fbdevVideoSetupVirtualVideo (ScreenPtr pScreen) +{ + XF86VideoAdaptorPtr pAdaptor; + FBDEVPortPrivPtr pPort; + int i; + + pAdaptor = calloc (1, sizeof (XF86VideoAdaptorRec) + + (sizeof (DevUnion) + sizeof (FBDEVPortPriv)) * FBDEV_MAX_PORT); + if (!pAdaptor) + return NULL; + + dummy_encoding[0].width = pScreen->width; + dummy_encoding[0].height = pScreen->height; + + pAdaptor->type = XvWindowMask | XvPixmapMask | XvOutputMask | XvStillMask; + pAdaptor->flags = 0; + pAdaptor->name = "FBDEV Virtual Video"; + pAdaptor->nEncodings = sizeof (dummy_encoding) / sizeof (XF86VideoEncodingRec); + pAdaptor->pEncodings = dummy_encoding; + pAdaptor->nFormats = NUM_FORMATS; + pAdaptor->pFormats = formats; + pAdaptor->nPorts = FBDEV_MAX_PORT; + pAdaptor->pPortPrivates = (DevUnion*)(&pAdaptor[1]); + + pPort = (FBDEVPortPrivPtr) (&pAdaptor->pPortPrivates[FBDEV_MAX_PORT]); + + for (i = 0; i < FBDEV_MAX_PORT; i++) + { + pAdaptor->pPortPrivates[i].ptr = &pPort[i]; + pPort[i].index = i; + pPort[i].id = FOURCC_RGB32; + } + + pAdaptor->nAttributes = NUM_ATTRIBUTES; + pAdaptor->pAttributes = attributes; + pAdaptor->nImages = NUM_IMAGES; + pAdaptor->pImages = images; + + pAdaptor->GetPortAttribute = FBDEVVirtualVideoGetPortAttribute; + pAdaptor->SetPortAttribute = FBDEVVirtualVideoSetPortAttribute; + pAdaptor->QueryBestSize = FBDEVVirtualVideoQueryBestSize; + pAdaptor->GetStill = FBDEVVirtualVideoGetStill; + pAdaptor->StopVideo = FBDEVVirtualVideoStop; + + if (!_fbdevVirtualVideoRegisterEventResourceTypes ()) + { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "Failed to register EventResourceTypes. \n"); + return NULL; + } + + return pAdaptor; +} diff --git a/src/xv/fbdev_video_virtual.h b/src/xv/fbdev_video_virtual.h new file mode 100644 index 0000000..fbf363d --- /dev/null +++ b/src/xv/fbdev_video_virtual.h @@ -0,0 +1,37 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef __FBDEV_VIDEO_VIRTUAL_H__ +#define __FBDEV_VIDEO_VIRTUAL_H__ + +/* setup virtual adaptor */ +XF86VideoAdaptorPtr fbdevVideoSetupVirtualVideo (ScreenPtr pScreen); + +#endif // __FBDEV_VIDEO_VIRTUAL_H__ diff --git a/src/xv/i386/fbdev_video_v4l2.c b/src/xv/i386/fbdev_video_v4l2.c new file mode 100644 index 0000000..3fa2a95 --- /dev/null +++ b/src/xv/i386/fbdev_video_v4l2.c @@ -0,0 +1,834 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fbdev_util.h" +#include "fbdev_video_v4l2.h" + +#include "fbdev.h" +#include "fbdev_fb.h" +#include "fbdev_util.h" +#include "fbdev_video.h" +#include "fbdev_video_fourcc.h" +#include "fbdev_pixman.h" + +#define BUF_NUM 1 + +typedef struct _DeviceInfo +{ + char *video; /* video */ + int bOpened; +} DeviceInfo; + +typedef struct _FormatInfo +{ + int id; + int type; + uint pixelformat; + FBDevV4l2Memory memory; +} FormatInfo; + +typedef struct +{ + int index; + + ScreenPtr pScreen; + + int video_fd; + + struct + { + int init; + xRectangle img; + xRectangle crop; + xRectangle dst; + int id; + int hw_rotate; + int scn_rotate; + int hflip; + int vflip; + int streamon; + int cur_idx; + + void* last_buffer; + int queued_index; + + void* backup; + Bool sync; + } status; + + int size; + unsigned int pixfmt; + FBDevV4l2FimcBuffer fimcbuf; + FBDevV4l2SrcBuffer *src_buf; + FBDevV4l2DstBuffer *dst_buf; + FBDevV4l2Memory memory; + + int offset_x; + int offset_y; + + int re_setting; +} FBDevDispHandle; + +enum +{ + TYPE_RGB, + TYPE_YUV444, + TYPE_YUV422, + TYPE_YUV420, +}; + +static FormatInfo format_infos [] = +{ + { FOURCC_RGB565, TYPE_RGB, V4L2_PIX_FMT_RGB565, V4L2_MEMORY_MMAP }, + { FOURCC_RGB32, TYPE_RGB, V4L2_PIX_FMT_RGB32, V4L2_MEMORY_MMAP }, + { FOURCC_I420, TYPE_YUV420, V4L2_PIX_FMT_YUV420, V4L2_MEMORY_MMAP }, + { FOURCC_YUY2, TYPE_YUV422, V4L2_PIX_FMT_YUYV, V4L2_MEMORY_MMAP }, + { FOURCC_YV12, TYPE_YUV420, V4L2_PIX_FMT_YVU420, V4L2_MEMORY_MMAP }, + +}; + +static XF86ImageRec Images[] = +{ + XVIMAGE_I420, + XVIMAGE_YV12, + XVIMAGE_YUY2, + XVIMAGE_RGB32, + XVIMAGE_RGB565, +}; + +static DeviceInfo device_infos[] = +{ + { "/dev/video1", FALSE }, + { "/dev/video2", FALSE }, +}; + +#define NUM_IMAGES (sizeof(Images) / sizeof(XF86ImageRec)) +#define DEVICE_NUMS (sizeof (device_infos) / sizeof (DeviceInfo)) + +static Bool +_fbdevVideoV4l2SetDst (int fd, int offset_x, int offset_y, xRectangle *rect) +{ + struct v4l2_format format = {0,}; + int caps; + + return_val_if_fail (fd >= 0, FALSE); + + DRVLOG ("[SetDst] offset(%d,%d) win(%d,%d %dx%d) \n", offset_x, offset_y, + rect->x, rect->y, rect->width, rect->height); + + caps = V4L2_CAP_VIDEO_OVERLAY; + if (!fbdev_v4l2_querycap (fd, caps)) + return FALSE; + + /* set format */ + CLEAR (format); + format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + if (!fbdev_v4l2_g_fmt (fd, &format)) + return FALSE; + + format.fmt.win.w.left = rect->x + offset_x; + format.fmt.win.w.top = rect->y + offset_y; + format.fmt.win.w.width = rect->width; + format.fmt.win.w.height = rect->height; + if (!fbdev_v4l2_s_fmt (fd, &format)) + return FALSE; + + return TRUE; +} + +static Bool +_fbdevVideoV4l2SetBuffer (int fd, + FBDevV4l2BufType type, + FBDevV4l2Memory memory, + int num_buf, + FBDevV4l2DstBuffer **mem_buf) +{ + struct v4l2_requestbuffers req = {0,}; + + return_val_if_fail (fd >= 0, FALSE); + + DRVLOG ("[SetBuffer] num_buf(%d) mem_buf(%p) memory(%d)\n", + num_buf, mem_buf, memory); + + CLEAR (req); + req.count = num_buf; + req.type = type; + req.memory = memory; + if (!fbdev_v4l2_reqbuf (fd, &req)) + return FALSE; + + if (memory == V4L2_MEMORY_MMAP) + { + FBDevV4l2DstBuffer *out_buf; + int i; + + return_val_if_fail (mem_buf != NULL, FALSE); + + out_buf = calloc (req.count, sizeof (FBDevV4l2DstBuffer)); + return_val_if_fail (out_buf != NULL, FALSE); + + for (i = 0; i < num_buf; i++) + { + struct v4l2_buffer buffer = {0,}; + + CLEAR (buffer); + buffer.index = i; + buffer.type = type; + buffer.memory = V4L2_MEMORY_MMAP; + if (!fbdev_v4l2_querybuf (fd, &buffer)) + { + free (out_buf); + return FALSE; + } + + out_buf[i].index = buffer.index; + out_buf[i].size = buffer.length; + out_buf[i].buf = mmap (NULL, buffer.length, + PROT_READ | PROT_WRITE , \ + MAP_SHARED , fd, buffer.m.offset & ~(PAGE_SIZE - 1)); + out_buf[i].buf += buffer.m.offset & (PAGE_SIZE - 1); + + if (out_buf[i].buf == MAP_FAILED) + { + xf86DrvMsg (0, X_ERROR, "[SetBuffer] mmap failed. index(%d)\n", i); + free (out_buf); + return FALSE; + } + } + + *mem_buf = out_buf; + } + + return TRUE; +} + +static Bool +_fbdevVideoV4l2ClearBuffer (int fd, + FBDevV4l2BufType type, + FBDevV4l2Memory memory, + int num_buf, + FBDevV4l2DstBuffer *mem_buf) +{ + struct v4l2_requestbuffers req = {0,}; + + return_val_if_fail (fd >= 0, FALSE); + + DRVLOG ("[ClearBuffer] memory(%d) num_buf(%d) mem_buf(%p)\n", + num_buf, mem_buf, memory); + + if (memory == V4L2_MEMORY_MMAP && mem_buf) + { + int i; + + for (i = 0; i < num_buf; i++) + if (mem_buf[i].buf) + if (munmap (mem_buf[i].buf, mem_buf[i].size) == -1) + xf86DrvMsg (0, X_WARNING, "[ClearBuffer] Failed to unmap v4l2 buffer at index %d\n", i); + + free (mem_buf); + } + + CLEAR (req); + req.count = 0; + req.type = type; + req.memory = memory; + if (!fbdev_v4l2_reqbuf (fd, &req)) + return FALSE; + + return TRUE; +} + +static Bool +_fbdevVideoV4l2StreamOn (int fd) +{ + return_val_if_fail (fd >= 0, FALSE); + + DRVLOG ("[StreamOn] \n"); + + if (!fbdev_v4l2_start_overlay (fd)) + return FALSE; + + return TRUE; +} + + +static Bool +_fbdevVideoV4l2StreamOff (int fd) +{ + return_val_if_fail (fd >= 0, FALSE); + + DRVLOG ("[StreamOff] \n"); + + if (!fbdev_v4l2_stop_overlay (fd)) + return FALSE; + + return TRUE; +} + +static int +_open_device (char *device) +{ + int fd; + + return_val_if_fail (device != NULL, -1); + + fd = open (device, O_RDWR); + if (fd < 0) + { + xf86DrvMsg (0, X_ERROR, "Cannot open '%s'. fd(%d)\n", device, fd); + return -1; + } + + DRVLOG ("'%s' opened. fd(%d) \n", device, fd); + + return fd; +} + +static void +_close_device (int fd) +{ + int ret; + + return_if_fail (fd >= 0); + + ret = close (fd); + if (ret < 0) + { + xf86DrvMsg (0, X_ERROR, "Cannot close fd(%d)\n", fd); + return; + } + + DRVLOG ("fd(%d) closed. \n", fd); +} + +static Bool +_fbdevVideoV4l2EnsureStreamOff (FBDevDispHandle *hdisp) +{ + if (!hdisp->status.streamon) + return TRUE; + + if (!_fbdevVideoV4l2StreamOff (hdisp->video_fd)) + return FALSE; + + hdisp->status.streamon = FALSE; + + return TRUE; +} + +static Bool +_fbdevVideoV4l2OpenDevice (FBDevDispHandle *hdisp, int index) +{ + if (device_infos[index].bOpened) + { + DRVLOG ("[OpenDevice, %p] Already opened : %s\n", hdisp, device_infos[index].video); + return FALSE; + } + + hdisp->video_fd = _open_device (device_infos[index].video); + if (hdisp->video_fd < 0) + return FALSE; + + device_infos[index].bOpened = TRUE; + + return TRUE; +} + +/* This function never failed. + * If failed, it means kernel has some problems. + * Then a device should be rebooted. + */ +static void +_fbdevVideoV4l2CloseDevice (FBDevDispHandle *hdisp) +{ + if (!_fbdevVideoV4l2EnsureStreamOff (hdisp)) // We will consider this as a LCD Off case. + xf86DrvMsg (0, X_WARNING, "[CloseDevice, %p] Warning : Cannot stream off!! \n", hdisp); + + if (hdisp->video_fd >= 0) + if (!_fbdevVideoV4l2ClearBuffer (hdisp->video_fd, + V4L2_BUF_TYPE_VIDEO_OVERLAY, + hdisp->memory, + BUF_NUM, + hdisp->dst_buf)) + xf86DrvMsg (0, X_WARNING, "[CloseDevice, %p] Warning : Cannot clear buffer!! \n", hdisp); + + hdisp->dst_buf = NULL; + + if (hdisp->video_fd >= 0) + { + _close_device (hdisp->video_fd); + hdisp->video_fd = -1; + } + + device_infos[hdisp->index].bOpened = FALSE; +} + +int +fbdevVideoV4l2GetHandleNums (void) +{ + return DEVICE_NUMS; +} + +Bool +fbdevVideoV4l2HandleOpened (int index) +{ + return_val_if_fail (index < DEVICE_NUMS, FALSE); + + return device_infos[index].bOpened; +} + +void * +fbdevVideoV4l2OpenHandle (ScreenPtr pScreen, int index, int requestbuffer) +{ + FBDevDispHandle *handle; + + return_val_if_fail (pScreen != NULL, NULL); + return_val_if_fail (index < DEVICE_NUMS, NULL); + + handle = (FBDevDispHandle*)calloc (sizeof (FBDevDispHandle), 1); + + return_val_if_fail (handle != NULL, NULL); + + handle->pScreen = pScreen; + handle->index = index; + handle->status.hw_rotate = -1; + handle->status.id = 0; + handle->status.cur_idx = -1; + handle->status.init = 0; + handle->memory = V4L2_MEMORY_MMAP; + handle->video_fd = -1; + + if (!_fbdevVideoV4l2OpenDevice (handle, index)) + { + free (handle); + return NULL; + } + + DRVLOG ("[OpenHandle, %p] Handle(%d) opened. \n", handle, index); + + return handle; +} + +void +fbdevVideoV4l2CloseHandle (void *handle) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + + return_if_fail (handle != NULL); + + _fbdevVideoV4l2CloseDevice ((FBDevDispHandle*)handle); + + if (hdisp->status.backup) + { + free (hdisp->status.backup); + hdisp->status.backup = NULL; + } + + DRVLOG ("[CloseHandle, %p] Handle(%d) closed. \n", hdisp, hdisp->index); + + free (handle); +} + +Bool +fbdevVideoV4l2StreamOn (void *handle) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + uint phy_addrs[3]; + + return_val_if_fail (hdisp != NULL, FALSE); + + hdisp->re_setting = TRUE; + + if (!_fbdevVideoV4l2OpenDevice (hdisp, hdisp->index)) + return FALSE; + + fbdevVideoV4l2SetFormat (handle, + &hdisp->status.img, + &hdisp->status.crop, + &hdisp->status.dst, + hdisp->status.id, + hdisp->status.scn_rotate, + hdisp->status.hw_rotate, + hdisp->status.hflip, + hdisp->status.vflip, + BUF_NUM, + hdisp->status.sync); + + phy_addrs[0] = hdisp->fimcbuf.base[0]; + phy_addrs[1] = hdisp->fimcbuf.base[1]; + phy_addrs[2] = hdisp->fimcbuf.base[2]; + + if (hdisp->status.backup) + { + int size; + + size = fbdevVideoQueryImageAttributes (NULL, FOURCC_RGB32, + (unsigned short*)&hdisp->status.dst.width, + (unsigned short*)&hdisp->status.dst.height, + NULL, NULL); + + memcpy (hdisp->dst_buf[0].buf, hdisp->status.backup, size); + + free (hdisp->status.backup); + hdisp->status.backup = NULL; + } + + hdisp->re_setting = FALSE; + + DRVLOG ("%s \n", __FUNCTION__); + + return TRUE; +} + +void +fbdevVideoV4l2StreamOff (void *handle) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + + return_if_fail (hdisp != NULL); + + if (hdisp->memory == V4L2_MEMORY_MMAP) + { + int size; + + if (hdisp->status.backup) + { + free (hdisp->status.backup); + hdisp->status.backup = NULL; + } + + size = fbdevVideoQueryImageAttributes (NULL, FOURCC_RGB32, + (unsigned short*)&hdisp->status.dst.width, + (unsigned short*)&hdisp->status.dst.height, + NULL, NULL); + + if (size > 0) + hdisp->status.backup = malloc (size); + + if (hdisp->status.backup && + hdisp->dst_buf && + hdisp->dst_buf[hdisp->status.queued_index].buf) + { + memcpy (hdisp->status.backup, + hdisp->dst_buf[hdisp->status.queued_index].buf, + size); + } + } + + _fbdevVideoV4l2CloseDevice (hdisp); + + DRVLOG ("%s \n", __FUNCTION__); +} + +void +fbdevVideoV4l2VideoOffset (void *handle, int x, int y) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + + return_if_fail (handle != NULL); + + DRVLOG ("[VideoOffset, %p] to %d,%d\n", hdisp, x, y); + + if (hdisp->offset_x == x && hdisp->offset_y == y) + return; + + if (!_fbdevVideoV4l2SetDst (hdisp->video_fd, x, y, &hdisp->status.dst)) + { + xf86DrvMsg (0, X_ERROR, "[VideoOffset, %p] _fbdevVideoV4l2SetDst is failed. \n", hdisp); + return; + } + + hdisp->offset_x = x; + hdisp->offset_y = y; +} + +/* img->x, img->y : not used. */ +Bool +fbdevVideoV4l2SetFormat (void *handle, + xRectangle *img, xRectangle *crop, xRectangle *dst, + uint id, + int scn_rotate, + int hw_rotate, + int hflip, + int vflip, + int requestbuffer, + Bool sync) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + Bool src_changed = FALSE; + Bool dst_changed = FALSE; + Bool buf_changed = FALSE; + + return_val_if_fail (handle != NULL, FALSE); + return_val_if_fail (img != NULL, FALSE); + return_val_if_fail (crop != NULL, FALSE); + return_val_if_fail (dst != NULL, FALSE); + + DRVLOG ("[SetFormat, %p] try to set : img(%d,%d %dx%d) crop(%d,%d %dx%d) dst(%d,%d %dx%d) id(%x), rot(%d), flip(%d,%d) req(%d)\n", hdisp, + img->x, img->y, img->width, img->height, + crop->x, crop->y, crop->width, crop->height, + dst->x, dst->y, dst->width, dst->height, + id, hw_rotate, hflip, vflip, requestbuffer); + + if (memcmp (&hdisp->status.img, img, sizeof (xRectangle)) || + memcmp (&hdisp->status.crop, crop, sizeof (xRectangle)) || + hdisp->status.id != id) + src_changed = TRUE; + + if (memcmp (&hdisp->status.dst, dst, sizeof (xRectangle)) || + hdisp->status.hw_rotate != hw_rotate || + hdisp->status.hflip != hflip || + hdisp->status.vflip != vflip) + dst_changed = TRUE; + + if (hdisp->status.init && (src_changed || dst_changed || buf_changed)) + { + _fbdevVideoV4l2CloseDevice (hdisp); + _fbdevVideoV4l2OpenDevice (hdisp, hdisp->index); + + DRVLOG ("[SetFormat, %p] changed : img(%d) dst(%d) buf(%d) \n", hdisp, + src_changed, dst_changed, buf_changed); + + /* After close device, below all steps should be done. */ + src_changed = dst_changed = buf_changed = TRUE; + hdisp->status.init = 0; + } + + if (hdisp->re_setting) + src_changed = dst_changed = buf_changed = TRUE; + + if (src_changed || dst_changed || buf_changed) + { + fbdevVideoV4l2GetFormatInfo (id, NULL, &hdisp->pixfmt, &hdisp->memory); + + DRVLOG ("[SetFormat, %p] id(%c%c%c%c) => pixfmt(%d) memory(%d) \n", hdisp, + id & 0xFF, (id & 0xFF00) >> 8, (id & 0xFF0000) >> 16, (id & 0xFF000000) >> 24, + hdisp->pixfmt, hdisp->memory); + + hdisp->status.img = *img; + hdisp->status.crop = *crop; + hdisp->status.id = id; + hdisp->status.sync = sync; + hdisp->status.init = 1; + + hdisp->status.cur_idx = 0; + hdisp->status.hw_rotate = hw_rotate; + hdisp->status.scn_rotate = scn_rotate; + hdisp->status.hflip = hflip; + hdisp->status.vflip = vflip; + hdisp->status.dst = *dst; + + if (!_fbdevVideoV4l2SetDst (hdisp->video_fd, hdisp->offset_x, hdisp->offset_y, dst)) + { + xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _fbdevVideoV4l2SetDst is failed. \n", hdisp); + return FALSE; + } + + if (!_fbdevVideoV4l2SetBuffer (hdisp->video_fd, + V4L2_BUF_TYPE_VIDEO_OVERLAY, + hdisp->memory, + BUF_NUM, + &hdisp->dst_buf)) + { + xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _fbdevVideoV4l2SetBuffer is failed. \n", hdisp); + return FALSE; + } + + hdisp->status.cur_idx = 0; + } + + if (!hdisp->status.streamon) + { + _fbdevVideoV4l2StreamOn (hdisp->video_fd); + hdisp->status.streamon = TRUE; + } + + return TRUE; +} + +XF86ImagePtr +fbdevVideoV4l2SupportImages (int *count) +{ + if (count) + *count = NUM_IMAGES; + + return Images; +} + +int +fbdevVideoV4l2Draw (void *handle, uchar *buf, uint *phy_addrs) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + pixman_format_code_t src_format, dst_format; + xRectangle img = hdisp->status.img; + xRectangle src = hdisp->status.crop; + xRectangle pxm = hdisp->status.dst; + xRectangle dst = hdisp->status.dst; + + pxm.x = pxm.y = dst.x = dst.y = 0; + + switch (hdisp->pixfmt) + { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + src_format = PIXMAN_yv12; + break; + case V4L2_PIX_FMT_YUYV: + src_format = PIXMAN_yuy2; + break; + case V4L2_PIX_FMT_RGB565: + src_format = PIXMAN_r5g6b5; + break; + case V4L2_PIX_FMT_RGB24: + src_format = PIXMAN_r8g8b8; + break; + case V4L2_PIX_FMT_RGB32: + src_format = PIXMAN_a8r8g8b8; + break; + default: + return FALSE; + } + + switch (hdisp->pixfmt) + { + case V4L2_PIX_FMT_YUV420: + dst_format = PIXMAN_x8b8g8r8; + break; + default: + dst_format = PIXMAN_x8r8g8b8; + break; + } + + /* support only RGB */ + fbdev_pixman_convert_image (PIXMAN_OP_SRC, + buf, hdisp->dst_buf[0].buf, + src_format, dst_format, + &img, &pxm, &src, &dst, + NULL, (hdisp->status.hw_rotate + (360 - hdisp->status.scn_rotate)) % 360, + hdisp->status.hflip, hdisp->status.vflip); + + return TRUE; +} + +Bool +fbdevVideoV4l2GetFormatInfo (int id, int *type, uint *pixelformat, FBDevV4l2Memory *memory) +{ + int i; + + for (i = 0; i < sizeof (format_infos) / sizeof (FormatInfo); i++) + if (format_infos[i].id == id) + { + if (type) + *type = format_infos[i].type; + if (pixelformat) + *pixelformat = format_infos[i].pixelformat; + if (memory) + *memory = format_infos[i].memory; + return TRUE; + } + + return FALSE; +} + +/* img : original src size + * src : real src size (cropped area inside img) + * dst : real dst size + * original dst size (in case that image is drawn on opened framebuffer) + */ +Bool +fbdevVideoV4l2CheckSize (void *handle, uint pixelformat, + xRectangle *img, xRectangle *src, xRectangle *dst, + int type, int memory) +{ + /* img */ + if (img) + { + if (img->width % 16) + xf86DrvMsg (0, X_WARNING, "img's width(%d) is not multiple of 16!!!\n", img->width); + + if (type == TYPE_YUV420 && img->height % 2) + xf86DrvMsg (0, X_WARNING, "img's height(%d) is not multiple of 2!!!\n", img->height); + + return_val_if_fail (img->width >= 16, FALSE); + return_val_if_fail (img->height >= 16, FALSE); + } + + /* src */ + if (src) + { + if (type == TYPE_YUV420 || type == TYPE_YUV422) + { + src->x = src->x & (~0x1); + src->width = src->width & (~0x1); + } + + if (type == TYPE_YUV420) + src->height = src->height & (~0x1); + + return_val_if_fail (src->width >= 16, FALSE); + return_val_if_fail (src->height >= 16, FALSE); + } + + /* dst */ + if (dst) + { + dst->width = dst->width & (~0x1); + dst->height = dst->height & (~0x1); + + return_val_if_fail (dst->width >= 8, FALSE); + return_val_if_fail (dst->height >= 8, FALSE); + } + + return TRUE; +} + +void +fbdevVideoGetFBInfo (void *handle, void **base, xRectangle *pos) +{ + FBDevDispHandle *hdisp = (FBDevDispHandle*)handle; + + if (!hdisp) + return; + + if (pos) + *pos = hdisp->status.dst; + if (base) + *base = hdisp->dst_buf[0].buf; +} diff --git a/src/xv/xv_types.h b/src/xv/xv_types.h new file mode 100644 index 0000000..d8465d9 --- /dev/null +++ b/src/xv/xv_types.h @@ -0,0 +1,80 @@ +/************************************************************************** + +xserver-xorg-video-emulfb + +Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: YoungHoon Jung + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* */ +/* File name : xv_types.h */ +/* Author : YoungHoon Jung (yhoon.jung@samsung.com) */ +/* Protocol Version : 1.0.1 (Dec 16th 2009) */ +/* This file is for describing Xv APIs' buffer encoding method. */ +/* */ + +#define XV_PUTIMAGE_HEADER 0xDEADCD01 +#define XV_PUTIMAGE_VERSION 0x00010001 + +/* Return Values */ +#define XV_OK 0 +#define XV_HEADER_ERROR -1 +#define XV_VERSION_MISMATCH -2 + +/* Data structure for XvPutImage / XvShmPutImage */ +typedef struct { + unsigned int _header; /* for internal use only */ + unsigned int _version; /* for internal use only */ + + unsigned int YPhyAddr; + unsigned int CbPhyAddr; + unsigned int CrPhyAddr; + unsigned int RotAngle; + unsigned int VideoMode; +} XV_PUTIMAGE_DATA, * XV_PUTIMAGE_DATA_PTR; + +static void +#ifdef __GNUC__ +__attribute__ ((unused)) +#endif +XV_PUTIMAGE_INIT_DATA(XV_PUTIMAGE_DATA_PTR data) +{ + data->_header = XV_PUTIMAGE_HEADER; + data->_version = XV_PUTIMAGE_VERSION; +} + + +static int +#ifdef __GNUC__ +__attribute__ ((unused)) +#endif +XV_PUTIMAGE_VALIDATE_DATA(XV_PUTIMAGE_DATA_PTR data) +{ + if (data->_header != XV_PUTIMAGE_HEADER) + return XV_HEADER_ERROR; + if (data->_version != XV_PUTIMAGE_VERSION) + return XV_VERSION_MISMATCH; + return XV_OK; +} -- 2.7.4