diff options
205 files changed, 112388 insertions, 1083 deletions
diff --git a/classes/gnome.bbclass b/classes/gnome.bbclass index da88884dde..3d04298ac6 100644 --- a/classes/gnome.bbclass +++ b/classes/gnome.bbclass @@ -23,5 +23,6 @@ gnome_stage_includes() { do_install_append() { rm -rf ${D}${localstatedir}/lib/scrollkeeper/* + rm -f ${D}${datadir}/applications/*.cache } diff --git a/classes/insane.bbclass b/classes/insane.bbclass index 606270d62c..c41b84a4c0 100644 --- a/classes/insane.bbclass +++ b/classes/insane.bbclass @@ -73,7 +73,7 @@ def package_qa_get_machine_dict(): "arm" : (40, 0, 0, True, True), "armeb" : (40, 0, 0, False, True), }, - "linux-uclibcgnueabi" : { + "linux-uclibceabi" : { "arm" : (40, 0, 0, True, True), "armeb" : (40, 0, 0, False, True), }, diff --git a/classes/package.bbclass b/classes/package.bbclass index f6bd7c5b4a..5a9fa503ae 100644 --- a/classes/package.bbclass +++ b/classes/package.bbclass @@ -202,6 +202,51 @@ def runstrip(file, d): return 1 +def write_package_md5sums (root, outfile, ignorepaths): + # For each regular file under root, writes an md5sum to outfile. + # With thanks to patch.bbclass. + import bb, os + + try: + # Python 2.5+ + import hashlib + ctor = hashlib.md5 + except ImportError: + import md5 + ctor = md5.new + + outf = file(outfile, 'w') + + # Each output line looks like: "<hex...> <filename without leading slash>" + striplen = len(root) + if not root.endswith('/'): + striplen += 1 + + for walkroot, dirs, files in os.walk(root): + # Skip e.g. the DEBIAN directory + if walkroot[striplen:] in ignorepaths: + dirs[:] = [] + continue + + for name in files: + fullpath = os.path.join(walkroot, name) + if os.path.islink(fullpath) or (not os.path.isfile(fullpath)): + continue + + m = ctor() + f = file(fullpath, 'rb') + while True: + d = f.read(8192) + if not d: + break + m.update(d) + f.close() + + print >> outf, "%s %s" % (m.hexdigest(), fullpath[striplen:]) + + outf.close() + + # # Package data handling routines # diff --git a/classes/package_deb.bbclass b/classes/package_deb.bbclass index e5339a9064..4a17010538 100644 --- a/classes/package_deb.bbclass +++ b/classes/package_deb.bbclass @@ -243,6 +243,13 @@ python do_package_deb () { conffiles.write('%s\n' % f) conffiles.close() + try: + write_package_md5sums(root, os.path.join(controldir, 'md5sums'), + ['DEBIAN']) + except: + bb.utils.unlockfile(lf) + raise + os.chdir(basedir) ret = os.system("PATH=\"%s\" fakeroot dpkg-deb -b %s %s" % (bb.data.getVar("PATH", localdata, 1), root, pkgoutdir)) if ret != 0: diff --git a/classes/qmake_base.bbclass b/classes/qmake_base.bbclass index 5eccfa47e4..50d8bb53da 100644 --- a/classes/qmake_base.bbclass +++ b/classes/qmake_base.bbclass @@ -33,7 +33,7 @@ oe_qmake_mkspecs () { qmake_base_do_configure() { case ${QMAKESPEC} in - *linux-oe-g++|*linux-uclibc-oe-g++|*linux-gnueabi-oe-g++|*linux-uclibcgnueabi-oe-g++) + *linux-oe-g++|*linux-uclibc-oe-g++|*linux-gnueabi-oe-g++|*linux-uclibceabi-oe-g++) ;; *-oe-g++) die Unsupported target ${TARGET_OS} for oe-g++ qmake spec diff --git a/classes/siteinfo.bbclass b/classes/siteinfo.bbclass index e51d7ab8a6..2bacd69488 100644 --- a/classes/siteinfo.bbclass +++ b/classes/siteinfo.bbclass @@ -22,21 +22,27 @@ def get_siteinfo_list(d): targetinfo = {\ "armeb-linux": "endian-big bit-32 common-linux common-glibc arm-common",\ + "armeb-linux-gnu": "endian-big bit-32 common-linux common-glibc arm-common",\ "armeb-linux-gnueabi": "endian-big bit-32 common-linux common-glibc arm-common armeb-linux",\ "armeb-linux-uclibc": "endian-big bit-32 common-linux common-uclibc arm-common",\ - "armeb-linux-uclibcgnueabi": "endian-big bit-32 common-linux common-uclibc arm-common armeb-linux-uclibc",\ + "armeb-linux-uclibceabi": "endian-big bit-32 common-linux common-uclibc arm-common armeb-linux-uclibc",\ "arm-darwin": "endian-little bit-32 common-darwin",\ "arm-darwin9": "endian-little bit-32 common-darwin",\ "arm-linux": "endian-little bit-32 common-linux common-glibc arm-common",\ + "arm-linux-gnu": "endian-little bit-32 common-linux common-glibc arm-common",\ "arm-linux-gnueabi": "endian-little bit-32 common-linux common-glibc arm-common arm-linux",\ "arm-linux-uclibc": "endian-little bit-32 common-linux common-uclibc arm-common",\ - "arm-linux-uclibcgnueabi": "endian-little bit-32 common-linux common-uclibc arm-common arm-linux-uclibc",\ + "arm-linux-uclibceabi": "endian-little bit-32 common-linux common-uclibc arm-common arm-linux-uclibc",\ "avr32-linux-uclibc": "endian-big bit-32 common-linux common-uclibc avr32-common",\ "bfin-uclinux-uclibc": "endian-little bit-32 common-uclibc bfin-common",\ "i386-linux": "endian-little bit-32 common-linux common-glibc ix86-common",\ + "i386-linux-gnu": "endian-little bit-32 common-linux common-glibc ix86-common",\ "i486-linux": "endian-little bit-32 common-linux common-glibc ix86-common",\ + "i486-linux-gnu": "endian-little bit-32 common-linux common-glibc ix86-common",\ "i586-linux": "endian-little bit-32 common-linux common-glibc ix86-common",\ + "i586-linux-gnu": "endian-little bit-32 common-linux common-glibc ix86-common",\ "i686-linux": "endian-little bit-32 common-linux common-glibc ix86-common",\ + "i686-linux-gnu": "endian-little bit-32 common-linux common-glibc ix86-common",\ "i386-linux-uclibc": "endian-little bit-32 common-linux common-uclibc ix86-common",\ "i486-linux-uclibc": "endian-little bit-32 common-linux common-uclibc ix86-common",\ "i586-linux-uclibc": "endian-little bit-32 common-linux common-uclibc ix86-common",\ @@ -50,22 +56,34 @@ def get_siteinfo_list(d): "i586-mingw32": "endian-little bit-32 common-mingw ix86-common",\ "i686-mingw32": "endian-little bit-32 common-mingw ix86-common",\ "ia64-linux": "endian-little bit-64 common-linux common-glibc",\ + "ia64-linux-gnu": "endian-little bit-64 common-linux common-glibc",\ "mipsel-linux": "endian-little bit-32 common-linux common-glibc",\ + "mipsel-linux-gnu": "endian-little bit-32 common-linux common-glibc",\ "mipsel-linux-uclibc": "endian-little bit-32 common-linux common-uclibc",\ "mips-linux": "endian-big bit-32 common-linux common-glibc",\ + "mips-linux-gnu": "endian-big bit-32 common-linux common-glibc",\ "mips-linux-uclibc": "endian-big bit-32 common-linux common-uclibc",\ "powerpc-darwin": "endian-big bit-32 common-darwin",\ "ppc-linux": "endian-big bit-32 common-linux common-glibc powerpc-common",\ + "ppc-linux-gnu": "endian-big bit-32 common-linux common-glibc powerpc-common",\ "ppc64-linux": "endian-big bit-64 common-linux common-glibc powerpc-common",\ + "ppc64-linux-gnu": "endian-big bit-64 common-linux common-glibc powerpc-common",\ "powerpc-linux": "endian-big bit-32 common-linux common-glibc powerpc-common",\ + "powerpc-linux-gnu": "endian-big bit-32 common-linux common-glibc powerpc-common",\ "powerpc-linux-gnuspe": "endian-big bit-32 common-linux common-glibc powerpc-common",\ "powerpc-linux-uclibc": "endian-big bit-32 common-linux common-uclibc powerpc-common",\ + "powerpc-linux-uclibcspe": "endian-big bit-32 common-linux common-uclibc powerpc-common",\ "sh3-linux": "endian-little bit-32 common-linux common-glibc sh-common",\ + "sh3-linux-gnu": "endian-little bit-32 common-linux common-glibc sh-common",\ "sh4-linux": "endian-little bit-32 common-linux common-glibc sh-common",\ + "sh4-linux-gnu": "endian-little bit-32 common-linux common-glibc sh-common",\ "sh4-linux-uclibc": "endian-little bit-32 common-linux common-uclibc sh-common",\ "sparc-linux": "endian-big bit-32 common-linux common-glibc",\ + "sparc-linux-gnu": "endian-big bit-32 common-linux common-glibc",\ "viac3-linux": "endian-little bit-32 common-linux common-glibc ix86-common",\ + "viac3-linux-gnu": "endian-little bit-32 common-linux common-glibc ix86-common",\ "x86_64-linux": "endian-little bit-64 common-linux common-glibc",\ + "x86_64-linux-gnu": "endian-little bit-64 common-linux common-glibc",\ "x86_64-linux-uclibc": "endian-little bit-64 common-linux common-uclibc"} if target in targetinfo: info = targetinfo[target].split() diff --git a/conf/abi_version.conf b/conf/abi_version.conf index 7939d65ad1..7f190c38c1 100644 --- a/conf/abi_version.conf +++ b/conf/abi_version.conf @@ -4,7 +4,7 @@ # that breaks the format and have been previously discussed on the mailing list # with general agreement from the core team. # -OELAYOUT_ABI = "2" +OELAYOUT_ABI = "3" # # DISTRO_PR allows us to regenerate all packages when a fundamental change is diff --git a/conf/checksums.ini b/conf/checksums.ini index 5c0e4967ce..053a2ad932 100644 --- a/conf/checksums.ini +++ b/conf/checksums.ini @@ -678,6 +678,10 @@ sha256=d60027a4a36e64d02723d00b76c08e8d92850cab6269b2edcda4a1bb30cc7723 md5=f4898b999f39c79d55c13c0e0f597c71 sha256=e7bc69a316e6e2a263987a0aec5c6249dc152361e9559b4818a680681409aac1 +[http://ftp.gnome.org/pub/GNOME/sources/ORBit2/2.14/ORBit2-2.14.17.tar.bz2] +md5=10bfb957fa4a8935a0b4afaee7d71df7 +sha256=62bfce3f678f9347a19c766944e8aef7b89bc32b25ac23eb3e4c25929ce8974c + [http://downloads.sourceforge.net/openipmi/OpenIPMI-2.0.14.tar.gz] md5=f766680bb237ca2f837c005efba54efa sha256=fbd907dde45054227568f3117df0418a7819cfee02875d3723779432e8a66dc9 @@ -4014,6 +4018,14 @@ sha256=fdea779f261f70b9bbec40121c830b11e3e63b6188f662f95505045ff8d44add md5=4dc988ee16e1471799af97763297b41b sha256=ca4452f2a2ce2daf6eaa1743ded2d3b36013200c48e3f2117b65584ca5cc1d9b +[http://compcache.googlecode.com/files/compcache-0.6.tar.gz] +md5=0a574643c0eb857b946adcd5d5a22eb0 +sha256=e5f697be6c1b7bfb9ac9ba5b8d836ff20f880c161f998c482caba83caf443c0c + +[http://compcache.googlecode.com/files/compcache-0.6pre3.tar.gz] +md5=532fbc4e6a8ae0670ec15a49484f313f +sha256=3e54f26665bd1b7ece4e4621a15f82da66a95bafd04286d447be5a596790a7db + [http://amelang.net/composite_pixbuf.c] md5=97edf3cce3353b6cb5f822442a83aa5e sha256=bd6f9e5dc0a89e9918f78a550f6e688480f044cec2e8674d34c7c6212831d6bd @@ -4954,6 +4966,10 @@ sha256=e19f52cde20094ce20a1edee019ae7715bc1e8beca62ec4989a3da626ba9898a md5=2d29a68f8fb75b3bed7a18f3d0a002bb sha256=e19f52cde20094ce20a1edee019ae7715bc1e8beca62ec4989a3da626ba9898a +[ftp://ftp.debian.org/debian/pool/main/d/diffstat/diffstat_1.47-1.diff.gz] +md5=b49f997897f5dfc2d2b8e0b6ea3df83c +sha256=56dcebb128d401cd5608fcd77739b42f9cfc5af531d85822287f631ad6328dcd + [ftp://ftp.us.debian.org/debian/pool/main/d/diffstat/diffstat_1.47-1.diff.gz] md5=b49f997897f5dfc2d2b8e0b6ea3df83c sha256=56dcebb128d401cd5608fcd77739b42f9cfc5af531d85822287f631ad6328dcd @@ -10014,6 +10030,10 @@ sha256=c9a5f4c9b1eddd7cb042d83390072f832f19f3712d023e4d6568391e5eb4878a md5=6be89b26592f36ef631b22a68b8e06c4 sha256=94bd5110a03837145afe5c81760f22bd7bef9ef455f4417340eeeb2b12e54fb0 +[http://gstreamer.freedesktop.org/src/gst-ffmpeg/gst-ffmpeg-0.10.8.tar.bz2] +md5=a7177f85c87d404a3c0d511b835129d1 +sha256=d9e056793d05bf0b6f4989b27d3107c2f223a14205ee54be403bbe52945c8853 + [http://core.fluendo.com/gstreamer/src/gst-fluendo-mp3/gst-fluendo-mp3-0.10.2.tar.bz2] md5=f3c32e0bc3ec1be461ce43e407a6a67f sha256=cba1eac94de8de8c181c6c60dfc59f8069d388761aba71bcd8c48b8ba9b2edf5 @@ -11478,6 +11498,10 @@ sha256=90f69ae24cc21fa6d33dc406077f16c06113b3000f7d267e7056e52f50d0abc0 md5=a593b2eabde56f122e2bb3d2d45f7ca7 sha256=90f69ae24cc21fa6d33dc406077f16c06113b3000f7d267e7056e52f50d0abc0 +[http://downloads.sourceforge.net/inotify-tools/inotify-tools-3.13.tar.gz] +md5=35d7178297390f18bae451e083362acf +sha256=464146acec2c118be63a6c2a090d9252fbe9689c093db85b695d0502fa229445 + [http://www.rpsys.net/openzaurus/patches/archive/input_modalias_fix-r0.patch] md5=291fdc77615d56d1ec8a9d4ad3dcc39e sha256=04f8f5890cc45beb1305f6b94f3a4cdd480132703277ed53c32e1d8e0975702e @@ -12486,6 +12510,10 @@ sha256=feb4abd0ea31b5a0b8344bfcb0e5987eefad723fa45f1d8e1e95c62acebab524 md5=9e10a77ff225587e59c0a28c66b4faa7 sha256=91a5b69435f10002b222be022c832d9860a93e0bc181e3f94abc150486ab031a +[http://ftp.gnome.org/pub/GNOME/sources/libIDL/0.8/libIDL-0.8.13.tar.bz2] +md5=b43b289a859eb38a710f70622c46e571 +sha256=bccc7e10dae979518ff012f8464e47ec4b3558a5456a94c8679653aa0b262b71 + [ftp://ftp.gnome.org/pub/GNOME/sources/libIDL/0.8/libIDL-0.8.2.tar.bz2] md5=a75d2dbf3a3c66b567047c94245f8b82 sha256=1c9529f7245778a4f1422d6257d446b7c90a19c3b603b1a25db1669552c464b3 @@ -13742,6 +13770,10 @@ sha256=15e4c95402caa3c97394189a6b1b693eced23d80e292fcca12585317434adc2e md5=da4f9d1c6cd1337f6ef5e2db768d8557 sha256=7c79a2afaef4fd6726bad0530e29d2bc19689e07720a05c3ad32012e5aed3138 +[http://ftp.gnome.org/pub/GNOME/sources/libglade/2.6/libglade-2.6.4.tar.bz2] +md5=d1776b40f4e166b5e9c107f1c8fe4139 +sha256=64361e7647839d36ed8336d992fd210d3e8139882269bed47dc4674980165dec + [ftp://ftp.gnome.org/pub/GNOME/sources/libglademm/2.4/libglademm-2.4.1.tar.bz2] md5=81688d8499028aee8132db48a71e90eb sha256=4efb4fe267c19bf96e56f01f0d7a5508c1619cfac139a8e2e5c7f99a8d9cf97c @@ -14502,6 +14534,10 @@ sha256=15b0492ac252f6e8ce57c106bda0722413196d16d198c97f20a05908d1b977af md5=ba76f68b7e3bd284ac2c2a1b9c5ecb06 sha256=2389a9b8220f776033f728a8d46352cfee5c8705066e34887bfb188f9f0d3856 +[http://www.galago-project.org/files/releases/source/libnotify/libnotify-0.4.5.tar.gz] +md5=472e2c1f808848365572a9b024d9e8f5 +sha256=0799db8ea1500b65a477421a8c930cc8c8b0bbc0596e55ea1601e2542f3fb0d9 + [http://www.netsurf-browser.org/projects/releases/libnsbmp-0.0.1-src.tar.gz] md5=61e1e5703580c1bc7d950a1aacea7bad sha256=424d12aae7a6ea8c90438cf4ccff486dc01a3a2a7b68eb602ee2b8c28178b6d1 @@ -15270,6 +15306,10 @@ sha256=59e835a57e6df03e4d2253b2357253f3d13da9473ff465563a3b9833a744fc36 md5=02b9e41c70ca738e1aa914f400fc1f05 sha256=d627a10f523af14e9ead655ebab3a26e7faeea006bdfa7739bc4c04058ddf4c6 +[http://ftp.gnome.org/pub/GNOME/sources/libunique/1.1/libunique-1.1.2.tar.bz2] +md5=f33749109768d43ef69ca7e8ffa7cfb7 +sha256=73fb130295fc42b237aa3d808905f65ead9f979acbe49434eca830c6085f0c6e + [http://downloads.sourceforge.net/upnp/libupnp-1.3.1.tar.gz] md5=6646be5e31e58188e8f47c6ce64faa4c sha256=4d0d6a5302222757fb36ee21d8f8e1b3de849c2de658ab1105272f32ff78767d @@ -23374,6 +23414,10 @@ sha256=10fd6f07264d3fbd92c03858a99637cd4b9d98ab00fb4d31720adce0c1ed7af4 md5=7be5e39236e2d6efa61a18e83e5ab73d sha256=7d56a3044c19e7ca4b492f3739d9aa6f6bdb6e51ecf4daa5d29c035ae430f1ef +[http://ftp.gnome.org/pub/GNOME/sources/swfdec-gnome/2.26/swfdec-gnome-2.26.0.tar.bz2] +md5=53d611d9a76a06a703650c4b73fd44cc +sha256=bf48dcadd9ca015f40a9aaa9cc94d402e9daf7c88b747789c79fcc921e9e1626 + [http://swfdec.freedesktop.org/download/swfdec-mozilla/0.7/swfdec-mozilla-0.7.2.tar.gz] md5=3bc6a49357b4b8b478ce3dfb4f007f18 sha256=84962251e647fdcdcf111bef0c478f7d3679ae104267ba72e59ad749c6955cc2 @@ -23590,6 +23634,10 @@ sha256=fdd50cb114151c66b8180c0ce90ba0e99f77a69770ac21598a87be935eec2224 md5=c82a9d305c3a1bf924bba6b1bced3e86 sha256=7f56dd08cf5425218b697d5db82e6ce03aff4f7b57f58d3053f0a7af632b3747 +[http://ftp.gnome.org/pub/GNOME/sources/system-tools-backends/2.8/system-tools-backends-2.8.1.tar.bz2] +md5=2aecff382af4d8ba7fcd69298cc79413 +sha256=c1f5746d22ef439ee47c9b012273ccbefbb2621075f05876bdb6ad5cfe4e1bbe + [ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/sysvinit-2.86.tar.gz] md5=7d5d61c026122ab791ac04c8a84db967 sha256=035f98fae17d9cff002993c564ccc83dc4ed136127172caeff872b6abdb679d8 @@ -26170,6 +26218,10 @@ sha256=45c4b6df8d1dbc4db8aa580be4f3c693ebba4eba4908d82489948827d3bed0e5 md5=23341f098e7fe8ec13ef06ef784ac51a sha256=63606119e86c27b47bd7ec4b2b6048b76515df6755fc5dd8bcfc98f5fe53d994 +[http://xorg.freedesktop.org/releases/individual/driver/xf86-input-evdev-2.2.5.tar.bz2] +md5=e926692d74ee81ed459d0fe89439ff8b +sha256=433fd29043cd427ba486bcce471aae3ad1abca94c8682feff92da0c380b8dff3 + [http://xorg.freedesktop.org/releases/X11R7.0/src/driver/xf86-input-evdev-X11R7.0-1.0.0.5.tar.bz2] md5=d982c6f185f4c75a4b65703ceed7be06 sha256=ba53e8ce6bfa01da7fa86a31853542a71722b41b511041bdb58cf66c10f3edb4 @@ -26658,6 +26710,10 @@ sha256=309d1f618c77559ea494c05d45b09577790c44900685e17bc812e4e1b19df6e7 md5=6572b39fec77b8e6de1c858a93992924 sha256=bba725daeb2a313b83f2b92855a9ae8aa72c4cc8581f9f62f101ebdf00ac359d +[http://xorg.freedesktop.org/releases/individual/driver/xf86-video-fbdev-0.4.1.tar.bz2] +md5=79ce1eb9f9d2ed56de70d8e06cb767d9 +sha256=2bf857179523433a9cc6c6eea059298db4c865e649aa58dfc67c828f28b7288f + [http://xorg.freedesktop.org/releases/X11R7.0/src/driver/xf86-video-fbdev-X11R7.0-0.1.0.5.tar.bz2] md5=1cf374eeb9151ac16a7ec2cd38048737 sha256=c6032ec1753a0f5975b5a7488ca3ca0d46f84bc5dd8fcb42eebd807c7faec765 @@ -27726,6 +27782,10 @@ sha256=c15dd54ad64e660d5a3e8c1ea0d14e50ba1127aab2e3211b82e3ee1e6c7045a4 md5=977d657e8d7b59f7d82c98ebef444b28 sha256=330c3e5188abf256131c162c456060804f369349e9a0e7aa3efbc54add802e45 +[http://xorg.freedesktop.org/releases/individual/app/xinput-1.4.2.tar.bz2] +md5=58e619576cbf4b6057eebb7a97fe2ddf +sha256=3195916b6cebf109eb571b939d7cea7075ef1933782526a6d8fbbb353bc3924b + [http://xorg.freedesktop.org/releases/individual/app/xkbcomp-1.0.3.tar.bz2] md5=2fbcae1323c266edf5b6c61751f2e343 sha256=0635bae5dae3c933ebba997475ae14fa213aee1f2ea8aaff2ca76c50f8aec716 @@ -28890,10 +28950,3 @@ sha256=f57c4e33eb2cdd87a6c2f01bfa4794340fbe61ea1a1cfc7dac3b6671e1dd22af md5=5f7b88ebb2bcd7e8044328482d079661 sha256=f57c4e33eb2cdd87a6c2f01bfa4794340fbe61ea1a1cfc7dac3b6671e1dd22af -[http://compcache.googlecode.com/files/compcache-0.6pre3.tar.gz] -md5=532fbc4e6a8ae0670ec15a49484f313f -sha256=3e54f26665bd1b7ece4e4621a15f82da66a95bafd04286d447be5a596790a7db - -[http://compcache.googlecode.com/files/compcache-0.6.tar.gz] -md5=0a574643c0eb857b946adcd5d5a22eb0 -sha256=e5f697be6c1b7bfb9ac9ba5b8d836ff20f880c161f998c482caba83caf443c0c diff --git a/conf/distro/include/angstrom-2007-for-openmoko.inc b/conf/distro/include/angstrom-2007-for-openmoko.inc index 1deb85d7f7..6741bae3e1 100644 --- a/conf/distro/include/angstrom-2007-for-openmoko.inc +++ b/conf/distro/include/angstrom-2007-for-openmoko.inc @@ -143,8 +143,8 @@ PREFERRED_PROVIDER_virtual/powerpc-angstrom-linux-libc-for-gcc = "glibc" PREFERRED_PROVIDER_virtual/mipsel-angstrom-linux-libc-for-gcc = "glibc" PREFERRED_PROVIDER_virtual/sparc-angstrom-linux-libc-for-gcc = "glibc" -PREFERRED_PROVIDER_virtual/arm-angstrom-linux-uclibcgnueabi-libc-for-gcc = "uclibc-initial" -PREFERRED_PROVIDER_virtual/armeb-angstrom-linux-uclibcgnueabi-libc-for-gcc = "uclibc-initial" +PREFERRED_PROVIDER_virtual/arm-angstrom-linux-uclibceabi-libc-for-gcc = "uclibc-initial" +PREFERRED_PROVIDER_virtual/armeb-angstrom-linux-uclibceabi-libc-for-gcc = "uclibc-initial" # hostap stuff, we prefer the in-kernel modules, but those don't work for all machines PREFERRED_PROVIDER_hostap-conf ?= "hostap-conf" diff --git a/conf/distro/include/angstrom-uclibc.inc b/conf/distro/include/angstrom-uclibc.inc index a60952ff06..004d90434c 100644 --- a/conf/distro/include/angstrom-uclibc.inc +++ b/conf/distro/include/angstrom-uclibc.inc @@ -9,7 +9,7 @@ USE_NLS_glib-2.0 = "yes" USE_NLS_glib-2.0-native = "yes" USE_NLS_gcc-cross = "no" -TARGET_OS_UC = "linux${@['-uclibc','-uclibcgnueabi'][bb.data.getVar('TARGET_ARCH',d,1) in ['arm', 'armeb'] and bb.data.getVar('MACHINE',d) not in ['collie','h3600', 'h3800', 'simpad', 'htcwallaby']]}" +TARGET_OS_UC = "linux${@['-uclibc','-uclibceabi'][bb.data.getVar('TARGET_ARCH',d,1) in ['arm', 'armeb'] and bb.data.getVar('MACHINE',d) not in ['collie','h3600', 'h3800', 'simpad', 'htcwallaby']]}" TARGET_OS = "${@['${TARGET_OS_UC}', 'uclinux-uclibc'][bb.data.getVar('TARGET_ARCH',d) in ['bfin']]}" #mess with compiler flags to use -Os instead of -O2 diff --git a/conf/distro/include/angstrom-uclinux-uclibc.inc b/conf/distro/include/angstrom-uclinux-uclibc.inc index 019f814b8f..ad499f7b67 100644 --- a/conf/distro/include/angstrom-uclinux-uclibc.inc +++ b/conf/distro/include/angstrom-uclinux-uclibc.inc @@ -6,7 +6,7 @@ USE_NLS_glib-2.0 = "yes" USE_NLS_glib-2.0-native = "yes" USE_NLS_gcc-cross = "no" -TARGET_OS_UC = "uclinux${@['-uclibc','-uclibcgnueabi'][bb.data.getVar('TARGET_ARCH',d,1) in ['arm', 'armeb'] and bb.data.getVar('MACHINE',d) not in ['collie','h3600', 'h3800', 'simpad', 'htcwallaby']]}" +TARGET_OS_UC = "uclinux${@['-uclibc','-uclibceabi'][bb.data.getVar('TARGET_ARCH',d,1) in ['arm', 'armeb'] and bb.data.getVar('MACHINE',d) not in ['collie','h3600', 'h3800', 'simpad', 'htcwallaby']]}" #mess with compiler flags to use -Os instead of -O2 #Please see http://free-electrons.com/doc/embedded_linux_optimizations/img47.html for some more info diff --git a/conf/distro/include/fso-autorev.inc b/conf/distro/include/fso-autorev.inc index a66a37fdd0..607f3cd06d 100644 --- a/conf/distro/include/fso-autorev.inc +++ b/conf/distro/include/fso-autorev.inc @@ -29,6 +29,7 @@ SRCREV_pn-libfso-glib = "${AUTOREV}" SRCREV_pn-libgee = "${AUTOREV}" SRCREV_pn-libgsm0710 = "${AUTOREV}" SRCREV_pn-libgsm0710mux = "${AUTOREV}" +SRCREV_pn-libpersistence = "${AUTOREV}" SRCREV_pn-mickeydbus = "${AUTOREV}" SRCREV_pn-mickeyterm = "${AUTOREV}" SRCREV_pn-misc-vapi = "${AUTOREV}" diff --git a/conf/distro/include/sane-toolchain-eglibc.inc b/conf/distro/include/sane-toolchain-eglibc.inc index 88719f5f33..4c5f44ff8e 100644 --- a/conf/distro/include/sane-toolchain-eglibc.inc +++ b/conf/distro/include/sane-toolchain-eglibc.inc @@ -3,8 +3,6 @@ # eglibc: # [23:00] oxo: glibc (any version) on sparc does not like (repeat me) "-Os" -TARGET_OS = "linux${@['','-gnueabi'][bb.data.getVar('TARGET_ARCH',d,1) in ['arm', 'armeb'] and bb.data.getVar('MACHINE',d) not in ['collie','h3600', 'h3800', 'simpad', 'htcwallaby']]}" - FULL_OPTIMIZATION = "-fexpensive-optimizations -fomit-frame-pointer -frename-registers -Os" FULL_OPTIMIZATION_pn-perl = "-fexpensive-optimizations -fomit-frame-pointer -frename-registers -O1" FULL_OPTIMIZATION_sparc = "-fexpensive-optimizations -fomit-frame-pointer -frename-registers -O2" diff --git a/conf/distro/include/sane-toolchain-glibc.inc b/conf/distro/include/sane-toolchain-glibc.inc index f3da7c31a2..f029c6fe46 100644 --- a/conf/distro/include/sane-toolchain-glibc.inc +++ b/conf/distro/include/sane-toolchain-glibc.inc @@ -2,8 +2,6 @@ # glibc: -TARGET_OS = "linux${@['','-gnueabi'][bb.data.getVar('TARGET_ARCH',d,1) in ['arm', 'armeb'] and bb.data.getVar('MACHINE',d) not in ['collie','h3600', 'h3800', 'simpad', 'htcwallaby']]}" - #mess with compiler flags to use -Os instead of -O2 #Please see http://free-electrons.com/doc/embedded_linux_optimizations/img47.html for some more info # perl has some problems, see http://bugs.openembedded.net/show_bug.cgi?id=1616 diff --git a/conf/distro/include/sane-toolchain-uclibc.inc b/conf/distro/include/sane-toolchain-uclibc.inc index 04935fe46d..3069820918 100644 --- a/conf/distro/include/sane-toolchain-uclibc.inc +++ b/conf/distro/include/sane-toolchain-uclibc.inc @@ -15,9 +15,6 @@ USE_NLS_glib-2.0 = "yes" USE_NLS_glib-2.0-native = "yes" USE_NLS_gcc-cross = "no" -TARGET_OS_UC = "linux${@['-uclibc','-uclibcgnueabi'][bb.data.getVar('TARGET_ARCH',d,1) in ['arm', 'armeb'] and bb.data.getVar('MACHINE',d) not in ['collie','h3600', 'h3800', 'simpad', 'htcwallaby']]}" -TARGET_OS = "${@['${TARGET_OS_UC}', 'uclinux-uclibc'][bb.data.getVar('TARGET_ARCH',d) in ['bfin']]}" - #mess with compiler flags to use -Os instead of -O2 #Please see http://free-electrons.com/doc/embedded_linux_optimizations/img47.html for some more info FULL_OPTIMIZATION = "-fexpensive-optimizations -fomit-frame-pointer -frename-registers -Os" diff --git a/conf/distro/include/sane-toolchain-uclinux-uclibc.inc b/conf/distro/include/sane-toolchain-uclinux-uclibc.inc index b757efb55a..fbb239a683 100644 --- a/conf/distro/include/sane-toolchain-uclinux-uclibc.inc +++ b/conf/distro/include/sane-toolchain-uclinux-uclibc.inc @@ -7,8 +7,6 @@ USE_NLS_glib-2.0 = "yes" USE_NLS_glib-2.0-native = "yes" USE_NLS_gcc-cross = "no" -TARGET_OS_UC = "uclinux${@['-uclibc','-uclibcgnueabi'][bb.data.getVar('TARGET_ARCH',d,1) in ['arm', 'armeb'] and bb.data.getVar('MACHINE',d) not in ['collie','h3600', 'h3800', 'simpad', 'htcwallaby']]}" - #mess with compiler flags to use -Os instead of -O2 #Please see http://free-electrons.com/doc/embedded_linux_optimizations/img47.html for some more info FULL_OPTIMIZATION = "-fexpensive-optimizations -fomit-frame-pointer -frename-registers -Os" diff --git a/conf/distro/include/sane-toolchain.inc b/conf/distro/include/sane-toolchain.inc index cebe77b4b5..65cb7763d1 100644 --- a/conf/distro/include/sane-toolchain.inc +++ b/conf/distro/include/sane-toolchain.inc @@ -65,16 +65,21 @@ PREFERRED_PROVIDER_linux-libc-headers = "linux-libc-headers" # Branding TARGET_VENDOR = "-oe" +# Add FEED_ARCH to the overrides list so that we can override the +# ARM_INSTRUCTION_SET like below + +OVERRIDES .= ":${FEED_ARCH}" + # ARM920T and up can use thumb mode to decrease binary size at the expense of speed # (the complete story is a bit more nuanced due to cache starvation) # Minimal turns on thumb for armv4t machine according to this RFC: # http://lists.linuxtogo.org/pipermail/angstrom-distro-devel/2008-October/002714.html # We can't set ARM_INSTRUCTION_SET_<override> directly since that will un-overridable in recipes like gcc -PREFERRED_ARM_INSTRUCTION_SET ?= "arm" PREFERRED_ARM_INSTRUCTION_SET_armv4t = "thumb" PREFERRED_ARM_INSTRUCTION_SET_armv5te = "thumb" PREFERRED_ARM_INSTRUCTION_SET_armv5teb = "thumb" +PREFERRED_ARM_INSTRUCTION_SET ?= "arm" ARM_INSTRUCTION_SET = "${PREFERRED_ARM_INSTRUCTION_SET}" # "arm" "thumb" # The instruction set the compiler should use when generating application @@ -136,7 +141,58 @@ ENABLE_BINARY_LOCALE_GENERATION_armv7a = "0" #qemu has taken a dislike to armeb as well ENABLE_BINARY_LOCALE_GENERATION_armeb = "0" +def detect_arm_abi (d): + import bb + if bb.data.getVar('DISTRO_FEATURES',d) is None: + if bb.data.getVar('TARGET_ARCH', d, 1) in [ 'arm', 'armeb' ]: + return "oabi" + else: + return "" + if bb.data.getVar('TARGET_ARCH', d, 1) in [ 'arm', 'armeb' ]: + if 'eabi' in bb.data.getVar('DISTRO_FEATURES',d).split(): + return "eabi" + return "oabi" + return "" + +def compute_os_portion_of_target_triplet (d): + import bb + arm_eabi_supporting_arches = "armv6 armv6-novfp \ + armv5te iwmmxt armv7a armv7 armv6 armv5teb armv5te armv4t" + ppc_spe_supporting_arches = "ppce500v2 ppce500" + + if bb.data.getVar("LIBC", d, 1) == "uclibc": + libc_suffix = "uclibc" + else: + libc_suffix = "gnu" + + if bb.data.getVar('TARGET_ARCH',d,1) in ['bfin']: + if libc_suffix == "gnu": + bb.fatal("bfin is not supported on glibc/eglibc. Please choose uclibc") + else: + os_suffix = "uclinux" + else: + os_suffix = "linux" + bparch = bb.data.getVar('BASE_PACKAGE_ARCH', d,1) + + if bb.data.getVar('DISTRO_FEATURES',d,1) is not None and \ + bparch is not None: + if 'eabi' in bb.data.getVar('DISTRO_FEATURES',d,1).split() and \ + bb.data.getVar('TARGET_ARCH', d, 1) in [ 'arm', 'armeb' ]: + if bparch not in arm_eabi_supporting_arches.split(): + bb.fatal("DISTRO requested EABI but selected machine does not support EABI") + abi_suffix = "" + else: + abi_suffix = "eabi" + elif bparch in ppc_spe_supporting_arches.split(): + abi_suffix = "spe" + else: + abi_suffix = "" + else: + bb.note("DISTRO_FEATURES is not set abi suffix not set") + abi_suffix = "" + return os_suffix + "-" + libc_suffix + abi_suffix # This is needed to get a correct PACKAGE_ARCH for packages that have PACKAGE_ARCH = ${MACHINE_ARCH} -ARM_ABI ?= "${@['','oabi'][bb.data.getVar('MACHINE',d) in ['collie','h3600', 'h3800', 'simpad', 'htcwallaby']]}" +ARM_ABI = "${@detect_arm_abi(d)}" +TARGET_OS = "${@compute_os_portion_of_target_triplet(d)}" include conf/distro/include/sane-toolchain-${ARM_ABI}.inc diff --git a/conf/distro/micro-uclibc.conf b/conf/distro/micro-uclibc.conf index 9cce7d18d0..fb1887c96c 100644 --- a/conf/distro/micro-uclibc.conf +++ b/conf/distro/micro-uclibc.conf @@ -7,9 +7,6 @@ #@COMMENT: based on uclibc. ############################################################################# -# Use overrides for micro as well -OVERRIDES .= ":micro" - ############################################################################# # DISTRO CONFIGURATION ############################################################################# @@ -24,3 +21,6 @@ LIBC = "uclibc" # Based on the Micro Linux distribution require conf/distro/micro.conf +# Use overrides for micro as well +OVERRIDES .= ":micro" + diff --git a/conf/distro/micro.conf b/conf/distro/micro.conf index 2d45425290..aca4a18caf 100644 --- a/conf/distro/micro.conf +++ b/conf/distro/micro.conf @@ -16,16 +16,10 @@ DISTRO_NAME = "micro" DISTRO_VERSION = "${SRCDATE}" ############################################################################# -# TARGET OS -############################################################################# -# Linux -TARGET_OS = "linux" - -############################################################################# # DISTRO FEATURE SELECTION ############################################################################# # No features selected -DISTRO_FEATURES = "" +DISTRO_FEATURES = "eabi" ############################################################################# # LIBRARY NAMES @@ -79,7 +73,7 @@ ${TARGET_ARCH}:build-${BUILD_OS}:fail-fast:pn-${PN}" # PREFERRED PROVIDERS ############################################################################# PREFERRED_PROVIDER_task-bootstrap = "task-bootstrap" - +PREFERRED_PROVIDER_virtual/libx11 = "libx11" ############################################################################# # PREFERRED VERSIONS ############################################################################# @@ -110,3 +104,4 @@ USE_LDCONFIG = "0" # Disable online package management ONLINE_PACKAGE_MANAGEMENT = "none" +DISTRO_BLUETOOTH_MANAGER = "bluez4" diff --git a/conf/distro/minimal.conf b/conf/distro/minimal.conf index fa2a926a1d..ecf6649fab 100644 --- a/conf/distro/minimal.conf +++ b/conf/distro/minimal.conf @@ -25,6 +25,8 @@ DISTRO_CHECK := "${@bb.data.getVar("DISTRO_VERSION",d,1) or bb.fatal('Remove thi DISTRO_BLUETOOTH_MANAGER = "bluez4" # We want images supporting the following features (for task-base) DISTRO_FEATURES = "nfs smbfs wifi ppp alsa ext2 vfat pcmcia usbgadget usbhost pci" +# Following features are for ARM and E500 based machines +DISTRO_FEATURES += "eabi" ############################################################################# # LIBRARY NAMES @@ -71,15 +73,15 @@ KERNEL = "kernel26" MACHINE_KERNEL_VERSION = "2.6" ############################################################################# -# TOOLCHAIN +# OVERWRITES adjusted from bitbake.conf to feature the MACHINE_CLASS ############################################################################# -LIBC ?= "eglibc" -require conf/distro/include/sane-toolchain.inc +OVERRIDES = "local:${MACHINE}:${MACHINE_CLASS}:${DISTRO}:${TARGET_OS}:${TARGET_ARCH}:build-${BUILD_OS}:fail-fast:pn-${PN}" ############################################################################# -# OVERWRITES adjusted from bitbake.conf to feature the MACHINE_CLASS +# TOOLCHAIN ############################################################################# -OVERRIDES = "local:${MACHINE}:${MACHINE_CLASS}:${DISTRO}:${TARGET_OS}:${TARGET_ARCH}:build-${BUILD_OS}:fail-fast:pn-${PN}" +LIBC ?= "eglibc" +require conf/distro/include/sane-toolchain.inc ############################################################################# # PREFERRED PROVIDERS diff --git a/conf/machine/include/omap3.inc b/conf/machine/include/omap3.inc index 163c9c901a..889e0f6478 100644 --- a/conf/machine/include/omap3.inc +++ b/conf/machine/include/omap3.inc @@ -1,7 +1,7 @@ require conf/machine/include/tune-cortexa8.inc PREFERRED_PROVIDER_virtual/kernel = "linux-omap" # Increase this everytime you change something in the kernel -MACHINE_KERNEL_PR = "r43" +MACHINE_KERNEL_PR = "r44" KERNEL_IMAGETYPE = "uImage" diff --git a/conf/machine/include/tune-strongarm.inc b/conf/machine/include/tune-strongarm.inc index 5745c36311..2a583fe6e4 100644 --- a/conf/machine/include/tune-strongarm.inc +++ b/conf/machine/include/tune-strongarm.inc @@ -5,5 +5,5 @@ ARM_ABI = "oabi" TARGET_CC_ARCH = "-march=armv4 -mtune=strongarm" FEED_ARCH = "arm-oabi" - +PACKAGE_BASE_ARCH = "armv4" PACKAGE_EXTRA_ARCHS += "armv4 " diff --git a/conf/machine/include/tune-xscale.inc b/conf/machine/include/tune-xscale.inc index 79d22bc794..7fa6447648 100644 --- a/conf/machine/include/tune-xscale.inc +++ b/conf/machine/include/tune-xscale.inc @@ -3,7 +3,7 @@ FEED_ARCH = "${@['armv5teb', 'armv5te'][bb.data.getVar('SITEINFO_ENDIANESS', d, TARGET_CC_ARCH = "-march=armv5te -mtune=xscale" TARGET_CC_KERNEL_ARCH = "-march=armv5te -mtune=xscale" PACKAGE_EXTRA_ARCHS += "${@['armv4b armv4tb armv5teb', 'armv4 armv4t armv5te'][bb.data.getVar('SITEINFO_ENDIANESS', d, 1) == 'le']}" -BASE_PACKAGE_ARCH = "${@['armv5teb', 'armv5te'][bb.data.getVar('SITEINFO_ENDIANESS', d, 1) == 'le']}" +BASE_PACKAGE_ARCH := "${@['armv5teb', 'armv5te'][bb.data.getVar('SITEINFO_ENDIANESS', d, 1) == 'le']}" # Include tune file for thumb support, it defaults to off so DISTROs can turn it on if they wish require conf/machine/include/tune-thumb.inc diff --git a/recipes/alsa/alsa-utils_1.0.13.bb b/recipes/alsa/alsa-utils_1.0.13.bb index 1e6af1ec09..e77c2d97f7 100644 --- a/recipes/alsa/alsa-utils_1.0.13.bb +++ b/recipes/alsa/alsa-utils_1.0.13.bb @@ -12,7 +12,7 @@ SRC_URI = "ftp://ftp.alsa-project.org/pub/utils/alsa-utils-${PV}.tar.bz2" # please close bug and remove this comment when properly fixed # EXTRA_OECONF_linux-uclibc = "--disable-nls" -EXTRA_OECONF_linux-uclibcgnueabi = "--disable-nls" +EXTRA_OECONF_linux-uclibceabi = "--disable-nls" inherit autotools diff --git a/recipes/angstrom/angstrom-uboot-scripts.bb b/recipes/angstrom/angstrom-uboot-scripts.bb new file mode 100644 index 0000000000..bcdba45d9f --- /dev/null +++ b/recipes/angstrom/angstrom-uboot-scripts.bb @@ -0,0 +1,36 @@ +DESCRIPTION = "Various uboot scripts" + +DEPENDS = "u-boot-mkimage-native" + +SRC_URI = "file://*.cmd" + +do_configure() { + cp ${WORKDIR}/*.cmd ${S} +} + +do_compile() { + for i in *.cmd ; do + uboot-mkimage -A ${TARGET_ARCH} -O linux -T script -C none -a 0 -e 0 -n "Angstrom $i" -d $i $i.scr + done +} + +do_install() { + install -d ${D}${datadir}/u-boot-scripts + for i in *.scr ; do + install -m 0644 $i ${D}${datadir}/u-boot-scripts + done +} + +FILES_${PN} += "${datadir}" + +addtask deploy before do_package after do_install + +do_deploy() { + install -d ${DEPLOY_DIR_IMAGE} + for i in *.scr ; do + cp $i ${DEPLOY_DIR_IMAGE} + package_stagefile_shell ${DEPLOY_DIR_IMAGE}/$i + done +} + +PACKAGE_ARCH = "${MACHINE_ARCH}" diff --git a/recipes/angstrom/angstrom-uboot-scripts/pico.cmd b/recipes/angstrom/angstrom-uboot-scripts/pico.cmd new file mode 100644 index 0000000000..695ee26357 --- /dev/null +++ b/recipes/angstrom/angstrom-uboot-scripts/pico.cmd @@ -0,0 +1,3 @@ +setenv dvimode '640x480MR-24@60' +run loaduimage +run mmcboot diff --git a/recipes/avahi/avahi.inc b/recipes/avahi/avahi.inc index f5e68e26fe..cefb2bed64 100644 --- a/recipes/avahi/avahi.inc +++ b/recipes/avahi/avahi.inc @@ -25,7 +25,7 @@ AVAHI_PYTHON = "--disable-python" AVAHI_GTK = "--disable-gtk" LDFLAGS_append_linux-uclibc = " -lintl" -LDFLAGS_append_linux-uclibcgnueabi = " -lintl " +LDFLAGS_append_linux-uclibceabi = " -lintl " LDFLAGS_append_uclinux-uclibc = " -lintl" PACKAGES =+ "avahi-daemon avahi-discover libavahi-common libavahi-core libavahi-client avahi-dnsconfd libavahi-glib libavahi-ui avahi-discover-standalone avahi-autoipd avahi-utils" diff --git a/recipes/canutils/canutils_3.0.2.bb b/recipes/canutils/canutils_3.0.2.bb new file mode 100644 index 0000000000..b748641e7d --- /dev/null +++ b/recipes/canutils/canutils_3.0.2.bb @@ -0,0 +1,11 @@ +DESCRIPTION = "A collection of CAN utilities" +LICENSE = "GPL" + +PRIORITY = "optional" +DEPENDS = "linux-libc-headers perl-native" +PR = "r0" + +SRC_URI = "http://www.pengutronix.de/software/socket-can/download/canutils/v3.0/${P}.tar.bz2" + +inherit autotools pkgconfig + diff --git a/recipes/cups/cups.inc b/recipes/cups/cups.inc index cbec781881..006e6a3250 100644 --- a/recipes/cups/cups.inc +++ b/recipes/cups/cups.inc @@ -24,9 +24,10 @@ EXTRA_OECONF = " \ do_configure() { + export DSOFLAGS="${LDFLAGS}" gnu-configize libtoolize --force - DSOFLAGS="${LDFLAGS}" oe_runconf + oe_runconf } do_compile () { diff --git a/recipes/diffutils/diffutils_2.8.1.bb b/recipes/diffutils/diffutils_2.8.1.bb index b979fa89f6..590d7f4af9 100644 --- a/recipes/diffutils/diffutils_2.8.1.bb +++ b/recipes/diffutils/diffutils_2.8.1.bb @@ -15,7 +15,7 @@ inherit autotools update-alternatives # because it uses __mempcpy, there are other things (TBD: # see diffutils.mk in buildroot) EXTRA_OECONF_linux-uclibc = "--without-included-regex" -EXTRA_OECONF_linux-uclibcgnueabi = "--without-included-regex" +EXTRA_OECONF_linux-uclibceabi = "--without-included-regex" do_install_append () { mv ${D}${bindir}/diff ${D}${bindir}/diff.${PN} diff --git a/recipes/efl1/evas-native_svn.bb b/recipes/efl1/evas-native_svn.bb index 4a17942c78..d3da6659d6 100644 --- a/recipes/efl1/evas-native_svn.bb +++ b/recipes/efl1/evas-native_svn.bb @@ -1,7 +1,7 @@ require evas.inc inherit native -DEPENDS = "freetype-native libpng-native jpeg-native eet-native eina-native libfribidi-native" -PR = "r1" +DEPENDS = "freetype-native libxext-native libpng-native jpeg-native eet-native eina-native libfribidi-native" +PR = "r2" EXTRA_OECONF = "\ --x-includes=${STAGING_INCDIR}/X11 \ diff --git a/recipes/eibd/eibd.inc b/recipes/eibd/eibd.inc index f021d96f3f..e509764f64 100644 --- a/recipes/eibd/eibd.inc +++ b/recipes/eibd/eibd.inc @@ -5,7 +5,7 @@ PRIORITY = "optional" LICENSE = "GPLv2" DEPENDS = " pthsem libxml2" DEPENDS_append_linux-uclibc = " argp-standalone " -DEPENDS_append_linux-uclibcgnueabi = " argp-standalone " +DEPENDS_append_linux-uclibceabi = " argp-standalone " SRC_URI += " file://eibd " diff --git a/recipes/freesmartphone/libpersistence_git.bb b/recipes/freesmartphone/libpersistence_git.bb new file mode 100644 index 0000000000..8f6aafd42a --- /dev/null +++ b/recipes/freesmartphone/libpersistence_git.bb @@ -0,0 +1,14 @@ +DESCRIPTION = "A GObject Persistence Library" +AUTHOR = "Jürg Billeter, Michael 'Mickey' Lauer" +LICENSE = "LGPL" +SECTION = "devel" +DEPENDS = "libgee" +PV = "0.1.0+gitr${SRCREV}" +PR = "r0" + +SRC_URI = "\ + ${FREESMARTPHONE_GIT}/${PN};protocol=git;branch=mickey \ +" +S = "${WORKDIR}/git" + +inherit autotools_stage pkgconfig vala diff --git a/recipes/freesmartphone/mickeydbus_git.bb b/recipes/freesmartphone/mickeydbus_git.bb index 4774f84ba1..229ff7f1fd 100644 --- a/recipes/freesmartphone/mickeydbus_git.bb +++ b/recipes/freesmartphone/mickeydbus_git.bb @@ -4,7 +4,7 @@ HOMEPAGE = "http://www.freesmartphone.org" SECTION = "console/network" LICENSE = "GPLv2" PV = "0.9.2+gitr${SRCREV}" -PR = "r1" +PR = "r2" SRC_URI = "${FREESMARTPHONE_GIT}/python-helpers.git;protocol=git;branch=master" S = "${WORKDIR}/git" @@ -16,7 +16,9 @@ do_install() { RDEPENDS_${PN} = "\ python-dbus \ + python-pygobject \ python-pprint \ + python-xml \ " PACKAGE_ARCH_${PN} = "all" diff --git a/recipes/gcc/gcc-4.4.1.inc b/recipes/gcc/gcc-4.4.1.inc index 6ac5ab48ad..9bc4d17dd6 100644 --- a/recipes/gcc/gcc-4.4.1.inc +++ b/recipes/gcc/gcc-4.4.1.inc @@ -7,7 +7,7 @@ LICENSE = "GPLv3" DEPENDS = "mpfr gmp" -INC_PR = "r4" +INC_PR = "r5" FILESPATHPKG .= ":gcc-$PV" @@ -18,6 +18,8 @@ SRC_URI = "${GNU_MIRROR}/gcc/gcc-${PV}/gcc-${PV}.tar.bz2 \ file://gcc-disable-linux-unwind-with-libc-inhibit.patch;patch=1 \ file://gcc-link-libgcc-with-libm.patch;patch=1 \ file://gcc-improve-tls-macro.patch;patch=1 \ + file://cache-amnesia.patch;patch=1 \ + file://gcc-flags-for-build.patch;patch=1 \ " # Language Overrides FORTRAN = "" @@ -28,3 +30,46 @@ EXTRA_OECONF_BASE = " --enable-libssp \ --disable-libmudflap" EXTRA_OECONF_append_linux-uclibc = " ${@base_contains('TARGET_ARCH', 'powerpc', '--disable-decimal-float --without-long-double-128', '',d)}" +do_configure () { + # Setup these vars for cross building only + # ... because foo_FOR_TARGET apparently gets misinterpreted inside the + # gcc build stuff when the build is producing a cross compiler - i.e. + # when the 'current' target is the 'host' system, and the host is not + # the target (because the build is actually making a cross compiler!) + if [ "${BUILD_SYS}" != "${HOST_SYS}" ]; then + export CC_FOR_TARGET="${CC}" + export GCC_FOR_TARGET="${CC}" + export CXX_FOR_TARGET="${CXX}" + export AS_FOR_TARGET="${HOST_PREFIX}as" + export LD_FOR_TARGET="${HOST_PREFIX}ld" + export NM_FOR_TARGET="${HOST_PREFIX}nm" + export AR_FOR_TARGET="${HOST_PREFIX}ar" + export GFORTRAN_FOR_TARGET="gfortran" + export RANLIB_FOR_TARGET="${HOST_PREFIX}ranlib" + fi + export CC_FOR_BUILD="${BUILD_CC}" + export CXX_FOR_BUILD="${BUILD_CXX}" + export CFLAGS_FOR_BUILD="${BUILD_CFLAGS}" + export CPPFLAGS_FOR_BUILD="${BUILD_CPPFLAGS}" + export CXXFLAGS_FOR_BUILD="${BUILD_CXXFLAGS}" + export LDFLAGS_FOR_BUILD="${BUILD_LDFLAGS}" + export ARCH_FLAGS_FOR_TARGET="${ARCH_FLAGS_FOR_TARGET}" + + # Make sure LDFLAGS are honored. + sed -i 's/^LDFLAGS = $/LDFLAGS = @LDFLAGS@/' ${S}/Makefile.in + sed -i 's/^LDFLAGS = $/LDFLAGS = @LDFLAGS@/' ${S}/Makefile.tpl + + (cd ${S} && gnu-configize) || die "failure running gnu-configize" + + # splice our idea of where the headers live into gcc's world + #echo "NATIVE_SYSTEM_HEADER_DIR = ${layout_includedir}" > ${T}/t-oe + #sed 's%^tmake_file=.*$%& ${T}/t-oe%' < ${S}/gcc/Makefile.in >${S}/gcc/Makefile.in.new + #mv ${S}/gcc/Makefile.in.new ${S}/gcc/Makefile.in + + #echo "#define STANDARD_INCLUDE_DIR \"${layout_includedir}\"" >> ${S}/gcc/defaults.h + + oe_runconf + + # make sure that no @LDFLAG@ is left in the generated Makefile + sed -i "s/@LDFLAGS@//g" ${B}/Makefile +} diff --git a/recipes/gcc/gcc-4.4.1/cache-amnesia.patch b/recipes/gcc/gcc-4.4.1/cache-amnesia.patch index fb4d1a26d8..d5281ea575 100644 --- a/recipes/gcc/gcc-4.4.1/cache-amnesia.patch +++ b/recipes/gcc/gcc-4.4.1/cache-amnesia.patch @@ -3,27 +3,27 @@ gcc/configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) -Index: gcc-4.3.1/gcc/configure +Index: gcc-4.4.1/gcc/configure.ac =================================================================== ---- gcc-4.3.1.orig/gcc/configure 2008-08-20 00:27:57.000000000 -0700 -+++ gcc-4.3.1/gcc/configure 2008-08-20 00:45:11.000000000 -0700 -@@ -12813,7 +12813,7 @@ else - esac +--- gcc-4.4.1.orig/gcc/configure.ac 2009-03-24 10:46:03.000000000 -0700 ++++ gcc-4.4.1/gcc/configure.ac 2009-09-04 19:23:39.751461633 -0700 +@@ -1455,7 +1455,7 @@ saved_CFLAGS="${CFLAGS}" CC="${CC_FOR_BUILD}" CFLAGS="${CFLAGS_FOR_BUILD}" \ + LDFLAGS="${LDFLAGS_FOR_BUILD}" \ - ${realsrcdir}/configure \ + CONFIG_SITE= ${realsrcdir}/configure --cache-file=./other.cache \ --enable-languages=${enable_languages-all} \ --target=$target_alias --host=$build_alias --build=$build_alias CFLAGS="${saved_CFLAGS}" -Index: gcc-4.3.1/gcc/configure.ac +Index: gcc-4.4.1/gcc/configure =================================================================== ---- gcc-4.3.1.orig/gcc/configure.ac 2008-08-20 00:27:57.000000000 -0700 -+++ gcc-4.3.1/gcc/configure.ac 2008-08-20 00:44:52.000000000 -0700 -@@ -1480,7 +1480,7 @@ else - esac +--- gcc-4.4.1.orig/gcc/configure 2009-03-24 10:46:03.000000000 -0700 ++++ gcc-4.4.1/gcc/configure 2009-09-04 19:25:37.831459717 -0700 +@@ -13531,7 +13531,7 @@ saved_CFLAGS="${CFLAGS}" CC="${CC_FOR_BUILD}" CFLAGS="${CFLAGS_FOR_BUILD}" \ + LDFLAGS="${LDFLAGS_FOR_BUILD}" \ - ${realsrcdir}/configure \ + CONFIG_SITE= ${realsrcdir}/configure --cache-file=./other.cache \ --enable-languages=${enable_languages-all} \ diff --git a/recipes/gcc/gcc-4.4.1/gcc-flags-for-build.patch b/recipes/gcc/gcc-4.4.1/gcc-flags-for-build.patch index 43a9d73dcf..5193abecdb 100644 --- a/recipes/gcc/gcc-4.4.1/gcc-flags-for-build.patch +++ b/recipes/gcc/gcc-4.4.1/gcc-flags-for-build.patch @@ -1,8 +1,8 @@ -Index: gcc-4.3.2/Makefile.def +Index: gcc-4.4.1/Makefile.def =================================================================== ---- gcc-4.3.2.orig/Makefile.def 2008-08-28 18:21:19.000000000 -0700 -+++ gcc-4.3.2/Makefile.def 2008-08-28 18:21:41.000000000 -0700 -@@ -207,6 +207,7 @@ +--- gcc-4.4.1.orig/Makefile.def 2009-04-24 21:10:29.000000000 -0700 ++++ gcc-4.4.1/Makefile.def 2009-09-04 19:48:48.544457885 -0700 +@@ -227,6 +227,7 @@ flags_to_pass = { flag= BISON ; }; flags_to_pass = { flag= CC_FOR_BUILD ; }; flags_to_pass = { flag= CFLAGS_FOR_BUILD ; }; @@ -10,11 +10,11 @@ Index: gcc-4.3.2/Makefile.def flags_to_pass = { flag= CXX_FOR_BUILD ; }; flags_to_pass = { flag= EXPECT ; }; flags_to_pass = { flag= FLEX ; }; -Index: gcc-4.3.2/gcc/Makefile.in +Index: gcc-4.4.1/gcc/Makefile.in =================================================================== ---- gcc-4.3.2.orig/gcc/Makefile.in 2008-08-28 18:21:20.000000000 -0700 -+++ gcc-4.3.2/gcc/Makefile.in 2008-08-28 18:21:41.000000000 -0700 -@@ -673,7 +673,7 @@ +--- gcc-4.4.1.orig/gcc/Makefile.in 2009-05-21 16:17:37.000000000 -0700 ++++ gcc-4.4.1/gcc/Makefile.in 2009-09-04 19:48:48.544457885 -0700 +@@ -695,7 +695,7 @@ # Native linker and preprocessor flags. For x-fragment overrides. BUILD_LDFLAGS=@BUILD_LDFLAGS@ @@ -23,11 +23,11 @@ Index: gcc-4.3.2/gcc/Makefile.in # Actual name to use when installing a native compiler. GCC_INSTALL_NAME := $(shell echo gcc|sed '$(program_transform_name)') -Index: gcc-4.3.2/gcc/configure.ac +Index: gcc-4.4.1/gcc/configure.ac =================================================================== ---- gcc-4.3.2.orig/gcc/configure.ac 2008-08-28 18:21:20.000000000 -0700 -+++ gcc-4.3.2/gcc/configure.ac 2008-08-28 18:21:41.000000000 -0700 -@@ -1775,10 +1775,11 @@ +--- gcc-4.4.1.orig/gcc/configure.ac 2009-09-04 19:44:39.460457838 -0700 ++++ gcc-4.4.1/gcc/configure.ac 2009-09-04 19:48:48.548458814 -0700 +@@ -1745,10 +1745,11 @@ # Also, we cannot run fixincludes or fix-header. # These are the normal (build=host) settings: @@ -43,7 +43,7 @@ Index: gcc-4.3.2/gcc/configure.ac # Possibly disable fixproto, on a per-target basis. case ${use_fixproto} in -@@ -1796,6 +1797,7 @@ +@@ -1766,6 +1767,7 @@ then BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)' BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)' @@ -51,11 +51,11 @@ Index: gcc-4.3.2/gcc/configure.ac if test "x$TARGET_SYSTEM_ROOT" = x; then if test "x$STMP_FIXPROTO" != x; then -Index: gcc-4.3.2/Makefile.in +Index: gcc-4.4.1/Makefile.in =================================================================== ---- gcc-4.3.2.orig/Makefile.in 2008-08-28 18:21:20.000000000 -0700 -+++ gcc-4.3.2/Makefile.in 2008-08-28 18:21:41.000000000 -0700 -@@ -272,6 +272,7 @@ +--- gcc-4.4.1.orig/Makefile.in 2009-04-24 21:10:29.000000000 -0700 ++++ gcc-4.4.1/Makefile.in 2009-09-04 19:48:48.560478778 -0700 +@@ -288,6 +288,7 @@ AS_FOR_BUILD = @AS_FOR_BUILD@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ @@ -63,7 +63,7 @@ Index: gcc-4.3.2/Makefile.in CXXFLAGS_FOR_BUILD = @CXXFLAGS_FOR_BUILD@ CXX_FOR_BUILD = @CXX_FOR_BUILD@ DLLTOOL_FOR_BUILD = @DLLTOOL_FOR_BUILD@ -@@ -502,6 +503,7 @@ +@@ -528,6 +529,7 @@ "BISON=$(BISON)" \ "CC_FOR_BUILD=$(CC_FOR_BUILD)" \ "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \ @@ -71,20 +71,20 @@ Index: gcc-4.3.2/Makefile.in "CXX_FOR_BUILD=$(CXX_FOR_BUILD)" \ "EXPECT=$(EXPECT)" \ "FLEX=$(FLEX)" \ -Index: gcc-4.3.2/gcc/configure +Index: gcc-4.4.1/gcc/configure =================================================================== ---- gcc-4.3.2.orig/gcc/configure 2008-08-28 18:21:20.000000000 -0700 -+++ gcc-4.3.2/gcc/configure 2008-08-28 18:21:50.000000000 -0700 +--- gcc-4.4.1.orig/gcc/configure 2009-09-04 19:44:39.464458137 -0700 ++++ gcc-4.4.1/gcc/configure 2009-09-04 19:50:28.600466982 -0700 @@ -458,7 +458,7 @@ # include <unistd.h> #endif" --ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP EGREP loose_warn cxx_compat_warn strict_warn warn_cflags nocommon_flag TREEBROWSER valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_decimal_float enable_fixed_point enable_shared TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR onestep PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI datarootdir docdir htmldir SET_MAKE AWK LN_S LN RANLIB ac_ct_RANLIB ranlib_flags INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON NM AR COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB TARGET_GETGROUPS_T LIBICONV LTLIBICONV LIBICONV_DEP manext objext gthread_flags extra_modes_file extra_opt_files USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT host_cc_for_libada CROSS ALL SYSTEM_HEADER_DIR inhibit_libc CC_FOR_BUILD BUILD_CFLAGS BUILD_LDFLAGS STMP_FIXINC STMP_FIXPROTO collect2 LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN ac_ct_AR STRIP ac_ct_STRIP lt_ECHO objdir enable_fast_install gcc_cv_as ORIGINAL_AS_FOR_TARGET gcc_cv_ld ORIGINAL_LD_FOR_TARGET gcc_cv_nm ORIGINAL_NM_FOR_TARGET gcc_cv_objdump libgcc_visibility GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir subdirs srcdir all_compilers all_gtfiles all_lang_makefrags all_lang_makefiles all_languages all_selected_languages build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines build_file_translate check_languages cpp_install_dir xmake_file tmake_file extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines c_target_objs cxx_target_objs target_cpu_default GMPLIBS GMPINC LIBOBJS LTLIBOBJS' -+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP EGREP loose_warn cxx_compat_warn strict_warn warn_cflags nocommon_flag TREEBROWSER valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_decimal_float enable_fixed_point enable_shared TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR onestep PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI datarootdir docdir htmldir SET_MAKE AWK LN_S LN RANLIB ac_ct_RANLIB ranlib_flags INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON NM AR COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB TARGET_GETGROUPS_T LIBICONV LTLIBICONV LIBICONV_DEP manext objext gthread_flags extra_modes_file extra_opt_files USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT host_cc_for_libada CROSS ALL SYSTEM_HEADER_DIR inhibit_libc CC_FOR_BUILD BUILD_CFLAGS BUILD_LDFLAGS BUILD_CPPFLAGS STMP_FIXINC STMP_FIXPROTO collect2 LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN ac_ct_AR STRIP ac_ct_STRIP lt_ECHO objdir enable_fast_install gcc_cv_as ORIGINAL_AS_FOR_TARGET gcc_cv_ld ORIGINAL_LD_FOR_TARGET gcc_cv_nm ORIGINAL_NM_FOR_TARGET gcc_cv_objdump libgcc_visibility GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir subdirs srcdir all_compilers all_gtfiles all_lang_makefrags all_lang_makefiles all_languages all_selected_languages build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines build_file_translate check_languages cpp_install_dir xmake_file tmake_file extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines c_target_objs cxx_target_objs target_cpu_default GMPLIBS GMPINC LIBOBJS LTLIBOBJS' +-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP EGREP loose_warn strict_warn warn_cflags nocommon_flag TREEBROWSER valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_decimal_float enable_fixed_point enable_shared TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR onestep PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI datarootdir docdir htmldir SET_MAKE AWK LN_S LN RANLIB ac_ct_RANLIB ranlib_flags INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON NM AR COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB TARGET_GETGROUPS_T LIBICONV LTLIBICONV LIBICONV_DEP manext objext gthread_flags extra_modes_file extra_opt_files USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT CROSS ALL SYSTEM_HEADER_DIR inhibit_libc CC_FOR_BUILD BUILD_CFLAGS BUILD_LDFLAGS STMP_FIXINC STMP_FIXPROTO collect2 LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN OBJDUMP ac_ct_OBJDUMP ac_ct_AR STRIP ac_ct_STRIP lt_ECHO DSYMUTIL ac_ct_DSYMUTIL NMEDIT ac_ct_NMEDIT LIPO ac_ct_LIPO OTOOL ac_ct_OTOOL OTOOL64 ac_ct_OTOOL64 objdir enable_fast_install gcc_cv_as ORIGINAL_AS_FOR_TARGET gcc_cv_ld ORIGINAL_LD_FOR_TARGET gcc_cv_nm ORIGINAL_NM_FOR_TARGET gcc_cv_objdump gcc_cv_readelf libgcc_visibility GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir subdirs srcdir all_compilers all_gtfiles all_lang_makefrags all_lang_makefiles all_languages all_selected_languages build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines build_file_translate check_languages cpp_install_dir xmake_file tmake_file extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines c_target_objs cxx_target_objs fortran_target_objs target_cpu_default GMPLIBS GMPINC PPLLIBS PPLINC CLOOGLIBS CLOOGINC LIBOBJS LTLIBOBJS' ++ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP EGREP loose_warn strict_warn warn_cflags nocommon_flag TREEBROWSER valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_decimal_float enable_fixed_point enable_shared TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR onestep PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI datarootdir docdir htmldir SET_MAKE AWK LN_S LN RANLIB ac_ct_RANLIB ranlib_flags INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON NM AR COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB TARGET_GETGROUPS_T LIBICONV LTLIBICONV LIBICONV_DEP manext objext gthread_flags extra_modes_file extra_opt_files USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT CROSS ALL SYSTEM_HEADER_DIR inhibit_libc CC_FOR_BUILD BUILD_CFLAGS BUILD_LDFLAGS BUILD_CPPFLAGS STMP_FIXINC STMP_FIXPROTO collect2 LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN OBJDUMP ac_ct_OBJDUMP ac_ct_AR STRIP ac_ct_STRIP lt_ECHO DSYMUTIL ac_ct_DSYMUTIL NMEDIT ac_ct_NMEDIT LIPO ac_ct_LIPO OTOOL ac_ct_OTOOL OTOOL64 ac_ct_OTOOL64 objdir enable_fast_install gcc_cv_as ORIGINAL_AS_FOR_TARGET gcc_cv_ld ORIGINAL_LD_FOR_TARGET gcc_cv_nm ORIGINAL_NM_FOR_TARGET gcc_cv_objdump gcc_cv_readelf libgcc_visibility GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir subdirs srcdir all_compilers all_gtfiles all_lang_makefrags all_lang_makefiles all_languages all_selected_languages build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines build_file_translate check_languages cpp_install_dir xmake_file tmake_file extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines c_target_objs cxx_target_objs fortran_target_objs target_cpu_default GMPLIBS GMPINC PPLLIBS PPLINC CLOOGLIBS CLOOGINC LIBOBJS LTLIBOBJS' ac_subst_files='language_hooks' + ac_pwd=`pwd` - # Initialize some variables set by options. -@@ -13471,6 +13471,7 @@ +@@ -14025,6 +14025,7 @@ CC_FOR_BUILD='$(CC)' BUILD_CFLAGS='$(ALL_CFLAGS)' BUILD_LDFLAGS='$(LDFLAGS)' @@ -92,7 +92,7 @@ Index: gcc-4.3.2/gcc/configure STMP_FIXINC=stmp-fixinc # Possibly disable fixproto, on a per-target basis. -@@ -13489,6 +13490,7 @@ +@@ -14043,6 +14044,7 @@ then BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)' BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)' @@ -100,107 +100,107 @@ Index: gcc-4.3.2/gcc/configure if test "x$TARGET_SYSTEM_ROOT" = x; then if test "x$STMP_FIXPROTO" != x; then -@@ -14067,13 +14069,13 @@ +@@ -14509,13 +14511,13 @@ else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext -- (eval echo "\"\$as_me:14070: $ac_compile\"" >&5) -+ (eval echo "\"\$as_me:14072: $ac_compile\"" >&5) +- (eval echo "\"\$as_me:14512: $ac_compile\"" >&5) ++ (eval echo "\"\$as_me:14514: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 -- (eval echo "\"\$as_me:14073: $NM \\\"conftest.$ac_objext\\\"\"" >&5) -+ (eval echo "\"\$as_me:14075: $NM \\\"conftest.$ac_objext\\\"\"" >&5) +- (eval echo "\"\$as_me:14515: $NM \\\"conftest.$ac_objext\\\"\"" >&5) ++ (eval echo "\"\$as_me:14517: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 -- (eval echo "\"\$as_me:14076: output\"" >&5) -+ (eval echo "\"\$as_me:14078: output\"" >&5) +- (eval echo "\"\$as_me:14518: output\"" >&5) ++ (eval echo "\"\$as_me:14520: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" -@@ -15128,7 +15130,7 @@ +@@ -15672,7 +15674,7 @@ ;; *-*-irix6*) # Find out which ABI we are using. -- echo '#line 15131 "configure"' > conftest.$ac_ext -+ echo '#line 15133 "configure"' > conftest.$ac_ext +- echo '#line 15675 "configure"' > conftest.$ac_ext ++ echo '#line 15677 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? -@@ -15748,11 +15750,11 @@ +@@ -16971,11 +16973,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` -- (eval echo "\"\$as_me:15751: $lt_compile\"" >&5) -+ (eval echo "\"\$as_me:15753: $lt_compile\"" >&5) +- (eval echo "\"\$as_me:16974: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:16976: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 -- echo "$as_me:15755: \$? = $ac_status" >&5 -+ echo "$as_me:15757: \$? = $ac_status" >&5 +- echo "$as_me:16978: \$? = $ac_status" >&5 ++ echo "$as_me:16980: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. -@@ -16070,11 +16072,11 @@ +@@ -17310,11 +17312,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` -- (eval echo "\"\$as_me:16073: $lt_compile\"" >&5) -+ (eval echo "\"\$as_me:16075: $lt_compile\"" >&5) +- (eval echo "\"\$as_me:17313: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:17315: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 -- echo "$as_me:16077: \$? = $ac_status" >&5 -+ echo "$as_me:16079: \$? = $ac_status" >&5 +- echo "$as_me:17317: \$? = $ac_status" >&5 ++ echo "$as_me:17319: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. -@@ -16175,11 +16177,11 @@ +@@ -17415,11 +17417,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` -- (eval echo "\"\$as_me:16178: $lt_compile\"" >&5) -+ (eval echo "\"\$as_me:16180: $lt_compile\"" >&5) +- (eval echo "\"\$as_me:17418: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:17420: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 -- echo "$as_me:16182: \$? = $ac_status" >&5 -+ echo "$as_me:16184: \$? = $ac_status" >&5 +- echo "$as_me:17422: \$? = $ac_status" >&5 ++ echo "$as_me:17424: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized -@@ -16230,11 +16232,11 @@ +@@ -17470,11 +17472,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` -- (eval echo "\"\$as_me:16233: $lt_compile\"" >&5) -+ (eval echo "\"\$as_me:16235: $lt_compile\"" >&5) +- (eval echo "\"\$as_me:17473: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:17475: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 -- echo "$as_me:16237: \$? = $ac_status" >&5 -+ echo "$as_me:16239: \$? = $ac_status" >&5 +- echo "$as_me:17477: \$? = $ac_status" >&5 ++ echo "$as_me:17479: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized -@@ -19027,7 +19029,7 @@ +@@ -20282,7 +20284,7 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF --#line 19030 "configure" -+#line 19032 "configure" +-#line 20285 "configure" ++#line 20287 "configure" #include "confdefs.h" #if HAVE_DLFCN_H -@@ -19127,7 +19129,7 @@ +@@ -20378,7 +20380,7 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF --#line 19130 "configure" -+#line 19132 "configure" +-#line 20381 "configure" ++#line 20383 "configure" #include "confdefs.h" #if HAVE_DLFCN_H -@@ -23938,6 +23940,7 @@ +@@ -25544,6 +25546,7 @@ s,@CC_FOR_BUILD@,$CC_FOR_BUILD,;t t s,@BUILD_CFLAGS@,$BUILD_CFLAGS,;t t s,@BUILD_LDFLAGS@,$BUILD_LDFLAGS,;t t @@ -208,11 +208,11 @@ Index: gcc-4.3.2/gcc/configure s,@STMP_FIXINC@,$STMP_FIXINC,;t t s,@STMP_FIXPROTO@,$STMP_FIXPROTO,;t t s,@collect2@,$collect2,;t t -Index: gcc-4.3.2/Makefile.tpl +Index: gcc-4.4.1/Makefile.tpl =================================================================== ---- gcc-4.3.2.orig/Makefile.tpl 2008-08-28 18:21:20.000000000 -0700 -+++ gcc-4.3.2/Makefile.tpl 2008-08-28 18:21:41.000000000 -0700 -@@ -275,6 +275,7 @@ +--- gcc-4.4.1.orig/Makefile.tpl 2009-04-14 01:57:33.000000000 -0700 ++++ gcc-4.4.1/Makefile.tpl 2009-09-04 19:48:48.572480864 -0700 +@@ -291,6 +291,7 @@ AS_FOR_BUILD = @AS_FOR_BUILD@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ @@ -220,20 +220,20 @@ Index: gcc-4.3.2/Makefile.tpl CXXFLAGS_FOR_BUILD = @CXXFLAGS_FOR_BUILD@ CXX_FOR_BUILD = @CXX_FOR_BUILD@ DLLTOOL_FOR_BUILD = @DLLTOOL_FOR_BUILD@ -Index: gcc-4.3.2/configure +Index: gcc-4.4.1/configure =================================================================== ---- gcc-4.3.2.orig/configure 2008-08-28 18:21:20.000000000 -0700 -+++ gcc-4.3.2/configure 2008-08-28 18:21:41.000000000 -0700 +--- gcc-4.4.1.orig/configure 2009-09-04 19:44:36.588457634 -0700 ++++ gcc-4.4.1/configure 2009-09-04 19:50:39.904468246 -0700 @@ -272,7 +272,7 @@ PACKAGE_BUGREPORT= ac_unique_file="move-if-change" --ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os build_noncanonical host_noncanonical target_noncanonical host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN LN_S TOPLEVEL_CONFIGURE_ARGUMENTS build_libsubdir build_subdir host_subdir target_subdir CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE do_compare gmplibs gmpinc stage1_languages SYSROOT_CFLAGS_FOR_TARGET DEBUG_PREFIX_CFLAGS_FOR_TARGET CFLAGS_FOR_TARGET CXXFLAGS_FOR_TARGET RPATH_ENVVAR tooldir build_tooldir CONFIGURE_GDB_TK GDB_TK INSTALL_GDB_TK build_configargs build_configdirs host_configargs configdirs target_configargs AR_FOR_BUILD AS_FOR_BUILD CC_FOR_BUILD CFLAGS_FOR_BUILD CXXFLAGS_FOR_BUILD CXX_FOR_BUILD DLLTOOL_FOR_BUILD GCJ_FOR_BUILD GFORTRAN_FOR_BUILD LDFLAGS_FOR_BUILD LD_FOR_BUILD NM_FOR_BUILD RANLIB_FOR_BUILD WINDMC_FOR_BUILD WINDRES_FOR_BUILD config_shell YACC BISON M4 LEX FLEX MAKEINFO EXPECT RUNTEST AR AS DLLTOOL LD LIPO NM RANLIB STRIP WINDRES WINDMC OBJCOPY OBJDUMP CC_FOR_TARGET CXX_FOR_TARGET GCC_FOR_TARGET GCJ_FOR_TARGET GFORTRAN_FOR_TARGET AR_FOR_TARGET AS_FOR_TARGET DLLTOOL_FOR_TARGET LD_FOR_TARGET LIPO_FOR_TARGET NM_FOR_TARGET OBJDUMP_FOR_TARGET RANLIB_FOR_TARGET STRIP_FOR_TARGET WINDRES_FOR_TARGET WINDMC_FOR_TARGET RAW_CXX_FOR_TARGET FLAGS_FOR_TARGET COMPILER_AS_FOR_TARGET COMPILER_LD_FOR_TARGET COMPILER_NM_FOR_TARGET MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT stage1_cflags stage1_checking stage2_werror_flag datarootdir docdir pdfdir htmldir LIBOBJS LTLIBOBJS' -+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os build_noncanonical host_noncanonical target_noncanonical host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN LN_S TOPLEVEL_CONFIGURE_ARGUMENTS build_libsubdir build_subdir host_subdir target_subdir CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE do_compare gmplibs gmpinc stage1_languages SYSROOT_CFLAGS_FOR_TARGET DEBUG_PREFIX_CFLAGS_FOR_TARGET CFLAGS_FOR_TARGET CXXFLAGS_FOR_TARGET RPATH_ENVVAR tooldir build_tooldir CONFIGURE_GDB_TK GDB_TK INSTALL_GDB_TK build_configargs build_configdirs host_configargs configdirs target_configargs AR_FOR_BUILD AS_FOR_BUILD CC_FOR_BUILD CFLAGS_FOR_BUILD CPPFLAGS_FOR_BUILD CXXFLAGS_FOR_BUILD CXX_FOR_BUILD DLLTOOL_FOR_BUILD GCJ_FOR_BUILD GFORTRAN_FOR_BUILD LDFLAGS_FOR_BUILD LD_FOR_BUILD NM_FOR_BUILD RANLIB_FOR_BUILD WINDMC_FOR_BUILD WINDRES_FOR_BUILD config_shell YACC BISON M4 LEX FLEX MAKEINFO EXPECT RUNTEST AR AS DLLTOOL LD LIPO NM RANLIB STRIP WINDRES WINDMC OBJCOPY OBJDUMP CC_FOR_TARGET CXX_FOR_TARGET GCC_FOR_TARGET GCJ_FOR_TARGET GFORTRAN_FOR_TARGET AR_FOR_TARGET AS_FOR_TARGET DLLTOOL_FOR_TARGET LD_FOR_TARGET LIPO_FOR_TARGET NM_FOR_TARGET OBJDUMP_FOR_TARGET RANLIB_FOR_TARGET STRIP_FOR_TARGET WINDRES_FOR_TARGET WINDMC_FOR_TARGET RAW_CXX_FOR_TARGET FLAGS_FOR_TARGET COMPILER_AS_FOR_TARGET COMPILER_LD_FOR_TARGET COMPILER_NM_FOR_TARGET MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT stage1_cflags stage1_checking stage2_werror_flag datarootdir docdir pdfdir htmldir LIBOBJS LTLIBOBJS' +-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS TOPLEVEL_CONFIGURE_ARGUMENTS build build_cpu build_vendor build_os build_noncanonical host_noncanonical target_noncanonical host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN LN_S build_libsubdir build_subdir host_subdir target_subdir CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE do_compare gmplibs gmpinc extra_mpfr_configure_flags ppllibs pplinc clooglibs clooginc stage1_languages SYSROOT_CFLAGS_FOR_TARGET DEBUG_PREFIX_CFLAGS_FOR_TARGET CFLAGS_FOR_TARGET CXXFLAGS_FOR_TARGET RPATH_ENVVAR GCC_SHLIB_SUBDIR tooldir build_tooldir CONFIGURE_GDB_TK GDB_TK INSTALL_GDB_TK build_configargs build_configdirs host_configargs configdirs target_configargs AR_FOR_BUILD AS_FOR_BUILD CC_FOR_BUILD CFLAGS_FOR_BUILD CXXFLAGS_FOR_BUILD CXX_FOR_BUILD DLLTOOL_FOR_BUILD GCJ_FOR_BUILD GFORTRAN_FOR_BUILD LDFLAGS_FOR_BUILD LD_FOR_BUILD NM_FOR_BUILD RANLIB_FOR_BUILD WINDMC_FOR_BUILD WINDRES_FOR_BUILD config_shell YACC BISON M4 LEX FLEX MAKEINFO EXPECT RUNTEST AR AS DLLTOOL LD LIPO NM RANLIB STRIP WINDRES WINDMC OBJCOPY OBJDUMP CC_FOR_TARGET CXX_FOR_TARGET GCC_FOR_TARGET GCJ_FOR_TARGET GFORTRAN_FOR_TARGET AR_FOR_TARGET AS_FOR_TARGET DLLTOOL_FOR_TARGET LD_FOR_TARGET LIPO_FOR_TARGET NM_FOR_TARGET OBJDUMP_FOR_TARGET RANLIB_FOR_TARGET STRIP_FOR_TARGET WINDRES_FOR_TARGET WINDMC_FOR_TARGET RAW_CXX_FOR_TARGET FLAGS_FOR_TARGET COMPILER_AS_FOR_TARGET COMPILER_LD_FOR_TARGET COMPILER_NM_FOR_TARGET MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT stage1_cflags stage1_checking stage2_werror_flag datarootdir docdir pdfdir htmldir LIBOBJS LTLIBOBJS' ++ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS TOPLEVEL_CONFIGURE_ARGUMENTS build build_cpu build_vendor build_os build_noncanonical host_noncanonical target_noncanonical host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN LN_S build_libsubdir build_subdir host_subdir target_subdir CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE do_compare gmplibs gmpinc extra_mpfr_configure_flags ppllibs pplinc clooglibs clooginc stage1_languages SYSROOT_CFLAGS_FOR_TARGET DEBUG_PREFIX_CFLAGS_FOR_TARGET CFLAGS_FOR_TARGET CXXFLAGS_FOR_TARGET RPATH_ENVVAR GCC_SHLIB_SUBDIR tooldir build_tooldir CONFIGURE_GDB_TK GDB_TK INSTALL_GDB_TK build_configargs build_configdirs host_configargs configdirs target_configargs AR_FOR_BUILD AS_FOR_BUILD CC_FOR_BUILD CFLAGS_FOR_BUILD CPPFLAGS_FOR_BUILD CXXFLAGS_FOR_BUILD CXX_FOR_BUILD DLLTOOL_FOR_BUILD GCJ_FOR_BUILD GFORTRAN_FOR_BUILD LDFLAGS_FOR_BUILD LD_FOR_BUILD NM_FOR_BUILD RANLIB_FOR_BUILD WINDMC_FOR_BUILD WINDRES_FOR_BUILD config_shell YACC BISON M4 LEX FLEX MAKEINFO EXPECT RUNTEST AR AS DLLTOOL LD LIPO NM RANLIB STRIP WINDRES WINDMC OBJCOPY OBJDUMP CC_FOR_TARGET CXX_FOR_TARGET GCC_FOR_TARGET GCJ_FOR_TARGET GFORTRAN_FOR_TARGET AR_FOR_TARGET AS_FOR_TARGET DLLTOOL_FOR_TARGET LD_FOR_TARGET LIPO_FOR_TARGET NM_FOR_TARGET OBJDUMP_FOR_TARGET RANLIB_FOR_TARGET STRIP_FOR_TARGET WINDRES_FOR_TARGET WINDMC_FOR_TARGET RAW_CXX_FOR_TARGET FLAGS_FOR_TARGET COMPILER_AS_FOR_TARGET COMPILER_LD_FOR_TARGET COMPILER_NM_FOR_TARGET MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT stage1_cflags stage1_checking stage2_werror_flag datarootdir docdir pdfdir htmldir LIBOBJS LTLIBOBJS' ac_subst_files='serialization_dependencies host_makefile_frag target_makefile_frag alphaieee_frag ospace_frag' + ac_pwd=`pwd` - # Initialize some variables set by options. -@@ -5914,6 +5914,7 @@ +@@ -6312,6 +6312,7 @@ # our build compiler if desired. if test x"${build}" = x"${host}" ; then CFLAGS_FOR_BUILD=${CFLAGS_FOR_BUILD-${CFLAGS}} @@ -241,7 +241,7 @@ Index: gcc-4.3.2/configure CXXFLAGS_FOR_BUILD=${CXXFLAGS_FOR_BUILD-${CXXFLAGS}} LDFLAGS_FOR_BUILD=${LDFLAGS_FOR_BUILD-${LDFLAGS}} fi -@@ -5991,6 +5992,7 @@ +@@ -6390,6 +6391,7 @@ @@ -249,7 +249,7 @@ Index: gcc-4.3.2/configure # Generate default definitions for YACC, M4, LEX and other programs that run # on the build machine. These are used if the Makefile can't locate these # programs in objdir. -@@ -12874,6 +12876,7 @@ +@@ -13279,6 +13281,7 @@ s,@AS_FOR_BUILD@,$AS_FOR_BUILD,;t t s,@CC_FOR_BUILD@,$CC_FOR_BUILD,;t t s,@CFLAGS_FOR_BUILD@,$CFLAGS_FOR_BUILD,;t t @@ -257,11 +257,11 @@ Index: gcc-4.3.2/configure s,@CXXFLAGS_FOR_BUILD@,$CXXFLAGS_FOR_BUILD,;t t s,@CXX_FOR_BUILD@,$CXX_FOR_BUILD,;t t s,@DLLTOOL_FOR_BUILD@,$DLLTOOL_FOR_BUILD,;t t -Index: gcc-4.3.2/configure.ac +Index: gcc-4.4.1/configure.ac =================================================================== ---- gcc-4.3.2.orig/configure.ac 2008-08-28 18:21:20.000000000 -0700 -+++ gcc-4.3.2/configure.ac 2008-08-28 18:21:41.000000000 -0700 -@@ -2425,6 +2425,7 @@ +--- gcc-4.4.1.orig/configure.ac 2009-09-04 19:44:36.584475215 -0700 ++++ gcc-4.4.1/configure.ac 2009-09-04 19:48:48.576467893 -0700 +@@ -2613,6 +2613,7 @@ # our build compiler if desired. if test x"${build}" = x"${host}" ; then CFLAGS_FOR_BUILD=${CFLAGS_FOR_BUILD-${CFLAGS}} @@ -269,7 +269,7 @@ Index: gcc-4.3.2/configure.ac CXXFLAGS_FOR_BUILD=${CXXFLAGS_FOR_BUILD-${CXXFLAGS}} LDFLAGS_FOR_BUILD=${LDFLAGS_FOR_BUILD-${LDFLAGS}} fi -@@ -2489,6 +2490,7 @@ +@@ -2678,6 +2679,7 @@ AC_SUBST(AS_FOR_BUILD) AC_SUBST(CC_FOR_BUILD) AC_SUBST(CFLAGS_FOR_BUILD) diff --git a/recipes/gcc/gcc-configure-canadian-sdk.inc b/recipes/gcc/gcc-configure-canadian-sdk.inc index 738b120a45..83ae6f548d 100644 --- a/recipes/gcc/gcc-configure-canadian-sdk.inc +++ b/recipes/gcc/gcc-configure-canadian-sdk.inc @@ -1,7 +1,7 @@ require gcc-configure-common.inc USE_NLS = '${@base_conditional( "TARGET_OS", "linux-uclibc", "no", "", d )}' -USE_NLS = '${@base_conditional( "TARGET_OS", "linux-uclibcgnueabi", "no", "", d )}' +USE_NLS = '${@base_conditional( "TARGET_OS", "linux-uclibceabi", "no", "", d )}' # # We need to override this and make sure the compiler can find staging diff --git a/recipes/gcc/gcc-configure-common.inc b/recipes/gcc/gcc-configure-common.inc index 9363585de1..1c605a132d 100644 --- a/recipes/gcc/gcc-configure-common.inc +++ b/recipes/gcc/gcc-configure-common.inc @@ -9,7 +9,7 @@ JAVA_arm ?= "" JAVA_armeb ?= "" JAVA_mipsel ?= "" JAVA_sh3 ?= "" -OBJC_linux-uclibcgnueabi ?= "" +OBJC_linux-uclibceabi ?= "" OBJC_linux-uclibc ?= "" OBJC_avr ?= "" OBJC ?= ",objc" @@ -41,7 +41,7 @@ EXTRA_OECONF = "${@['--enable-clocale=generic', ''][bb.data.getVar('USE_NLS', d, EXTRA_OECONF_append_linux = " --enable-__cxa_atexit" EXTRA_OECONF_append_linux-gnueabi = " --enable-__cxa_atexit" EXTRA_OECONF_append_linux-uclibc = " --disable-__cxa_atexit" -EXTRA_OECONF_append_linux-uclibcgnueabi = " --disable-__cxa_atexit" +EXTRA_OECONF_append_linux-uclibceabi = " --disable-__cxa_atexit" EXTRA_OECONF_FPU = "${@get_gcc_fpu_setting(bb, d)}" CPPFLAGS = "" diff --git a/recipes/gcc/gcc-configure-sdk.inc b/recipes/gcc/gcc-configure-sdk.inc index d04f6080ee..205b1067ef 100644 --- a/recipes/gcc/gcc-configure-sdk.inc +++ b/recipes/gcc/gcc-configure-sdk.inc @@ -2,7 +2,7 @@ require gcc-configure-common.inc # The two lines below conflict, this needs fixing - RP USE_NLS = '${@base_conditional( "TARGET_OS", "linux-uclibc", "no", "", d )}' -USE_NLS = '${@base_conditional( "TARGET_OS", "linux-uclibcgnueabi", "no", "", d )}' +USE_NLS = '${@base_conditional( "TARGET_OS", "linux-uclibceabi", "no", "", d )}' EXTRA_OECONF_PATHS = "--with-sysroot=${prefix}/${TARGET_SYS} \ --with-build-time-tools=${CROSS_DIR}/${TARGET_SYS}/bin \ diff --git a/recipes/gettext/gettext_0.14.1.bb b/recipes/gettext/gettext_0.14.1.bb index 30fb92d351..b383525d88 100644 --- a/recipes/gettext/gettext_0.14.1.bb +++ b/recipes/gettext/gettext_0.14.1.bb @@ -15,7 +15,7 @@ SRC_URI = "${GNU_MIRROR}/gettext/gettext-${PV}.tar.gz \ file://disable_java.patch;patch=1" SRC_URI_append_linux-uclibc = " file://gettext-error_print_progname.patch;patch=1" -SRC_URI_append_linux-uclibcgnueabi = " file://gettext-error_print_progname.patch;patch=1" +SRC_URI_append_linux-uclibceabi = " file://gettext-error_print_progname.patch;patch=1" PARALLEL_MAKE = "" diff --git a/recipes/gettext/gettext_0.17.bb b/recipes/gettext/gettext_0.17.bb index 04dee4c4f2..9f9f695b6a 100644 --- a/recipes/gettext/gettext_0.17.bb +++ b/recipes/gettext/gettext_0.17.bb @@ -14,7 +14,7 @@ SRC_URI = "${GNU_MIRROR}/gettext/gettext-${PV}.tar.gz \ " SRC_URI_append_linux-uclibc = " file://gettext-error_print_progname.patch;patch=1" -SRC_URI_append_linux-uclibcgnueabi = " file://gettext-error_print_progname.patch;patch=1" +SRC_URI_append_linux-uclibceabi = " file://gettext-error_print_progname.patch;patch=1" PARALLEL_MAKE = "" diff --git a/recipes/gnome/gnome-keyring_2.26.0.bb b/recipes/gnome/gnome-keyring_2.26.0.bb index abec0f1b38..b954d1af76 100644 --- a/recipes/gnome/gnome-keyring_2.26.0.bb +++ b/recipes/gnome/gnome-keyring_2.26.0.bb @@ -3,7 +3,6 @@ SECTION = "x11/gnome" inherit autotools gnome pkgconfig -DEPENDS = "gconf-dbus gtk+ libtasn1 libtasn1-native libgcrypt" DEPENDS = " libpam gconf gtk+ libtasn1 libtasn1-native libgcrypt" EXTRA_OECONF = "--disable-gtk-doc" diff --git a/recipes/gnome/libunique_1.1.2.bb b/recipes/gnome/libunique_1.1.2.bb new file mode 100644 index 0000000000..c0fbee73be --- /dev/null +++ b/recipes/gnome/libunique_1.1.2.bb @@ -0,0 +1,11 @@ +LICENSE = "LGPL" +SECTION = "x11/gnome" + +inherit autotools_stage gnome lib_package + +DEPENDS = "gtk+ dbus" + +do_configure_prepend() { + sed -i -e 's: doc : :g' ${S}/Makefile.am +} + diff --git a/recipes/gnome/orbit2-2.14.17/configure-lossage.patch b/recipes/gnome/orbit2-2.14.17/configure-lossage.patch new file mode 100644 index 0000000000..5fc1de5610 --- /dev/null +++ b/recipes/gnome/orbit2-2.14.17/configure-lossage.patch @@ -0,0 +1,37 @@ +--- ORBit2-2.14.17/configure.in-orig 2009-01-10 09:36:18.000000000 -0800 ++++ ORBit2-2.14.17/configure.in 2009-06-17 15:10:59.000000000 -0700 +@@ -217,20 +217,20 @@ dnl + dnl So many people with broken linking setups asked about this + dnl it turned out to be necessary to check for this. + dnl +-dofus_save_libs="$LIBS" +-LIBS="$ORBIT_LIBS $LIBS" +-AC_TRY_RUN([ #include <stdio.h> +- main () +- { +- return 0; +- } ],, +- AC_MSG_ERROR([ +-Linking is badly borked on your system. Please ensure your library path is correct +-Check config.log for details - check near the end of the log above 'failed program was' +-Alternatively ensure that your /etc/ld.so.conf (and/or LD_LIBRARY_PATH) includes the +-prefix you're compiling on: '${prefix}' ]), +-AC_MSG_WARN([Could not check for borked linking while cross-compiling])) +-LIBS="$dofus_save_libs" ++dnl dofus_save_libs="$LIBS" ++dnl LIBS="$ORBIT_LIBS $LIBS" ++dnl AC_TRY_RUN([ #include <stdio.h> ++dnl main () ++dnl { ++dnl return 0; ++dnl } ],, ++dnl AC_MSG_ERROR([ ++dnl Linking is badly borked on your system. Please ensure your library path is correct ++dnl Check config.log for details - check near the end of the log above 'failed program was' ++dnl Alternatively ensure that your /etc/ld.so.conf (and/or LD_LIBRARY_PATH) includes the ++dnl prefix you're compiling on: '${prefix}' ]), ++dnl AC_MSG_WARN([Could not check for borked linking while cross-compiling])) ++dnl LIBS="$dofus_save_libs" + + orig_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $ORBIT_CFLAGS" diff --git a/recipes/gnome/orbit2.inc b/recipes/gnome/orbit2.inc new file mode 100644 index 0000000000..5f6e6f6105 --- /dev/null +++ b/recipes/gnome/orbit2.inc @@ -0,0 +1,46 @@ +LICENSE = "GPL" +DESCRIPTION = "CORBA ORB" +SECTION = "x11/gnome/libs" +SRC_URI = "http://ftp.gnome.org/pub/GNOME/sources/ORBit2/2.14/ORBit2-${PV}.tar.bz2 \ + file://configure-lossage.patch;patch=1;pnum=1 \ + file://pkgconfig-fix.patch;patch=1 \ + file://gtk-doc.m4 \ + file://gtk-doc.make" +DEPENDS = "libidl popt orbit2-native gtk-doc" +PARALLEL_MAKE = "" + +FILES_${PN} += "${libdir}/orbit-2.0/*.so" +FILES_${PN}-dev += "${libdir}/orbit-2.0/*.a ${libdir}/orbit-2.0/*.la" +FILES_${PN}-dbg += "${libdir}/orbit-2.0/.debug" + +S = "${WORKDIR}/ORBit2-${PV}" + +LEAD_SONAME = "libORBit-2.so" + +inherit autotools pkgconfig + +EXTRA_OECONF = "--disable-gtk-doc" +EXTRA_OEMAKE = "IDL_COMPILER='${STAGING_BINDIR_NATIVE}/orbit-idl-2'" + +do_configure_prepend() { + mkdir -p m4 + install ${WORKDIR}/gtk-doc.m4 ./m4/ + install ${WORKDIR}/gtk-doc.make ./ +} + +do_stage() { + oe_libinstall -so -C src/orb libORBit-2 ${STAGING_LIBDIR} + oe_libinstall -so -C src/services/name libORBitCosNaming-2 ${STAGING_LIBDIR} + oe_libinstall -so -C src/services/imodule libORBit-imodule-2 ${STAGING_LIBDIR} + install -m 0644 src/services/name/libname-server-2.a ${STAGING_LIBDIR}/ + + for dir in orbit orbit/poa orbit/orb-core orbit/util orbit/dynamic; do + install -d ${STAGING_INCDIR}/orbit-2.0/$dir + ( cd include/$dir; for i in *.h; do install -m 0644 $i ${STAGING_INCDIR}/orbit-2.0/$dir/$i; done ) + done + + install -d ${STAGING_INCDIR}/orbit-2.0/ORBitservices + install -m 0644 src/services/name/CosNaming.h ${STAGING_INCDIR}/orbit-2.0/ORBitservices/ + install -m 0644 src/services/name/CosNaming_impl.h ${STAGING_INCDIR}/orbit-2.0/ORBitservices/ + install -m 0644 src/services/imodule/orbit-imodule.h ${STAGING_INCDIR}/orbit-2.0/ORBitservices/ +} diff --git a/recipes/gnome/orbit2_2.14.12.bb b/recipes/gnome/orbit2_2.14.12.bb index 140776114d..7afc82479a 100644 --- a/recipes/gnome/orbit2_2.14.12.bb +++ b/recipes/gnome/orbit2_2.14.12.bb @@ -1,47 +1,4 @@ -LICENSE = "GPL" -PR = "r1" -DESCRIPTION = "CORBA ORB" -SECTION = "x11/gnome/libs" -SRC_URI = "http://ftp.gnome.org/pub/GNOME/sources/ORBit2/2.14/ORBit2-${PV}.tar.bz2 \ - file://configure-lossage.patch;patch=1;pnum=1 \ - file://pkgconfig-fix.patch;patch=1 \ - file://gtk-doc.m4 \ - file://gtk-doc.make" -DEPENDS = "libidl popt orbit2-native gtk-doc" -PARALLEL_MAKE = "" - -FILES_${PN} += "${libdir}/orbit-2.0/*.so" -FILES_${PN}-dev += "${libdir}/orbit-2.0/*.a ${libdir}/orbit-2.0/*.la" -FILES_${PN}-dbg += "${libdir}/orbit-2.0/.debug" - -S = "${WORKDIR}/ORBit2-${PV}" - -LEAD_SONAME = "libORBit-2.so" - -inherit autotools pkgconfig +require orbit2.inc -EXTRA_OECONF = "--disable-gtk-doc" -EXTRA_OEMAKE = "IDL_COMPILER='${STAGING_BINDIR_NATIVE}/orbit-idl-2'" - -do_configure_prepend() { - mkdir -p m4 - install ${WORKDIR}/gtk-doc.m4 ./m4/ - install ${WORKDIR}/gtk-doc.make ./ -} - -do_stage() { - oe_libinstall -so -C src/orb libORBit-2 ${STAGING_LIBDIR} - oe_libinstall -so -C src/services/name libORBitCosNaming-2 ${STAGING_LIBDIR} - oe_libinstall -so -C src/services/imodule libORBit-imodule-2 ${STAGING_LIBDIR} - install -m 0644 src/services/name/libname-server-2.a ${STAGING_LIBDIR}/ - - for dir in orbit orbit/poa orbit/orb-core orbit/util orbit/dynamic; do - install -d ${STAGING_INCDIR}/orbit-2.0/$dir - ( cd include/$dir; for i in *.h; do install -m 0644 $i ${STAGING_INCDIR}/orbit-2.0/$dir/$i; done ) - done +PR = "r1" - install -d ${STAGING_INCDIR}/orbit-2.0/ORBitservices - install -m 0644 src/services/name/CosNaming.h ${STAGING_INCDIR}/orbit-2.0/ORBitservices/ - install -m 0644 src/services/name/CosNaming_impl.h ${STAGING_INCDIR}/orbit-2.0/ORBitservices/ - install -m 0644 src/services/imodule/orbit-imodule.h ${STAGING_INCDIR}/orbit-2.0/ORBitservices/ -} diff --git a/recipes/gnome/orbit2_2.14.16.bb b/recipes/gnome/orbit2_2.14.16.bb index 5f6e6f6105..a5d5cd00b3 100644 --- a/recipes/gnome/orbit2_2.14.16.bb +++ b/recipes/gnome/orbit2_2.14.16.bb @@ -1,46 +1,2 @@ -LICENSE = "GPL" -DESCRIPTION = "CORBA ORB" -SECTION = "x11/gnome/libs" -SRC_URI = "http://ftp.gnome.org/pub/GNOME/sources/ORBit2/2.14/ORBit2-${PV}.tar.bz2 \ - file://configure-lossage.patch;patch=1;pnum=1 \ - file://pkgconfig-fix.patch;patch=1 \ - file://gtk-doc.m4 \ - file://gtk-doc.make" -DEPENDS = "libidl popt orbit2-native gtk-doc" -PARALLEL_MAKE = "" +require orbit2.inc -FILES_${PN} += "${libdir}/orbit-2.0/*.so" -FILES_${PN}-dev += "${libdir}/orbit-2.0/*.a ${libdir}/orbit-2.0/*.la" -FILES_${PN}-dbg += "${libdir}/orbit-2.0/.debug" - -S = "${WORKDIR}/ORBit2-${PV}" - -LEAD_SONAME = "libORBit-2.so" - -inherit autotools pkgconfig - -EXTRA_OECONF = "--disable-gtk-doc" -EXTRA_OEMAKE = "IDL_COMPILER='${STAGING_BINDIR_NATIVE}/orbit-idl-2'" - -do_configure_prepend() { - mkdir -p m4 - install ${WORKDIR}/gtk-doc.m4 ./m4/ - install ${WORKDIR}/gtk-doc.make ./ -} - -do_stage() { - oe_libinstall -so -C src/orb libORBit-2 ${STAGING_LIBDIR} - oe_libinstall -so -C src/services/name libORBitCosNaming-2 ${STAGING_LIBDIR} - oe_libinstall -so -C src/services/imodule libORBit-imodule-2 ${STAGING_LIBDIR} - install -m 0644 src/services/name/libname-server-2.a ${STAGING_LIBDIR}/ - - for dir in orbit orbit/poa orbit/orb-core orbit/util orbit/dynamic; do - install -d ${STAGING_INCDIR}/orbit-2.0/$dir - ( cd include/$dir; for i in *.h; do install -m 0644 $i ${STAGING_INCDIR}/orbit-2.0/$dir/$i; done ) - done - - install -d ${STAGING_INCDIR}/orbit-2.0/ORBitservices - install -m 0644 src/services/name/CosNaming.h ${STAGING_INCDIR}/orbit-2.0/ORBitservices/ - install -m 0644 src/services/name/CosNaming_impl.h ${STAGING_INCDIR}/orbit-2.0/ORBitservices/ - install -m 0644 src/services/imodule/orbit-imodule.h ${STAGING_INCDIR}/orbit-2.0/ORBitservices/ -} diff --git a/recipes/gnome/orbit2_2.14.17.bb b/recipes/gnome/orbit2_2.14.17.bb new file mode 100644 index 0000000000..a5d5cd00b3 --- /dev/null +++ b/recipes/gnome/orbit2_2.14.17.bb @@ -0,0 +1,2 @@ +require orbit2.inc + diff --git a/recipes/gnome/system-tools-backends_2.8.1.bb b/recipes/gnome/system-tools-backends_2.8.1.bb new file mode 100644 index 0000000000..08086188be --- /dev/null +++ b/recipes/gnome/system-tools-backends_2.8.1.bb @@ -0,0 +1,36 @@ +DESCRIPTION = "gnome system tools backends" +LICENSE = "GPL" + +DEPENDS = "dbus dbus-glib glib-2.0 policykit" + +inherit gnome pkgconfig update-rc.d + +SRC_URI += " \ + file://angstrom.patch;patch=1 \ + file://system-tools-backends \ + " + +do_configure_prepend() { + sed -i -e /IT_PROG_INTLTOOL/d ${S}/configure.in + sed -i -e /Makefile.in/d ${S}/configure.in + sed -i -e 's: po : :g' ${S}/Makefile.am + sed -i -e /policy/d ${S}/Makefile.am + sed -i -e 's:org.freedesktop.SystemToolsBackends.service \\:org.freedesktop.SystemToolsBackends.service:g' ${S}/Makefile.am + sed -i -e 's:@INTLTOOL_POLICY_RULE@::g' ${S}/Makefile.am + sed -i -e 's:CC=$(CC):CC="$(CC)":g' ${S}/Net-DBus/Makefile.am +} + +do_install_append () { + install -d ${D}/${sysconfdir}/init.d + install -m 0755 ${WORKDIR}/system-tools-backends ${D}/${sysconfdir}/init.d/ +} + +INITSCRIPT_NAME = "system-tools-backends" +INITSCRIPT_PARAMS = "start 50 2 3 4 5 . stop 70 1 ." + +FILES_${PN} += " ${sysconfdir}/dbus-1/system.d" +FILES_${PN} += " ${libdir}/pkgconfig" +FILES_${PN} += " ${datadir}/dbus-1/system-services" +FILES_${PN} += " ${datadir}/system-tools-backends-2.0/files" +FILES_${PN} += " ${datadir}/system-tools-backends-2.0/scripts" + diff --git a/recipes/gstreamer/gst-ffmpeg_0.10.7.bb b/recipes/gstreamer/gst-ffmpeg_0.10.7.bb index 20cea128dd..32b59f61ca 100644 --- a/recipes/gstreamer/gst-ffmpeg_0.10.7.bb +++ b/recipes/gstreamer/gst-ffmpeg_0.10.7.bb @@ -4,7 +4,7 @@ PRIORITY = "optional" LICENSE = "LGPL" HOMEPAGE = "http://www.gstreamer.net/" DEPENDS = "ffmpeg gstreamer gst-plugins-base zlib" -PR = "r1" +PR = "r2" inherit autotools pkgconfig diff --git a/recipes/gstreamer/gst-ffmpeg_0.10.8.bb b/recipes/gstreamer/gst-ffmpeg_0.10.8.bb new file mode 100644 index 0000000000..70d8556334 --- /dev/null +++ b/recipes/gstreamer/gst-ffmpeg_0.10.8.bb @@ -0,0 +1,26 @@ +DESCRIPTION = "FFmpeg-based GStreamer plug-in" +SECTION = "multimedia" +PRIORITY = "optional" +LICENSE = "LGPL" +HOMEPAGE = "http://www.gstreamer.net/" +DEPENDS = "ffmpeg gstreamer gst-plugins-base zlib" + +inherit autotools pkgconfig + +SRC_URI = "http://gstreamer.freedesktop.org/src/${PN}/${PN}-${PV}.tar.bz2 \ + file://lower-rank.diff;patch=1 \ +" + +FILES_${PN} += "${libdir}/gstreamer-0.10/*.so" +FILES_${PN}-dbg += "${libdir}/gstreamer-0.10/.debug" +FILES_${PN}-dev += "${libdir}/gstreamer-0.10/*.la ${libdir}/gstreamer-0.10/*.a" + +EXTRA_OECONF = " --with-system-ffmpeg " + +# We do this because the install program is called with -s which causes it to +# call "strip" and it then mangles cross compiled stuff.. +PATH_prepend="${CROSS_DIR}/${TARGET_SYS}/bin:" + +# Hack to get STAGING_LIBDIR into the linker path when building ffmpeg +CC = "${CCACHE} ${HOST_PREFIX}gcc ${TARGET_CC_ARCH} -L${STAGING_LIBDIR}" + diff --git a/recipes/gstreamer/gst-plugins-good_0.10.15.bb b/recipes/gstreamer/gst-plugins-good_0.10.15.bb index ff4d11bc08..5913a447e7 100644 --- a/recipes/gstreamer/gst-plugins-good_0.10.15.bb +++ b/recipes/gstreamer/gst-plugins-good_0.10.15.bb @@ -1,13 +1,13 @@ require gst-plugins.inc -PR = "r3" +PR = "r4" SRC_URI += "file://fix-unit-scale-asseration.patch;patch=1" OE_ALLOW_INSECURE_DOWNLOADS = "1" inherit gconf -DEPENDS += "gst-plugins-base openssl popt" +DEPENDS += "gst-plugins-base openssl popt esound" PACKAGES =+ "gst-plugin-gconfelements" FILES_gst-plugin-gconfelements += "${sysconfdir}/gconf" diff --git a/recipes/inotify-tools/inotify-tools_3.13.bb b/recipes/inotify-tools/inotify-tools_3.13.bb new file mode 100644 index 0000000000..e4f0734500 --- /dev/null +++ b/recipes/inotify-tools/inotify-tools_3.13.bb @@ -0,0 +1,13 @@ +DESCRIPTION = "command line utilities for the Linux inotify filesystem change notification system." +LICENSE = "GPL" +AUTHOR = "Rohan McGovern" +HOMEPAGE = "http://inotify-tools.sourceforge.net/" + +EXTRA_OECONF = "--disable-doxygen" + +SRC_URI = "${SOURCEFORGE_MIRROR}/inotify-tools/inotify-tools-${PV}.tar.gz \ + file://no-tests.patch;patch=1 \ + " + +inherit autotools + diff --git a/recipes/klibc/klibc-common.inc b/recipes/klibc/klibc-common.inc index b66bc616ef..3b0eb1c45b 100644 --- a/recipes/klibc/klibc-common.inc +++ b/recipes/klibc/klibc-common.inc @@ -31,7 +31,7 @@ ARM_INSTRUCTION_SET = "arm" SRC_URI_append_linux-gnueabi = "file://klibc-config-eabi.patch;patch=1 \ " -SRC_URI_append_linux-uclibcgnueabi = "file://klibc-config-eabi.patch;patch=1 \ +SRC_URI_append_linux-uclibceabi = "file://klibc-config-eabi.patch;patch=1 \ " EXTRA_OEMAKE = "'KLIBCARCH=${KLIBC_ARCH}' \ diff --git a/recipes/libffi/libffi_2.0+gcc4.3.2.bb b/recipes/libffi/libffi_2.0+gcc4.3.2.bb index be98050961..3b59b6a4d7 100644 --- a/recipes/libffi/libffi_2.0+gcc4.3.2.bb +++ b/recipes/libffi/libffi_2.0+gcc4.3.2.bb @@ -50,7 +50,7 @@ EXTRA_OECONF_PATHS = "--with-local-prefix=${prefix}/local \ EXTRA_OECONF_append_linux = " --enable-__cxa_atexit" EXTRA_OECONF_append_linux-gnueabi = " --enable-__cxa_atexit" EXTRA_OECONF_append_linux-uclibc = " --disable-__cxa_atexit" -EXTRA_OECONF_append_linux-uclibcgnueabi = " --disable-__cxa_atexit" +EXTRA_OECONF_append_linux-uclibceabi = " --disable-__cxa_atexit" EXTRA_OECONF_FPU = "${@get_gcc_fpu_setting(bb, d)}" #Somehow gcc doesn't set __SOFTFP__ when passing -mfloatabi=softp :( diff --git a/recipes/libffi/libffi_3.0.8.bb b/recipes/libffi/libffi_3.0.8.bb index cef09aeb28..d24e9715d4 100644 --- a/recipes/libffi/libffi_3.0.8.bb +++ b/recipes/libffi/libffi_3.0.8.bb @@ -46,7 +46,7 @@ EXTRA_OECONF_PATHS = "--with-local-prefix=${prefix}/local \ EXTRA_OECONF_append_linux = " --enable-__cxa_atexit" EXTRA_OECONF_append_linux-gnueabi = " --enable-__cxa_atexit" EXTRA_OECONF_append_linux-uclibc = " --disable-__cxa_atexit" -EXTRA_OECONF_append_linux-uclibcgnueabi = " --disable-__cxa_atexit" +EXTRA_OECONF_append_linux-uclibceabi = " --disable-__cxa_atexit" EXTRA_OECONF_FPU = "${@get_gcc_fpu_setting(bb, d)}" #Somehow gcc doesn't set __SOFTFP__ when passing -mfloatabi=softp :( diff --git a/recipes/libglade/libglade_2.6.4.bb b/recipes/libglade/libglade_2.6.4.bb new file mode 100644 index 0000000000..f73d6d5972 --- /dev/null +++ b/recipes/libglade/libglade_2.6.4.bb @@ -0,0 +1,9 @@ +require libglade.inc + +inherit gnome + +SRC_URI += "file://glade-cruft.patch;patch=1 file://no-xml2.patch;patch=1" + +EXTRA_OECONF += "--without-libxml2" + +LDFLAGS += "-lz" diff --git a/recipes/libidl/libidl-native_0.8.13.bb b/recipes/libidl/libidl-native_0.8.13.bb new file mode 100644 index 0000000000..e4109b26fa --- /dev/null +++ b/recipes/libidl/libidl-native_0.8.13.bb @@ -0,0 +1,5 @@ +SECTION = "libs" +require libidl_${PV}.bb +inherit native + +DEPENDS = "flex-native glib-2.0-native" diff --git a/recipes/libidl/libidl_0.8.13.bb b/recipes/libidl/libidl_0.8.13.bb new file mode 100644 index 0000000000..8865734d91 --- /dev/null +++ b/recipes/libidl/libidl_0.8.13.bb @@ -0,0 +1,8 @@ +require libidl.inc + +DEPENDS = "glib-2.0 flex-native libidl-native" + +PR = "r0" + +BINCONFIG_GLOB = "*-config-2" +inherit autotools pkgconfig binconfig diff --git a/recipes/libnotify/libnotify_0.4.5.bb b/recipes/libnotify/libnotify_0.4.5.bb new file mode 100644 index 0000000000..9152133b4d --- /dev/null +++ b/recipes/libnotify/libnotify_0.4.5.bb @@ -0,0 +1,14 @@ +DESCRIPTION = "Send desktop notifications to a notification daemon" +HOMEPAGE = "http://www.galago-project.org/" +SECTION = "libs" +LICENSE = "LGPL" +DEPENDS = "dbus gtk+" +PR = "r0" + +SRC_URI = "http://www.galago-project.org/files/releases/source/${PN}/${PN}-${PV}.tar.gz" + +inherit autotools pkgconfig + +do_stage() { + autotools_stage_all +} diff --git a/recipes/linknx/linknx.inc b/recipes/linknx/linknx.inc index ff2492fff5..1feb2b7c05 100644 --- a/recipes/linknx/linknx.inc +++ b/recipes/linknx/linknx.inc @@ -7,7 +7,7 @@ LICENSE = "GPL" DEPENDS = " pthsem lua5.1 curl libesmtp" DEPENDS_append_linux-uclibc = " argp-standalone" -DEPENDS_append_linux-uclibcgnueabi = " argp-standalone" +DEPENDS_append_linux-uclibceabi = " argp-standalone" SRC_URI += "file://configure-libcurl.patch;patch=1 \ file://linknx.start " diff --git a/recipes/linux/ep93xx-kernel_2.6.17+2.6.18-rc1.bb b/recipes/linux/ep93xx-kernel_2.6.17+2.6.18-rc1.bb index 79d90bc4c7..b233dd7870 100644 --- a/recipes/linux/ep93xx-kernel_2.6.17+2.6.18-rc1.bb +++ b/recipes/linux/ep93xx-kernel_2.6.17+2.6.18-rc1.bb @@ -27,7 +27,7 @@ do_configure() { fi - if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/linux/ep93xx-kernel_2.6.19+2.6.20-rc7.bb b/recipes/linux/ep93xx-kernel_2.6.19+2.6.20-rc7.bb index 642b13f607..9aab5d8bed 100644 --- a/recipes/linux/ep93xx-kernel_2.6.19+2.6.20-rc7.bb +++ b/recipes/linux/ep93xx-kernel_2.6.19+2.6.20-rc7.bb @@ -26,7 +26,7 @@ do_configure() { fi - if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/linux/files/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch b/recipes/linux/files/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch new file mode 100644 index 0000000000..1dee314700 --- /dev/null +++ b/recipes/linux/files/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch @@ -0,0 +1,429 @@ +Path: news.gmane.org!not-for-mail +From: Mikael Pettersson <mikpe@it.uu.se> +Newsgroups: gmane.linux.ports.arm.kernel +Subject: [PATCH][v3] ARM support for + TIF_RESTORE_SIGMASK/pselect6/ppoll/epoll_pwait +Date: Sat, 15 Aug 2009 13:09:28 +0200 (MEST) +Lines: 362 +Approved: news@gmane.org +Message-ID: <200908151109.n7FB9Sbs000150@pilspetsen.it.uu.se> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +X-Trace: ger.gmane.org 1250334940 22899 80.91.229.12 (15 Aug 2009 11:15:40 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Sat, 15 Aug 2009 11:15:40 +0000 (UTC) +To: linux-arm-kernel@lists.arm.linux.org.uk +Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.arm.linux.org.uk Sat Aug 15 13:15:33 2009 +Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.arm.linux.org.uk> +Envelope-to: linux-arm-kernel@m.gmane.org +Original-Received: from zeniv.linux.org.uk ([195.92.253.2]) + by lo.gmane.org with esmtp (Exim 4.50) + id 1McHER-0000U2-PG + for linux-arm-kernel@m.gmane.org; Sat, 15 Aug 2009 13:15:31 +0200 +Original-Received: from [2002:4e20:1eda:1:201:3dff:fe00:156] (helo=lists.arm.linux.org.uk) + by ZenIV.linux.org.uk with esmtpsa (Exim 4.69 #1 (Red Hat Linux)) + id 1McH9u-0005LV-3W; Sat, 15 Aug 2009 11:10:57 +0000 +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=arm.linux.org.uk; s=lists; h=Date:Message-Id:From:To:Subject: + List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help: + List-Subscribe:MIME-Version:Content-Type: + Content-Transfer-Encoding; bh=RVq9hPAexlUcptd3h6j5nomOyoEIjcDWAP + VeJtlhsa4=; b=HAoqRMC9svNzKlR0f938E0cRlLoJZvG2aSun171woWZAClu/Ud + IYN0iD2vm4eF+kYQkTYD6PGFCMbNnugmZe6gCpS0QhijoKyOzRBdykQHJuOLQtLE + q9KJzp24cQ/vwsV2+O1OqcmIFboIg2L5JQaUuv0djS7OkdspH0ysmi1lg= +Original-Received: from [::1] (helo=lists.arm.linux.org.uk) + by lists.arm.linux.org.uk with esmtp (Exim 4.69) + (envelope-from <linux-arm-kernel-bounces@lists.arm.linux.org.uk>) + id 1McH9o-0002us-34; Sat, 15 Aug 2009 12:10:44 +0100 +Original-Received: from aun.it.uu.se ([130.238.12.36] ident=root) + by lists.arm.linux.org.uk with esmtps (TLSv1:AES256-SHA:256) + (Exim 4.69) (envelope-from <mikpe@user.it.uu.se>) id 1McH8h-0002uj-Ck + for linux-arm-kernel@lists.arm.linux.org.uk; + Sat, 15 Aug 2009 12:09:35 +0100 +Original-Received: from pilspetsen.it.uu.se (daemon@pilspetsen.it.uu.se [130.238.18.39]) + by aun.it.uu.se (8.13.6/8.13.6) with ESMTP id n7FB9S04005839 + for <linux-arm-kernel@lists.arm.linux.org.uk>; + Sat, 15 Aug 2009 13:09:28 +0200 (MEST) +Original-Received: (from mikpe@localhost) + by pilspetsen.it.uu.se (8.13.8+Sun/8.13.7) id n7FB9Sbs000150 + for linux-arm-kernel@lists.arm.linux.org.uk; + Sat, 15 Aug 2009 13:09:28 +0200 (MEST) +X-BeenThere: linux-arm-kernel@lists.arm.linux.org.uk +X-Mailman-Version: 2.1.9 +Precedence: list +List-Id: ARM Linux kernel discussions <linux-arm-kernel.lists.arm.linux.org.uk> +List-Unsubscribe: <http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=unsubscribe> +List-Archive: <http://lists.arm.linux.org.uk/lurker/list/linux-arm-kernel.html> +List-Post: <mailto:linux-arm-kernel@lists.arm.linux.org.uk> +List-Help: <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=help> +List-Subscribe: <http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=subscribe> +Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.arm.linux.org.uk +Xref: news.gmane.org gmane.linux.ports.arm.kernel:64340 +Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/64340> + +This patch adds support for TIF_RESTORE_SIGMASK to ARM's signal handling, +which allows to hook up the pselect6, ppoll, and epoll_pwait syscalls on ARM. + +Tested here with eabi userspace and a test program with a deliberate race +between a child's exit and the parent's sigprocmask/select sequence. +Using sys_pselect6() instead of sigprocmask/select reliably prevents the race. + +The other arch's support for TIF_RESTORE_SIGMASK has evolved over time: + +In 2.6.16: +- add TIF_RESTORE_SIGMASK which parallels TIF_SIGPENDING +- test both when checking for pending signal [bad, changed later] +- reimplement sys_sigsuspend() to use current->saved_sigmask, + TIF_RESTORE_SIGMASK [changed later], and -ERESTARTNOHAND; + ditto for sys_rt_sigsuspend(), but drop private code and + use common code via __ARCH_WANT_SYS_RT_SIGSUSPEND; +- there are now no "extra" calls to do_signal() so its oldset + parameter is always ¤t->blocked so need not be passed, + also its return value is changed to void +- change handle_signal() to return 0/-errno +- change do_signal() to honor TIF_RESTORE_SIGMASK: + + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK is set + + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK + + if no signal was delivered and TIF_RESTORE_SIGMASK is set then + clear it and restore the sigmask +- hook up sys_pselect6() and sys_ppoll() + +In 2.6.19: +- hook up sys_epoll_pwait() + +In 2.6.26: +- allow archs to override how TIF_RESTORE_SIGMASK is implemented; + default set_restore_sigmask() sets both TIF_RESTORE_SIGMASK and + TIF_SIGPENDING; archs need now just test TIF_SIGPENDING again + when checking for pending signal work; some archs now implement + TIF_RESTORE_SIGMASK as a secondary/non-atomic thread flag bit +- call set_restore_sigmask() in sys_sigsuspend() instead of setting + TIF_RESTORE_SIGMASK + +In 2.6.29-rc: +- kill sys_pselect7() which no arch wanted + +So for 2.6.31-rc6/ARM this patch does the following: +- Add TIF_RESTORE_SIGMASK. Use the generic set_restore_sigmask() + which sets both TIF_SIGPENDING and TIF_RESTORE_SIGMASK, so + TIF_RESTORE_SIGMASK need not claim one of the scarce low thread + flags, and existing TIF_SIGPENDING and _TIF_WORK_MASK tests need + not be extended for TIF_RESTORE_SIGMASK. +- sys_sigsuspend() is reimplemented to use current->saved_sigmask and + set_restore_sigmask(), making it identical to most other archs. +- The private code for sys_rt_sigsuspend() is removed, instead generic + code supplies it via __ARCH_WANT_SYS_RT_SIGSUSPEND. +- sys_sigsuspend() and sys_rt_sigsuspend() no longer need a pt_regs + parameter, so their assembly code wrappers are removed. +- handle_signal() is changed to return 0 on success or -errno. +- The oldset parameter to do_signal() is now redundant and removed, + and the return value is now also redundant so it's changed to void. +- do_signal() is changed to honor TIF_RESTORE_SIGMASK: + + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK is set + + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK + + if no signal was delivered and TIF_RESTORE_SIGMASK is set then + clear it and restore the sigmask +- Hook up sys_pselect6, sys_ppoll, and sys_epoll_pwait. + +Signed-off-by: Mikael Pettersson +--- +Changes from previous versions: + +v2 (only posted as incremental diff against v1): +- moved sigmask restoration in no-signal-delivered case into + "if (syscall)" block for extra protection against exception + path also invoking do_signal() +v3 (this version): +- moved oldset initialisation into "if (signr > 0)" block, + as requested by Russell + + arch/arm/include/asm/thread_info.h | 2 + arch/arm/include/asm/unistd.h | 7 +-- + arch/arm/kernel/calls.S | 10 ++-- + arch/arm/kernel/entry-common.S | 10 ---- + arch/arm/kernel/signal.c | 86 +++++++++++++++---------------------- + 5 files changed, 48 insertions(+), 67 deletions(-) + +diff -rupN linux-2.6.31-rc6/arch/arm/include/asm/thread_info.h linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/thread_info.h +--- linux-2.6.31-rc6/arch/arm/include/asm/thread_info.h 2009-08-14 11:11:10.000000000 +0200 ++++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/thread_info.h 2009-08-14 11:26:44.000000000 +0200 +@@ -140,6 +140,7 @@ extern void vfp_sync_state(struct thread + #define TIF_USING_IWMMXT 17 + #define TIF_MEMDIE 18 + #define TIF_FREEZE 19 ++#define TIF_RESTORE_SIGMASK 20 + + #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) + #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) +@@ -147,6 +148,7 @@ extern void vfp_sync_state(struct thread + #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) + #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) + #define _TIF_FREEZE (1 << TIF_FREEZE) ++#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) + + /* + * Change these and you break ASM code in entry-common.S +diff -rupN linux-2.6.31-rc6/arch/arm/include/asm/unistd.h linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/unistd.h +--- linux-2.6.31-rc6/arch/arm/include/asm/unistd.h 2009-08-14 11:11:10.000000000 +0200 ++++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/unistd.h 2009-08-14 11:26:44.000000000 +0200 +@@ -360,8 +360,8 @@ + #define __NR_readlinkat (__NR_SYSCALL_BASE+332) + #define __NR_fchmodat (__NR_SYSCALL_BASE+333) + #define __NR_faccessat (__NR_SYSCALL_BASE+334) +- /* 335 for pselect6 */ +- /* 336 for ppoll */ ++#define __NR_pselect6 (__NR_SYSCALL_BASE+335) ++#define __NR_ppoll (__NR_SYSCALL_BASE+336) + #define __NR_unshare (__NR_SYSCALL_BASE+337) + #define __NR_set_robust_list (__NR_SYSCALL_BASE+338) + #define __NR_get_robust_list (__NR_SYSCALL_BASE+339) +@@ -372,7 +372,7 @@ + #define __NR_vmsplice (__NR_SYSCALL_BASE+343) + #define __NR_move_pages (__NR_SYSCALL_BASE+344) + #define __NR_getcpu (__NR_SYSCALL_BASE+345) +- /* 346 for epoll_pwait */ ++#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346) + #define __NR_kexec_load (__NR_SYSCALL_BASE+347) + #define __NR_utimensat (__NR_SYSCALL_BASE+348) + #define __NR_signalfd (__NR_SYSCALL_BASE+349) +@@ -432,6 +432,7 @@ + #define __ARCH_WANT_SYS_SIGPENDING + #define __ARCH_WANT_SYS_SIGPROCMASK + #define __ARCH_WANT_SYS_RT_SIGACTION ++#define __ARCH_WANT_SYS_RT_SIGSUSPEND + + #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) + #define __ARCH_WANT_SYS_TIME +diff -rupN linux-2.6.31-rc6/arch/arm/kernel/calls.S linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/calls.S +--- linux-2.6.31-rc6/arch/arm/kernel/calls.S 2009-08-14 11:11:10.000000000 +0200 ++++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/calls.S 2009-08-14 11:26:44.000000000 +0200 +@@ -81,7 +81,7 @@ + CALL(sys_ni_syscall) /* was sys_ssetmask */ + /* 70 */ CALL(sys_setreuid16) + CALL(sys_setregid16) +- CALL(sys_sigsuspend_wrapper) ++ CALL(sys_sigsuspend) + CALL(sys_sigpending) + CALL(sys_sethostname) + /* 75 */ CALL(sys_setrlimit) +@@ -188,7 +188,7 @@ + CALL(sys_rt_sigpending) + CALL(sys_rt_sigtimedwait) + CALL(sys_rt_sigqueueinfo) +- CALL(sys_rt_sigsuspend_wrapper) ++ CALL(sys_rt_sigsuspend) + /* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64)) + CALL(ABI(sys_pwrite64, sys_oabi_pwrite64)) + CALL(sys_chown16) +@@ -344,8 +344,8 @@ + CALL(sys_readlinkat) + CALL(sys_fchmodat) + CALL(sys_faccessat) +-/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */ +- CALL(sys_ni_syscall) /* eventually ppoll */ ++/* 335 */ CALL(sys_pselect6) ++ CALL(sys_ppoll) + CALL(sys_unshare) + CALL(sys_set_robust_list) + CALL(sys_get_robust_list) +@@ -355,7 +355,7 @@ + CALL(sys_vmsplice) + CALL(sys_move_pages) + /* 345 */ CALL(sys_getcpu) +- CALL(sys_ni_syscall) /* eventually epoll_pwait */ ++ CALL(sys_epoll_pwait) + CALL(sys_kexec_load) + CALL(sys_utimensat) + CALL(sys_signalfd) +diff -rupN linux-2.6.31-rc6/arch/arm/kernel/entry-common.S linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/entry-common.S +--- linux-2.6.31-rc6/arch/arm/kernel/entry-common.S 2009-08-14 11:11:10.000000000 +0200 ++++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/entry-common.S 2009-08-14 11:26:44.000000000 +0200 +@@ -373,16 +373,6 @@ sys_clone_wrapper: + b sys_clone + ENDPROC(sys_clone_wrapper) + +-sys_sigsuspend_wrapper: +- add r3, sp, #S_OFF +- b sys_sigsuspend +-ENDPROC(sys_sigsuspend_wrapper) +- +-sys_rt_sigsuspend_wrapper: +- add r2, sp, #S_OFF +- b sys_rt_sigsuspend +-ENDPROC(sys_rt_sigsuspend_wrapper) +- + sys_sigreturn_wrapper: + add r0, sp, #S_OFF + b sys_sigreturn +diff -rupN linux-2.6.31-rc6/arch/arm/kernel/signal.c linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/signal.c +--- linux-2.6.31-rc6/arch/arm/kernel/signal.c 2009-08-14 11:11:10.000000000 +0200 ++++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/signal.c 2009-08-14 11:26:44.000000000 +0200 +@@ -47,57 +47,22 @@ const unsigned long sigreturn_codes[7] = + MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, + }; + +-static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall); +- + /* + * atomically swap in the new signal mask, and wait for a signal. + */ +-asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs) ++asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) + { +- sigset_t saveset; +- + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sighand->siglock); +- saveset = current->blocked; ++ current->saved_sigmask = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); +- regs->ARM_r0 = -EINTR; +- +- while (1) { +- current->state = TASK_INTERRUPTIBLE; +- schedule(); +- if (do_signal(&saveset, regs, 0)) +- return regs->ARM_r0; +- } +-} +- +-asmlinkage int +-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs) +-{ +- sigset_t saveset, newset; +- +- /* XXX: Don't preclude handling different sized sigset_t's. */ +- if (sigsetsize != sizeof(sigset_t)) +- return -EINVAL; +- +- if (copy_from_user(&newset, unewset, sizeof(newset))) +- return -EFAULT; +- sigdelsetmask(&newset, ~_BLOCKABLE); +- +- spin_lock_irq(¤t->sighand->siglock); +- saveset = current->blocked; +- current->blocked = newset; +- recalc_sigpending(); +- spin_unlock_irq(¤t->sighand->siglock); +- regs->ARM_r0 = -EINTR; + +- while (1) { +- current->state = TASK_INTERRUPTIBLE; +- schedule(); +- if (do_signal(&saveset, regs, 0)) +- return regs->ARM_r0; +- } ++ current->state = TASK_INTERRUPTIBLE; ++ schedule(); ++ set_restore_sigmask(); ++ return -ERESTARTNOHAND; + } + + asmlinkage int +@@ -545,7 +510,7 @@ static inline void setup_syscall_restart + /* + * OK, we're invoking a handler + */ +-static void ++static int + handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, + struct pt_regs * regs, int syscall) +@@ -596,7 +561,7 @@ handle_signal(unsigned long sig, struct + + if (ret != 0) { + force_sigsegv(sig, tsk); +- return; ++ return ret; + } + + /* +@@ -610,6 +575,7 @@ handle_signal(unsigned long sig, struct + recalc_sigpending(); + spin_unlock_irq(&tsk->sighand->siglock); + ++ return 0; + } + + /* +@@ -621,7 +587,7 @@ handle_signal(unsigned long sig, struct + * the kernel can handle, and then we build all the user-level signal handling + * stack-frames in one go after that. + */ +-static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) ++static void do_signal(struct pt_regs *regs, int syscall) + { + struct k_sigaction ka; + siginfo_t info; +@@ -634,7 +600,7 @@ static int do_signal(sigset_t *oldset, s + * if so. + */ + if (!user_mode(regs)) +- return 0; ++ return; + + if (try_to_freeze()) + goto no_signal; +@@ -643,9 +609,24 @@ static int do_signal(sigset_t *oldset, s + + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + if (signr > 0) { +- handle_signal(signr, &ka, &info, oldset, regs, syscall); ++ sigset_t *oldset; ++ ++ if (test_thread_flag(TIF_RESTORE_SIGMASK)) ++ oldset = ¤t->saved_sigmask; ++ else ++ oldset = ¤t->blocked; ++ if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { ++ /* ++ * A signal was successfully delivered; the saved ++ * sigmask will have been stored in the signal frame, ++ * and will be restored by sigreturn, so we can simply ++ * clear the TIF_RESTORE_SIGMASK flag. ++ */ ++ if (test_thread_flag(TIF_RESTORE_SIGMASK)) ++ clear_thread_flag(TIF_RESTORE_SIGMASK); ++ } + single_step_set(current); +- return 1; ++ return; + } + + no_signal: +@@ -697,14 +678,21 @@ static int do_signal(sigset_t *oldset, s + regs->ARM_r0 == -ERESTARTNOINTR) { + setup_syscall_restart(regs); + } ++ ++ /* If there's no signal to deliver, we just put the saved sigmask ++ * back. ++ */ ++ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { ++ clear_thread_flag(TIF_RESTORE_SIGMASK); ++ sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); ++ } + } + single_step_set(current); +- return 0; + } + + asmlinkage void + do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall) + { + if (thread_flags & _TIF_SIGPENDING) +- do_signal(¤t->blocked, regs, syscall); ++ do_signal(regs, syscall); + } + +------------------------------------------------------------------- +List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel +FAQ: http://www.arm.linux.org.uk/mailinglists/faq.php +Etiquette: http://www.arm.linux.org.uk/mailinglists/etiquette.php + diff --git a/recipes/linux/gumstix-linux.inc b/recipes/linux/gumstix-linux.inc index 50111cb545..030abf2c88 100644 --- a/recipes/linux/gumstix-linux.inc +++ b/recipes/linux/gumstix-linux.inc @@ -17,7 +17,7 @@ do_deploy[dirs] = "${S}" do_configure_prepend() { echo "" > ${S}/.config - if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/linux/ixp4xx-kernel.inc b/recipes/linux/ixp4xx-kernel.inc index 8ec06e2682..910819e666 100644 --- a/recipes/linux/ixp4xx-kernel.inc +++ b/recipes/linux/ixp4xx-kernel.inc @@ -192,7 +192,7 @@ do_configure_prepend() { echo 'CONFIG_CPU_BIG_ENDIAN=y' >>'${S}/.config' fi - if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/linux/linux-2.6.28/tx27/defconfig b/recipes/linux/linux-2.6.28/tx27/defconfig index d46f4401f0..e43d3f2687 100644 --- a/recipes/linux/linux-2.6.28/tx27/defconfig +++ b/recipes/linux/linux-2.6.28/tx27/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.28 -# Sun Jun 7 01:39:35 2009 +# Tue Sep 1 15:05:17 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -46,8 +46,7 @@ CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y @@ -116,7 +115,7 @@ CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" CONFIG_CLASSIC_RCU=y -CONFIG_FREEZER=y +# CONFIG_FREEZER is not set # # System Type @@ -266,7 +265,9 @@ CONFIG_CMDLINE=" debug " # # CPU Power Management # -# CONFIG_CPU_IDLE is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y # # Floating point emulation @@ -291,10 +292,8 @@ CONFIG_HAVE_AOUT=y # CONFIG_PM=y # CONFIG_PM_DEBUG is not set -CONFIG_PM_SLEEP=y -CONFIG_SUSPEND=y -CONFIG_SUSPEND_FREEZER=y -CONFIG_APM_EMULATION=y +# CONFIG_SUSPEND is not set +# CONFIG_APM_EMULATION is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_NET=y @@ -477,10 +476,7 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_UB is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=16384 -# CONFIG_BLK_DEV_XIP is not set +# CONFIG_BLK_DEV_RAM is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set CONFIG_MISC_DEVICES=y @@ -537,7 +533,7 @@ CONFIG_NETDEVICES=y # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set +CONFIG_TUN=m # CONFIG_VETH is not set CONFIG_PHYLIB=y @@ -633,11 +629,13 @@ CONFIG_INPUT=y # # Userland interfaces # -# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set CONFIG_INPUT_EVDEV=y CONFIG_INPUT_EVBUG=m -# CONFIG_INPUT_APMPOWER is not set # # Input Device Drivers @@ -843,7 +841,6 @@ CONFIG_W1_SLAVE_DS2433_CRC=y CONFIG_POWER_SUPPLY=m # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_PDA_POWER is not set -# CONFIG_APM_POWER is not set # CONFIG_BATTERY_DS2760 is not set # CONFIG_BATTERY_BQ27x00 is not set CONFIG_LP3972=m @@ -1083,12 +1080,24 @@ CONFIG_FB_IMX=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +CONFIG_LCD_PLATFORM=m +CONFIG_BACKLIGHT_CLASS_DEVICE=m +# CONFIG_BACKLIGHT_CORGI is not set # # Display device support # -# CONFIG_DISPLAY_SUPPORT is not set +CONFIG_DISPLAY_SUPPORT=m + +# +# Display hardware drivers +# # # Console display driver support @@ -1117,11 +1126,7 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set -CONFIG_SND_DRIVERS=y -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set +# CONFIG_SND_DRIVERS is not set CONFIG_SND_ARM=y CONFIG_SND_SPI=y # CONFIG_SND_USB is not set @@ -1219,9 +1224,9 @@ CONFIG_USB_EHCI_MXC=y # # USB Device Class drivers # -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_WDM is not set +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=m # CONFIG_USB_TMC is not set # @@ -1448,22 +1453,35 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4_FS is not set +CONFIG_EXT4_FS=m +# CONFIG_EXT4DEV_COMPAT is not set +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set CONFIG_JBD=y +CONFIG_JBD2=m CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set +CONFIG_JFS_FS=m +# CONFIG_JFS_POSIX_ACL is not set +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_FILE_LOCKING=y -# CONFIG_XFS_FS is not set +CONFIG_XFS_FS=m +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_DEBUG is not set # CONFIG_OCFS2_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m -# CONFIG_FUSE_FS is not set +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=m # # CD-ROM/DVD Filesystems diff --git a/recipes/linux/linux-bd-neon-2.6_2.6.22.bb b/recipes/linux/linux-bd-neon-2.6_2.6.22.bb index 400fe782db..3fca851ef2 100644 --- a/recipes/linux/linux-bd-neon-2.6_2.6.22.bb +++ b/recipes/linux/linux-bd-neon-2.6_2.6.22.bb @@ -22,7 +22,7 @@ ALLOW_EMPTY = "1" do_configure() { cp arch/arm/configs/neon_defconfig .config || die "No default configuration for ${MACHINE} available." -# if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then +# if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then # echo "CONFIG_AEABI=y" >> ${S}/.config # echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config # else diff --git a/recipes/linux/linux-hackndev-2.6_git.bb b/recipes/linux/linux-hackndev-2.6_git.bb index 2f9f902bf7..5c093a1674 100644 --- a/recipes/linux/linux-hackndev-2.6_git.bb +++ b/recipes/linux/linux-hackndev-2.6_git.bb @@ -27,7 +27,7 @@ do_configure() { || die "No default configuration for ${MACHINE} available." fi - if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/linux/linux-handhelds-2.6.inc b/recipes/linux/linux-handhelds-2.6.inc index 5270c1465b..fe482830f8 100644 --- a/recipes/linux/linux-handhelds-2.6.inc +++ b/recipes/linux/linux-handhelds-2.6.inc @@ -50,7 +50,7 @@ do_configure() { echo "CONFIG_INITRAMFS_SOURCE=\"${WORKDIR}/initramfs.cpio\"" >> ${S}/.config fi - if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/linux/linux-navman_2.6.18.bb b/recipes/linux/linux-navman_2.6.18.bb index b37b68e8c9..2c9aef9e62 100644 --- a/recipes/linux/linux-navman_2.6.18.bb +++ b/recipes/linux/linux-navman_2.6.18.bb @@ -26,7 +26,7 @@ do_configure() { fi - if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/linux/linux-nokia800.inc b/recipes/linux/linux-nokia800.inc index 0fc4740a94..0f52b7c3b3 100644 --- a/recipes/linux/linux-nokia800.inc +++ b/recipes/linux/linux-nokia800.inc @@ -14,7 +14,7 @@ do_configure_prepend() { rm -f ${S}/.config || true - if [ "${TARGET_OS}" = "linux-gnueabi" -o "${TARGET_OS}" = "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" = "linux-gnueabi" -o "${TARGET_OS}" = "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/linux/linux-omap-2.6.29/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch b/recipes/linux/linux-omap-2.6.29/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch deleted file mode 100644 index 7852f0afdb..0000000000 --- a/recipes/linux/linux-omap-2.6.29/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch +++ /dev/null @@ -1,287 +0,0 @@ -From 8a7643b09856f4f661403dcedbe0455b3cbeeea9 Mon Sep 17 00:00:00 2001 -From: Steven Newbury <s_j_newbury@yahoo.co.uk> -Date: Fri, 22 May 2009 14:25:40 +0200 -Subject: [PATCH] implement TIF_RESTORE_SIGMASK support and enable the related - syscalls: - -pselect6 -ppoll -epoll_pwait - -Based on http://www.spinics.net/lists/arm-kernel/msg38114.html ---- - arch/arm/include/asm/thread_info.h | 2 + - arch/arm/include/asm/unistd.h | 7 ++- - arch/arm/kernel/calls.S | 6 +- - arch/arm/kernel/signal.c | 90 +++++++++++++++--------------------- - 4 files changed, 46 insertions(+), 59 deletions(-) - -diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h -index 4f88482..2cf0917 100644 ---- a/arch/arm/include/asm/thread_info.h -+++ b/arch/arm/include/asm/thread_info.h -@@ -136,6 +136,7 @@ extern void vfp_sync_state(struct thread_info *thread); - #define TIF_SIGPENDING 0 - #define TIF_NEED_RESCHED 1 - #define TIF_SYSCALL_TRACE 8 -+#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal */ - #define TIF_POLLING_NRFLAG 16 - #define TIF_USING_IWMMXT 17 - #define TIF_MEMDIE 18 -@@ -144,6 +145,7 @@ extern void vfp_sync_state(struct thread_info *thread); - #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) - #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) - #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) -+#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) - #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) - #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) - #define _TIF_FREEZE (1 << TIF_FREEZE) -diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h -index 94cc58e..cd1eaa0 100644 ---- a/arch/arm/include/asm/unistd.h -+++ b/arch/arm/include/asm/unistd.h -@@ -360,8 +360,8 @@ - #define __NR_readlinkat (__NR_SYSCALL_BASE+332) - #define __NR_fchmodat (__NR_SYSCALL_BASE+333) - #define __NR_faccessat (__NR_SYSCALL_BASE+334) -- /* 335 for pselect6 */ -- /* 336 for ppoll */ -+#define __NR_pselect6 (__NR_SYSCALL_BASE+335) -+#define __NR_ppoll (__NR_SYSCALL_BASE+336) - #define __NR_unshare (__NR_SYSCALL_BASE+337) - #define __NR_set_robust_list (__NR_SYSCALL_BASE+338) - #define __NR_get_robust_list (__NR_SYSCALL_BASE+339) -@@ -372,7 +372,7 @@ - #define __NR_vmsplice (__NR_SYSCALL_BASE+343) - #define __NR_move_pages (__NR_SYSCALL_BASE+344) - #define __NR_getcpu (__NR_SYSCALL_BASE+345) -- /* 346 for epoll_pwait */ -+#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346) - #define __NR_kexec_load (__NR_SYSCALL_BASE+347) - #define __NR_utimensat (__NR_SYSCALL_BASE+348) - #define __NR_signalfd (__NR_SYSCALL_BASE+349) -@@ -430,6 +430,7 @@ - #define __ARCH_WANT_SYS_SIGPENDING - #define __ARCH_WANT_SYS_SIGPROCMASK - #define __ARCH_WANT_SYS_RT_SIGACTION -+#define __ARCH_WANT_SYS_RT_SIGSUSPEND - - #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) - #define __ARCH_WANT_SYS_TIME -diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S -index 1680e9e..534000d 100644 ---- a/arch/arm/kernel/calls.S -+++ b/arch/arm/kernel/calls.S -@@ -344,8 +344,8 @@ - CALL(sys_readlinkat) - CALL(sys_fchmodat) - CALL(sys_faccessat) --/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */ -- CALL(sys_ni_syscall) /* eventually ppoll */ -+/* 335 */ CALL(sys_pselect6) -+ CALL(sys_ppoll) - CALL(sys_unshare) - CALL(sys_set_robust_list) - CALL(sys_get_robust_list) -@@ -355,7 +355,7 @@ - CALL(sys_vmsplice) - CALL(sys_move_pages) - /* 345 */ CALL(sys_getcpu) -- CALL(sys_ni_syscall) /* eventually epoll_pwait */ -+ CALL(sys_epoll_pwait) - CALL(sys_kexec_load) - CALL(sys_utimensat) - CALL(sys_signalfd) -diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c -index 80b8b5c..7645048 100644 ---- a/arch/arm/kernel/signal.c -+++ b/arch/arm/kernel/signal.c -@@ -47,57 +47,23 @@ const unsigned long sigreturn_codes[7] = { - MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, - }; - --static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall); -+static void do_signal(struct pt_regs * regs, int syscall); - - /* - * atomically swap in the new signal mask, and wait for a signal. - */ --asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs) -+asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) - { -- sigset_t saveset; -- - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); -- saveset = current->blocked; -+ current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); -- regs->ARM_r0 = -EINTR; -- -- while (1) { -- current->state = TASK_INTERRUPTIBLE; -- schedule(); -- if (do_signal(&saveset, regs, 0)) -- return regs->ARM_r0; -- } --} -- --asmlinkage int --sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs) --{ -- sigset_t saveset, newset; -- -- /* XXX: Don't preclude handling different sized sigset_t's. */ -- if (sigsetsize != sizeof(sigset_t)) -- return -EINVAL; -- -- if (copy_from_user(&newset, unewset, sizeof(newset))) -- return -EFAULT; -- sigdelsetmask(&newset, ~_BLOCKABLE); -- -- spin_lock_irq(¤t->sighand->siglock); -- saveset = current->blocked; -- current->blocked = newset; -- recalc_sigpending(); -- spin_unlock_irq(¤t->sighand->siglock); -- regs->ARM_r0 = -EINTR; -- -- while (1) { -- current->state = TASK_INTERRUPTIBLE; -- schedule(); -- if (do_signal(&saveset, regs, 0)) -- return regs->ARM_r0; -- } -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ set_thread_flag(TIF_RESTORE_SIGMASK); -+ return -ERESTARTNOHAND; - } - - asmlinkage int -@@ -290,7 +256,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) - - badframe: - force_sig(SIGSEGV, current); -- return 0; -+ return -EFAULT; - } - - asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) -@@ -325,7 +291,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) - - badframe: - force_sig(SIGSEGV, current); -- return 0; -+ return -EFAULT; - } - - static int -@@ -541,7 +507,7 @@ static inline void restart_syscall(struct pt_regs *regs) - /* - * OK, we're invoking a handler - */ --static void -+static int - handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs, int syscall) -@@ -592,7 +558,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, - - if (ret != 0) { - force_sigsegv(sig, tsk); -- return; -+ return ret; - } - - /* -@@ -606,6 +572,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, - recalc_sigpending(); - spin_unlock_irq(&tsk->sighand->siglock); - -+ return ret; - } - - /* -@@ -617,11 +584,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, - * the kernel can handle, and then we build all the user-level signal handling - * stack-frames in one go after that. - */ --static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) -+static void do_signal(struct pt_regs *regs, int syscall) - { - struct k_sigaction ka; - siginfo_t info; - int signr; -+ sigset_t *oldset; - - /* - * We want the common case to go fast, which -@@ -630,18 +598,29 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) - * if so. - */ - if (!user_mode(regs)) -- return 0; -+ return; - - if (try_to_freeze()) - goto no_signal; - - single_step_clear(current); - -+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) -+ oldset = ¤t->saved_sigmask; -+ else -+ oldset = ¤t->blocked; -+ - signr = get_signal_to_deliver(&info, &ka, regs, NULL); - if (signr > 0) { -- handle_signal(signr, &ka, &info, oldset, regs, syscall); -+ if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { -+ /* a signal was successfully delivered; the saved -+ * sigmask will have been stored in the signal frame, -+ * and will be restored by sigreturn, so we can simply -+ * clear the TIF_RESTORE_SIGMASK flag */ -+ clear_thread_flag(TIF_RESTORE_SIGMASK); -+ } - single_step_set(current); -- return 1; -+ return; - } - - no_signal: -@@ -665,7 +644,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) - usp = (u32 __user *)regs->ARM_sp; - - /* -- * Either we supports OABI only, or we have -+ * Either we support OABI only, or we have - * EABI with the OABI compat layer enabled. - * In the later case we don't know if user - * space is EABI or not, and if not we must -@@ -695,12 +674,17 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) - } - } - single_step_set(current); -- return 0; -+ /* if there's no signal to deliver, we just put the saved sigmask -+ back. */ -+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { -+ clear_thread_flag(TIF_RESTORE_SIGMASK); -+ sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); -+ } - } - - asmlinkage void - do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall) - { -- if (thread_flags & _TIF_SIGPENDING) -- do_signal(¤t->blocked, regs, syscall); -+ if (thread_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK)) -+ do_signal(regs, syscall); - } --- -1.6.2.4 - diff --git a/recipes/linux/linux-omap-2.6.29/cache/copy-page-tweak.patch b/recipes/linux/linux-omap-2.6.29/cache/copy-page-tweak.patch new file mode 100644 index 0000000000..9da374041c --- /dev/null +++ b/recipes/linux/linux-omap-2.6.29/cache/copy-page-tweak.patch @@ -0,0 +1,169 @@ +Path: news.gmane.org!not-for-mail +From: "Kirill A. Shutemov" <kirill@shutemov.name> +Newsgroups: gmane.linux.ports.arm.kernel +Subject: [PATCH] ARM: copy_page.S: take into account the size of the cache line +Date: Wed, 2 Sep 2009 20:19:58 +0300 +Lines: 92 +Approved: news@gmane.org +Message-ID: <1251911998-3112-1-git-send-email-kirill__11898.5180197798$1251901300$gmane$org@shutemov.name> +References: <20090902132423.GA12595@n2100.arm.linux.org.uk> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +X-Trace: ger.gmane.org 1251901300 3930 80.91.229.12 (2 Sep 2009 14:21:40 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 2 Sep 2009 14:21:40 +0000 (UTC) +Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>, + "Kirill A. Shutemov" <kirill@shutemov.name>, + Siarhei Siamashka <siarhei.siamashka@nokia.com>, + Moiseichuk Leonid <leonid.moiseichuk@nokia.com>, + Koskinen Aaro <aaro.koskinen@nokia.com> +To: linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org +Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 16:21:32 2009 +Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org> +Envelope-to: linux-arm-kernel@m.gmane.org +Original-Received: from bombadil.infradead.org ([18.85.46.34]) + by lo.gmane.org with esmtp (Exim 4.50) + id 1MiqiI-0003K3-An + for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 16:21:30 +0200 +Original-Received: from localhost ([::1] helo=bombadil.infradead.org) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1MiqhG-0005iZ-OK; Wed, 02 Sep 2009 14:20:26 +0000 +Original-Received: from mail-bw0-f222.google.com ([209.85.218.222]) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1Miqh8-0005LP-ED for linux-arm-kernel@lists.infradead.org; + Wed, 02 Sep 2009 14:20:23 +0000 +Original-Received: by bwz22 with SMTP id 22so788877bwz.18 + for <linux-arm-kernel@lists.infradead.org>; + Wed, 02 Sep 2009 07:20:06 -0700 (PDT) +Original-Received: by 10.204.162.143 with SMTP id v15mr6724283bkx.50.1251901206540; + Wed, 02 Sep 2009 07:20:06 -0700 (PDT) +Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14]) + by mx.google.com with ESMTPS id d13sm11540576fka.2.2009.09.02.07.20.05 + (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 07:20:05 -0700 (PDT) +X-Mailer: git-send-email 1.6.4.2 +In-Reply-To: <20090902132423.GA12595@n2100.arm.linux.org.uk> +X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) ) + MR-646709E3 +X-CRM114-CacheID: sfid-20090902_102018_607316_8AE98A04 +X-CRM114-Status: UNSURE ( 9.59 ) +X-CRM114-Notice: Please train this message. +X-Spam-Score: -4.2 (----) +X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary: + Content analysis details: (-4.2 points) + pts rule name description + ---- ---------------------- + -------------------------------------------------- + -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1% + [score: 0.0000] + -1.6 AWL AWL: From: address is in the auto white-list +X-BeenThere: linux-arm-kernel@lists.infradead.org +X-Mailman-Version: 2.1.12 +Precedence: list +List-Id: <linux-arm-kernel.lists.infradead.org> +List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe> +List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/> +List-Post: <mailto:linux-arm-kernel@lists.infradead.org> +List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help> +List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe> +Original-Sender: linux-arm-kernel-bounces@lists.infradead.org +Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org +Xref: news.gmane.org gmane.linux.ports.arm.kernel:65025 +Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65025> + +Optimized version of copy_page() was written with assumption that cache +line size is 32 bytes. On Cortex-A8 cache line size is 64 bytes. + +This patch tries to generalize copy_page() to work with any cache line +size if cache line size is multiple of 16 and page size is multiple of +two cache line size. + +After this optimization we've got ~25% speedup on OMAP3(tested in +userspace). + +There is test for kernelspace which trigger copy-on-write after fork(): + + #include <stdlib.h> + #include <string.h> + #include <unistd.h> + + #define BUF_SIZE (10000*4096) + #define NFORK 200 + + int main(int argc, char **argv) + { + char *buf = malloc(BUF_SIZE); + int i; + + memset(buf, 0, BUF_SIZE); + + for(i = 0; i < NFORK; i++) { + if (fork()) { + wait(NULL); + } else { + int j; + + for(j = 0; j < BUF_SIZE; j+= 4096) + buf[j] = (j & 0xFF) + 1; + break; + } + } + + free(buf); + return 0; + } + +Before optimization this test takes ~66 seconds, after optimization +takes ~56 seconds. + +Signed-off-by: Siarhei Siamashka <siarhei.siamashka@nokia.com> +Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> +--- + arch/arm/lib/copy_page.S | 16 ++++++++-------- + 1 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S +index 6ae04db..6ee2f67 100644 +--- a/arch/arm/lib/copy_page.S ++++ b/arch/arm/lib/copy_page.S +@@ -12,8 +12,9 @@ + #include <linux/linkage.h> + #include <asm/assembler.h> + #include <asm/asm-offsets.h> ++#include <asm/cache.h> + +-#define COPY_COUNT (PAGE_SZ/64 PLD( -1 )) ++#define COPY_COUNT (PAGE_SZ / (2 * L1_CACHE_BYTES) PLD( -1 )) + + .text + .align 5 +@@ -26,17 +27,16 @@ + ENTRY(copy_page) + stmfd sp!, {r4, lr} @ 2 + PLD( pld [r1, #0] ) +- PLD( pld [r1, #32] ) ++ PLD( pld [r1, #L1_CACHE_BYTES] ) + mov r2, #COPY_COUNT @ 1 + ldmia r1!, {r3, r4, ip, lr} @ 4+1 +-1: PLD( pld [r1, #64] ) +- PLD( pld [r1, #96] ) +-2: stmia r0!, {r3, r4, ip, lr} @ 4 +- ldmia r1!, {r3, r4, ip, lr} @ 4+1 +- stmia r0!, {r3, r4, ip, lr} @ 4 +- ldmia r1!, {r3, r4, ip, lr} @ 4+1 ++1: PLD( pld [r1, #2 * L1_CACHE_BYTES]) ++ PLD( pld [r1, #3 * L1_CACHE_BYTES]) ++2: ++ .rept (2 * L1_CACHE_BYTES / 16 - 1) + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmia r1!, {r3, r4, ip, lr} @ 4 ++ .endr + subs r2, r2, #1 @ 1 + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmgtia r1!, {r3, r4, ip, lr} @ 4 +-- +1.6.4.2 diff --git a/recipes/linux/linux-omap-2.6.29/cache/l1cache-shift.patch b/recipes/linux/linux-omap-2.6.29/cache/l1cache-shift.patch new file mode 100644 index 0000000000..e58d49c7a3 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.29/cache/l1cache-shift.patch @@ -0,0 +1,115 @@ +Path: news.gmane.org!not-for-mail +From: "Kirill A. Shutemov" <kirill@shutemov.name> +Newsgroups: gmane.linux.ports.arm.kernel +Subject: [PATCH 1/2] ARM: Introduce ARM_L1_CACHE_SHIFT to define cache line + size +Date: Wed, 2 Sep 2009 19:11:52 +0300 +Lines: 39 +Approved: news@gmane.org +Message-ID: <1251907913-16261-1-git-send-email-kirill__21953.4654439942$1251897245$gmane$org@shutemov.name> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +X-Trace: ger.gmane.org 1251897245 21910 80.91.229.12 (2 Sep 2009 13:14:05 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 2 Sep 2009 13:14:05 +0000 (UTC) +Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>, + "Kirill A. Shutemov" <kirill@shutemov.name>, + Siarhei Siamashka <siarhei.siamashka@nokia.com>, + Moiseichuk Leonid <leonid.moiseichuk@nokia.com>, + Koskinen Aaro <aaro.koskinen@nokia.com> +To: linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org +Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 15:13:57 2009 +Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org> +Envelope-to: linux-arm-kernel@m.gmane.org +Original-Received: from bombadil.infradead.org ([18.85.46.34]) + by lo.gmane.org with esmtp (Exim 4.50) + id 1Mipeu-0000ZH-G2 + for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 15:13:56 +0200 +Original-Received: from localhost ([::1] helo=bombadil.infradead.org) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1MipdW-00035E-AP; Wed, 02 Sep 2009 13:12:30 +0000 +Original-Received: from mail-bw0-f222.google.com ([209.85.218.222]) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1Mipd1-00031v-Ga for linux-arm-kernel@lists.infradead.org; + Wed, 02 Sep 2009 13:12:04 +0000 +Original-Received: by bwz22 with SMTP id 22so735896bwz.18 + for <linux-arm-kernel@lists.infradead.org>; + Wed, 02 Sep 2009 06:11:56 -0700 (PDT) +Original-Received: by 10.204.34.199 with SMTP id m7mr6687295bkd.48.1251897116013; + Wed, 02 Sep 2009 06:11:56 -0700 (PDT) +Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14]) + by mx.google.com with ESMTPS id c28sm2027077fka.19.2009.09.02.06.11.54 + (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 06:11:55 -0700 (PDT) +X-Mailer: git-send-email 1.6.3.4 +X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) ) + MR-646709E3 +X-CRM114-CacheID: sfid-20090902_091159_726883_CEFBECD2 +X-CRM114-Status: UNSURE ( 8.83 ) +X-CRM114-Notice: Please train this message. +X-Spam-Score: -4.6 (----) +X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary: + Content analysis details: (-4.6 points) + pts rule name description + ---- ---------------------- + -------------------------------------------------- + -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1% + [score: 0.0000] + -2.0 AWL AWL: From: address is in the auto white-list +X-BeenThere: linux-arm-kernel@lists.infradead.org +X-Mailman-Version: 2.1.12 +Precedence: list +List-Id: <linux-arm-kernel.lists.infradead.org> +List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe> +List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/> +List-Post: <mailto:linux-arm-kernel@lists.infradead.org> +List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help> +List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe> +Original-Sender: linux-arm-kernel-bounces@lists.infradead.org +Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org +Xref: news.gmane.org gmane.linux.ports.arm.kernel:65017 +Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65017> + +Currently kernel believes that all ARM CPUs have L1_CACHE_SHIFT == 5. +It's not true at least for CPUs based on Cortex-A8. + +List of CPUs with cache line size != 32 should be expanded later. + +Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> +--- + arch/arm/include/asm/cache.h | 2 +- + arch/arm/mm/Kconfig | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h +index feaa75f..2ee7743 100644 +--- a/arch/arm/include/asm/cache.h ++++ b/arch/arm/include/asm/cache.h +@@ -4,7 +4,7 @@ + #ifndef __ASMARM_CACHE_H + #define __ASMARM_CACHE_H + +-#define L1_CACHE_SHIFT 5 ++#define L1_CACHE_SHIFT (CONFIG_ARM_L1_CACHE_SHIFT) + #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) + + /* +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index 83c025e..3c37d4c 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -771,3 +771,8 @@ config CACHE_XSC3L2 + select OUTER_CACHE + help + This option enables the L2 cache on XScale3. ++ ++config ARM_L1_CACHE_SHIFT ++ int ++ default 6 if ARCH_OMAP3 ++ default 5 +-- +1.6.3.4 diff --git a/recipes/linux/linux-omap-2.6.31/beagleboard/defconfig b/recipes/linux/linux-omap-2.6.31/beagleboard/defconfig index f43c8f5fbb..81f3cadce4 100644 --- a/recipes/linux/linux-omap-2.6.31/beagleboard/defconfig +++ b/recipes/linux/linux-omap-2.6.31/beagleboard/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.31-rc1-omap1 -# Thu Jul 30 12:51:41 2009 +# Linux kernel version: 2.6.31-rc8-omap1 +# Fri Sep 4 15:16:17 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -30,6 +30,7 @@ CONFIG_CONSTRUCTORS=y # CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set @@ -68,8 +69,8 @@ CONFIG_USER_SCHED=y CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y -CONFIG_RD_BZIP2=y -CONFIG_RD_LZMA=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -96,7 +97,7 @@ CONFIG_AIO=y # Performance Counters # CONFIG_VM_EVENT_COUNTERS=y -CONFIG_STRIP_ASM_SYMS=y +# CONFIG_STRIP_ASM_SYMS is not set # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -129,7 +130,7 @@ CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_BLOCK=y CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set -CONFIG_BLK_DEV_INTEGRITY=y +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -215,21 +216,19 @@ CONFIG_OMAP_DM_TIMER=y # CONFIG_OMAP_LL_DEBUG_UART1 is not set # CONFIG_OMAP_LL_DEBUG_UART2 is not set CONFIG_OMAP_LL_DEBUG_UART3=y -CONFIG_OMAP2_VRAM=y -CONFIG_OMAP2_VRFB=y CONFIG_ARCH_OMAP34XX=y CONFIG_ARCH_OMAP3430=y # # OMAP Board Type # -# CONFIG_MACH_NOKIA_RX51 is not set -# CONFIG_MACH_OMAP_LDP is not set -# CONFIG_MACH_OMAP_3430SDP is not set -# CONFIG_MACH_OMAP3EVM is not set CONFIG_MACH_OMAP3_BEAGLE=y -# CONFIG_MACH_OVERO is not set +# CONFIG_MACH_OMAP_LDP is not set +CONFIG_MACH_OVERO=y +CONFIG_MACH_OMAP3EVM=y # CONFIG_MACH_OMAP3_PANDORA is not set +# CONFIG_MACH_OMAP_3430SDP is not set +# CONFIG_MACH_NOKIA_RX51 is not set # CONFIG_MACH_OMAP_ZOOM2 is not set # @@ -258,6 +257,7 @@ CONFIG_ARM_THUMBEE=y # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set CONFIG_HAS_TLS_REG=y +CONFIG_ARM_L1_CACHE_SHIFT=6 # CONFIG_ARM_ERRATA_430973 is not set # CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_460075 is not set @@ -281,7 +281,7 @@ CONFIG_VMSPLIT_3G=y # CONFIG_VMSPLIT_2G is not set # CONFIG_VMSPLIT_1G is not set CONFIG_PAGE_OFFSET=0xC0000000 -# CONFIG_PREEMPT is not set +CONFIG_PREEMPT=y CONFIG_HZ=128 CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set @@ -324,19 +324,17 @@ CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_DEBUG=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y +# CONFIG_CPU_IDLE is not set # # Floating point emulation @@ -348,7 +346,6 @@ CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_VFP=y CONFIG_VFPv3=y CONFIG_NEON=y -# CONFIG_ARM_ERRATUM_451034 is not set # # Userspace binary formats @@ -488,7 +485,7 @@ CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m CONFIG_NETFILTER_XT_TARGET_CONNMARK=m # CONFIG_NETFILTER_XT_TARGET_DSCP is not set CONFIG_NETFILTER_XT_TARGET_HL=m -CONFIG_NETFILTER_XT_TARGET_LED=m +# CONFIG_NETFILTER_XT_TARGET_LED is not set CONFIG_NETFILTER_XT_TARGET_MARK=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m @@ -531,7 +528,7 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m CONFIG_NETFILTER_XT_MATCH_TCPMSS=m CONFIG_NETFILTER_XT_MATCH_TIME=m CONFIG_NETFILTER_XT_MATCH_U32=m -CONFIG_NETFILTER_XT_MATCH_OSF=m +# CONFIG_NETFILTER_XT_MATCH_OSF is not set CONFIG_IP_VS=m CONFIG_IP_VS_IPV6=y CONFIG_IP_VS_DEBUG=y @@ -676,7 +673,7 @@ CONFIG_LLC=m # CONFIG_ECONET is not set CONFIG_WAN_ROUTER=m # CONFIG_PHONET is not set -CONFIG_IEEE802154=m +# CONFIG_IEEE802154 is not set CONFIG_NET_SCHED=y # @@ -732,10 +729,7 @@ CONFIG_CAN_BCM=m # CAN Device Drivers # CONFIG_CAN_VCAN=m -CONFIG_CAN_DEV=m -# CONFIG_CAN_CALC_BITTIMING is not set -CONFIG_CAN_SJA1000=m -CONFIG_CAN_SJA1000_PLATFORM=m +# CONFIG_CAN_DEV is not set # CONFIG_CAN_DEBUG_DEVICES is not set CONFIG_IRDA=m @@ -838,7 +832,6 @@ CONFIG_MAC80211_RC_PID=y CONFIG_MAC80211_RC_DEFAULT_PID=y # CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set CONFIG_MAC80211_RC_DEFAULT="pid" -# CONFIG_MAC80211_MESH is not set CONFIG_MAC80211_LEDS=y # CONFIG_MAC80211_DEBUGFS is not set # CONFIG_MAC80211_DEBUG_MENU is not set @@ -864,7 +857,7 @@ CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set -CONFIG_CONNECTOR=m +# CONFIG_CONNECTOR is not set CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set CONFIG_MTD_CONCAT=y @@ -1000,7 +993,7 @@ CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y # CONFIG_SCSI_TGT is not set -CONFIG_SCSI_NETLINK=y +# CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y # @@ -1023,20 +1016,17 @@ CONFIG_SCSI_WAIT_SCAN=m # SCSI Transports # # CONFIG_SCSI_SPI_ATTRS is not set -CONFIG_SCSI_FC_ATTRS=m +# CONFIG_SCSI_FC_ATTRS is not set CONFIG_SCSI_ISCSI_ATTRS=m # CONFIG_SCSI_SAS_LIBSAS is not set # CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m -CONFIG_LIBFC=m -CONFIG_LIBFCOE=m +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_DH is not set -CONFIG_SCSI_OSD_INITIATOR=m -CONFIG_SCSI_OSD_ULD=m -CONFIG_SCSI_OSD_DPRINT_SENSE=1 -# CONFIG_SCSI_OSD_DEBUG is not set +# CONFIG_SCSI_OSD_INITIATOR is not set # CONFIG_ATA is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m @@ -1053,11 +1043,11 @@ CONFIG_BLK_DEV_DM=m CONFIG_DM_CRYPT=m CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m -CONFIG_DM_LOG_USERSPACE=m +# CONFIG_DM_LOG_USERSPACE is not set CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_QL=m -CONFIG_DM_MULTIPATH_ST=m +# CONFIG_DM_MULTIPATH_QL is not set +# CONFIG_DM_MULTIPATH_ST is not set CONFIG_DM_DELAY=m # CONFIG_DM_UEVENT is not set CONFIG_NETDEVICES=y @@ -1067,8 +1057,47 @@ CONFIG_MACVLAN=m CONFIG_EQUALIZER=m CONFIG_TUN=m CONFIG_VETH=m -# CONFIG_NET_ETHERNET is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +CONFIG_ENC28J60=y +# CONFIG_ENC28J60_WRITEVERIFY is not set +# CONFIG_ETHOC is not set +CONFIG_SMC911X=y +CONFIG_SMSC911X=y +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set @@ -1080,10 +1109,10 @@ CONFIG_WLAN_80211=y CONFIG_LIBERTAS=y CONFIG_LIBERTAS_USB=y # CONFIG_LIBERTAS_SDIO is not set -CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_SPI is not set # CONFIG_LIBERTAS_DEBUG is not set # CONFIG_LIBERTAS_THINFIRM is not set -CONFIG_AT76C50X_USB=m +# CONFIG_AT76C50X_USB is not set CONFIG_USB_ZD1201=y CONFIG_USB_NET_RNDIS_WLAN=y CONFIG_RTL8187=y @@ -1093,9 +1122,7 @@ CONFIG_P54_COMMON=y CONFIG_P54_USB=y # CONFIG_P54_SPI is not set CONFIG_P54_LEDS=y -CONFIG_ATH_COMMON=m -CONFIG_AR9170_USB=m -CONFIG_AR9170_LEDS=y +# CONFIG_AR9170_USB is not set CONFIG_HOSTAP=y CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y @@ -1109,18 +1136,16 @@ CONFIG_ZD1211RW=y CONFIG_RT2X00=y CONFIG_RT2500USB=y CONFIG_RT73USB=y -CONFIG_RT2800USB=m +# CONFIG_RT2800USB is not set CONFIG_RT2X00_LIB_USB=y CONFIG_RT2X00_LIB=y -CONFIG_RT2X00_LIB_HT=y CONFIG_RT2X00_LIB_FIRMWARE=y CONFIG_RT2X00_LIB_CRYPTO=y CONFIG_RT2X00_LIB_RFKILL=y CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RT2X00_DEBUG is not set -CONFIG_WL12XX=m -CONFIG_IWM=m -# CONFIG_IWM_DEBUG is not set +# CONFIG_WL12XX is not set +# CONFIG_IWM is not set # # WiMAX Wireless Broadband devices @@ -1138,7 +1163,7 @@ CONFIG_USB_RTL8150=y CONFIG_USB_USBNET=y CONFIG_USB_NET_AX8817X=y CONFIG_USB_NET_CDCETHER=y -CONFIG_USB_NET_CDC_EEM=m +# CONFIG_USB_NET_CDC_EEM is not set CONFIG_USB_NET_DM9601=y CONFIG_USB_NET_SMSC95XX=y CONFIG_USB_NET_GL620A=y @@ -1154,13 +1179,11 @@ CONFIG_USB_ARMLINUX=y CONFIG_USB_EPSON2888=y CONFIG_USB_KC2190=y CONFIG_USB_NET_ZAURUS=y -CONFIG_USB_NET_INT51X1=m +# CONFIG_USB_NET_INT51X1 is not set # CONFIG_WAN is not set CONFIG_ATM_DRIVERS=y # CONFIG_ATM_DUMMY is not set # CONFIG_ATM_TCP is not set -CONFIG_IEEE802154_DRIVERS=m -CONFIG_IEEE802154_FAKEHARD=m CONFIG_PPP=m CONFIG_PPP_MULTILINK=y CONFIG_PPP_FILTER=y @@ -1204,13 +1227,14 @@ CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_KEYBOARD=y # CONFIG_KEYBOARD_ATKBD is not set -# CONFIG_KEYBOARD_SUNKBD is not set # CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set # CONFIG_KEYBOARD_NEWTON is not set # CONFIG_KEYBOARD_STOWAWAY is not set -# CONFIG_KEYBOARD_LM8323 is not set -CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y CONFIG_MOUSE_PS2_ALPS=y @@ -1224,7 +1248,7 @@ CONFIG_MOUSE_PS2_TRACKPOINT=y # CONFIG_MOUSE_BCM5974 is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_MOUSE_GPIO is not set -CONFIG_MOUSE_SYNAPTICS_I2C=m +# CONFIG_MOUSE_SYNAPTICS_I2C is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set @@ -1237,7 +1261,7 @@ CONFIG_INPUT_MISC=y # CONFIG_INPUT_CM109 is not set CONFIG_INPUT_TWL4030_PWRBUTTON=y CONFIG_INPUT_UINPUT=y -CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set # # Hardware I/O ports @@ -1283,7 +1307,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_TIMERIOMEM=m +# CONFIG_HW_RANDOM_TIMERIOMEM is not set # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set @@ -1339,12 +1363,12 @@ CONFIG_SPI_MASTER=y # # CONFIG_SPI_BITBANG is not set # CONFIG_SPI_GPIO is not set -# CONFIG_SPI_OMAP24XX is not set +CONFIG_SPI_OMAP24XX=y # # SPI Protocol Masters # -# CONFIG_SPI_SPIDEV is not set +CONFIG_SPI_SPIDEV=y # CONFIG_SPI_TLE62X0 is not set CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y @@ -1377,6 +1401,7 @@ CONFIG_POWER_SUPPLY=m # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_PDA_POWER is not set # CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_DS2782 is not set # CONFIG_BATTERY_BQ27x00 is not set # CONFIG_BATTERY_MAX17040 is not set CONFIG_HWMON=y @@ -1455,7 +1480,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # # CONFIG_SOFT_WATCHDOG is not set CONFIG_OMAP_WATCHDOG=y -CONFIG_TWL4030_WATCHDOG=m +# CONFIG_TWL4030_WATCHDOG is not set # # USB-based Watchdog Cards @@ -1480,6 +1505,7 @@ CONFIG_SSB=y # CONFIG_HTC_PASIC3 is not set # CONFIG_TPS65010 is not set CONFIG_TWL4030_CORE=y +CONFIG_TWL4030_MADC=y # CONFIG_MFD_TMIO is not set # CONFIG_MFD_T7L66XB is not set # CONFIG_MFD_TC6387XB is not set @@ -1490,7 +1516,7 @@ CONFIG_TWL4030_CORE=y # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set # CONFIG_EZX_PCAP is not set -CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_SUPPORT=y # # Multimedia core support @@ -1527,6 +1553,7 @@ CONFIG_MEDIA_TUNER_MC44S803=m CONFIG_VIDEO_V4L2=m CONFIG_VIDEO_V4L1=m CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_DMA_SG=m CONFIG_VIDEOBUF_VMALLOC=m CONFIG_VIDEOBUF_DVB=m CONFIG_VIDEO_IR=m @@ -1540,6 +1567,7 @@ CONFIG_VIDEO_IR_I2C=m CONFIG_VIDEO_MSP3400=m CONFIG_VIDEO_CS53L32A=m CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_MT9V011=m CONFIG_VIDEO_SAA711X=m CONFIG_VIDEO_TVP5150=m CONFIG_VIDEO_CX25840=m @@ -1550,6 +1578,10 @@ CONFIG_VIDEO_VIVI=m # CONFIG_VIDEO_SAA5246A is not set # CONFIG_VIDEO_SAA5249 is not set # CONFIG_VIDEO_AU0828 is not set +CONFIG_VIDEO_OMAP3=y +CONFIG_VIDEO_OMAP_VIDEOOUT=m +# CONFIG_NTSC_M is not set +CONFIG_PAL_BDGHI=y # CONFIG_SOC_CAMERA is not set CONFIG_V4L_USB_DRIVERS=y CONFIG_USB_VIDEO_CLASS=m @@ -1561,11 +1593,12 @@ CONFIG_USB_GSPCA_CONEX=m CONFIG_USB_GSPCA_ETOMS=m CONFIG_USB_GSPCA_FINEPIX=m CONFIG_USB_GSPCA_MARS=m -CONFIG_USB_GSPCA_MR97310A=m +# CONFIG_USB_GSPCA_MR97310A is not set CONFIG_USB_GSPCA_OV519=m CONFIG_USB_GSPCA_OV534=m CONFIG_USB_GSPCA_PAC207=m CONFIG_USB_GSPCA_PAC7311=m +# CONFIG_USB_GSPCA_SN9C20X is not set CONFIG_USB_GSPCA_SONIXB=m CONFIG_USB_GSPCA_SONIXJ=m CONFIG_USB_GSPCA_SPCA500=m @@ -1574,8 +1607,8 @@ CONFIG_USB_GSPCA_SPCA505=m CONFIG_USB_GSPCA_SPCA506=m CONFIG_USB_GSPCA_SPCA508=m CONFIG_USB_GSPCA_SPCA561=m -CONFIG_USB_GSPCA_SQ905=m -CONFIG_USB_GSPCA_SQ905C=m +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set CONFIG_USB_GSPCA_STK014=m CONFIG_USB_GSPCA_SUNPLUS=m CONFIG_USB_GSPCA_T613=m @@ -1591,7 +1624,7 @@ CONFIG_VIDEO_EM28XX=m CONFIG_VIDEO_EM28XX_ALSA=m CONFIG_VIDEO_EM28XX_DVB=m CONFIG_VIDEO_CX231XX=m -CONFIG_VIDEO_CX231XX_ALSA=m +# CONFIG_VIDEO_CX231XX_ALSA is not set CONFIG_VIDEO_CX231XX_DVB=m CONFIG_VIDEO_USBVISION=m CONFIG_VIDEO_USBVIDEO=m @@ -1652,7 +1685,7 @@ CONFIG_DVB_USB_CINERGY_T2=m CONFIG_DVB_USB_ANYSEE=m CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AF9015=m -CONFIG_DVB_USB_CE6230=m +# CONFIG_DVB_USB_CE6230 is not set CONFIG_DVB_SIANO_SMS1XXX=m CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y @@ -1719,12 +1752,11 @@ CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -CONFIG_FB_SYS_FILLRECT=m -CONFIG_FB_SYS_COPYAREA=m -CONFIG_FB_SYS_IMAGEBLIT=m +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set -CONFIG_FB_SYS_FOPS=m -CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SYS_FOPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -1734,13 +1766,14 @@ CONFIG_FB_DEFERRED_IO=y # # Frame buffer hardware drivers # -# CONFIG_FB_UVESA is not set # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set -CONFIG_FB_BROADSHEET=m +# CONFIG_FB_BROADSHEET is not set # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set +CONFIG_OMAP2_VRAM=y +CONFIG_OMAP2_VRFB=y CONFIG_OMAP2_DSS=y CONFIG_OMAP2_VRAM_SIZE=14 CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y @@ -1751,19 +1784,18 @@ CONFIG_OMAP2_DSS_DSI=y CONFIG_OMAP2_DSS_USE_DSI_PLL=y # CONFIG_OMAP2_DSS_FAKE_VSYNC is not set CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1 +CONFIG_FB_OMAP2=y +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y +# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set +CONFIG_FB_OMAP2_NUM_FBS=3 # # OMAP2/3 Display Device Drivers # CONFIG_PANEL_GENERIC=y CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=m -# CONFIG_PANEL_SHARP_LS037V7DW01 is not set -# CONFIG_PANEL_N800 is not set -# CONFIG_CTRL_BLIZZARD is not set -CONFIG_FB_OMAP2=y -CONFIG_FB_OMAP2_DEBUG_SUPPORT=y -# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set -CONFIG_FB_OMAP2_NUM_FBS=3 +CONFIG_PANEL_SHARP_LS037V7DW01=m +# CONFIG_PANEL_TAAL is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # @@ -1832,6 +1864,8 @@ CONFIG_SND_USB_CAIAQ_INPUT=y CONFIG_SND_SOC=y CONFIG_SND_OMAP_SOC=y CONFIG_SND_OMAP_SOC_MCBSP=y +# CONFIG_SND_OMAP_SOC_OVERO is not set +# CONFIG_SND_OMAP_SOC_OMAP3EVM is not set CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_ALL_CODECS is not set @@ -1876,11 +1910,10 @@ CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y CONFIG_HID_SUNPLUS=y # CONFIG_HID_GREENASIA is not set -CONFIG_HID_SMARTJOYPLUS=m -# CONFIG_SMARTJOYPLUS_FF is not set +# CONFIG_HID_SMARTJOYPLUS is not set CONFIG_HID_TOPSEED=y # CONFIG_HID_THRUSTMASTER is not set -CONFIG_HID_WACOM=m +# CONFIG_HID_WACOM is not set # CONFIG_HID_ZEROPLUS is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y @@ -1983,7 +2016,7 @@ CONFIG_USB_SERIAL_BELKIN=m CONFIG_USB_SERIAL_CH341=m CONFIG_USB_SERIAL_WHITEHEAT=m CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_CP210X=m +# CONFIG_USB_SERIAL_CP210X is not set CONFIG_USB_SERIAL_CYPRESS_M8=m CONFIG_USB_SERIAL_EMPEG=m CONFIG_USB_SERIAL_FTDI_SIO=m @@ -2019,14 +2052,14 @@ CONFIG_USB_SERIAL_MOTOROLA=m CONFIG_USB_SERIAL_NAVMAN=m CONFIG_USB_SERIAL_PL2303=m CONFIG_USB_SERIAL_OTI6858=m -CONFIG_USB_SERIAL_QUALCOMM=m +# CONFIG_USB_SERIAL_QUALCOMM is not set CONFIG_USB_SERIAL_SPCP8X5=m CONFIG_USB_SERIAL_HP4X=m CONFIG_USB_SERIAL_SAFE=m # CONFIG_USB_SERIAL_SAFE_PADDED is not set CONFIG_USB_SERIAL_SIEMENS_MPI=m CONFIG_USB_SERIAL_SIERRAWIRELESS=m -CONFIG_USB_SERIAL_SYMBOL=m +# CONFIG_USB_SERIAL_SYMBOL is not set CONFIG_USB_SERIAL_TI=m CONFIG_USB_SERIAL_CYBERJACK=m CONFIG_USB_SERIAL_XIRCOM=m @@ -2079,8 +2112,8 @@ CONFIG_USB_GADGET_SELECTED=y # CONFIG_USB_GADGET_PXA25X is not set # CONFIG_USB_GADGET_PXA27X is not set # CONFIG_USB_GADGET_S3C_HSOTG is not set -# CONFIG_USB_GADGET_S3C2410 is not set # CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_S3C2410 is not set # CONFIG_USB_GADGET_M66592 is not set # CONFIG_USB_GADGET_AMD5536UDC is not set # CONFIG_USB_GADGET_FSL_QE is not set @@ -2092,7 +2125,7 @@ CONFIG_USB_GADGET_SELECTED=y CONFIG_USB_GADGET_DUALSPEED=y CONFIG_USB_ZERO=m CONFIG_USB_ZERO_HNPTEST=y -CONFIG_USB_AUDIO=m +# CONFIG_USB_AUDIO is not set CONFIG_USB_ETH=m CONFIG_USB_ETH_RNDIS=y CONFIG_USB_GADGETFS=m @@ -2143,7 +2176,7 @@ CONFIG_LEDS_OMAP=y # CONFIG_LEDS_PCA9532 is not set CONFIG_LEDS_GPIO=y CONFIG_LEDS_GPIO_PLATFORM=y -# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_DAC124S085 is not set # CONFIG_LEDS_BD2802 is not set @@ -2155,7 +2188,7 @@ CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=m CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_BACKLIGHT=m -CONFIG_LEDS_TRIGGER_GPIO=y +# CONFIG_LEDS_TRIGGER_GPIO is not set CONFIG_LEDS_TRIGGER_DEFAULT_ON=m # @@ -2179,7 +2212,7 @@ CONFIG_RTC_INTF_DEV=y # # I2C RTC drivers # -# CONFIG_RTC_DRV_DS1307 is not set +CONFIG_RTC_DRV_DS1307=y # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set # CONFIG_RTC_DRV_MAX6900 is not set @@ -2189,7 +2222,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_PCF8563 is not set # CONFIG_RTC_DRV_PCF8583 is not set # CONFIG_RTC_DRV_M41T80 is not set -CONFIG_RTC_DRV_TWL4030=y +CONFIG_RTC_DRV_TWL4030=m # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_RX8581 is not set @@ -2230,7 +2263,7 @@ CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set # CONFIG_REGULATOR_FIXED_VOLTAGE is not set # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set -CONFIG_REGULATOR_USERSPACE_CONSUMER=m +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set # CONFIG_REGULATOR_BQ24022 is not set # CONFIG_REGULATOR_MAX1586 is not set CONFIG_REGULATOR_TWL4030=y @@ -2246,7 +2279,7 @@ CONFIG_STAGING=y # CONFIG_USB_IP_COMMON is not set CONFIG_W35UND=m # CONFIG_PRISM2_USB is not set -# CONFIG_ECHO is not set +CONFIG_ECHO=m CONFIG_USB_ATMEL=m # CONFIG_AGNX is not set CONFIG_OTUS=m @@ -2269,17 +2302,12 @@ CONFIG_ANDROID_TIMED_OUTPUT=y CONFIG_ANDROID_TIMED_GPIO=m # CONFIG_ANDROID_LOW_MEMORY_KILLER is not set # CONFIG_DST is not set -CONFIG_POHMELFS=m -# CONFIG_POHMELFS_DEBUG is not set -CONFIG_POHMELFS_CRYPTO=y +# CONFIG_POHMELFS is not set # CONFIG_STLC45XX is not set -CONFIG_USB_SERIAL_ATEN2011=m -# CONFIG_B3DFG is not set # CONFIG_PLAN9AUTH is not set -# CONFIG_HECI is not set # CONFIG_LINE6_USB is not set -CONFIG_USB_SERIAL_QUATECH2=m -CONFIG_USB_CPC=m +# CONFIG_USB_SERIAL_QUATECH2 is not set +# CONFIG_USB_CPC is not set # CONFIG_FB_UDL is not set # @@ -2349,7 +2377,7 @@ CONFIG_QUOTACTL=y # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=m CONFIG_FUSE_FS=m -CONFIG_CUSE=m +# CONFIG_CUSE is not set # # Caches @@ -2440,14 +2468,13 @@ CONFIG_SYSV_FS=m CONFIG_UFS_FS=m # CONFIG_UFS_FS_WRITE is not set # CONFIG_UFS_DEBUG is not set -# CONFIG_EXOFS_FS is not set -CONFIG_NILFS2_FS=m +# CONFIG_NILFS2_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set CONFIG_NFS_V4=y -CONFIG_NFS_V4_1=y +# CONFIG_NFS_V4_1 is not set CONFIG_ROOT_NFS=y CONFIG_NFSD=m CONFIG_NFSD_V2_ACL=y @@ -2578,6 +2605,7 @@ CONFIG_TIMER_STATS=y # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_PREEMPT=y # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -2612,7 +2640,21 @@ CONFIG_EVENT_TRACING=y CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y -# CONFIG_FTRACE is not set +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_BOOT_TRACER is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set # CONFIG_DYNAMIC_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -2726,7 +2768,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m # Compression # CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_ZLIB=m +# CONFIG_CRYPTO_ZLIB is not set CONFIG_CRYPTO_LZO=y # @@ -2753,8 +2795,6 @@ CONFIG_ZLIB_DEFLATE=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y CONFIG_DECOMPRESS_GZIP=y -CONFIG_DECOMPRESS_BZIP2=y -CONFIG_DECOMPRESS_LZMA=y CONFIG_TEXTSEARCH=y CONFIG_TEXTSEARCH_KMP=m CONFIG_TEXTSEARCH_BM=m diff --git a/recipes/linux/linux-omap-2.6.31/beagleboard/ehci.patch b/recipes/linux/linux-omap-2.6.31/beagleboard/ehci.patch new file mode 100644 index 0000000000..633b1b2269 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/beagleboard/ehci.patch @@ -0,0 +1,35 @@ +From 870bb728d41c231941791bffe8783cd88cb7580a Mon Sep 17 00:00:00 2001 +From: Steve Sakoman <steve@sakoman.com> +Date: Sat, 29 Aug 2009 15:46:30 -0700 +Subject: [PATCH] ARM: OMAP3: Fix EHCI initialization for Beagle + +--- + arch/arm/mach-omap2/board-omap3beagle.c | 5 +++-- + 1 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c +index 07aee90..65934ea 100644 +--- a/arch/arm/mach-omap2/board-omap3beagle.c ++++ b/arch/arm/mach-omap2/board-omap3beagle.c +@@ -161,7 +161,7 @@ static int beagle_twl_gpio_setup(struct device *dev, + + /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */ + gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); +- gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1); ++ gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); + + /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ + gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; +@@ -412,7 +412,8 @@ static void __init omap3_beagle_init(void) + gpio_direction_output(170, true); + + usb_musb_init(); +- usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61); ++ usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, false, true, ++ -EINVAL, 147); + omap3beagle_flash_init(); + + /* Ensure SDRC pins are mux'd for self-refresh */ +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-2.6.31/beagleboard/logo_linux_clut224.ppm b/recipes/linux/linux-omap-2.6.31/beagleboard/logo_linux_clut224.ppm new file mode 100644 index 0000000000..d29fc1c544 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/beagleboard/logo_linux_clut224.ppm @@ -0,0 +1,73147 @@ +P3 +# CREATOR: GIMP PNM Filter Version 1.1 +387 63 +255 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +246 +116 +28 +246 +116 +28 +246 +116 +28 +246 +116 +28 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +111 +26 +246 +116 +28 +246 +116 +28 +247 +118 +39 +247 +118 +39 +247 +118 +39 +246 +116 +28 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +118 +39 +247 +118 +39 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +118 +39 +247 +118 +39 +246 +116 +28 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +118 +39 +247 +118 +39 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +118 +39 +246 +116 +28 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +118 +39 +246 +116 +28 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +118 +39 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +118 +39 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +118 +39 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +118 +39 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +130 +53 +248 +138 +64 +250 +139 +73 +247 +143 +74 +247 +143 +74 +249 +146 +83 +249 +146 +83 +249 +146 +83 +247 +143 +74 +250 +139 +73 +248 +138 +64 +247 +130 +53 +247 +123 +41 +247 +118 +39 +246 +116 +28 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +53 +248 +138 +64 +250 +139 +73 +247 +143 +74 +247 +143 +74 +250 +139 +73 +248 +138 +64 +247 +130 +53 +247 +123 +41 +246 +116 +28 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +123 +41 +247 +130 +60 +248 +138 +64 +247 +143 +74 +247 +143 +74 +247 +143 +74 +250 +139 +73 +247 +130 +60 +247 +130 +53 +247 +123 +41 +246 +116 +28 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +118 +39 +247 +130 +53 +247 +130 +60 +250 +139 +73 +247 +143 +74 +247 +143 +74 +247 +143 +74 +248 +138 +64 +247 +130 +60 +247 +130 +53 +247 +118 +39 +247 +111 +26 +247 +111 +26 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +123 +41 +247 +130 +60 +248 +138 +64 +247 +143 +74 +247 +143 +74 +247 +143 +74 +250 +139 +73 +247 +130 +60 +247 +130 +53 +247 +123 +41 +246 +116 +28 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +130 +53 +247 +130 +60 +250 +139 +73 +249 +146 +83 +249 +152 +92 +249 +159 +103 +249 +159 +103 +247 +165 +111 +251 +168 +115 +251 +168 +115 +247 +165 +111 +247 +165 +111 +249 +159 +103 +249 +152 +92 +249 +146 +83 +250 +139 +73 +247 +130 +60 +247 +123 +41 +247 +118 +39 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +60 +247 +143 +74 +247 +150 +84 +246 +156 +93 +249 +159 +103 +249 +159 +103 +246 +156 +93 +247 +150 +84 +250 +139 +73 +247 +130 +60 +247 +123 +41 +246 +116 +28 +247 +111 +26 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +123 +41 +248 +138 +64 +247 +143 +74 +249 +152 +92 +249 +159 +103 +249 +159 +103 +249 +159 +103 +246 +156 +93 +247 +150 +84 +250 +139 +73 +247 +130 +53 +247 +123 +41 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +130 +53 +248 +138 +64 +249 +146 +83 +249 +152 +92 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +152 +92 +249 +146 +83 +248 +138 +64 +247 +130 +53 +247 +118 +39 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +130 +53 +248 +138 +64 +247 +143 +74 +249 +152 +92 +249 +159 +103 +249 +159 +103 +249 +159 +103 +246 +156 +93 +247 +150 +84 +250 +139 +73 +247 +130 +53 +247 +123 +41 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +118 +39 +247 +123 +41 +247 +130 +60 +250 +139 +73 +247 +150 +84 +249 +159 +103 +247 +165 +111 +249 +174 +124 +248 +180 +134 +252 +185 +144 +240 +181 +138 +219 +170 +138 +219 +170 +138 +230 +173 +136 +240 +181 +138 +248 +180 +134 +249 +174 +124 +247 +165 +111 +249 +159 +103 +249 +146 +83 +248 +138 +64 +247 +130 +53 +247 +123 +41 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +247 +130 +60 +247 +143 +74 +249 +159 +103 +214 +151 +109 +121 +100 +85 +65 +67 +64 +74 +68 +68 +129 +102 +78 +214 +151 +109 +246 +156 +93 +247 +143 +74 +247 +130 +53 +247 +118 +39 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +111 +26 +246 +116 +28 +247 +123 +41 +248 +138 +64 +249 +146 +83 +249 +159 +103 +204 +141 +99 +102 +91 +75 +65 +67 +64 +81 +77 +76 +146 +111 +88 +238 +159 +107 +249 +152 +92 +250 +139 +73 +247 +130 +53 +247 +118 +39 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +130 +53 +248 +138 +64 +247 +150 +84 +245 +162 +103 +162 +125 +96 +81 +77 +76 +55 +66 +67 +99 +90 +79 +187 +140 +108 +249 +159 +103 +247 +150 +84 +248 +138 +64 +247 +123 +41 +246 +116 +28 +247 +111 +26 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +111 +26 +246 +116 +28 +247 +123 +41 +248 +138 +64 +249 +146 +83 +249 +159 +103 +187 +140 +108 +102 +91 +75 +58 +69 +70 +76 +78 +76 +146 +111 +88 +238 +159 +107 +249 +152 +92 +250 +139 +73 +247 +130 +53 +247 +118 +39 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +53 +248 +138 +64 +249 +146 +83 +249 +159 +103 +251 +168 +115 +248 +180 +134 +239 +182 +144 +186 +157 +134 +124 +111 +99 +82 +69 +65 +65 +58 +56 +55 +48 +48 +65 +58 +56 +65 +58 +56 +65 +58 +56 +99 +90 +79 +158 +130 +108 +230 +173 +136 +250 +176 +132 +247 +165 +111 +249 +152 +92 +247 +143 +74 +247 +130 +53 +247 +123 +41 +246 +116 +28 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +111 +26 +247 +118 +39 +247 +130 +53 +250 +139 +73 +246 +156 +93 +214 +151 +109 +74 +68 +68 +56 +64 +60 +95 +87 +59 +88 +82 +59 +56 +64 +60 +81 +77 +76 +238 +159 +107 +249 +152 +92 +248 +138 +64 +247 +130 +53 +246 +116 +28 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +130 +53 +247 +143 +74 +249 +159 +103 +187 +140 +108 +51 +62 +63 +69 +69 +61 +95 +87 +59 +83 +78 +61 +48 +58 +59 +121 +100 +85 +247 +165 +111 +247 +150 +84 +248 +138 +64 +247 +123 +41 +246 +116 +28 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +247 +130 +60 +247 +150 +84 +247 +165 +111 +139 +115 +96 +48 +58 +59 +95 +78 +64 +118 +86 +65 +81 +73 +62 +48 +58 +59 +162 +125 +96 +249 +159 +103 +249 +146 +83 +247 +130 +60 +247 +123 +41 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +130 +53 +247 +143 +74 +249 +159 +103 +187 +140 +108 +48 +58 +59 +76 +70 +64 +118 +86 +65 +95 +78 +64 +51 +62 +63 +121 +100 +85 +247 +165 +111 +247 +150 +84 +248 +138 +64 +247 +123 +41 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +60 +247 +143 +74 +249 +152 +92 +247 +165 +111 +250 +176 +132 +251 +192 +154 +167 +142 +123 +65 +58 +56 +35 +31 +30 +71 +60 +43 +108 +87 +46 +129 +106 +52 +137 +110 +49 +156 +125 +62 +187 +166 +150 +129 +106 +52 +101 +83 +47 +59 +50 +39 +55 +48 +48 +139 +115 +96 +240 +181 +138 +249 +174 +124 +249 +159 +103 +247 +143 +74 +247 +130 +53 +247 +123 +41 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +247 +130 +60 +247 +150 +84 +247 +165 +111 +124 +111 +99 +56 +64 +60 +137 +110 +49 +171 +129 +45 +171 +129 +45 +129 +106 +52 +51 +62 +63 +162 +125 +96 +247 +165 +111 +249 +146 +83 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +248 +138 +64 +249 +152 +92 +245 +169 +119 +81 +77 +76 +69 +69 +61 +152 +119 +47 +171 +129 +45 +171 +129 +45 +105 +93 +60 +48 +58 +59 +187 +140 +108 +249 +159 +103 +247 +143 +74 +247 +130 +53 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +111 +26 +246 +116 +28 +247 +130 +53 +250 +139 +73 +249 +159 +103 +210 +156 +119 +51 +62 +63 +112 +85 +63 +234 +126 +45 +234 +126 +45 +225 +124 +48 +95 +78 +64 +63 +74 +74 +234 +168 +124 +246 +156 +93 +250 +139 +73 +247 +123 +41 +246 +116 +28 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +248 +138 +64 +249 +152 +92 +245 +169 +119 +81 +77 +76 +81 +73 +62 +212 +120 +56 +234 +126 +45 +234 +126 +45 +135 +94 +64 +41 +58 +57 +187 +140 +108 +249 +159 +103 +247 +143 +74 +247 +130 +53 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +60 +249 +146 +83 +249 +159 +103 +249 +174 +124 +249 +189 +146 +236 +186 +153 +99 +90 +79 +47 +40 +38 +85 +71 +43 +145 +114 +49 +171 +129 +45 +171 +129 +45 +171 +129 +45 +168 +127 +42 +160 +120 +43 +195 +167 +113 +216 +194 +154 +168 +127 +42 +168 +127 +42 +123 +102 +54 +59 +50 +39 +82 +69 +65 +230 +173 +136 +249 +174 +124 +249 +159 +103 +247 +143 +74 +247 +130 +53 +247 +118 +39 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +248 +138 +64 +246 +156 +93 +245 +169 +119 +84 +85 +82 +83 +78 +61 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +75 +74 +61 +101 +100 +92 +249 +174 +124 +246 +156 +93 +248 +138 +64 +247 +123 +41 +246 +116 +28 +247 +111 +26 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +111 +26 +247 +118 +39 +247 +130 +53 +247 +143 +74 +249 +159 +103 +210 +156 +119 +48 +58 +59 +105 +93 +60 +171 +129 +45 +158 +125 +46 +161 +127 +40 +152 +119 +47 +62 +63 +61 +139 +115 +96 +251 +168 +115 +247 +150 +84 +247 +130 +60 +247 +123 +41 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +111 +26 +247 +118 +39 +247 +130 +53 +249 +146 +83 +247 +165 +111 +158 +130 +108 +51 +62 +63 +188 +112 +56 +234 +125 +52 +224 +123 +55 +234 +126 +45 +163 +104 +61 +48 +58 +59 +210 +156 +119 +247 +165 +111 +249 +146 +83 +247 +130 +60 +247 +118 +39 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +130 +53 +247 +143 +74 +247 +165 +111 +210 +156 +119 +55 +66 +67 +146 +97 +64 +234 +126 +45 +224 +123 +55 +234 +125 +52 +199 +115 +54 +62 +63 +61 +139 +115 +96 +251 +168 +115 +247 +150 +84 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +60 +249 +146 +83 +249 +159 +103 +250 +176 +132 +219 +170 +138 +150 +125 +114 +65 +58 +56 +24 +22 +23 +59 +50 +39 +152 +119 +47 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +160 +120 +43 +158 +125 +46 +227 +196 +175 +192 +155 +91 +160 +120 +43 +171 +129 +45 +158 +125 +46 +85 +71 +43 +65 +58 +56 +219 +170 +138 +249 +174 +124 +246 +156 +93 +250 +139 +73 +247 +130 +53 +247 +118 +39 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +247 +103 +7 +246 +109 +10 +246 +116 +28 +247 +130 +53 +247 +143 +74 +249 +159 +103 +230 +173 +136 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +91 +92 +89 +252 +185 +144 +247 +165 +111 +249 +146 +83 +247 +130 +60 +247 +123 +41 +246 +116 +28 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +111 +26 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +123 +41 +248 +138 +64 +249 +152 +92 +249 +174 +124 +203 +161 +131 +43 +57 +62 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +133 +120 +107 +250 +176 +132 +246 +156 +93 +248 +138 +64 +247 +123 +41 +246 +116 +28 +247 +111 +26 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +111 +26 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +248 +138 +64 +249 +152 +92 +249 +174 +124 +154 +133 +118 +56 +64 +60 +199 +115 +54 +227 +126 +50 +224 +123 +55 +234 +125 +52 +183 +110 +59 +51 +62 +63 +186 +157 +134 +250 +176 +132 +246 +156 +93 +250 +139 +73 +247 +130 +53 +247 +118 +39 +247 +111 +26 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +130 +53 +250 +139 +73 +246 +156 +93 +249 +174 +124 +209 +171 +139 +51 +62 +63 +155 +100 +63 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +133 +120 +107 +249 +174 +124 +246 +156 +93 +248 +138 +64 +247 +123 +41 +247 +111 +26 +246 +109 +10 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +130 +53 +247 +143 +74 +249 +159 +103 +250 +176 +132 +158 +130 +108 +47 +40 +38 +59 +50 +39 +85 +71 +43 +85 +71 +43 +59 +50 +39 +35 +31 +30 +123 +102 +54 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +152 +119 +47 +192 +155 +91 +224 +207 +180 +158 +125 +46 +160 +120 +43 +168 +127 +42 +171 +129 +45 +71 +60 +43 +82 +69 +65 +239 +182 +144 +249 +174 +124 +249 +152 +92 +248 +138 +64 +247 +123 +41 +246 +116 +28 +247 +111 +26 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +111 +26 +247 +118 +39 +247 +130 +53 +249 +146 +83 +247 +165 +111 +239 +182 +144 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +91 +92 +89 +250 +197 +158 +250 +176 +132 +249 +159 +103 +247 +143 +74 +247 +130 +60 +247 +123 +41 +247 +118 +39 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +118 +39 +247 +118 +39 +246 +116 +28 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +246 +116 +28 +246 +116 +28 +246 +116 +28 +247 +118 +39 +247 +118 +39 +246 +116 +28 +246 +116 +28 +246 +116 +28 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +246 +116 +28 +247 +118 +39 +247 +118 +39 +246 +116 +28 +246 +116 +28 +246 +116 +28 +246 +116 +28 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +130 +60 +249 +146 +83 +249 +159 +103 +248 +180 +134 +212 +173 +150 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +65 +67 +64 +137 +127 +115 +248 +180 +134 +249 +159 +103 +247 +143 +74 +247 +130 +53 +247 +118 +39 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +118 +39 +247 +118 +39 +246 +116 +28 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +118 +39 +247 +130 +53 +250 +139 +73 +249 +159 +103 +250 +176 +132 +167 +142 +123 +56 +64 +60 +199 +115 +54 +227 +126 +50 +224 +123 +55 +234 +125 +52 +173 +106 +60 +48 +58 +59 +187 +166 +150 +249 +189 +146 +251 +168 +115 +249 +152 +92 +250 +139 +73 +247 +130 +53 +247 +123 +41 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +246 +116 +28 +247 +118 +39 +247 +118 +39 +246 +116 +28 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +246 +116 +28 +247 +118 +39 +247 +118 +39 +246 +116 +28 +246 +116 +28 +246 +116 +28 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +53 +248 +138 +64 +247 +150 +84 +247 +165 +111 +252 +185 +144 +212 +173 +150 +51 +62 +63 +155 +100 +63 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +133 +120 +107 +248 +180 +134 +249 +159 +103 +250 +139 +73 +247 +123 +41 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +246 +116 +28 +247 +118 +39 +247 +118 +39 +247 +118 +39 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +103 +7 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +246 +116 +28 +247 +118 +39 +247 +118 +39 +246 +116 +28 +246 +116 +28 +246 +116 +28 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +111 +26 +247 +118 +39 +247 +130 +53 +250 +139 +73 +249 +159 +103 +250 +176 +132 +167 +142 +123 +24 +22 +23 +85 +71 +43 +158 +125 +46 +171 +129 +45 +171 +129 +45 +171 +129 +45 +85 +71 +43 +35 +31 +30 +145 +114 +49 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +152 +119 +47 +216 +194 +154 +195 +167 +113 +152 +119 +47 +158 +125 +46 +168 +127 +42 +158 +125 +46 +59 +50 +39 +139 +115 +96 +252 +185 +144 +247 +165 +111 +247 +150 +84 +247 +130 +60 +247 +123 +41 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +130 +60 +247 +150 +84 +251 +168 +115 +236 +186 +153 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +91 +92 +89 +251 +209 +178 +249 +189 +146 +249 +174 +124 +249 +159 +103 +249 +146 +83 +248 +138 +64 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +118 +39 +246 +116 +28 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +123 +41 +246 +116 +28 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +118 +39 +246 +116 +28 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +248 +138 +64 +247 +143 +74 +246 +156 +93 +249 +174 +124 +251 +192 +154 +207 +178 +158 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +137 +127 +115 +249 +189 +146 +247 +165 +111 +247 +150 +84 +248 +138 +64 +247 +130 +53 +247 +123 +41 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +118 +39 +247 +118 +39 +247 +118 +39 +247 +123 +41 +247 +130 +60 +247 +143 +74 +249 +159 +103 +252 +185 +144 +167 +142 +123 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +234 +125 +52 +173 +106 +60 +51 +62 +63 +187 +166 +150 +250 +200 +166 +248 +180 +134 +247 +165 +111 +249 +152 +92 +247 +143 +74 +247 +130 +60 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +118 +39 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +118 +39 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +118 +39 +247 +118 +39 +247 +118 +39 +247 +118 +39 +247 +118 +39 +247 +118 +39 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +60 +250 +139 +73 +249 +152 +92 +247 +165 +111 +248 +180 +134 +250 +197 +158 +207 +178 +158 +51 +62 +63 +155 +100 +63 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +252 +185 +144 +249 +159 +103 +247 +143 +74 +247 +130 +53 +246 +116 +28 +246 +109 +10 +247 +103 +7 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +118 +39 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +118 +39 +247 +118 +39 +246 +116 +28 +246 +116 +28 +246 +116 +28 +247 +118 +39 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +118 +39 +246 +116 +28 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +248 +138 +64 +247 +150 +84 +251 +168 +115 +230 +173 +136 +47 +40 +38 +59 +50 +39 +168 +127 +42 +168 +127 +42 +158 +125 +46 +158 +125 +46 +161 +127 +40 +171 +129 +45 +59 +50 +39 +71 +60 +43 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +152 +119 +47 +170 +137 +67 +239 +227 +208 +170 +137 +67 +160 +120 +43 +158 +125 +46 +171 +129 +45 +123 +102 +54 +47 +40 +38 +209 +171 +139 +248 +180 +134 +247 +165 +111 +249 +146 +83 +247 +130 +60 +247 +123 +41 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +111 +26 +247 +123 +41 +247 +130 +60 +247 +150 +84 +249 +174 +124 +236 +186 +153 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +91 +92 +89 +255 +215 +190 +253 +204 +176 +249 +189 +146 +249 +174 +124 +247 +165 +111 +246 +156 +93 +249 +146 +83 +247 +143 +74 +248 +138 +64 +247 +130 +60 +247 +130 +53 +247 +123 +41 +246 +116 +28 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +130 +53 +248 +138 +64 +250 +139 +73 +247 +143 +74 +249 +146 +83 +247 +150 +84 +249 +146 +83 +249 +146 +83 +247 +143 +74 +248 +138 +64 +247 +130 +60 +247 +130 +53 +247 +123 +41 +247 +118 +39 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +130 +53 +248 +138 +64 +250 +139 +73 +247 +143 +74 +249 +146 +83 +249 +146 +83 +249 +146 +83 +249 +146 +83 +249 +146 +83 +247 +143 +74 +247 +143 +74 +250 +139 +73 +250 +139 +73 +248 +138 +64 +247 +130 +60 +247 +130 +53 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +60 +250 +139 +73 +247 +143 +74 +249 +146 +83 +249 +146 +83 +249 +146 +83 +249 +146 +83 +249 +146 +83 +247 +143 +74 +247 +143 +74 +247 +143 +74 +247 +143 +74 +247 +150 +84 +249 +159 +103 +249 +174 +124 +252 +185 +144 +250 +200 +166 +217 +187 +166 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +137 +127 +115 +251 +192 +154 +249 +174 +124 +246 +156 +93 +247 +143 +74 +248 +138 +64 +247 +130 +60 +247 +130 +60 +248 +138 +64 +250 +139 +73 +247 +143 +74 +249 +146 +83 +247 +150 +84 +249 +146 +83 +249 +146 +83 +247 +143 +74 +248 +138 +64 +247 +130 +60 +247 +130 +53 +247 +130 +53 +247 +130 +60 +250 +139 +73 +247 +150 +84 +251 +168 +115 +249 +189 +146 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +234 +125 +52 +173 +106 +60 +48 +58 +59 +187 +166 +150 +253 +212 +188 +250 +197 +158 +248 +180 +134 +251 +168 +115 +249 +159 +103 +247 +150 +84 +247 +143 +74 +250 +139 +73 +248 +138 +64 +247 +130 +53 +247 +123 +41 +247 +118 +39 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +111 +26 +247 +118 +39 +247 +123 +41 +247 +130 +53 +248 +138 +64 +250 +139 +73 +247 +143 +74 +249 +146 +83 +247 +150 +84 +247 +150 +84 +249 +146 +83 +247 +143 +74 +250 +139 +73 +247 +130 +60 +247 +130 +53 +247 +123 +41 +247 +118 +39 +247 +111 +26 +247 +111 +26 +246 +109 +10 +246 +109 +10 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +118 +39 +247 +123 +41 +247 +130 +53 +247 +130 +60 +248 +138 +64 +247 +143 +74 +249 +146 +83 +249 +146 +83 +249 +146 +83 +249 +146 +83 +249 +146 +83 +247 +143 +74 +247 +143 +74 +247 +143 +74 +250 +139 +73 +250 +139 +73 +250 +139 +73 +248 +138 +64 +248 +138 +64 +248 +138 +64 +248 +138 +64 +248 +138 +64 +248 +138 +64 +250 +139 +73 +250 +139 +73 +250 +139 +73 +250 +139 +73 +247 +143 +74 +247 +143 +74 +250 +139 +73 +250 +139 +73 +248 +138 +64 +248 +138 +64 +247 +130 +60 +247 +130 +60 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +60 +247 +130 +60 +248 +138 +64 +250 +139 +73 +247 +143 +74 +247 +150 +84 +249 +159 +103 +251 +168 +115 +248 +180 +134 +250 +197 +158 +253 +212 +188 +207 +178 +158 +51 +62 +63 +155 +100 +63 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +249 +189 +146 +247 +165 +111 +247 +143 +74 +247 +130 +53 +246 +116 +28 +246 +109 +10 +247 +103 +7 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +111 +26 +247 +118 +39 +247 +123 +41 +247 +130 +53 +247 +130 +60 +250 +139 +73 +247 +143 +74 +249 +146 +83 +247 +150 +84 +247 +150 +84 +249 +146 +83 +247 +143 +74 +250 +139 +73 +248 +138 +64 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +118 +39 +247 +118 +39 +247 +118 +39 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +248 +138 +64 +248 +138 +64 +250 +139 +73 +250 +139 +73 +247 +143 +74 +247 +143 +74 +250 +139 +73 +250 +139 +73 +248 +138 +64 +247 +130 +60 +247 +130 +60 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +60 +248 +138 +64 +250 +139 +73 +247 +143 +74 +249 +146 +83 +249 +146 +83 +249 +146 +83 +249 +146 +83 +249 +146 +83 +247 +143 +74 +247 +143 +74 +250 +139 +73 +250 +139 +73 +248 +138 +64 +247 +130 +60 +247 +130 +53 +247 +123 +41 +247 +123 +41 +246 +116 +28 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +111 +26 +247 +118 +39 +247 +130 +53 +247 +143 +74 +249 +159 +103 +252 +185 +144 +139 +115 +96 +35 +31 +30 +129 +106 +52 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +117 +98 +55 +35 +31 +30 +152 +119 +47 +168 +127 +42 +168 +127 +42 +160 +120 +43 +168 +127 +42 +171 +129 +45 +152 +119 +47 +216 +194 +154 +224 +207 +180 +160 +120 +43 +160 +120 +43 +137 +110 +49 +102 +91 +75 +35 +31 +30 +115 +102 +92 +250 +200 +166 +250 +176 +132 +249 +159 +103 +249 +146 +83 +247 +130 +60 +247 +123 +41 +246 +116 +28 +247 +111 +26 +246 +116 +28 +247 +123 +41 +248 +138 +64 +249 +152 +92 +249 +174 +124 +236 +186 +153 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +91 +92 +89 +255 +215 +190 +255 +215 +190 +253 +204 +176 +250 +197 +158 +252 +185 +144 +249 +174 +124 +251 +168 +115 +249 +159 +103 +246 +156 +93 +247 +150 +84 +250 +139 +73 +247 +130 +60 +247 +130 +53 +247 +123 +41 +247 +118 +39 +246 +116 +28 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +130 +53 +248 +138 +64 +249 +146 +83 +249 +152 +92 +249 +159 +103 +247 +165 +111 +251 +168 +115 +251 +168 +115 +251 +168 +115 +251 +168 +115 +247 +165 +111 +249 +159 +103 +247 +150 +84 +247 +143 +74 +248 +138 +64 +247 +130 +53 +247 +123 +41 +247 +118 +39 +246 +116 +28 +246 +116 +28 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +130 +60 +250 +139 +73 +249 +146 +83 +249 +152 +92 +249 +159 +103 +247 +165 +111 +251 +168 +115 +251 +168 +115 +251 +168 +115 +251 +168 +115 +247 +165 +111 +247 +165 +111 +247 +165 +111 +249 +159 +103 +249 +159 +103 +246 +156 +93 +247 +150 +84 +249 +146 +83 +247 +143 +74 +248 +138 +64 +247 +130 +60 +247 +130 +60 +247 +130 +60 +248 +138 +64 +250 +139 +73 +249 +146 +83 +249 +152 +92 +249 +159 +103 +249 +159 +103 +247 +165 +111 +251 +168 +115 +251 +168 +115 +251 +168 +115 +251 +168 +115 +247 +165 +111 +247 +165 +111 +249 +159 +103 +247 +165 +111 +251 +168 +115 +250 +176 +132 +252 +185 +144 +250 +200 +166 +255 +215 +190 +217 +187 +166 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +65 +67 +64 +137 +127 +115 +250 +200 +166 +250 +176 +132 +247 +165 +111 +249 +152 +92 +247 +150 +84 +249 +146 +83 +247 +150 +84 +249 +152 +92 +249 +159 +103 +247 +165 +111 +251 +168 +115 +251 +168 +115 +251 +168 +115 +247 +165 +111 +249 +159 +103 +246 +156 +93 +247 +150 +84 +247 +143 +74 +250 +139 +73 +247 +143 +74 +249 +146 +83 +249 +159 +103 +249 +174 +124 +251 +192 +154 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +173 +106 +60 +51 +62 +63 +187 +166 +150 +255 +215 +190 +253 +212 +188 +250 +200 +166 +249 +189 +146 +248 +180 +134 +249 +174 +124 +247 +165 +111 +249 +159 +103 +249 +152 +92 +247 +143 +74 +248 +138 +64 +247 +130 +53 +247 +123 +41 +247 +118 +39 +246 +116 +28 +247 +111 +26 +246 +116 +28 +247 +118 +39 +247 +123 +41 +247 +130 +53 +248 +138 +64 +247 +143 +74 +249 +152 +92 +249 +159 +103 +247 +165 +111 +251 +168 +115 +251 +168 +115 +251 +168 +115 +251 +168 +115 +247 +165 +111 +249 +159 +103 +249 +152 +92 +247 +143 +74 +248 +138 +64 +247 +130 +53 +247 +123 +41 +247 +118 +39 +247 +111 +26 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +53 +248 +138 +64 +247 +143 +74 +247 +150 +84 +249 +159 +103 +249 +159 +103 +247 +165 +111 +251 +168 +115 +251 +168 +115 +251 +168 +115 +251 +168 +115 +247 +165 +111 +247 +165 +111 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +246 +156 +93 +246 +156 +93 +246 +156 +93 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +152 +92 +249 +152 +92 +247 +150 +84 +249 +146 +83 +249 +146 +83 +249 +146 +83 +247 +150 +84 +249 +152 +92 +246 +156 +93 +249 +159 +103 +247 +165 +111 +249 +174 +124 +250 +176 +132 +249 +189 +146 +250 +200 +166 +253 +212 +188 +255 +215 +190 +207 +178 +158 +51 +62 +63 +155 +100 +63 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +249 +189 +146 +247 +165 +111 +247 +143 +74 +247 +130 +53 +246 +116 +28 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +53 +248 +138 +64 +247 +143 +74 +247 +150 +84 +249 +159 +103 +247 +165 +111 +251 +168 +115 +251 +168 +115 +251 +168 +115 +251 +168 +115 +247 +165 +111 +249 +159 +103 +249 +152 +92 +249 +146 +83 +250 +139 +73 +247 +130 +60 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +60 +248 +138 +64 +247 +143 +74 +249 +146 +83 +249 +152 +92 +246 +156 +93 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +249 +159 +103 +246 +156 +93 +249 +152 +92 +247 +150 +84 +249 +146 +83 +247 +143 +74 +247 +143 +74 +247 +143 +74 +249 +146 +83 +247 +150 +84 +246 +156 +93 +249 +159 +103 +247 +165 +111 +247 +165 +111 +251 +168 +115 +251 +168 +115 +251 +168 +115 +247 +165 +111 +247 +165 +111 +247 +165 +111 +249 +159 +103 +249 +159 +103 +246 +156 +93 +247 +150 +84 +247 +143 +74 +248 +138 +64 +247 +130 +53 +247 +123 +41 +247 +118 +39 +247 +111 +26 +246 +109 +10 +247 +103 +7 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +248 +138 +64 +249 +152 +92 +249 +174 +124 +236 +186 +153 +47 +40 +38 +59 +50 +39 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +47 +40 +38 +108 +87 +46 +168 +127 +42 +111 +94 +57 +76 +70 +64 +59 +50 +39 +101 +83 +47 +160 +120 +43 +170 +137 +67 +253 +255 +252 +195 +167 +113 +145 +114 +49 +69 +69 +61 +120 +114 +108 +35 +31 +30 +47 +40 +38 +217 +187 +166 +250 +197 +158 +250 +176 +132 +249 +159 +103 +249 +146 +83 +248 +138 +64 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +130 +53 +250 +139 +73 +246 +156 +93 +250 +176 +132 +232 +190 +161 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +91 +92 +89 +255 +215 +190 +255 +215 +190 +245 +212 +186 +227 +196 +175 +212 +173 +150 +209 +171 +139 +219 +170 +138 +240 +181 +138 +250 +176 +132 +251 +168 +115 +249 +159 +103 +247 +150 +84 +250 +139 +73 +247 +130 +60 +247 +130 +53 +247 +130 +53 +247 +130 +53 +247 +130 +53 +248 +138 +64 +249 +146 +83 +246 +156 +93 +247 +165 +111 +249 +174 +124 +248 +180 +134 +240 +181 +138 +219 +170 +138 +203 +161 +131 +203 +161 +131 +219 +170 +138 +240 +181 +138 +250 +176 +132 +249 +174 +124 +249 +159 +103 +249 +152 +92 +247 +143 +74 +247 +130 +60 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +53 +248 +138 +64 +249 +146 +83 +246 +156 +93 +247 +165 +111 +249 +174 +124 +245 +179 +138 +230 +173 +136 +203 +161 +131 +203 +161 +131 +219 +170 +138 +239 +182 +144 +251 +192 +154 +249 +189 +146 +252 +185 +144 +252 +185 +144 +248 +180 +134 +245 +169 +119 +234 +168 +124 +247 +165 +111 +249 +159 +103 +249 +152 +92 +247 +150 +84 +247 +150 +84 +247 +150 +84 +249 +152 +92 +249 +159 +103 +247 +165 +111 +249 +174 +124 +248 +180 +134 +230 +173 +136 +219 +170 +138 +203 +161 +131 +209 +171 +139 +239 +182 +144 +251 +192 +154 +249 +189 +146 +249 +189 +146 +252 +185 +144 +252 +185 +144 +249 +189 +146 +236 +186 +153 +250 +200 +166 +255 +215 +190 +255 +215 +190 +217 +187 +166 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +65 +67 +64 +137 +127 +115 +253 +204 +176 +252 +185 +144 +249 +174 +124 +247 +165 +111 +247 +165 +111 +247 +165 +111 +251 +168 +115 +249 +174 +124 +248 +180 +134 +230 +173 +136 +219 +170 +138 +203 +161 +131 +209 +171 +139 +230 +173 +136 +245 +179 +138 +250 +176 +132 +251 +168 +115 +249 +159 +103 +249 +159 +103 +246 +156 +93 +249 +159 +103 +251 +168 +115 +248 +180 +134 +250 +197 +158 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +173 +106 +60 +51 +62 +63 +187 +166 +150 +255 +215 +190 +255 +215 +190 +234 +204 +183 +207 +178 +158 +209 +171 +139 +209 +171 +139 +230 +173 +136 +248 +180 +134 +249 +174 +124 +247 +165 +111 +249 +152 +92 +247 +143 +74 +248 +138 +64 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +130 +53 +248 +138 +64 +247 +143 +74 +249 +152 +92 +247 +165 +111 +249 +174 +124 +248 +180 +134 +240 +181 +138 +219 +170 +138 +203 +161 +131 +203 +161 +131 +219 +170 +138 +240 +181 +138 +248 +180 +134 +249 +174 +124 +247 +165 +111 +249 +152 +92 +247 +143 +74 +248 +138 +64 +247 +130 +53 +247 +123 +41 +247 +123 +41 +247 +123 +41 +247 +130 +53 +247 +130 +60 +247 +143 +74 +249 +152 +92 +249 +159 +103 +249 +174 +124 +250 +176 +132 +240 +181 +138 +219 +170 +138 +203 +161 +131 +203 +161 +131 +230 +173 +136 +251 +192 +154 +249 +189 +146 +249 +189 +146 +252 +185 +144 +252 +185 +144 +248 +180 +134 +234 +168 +124 +250 +176 +132 +248 +180 +134 +250 +176 +132 +250 +176 +132 +250 +176 +132 +248 +180 +134 +248 +180 +134 +230 +173 +136 +240 +181 +138 +252 +185 +144 +252 +185 +144 +252 +185 +144 +252 +185 +144 +248 +180 +134 +234 +168 +124 +234 +168 +124 +249 +174 +124 +251 +168 +115 +247 +165 +111 +247 +165 +111 +247 +165 +111 +251 +168 +115 +249 +174 +124 +250 +176 +132 +248 +180 +134 +230 +173 +136 +219 +170 +138 +209 +171 +139 +207 +178 +158 +227 +196 +175 +253 +212 +188 +255 +215 +190 +217 +187 +166 +51 +62 +63 +155 +100 +63 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +249 +189 +146 +247 +165 +111 +247 +143 +74 +247 +130 +53 +246 +116 +28 +247 +111 +26 +246 +109 +10 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +60 +247 +143 +74 +249 +152 +92 +249 +159 +103 +249 +174 +124 +248 +180 +134 +240 +181 +138 +219 +170 +138 +203 +161 +131 +203 +161 +131 +219 +170 +138 +240 +181 +138 +248 +180 +134 +249 +174 +124 +247 +165 +111 +249 +159 +103 +247 +150 +84 +249 +146 +83 +247 +143 +74 +247 +143 +74 +249 +146 +83 +249 +152 +92 +249 +159 +103 +247 +165 +111 +234 +168 +124 +234 +168 +124 +248 +180 +134 +252 +185 +144 +252 +185 +144 +252 +185 +144 +248 +180 +134 +250 +176 +132 +234 +168 +124 +249 +174 +124 +251 +168 +115 +247 +165 +111 +247 +165 +111 +249 +159 +103 +247 +165 +111 +251 +168 +115 +249 +174 +124 +250 +176 +132 +248 +180 +134 +230 +173 +136 +203 +161 +131 +203 +161 +131 +219 +170 +138 +239 +182 +144 +251 +192 +154 +249 +189 +146 +252 +185 +144 +252 +185 +144 +248 +180 +134 +234 +168 +124 +238 +159 +107 +247 +165 +111 +249 +152 +92 +247 +143 +74 +247 +130 +60 +247 +123 +41 +246 +116 +28 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +111 +26 +246 +116 +28 +247 +130 +53 +247 +143 +74 +247 +165 +111 +252 +185 +144 +154 +133 +118 +24 +22 +23 +108 +87 +46 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +71 +60 +43 +85 +71 +43 +101 +83 +47 +89 +84 +82 +152 +147 +147 +24 +22 +23 +24 +22 +23 +108 +87 +46 +168 +127 +42 +224 +207 +180 +253 +255 +252 +209 +171 +139 +101 +83 +47 +24 +22 +23 +35 +31 +30 +35 +31 +30 +167 +142 +123 +253 +212 +188 +250 +197 +158 +248 +180 +134 +247 +165 +111 +247 +150 +84 +250 +139 +73 +247 +130 +60 +247 +130 +60 +248 +138 +64 +249 +146 +83 +249 +159 +103 +250 +176 +132 +232 +190 +161 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +97 +98 +96 +217 +187 +166 +137 +127 +115 +91 +92 +89 +55 +66 +67 +48 +58 +59 +48 +58 +59 +55 +66 +67 +84 +85 +82 +133 +120 +107 +209 +171 +139 +248 +180 +134 +251 +168 +115 +249 +159 +103 +247 +150 +84 +247 +143 +74 +250 +139 +73 +250 +139 +73 +249 +146 +83 +249 +152 +92 +247 +165 +111 +249 +174 +124 +245 +179 +138 +178 +146 +122 +124 +111 +99 +76 +78 +76 +51 +62 +63 +48 +58 +59 +48 +58 +59 +58 +69 +70 +91 +92 +89 +144 +125 +110 +203 +161 +131 +248 +180 +134 +249 +174 +124 +249 +159 +103 +247 +150 +84 +247 +143 +74 +248 +138 +64 +248 +138 +64 +250 +139 +73 +249 +146 +83 +246 +156 +93 +247 +165 +111 +250 +176 +132 +230 +173 +136 +154 +133 +118 +101 +100 +92 +58 +69 +70 +48 +58 +59 +48 +58 +59 +51 +62 +63 +84 +85 +82 +137 +127 +115 +217 +187 +166 +253 +212 +188 +227 +196 +175 +144 +125 +110 +89 +84 +82 +81 +77 +76 +115 +102 +92 +210 +156 +119 +249 +174 +124 +251 +168 +115 +251 +168 +115 +251 +168 +115 +249 +174 +124 +250 +176 +132 +252 +185 +144 +195 +157 +134 +124 +111 +99 +76 +78 +76 +51 +62 +63 +48 +58 +59 +48 +58 +59 +70 +79 +77 +120 +114 +108 +187 +166 +150 +253 +212 +188 +253 +212 +188 +172 +150 +134 +101 +100 +92 +77 +85 +81 +101 +100 +92 +176 +156 +141 +255 +215 +190 +217 +187 +166 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +137 +127 +115 +253 +212 +188 +250 +197 +158 +252 +185 +144 +248 +180 +134 +248 +180 +134 +252 +185 +144 +239 +182 +144 +167 +142 +123 +109 +106 +99 +70 +79 +77 +48 +58 +59 +48 +58 +59 +48 +58 +59 +58 +69 +70 +91 +92 +89 +150 +125 +114 +219 +170 +138 +248 +180 +134 +249 +174 +124 +249 +174 +124 +249 +174 +124 +250 +176 +132 +249 +189 +146 +253 +204 +176 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +234 +125 +52 +183 +110 +59 +51 +62 +63 +176 +156 +141 +187 +166 +150 +109 +106 +99 +63 +74 +74 +43 +57 +62 +43 +57 +62 +43 +57 +62 +63 +74 +74 +109 +106 +99 +178 +146 +122 +245 +179 +138 +249 +174 +124 +249 +159 +103 +247 +150 +84 +247 +143 +74 +248 +138 +64 +248 +138 +64 +248 +138 +64 +247 +143 +74 +247 +150 +84 +249 +159 +103 +249 +174 +124 +252 +185 +144 +195 +157 +134 +124 +111 +99 +77 +85 +81 +51 +62 +63 +41 +58 +57 +43 +57 +62 +51 +62 +63 +77 +85 +81 +124 +111 +99 +195 +157 +134 +252 +185 +144 +249 +174 +124 +249 +159 +103 +247 +150 +84 +247 +143 +74 +248 +138 +64 +247 +130 +60 +248 +138 +64 +250 +139 +73 +247 +150 +84 +249 +159 +103 +251 +168 +115 +248 +180 +134 +203 +161 +131 +124 +111 +99 +77 +85 +81 +48 +58 +59 +43 +57 +62 +43 +57 +62 +63 +74 +74 +109 +106 +99 +187 +166 +150 +253 +212 +188 +253 +212 +188 +187 +166 +150 +109 +106 +99 +77 +85 +81 +84 +85 +82 +150 +125 +114 +232 +190 +161 +253 +204 +176 +253 +204 +176 +172 +150 +134 +101 +100 +92 +77 +85 +81 +91 +92 +89 +137 +127 +115 +227 +196 +175 +253 +212 +188 +186 +157 +134 +109 +106 +99 +77 +85 +81 +84 +85 +82 +124 +111 +99 +219 +170 +138 +249 +189 +146 +249 +189 +146 +249 +189 +146 +251 +192 +154 +250 +197 +158 +186 +157 +134 +109 +106 +99 +70 +79 +77 +43 +57 +62 +43 +57 +62 +41 +58 +57 +63 +74 +74 +101 +100 +92 +176 +156 +141 +194 +173 +157 +55 +66 +67 +155 +100 +63 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +249 +189 +146 +247 +165 +111 +247 +143 +74 +247 +130 +53 +247 +118 +39 +247 +111 +26 +246 +109 +10 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +60 +249 +146 +83 +249 +159 +103 +249 +174 +124 +252 +185 +144 +203 +161 +131 +133 +120 +107 +84 +85 +82 +55 +66 +67 +43 +57 +62 +41 +58 +57 +51 +62 +63 +77 +85 +81 +124 +111 +99 +178 +146 +122 +239 +182 +144 +250 +176 +132 +249 +174 +124 +247 +165 +111 +249 +159 +103 +249 +159 +103 +247 +165 +111 +249 +174 +124 +210 +156 +119 +124 +111 +99 +77 +85 +81 +77 +85 +81 +109 +106 +99 +194 +173 +157 +253 +212 +188 +217 +187 +166 +133 +120 +107 +89 +84 +82 +76 +78 +76 +101 +100 +92 +178 +146 +122 +249 +189 +146 +252 +185 +144 +252 +185 +144 +252 +185 +144 +251 +192 +154 +236 +186 +153 +167 +142 +123 +101 +100 +92 +63 +74 +74 +41 +58 +57 +43 +57 +62 +51 +62 +63 +77 +85 +81 +137 +127 +115 +217 +187 +166 +253 +212 +188 +227 +196 +175 +144 +125 +110 +84 +85 +82 +76 +78 +76 +115 +102 +92 +204 +141 +99 +249 +159 +103 +247 +143 +74 +247 +130 +60 +247 +123 +41 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +248 +138 +64 +249 +152 +92 +249 +174 +124 +250 +197 +158 +82 +69 +65 +47 +40 +38 +152 +119 +47 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +101 +83 +47 +59 +50 +39 +101 +83 +47 +24 +22 +23 +35 +31 +30 +24 +22 +23 +24 +22 +23 +108 +87 +46 +168 +127 +42 +195 +167 +113 +253 +255 +252 +253 +255 +252 +239 +227 +208 +186 +157 +134 +162 +125 +96 +105 +93 +60 +47 +40 +38 +150 +125 +114 +217 +187 +166 +250 +200 +166 +252 +185 +144 +251 +168 +115 +246 +156 +93 +249 +146 +83 +247 +143 +74 +249 +146 +83 +249 +152 +92 +247 +165 +111 +252 +185 +144 +232 +190 +161 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +55 +66 +67 +58 +69 +70 +56 +64 +60 +83 +78 +61 +105 +93 +60 +117 +98 +55 +117 +98 +55 +105 +93 +60 +83 +78 +61 +56 +64 +60 +55 +66 +67 +144 +125 +110 +239 +182 +144 +250 +176 +132 +247 +165 +111 +249 +159 +103 +246 +156 +93 +249 +159 +103 +247 +165 +111 +249 +174 +124 +252 +185 +144 +195 +157 +134 +89 +84 +82 +48 +58 +59 +63 +69 +60 +95 +87 +59 +111 +94 +57 +123 +102 +54 +117 +98 +55 +105 +93 +60 +83 +78 +61 +56 +64 +60 +51 +62 +63 +124 +111 +99 +219 +170 +138 +248 +180 +134 +251 +168 +115 +249 +159 +103 +249 +152 +92 +249 +152 +92 +246 +156 +93 +247 +165 +111 +249 +174 +124 +252 +185 +144 +167 +142 +123 +70 +79 +77 +51 +62 +63 +75 +74 +61 +100 +89 +56 +117 +98 +55 +123 +102 +54 +105 +93 +60 +83 +78 +61 +51 +62 +63 +63 +74 +74 +172 +150 +134 +109 +106 +99 +51 +62 +63 +83 +78 +61 +95 +87 +59 +65 +67 +64 +65 +67 +64 +209 +171 +139 +249 +189 +146 +249 +189 +146 +249 +189 +146 +250 +197 +158 +212 +173 +150 +109 +106 +99 +48 +58 +59 +63 +69 +60 +95 +87 +59 +111 +94 +57 +123 +102 +54 +117 +98 +55 +95 +87 +59 +62 +63 +61 +48 +58 +59 +137 +127 +115 +146 +135 +124 +48 +58 +59 +75 +74 +61 +95 +87 +59 +75 +74 +61 +48 +58 +59 +161 +144 +134 +217 +187 +166 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +137 +127 +115 +255 +215 +190 +251 +209 +178 +250 +200 +166 +250 +200 +166 +250 +200 +166 +172 +150 +134 +77 +85 +81 +48 +58 +59 +69 +69 +61 +95 +87 +59 +111 +94 +57 +123 +102 +54 +117 +98 +55 +100 +89 +56 +75 +74 +61 +56 +64 +60 +55 +66 +67 +133 +120 +107 +236 +186 +153 +251 +192 +154 +249 +189 +146 +251 +192 +154 +250 +200 +166 +253 +212 +188 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +173 +106 +60 +51 +62 +63 +63 +74 +74 +48 +58 +59 +76 +70 +64 +118 +86 +65 +146 +97 +64 +155 +100 +63 +146 +97 +64 +118 +86 +65 +76 +70 +64 +43 +57 +62 +91 +92 +89 +203 +161 +131 +248 +180 +134 +251 +168 +115 +249 +159 +103 +249 +152 +92 +247 +150 +84 +249 +152 +92 +249 +159 +103 +251 +168 +115 +248 +180 +134 +209 +171 +139 +101 +100 +92 +43 +57 +62 +69 +69 +61 +106 +82 +65 +135 +94 +64 +155 +100 +63 +155 +100 +63 +135 +94 +64 +106 +82 +65 +65 +67 +64 +43 +57 +62 +101 +100 +92 +209 +171 +139 +248 +180 +134 +251 +168 +115 +249 +159 +103 +249 +152 +92 +247 +150 +84 +247 +150 +84 +246 +156 +93 +247 +165 +111 +250 +176 +132 +219 +170 +138 +124 +111 +99 +48 +58 +59 +62 +63 +61 +106 +82 +65 +139 +96 +61 +155 +100 +63 +146 +97 +64 +125 +90 +64 +76 +70 +64 +41 +58 +57 +120 +114 +108 +172 +150 +134 +51 +62 +63 +69 +69 +61 +112 +85 +63 +95 +78 +64 +51 +62 +63 +120 +114 +108 +245 +212 +186 +146 +135 +124 +43 +57 +62 +81 +73 +62 +118 +86 +65 +95 +78 +64 +56 +64 +60 +101 +100 +92 +133 +120 +107 +43 +57 +62 +76 +70 +64 +112 +85 +63 +106 +82 +65 +62 +63 +61 +77 +85 +81 +227 +196 +175 +253 +212 +188 +253 +212 +188 +217 +187 +166 +109 +106 +99 +41 +58 +57 +69 +69 +61 +112 +85 +63 +139 +96 +61 +155 +100 +63 +146 +97 +64 +118 +86 +65 +81 +73 +62 +48 +58 +59 +58 +69 +70 +51 +62 +63 +155 +100 +63 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +192 +154 +247 +165 +111 +249 +146 +83 +247 +130 +53 +247 +118 +39 +247 +111 +26 +247 +111 +26 +246 +116 +28 +247 +123 +41 +248 +138 +64 +249 +146 +83 +249 +159 +103 +250 +176 +132 +219 +170 +138 +124 +111 +99 +43 +57 +62 +62 +63 +61 +106 +82 +65 +135 +94 +64 +155 +100 +63 +155 +100 +63 +139 +96 +61 +106 +82 +65 +69 +69 +61 +43 +57 +62 +91 +92 +89 +195 +157 +134 +251 +192 +154 +252 +185 +144 +248 +180 +134 +248 +180 +134 +252 +185 +144 +203 +161 +131 +63 +74 +74 +62 +63 +61 +106 +82 +65 +112 +85 +63 +69 +69 +61 +55 +66 +67 +146 +135 +124 +63 +74 +74 +56 +64 +60 +95 +78 +64 +112 +85 +63 +76 +70 +64 +48 +58 +59 +172 +150 +134 +253 +204 +176 +251 +209 +178 +251 +209 +178 +187 +166 +150 +77 +85 +81 +48 +58 +59 +81 +73 +62 +125 +90 +64 +146 +97 +64 +155 +100 +63 +139 +96 +61 +95 +78 +64 +56 +64 +60 +58 +69 +70 +161 +144 +134 +109 +106 +99 +51 +62 +63 +95 +78 +64 +112 +85 +63 +65 +67 +64 +65 +67 +64 +204 +141 +99 +246 +156 +93 +250 +139 +73 +247 +130 +53 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +246 +116 +28 +247 +130 +53 +247 +143 +74 +249 +159 +103 +252 +185 +144 +209 +171 +139 +24 +22 +23 +85 +71 +43 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +137 +110 +49 +47 +40 +38 +137 +110 +49 +101 +83 +47 +59 +50 +39 +59 +50 +39 +101 +83 +47 +158 +125 +46 +160 +120 +43 +192 +155 +91 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +237 +233 +225 +152 +147 +147 +81 +77 +76 +55 +48 +48 +115 +102 +92 +212 +173 +150 +251 +192 +154 +249 +174 +124 +247 +165 +111 +249 +159 +103 +249 +159 +103 +247 +165 +111 +249 +174 +124 +249 +189 +146 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +43 +57 +62 +95 +87 +59 +145 +114 +49 +168 +127 +42 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +168 +127 +42 +145 +114 +49 +95 +87 +59 +48 +58 +59 +109 +106 +99 +236 +186 +153 +252 +185 +144 +248 +180 +134 +250 +176 +132 +250 +176 +132 +252 +185 +144 +251 +192 +154 +150 +125 +114 +48 +58 +59 +69 +69 +61 +117 +98 +55 +158 +125 +46 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +168 +127 +42 +152 +119 +47 +100 +89 +56 +56 +64 +60 +63 +74 +74 +186 +157 +134 +249 +189 +146 +248 +180 +134 +249 +174 +124 +249 +174 +124 +250 +176 +132 +252 +185 +144 +251 +192 +154 +133 +120 +107 +48 +58 +59 +75 +74 +61 +137 +110 +49 +168 +127 +42 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +145 +114 +49 +75 +74 +61 +43 +57 +62 +51 +62 +63 +123 +102 +54 +171 +129 +45 +171 +129 +45 +145 +114 +49 +56 +64 +60 +133 +120 +107 +253 +212 +188 +251 +209 +178 +253 +212 +188 +194 +173 +157 +63 +74 +74 +56 +64 +60 +111 +94 +57 +158 +125 +46 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +158 +125 +46 +105 +93 +60 +51 +62 +63 +43 +57 +62 +88 +82 +59 +168 +127 +42 +171 +129 +45 +168 +127 +42 +88 +82 +59 +63 +74 +74 +187 +166 +150 +55 +66 +67 +111 +94 +57 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +137 +127 +115 +255 +215 +190 +255 +215 +190 +255 +215 +190 +245 +212 +186 +133 +120 +107 +48 +58 +59 +75 +74 +61 +129 +106 +52 +158 +125 +46 +171 +129 +45 +171 +129 +45 +171 +129 +45 +168 +127 +42 +171 +129 +45 +168 +127 +42 +145 +114 +49 +95 +87 +59 +51 +62 +63 +77 +85 +81 +212 +173 +150 +253 +204 +176 +253 +204 +176 +251 +209 +178 +255 +215 +190 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +41 +58 +57 +69 +69 +61 +155 +100 +63 +214 +121 +50 +234 +126 +45 +234 +126 +45 +234 +126 +45 +234 +126 +45 +234 +126 +45 +224 +123 +55 +155 +100 +63 +69 +69 +61 +51 +62 +63 +178 +146 +122 +249 +189 +146 +250 +176 +132 +251 +168 +115 +251 +168 +115 +249 +174 +124 +250 +176 +132 +249 +189 +146 +167 +142 +123 +55 +66 +67 +65 +67 +64 +146 +97 +64 +212 +120 +56 +234 +126 +45 +234 +125 +52 +234 +126 +45 +234 +125 +52 +234 +126 +45 +234 +125 +52 +209 +117 +53 +146 +97 +64 +65 +67 +64 +55 +66 +67 +178 +146 +122 +249 +189 +146 +250 +176 +132 +251 +168 +115 +247 +165 +111 +251 +168 +115 +249 +174 +124 +252 +185 +144 +203 +161 +131 +63 +74 +74 +56 +64 +60 +125 +90 +64 +209 +117 +53 +234 +126 +45 +234 +126 +45 +234 +125 +52 +234 +126 +45 +234 +126 +45 +214 +121 +50 +146 +97 +64 +56 +64 +60 +41 +58 +57 +81 +73 +62 +209 +117 +53 +234 +126 +45 +234 +126 +45 +125 +90 +64 +51 +62 +63 +176 +156 +141 +55 +66 +67 +106 +82 +65 +225 +124 +48 +234 +126 +45 +234 +126 +45 +146 +97 +64 +41 +58 +57 +43 +57 +62 +125 +90 +64 +214 +121 +50 +234 +126 +45 +234 +126 +45 +183 +110 +59 +56 +64 +60 +137 +127 +115 +255 +215 +190 +194 +173 +157 +63 +74 +74 +62 +63 +61 +146 +97 +64 +214 +121 +50 +234 +125 +52 +234 +126 +45 +234 +125 +52 +234 +125 +52 +234 +126 +45 +225 +124 +48 +173 +106 +60 +81 +73 +62 +35 +56 +60 +155 +100 +63 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +192 +154 +247 +165 +111 +249 +146 +83 +247 +130 +53 +247 +118 +39 +246 +116 +28 +246 +116 +28 +247 +123 +41 +247 +130 +60 +249 +146 +83 +247 +165 +111 +248 +180 +134 +186 +157 +134 +58 +69 +70 +56 +64 +60 +135 +94 +64 +199 +115 +54 +234 +125 +52 +234 +126 +45 +234 +125 +52 +234 +125 +52 +234 +126 +45 +234 +125 +52 +212 +120 +56 +155 +100 +63 +76 +70 +64 +51 +62 +63 +146 +135 +124 +251 +209 +178 +253 +204 +176 +250 +200 +166 +253 +204 +176 +101 +100 +92 +69 +69 +61 +194 +112 +58 +234 +126 +45 +234 +126 +45 +199 +115 +54 +65 +67 +64 +35 +56 +60 +81 +73 +62 +194 +112 +58 +234 +125 +52 +234 +126 +45 +214 +121 +50 +95 +78 +64 +63 +74 +74 +238 +205 +179 +255 +215 +190 +161 +144 +134 +43 +57 +62 +81 +73 +62 +173 +106 +60 +225 +124 +48 +234 +126 +45 +234 +126 +45 +234 +125 +52 +234 +126 +45 +234 +126 +45 +194 +112 +58 +95 +78 +64 +41 +58 +57 +48 +58 +59 +155 +100 +63 +234 +126 +45 +234 +126 +45 +199 +115 +54 +69 +69 +61 +99 +90 +79 +251 +168 +115 +247 +150 +84 +247 +130 +60 +247 +123 +41 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +103 +7 +247 +111 +26 +247 +118 +39 +247 +130 +60 +247 +150 +84 +249 +174 +124 +251 +192 +154 +124 +111 +99 +35 +31 +30 +137 +110 +49 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +47 +40 +38 +108 +87 +46 +175 +132 +40 +161 +127 +40 +168 +127 +42 +171 +129 +45 +158 +125 +46 +152 +119 +47 +203 +161 +131 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +186 +181 +179 +89 +84 +82 +47 +40 +38 +139 +115 +96 +236 +186 +153 +252 +185 +144 +250 +176 +132 +249 +174 +124 +250 +176 +132 +252 +185 +144 +250 +197 +158 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +111 +94 +57 +171 +129 +45 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +111 +94 +57 +48 +58 +59 +109 +106 +99 +253 +204 +176 +250 +200 +166 +250 +200 +166 +250 +200 +166 +253 +204 +176 +137 +127 +115 +43 +57 +62 +88 +82 +59 +158 +125 +46 +171 +129 +45 +161 +127 +40 +158 +125 +46 +158 +125 +46 +168 +127 +42 +161 +127 +40 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +145 +114 +49 +69 +69 +61 +51 +62 +63 +187 +166 +150 +250 +200 +166 +250 +197 +158 +251 +192 +154 +250 +197 +158 +253 +204 +176 +133 +120 +107 +48 +58 +59 +95 +87 +59 +168 +127 +42 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +158 +125 +46 +75 +74 +61 +62 +63 +61 +168 +127 +42 +161 +127 +40 +158 +125 +46 +171 +129 +45 +83 +78 +61 +91 +92 +89 +255 +215 +190 +255 +215 +190 +207 +178 +158 +58 +69 +70 +63 +69 +60 +145 +114 +49 +171 +129 +45 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +105 +93 +60 +43 +57 +62 +137 +110 +49 +171 +129 +45 +158 +125 +46 +171 +129 +45 +137 +110 +49 +51 +62 +63 +146 +135 +124 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +152 +119 +47 +65 +67 +64 +137 +127 +115 +255 +215 +190 +255 +215 +190 +245 +212 +186 +120 +114 +108 +48 +58 +59 +100 +89 +56 +168 +127 +42 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +129 +106 +52 +61 +67 +58 +63 +74 +74 +207 +178 +158 +255 +215 +190 +255 +215 +190 +255 +215 +190 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +234 +125 +52 +173 +106 +60 +95 +78 +64 +209 +117 +53 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +126 +45 +209 +117 +53 +89 +75 +66 +51 +62 +63 +187 +166 +150 +250 +197 +158 +251 +192 +154 +249 +189 +146 +251 +192 +154 +250 +200 +166 +161 +144 +134 +41 +58 +57 +95 +78 +64 +199 +115 +54 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +126 +45 +199 +115 +54 +89 +75 +66 +41 +58 +57 +167 +142 +123 +250 +200 +166 +251 +192 +154 +252 +185 +144 +249 +189 +146 +250 +197 +158 +212 +173 +150 +63 +74 +74 +69 +69 +61 +183 +110 +59 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +126 +45 +163 +104 +61 +41 +58 +57 +135 +94 +64 +234 +126 +45 +224 +123 +55 +234 +125 +52 +188 +112 +56 +51 +62 +63 +109 +106 +99 +51 +62 +63 +188 +112 +56 +234 +126 +45 +224 +123 +55 +234 +125 +52 +188 +112 +56 +43 +57 +62 +112 +85 +63 +234 +126 +45 +227 +126 +50 +224 +123 +55 +227 +126 +50 +234 +126 +45 +95 +78 +64 +109 +106 +99 +217 +187 +166 +58 +69 +70 +69 +69 +61 +188 +112 +56 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +214 +121 +50 +95 +78 +64 +146 +97 +64 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +192 +154 +247 +165 +111 +249 +146 +83 +247 +130 +53 +247 +123 +41 +247 +118 +39 +247 +123 +41 +247 +130 +53 +247 +143 +74 +249 +159 +103 +250 +176 +132 +186 +157 +134 +51 +62 +63 +81 +73 +62 +188 +112 +56 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +126 +45 +212 +120 +56 +106 +82 +65 +41 +58 +57 +146 +135 +124 +255 +215 +190 +255 +215 +190 +234 +204 +183 +63 +74 +74 +125 +90 +64 +234 +126 +45 +224 +123 +55 +227 +126 +50 +234 +125 +52 +89 +75 +66 +62 +63 +61 +199 +115 +54 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +126 +45 +163 +104 +61 +48 +58 +59 +217 +187 +166 +172 +150 +134 +41 +58 +57 +106 +82 +65 +214 +121 +50 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +225 +124 +48 +81 +73 +62 +69 +69 +61 +227 +126 +50 +227 +126 +50 +224 +123 +55 +238 +123 +45 +125 +90 +64 +55 +66 +67 +250 +176 +132 +246 +156 +93 +250 +139 +73 +247 +123 +41 +247 +111 +26 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +250 +139 +73 +249 +159 +103 +248 +180 +134 +232 +190 +161 +47 +40 +38 +71 +60 +43 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +71 +60 +43 +71 +60 +43 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +160 +120 +43 +170 +137 +67 +237 +233 +225 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +186 +181 +179 +74 +68 +68 +89 +75 +66 +212 +173 +150 +250 +197 +158 +251 +192 +154 +249 +189 +146 +251 +192 +154 +253 +204 +176 +234 +204 +183 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +152 +119 +47 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +171 +129 +45 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +111 +94 +57 +48 +58 +59 +161 +144 +134 +255 +215 +190 +255 +215 +190 +255 +215 +190 +172 +150 +134 +48 +58 +59 +95 +87 +59 +168 +127 +42 +168 +127 +42 +158 +125 +46 +161 +127 +40 +171 +129 +45 +158 +125 +46 +152 +119 +47 +152 +119 +47 +168 +127 +42 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +152 +119 +47 +69 +69 +61 +58 +69 +70 +217 +187 +166 +255 +215 +190 +255 +215 +190 +255 +215 +190 +172 +150 +134 +43 +57 +62 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +171 +129 +45 +171 +129 +45 +158 +125 +46 +168 +127 +42 +137 +110 +49 +83 +78 +61 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +84 +85 +82 +255 +215 +190 +238 +205 +179 +84 +85 +82 +62 +63 +61 +145 +114 +49 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +171 +129 +45 +171 +129 +45 +168 +127 +42 +161 +127 +40 +158 +125 +46 +88 +82 +59 +152 +119 +47 +161 +127 +40 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +152 +119 +47 +63 +69 +60 +137 +127 +115 +255 +215 +190 +255 +215 +190 +137 +127 +115 +48 +58 +59 +105 +93 +60 +171 +129 +45 +161 +127 +40 +158 +125 +46 +168 +127 +42 +168 +127 +42 +158 +125 +46 +152 +119 +47 +152 +119 +47 +168 +127 +42 +171 +129 +45 +158 +125 +46 +158 +125 +46 +171 +129 +45 +145 +114 +49 +62 +63 +61 +70 +79 +77 +227 +196 +175 +255 +215 +190 +255 +215 +190 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +212 +120 +56 +214 +121 +50 +227 +126 +50 +224 +123 +55 +227 +126 +50 +234 +126 +45 +234 +126 +45 +234 +125 +52 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +209 +117 +53 +76 +70 +64 +70 +79 +77 +234 +204 +183 +253 +212 +188 +251 +209 +178 +253 +212 +188 +187 +166 +150 +43 +57 +62 +95 +78 +64 +225 +124 +48 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +234 +126 +45 +234 +126 +45 +227 +126 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +125 +52 +214 +121 +50 +95 +78 +64 +48 +58 +59 +194 +173 +157 +253 +212 +188 +251 +209 +178 +251 +209 +178 +245 +212 +186 +91 +92 +89 +62 +63 +61 +188 +112 +56 +234 +126 +45 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +234 +125 +52 +234 +126 +45 +227 +126 +50 +224 +123 +55 +234 +126 +45 +125 +90 +64 +146 +97 +64 +234 +125 +52 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +97 +98 +96 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +224 +123 +55 +212 +120 +56 +183 +110 +59 +214 +121 +50 +227 +126 +50 +224 +123 +55 +227 +126 +50 +227 +126 +50 +234 +126 +45 +95 +78 +64 +84 +85 +82 +91 +92 +89 +62 +63 +61 +188 +112 +56 +234 +126 +45 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +234 +126 +45 +234 +126 +45 +227 +126 +50 +224 +123 +55 +227 +126 +50 +224 +123 +55 +209 +117 +53 +227 +126 +50 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +192 +154 +247 +165 +111 +249 +146 +83 +247 +130 +60 +247 +123 +41 +247 +123 +41 +247 +130 +53 +248 +138 +64 +249 +152 +92 +249 +174 +124 +209 +171 +139 +58 +69 +70 +81 +73 +62 +209 +117 +53 +234 +125 +52 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +234 +125 +52 +234 +125 +52 +234 +125 +52 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +112 +85 +63 +41 +58 +57 +172 +150 +134 +255 +215 +190 +227 +196 +175 +63 +74 +74 +135 +94 +64 +234 +125 +52 +224 +123 +55 +224 +123 +55 +224 +123 +55 +194 +112 +58 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +238 +128 +40 +163 +104 +61 +55 +66 +67 +161 +144 +134 +58 +69 +70 +95 +78 +64 +225 +124 +48 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +234 +126 +45 +234 +126 +45 +234 +125 +52 +227 +126 +50 +234 +125 +52 +173 +106 +60 +118 +86 +65 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +125 +52 +146 +97 +64 +51 +62 +63 +252 +185 +144 +249 +159 +103 +247 +143 +74 +247 +130 +53 +246 +116 +28 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +111 +26 +247 +118 +39 +247 +130 +53 +249 +146 +83 +251 +168 +115 +251 +192 +154 +154 +133 +118 +24 +22 +23 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +108 +87 +46 +47 +40 +38 +158 +125 +46 +158 +125 +46 +158 +125 +46 +160 +120 +43 +156 +125 +62 +224 +207 +180 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +152 +147 +147 +35 +31 +30 +55 +48 +48 +154 +133 +118 +217 +187 +166 +253 +204 +176 +253 +204 +176 +253 +212 +188 +234 +204 +183 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +158 +125 +46 +168 +127 +42 +158 +125 +46 +123 +102 +54 +105 +93 +60 +111 +94 +57 +129 +106 +52 +168 +127 +42 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +83 +78 +61 +58 +69 +70 +227 +196 +175 +255 +215 +190 +217 +187 +166 +58 +69 +70 +75 +74 +61 +168 +127 +42 +161 +127 +40 +158 +125 +46 +168 +127 +42 +152 +119 +47 +105 +93 +60 +69 +69 +61 +62 +63 +61 +62 +63 +61 +75 +74 +61 +117 +98 +55 +161 +127 +40 +161 +127 +40 +158 +125 +46 +171 +129 +45 +145 +114 +49 +56 +64 +60 +97 +98 +96 +245 +212 +186 +255 +215 +190 +227 +196 +175 +63 +74 +74 +75 +74 +61 +158 +125 +46 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +158 +125 +46 +129 +106 +52 +111 +94 +57 +105 +93 +60 +129 +106 +52 +158 +125 +46 +168 +127 +42 +161 +127 +40 +152 +119 +47 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +84 +85 +82 +255 +215 +190 +161 +144 +134 +48 +58 +59 +123 +102 +54 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +117 +98 +55 +105 +93 +60 +117 +98 +55 +145 +114 +49 +171 +129 +45 +168 +127 +42 +152 +119 +47 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +137 +127 +115 +255 +215 +190 +194 +173 +157 +48 +58 +59 +88 +82 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +152 +119 +47 +95 +87 +59 +69 +69 +61 +62 +63 +61 +62 +63 +61 +83 +78 +61 +123 +102 +54 +168 +127 +42 +161 +127 +40 +158 +125 +46 +171 +129 +45 +129 +106 +52 +51 +62 +63 +120 +114 +108 +255 +215 +190 +255 +215 +190 +161 +144 +134 +56 +64 +60 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +227 +126 +50 +227 +126 +50 +188 +112 +56 +146 +97 +64 +135 +94 +64 +146 +97 +64 +199 +115 +54 +234 +125 +52 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +126 +45 +173 +106 +60 +48 +58 +59 +146 +135 +124 +255 +215 +190 +255 +215 +190 +234 +204 +183 +77 +85 +81 +76 +70 +64 +214 +121 +50 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +214 +121 +50 +163 +104 +61 +135 +94 +64 +135 +94 +64 +163 +104 +61 +224 +123 +55 +234 +125 +52 +224 +123 +55 +224 +123 +55 +227 +126 +50 +212 +120 +56 +76 +70 +64 +77 +85 +81 +238 +205 +179 +255 +215 +190 +255 +215 +190 +161 +144 +134 +48 +58 +59 +155 +100 +63 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +199 +115 +54 +155 +100 +63 +135 +94 +64 +146 +97 +64 +188 +112 +56 +227 +126 +50 +227 +126 +50 +214 +121 +50 +209 +117 +53 +227 +126 +50 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +125 +52 +227 +126 +50 +224 +123 +55 +227 +126 +50 +227 +126 +50 +199 +115 +54 +125 +90 +64 +51 +62 +63 +55 +66 +67 +41 +58 +57 +146 +97 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +126 +45 +209 +117 +53 +155 +100 +63 +135 +94 +64 +139 +96 +61 +183 +110 +59 +227 +126 +50 +227 +126 +50 +227 +126 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +192 +154 +247 +165 +111 +249 +146 +83 +247 +130 +60 +247 +130 +53 +247 +130 +53 +247 +130 +60 +249 +146 +83 +247 +165 +111 +252 +185 +144 +101 +100 +92 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +173 +106 +60 +135 +94 +64 +135 +94 +64 +163 +104 +61 +214 +121 +50 +234 +125 +52 +224 +123 +55 +224 +123 +55 +227 +126 +50 +224 +123 +55 +81 +73 +62 +58 +69 +70 +227 +196 +175 +234 +204 +183 +63 +74 +74 +135 +94 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +224 +123 +55 +227 +126 +50 +234 +125 +52 +212 +120 +56 +155 +100 +63 +69 +69 +61 +76 +78 +76 +84 +85 +82 +65 +67 +64 +209 +117 +53 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +183 +110 +59 +139 +96 +61 +135 +94 +64 +155 +100 +63 +209 +117 +53 +234 +125 +52 +224 +123 +55 +212 +120 +56 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +126 +45 +139 +96 +61 +55 +66 +67 +251 +192 +154 +251 +168 +115 +249 +146 +83 +247 +130 +53 +247 +118 +39 +246 +109 +10 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +248 +138 +64 +249 +152 +92 +250 +176 +132 +232 +190 +161 +65 +58 +56 +59 +50 +39 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +47 +40 +38 +129 +106 +52 +168 +127 +42 +160 +120 +43 +158 +125 +46 +224 +207 +180 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +219 +212 +208 +62 +63 +61 +35 +31 +30 +91 +92 +89 +164 +158 +157 +186 +181 +179 +82 +69 +65 +176 +156 +141 +255 +215 +190 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +129 +106 +52 +65 +67 +64 +48 +58 +59 +55 +66 +67 +55 +66 +67 +48 +58 +59 +83 +78 +61 +145 +114 +49 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +137 +110 +49 +51 +62 +63 +146 +135 +124 +255 +215 +190 +120 +114 +108 +56 +64 +60 +145 +114 +49 +171 +129 +45 +158 +125 +46 +168 +127 +42 +152 +119 +47 +69 +69 +61 +43 +57 +62 +109 +106 +99 +146 +135 +124 +137 +127 +115 +91 +92 +89 +43 +57 +62 +88 +82 +59 +158 +125 +46 +161 +127 +40 +158 +125 +46 +171 +129 +45 +117 +98 +55 +48 +58 +59 +172 +150 +134 +255 +215 +190 +146 +135 +124 +51 +62 +63 +137 +110 +49 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +75 +74 +61 +48 +58 +59 +55 +66 +67 +55 +66 +67 +48 +58 +59 +69 +69 +61 +137 +110 +49 +168 +127 +42 +161 +127 +40 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +91 +92 +89 +234 +204 +183 +70 +79 +77 +83 +78 +61 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +111 +94 +57 +56 +64 +60 +43 +57 +62 +58 +69 +70 +48 +58 +59 +56 +64 +60 +100 +89 +56 +158 +125 +46 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +111 +94 +57 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +65 +67 +64 +137 +127 +115 +255 +215 +190 +97 +98 +96 +62 +63 +61 +152 +119 +47 +168 +127 +42 +158 +125 +46 +168 +127 +42 +137 +110 +49 +62 +63 +61 +51 +62 +63 +120 +114 +108 +146 +135 +124 +137 +127 +115 +84 +85 +82 +43 +57 +62 +95 +87 +59 +168 +127 +42 +158 +125 +46 +158 +125 +46 +171 +129 +45 +100 +89 +56 +43 +57 +62 +194 +173 +157 +255 +215 +190 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +224 +123 +55 +118 +86 +65 +51 +62 +63 +43 +57 +62 +58 +69 +70 +41 +58 +57 +56 +64 +60 +146 +97 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +106 +82 +65 +63 +74 +74 +234 +204 +183 +255 +215 +190 +161 +144 +134 +48 +58 +59 +173 +106 +60 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +183 +110 +59 +76 +70 +64 +43 +57 +62 +55 +66 +67 +55 +66 +67 +48 +58 +59 +81 +73 +62 +183 +110 +59 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +126 +45 +163 +104 +61 +48 +58 +59 +161 +144 +134 +255 +215 +190 +234 +204 +183 +63 +74 +74 +95 +78 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +135 +94 +64 +62 +63 +61 +43 +57 +62 +58 +69 +70 +43 +57 +62 +51 +62 +63 +125 +90 +64 +225 +124 +48 +227 +126 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +97 +98 +96 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +125 +52 +227 +126 +50 +173 +106 +60 +95 +78 +64 +56 +64 +60 +51 +62 +63 +120 +114 +108 +70 +79 +77 +89 +75 +66 +225 +124 +48 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +163 +104 +61 +65 +67 +64 +41 +58 +57 +55 +66 +67 +51 +62 +63 +48 +58 +59 +106 +82 +65 +209 +117 +53 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +192 +154 +247 +165 +111 +249 +146 +83 +248 +138 +64 +247 +130 +53 +247 +130 +60 +250 +139 +73 +246 +156 +93 +250 +176 +132 +186 +157 +134 +41 +58 +57 +146 +97 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +125 +52 +199 +115 +54 +89 +75 +66 +48 +58 +59 +51 +62 +63 +55 +66 +67 +43 +57 +62 +76 +70 +64 +173 +106 +60 +234 +125 +52 +224 +123 +55 +224 +123 +55 +227 +126 +50 +183 +110 +59 +51 +62 +63 +137 +127 +115 +234 +204 +183 +63 +74 +74 +135 +94 +64 +234 +125 +52 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +126 +45 +199 +115 +54 +125 +90 +64 +69 +69 +61 +41 +58 +57 +97 +98 +96 +146 +135 +124 +51 +62 +63 +146 +97 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +214 +121 +50 +106 +82 +65 +48 +58 +59 +51 +62 +63 +55 +66 +67 +41 +58 +57 +65 +67 +64 +163 +104 +61 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +125 +52 +139 +96 +61 +55 +66 +67 +250 +197 +158 +251 +168 +115 +247 +150 +84 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +246 +116 +28 +247 +130 +53 +247 +143 +74 +249 +159 +103 +252 +185 +144 +154 +133 +118 +24 +22 +23 +108 +87 +46 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +71 +60 +43 +85 +71 +43 +171 +129 +45 +160 +120 +43 +216 +194 +154 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +237 +233 +225 +65 +58 +56 +62 +63 +61 +219 +212 +208 +253 +255 +252 +237 +233 +225 +120 +114 +108 +35 +31 +30 +55 +48 +48 +227 +196 +175 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +129 +106 +52 +51 +62 +63 +84 +85 +82 +187 +166 +150 +227 +196 +175 +227 +196 +175 +161 +144 +134 +51 +62 +63 +69 +69 +61 +152 +119 +47 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +91 +92 +89 +217 +187 +166 +55 +66 +67 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +75 +74 +61 +58 +69 +70 +187 +166 +150 +255 +215 +190 +255 +215 +190 +255 +215 +190 +245 +212 +186 +161 +144 +134 +43 +57 +62 +100 +89 +56 +171 +129 +45 +158 +125 +46 +158 +125 +46 +161 +127 +40 +75 +74 +61 +84 +85 +82 +234 +204 +183 +76 +78 +76 +88 +82 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +62 +63 +61 +63 +74 +74 +176 +156 +141 +227 +196 +175 +227 +196 +175 +176 +156 +141 +70 +79 +77 +62 +63 +61 +145 +114 +49 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +97 +98 +96 +172 +150 +134 +48 +58 +59 +129 +106 +52 +168 +127 +42 +158 +125 +46 +158 +125 +46 +171 +129 +45 +105 +93 +60 +43 +57 +62 +120 +114 +108 +207 +178 +158 +227 +196 +175 +217 +187 +166 +120 +114 +108 +41 +58 +57 +95 +87 +59 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +56 +64 +60 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +65 +67 +64 +146 +135 +124 +207 +178 +158 +48 +58 +59 +111 +94 +57 +171 +129 +45 +158 +125 +46 +168 +127 +42 +152 +119 +47 +62 +63 +61 +70 +79 +77 +207 +178 +158 +255 +215 +190 +255 +215 +190 +255 +215 +190 +238 +205 +179 +137 +127 +115 +43 +57 +62 +117 +98 +55 +168 +127 +42 +158 +125 +46 +168 +127 +42 +152 +119 +47 +62 +63 +61 +109 +106 +99 +255 +215 +190 +161 +144 +134 +56 +64 +60 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +106 +82 +65 +41 +58 +57 +137 +127 +115 +217 +187 +166 +227 +196 +175 +207 +178 +158 +109 +106 +99 +41 +58 +57 +146 +97 +64 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +173 +106 +60 +48 +58 +59 +176 +156 +141 +245 +212 +186 +70 +79 +77 +95 +78 +64 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +188 +112 +56 +56 +64 +60 +70 +79 +77 +176 +156 +141 +227 +196 +175 +227 +196 +175 +176 +156 +141 +63 +74 +74 +62 +63 +61 +194 +112 +58 +227 +126 +50 +224 +123 +55 +227 +126 +50 +227 +126 +50 +95 +78 +64 +77 +85 +81 +245 +212 +186 +172 +150 +134 +48 +58 +59 +173 +106 +60 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +125 +52 +135 +94 +64 +35 +56 +60 +120 +114 +108 +207 +178 +158 +227 +196 +175 +217 +187 +166 +133 +120 +107 +35 +56 +60 +118 +86 +65 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +95 +78 +64 +48 +58 +59 +70 +79 +77 +146 +135 +124 +217 +187 +166 +207 +178 +158 +51 +62 +63 +155 +100 +63 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +125 +52 +163 +104 +61 +48 +58 +59 +91 +92 +89 +194 +173 +157 +227 +196 +175 +217 +187 +166 +146 +135 +124 +43 +57 +62 +89 +75 +66 +214 +121 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +192 +154 +247 +165 +111 +247 +150 +84 +248 +138 +64 +247 +130 +60 +248 +138 +64 +249 +146 +83 +247 +165 +111 +239 +182 +144 +91 +92 +89 +76 +70 +64 +224 +123 +55 +227 +126 +50 +224 +123 +55 +227 +126 +50 +209 +117 +53 +76 +70 +64 +55 +66 +67 +172 +150 +134 +227 +196 +175 +227 +196 +175 +187 +166 +150 +77 +85 +81 +51 +62 +63 +173 +106 +60 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +118 +86 +65 +58 +69 +70 +217 +187 +166 +70 +79 +77 +135 +94 +64 +234 +125 +52 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +225 +124 +48 +125 +90 +64 +56 +64 +60 +55 +66 +67 +120 +114 +108 +187 +166 +150 +245 +212 +186 +120 +114 +108 +76 +70 +64 +214 +121 +50 +227 +126 +50 +224 +123 +55 +227 +126 +50 +225 +124 +48 +95 +78 +64 +43 +57 +62 +146 +135 +124 +217 +187 +166 +227 +196 +175 +194 +173 +157 +91 +92 +89 +48 +58 +59 +163 +104 +61 +234 +125 +52 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +126 +45 +139 +96 +61 +55 +66 +67 +250 +197 +158 +249 +174 +124 +247 +150 +84 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +111 +26 +247 +118 +39 +247 +130 +53 +249 +146 +83 +251 +168 +115 +239 +182 +144 +65 +58 +56 +59 +50 +39 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +108 +87 +46 +47 +40 +38 +152 +119 +47 +170 +137 +67 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +174 +168 +167 +24 +22 +23 +109 +106 +99 +152 +147 +147 +97 +98 +96 +47 +40 +38 +24 +22 +23 +35 +31 +30 +35 +31 +30 +176 +156 +141 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +69 +69 +61 +76 +78 +76 +227 +196 +175 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +187 +166 +150 +51 +62 +63 +95 +87 +59 +168 +127 +42 +158 +125 +46 +158 +125 +46 +171 +129 +45 +117 +98 +55 +55 +66 +67 +109 +106 +99 +48 +58 +59 +137 +110 +49 +168 +127 +42 +158 +125 +46 +168 +127 +42 +117 +98 +55 +48 +58 +59 +187 +166 +150 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +137 +127 +115 +51 +62 +63 +145 +114 +49 +168 +127 +42 +158 +125 +46 +171 +129 +45 +117 +98 +55 +55 +66 +67 +137 +127 +115 +55 +66 +67 +123 +102 +54 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +55 +66 +67 +207 +178 +158 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +217 +187 +166 +58 +69 +70 +83 +78 +61 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +91 +92 +89 +109 +106 +99 +69 +69 +61 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +120 +114 +108 +245 +212 +186 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +137 +127 +115 +48 +58 +59 +129 +106 +52 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +65 +67 +64 +146 +135 +124 +146 +135 +124 +62 +63 +61 +152 +119 +47 +168 +127 +42 +158 +125 +46 +168 +127 +42 +100 +89 +56 +51 +62 +63 +207 +178 +158 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +109 +106 +99 +63 +69 +60 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +100 +89 +56 +51 +62 +63 +227 +196 +175 +172 +150 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +155 +100 +63 +41 +58 +57 +146 +135 +124 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +245 +212 +186 +109 +106 +99 +56 +64 +60 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +224 +123 +55 +76 +70 +64 +109 +106 +99 +194 +173 +157 +43 +57 +62 +163 +104 +61 +234 +125 +52 +224 +123 +55 +224 +123 +55 +225 +124 +48 +89 +75 +66 +63 +74 +74 +217 +187 +166 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +217 +187 +166 +58 +69 +70 +95 +78 +64 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +155 +100 +63 +43 +57 +62 +207 +178 +158 +109 +106 +99 +76 +70 +64 +224 +123 +55 +227 +126 +50 +224 +123 +55 +227 +126 +50 +194 +112 +58 +51 +62 +63 +120 +114 +108 +253 +212 +188 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +137 +127 +115 +48 +58 +59 +173 +106 +60 +234 +125 +52 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +188 +112 +56 +62 +63 +61 +58 +69 +70 +161 +144 +134 +234 +204 +183 +255 +215 +190 +255 +215 +190 +137 +127 +115 +62 +63 +61 +209 +117 +53 +227 +126 +50 +224 +123 +55 +227 +126 +50 +212 +120 +56 +69 +69 +61 +77 +85 +81 +234 +204 +183 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +176 +156 +141 +35 +56 +60 +135 +94 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +192 +154 +251 +168 +115 +247 +150 +84 +250 +139 +73 +248 +138 +64 +250 +139 +73 +249 +152 +92 +249 +174 +124 +209 +171 +139 +43 +57 +62 +135 +94 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +126 +45 +112 +85 +63 +51 +62 +63 +194 +173 +157 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +227 +196 +175 +70 +79 +77 +76 +70 +64 +214 +121 +50 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +48 +58 +59 +146 +135 +124 +77 +85 +81 +135 +94 +64 +234 +125 +52 +224 +123 +55 +224 +123 +55 +227 +126 +50 +214 +121 +50 +95 +78 +64 +35 +56 +60 +120 +114 +108 +217 +187 +166 +255 +215 +190 +255 +215 +190 +227 +196 +175 +58 +69 +70 +125 +90 +64 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +139 +96 +61 +41 +58 +57 +172 +150 +134 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +234 +204 +183 +77 +85 +81 +76 +70 +64 +214 +121 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +125 +52 +139 +96 +61 +51 +62 +63 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +111 +26 +247 +123 +41 +248 +138 +64 +249 +152 +92 +249 +174 +124 +178 +146 +122 +24 +22 +23 +101 +83 +47 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +152 +119 +47 +47 +40 +38 +123 +102 +54 +209 +171 +139 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +164 +158 +157 +24 +22 +23 +24 +22 +23 +24 +22 +23 +24 +22 +23 +24 +22 +23 +35 +31 +30 +35 +31 +30 +47 +40 +38 +194 +173 +157 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +129 +106 +52 +48 +58 +59 +176 +156 +141 +255 +215 +190 +255 +215 +190 +253 +212 +188 +255 +215 +190 +255 +215 +190 +255 +215 +190 +120 +114 +108 +56 +64 +60 +152 +119 +47 +161 +127 +40 +158 +125 +46 +168 +127 +42 +137 +110 +49 +51 +62 +63 +48 +58 +59 +75 +74 +61 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +63 +74 +74 +194 +173 +157 +207 +178 +158 +207 +178 +158 +207 +178 +158 +207 +178 +158 +207 +178 +158 +207 +178 +158 +172 +150 +134 +48 +58 +59 +111 +94 +57 +171 +129 +45 +158 +125 +46 +168 +127 +42 +152 +119 +47 +56 +64 +60 +51 +62 +63 +56 +64 +60 +152 +119 +47 +168 +127 +42 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +146 +135 +124 +255 +215 +190 +255 +215 +190 +253 +212 +188 +253 +212 +188 +255 +215 +190 +255 +215 +190 +146 +135 +124 +51 +62 +63 +145 +114 +49 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +70 +79 +77 +63 +74 +74 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +171 +129 +45 +95 +87 +59 +55 +66 +67 +227 +196 +175 +255 +215 +190 +255 +215 +190 +253 +212 +188 +255 +215 +190 +255 +215 +190 +234 +204 +183 +70 +79 +77 +88 +82 +59 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +56 +64 +60 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +137 +127 +115 +97 +98 +96 +83 +78 +61 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +69 +69 +61 +84 +85 +82 +207 +178 +158 +207 +178 +158 +207 +178 +158 +207 +178 +158 +207 +178 +158 +207 +178 +158 +217 +187 +166 +146 +135 +124 +48 +58 +59 +129 +106 +52 +168 +127 +42 +158 +125 +46 +168 +127 +42 +129 +106 +52 +51 +62 +63 +187 +166 +150 +176 +156 +141 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +89 +75 +66 +70 +79 +77 +245 +212 +186 +255 +215 +190 +255 +215 +190 +253 +212 +188 +255 +215 +190 +255 +215 +190 +217 +187 +166 +43 +57 +62 +125 +90 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +126 +45 +106 +82 +65 +77 +85 +81 +133 +120 +107 +62 +63 +61 +209 +117 +53 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +48 +58 +59 +161 +144 +134 +255 +215 +190 +255 +215 +190 +253 +212 +188 +253 +212 +188 +255 +215 +190 +255 +215 +190 +146 +135 +124 +48 +58 +59 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +199 +115 +54 +62 +63 +61 +133 +120 +107 +77 +85 +81 +118 +86 +65 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +126 +45 +125 +90 +64 +55 +66 +67 +227 +196 +175 +255 +215 +190 +255 +215 +190 +253 +212 +188 +255 +215 +190 +255 +215 +190 +234 +204 +183 +63 +74 +74 +106 +82 +65 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +97 +98 +96 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +224 +123 +55 +89 +75 +66 +63 +74 +74 +217 +187 +166 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +91 +92 +89 +95 +78 +64 +227 +126 +50 +227 +126 +50 +224 +123 +55 +234 +126 +45 +146 +97 +64 +43 +57 +62 +187 +166 +150 +255 +215 +190 +255 +215 +190 +253 +212 +188 +255 +215 +190 +255 +215 +190 +255 +215 +190 +101 +100 +92 +76 +70 +64 +224 +123 +55 +227 +126 +50 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +192 +154 +251 +168 +115 +247 +150 +84 +250 +139 +73 +250 +139 +73 +247 +143 +74 +249 +159 +103 +250 +176 +132 +154 +133 +118 +51 +62 +63 +183 +110 +59 +227 +126 +50 +224 +123 +55 +227 +126 +50 +199 +115 +54 +62 +63 +61 +133 +120 +107 +255 +215 +190 +255 +215 +190 +253 +212 +188 +253 +212 +188 +255 +215 +190 +255 +215 +190 +176 +156 +141 +43 +57 +62 +163 +104 +61 +234 +125 +52 +224 +123 +55 +227 +126 +50 +214 +121 +50 +76 +70 +64 +91 +92 +89 +70 +79 +77 +135 +94 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +125 +52 +146 +97 +64 +35 +56 +60 +161 +144 +134 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +194 +173 +157 +48 +58 +59 +163 +104 +61 +234 +126 +45 +224 +123 +55 +227 +126 +50 +214 +121 +50 +76 +70 +64 +97 +98 +96 +255 +215 +190 +255 +215 +190 +255 +215 +190 +253 +212 +188 +255 +215 +190 +255 +215 +190 +187 +166 +150 +43 +57 +62 +163 +104 +61 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +139 +96 +61 +55 +66 +67 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +109 +10 +247 +111 +26 +247 +123 +41 +248 +138 +64 +249 +159 +103 +248 +180 +134 +124 +111 +99 +35 +31 +30 +137 +110 +49 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +59 +50 +39 +85 +71 +43 +216 +194 +154 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +207 +202 +200 +47 +40 +38 +24 +22 +23 +35 +31 +30 +35 +31 +30 +35 +31 +30 +35 +31 +30 +24 +22 +23 +65 +58 +56 +238 +205 +179 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +100 +89 +56 +63 +74 +74 +227 +196 +175 +255 +215 +190 +253 +204 +176 +250 +200 +166 +250 +200 +166 +251 +209 +178 +255 +215 +190 +194 +173 +157 +48 +58 +59 +123 +102 +54 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +43 +57 +62 +95 +87 +59 +168 +127 +42 +158 +125 +46 +161 +127 +40 +158 +125 +46 +63 +69 +60 +43 +57 +62 +51 +62 +63 +51 +62 +63 +51 +62 +63 +51 +62 +63 +51 +62 +63 +51 +62 +63 +51 +62 +63 +51 +62 +63 +43 +57 +62 +88 +82 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +75 +74 +61 +43 +57 +62 +75 +74 +61 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +117 +98 +55 +51 +62 +63 +217 +187 +166 +255 +215 +190 +253 +204 +176 +250 +200 +166 +250 +200 +166 +253 +204 +176 +255 +215 +190 +217 +187 +166 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +48 +58 +59 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +69 +69 +61 +109 +106 +99 +255 +215 +190 +253 +212 +188 +253 +204 +176 +250 +200 +166 +250 +200 +166 +253 +212 +188 +255 +215 +190 +120 +114 +108 +63 +69 +60 +158 +125 +46 +161 +127 +40 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +120 +114 +108 +70 +79 +77 +105 +93 +60 +171 +129 +45 +158 +125 +46 +168 +127 +42 +152 +119 +47 +56 +64 +60 +51 +62 +63 +51 +62 +63 +51 +62 +63 +51 +62 +63 +51 +62 +63 +51 +62 +63 +51 +62 +63 +51 +62 +63 +51 +62 +63 +43 +57 +62 +111 +94 +57 +171 +129 +45 +158 +125 +46 +161 +127 +40 +152 +119 +47 +62 +63 +61 +146 +135 +124 +172 +150 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +199 +115 +54 +62 +63 +61 +146 +135 +124 +255 +215 +190 +253 +212 +188 +250 +200 +166 +250 +200 +166 +253 +204 +176 +253 +212 +188 +253 +212 +188 +97 +98 +96 +89 +75 +66 +227 +126 +50 +227 +126 +50 +224 +123 +55 +234 +126 +45 +139 +96 +61 +51 +62 +63 +63 +74 +74 +89 +75 +66 +227 +126 +50 +227 +126 +50 +224 +123 +55 +234 +125 +52 +135 +94 +64 +55 +66 +67 +217 +187 +166 +255 +215 +190 +253 +204 +176 +250 +200 +166 +250 +200 +166 +253 +204 +176 +255 +215 +190 +217 +187 +166 +51 +62 +63 +139 +96 +61 +234 +126 +45 +224 +123 +55 +227 +126 +50 +225 +124 +48 +81 +73 +62 +58 +69 +70 +51 +62 +63 +146 +97 +64 +234 +126 +45 +224 +123 +55 +227 +126 +50 +224 +123 +55 +81 +73 +62 +109 +106 +99 +255 +215 +190 +253 +212 +188 +253 +204 +176 +250 +200 +166 +250 +200 +166 +253 +212 +188 +255 +215 +190 +120 +114 +108 +69 +69 +61 +212 +120 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +234 +125 +52 +224 +123 +55 +227 +126 +50 +194 +112 +58 +51 +62 +63 +146 +135 +124 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +234 +204 +183 +70 +79 +77 +118 +86 +65 +234 +125 +52 +224 +123 +55 +227 +126 +50 +227 +126 +50 +106 +82 +65 +77 +85 +81 +245 +212 +186 +255 +215 +190 +253 +204 +176 +250 +200 +166 +250 +200 +166 +251 +209 +178 +255 +215 +190 +176 +156 +141 +56 +64 +60 +188 +112 +56 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +192 +154 +251 +168 +115 +249 +152 +92 +247 +143 +74 +247 +143 +74 +247 +150 +84 +249 +159 +103 +248 +180 +134 +120 +114 +108 +69 +69 +61 +212 +120 +56 +227 +126 +50 +224 +123 +55 +234 +125 +52 +155 +100 +63 +43 +57 +62 +194 +173 +157 +255 +215 +190 +253 +204 +176 +250 +200 +166 +250 +200 +166 +253 +204 +176 +255 +215 +190 +234 +204 +183 +63 +74 +74 +112 +85 +63 +234 +125 +52 +227 +126 +50 +224 +123 +55 +234 +125 +52 +106 +82 +65 +58 +69 +70 +55 +66 +67 +135 +94 +64 +234 +125 +52 +224 +123 +55 +227 +126 +50 +227 +126 +50 +95 +78 +64 +77 +85 +81 +245 +212 +186 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +48 +58 +59 +172 +150 +134 +255 +215 +190 +251 +209 +178 +250 +200 +166 +250 +200 +166 +253 +204 +176 +255 +215 +190 +245 +212 +186 +63 +74 +74 +112 +85 +63 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +126 +45 +139 +96 +61 +55 +66 +67 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +250 +139 +73 +249 +159 +103 +252 +185 +144 +82 +69 +65 +47 +40 +38 +158 +125 +46 +161 +127 +40 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +85 +71 +43 +59 +50 +39 +216 +194 +154 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +164 +158 +157 +47 +40 +38 +24 +22 +23 +24 +22 +23 +24 +22 +23 +35 +31 +30 +65 +67 +64 +65 +58 +56 +227 +196 +175 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +84 +85 +82 +255 +215 +190 +251 +209 +178 +250 +197 +158 +251 +192 +154 +251 +192 +154 +250 +200 +166 +253 +212 +188 +227 +196 +175 +58 +69 +70 +105 +93 +60 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +75 +74 +61 +41 +58 +57 +111 +94 +57 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +137 +110 +49 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +41 +58 +57 +83 +78 +61 +168 +127 +42 +158 +125 +46 +158 +125 +46 +171 +129 +45 +95 +87 +59 +70 +79 +77 +245 +212 +186 +253 +212 +188 +250 +200 +166 +251 +192 +154 +251 +192 +154 +250 +200 +166 +253 +212 +188 +238 +205 +179 +70 +79 +77 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +48 +58 +59 +48 +58 +59 +129 +106 +52 +168 +127 +42 +158 +125 +46 +168 +127 +42 +152 +119 +47 +56 +64 +60 +146 +135 +124 +255 +215 +190 +253 +204 +176 +250 +197 +158 +251 +192 +154 +251 +192 +154 +253 +204 +176 +255 +215 +190 +172 +150 +134 +51 +62 +63 +145 +114 +49 +168 +127 +42 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +97 +98 +96 +55 +66 +67 +123 +102 +54 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +123 +102 +54 +117 +98 +55 +145 +114 +49 +161 +127 +40 +158 +125 +46 +158 +125 +46 +158 +125 +46 +69 +69 +61 +137 +127 +115 +172 +150 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +234 +125 +52 +183 +110 +59 +51 +62 +63 +187 +166 +150 +255 +215 +190 +253 +204 +176 +251 +192 +154 +251 +192 +154 +250 +197 +158 +253 +204 +176 +255 +215 +190 +137 +127 +115 +65 +67 +64 +209 +117 +53 +227 +126 +50 +224 +123 +55 +234 +125 +52 +163 +104 +61 +43 +57 +62 +41 +58 +57 +106 +82 +65 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +106 +82 +65 +77 +85 +81 +245 +212 +186 +251 +209 +178 +250 +197 +158 +249 +189 +146 +251 +192 +154 +250 +197 +158 +251 +209 +178 +238 +205 +179 +77 +85 +81 +112 +85 +63 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +106 +82 +65 +41 +58 +57 +48 +58 +59 +163 +104 +61 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +62 +63 +61 +146 +135 +124 +255 +215 +190 +253 +204 +176 +250 +197 +158 +251 +192 +154 +251 +192 +154 +253 +204 +176 +255 +215 +190 +176 +156 +141 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +234 +125 +52 +224 +123 +55 +227 +126 +50 +183 +110 +59 +48 +58 +59 +176 +156 +141 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +227 +196 +175 +58 +69 +70 +139 +96 +61 +234 +125 +52 +224 +123 +55 +227 +126 +50 +214 +121 +50 +76 +70 +64 +120 +114 +108 +255 +215 +190 +253 +204 +176 +250 +197 +158 +251 +192 +154 +251 +192 +154 +250 +200 +166 +255 +215 +190 +207 +178 +158 +48 +58 +59 +163 +104 +61 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +192 +154 +249 +174 +124 +246 +156 +93 +247 +150 +84 +249 +146 +83 +249 +152 +92 +251 +168 +115 +249 +189 +146 +97 +98 +96 +89 +75 +66 +225 +124 +48 +227 +126 +50 +224 +123 +55 +234 +126 +45 +125 +90 +64 +58 +69 +70 +227 +196 +175 +253 +212 +188 +250 +200 +166 +251 +192 +154 +249 +189 +146 +250 +197 +158 +251 +209 +178 +255 +215 +190 +97 +98 +96 +89 +75 +66 +227 +126 +50 +227 +126 +50 +224 +123 +55 +234 +126 +45 +125 +90 +64 +43 +57 +62 +43 +57 +62 +135 +94 +64 +234 +125 +52 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +101 +100 +92 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +137 +127 +115 +69 +69 +61 +212 +120 +56 +227 +126 +50 +224 +123 +55 +234 +126 +45 +155 +100 +63 +43 +57 +62 +207 +178 +158 +255 +215 +190 +250 +200 +166 +251 +192 +154 +251 +192 +154 +250 +197 +158 +251 +209 +178 +255 +215 +190 +109 +106 +99 +89 +75 +66 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +139 +96 +61 +55 +66 +67 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +247 +143 +74 +249 +159 +103 +252 +185 +144 +55 +48 +48 +59 +50 +39 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +156 +125 +62 +101 +83 +47 +59 +50 +39 +209 +171 +139 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +219 +212 +208 +137 +127 +115 +101 +100 +92 +120 +114 +108 +186 +181 +179 +152 +147 +147 +55 +48 +48 +227 +196 +175 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +97 +98 +96 +255 +215 +190 +253 +204 +176 +251 +192 +154 +249 +189 +146 +249 +189 +146 +250 +197 +158 +251 +209 +178 +234 +204 +183 +70 +79 +77 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +161 +127 +40 +75 +74 +61 +41 +58 +57 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +168 +127 +42 +168 +127 +42 +168 +127 +42 +171 +129 +45 +75 +74 +61 +41 +58 +57 +88 +82 +59 +168 +127 +42 +158 +125 +46 +158 +125 +46 +171 +129 +45 +88 +82 +59 +77 +85 +81 +245 +212 +186 +251 +209 +178 +250 +197 +158 +249 +189 +146 +249 +189 +146 +250 +197 +158 +251 +209 +178 +245 +212 +186 +84 +85 +82 +88 +82 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +43 +57 +62 +48 +58 +59 +129 +106 +52 +168 +127 +42 +158 +125 +46 +168 +127 +42 +145 +114 +49 +56 +64 +60 +161 +144 +134 +255 +215 +190 +250 +200 +166 +251 +192 +154 +249 +189 +146 +251 +192 +154 +250 +200 +166 +255 +215 +190 +187 +166 +150 +51 +62 +63 +137 +110 +49 +168 +127 +42 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +65 +67 +64 +91 +92 +89 +55 +66 +67 +129 +106 +52 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +171 +129 +45 +168 +127 +42 +168 +127 +42 +168 +127 +42 +158 +125 +46 +63 +69 +60 +137 +127 +115 +172 +150 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +173 +106 +60 +48 +58 +59 +187 +166 +150 +255 +215 +190 +250 +200 +166 +251 +192 +154 +249 +189 +146 +251 +192 +154 +250 +200 +166 +255 +215 +190 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +234 +125 +52 +173 +106 +60 +48 +58 +59 +41 +58 +57 +118 +86 +65 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +125 +52 +95 +78 +64 +91 +92 +89 +255 +215 +190 +253 +204 +176 +251 +192 +154 +252 +185 +144 +252 +185 +144 +251 +192 +154 +253 +204 +176 +245 +212 +186 +91 +92 +89 +106 +82 +65 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +112 +85 +63 +41 +58 +57 +48 +58 +59 +173 +106 +60 +234 +125 +52 +224 +123 +55 +227 +126 +50 +199 +115 +54 +56 +64 +60 +161 +144 +134 +255 +215 +190 +250 +200 +166 +251 +192 +154 +249 +189 +146 +251 +192 +154 +250 +200 +166 +255 +215 +190 +187 +166 +150 +48 +58 +59 +183 +110 +59 +234 +125 +52 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +51 +62 +63 +176 +156 +141 +255 +215 +190 +253 +212 +188 +251 +209 +178 +253 +212 +188 +217 +187 +166 +55 +66 +67 +146 +97 +64 +234 +126 +45 +224 +123 +55 +227 +126 +50 +214 +121 +50 +69 +69 +61 +137 +127 +115 +255 +215 +190 +253 +204 +176 +251 +192 +154 +249 +189 +146 +249 +189 +146 +250 +200 +166 +253 +212 +188 +217 +187 +166 +51 +62 +63 +155 +100 +63 +234 +125 +52 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +250 +197 +158 +249 +174 +124 +249 +159 +103 +249 +152 +92 +249 +152 +92 +249 +159 +103 +249 +174 +124 +250 +197 +158 +91 +92 +89 +95 +78 +64 +227 +126 +50 +227 +126 +50 +224 +123 +55 +234 +125 +52 +125 +90 +64 +70 +79 +77 +234 +204 +183 +251 +209 +178 +250 +197 +158 +249 +189 +146 +252 +185 +144 +251 +192 +154 +253 +204 +176 +255 +215 +190 +120 +114 +108 +81 +73 +62 +224 +123 +55 +227 +126 +50 +224 +123 +55 +234 +126 +45 +135 +94 +64 +41 +58 +57 +41 +58 +57 +135 +94 +64 +234 +125 +52 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +101 +100 +92 +253 +212 +188 +253 +212 +188 +251 +209 +178 +251 +209 +178 +255 +215 +190 +137 +127 +115 +76 +70 +64 +214 +121 +50 +227 +126 +50 +224 +123 +55 +234 +125 +52 +146 +97 +64 +51 +62 +63 +227 +196 +175 +253 +212 +188 +250 +197 +158 +249 +189 +146 +249 +189 +146 +251 +192 +154 +253 +204 +176 +255 +215 +190 +120 +114 +108 +81 +73 +62 +227 +126 +50 +227 +126 +50 +224 +123 +55 +234 +126 +45 +139 +96 +61 +51 +62 +63 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +250 +139 +73 +249 +159 +103 +252 +185 +144 +55 +48 +48 +59 +50 +39 +161 +127 +40 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +154 +125 +71 +170 +137 +67 +108 +87 +46 +59 +50 +39 +192 +155 +91 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +186 +181 +179 +47 +40 +38 +65 +58 +56 +245 +212 +186 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +84 +85 +82 +253 +212 +188 +251 +209 +178 +250 +197 +158 +251 +192 +154 +251 +192 +154 +250 +200 +166 +253 +212 +188 +234 +204 +183 +63 +74 +74 +100 +89 +56 +171 +129 +45 +158 +125 +46 +158 +125 +46 +161 +127 +40 +75 +74 +61 +41 +58 +57 +111 +94 +57 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +111 +94 +57 +56 +64 +60 +43 +57 +62 +83 +78 +61 +168 +127 +42 +158 +125 +46 +158 +125 +46 +171 +129 +45 +95 +87 +59 +70 +79 +77 +245 +212 +186 +251 +209 +178 +250 +197 +158 +251 +192 +154 +251 +192 +154 +250 +197 +158 +251 +209 +178 +245 +212 +186 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +43 +57 +62 +48 +58 +59 +129 +106 +52 +168 +127 +42 +158 +125 +46 +158 +125 +46 +152 +119 +47 +56 +64 +60 +161 +144 +134 +255 +215 +190 +253 +204 +176 +251 +192 +154 +249 +189 +146 +251 +192 +154 +250 +200 +166 +255 +215 +190 +176 +156 +141 +51 +62 +63 +137 +110 +49 +168 +127 +42 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +91 +92 +89 +55 +66 +67 +123 +102 +54 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +145 +114 +49 +100 +89 +56 +48 +58 +59 +187 +166 +150 +176 +156 +141 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +51 +62 +63 +176 +156 +141 +255 +215 +190 +250 +200 +166 +251 +192 +154 +251 +192 +154 +250 +197 +158 +253 +204 +176 +255 +215 +190 +146 +135 +124 +62 +63 +61 +209 +117 +53 +227 +126 +50 +224 +123 +55 +234 +125 +52 +163 +104 +61 +48 +58 +59 +41 +58 +57 +112 +85 +63 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +106 +82 +65 +84 +85 +82 +255 +215 +190 +251 +209 +178 +250 +197 +158 +249 +189 +146 +249 +189 +146 +250 +197 +158 +251 +209 +178 +238 +205 +179 +84 +85 +82 +106 +82 +65 +234 +125 +52 +224 +123 +55 +227 +126 +50 +227 +126 +50 +106 +82 +65 +41 +58 +57 +48 +58 +59 +173 +106 +60 +227 +126 +50 +224 +123 +55 +227 +126 +50 +199 +115 +54 +62 +63 +61 +146 +135 +124 +255 +215 +190 +253 +204 +176 +251 +192 +154 +249 +189 +146 +251 +192 +154 +250 +200 +166 +255 +215 +190 +176 +156 +141 +51 +62 +63 +183 +110 +59 +227 +126 +50 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +51 +62 +63 +176 +156 +141 +253 +212 +188 +253 +204 +176 +250 +200 +166 +253 +204 +176 +217 +187 +166 +55 +66 +67 +146 +97 +64 +234 +125 +52 +224 +123 +55 +227 +126 +50 +214 +121 +50 +76 +70 +64 +120 +114 +108 +255 +215 +190 +253 +204 +176 +250 +197 +158 +251 +192 +154 +251 +192 +154 +250 +200 +166 +253 +212 +188 +207 +178 +158 +48 +58 +59 +163 +104 +61 +227 +126 +50 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +250 +200 +166 +248 +180 +134 +251 +168 +115 +247 +165 +111 +247 +165 +111 +251 +168 +115 +248 +180 +134 +250 +200 +166 +91 +92 +89 +89 +75 +66 +225 +124 +48 +227 +126 +50 +224 +123 +55 +234 +126 +45 +125 +90 +64 +63 +74 +74 +227 +196 +175 +251 +209 +178 +250 +197 +158 +249 +189 +146 +249 +189 +146 +250 +197 +158 +253 +204 +176 +255 +215 +190 +109 +106 +99 +89 +75 +66 +225 +124 +48 +227 +126 +50 +224 +123 +55 +234 +125 +52 +125 +90 +64 +43 +57 +62 +41 +58 +57 +135 +94 +64 +234 +126 +45 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +101 +100 +92 +253 +212 +188 +253 +204 +176 +250 +200 +166 +250 +200 +166 +251 +209 +178 +137 +127 +115 +76 +70 +64 +214 +121 +50 +227 +126 +50 +224 +123 +55 +234 +125 +52 +155 +100 +63 +43 +57 +62 +217 +187 +166 +253 +212 +188 +250 +200 +166 +251 +192 +154 +249 +189 +146 +250 +197 +158 +253 +204 +176 +255 +215 +190 +120 +114 +108 +81 +73 +62 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +125 +52 +139 +96 +61 +55 +66 +67 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +250 +139 +73 +249 +159 +103 +248 +180 +134 +76 +70 +64 +47 +40 +38 +152 +119 +47 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +156 +125 +62 +154 +125 +71 +170 +137 +67 +101 +83 +47 +59 +50 +39 +170 +137 +67 +255 +238 +227 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +152 +147 +147 +35 +31 +30 +24 +22 +23 +115 +102 +92 +255 +215 +190 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +171 +129 +45 +105 +93 +60 +58 +69 +70 +227 +196 +175 +255 +215 +190 +253 +204 +176 +250 +200 +166 +250 +200 +166 +253 +204 +176 +255 +215 +190 +207 +178 +158 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +69 +69 +61 +43 +57 +62 +100 +89 +56 +171 +129 +45 +158 +125 +46 +161 +127 +40 +158 +125 +46 +75 +74 +61 +48 +58 +59 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +48 +58 +59 +101 +100 +92 +91 +92 +89 +75 +74 +61 +168 +127 +42 +158 +125 +46 +158 +125 +46 +171 +129 +45 +111 +94 +57 +55 +66 +67 +227 +196 +175 +255 +215 +190 +253 +204 +176 +250 +200 +166 +250 +200 +166 +253 +204 +176 +255 +215 +190 +227 +196 +175 +51 +62 +63 +105 +93 +60 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +48 +58 +59 +48 +58 +59 +123 +102 +54 +168 +127 +42 +158 +125 +46 +161 +127 +40 +158 +125 +46 +69 +69 +61 +120 +114 +108 +255 +215 +190 +251 +209 +178 +250 +200 +166 +250 +197 +158 +250 +200 +166 +251 +209 +178 +255 +215 +190 +146 +135 +124 +56 +64 +60 +152 +119 +47 +168 +127 +42 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +109 +106 +99 +63 +74 +74 +111 +94 +57 +171 +129 +45 +158 +125 +46 +161 +127 +40 +152 +119 +47 +69 +69 +61 +51 +62 +63 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +56 +64 +60 +51 +62 +63 +48 +58 +59 +120 +114 +108 +245 +212 +186 +172 +150 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +209 +117 +53 +62 +63 +61 +137 +127 +115 +255 +215 +190 +251 +209 +178 +250 +200 +166 +250 +200 +166 +250 +200 +166 +253 +212 +188 +255 +215 +190 +109 +106 +99 +81 +73 +62 +224 +123 +55 +227 +126 +50 +224 +123 +55 +234 +125 +52 +155 +100 +63 +48 +58 +59 +43 +57 +62 +95 +78 +64 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +125 +52 +125 +90 +64 +63 +74 +74 +227 +196 +175 +253 +212 +188 +250 +200 +166 +250 +197 +158 +250 +197 +158 +253 +204 +176 +255 +215 +190 +227 +196 +175 +55 +66 +67 +125 +90 +64 +234 +125 +52 +224 +123 +55 +224 +123 +55 +227 +126 +50 +89 +75 +66 +48 +58 +59 +48 +58 +59 +155 +100 +63 +234 +126 +45 +224 +123 +55 +227 +126 +50 +214 +121 +50 +76 +70 +64 +120 +114 +108 +255 +215 +190 +251 +209 +178 +250 +200 +166 +250 +197 +158 +250 +200 +166 +251 +209 +178 +255 +215 +190 +137 +127 +115 +62 +63 +61 +209 +117 +53 +227 +126 +50 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +97 +98 +96 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +48 +58 +59 +176 +156 +141 +251 +209 +178 +250 +200 +166 +250 +197 +158 +250 +200 +166 +227 +196 +175 +63 +74 +74 +135 +94 +64 +234 +126 +45 +224 +123 +55 +227 +126 +50 +227 +126 +50 +95 +78 +64 +91 +92 +89 +253 +212 +188 +253 +212 +188 +250 +200 +166 +250 +200 +166 +250 +200 +166 +251 +209 +178 +255 +215 +190 +172 +150 +134 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +251 +209 +178 +251 +192 +154 +250 +176 +132 +249 +174 +124 +249 +174 +124 +248 +180 +134 +251 +192 +154 +251 +209 +178 +109 +106 +99 +76 +70 +64 +214 +121 +50 +227 +126 +50 +224 +123 +55 +234 +126 +45 +146 +97 +64 +43 +57 +62 +217 +187 +166 +255 +215 +190 +253 +204 +176 +250 +197 +158 +250 +197 +158 +250 +200 +166 +253 +212 +188 +245 +212 +186 +70 +79 +77 +106 +82 +65 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +112 +85 +63 +51 +62 +63 +51 +62 +63 +135 +94 +64 +234 +126 +45 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +101 +100 +92 +245 +212 +186 +250 +200 +166 +251 +192 +154 +250 +197 +158 +253 +204 +176 +146 +135 +124 +65 +67 +64 +209 +117 +53 +227 +126 +50 +224 +123 +55 +234 +125 +52 +173 +106 +60 +48 +58 +59 +187 +166 +150 +255 +215 +190 +253 +204 +176 +250 +200 +166 +250 +197 +158 +250 +200 +166 +253 +212 +188 +255 +215 +190 +84 +85 +82 +95 +78 +64 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +125 +52 +139 +96 +61 +55 +66 +67 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +109 +10 +247 +111 +26 +247 +123 +41 +248 +138 +64 +249 +152 +92 +249 +174 +124 +121 +100 +85 +35 +31 +30 +108 +87 +46 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +156 +125 +62 +154 +125 +71 +154 +125 +71 +171 +129 +45 +85 +71 +43 +71 +60 +43 +171 +129 +45 +224 +207 +180 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +237 +233 +225 +174 +168 +167 +81 +77 +76 +24 +22 +23 +35 +31 +30 +35 +31 +30 +187 +166 +150 +255 +215 +190 +255 +215 +190 +234 +204 +183 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +129 +106 +52 +51 +62 +63 +176 +156 +141 +255 +215 +190 +255 +215 +190 +253 +212 +188 +253 +212 +188 +255 +215 +190 +255 +215 +190 +146 +135 +124 +51 +62 +63 +145 +114 +49 +168 +127 +42 +158 +125 +46 +158 +125 +46 +152 +119 +47 +56 +64 +60 +43 +57 +62 +83 +78 +61 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +48 +58 +59 +146 +135 +124 +161 +144 +134 +161 +144 +134 +161 +144 +134 +161 +144 +134 +161 +144 +134 +161 +144 +134 +161 +144 +134 +161 +144 +134 +172 +150 +134 +172 +150 +134 +146 +135 +124 +146 +135 +124 +194 +173 +157 +245 +212 +186 +137 +127 +115 +63 +69 +60 +158 +125 +46 +161 +127 +40 +158 +125 +46 +168 +127 +42 +137 +110 +49 +51 +62 +63 +161 +144 +134 +255 +215 +190 +255 +215 +190 +253 +212 +188 +253 +212 +188 +255 +215 +190 +255 +215 +190 +161 +144 +134 +48 +58 +59 +137 +110 +49 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +55 +66 +67 +51 +62 +63 +105 +93 +60 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +70 +79 +77 +245 +212 +186 +255 +215 +190 +253 +212 +188 +251 +209 +178 +253 +212 +188 +255 +215 +190 +255 +215 +190 +91 +92 +89 +75 +74 +61 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +133 +120 +107 +84 +85 +82 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +75 +74 +61 +55 +66 +67 +161 +144 +134 +161 +144 +134 +161 +144 +134 +161 +144 +134 +161 +144 +134 +161 +144 +134 +161 +144 +134 +161 +144 +134 +161 +144 +134 +172 +150 +134 +172 +150 +134 +137 +127 +115 +146 +135 +124 +207 +178 +158 +245 +212 +186 +255 +215 +190 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +76 +78 +76 +245 +212 +186 +255 +215 +190 +253 +212 +188 +253 +212 +188 +253 +212 +188 +255 +215 +190 +227 +196 +175 +58 +69 +70 +118 +86 +65 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +125 +90 +64 +63 +74 +74 +97 +98 +96 +76 +70 +64 +214 +121 +50 +227 +126 +50 +224 +123 +55 +234 +125 +52 +163 +104 +61 +48 +58 +59 +187 +166 +150 +255 +215 +190 +255 +215 +190 +251 +209 +178 +251 +209 +178 +255 +215 +190 +255 +215 +190 +176 +156 +141 +48 +58 +59 +173 +106 +60 +227 +126 +50 +224 +123 +55 +227 +126 +50 +212 +120 +56 +69 +69 +61 +101 +100 +92 +63 +74 +74 +125 +90 +64 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +106 +82 +65 +63 +74 +74 +234 +204 +183 +255 +215 +190 +253 +212 +188 +253 +212 +188 +253 +212 +188 +255 +215 +190 +245 +212 +186 +70 +79 +77 +89 +75 +66 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +234 +125 +52 +183 +110 +59 +51 +62 +63 +176 +156 +141 +253 +204 +176 +251 +192 +154 +251 +192 +154 +251 +192 +154 +250 +200 +166 +77 +85 +81 +106 +82 +65 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +135 +94 +64 +51 +62 +63 +217 +187 +166 +255 +215 +190 +255 +215 +190 +253 +212 +188 +253 +212 +188 +255 +215 +190 +255 +215 +190 +109 +106 +99 +76 +70 +64 +224 +123 +55 +227 +126 +50 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +255 +215 +190 +250 +200 +166 +251 +192 +154 +252 +185 +144 +252 +185 +144 +251 +192 +154 +250 +200 +166 +255 +215 +190 +146 +135 +124 +56 +64 +60 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +194 +112 +58 +51 +62 +63 +146 +135 +124 +255 +215 +190 +255 +215 +190 +251 +209 +178 +251 +209 +178 +253 +212 +188 +255 +215 +190 +194 +173 +157 +43 +57 +62 +146 +97 +64 +234 +126 +45 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +77 +85 +81 +63 +74 +74 +135 +94 +64 +234 +125 +52 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +101 +100 +92 +251 +209 +178 +250 +197 +158 +249 +189 +146 +249 +189 +146 +250 +200 +166 +172 +150 +134 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +120 +114 +108 +255 +215 +190 +255 +215 +190 +253 +212 +188 +251 +209 +178 +253 +212 +188 +255 +215 +190 +217 +187 +166 +51 +62 +63 +135 +94 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +126 +45 +139 +96 +61 +55 +66 +67 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +111 +26 +247 +118 +39 +247 +130 +60 +247 +150 +84 +251 +168 +115 +187 +140 +108 +24 +22 +23 +59 +50 +39 +168 +127 +42 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +156 +125 +62 +154 +125 +71 +154 +125 +71 +154 +125 +71 +156 +125 +62 +158 +125 +46 +47 +40 +38 +108 +87 +46 +158 +125 +46 +195 +167 +113 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +219 +212 +208 +164 +158 +157 +109 +106 +99 +65 +58 +56 +24 +22 +23 +24 +22 +23 +94 +60 +47 +178 +86 +46 +59 +50 +39 +150 +125 +114 +255 +215 +190 +255 +215 +190 +234 +204 +183 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +69 +69 +61 +84 +85 +82 +234 +204 +183 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +217 +187 +166 +55 +66 +67 +83 +78 +61 +168 +127 +42 +158 +125 +46 +158 +125 +46 +171 +129 +45 +123 +102 +54 +51 +62 +63 +76 +78 +76 +56 +64 +60 +152 +119 +47 +168 +127 +42 +158 +125 +46 +168 +127 +42 +129 +106 +52 +48 +58 +59 +161 +144 +134 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +217 +187 +166 +133 +120 +107 +77 +85 +81 +77 +85 +81 +146 +135 +124 +245 +212 +186 +176 +156 +141 +51 +62 +63 +137 +110 +49 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +75 +74 +61 +63 +74 +74 +227 +196 +175 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +234 +204 +183 +76 +78 +76 +75 +74 +61 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +77 +85 +81 +77 +85 +81 +88 +82 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +129 +106 +52 +48 +58 +59 +146 +135 +124 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +172 +150 +134 +48 +58 +59 +117 +98 +55 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +146 +135 +124 +120 +114 +108 +69 +69 +61 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +111 +94 +57 +51 +62 +63 +176 +156 +141 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +194 +173 +157 +120 +114 +108 +70 +79 +77 +84 +85 +82 +161 +144 +134 +255 +215 +190 +255 +215 +190 +161 +144 +134 +56 +64 +60 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +155 +100 +63 +41 +58 +57 +161 +144 +134 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +137 +127 +115 +48 +58 +59 +183 +110 +59 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +89 +75 +66 +97 +98 +96 +172 +150 +134 +48 +58 +59 +183 +110 +59 +227 +126 +50 +224 +123 +55 +227 +126 +50 +214 +121 +50 +76 +70 +64 +84 +85 +82 +234 +204 +183 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +234 +204 +183 +77 +85 +81 +81 +73 +62 +224 +123 +55 +227 +126 +50 +224 +123 +55 +234 +125 +52 +173 +106 +60 +48 +58 +59 +176 +156 +141 +97 +98 +96 +95 +78 +64 +227 +126 +50 +227 +126 +50 +224 +123 +55 +234 +125 +52 +173 +106 +60 +48 +58 +59 +146 +135 +124 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +161 +144 +134 +41 +58 +57 +155 +100 +63 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +51 +62 +63 +176 +156 +141 +250 +200 +166 +249 +189 +146 +252 +185 +144 +249 +189 +146 +250 +200 +166 +120 +114 +108 +69 +69 +61 +214 +121 +50 +227 +126 +50 +224 +123 +55 +227 +126 +50 +199 +115 +54 +62 +63 +61 +101 +100 +92 +245 +212 +186 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +187 +166 +150 +43 +57 +62 +135 +94 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +255 +215 +190 +253 +212 +188 +253 +204 +176 +250 +200 +166 +250 +200 +166 +253 +204 +176 +253 +212 +188 +255 +215 +190 +187 +166 +150 +41 +58 +57 +155 +100 +63 +234 +125 +52 +224 +123 +55 +227 +126 +50 +227 +126 +50 +95 +78 +64 +58 +69 +70 +227 +196 +175 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +245 +212 +186 +91 +92 +89 +62 +63 +61 +209 +117 +53 +227 +126 +50 +224 +123 +55 +227 +126 +50 +199 +115 +54 +62 +63 +61 +133 +120 +107 +77 +85 +81 +135 +94 +64 +234 +126 +45 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +101 +100 +92 +253 +204 +176 +251 +192 +154 +252 +185 +144 +252 +185 +144 +251 +192 +154 +212 +173 +150 +48 +58 +59 +155 +100 +63 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +125 +52 +118 +86 +65 +51 +62 +63 +207 +178 +158 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +109 +106 +99 +56 +64 +60 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +125 +52 +139 +96 +61 +55 +66 +67 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +247 +111 +26 +246 +116 +28 +247 +130 +53 +247 +143 +74 +249 +159 +103 +248 +180 +134 +89 +75 +66 +24 +22 +23 +85 +71 +43 +171 +129 +45 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +156 +125 +62 +154 +125 +71 +154 +125 +71 +154 +125 +71 +156 +125 +62 +175 +132 +40 +85 +71 +43 +47 +40 +38 +158 +125 +46 +158 +125 +46 +170 +137 +67 +237 +233 +225 +253 +255 +252 +253 +255 +252 +253 +255 +252 +207 +202 +200 +164 +158 +157 +146 +135 +124 +120 +114 +108 +89 +84 +82 +65 +58 +56 +47 +40 +38 +24 +22 +23 +24 +22 +23 +35 +31 +30 +94 +60 +47 +178 +86 +46 +226 +110 +35 +241 +100 +24 +144 +77 +47 +65 +58 +56 +253 +212 +188 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +129 +106 +52 +48 +58 +59 +101 +100 +92 +217 +187 +166 +245 +212 +186 +245 +212 +186 +194 +173 +157 +76 +78 +76 +56 +64 +60 +145 +114 +49 +168 +127 +42 +158 +125 +46 +158 +125 +46 +171 +129 +45 +88 +82 +59 +77 +85 +81 +176 +156 +141 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +95 +87 +59 +41 +58 +57 +137 +127 +115 +227 +196 +175 +255 +215 +190 +255 +215 +190 +255 +215 +190 +245 +212 +186 +207 +178 +158 +120 +114 +108 +48 +58 +59 +62 +63 +61 +100 +89 +56 +95 +87 +59 +51 +62 +63 +120 +114 +108 +227 +196 +175 +55 +66 +67 +100 +89 +56 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +137 +110 +49 +51 +62 +63 +84 +85 +82 +207 +178 +158 +245 +212 +186 +245 +212 +186 +207 +178 +158 +97 +98 +96 +51 +62 +63 +137 +110 +49 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +91 +92 +89 +120 +114 +108 +63 +69 +60 +158 +125 +46 +161 +127 +40 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +43 +57 +62 +161 +144 +134 +227 +196 +175 +253 +212 +188 +234 +204 +183 +161 +144 +134 +51 +62 +63 +75 +74 +61 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +146 +135 +124 +176 +156 +141 +48 +58 +59 +137 +110 +49 +171 +129 +45 +158 +125 +46 +161 +127 +40 +158 +125 +46 +75 +74 +61 +43 +57 +62 +161 +144 +134 +234 +204 +183 +255 +215 +190 +255 +215 +190 +255 +215 +190 +245 +212 +186 +194 +173 +157 +109 +106 +99 +43 +57 +62 +69 +69 +61 +105 +93 +60 +88 +82 +59 +48 +58 +59 +146 +135 +124 +255 +215 +190 +161 +144 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +225 +124 +48 +95 +78 +64 +43 +57 +62 +161 +144 +134 +234 +204 +183 +245 +212 +186 +227 +196 +175 +146 +135 +124 +35 +56 +60 +125 +90 +64 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +188 +112 +56 +51 +62 +63 +161 +144 +134 +234 +204 +183 +51 +62 +63 +125 +90 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +125 +52 +163 +104 +61 +43 +57 +62 +97 +98 +96 +207 +178 +158 +245 +212 +186 +245 +212 +186 +207 +178 +158 +91 +92 +89 +48 +58 +59 +173 +106 +60 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +118 +86 +65 +55 +66 +67 +234 +204 +183 +146 +135 +124 +56 +64 +60 +194 +112 +58 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +125 +52 +112 +85 +63 +35 +56 +60 +146 +135 +124 +227 +196 +175 +253 +212 +188 +234 +204 +183 +161 +144 +134 +43 +57 +62 +95 +78 +64 +225 +124 +48 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +51 +62 +63 +176 +156 +141 +250 +197 +158 +252 +185 +144 +248 +180 +134 +248 +180 +134 +251 +192 +154 +172 +150 +134 +48 +58 +59 +173 +106 +60 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +126 +45 +139 +96 +61 +41 +58 +57 +120 +114 +108 +217 +187 +166 +245 +212 +186 +234 +204 +183 +176 +156 +141 +58 +69 +70 +81 +73 +62 +214 +121 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +255 +215 +190 +255 +215 +190 +217 +187 +166 +133 +120 +107 +84 +85 +82 +91 +92 +89 +146 +135 +124 +234 +204 +183 +238 +205 +179 +63 +74 +74 +95 +78 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +84 +85 +82 +194 +173 +157 +245 +212 +186 +245 +212 +186 +217 +187 +166 +109 +106 +99 +41 +58 +57 +146 +97 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +126 +45 +146 +97 +64 +51 +62 +63 +187 +166 +150 +76 +78 +76 +135 +94 +64 +234 +126 +45 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +97 +98 +96 +250 +200 +166 +249 +189 +146 +248 +180 +134 +248 +180 +134 +252 +185 +144 +232 +190 +161 +70 +79 +77 +112 +85 +63 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +199 +115 +54 +65 +67 +64 +70 +79 +77 +187 +166 +150 +238 +205 +179 +245 +212 +186 +217 +187 +166 +133 +120 +107 +35 +56 +60 +135 +94 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +126 +45 +139 +96 +61 +55 +66 +67 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +123 +41 +247 +130 +60 +247 +150 +84 +251 +168 +115 +203 +161 +131 +55 +48 +48 +24 +22 +23 +71 +60 +43 +145 +114 +49 +171 +129 +45 +171 +129 +45 +158 +125 +46 +156 +125 +62 +154 +125 +71 +154 +125 +71 +156 +125 +62 +156 +125 +62 +171 +129 +45 +171 +129 +45 +101 +83 +47 +35 +31 +30 +123 +102 +54 +171 +129 +45 +158 +125 +46 +160 +120 +43 +224 +207 +180 +253 +255 +252 +253 +255 +252 +219 +212 +208 +47 +40 +38 +24 +22 +23 +24 +22 +23 +24 +22 +23 +24 +22 +23 +24 +22 +23 +35 +31 +30 +35 +31 +30 +24 +22 +23 +47 +40 +38 +226 +110 +35 +241 +100 +24 +226 +110 +35 +226 +110 +35 +144 +77 +47 +55 +48 +48 +238 +205 +179 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +123 +102 +54 +56 +64 +60 +51 +62 +63 +84 +85 +82 +84 +85 +82 +48 +58 +59 +63 +69 +60 +129 +106 +52 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +56 +64 +60 +137 +127 +115 +245 +212 +186 +84 +85 +82 +69 +69 +61 +158 +125 +46 +158 +125 +46 +158 +125 +46 +161 +127 +40 +158 +125 +46 +95 +87 +59 +48 +58 +59 +63 +74 +74 +109 +106 +99 +133 +120 +107 +133 +120 +107 +91 +92 +89 +51 +62 +63 +56 +64 +60 +100 +89 +56 +152 +119 +47 +171 +129 +45 +175 +132 +40 +100 +89 +56 +48 +58 +59 +217 +187 +166 +120 +114 +108 +63 +69 +60 +152 +119 +47 +161 +127 +40 +158 +125 +46 +158 +125 +46 +168 +127 +42 +129 +106 +52 +61 +67 +58 +51 +62 +63 +84 +85 +82 +84 +85 +82 +51 +62 +63 +56 +64 +60 +123 +102 +54 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +97 +98 +96 +187 +166 +150 +48 +58 +59 +123 +102 +54 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +158 +125 +46 +83 +78 +61 +48 +58 +59 +63 +74 +74 +91 +92 +89 +70 +79 +77 +48 +58 +59 +75 +74 +61 +152 +119 +47 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +146 +135 +124 +234 +204 +183 +63 +74 +74 +83 +78 +61 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +152 +119 +47 +83 +78 +61 +48 +58 +59 +70 +79 +77 +109 +106 +99 +133 +120 +107 +120 +114 +108 +84 +85 +82 +48 +58 +59 +61 +67 +58 +111 +94 +57 +158 +125 +46 +171 +129 +45 +171 +129 +45 +88 +82 +59 +58 +69 +70 +238 +205 +179 +172 +150 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +212 +120 +56 +95 +78 +64 +43 +57 +62 +70 +79 +77 +84 +85 +82 +63 +74 +74 +48 +58 +59 +118 +86 +65 +225 +124 +48 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +112 +85 +63 +55 +66 +67 +227 +196 +175 +255 +215 +190 +120 +114 +108 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +155 +100 +63 +62 +63 +61 +51 +62 +63 +77 +85 +81 +77 +85 +81 +51 +62 +63 +62 +63 +61 +155 +100 +63 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +199 +115 +54 +56 +64 +60 +120 +114 +108 +255 +215 +190 +217 +187 +166 +43 +57 +62 +125 +90 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +224 +123 +55 +106 +82 +65 +48 +58 +59 +63 +74 +74 +84 +85 +82 +70 +79 +77 +43 +57 +62 +95 +78 +64 +212 +120 +56 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +234 +125 +52 +183 +110 +59 +51 +62 +63 +172 +150 +134 +251 +192 +154 +248 +180 +134 +249 +174 +124 +249 +174 +124 +248 +180 +134 +236 +186 +153 +63 +74 +74 +95 +78 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +135 +94 +64 +51 +62 +63 +55 +66 +67 +84 +85 +82 +70 +79 +77 +41 +58 +57 +81 +73 +62 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +255 +215 +190 +194 +173 +157 +58 +69 +70 +62 +63 +61 +106 +82 +65 +95 +78 +64 +51 +62 +63 +91 +92 +89 +238 +205 +179 +161 +144 +134 +48 +58 +59 +183 +110 +59 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +125 +52 +173 +106 +60 +65 +67 +64 +48 +58 +59 +77 +85 +81 +84 +85 +82 +55 +66 +67 +56 +64 +60 +146 +97 +64 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +209 +117 +53 +69 +69 +61 +101 +100 +92 +227 +196 +175 +63 +74 +74 +135 +94 +64 +234 +125 +52 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +101 +100 +92 +250 +197 +158 +252 +185 +144 +249 +174 +124 +249 +174 +124 +250 +176 +132 +251 +192 +154 +120 +114 +108 +62 +63 +61 +209 +117 +53 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +188 +112 +56 +76 +70 +64 +41 +58 +57 +77 +85 +81 +84 +85 +82 +58 +69 +70 +48 +58 +59 +125 +90 +64 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +126 +45 +139 +96 +61 +55 +66 +67 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +243 +101 +2 +247 +103 +7 +247 +103 +7 +247 +111 +26 +247 +118 +39 +247 +130 +53 +250 +139 +73 +246 +156 +93 +249 +174 +124 +203 +161 +131 +55 +48 +48 +24 +22 +23 +35 +31 +30 +85 +71 +43 +137 +110 +49 +152 +119 +47 +168 +127 +42 +171 +129 +45 +171 +129 +45 +168 +127 +42 +152 +119 +47 +117 +98 +55 +59 +50 +39 +35 +31 +30 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +152 +119 +47 +224 +207 +180 +253 +255 +252 +253 +255 +252 +253 +255 +252 +146 +135 +124 +65 +58 +56 +35 +31 +30 +24 +22 +23 +24 +22 +23 +35 +31 +30 +35 +31 +30 +35 +31 +30 +35 +31 +30 +24 +22 +23 +83 +53 +42 +236 +108 +29 +236 +108 +29 +226 +110 +35 +94 +60 +47 +65 +58 +56 +253 +212 +188 +255 +215 +190 +238 +205 +179 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +161 +127 +40 +168 +127 +42 +145 +114 +49 +105 +93 +60 +83 +78 +61 +83 +78 +61 +111 +94 +57 +158 +125 +46 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +88 +82 +59 +51 +62 +63 +217 +187 +166 +255 +215 +190 +176 +156 +141 +43 +57 +62 +105 +93 +60 +171 +129 +45 +158 +125 +46 +158 +125 +46 +161 +127 +40 +168 +127 +42 +137 +110 +49 +88 +82 +59 +69 +69 +61 +62 +63 +61 +63 +69 +60 +75 +74 +61 +105 +93 +60 +152 +119 +47 +171 +129 +45 +168 +127 +42 +158 +125 +46 +171 +129 +45 +129 +106 +52 +48 +58 +59 +194 +173 +157 +207 +178 +158 +43 +57 +62 +100 +89 +56 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +152 +119 +47 +111 +94 +57 +83 +78 +61 +83 +78 +61 +105 +93 +60 +145 +114 +49 +168 +127 +42 +161 +127 +40 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +84 +85 +82 +245 +212 +186 +77 +85 +81 +75 +74 +61 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +168 +127 +42 +129 +106 +52 +95 +87 +59 +81 +73 +62 +95 +87 +59 +123 +102 +54 +168 +127 +42 +168 +127 +42 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +56 +64 +60 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +137 +127 +115 +255 +215 +190 +161 +144 +134 +48 +58 +59 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +168 +127 +42 +129 +106 +52 +88 +82 +59 +69 +69 +61 +62 +63 +61 +63 +69 +60 +75 +74 +61 +117 +98 +55 +152 +119 +47 +171 +129 +45 +161 +127 +40 +158 +125 +46 +171 +129 +45 +111 +94 +57 +48 +58 +59 +227 +196 +175 +176 +156 +141 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +227 +126 +50 +163 +104 +61 +112 +85 +63 +95 +78 +64 +118 +86 +65 +173 +106 +60 +227 +126 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +125 +52 +183 +110 +59 +51 +62 +63 +133 +120 +107 +255 +215 +190 +255 +215 +190 +217 +187 +166 +51 +62 +63 +106 +82 +65 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +199 +115 +54 +135 +94 +64 +95 +78 +64 +95 +78 +64 +135 +94 +64 +199 +115 +54 +234 +125 +52 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +126 +45 +106 +82 +65 +51 +62 +63 +217 +187 +166 +255 +215 +190 +255 +215 +190 +120 +114 +108 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +173 +106 +60 +118 +86 +65 +95 +78 +64 +112 +85 +63 +163 +104 +61 +227 +126 +50 +227 +126 +50 +227 +126 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +101 +100 +92 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +51 +62 +63 +172 +150 +134 +252 +185 +144 +249 +174 +124 +247 +165 +111 +247 +165 +111 +249 +174 +124 +252 +185 +144 +154 +133 +118 +48 +58 +59 +163 +104 +61 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +188 +112 +56 +125 +90 +64 +95 +78 +64 +106 +82 +65 +155 +100 +63 +224 +123 +55 +234 +125 +52 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +137 +127 +115 +253 +212 +188 +91 +92 +89 +69 +69 +61 +194 +112 +58 +234 +126 +45 +234 +126 +45 +163 +104 +61 +51 +62 +63 +137 +127 +115 +238 +205 +179 +63 +74 +74 +89 +75 +66 +227 +126 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +209 +117 +53 +146 +97 +64 +106 +82 +65 +95 +78 +64 +125 +90 +64 +194 +112 +58 +234 +126 +45 +227 +126 +50 +224 +123 +55 +227 +126 +50 +234 +126 +45 +125 +90 +64 +41 +58 +57 +194 +173 +157 +238 +205 +179 +63 +74 +74 +135 +94 +64 +234 +125 +52 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +101 +100 +92 +251 +192 +154 +250 +176 +132 +251 +168 +115 +247 +165 +111 +249 +174 +124 +245 +179 +138 +195 +157 +134 +41 +58 +57 +135 +94 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +125 +52 +214 +121 +50 +146 +97 +64 +106 +82 +65 +95 +78 +64 +125 +90 +64 +183 +110 +59 +227 +126 +50 +227 +126 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +125 +52 +139 +96 +61 +55 +66 +67 +250 +200 +166 +249 +174 +124 +249 +152 +92 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +247 +103 +7 +246 +109 +10 +247 +111 +26 +247 +118 +39 +247 +130 +53 +247 +143 +74 +249 +159 +103 +250 +176 +132 +219 +170 +138 +115 +102 +92 +47 +40 +38 +24 +22 +23 +35 +31 +30 +47 +40 +38 +59 +50 +39 +59 +50 +39 +59 +50 +39 +59 +50 +39 +47 +40 +38 +47 +40 +38 +71 +60 +43 +137 +110 +49 +171 +129 +45 +158 +125 +46 +158 +125 +46 +152 +119 +47 +170 +137 +67 +219 +212 +208 +237 +233 +225 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +219 +212 +208 +152 +147 +147 +109 +106 +99 +65 +67 +64 +35 +31 +30 +35 +31 +30 +35 +31 +30 +35 +31 +30 +24 +22 +23 +94 +60 +47 +178 +86 +46 +109 +63 +45 +35 +31 +30 +124 +111 +99 +251 +209 +178 +251 +209 +178 +234 +204 +183 +76 +78 +76 +95 +87 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +117 +98 +55 +129 +106 +52 +168 +127 +42 +168 +127 +42 +171 +129 +45 +168 +127 +42 +168 +127 +42 +171 +129 +45 +161 +127 +40 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +117 +98 +55 +48 +58 +59 +146 +135 +124 +255 +215 +190 +255 +215 +190 +255 +215 +190 +120 +114 +108 +51 +62 +63 +123 +102 +54 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +168 +127 +42 +158 +125 +46 +152 +119 +47 +152 +119 +47 +158 +125 +46 +168 +127 +42 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +158 +125 +46 +81 +73 +62 +58 +69 +70 +227 +196 +175 +255 +215 +190 +120 +114 +108 +48 +58 +59 +129 +106 +52 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +161 +127 +40 +168 +127 +42 +168 +127 +42 +168 +127 +42 +171 +129 +45 +168 +127 +42 +168 +127 +42 +152 +119 +47 +117 +98 +55 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +88 +82 +59 +84 +85 +82 +255 +215 +190 +176 +156 +141 +48 +58 +59 +111 +94 +57 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +168 +127 +42 +168 +127 +42 +168 +127 +42 +168 +127 +42 +158 +125 +46 +158 +125 +46 +145 +114 +49 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +117 +98 +55 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +63 +69 +60 +137 +127 +115 +255 +215 +190 +238 +205 +179 +91 +92 +89 +56 +64 +60 +137 +110 +49 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +168 +127 +42 +158 +125 +46 +152 +119 +47 +158 +125 +46 +168 +127 +42 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +152 +119 +47 +69 +69 +61 +84 +85 +82 +245 +212 +186 +172 +150 +134 +62 +63 +61 +199 +115 +54 +227 +126 +50 +224 +123 +55 +227 +126 +50 +199 +115 +54 +125 +90 +64 +227 +126 +50 +227 +126 +50 +227 +126 +50 +234 +125 +52 +227 +126 +50 +234 +125 +52 +234 +125 +52 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +214 +121 +50 +81 +73 +62 +63 +74 +74 +227 +196 +175 +255 +215 +190 +253 +212 +188 +255 +215 +190 +146 +135 +124 +48 +58 +59 +146 +97 +64 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +126 +45 +227 +126 +50 +227 +126 +50 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +126 +45 +139 +96 +61 +48 +58 +59 +146 +135 +124 +255 +215 +190 +253 +212 +188 +255 +215 +190 +217 +187 +166 +55 +66 +67 +95 +78 +64 +225 +124 +48 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +227 +126 +50 +227 +126 +50 +227 +126 +50 +224 +123 +55 +234 +126 +45 +163 +104 +61 +183 +110 +59 +227 +126 +50 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +97 +98 +96 +56 +64 +60 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +183 +110 +59 +51 +62 +63 +167 +142 +123 +248 +180 +134 +247 +165 +111 +249 +159 +103 +246 +156 +93 +249 +159 +103 +249 +174 +124 +239 +182 +144 +77 +85 +81 +65 +67 +64 +199 +115 +54 +234 +125 +52 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +227 +126 +50 +227 +126 +50 +234 +125 +52 +227 +126 +50 +227 +126 +50 +135 +94 +64 +188 +112 +56 +227 +126 +50 +224 +123 +55 +227 +126 +50 +209 +117 +53 +65 +67 +64 +146 +135 +124 +227 +196 +175 +43 +57 +62 +146 +97 +64 +234 +126 +45 +224 +123 +55 +224 +123 +55 +234 +126 +45 +106 +82 +65 +70 +79 +77 +253 +212 +188 +176 +156 +141 +41 +58 +57 +125 +90 +64 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +234 +125 +52 +227 +126 +50 +234 +125 +52 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +126 +45 +155 +100 +63 +48 +58 +59 +120 +114 +108 +253 +212 +188 +234 +204 +183 +63 +74 +74 +135 +94 +64 +234 +126 +45 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +101 +100 +92 +252 +185 +144 +245 +169 +119 +249 +159 +103 +249 +159 +103 +247 +165 +111 +249 +174 +124 +251 +192 +154 +109 +106 +99 +62 +63 +61 +188 +112 +56 +234 +125 +52 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +234 +125 +52 +227 +126 +50 +234 +125 +52 +227 +126 +50 +227 +126 +50 +212 +120 +56 +199 +115 +54 +224 +123 +55 +224 +123 +55 +224 +123 +55 +234 +126 +45 +139 +96 +61 +55 +66 +67 +250 +200 +166 +249 +174 +124 +247 +150 +84 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +243 +101 +2 +243 +101 +2 +247 +103 +7 +247 +111 +26 +247 +111 +26 +247 +123 +41 +247 +130 +60 +243 +141 +78 +249 +159 +103 +250 +176 +132 +251 +192 +154 +207 +178 +158 +154 +133 +118 +82 +69 +65 +24 +22 +23 +71 +60 +43 +101 +83 +47 +101 +83 +47 +101 +83 +47 +117 +98 +55 +145 +114 +49 +171 +129 +45 +168 +127 +42 +160 +120 +43 +160 +120 +43 +158 +125 +46 +192 +155 +91 +237 +233 +225 +81 +77 +76 +55 +48 +48 +74 +68 +68 +81 +77 +76 +89 +84 +82 +91 +92 +89 +89 +84 +82 +81 +77 +76 +65 +58 +56 +47 +40 +38 +35 +31 +30 +55 +48 +48 +115 +102 +92 +172 +150 +134 +55 +48 +48 +24 +22 +23 +24 +22 +23 +24 +22 +23 +65 +58 +56 +230 +173 +136 +251 +192 +154 +250 +197 +158 +250 +200 +166 +84 +85 +82 +88 +82 +59 +171 +129 +45 +158 +125 +46 +158 +125 +46 +171 +129 +45 +83 +78 +61 +69 +69 +61 +168 +127 +42 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +117 +98 +55 +48 +58 +59 +101 +100 +92 +238 +205 +179 +253 +204 +176 +250 +200 +166 +253 +204 +176 +238 +205 +179 +91 +92 +89 +51 +62 +63 +117 +98 +55 +171 +129 +45 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +161 +127 +40 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +145 +114 +49 +75 +74 +61 +48 +58 +59 +172 +150 +134 +253 +212 +188 +255 +215 +190 +234 +204 +183 +84 +85 +82 +56 +64 +60 +129 +106 +52 +171 +129 +45 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +168 +127 +42 +81 +73 +62 +63 +69 +60 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +83 +78 +61 +84 +85 +82 +255 +215 +190 +245 +212 +186 +109 +106 +99 +51 +62 +63 +123 +102 +54 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +161 +127 +40 +171 +129 +45 +105 +93 +60 +51 +62 +63 +137 +110 +49 +168 +127 +42 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +137 +127 +115 +58 +69 +70 +111 +94 +57 +171 +129 +45 +158 +125 +46 +158 +125 +46 +158 +125 +46 +62 +63 +61 +137 +127 +115 +255 +215 +190 +255 +215 +190 +227 +196 +175 +77 +85 +81 +56 +64 +60 +129 +106 +52 +171 +129 +45 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +161 +127 +40 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +168 +127 +42 +137 +110 +49 +69 +69 +61 +51 +62 +63 +187 +166 +150 +255 +215 +190 +172 +150 +134 +51 +62 +63 +194 +112 +58 +227 +126 +50 +224 +123 +55 +234 +125 +52 +183 +110 +59 +48 +58 +59 +155 +100 +63 +234 +126 +45 +224 +123 +55 +224 +123 +55 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +125 +52 +209 +117 +53 +89 +75 +66 +48 +58 +59 +187 +166 +150 +250 +200 +166 +250 +197 +158 +251 +192 +154 +250 +197 +158 +250 +200 +166 +109 +106 +99 +48 +58 +59 +135 +94 +64 +234 +125 +52 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +135 +94 +64 +43 +57 +62 +120 +114 +108 +250 +200 +166 +250 +197 +158 +251 +192 +154 +250 +197 +158 +250 +200 +166 +172 +150 +134 +41 +58 +57 +106 +82 +65 +214 +121 +50 +234 +125 +52 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +224 +123 +55 +227 +126 +50 +234 +126 +45 +183 +110 +59 +48 +58 +59 +135 +94 +64 +234 +126 +45 +224 +123 +55 +227 +126 +50 +188 +112 +56 +51 +62 +63 +109 +106 +99 +51 +62 +63 +183 +110 +59 +227 +126 +50 +224 +123 +55 +234 +125 +52 +173 +106 +60 +48 +58 +59 +178 +146 +122 +245 +169 +119 +246 +156 +93 +247 +150 +84 +249 +146 +83 +247 +150 +84 +249 +159 +103 +249 +174 +124 +203 +161 +131 +58 +69 +70 +76 +70 +64 +194 +112 +58 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +183 +110 +59 +48 +58 +59 +163 +104 +61 +234 +126 +45 +224 +123 +55 +227 +126 +50 +209 +117 +53 +62 +63 +61 +146 +135 +124 +217 +187 +166 +43 +57 +62 +163 +104 +61 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +126 +45 +125 +90 +64 +58 +69 +70 +234 +204 +183 +255 +215 +190 +137 +127 +115 +41 +58 +57 +118 +86 +65 +225 +124 +48 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +126 +45 +146 +97 +64 +51 +62 +63 +97 +98 +96 +238 +205 +179 +255 +215 +190 +234 +204 +183 +63 +74 +74 +118 +86 +65 +234 +126 +45 +224 +123 +55 +227 +126 +50 +227 +126 +50 +81 +73 +62 +101 +100 +92 +250 +176 +132 +247 +165 +111 +246 +156 +93 +249 +152 +92 +249 +159 +103 +251 +168 +115 +252 +185 +144 +217 +187 +166 +58 +69 +70 +69 +69 +61 +199 +115 +54 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +224 +123 +55 +227 +126 +50 +225 +124 +48 +81 +73 +62 +81 +73 +62 +227 +126 +50 +227 +126 +50 +224 +123 +55 +234 +126 +45 +139 +96 +61 +55 +66 +67 +250 +197 +158 +249 +174 +124 +247 +150 +84 +247 +130 +60 +247 +118 +39 +247 +111 +26 +247 +103 +7 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +237 +95 +0 +237 +95 +0 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +237 +95 +0 +243 +101 +2 +247 +103 +7 +236 +102 +14 +247 +111 +26 +246 +116 +28 +247 +123 +41 +247 +130 +60 +243 +141 +78 +249 +159 +103 +249 +174 +124 +249 +189 +146 +253 +204 +176 +124 +111 +99 +35 +31 +30 +145 +114 +49 +175 +132 +40 +171 +129 +45 +168 +127 +42 +192 +155 +91 +216 +194 +154 +224 +207 +180 +224 +207 +180 +216 +194 +154 +216 +194 +154 +239 +227 +208 +253 +255 +252 +253 +255 +252 +186 +181 +179 +146 +135 +124 +120 +114 +108 +109 +106 +99 +95 +78 +64 +71 +60 +43 +85 +71 +43 +101 +83 +47 +108 +87 +46 +35 +31 +30 +150 +125 +114 +227 +196 +175 +255 +215 +190 +253 +212 +188 +212 +173 +150 +121 +100 +85 +95 +78 +64 +129 +102 +78 +234 +168 +124 +250 +176 +132 +250 +176 +132 +248 +180 +134 +249 +189 +146 +124 +111 +99 +62 +63 +61 +152 +119 +47 +171 +129 +45 +171 +129 +45 +145 +114 +49 +56 +64 +60 +43 +57 +62 +83 +78 +61 +152 +119 +47 +171 +129 +45 +171 +129 +45 +168 +127 +42 +168 +127 +42 +171 +129 +45 +171 +129 +45 +152 +119 +47 +95 +87 +59 +48 +58 +59 +101 +100 +92 +236 +186 +153 +251 +192 +154 +252 +185 +144 +248 +180 +134 +245 +179 +138 +249 +189 +146 +236 +186 +153 +101 +100 +92 +48 +58 +59 +88 +82 +59 +137 +110 +49 +168 +127 +42 +171 +129 +45 +168 +127 +42 +168 +127 +42 +168 +127 +42 +168 +127 +42 +171 +129 +45 +171 +129 +45 +168 +127 +42 +145 +114 +49 +100 +89 +56 +56 +64 +60 +58 +69 +70 +172 +150 +134 +250 +200 +166 +251 +192 +154 +250 +197 +158 +250 +200 +166 +217 +187 +166 +84 +85 +82 +51 +62 +63 +105 +93 +60 +158 +125 +46 +171 +129 +45 +171 +129 +45 +168 +127 +42 +168 +127 +42 +168 +127 +42 +171 +129 +45 +152 +119 +47 +83 +78 +61 +43 +57 +62 +48 +58 +59 +129 +106 +52 +175 +132 +40 +171 +129 +45 +158 +125 +46 +63 +69 +60 +120 +114 +108 +255 +215 +190 +255 +215 +190 +227 +196 +175 +84 +85 +82 +51 +62 +63 +105 +93 +60 +158 +125 +46 +171 +129 +45 +171 +129 +45 +168 +127 +42 +168 +127 +42 +168 +127 +42 +171 +129 +45 +158 +125 +46 +105 +93 +60 +48 +58 +59 +48 +58 +59 +129 +106 +52 +168 +127 +42 +158 +125 +46 +168 +127 +42 +145 +114 +49 +51 +62 +63 +172 +150 +134 +91 +92 +89 +75 +74 +61 +168 +127 +42 +171 +129 +45 +175 +132 +40 +117 +98 +55 +48 +58 +59 +176 +156 +141 +253 +204 +176 +253 +204 +176 +253 +204 +176 +217 +187 +166 +84 +85 +82 +48 +58 +59 +95 +87 +59 +145 +114 +49 +168 +127 +42 +171 +129 +45 +168 +127 +42 +168 +127 +42 +168 +127 +42 +168 +127 +42 +171 +129 +45 +171 +129 +45 +158 +125 +46 +137 +110 +49 +95 +87 +59 +51 +62 +63 +70 +79 +77 +187 +166 +150 +251 +209 +178 +251 +209 +178 +207 +178 +158 +43 +57 +62 +135 +94 +64 +238 +123 +45 +234 +126 +45 +234 +126 +45 +118 +86 +65 +35 +56 +60 +56 +64 +60 +155 +100 +63 +234 +125 +52 +234 +126 +45 +234 +125 +52 +227 +126 +50 +227 +126 +50 +234 +126 +45 +227 +126 +50 +163 +104 +61 +76 +70 +64 +51 +62 +63 +167 +142 +123 +251 +192 +154 +248 +180 +134 +249 +174 +124 +249 +174 +124 +250 +176 +132 +245 +179 +138 +236 +186 +153 +109 +106 +99 +41 +58 +57 +95 +78 +64 +183 +110 +59 +234 +125 +52 +234 +126 +45 +234 +125 +52 +227 +126 +50 +227 +126 +50 +234 +125 +52 +234 +126 +45 +227 +126 +50 +183 +110 +59 +95 +78 +64 +43 +57 +62 +124 +111 +99 +236 +186 +153 +252 +185 +144 +250 +176 +132 +249 +174 +124 +249 +174 +124 +248 +180 +134 +251 +192 +154 +154 +133 +118 +43 +57 +62 +81 +73 +62 +173 +106 +60 +227 +126 +50 +234 +126 +45 +227 +126 +50 +227 +126 +50 +227 +126 +50 +234 +126 +45 +234 +125 +52 +155 +100 +63 +56 +64 +60 +35 +56 +60 +89 +75 +66 +227 +126 +50 +234 +126 +45 +238 +128 +40 +146 +97 +64 +43 +57 +62 +176 +156 +141 +58 +69 +70 +118 +86 +65 +234 +126 +45 +234 +126 +45 +234 +126 +45 +112 +85 +63 +43 +57 +62 +210 +156 +119 +245 +162 +103 +247 +150 +84 +247 +143 +74 +248 +138 +64 +241 +138 +68 +249 +146 +83 +249 +159 +103 +250 +176 +132 +195 +157 +134 +58 +69 +70 +65 +67 +64 +155 +100 +63 +227 +126 +50 +234 +126 +45 +227 +126 +50 +227 +126 +50 +234 +125 +52 +234 +126 +45 +234 +126 +45 +173 +106 +60 +65 +67 +64 +35 +56 +60 +106 +82 +65 +234 +126 +45 +234 +126 +45 +238 +128 +40 +146 +97 +64 +43 +57 +62 +187 +166 +150 +234 +204 +183 +55 +66 +67 +106 +82 +65 +234 +126 +45 +234 +125 +52 +234 +125 +52 +224 +123 +55 +81 +73 +62 +91 +92 +89 +245 +212 +186 +253 +212 +188 +253 +212 +188 +137 +127 +115 +41 +58 +57 +89 +75 +66 +173 +106 +60 +227 +126 +50 +234 +126 +45 +227 +126 +50 +227 +126 +50 +227 +126 +50 +234 +125 +52 +234 +126 +45 +234 +125 +52 +194 +112 +58 +106 +82 +65 +43 +57 +62 +101 +100 +92 +227 +196 +175 +251 +209 +178 +251 +209 +178 +253 +212 +188 +97 +98 +96 +69 +69 +61 +209 +117 +53 +234 +126 +45 +238 +128 +40 +173 +106 +60 +51 +62 +63 +139 +115 +96 +251 +168 +115 +246 +156 +93 +247 +150 +84 +249 +146 +83 +249 +152 +92 +247 +165 +111 +248 +180 +134 +250 +200 +166 +187 +166 +150 +55 +66 +67 +69 +69 +61 +163 +104 +61 +234 +125 +52 +234 +126 +45 +234 +125 +52 +227 +126 +50 +227 +126 +50 +234 +126 +45 +234 +126 +45 +199 +115 +54 +95 +78 +64 +35 +56 +60 +81 +73 +62 +227 +126 +50 +227 +126 +50 +224 +123 +55 +234 +126 +45 +139 +96 +61 +51 +62 +63 +250 +197 +158 +245 +169 +119 +247 +150 +84 +247 +130 +60 +247 +118 +39 +235 +107 +16 +243 +101 +2 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +246 +97 +3 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +246 +97 +3 +237 +95 +0 +243 +101 +2 +247 +103 +7 +236 +102 +14 +247 +111 +26 +246 +116 +28 +238 +123 +45 +241 +132 +59 +247 +143 +74 +246 +156 +93 +245 +169 +119 +230 +173 +136 +47 +40 +38 +59 +50 +39 +168 +127 +42 +161 +127 +40 +160 +120 +43 +192 +155 +91 +255 +238 +227 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +253 +255 +252 +239 +227 +208 +170 +137 +67 +171 +129 +45 +171 +129 +45 +171 +129 +45 +59 +50 +39 +154 +133 +118 +250 +200 +166 +250 +197 +158 +249 +189 +146 +248 +180 +134 +249 +174 +124 +247 +165 +111 +247 +165 +111 +245 +162 +103 +249 +159 +103 +245 +162 +103 +247 +165 +111 +249 +174 +124 +203 +161 +131 +55 +66 +67 +69 +69 +61 +111 +94 +57 +105 +93 +60 +69 +69 +61 +63 +74 +74 +137 +127 +115 +51 +62 +63 +62 +63 +61 +95 +87 +59 +129 +106 +52 +137 +110 +49 +137 +110 +49 +123 +102 +54 +95 +87 +59 +62 +63 +61 +51 +62 +63 +133 +120 +107 +239 +182 +144 +248 +180 +134 +245 +169 +119 +247 +165 +111 +249 +159 +103 +245 +162 +103 +251 +168 +115 +250 +176 +132 +239 +182 +144 +154 +133 +118 +63 +74 +74 +51 +62 +63 +75 +74 +61 +105 +93 +60 +123 +102 +54 +137 +110 +49 +137 +110 +49 +137 +110 +49 +123 +102 +54 +100 +89 +56 +75 +74 +61 +56 +64 +60 +55 +66 +67 +124 +111 +99 +219 +170 +138 +252 +185 +144 +250 +176 +132 +249 +174 +124 +249 +174 +124 +250 +176 +132 +252 +185 +144 +236 +186 +153 +124 +111 +99 +48 +58 +59 +63 +69 +60 +95 +87 +59 +123 +102 +54 +137 +110 +49 +137 +110 +49 +129 +106 +52 +95 +87 +59 +62 +63 +61 +55 +66 +67 +146 +135 +124 +77 +85 +81 +61 +67 +58 +105 +93 +60 +111 +94 +57 +75 +74 +61 +48 +58 +59 +194 +173 +157 +255 +215 +190 +255 +215 +190 +255 +215 +190 +234 +204 +183 +120 +114 +108 +43 +57 +62 +69 +69 +61 +100 +89 +56 +129 +106 +52 +137 +110 +49 +137 +110 +49 +129 +106 +52 +105 +93 +60 +69 +69 +61 +48 +58 +59 +77 +85 +81 +51 +62 +63 +137 +110 +49 +168 +127 +42 +158 +125 +46 +168 +127 +42 +137 +110 +49 +51 +62 +63 +187 +166 +150 +187 +166 +150 +48 +58 +59 +75 +74 +61 +111 +94 +57 +95 +87 +59 +56 +64 +60 +99 +90 +79 +239 +182 +144 +252 +185 +144 +245 +179 +138 +252 +185 +144 +249 +189 +146 +236 +186 +153 +137 +127 +115 +55 +66 +67 +56 +64 +60 +83 +78 +61 +111 +94 +57 +129 +106 +52 +137 +110 +49 +137 +110 +49 +129 +106 +52 +117 +98 +55 +95 +87 +59 +69 +69 +61 +51 +62 +63 +63 +74 +74 +133 +120 +107 +236 +186 +153 +250 +197 +158 +251 +192 +154 +251 +192 +154 +250 +197 +158 +124 +111 +99 +51 +62 +63 +112 +85 +63 +146 +97 +64 +106 +82 +65 +48 +58 +59 +120 +114 +108 +101 +100 +92 +48 +58 +59 +95 +78 +64 +146 +97 +64 +183 +110 +59 +188 +112 +56 +173 +106 +60 +139 +96 +61 +89 +75 +66 +48 +58 +59 +77 +85 +81 +186 +157 +134 +245 +179 +138 +245 +169 +119 +245 +162 +103 +246 +156 +93 +246 +156 +93 +246 +156 +93 +247 +165 +111 +249 +174 +124 +249 +189 +146 +154 +133 +118 +58 +69 +70 +51 +62 +63 +95 +78 +64 +139 +96 +61 +173 +106 +60 +183 +110 +59 +183 +110 +59 +173 +106 +60 +139 +96 +61 +95 +78 +64 +51 +62 +63 +63 +74 +74 +167 +142 +123 +249 +189 +146 +249 +174 +124 +247 +165 +111 +246 +156 +93 +246 +156 +93 +246 +156 +93 +245 +162 +103 +245 +169 +119 +245 +179 +138 +178 +146 +122 +70 +79 +77 +48 +58 +59 +89 +75 +66 +139 +96 +61 +173 +106 +60 +188 +112 +56 +183 +110 +59 +155 +100 +63 +95 +78 +64 +48 +58 +59 +101 +100 +92 +146 +135 +124 +48 +58 +59 +95 +78 +64 +146 +97 +64 +125 +90 +64 +62 +63 +61 +101 +100 +92 +245 +212 +186 +137 +127 +115 +48 +58 +59 +106 +82 +65 +146 +97 +64 +106 +82 +65 +48 +58 +59 +124 +111 +99 +247 +165 +111 +247 +150 +84 +241 +138 +68 +241 +132 +59 +247 +130 +53 +247 +130 +53 +242 +133 +67 +241 +145 +79 +245 +162 +103 +250 +176 +132 +203 +161 +131 +91 +92 +89 +43 +57 +62 +81 +73 +62 +135 +94 +64 +173 +106 +60 +188 +112 +56 +183 +110 +59 +155 +100 +63 +106 +82 +65 +51 +62 +63 +91 +92 +89 +133 +120 +107 +48 +58 +59 +95 +78 +64 +146 +97 +64 +118 +86 +65 +56 +64 +60 +101 +100 +92 +245 +212 +186 +253 +212 +188 +146 +135 +124 +48 +58 +59 +118 +86 +65 +183 +110 +59 +173 +106 +60 +95 +78 +64 +43 +57 +62 +186 +157 +134 +250 +197 +158 +251 +192 +154 +250 +197 +158 +250 +200 +166 +172 +150 +134 +70 +79 +77 +48 +58 +59 +89 +75 +66 +135 +94 +64 +163 +104 +61 +183 +110 +59 +183 +110 +59 +173 +106 +60 +146 +97 +64 +95 +78 +64 +56 +64 +60 +55 +66 +67 +150 +125 +114 +236 +186 +153 +251 +192 +154 +249 +189 +146 +249 +189 +146 +251 +192 +154 +195 +157 +134 +51 +62 +63 +76 +70 +64 +139 +96 +61 +125 +90 +64 +65 +67 +64 +76 +78 +76 +234 +168 +124 +249 +159 +103 +247 +150 +84 +243 +141 +78 +247 +143 +74 +247 +150 +84 +249 +159 +103 +250 +176 +132 +250 +197 +158 +255 +215 +190 +207 +178 +158 +84 +85 +82 +48 +58 +59 +89 +75 +66 +146 +97 +64 +173 +106 +60 +183 +110 +59 +183 +110 +59 +163 +104 +61 +118 +86 +65 +62 +63 +61 +58 +69 +70 +63 +74 +74 +81 +73 +62 +227 +126 +50 +227 +126 +50 +224 +123 +55 +234 +126 +45 +135 +94 +64 +58 +69 +70 +251 +192 +154 +245 +169 +119 +249 +146 +83 +247 +130 +53 +238 +116 +34 +235 +107 +16 +243 +101 +2 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +246 +97 +3 +246 +97 +3 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +243 +101 +2 +236 +102 +14 +236 +102 +14 +235 +107 +16 +246 +116 +28 +239 +117 +44 +241 +132 +59 +247 +143 +74 +249 +152 +92 +214 +151 +109 +118 +86 +65 +146 +111 +88 +192 +155 +91 +192 +155 +91 +195 +167 +113 +239 +227 +208 +255 +238 +227 +255 +238 +227 +255 +238 +227 +255 +238 +227 +255 +238 +227 +255 +238 +227 +255 +238 +227 +255 +238 +227 +255 +238 +227 +255 +238 +227 +255 +238 +227 +255 +238 +227 +255 +238 +227 +255 +238 +227 +216 +194 +154 +192 +155 +91 +192 +155 +91 +192 +155 +91 +146 +111 +88 +162 +125 +96 +250 +176 +132 +245 +169 +119 +247 +165 +111 +249 +159 +103 +246 +156 +93 +247 +150 +84 +243 +141 +78 +243 +141 +78 +243 +141 +78 +241 +145 +79 +247 +150 +84 +249 +159 +103 +245 +169 +119 +187 +140 +108 +89 +84 +82 +48 +58 +59 +48 +58 +59 +91 +92 +89 +194 +173 +157 +255 +215 +190 +207 +178 +158 +109 +106 +99 +51 +62 +63 +48 +58 +59 +51 +62 +63 +48 +58 +59 +48 +58 +59 +55 +66 +67 +124 +111 +99 +203 +161 +131 +248 +180 +134 +245 +169 +119 +249 +159 +103 +247 +150 +84 +243 +141 +78 +243 +141 +78 +243 +141 +78 +247 +150 +84 +249 +159 +103 +245 +169 +119 +248 +180 +134 +219 +170 +138 +154 +133 +118 +84 +85 +82 +51 +62 +63 +48 +58 +59 +51 +62 +63 +51 +62 +63 +48 +58 +59 +48 +58 +59 +55 +66 +67 +91 +92 +89 +154 +133 +118 +209 +171 +139 +245 +179 +138 +249 +174 +124 +247 +165 +111 +249 +159 +103 +246 +156 +93 +246 +156 +93 +249 +159 +103 +247 +165 +111 +249 +174 +124 +252 +185 +144 +195 +157 +134 +109 +106 +99 +55 +66 +67 +48 +58 +59 +51 +62 +63 +51 +62 +63 +48 +58 +59 +51 +62 +63 +109 +106 +99 +207 +178 +158 +255 +215 +190 +217 +187 +166 +91 +92 +89 +51 +62 +63 +48 +58 +59 +76 +78 +76 +172 +150 +134 +253 +212 +188 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +255 +215 +190 +194 +173 +157 +101 +100 +92 +51 +62 +63 +48 +58 +59 +48 +58 +59 +51 +62 +63 +48 +58 +59 +48 +58 +59 +97 +98 +96 +194 +173 +157 +146 +135 +124 +56 +64 +60 +145 +114 +49 +168 +127 +42 +158 +125 +46 +168 +127 +42 +129 +106 +52 +48 +58 +59 +194 +173 +157 +255 +215 +190 +176 +156 +141 +76 +78 +76 +48 +58 +59 +55 +66 +67 +115 +102 +92 +234 +168 +124 +245 +169 +119 +247 +165 +111 +247 +165 +111 +247 +165 +111 +245 +169 +119 +249 +174 +124 +245 +179 +138 +209 +171 +139 +144 +125 +110 +76 +78 +76 +48 +58 +59 +48 +58 +59 +51 +62 +63 +51 +62 +63 +48 +58 +59 +48 +58 +59 +58 +69 +70 +101 +100 +92 +154 +133 +118 +219 +170 +138 +252 +185 +144 +248 +180 +134 +249 +174 +124 +245 +169 +119 +249 +174 +124 +250 +176 +132 +230 +173 +136 +124 +111 +99 +55 +66 +67 +43 +57 +62 +58 +69 +70 +137 +127 +115 +245 +212 +186 +245 +212 +186 +161 +144 +134 +70 +79 +77 +43 +57 +62 +51 +62 +63 +51 +62 +63 +48 +58 +59 +43 +57 +62 +84 +85 +82 +154 +133 +118 +240 +181 +138 +249 +174 +124 +247 +165 +111 +249 +152 +92 +243 +141 +78 +241 +138 +68 +242 +133 +67 +241 +138 +68 +241 +145 +79 +246 +156 +93 +247 +165 +111 +250 +176 +132 +219 +170 +138 +144 +125 +110 +77 +85 +81 +43 +57 +62 +48 +58 +59 +48 +58 +59 +51 +62 +63 +48 +58 +59 +43 +57 +62 +77 +85 +81 +150 +125 +114 +219 +170 +138 +250 +176 +132 +247 +165 +111 +246 +156 +93 +241 +145 +79 +241 +138 +68 +241 +138 +68 +241 +138 +68 +243 +141 +78 +249 +152 +92 +247 +165 +111 +250 +176 +132 +230 +173 +136 +154 +133 +118 +77 +85 +81 +43 +57 +62 +48 +58 +59 +51 +62 +63 +48 +58 +59 +43 +57 +62 +70 +79 +77 +161 +144 +134 +245 +212 +186 +255 +215 +190 +161 +144 +134 +63 +74 +74 +43 +57 +62 +51 +62 +63 +109 +106 +99 +217 +187 +166 +251 +209 +178 +238 +205 +179 +137 +127 +115 +58 +69 +70 +43 +57 +62 +58 +69 +70 +139 +115 +96 +238 +159 +107 +249 +152 +92 +241 +138 +68 +247 +130 +53 +238 +123 +45 +239 +117 +44 +247 +118 +39 +238 +123 +45 +241 +132 +59 +241 +145 +79 +249 +159 +103 +249 +174 +124 +240 +181 +138 +167 +142 +123 +91 +92 +89 +43 +57 +62 +48 +58 +59 +51 +62 +63 +48 +58 +59 +43 +57 +62 +63 +74 +74 +137 +127 +115 +234 +204 +183 +255 +215 +190 +146 +135 +124 +63 +74 +74 +43 +57 +62 +51 +62 +63 +115 +102 +92 +236 +186 +153 +251 +192 +154 +251 +192 +154 +236 +186 +153 +133 +120 +107 +43 +57 +62 +48 +58 +59 +48 +58 +59 +55 +66 +67 +158 +130 +108 +248 +180 +134 +250 +176 +132 +249 +174 +124 +249 +174 +124 +250 +176 +132 +252 +185 +144 +239 +182 +144 +154 +133 +118 +84 +85 +82 +43 +57 +62 +48 +58 +59 +48 +58 +59 +51 +62 +63 +48 +58 +59 +43 +57 +62 +70 +79 +77 +133 +120 +107 +219 +170 +138 +245 +179 +138 +250 +176 +132 +245 +169 +119 +247 +165 +111 +247 +165 +111 +245 +169 +119 +249 +174 +124 +187 +140 +108 +81 +77 +76 +43 +57 +62 +43 +57 +62 +99 +90 +79 +214 +151 +109 +249 +159 +103 +247 +150 +84 +247 +143 +74 +241 +138 +68 +241 +138 +68 +249 +146 +83 +249 +159 +103 +250 +176 +132 +250 +197 +158 +255 +215 +190 +255 +215 +190 +245 +212 +186 +161 +144 +134 +77 +85 +81 +43 +57 +62 +48 +58 +59 +51 +62 +63 +48 +58 +59 +41 +58 +57 +55 +66 +67 +120 +114 +108 +217 +187 +166 +97 +98 +96 +95 +78 +64 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +125 +52 +112 +85 +63 +70 +79 +77 +249 +189 +146 +247 +165 +111 +243 +141 +78 +247 +130 +53 +238 +116 +34 +236 +102 +14 +243 +101 +2 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +235 +94 +9 +235 +94 +9 +236 +102 +14 +235 +107 +16 +236 +108 +29 +239 +117 +44 +238 +123 +53 +242 +133 +67 +241 +145 +79 +241 +153 +96 +247 +165 +111 +249 +174 +124 +250 +176 +132 +245 +179 +138 +252 +185 +144 +249 +189 +146 +249 +189 +146 +249 +189 +146 +249 +189 +146 +249 +189 +146 +249 +189 +146 +249 +189 +146 +249 +189 +146 +249 +189 +146 +249 +189 +146 +249 +189 +146 +249 +189 +146 +249 +189 +146 +249 +189 +146 +252 +185 +144 +245 +179 +138 +250 +176 +132 +249 +174 +124 +245 +169 +119 +245 +162 +103 +241 +153 +96 +241 +145 +86 +243 +141 +78 +241 +138 +68 +242 +133 +67 +241 +132 +59 +238 +123 +53 +238 +123 +53 +238 +123 +53 +241 +132 +59 +242 +133 +67 +243 +141 +78 +241 +145 +86 +249 +159 +103 +238 +159 +107 +210 +156 +119 +210 +156 +119 +240 +181 +138 +249 +189 +146 +251 +192 +154 +251 +192 +154 +250 +197 +158 +212 +173 +150 +186 +157 +134 +167 +142 +123 +167 +142 +123 +195 +157 +134 +219 +170 +138 +248 +180 +134 +245 +169 +119 +245 +162 +103 +247 +150 +84 +243 +141 +78 +241 +132 +59 +238 +123 +53 +238 +123 +53 +238 +123 +53 +241 +132 +59 +241 +138 +68 +247 +150 +84 +245 +162 +103 +245 +169 +119 +250 +176 +132 +239 +182 +144 +219 +170 +138 +186 +157 +134 +167 +142 +123 +167 +142 +123 +172 +150 +134 +195 +157 +134 +219 +170 +138 +239 +182 +144 +248 +180 +134 +245 +169 +119 +245 +162 +103 +241 +153 +96 +241 +145 +79 +241 +138 +68 +241 +138 +68 +241 +138 +68 +241 +138 +68 +241 +145 +79 +241 +153 +96 +247 +165 +111 +249 +174 +124 +245 +179 +138 +219 +170 +138 +186 +157 +134 +167 +142 +123 +167 +142 +123 +186 +157 +134 +212 +173 +150 +250 +197 +158 +251 +192 +154 +251 +192 +154 +249 +189 +146 +239 +182 +144 +219 +170 +138 +219 +170 +138 +239 +182 +144 +250 +197 +158 +250 +200 +166 +251 +209 +178 +238 +205 +179 +172 +150 +134 +137 +127 +115 +161 +144 +134 +217 +187 +166 +253 +212 +188 +227 +196 +175 +194 +173 +157 +176 +156 +141 +172 +150 +134 +187 +166 +150 +217 +187 +166 +255 +215 +190 +245 +212 +186 +76 +78 +76 +75 +74 +61 +158 +125 +46 +158 +125 +46 +158 +125 +46 +171 +129 +45 +105 +93 +60 +58 +69 +70 +217 +187 +166 +255 +215 +190 +253 +204 +176 +236 +186 +153 +210 +156 +119 +210 +156 +119 +247 +165 +111 +249 +159 +103 +249 +152 +92 +241 +145 +86 +243 +141 +78 +241 +145 +79 +247 +150 +84 +241 +153 +96 +245 +162 +103 +245 +169 +119 +248 +180 +134 +239 +182 +144 +209 +171 +139 +186 +157 +134 +167 +142 +123 +167 +142 +123 +178 +146 +122 +195 +157 +134 +230 +173 +136 +239 +182 +144 +250 +176 +132 +245 +169 +119 +247 +165 +111 +249 +159 +103 +241 +153 +96 +249 +152 +92 +249 +152 +92 +241 +153 +96 +245 +162 +103 +247 +165 +111 +210 +156 +119 +210 +156 +119 +230 +173 +136 +249 +189 +146 +249 +189 +146 +251 +192 +154 +250 +197 +158 +236 +186 +153 +203 +161 +131 +167 +142 +123 +167 +142 +123 +178 +146 +122 +203 +161 +131 +240 +181 +138 +249 +174 +124 +247 +165 +111 +241 +153 +96 +243 +141 +78 +242 +133 +67 +238 +123 +53 +238 +123 +45 +238 +123 +45 +238 +123 +45 +241 +132 +59 +241 +138 +68 +241 +145 +86 +249 +159 +103 +245 +169 +119 +250 +176 +132 +240 +181 +138 +209 +171 +139 +178 +146 +122 +167 +142 +123 +167 +142 +123 +186 +157 +134 +209 +171 +139 +240 +181 +138 +250 +176 +132 +245 +169 +119 +249 +159 +103 +241 +145 +86 +241 +138 +68 +241 +132 +59 +238 +123 +45 +238 +123 +45 +238 +123 +45 +247 +130 +53 +242 +133 +67 +241 +145 +79 +241 +153 +96 +247 +165 +111 +250 +176 +132 +240 +181 +138 +203 +161 +131 +178 +146 +122 +167 +142 +123 +167 +142 +123 +195 +157 +134 +236 +186 +153 +251 +192 +154 +251 +192 +154 +249 +189 +146 +249 +189 +146 +230 +173 +136 +203 +161 +131 +219 +170 +138 +245 +179 +138 +245 +179 +138 +245 +179 +138 +245 +179 +138 +248 +180 +134 +234 +168 +124 +214 +151 +109 +214 +151 +109 +245 +162 +103 +241 +145 +86 +241 +138 +68 +238 +123 +53 +239 +117 +44 +238 +116 +34 +236 +108 +29 +236 +108 +29 +238 +116 +34 +238 +123 +45 +241 +132 +59 +243 +141 +78 +241 +153 +96 +247 +165 +111 +249 +174 +124 +240 +181 +138 +209 +171 +139 +178 +146 +122 +167 +142 +123 +167 +142 +123 +195 +157 +134 +236 +186 +153 +250 +197 +158 +251 +192 +154 +249 +189 +146 +249 +189 +146 +230 +173 +136 +210 +156 +119 +210 +156 +119 +250 +176 +132 +249 +174 +124 +249 +174 +124 +249 +174 +124 +249 +174 +124 +250 +176 +132 +210 +156 +119 +162 +125 +96 +162 +125 +96 +214 +151 +109 +247 +165 +111 +245 +162 +103 +241 +153 +96 +241 +153 +96 +241 +153 +96 +249 +159 +103 +247 +165 +111 +245 +169 +119 +250 +176 +132 +240 +181 +138 +209 +171 +139 +186 +157 +134 +167 +142 +123 +167 +142 +123 +178 +146 +122 +203 +161 +131 +239 +182 +144 +248 +180 +134 +245 +169 +119 +245 +162 +103 +241 +153 +96 +241 +145 +86 +241 +145 +86 +241 +145 +86 +247 +150 +84 +241 +153 +96 +245 +162 +103 +238 +159 +107 +204 +141 +99 +214 +151 +109 +241 +153 +96 +249 +152 +92 +243 +141 +78 +242 +133 +67 +241 +132 +59 +241 +132 +59 +241 +138 +68 +241 +145 +79 +245 +162 +103 +248 +180 +134 +212 +173 +150 +146 +135 +124 +137 +127 +115 +176 +156 +141 +234 +204 +183 +253 +212 +188 +217 +187 +166 +187 +166 +150 +172 +150 +134 +176 +156 +141 +194 +173 +157 +234 +204 +183 +255 +215 +190 +194 +173 +157 +43 +57 +62 +139 +96 +61 +234 +126 +45 +224 +123 +55 +227 +126 +50 +227 +126 +50 +89 +75 +66 +101 +100 +92 +245 +179 +138 +245 +162 +103 +241 +138 +68 +238 +123 +45 +236 +108 +29 +236 +102 +14 +235 +94 +9 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +235 +94 +9 +235 +94 +9 +236 +102 +14 +235 +107 +16 +236 +108 +29 +238 +116 +34 +238 +123 +45 +241 +132 +59 +241 +138 +68 +241 +145 +79 +249 +152 +92 +241 +153 +96 +245 +162 +103 +245 +162 +103 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +245 +162 +103 +245 +162 +103 +241 +153 +96 +241 +153 +96 +241 +145 +86 +243 +141 +78 +241 +138 +68 +241 +132 +59 +238 +123 +53 +238 +123 +45 +239 +117 +44 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +239 +117 +44 +238 +123 +45 +238 +123 +53 +241 +132 +59 +243 +141 +78 +241 +145 +86 +241 +153 +96 +245 +162 +103 +245 +162 +103 +247 +165 +111 +247 +165 +111 +245 +169 +119 +245 +169 +119 +245 +169 +119 +249 +174 +124 +245 +169 +119 +245 +169 +119 +245 +169 +119 +247 +165 +111 +241 +153 +96 +241 +145 +86 +243 +141 +78 +241 +132 +59 +238 +123 +53 +239 +117 +44 +238 +116 +34 +238 +116 +34 +238 +116 +34 +239 +117 +44 +238 +123 +45 +241 +132 +59 +241 +138 +68 +241 +145 +86 +241 +153 +96 +245 +162 +103 +245 +169 +119 +249 +174 +124 +250 +176 +132 +250 +176 +132 +250 +176 +132 +249 +174 +124 +245 +169 +119 +247 +165 +111 +241 +153 +96 +241 +145 +86 +243 +141 +78 +242 +133 +67 +241 +132 +59 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +45 +241 +132 +59 +242 +133 +67 +243 +141 +78 +249 +152 +92 +245 +162 +103 +247 +165 +111 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +247 +165 +111 +247 +165 +111 +247 +165 +111 +247 +165 +111 +245 +169 +119 +249 +174 +124 +245 +179 +138 +251 +192 +154 +232 +190 +161 +101 +100 +92 +51 +62 +63 +63 +69 +60 +51 +62 +63 +55 +66 +67 +109 +106 +99 +176 +156 +141 +234 +204 +183 +255 +215 +190 +255 +215 +190 +255 +215 +190 +245 +212 +186 +207 +178 +158 +91 +92 +89 +51 +62 +63 +129 +106 +52 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +75 +74 +61 +91 +92 +89 +245 +212 +186 +250 +200 +166 +252 +185 +144 +249 +174 +124 +247 +165 +111 +241 +153 +96 +241 +145 +79 +241 +138 +68 +242 +133 +67 +241 +132 +59 +238 +123 +53 +241 +132 +59 +241 +132 +59 +241 +138 +68 +243 +141 +78 +241 +145 +86 +241 +153 +96 +247 +165 +111 +245 +169 +119 +249 +174 +124 +250 +176 +132 +250 +176 +132 +249 +174 +124 +249 +174 +124 +245 +169 +119 +245 +162 +103 +241 +153 +96 +241 +145 +86 +241 +145 +79 +241 +138 +68 +242 +133 +67 +242 +133 +67 +242 +133 +67 +241 +138 +68 +243 +141 +78 +241 +145 +86 +241 +153 +96 +241 +153 +96 +245 +162 +103 +245 +162 +103 +247 +165 +111 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +247 +165 +111 +245 +162 +103 +241 +153 +96 +241 +145 +79 +241 +138 +68 +238 +123 +53 +238 +123 +45 +238 +116 +34 +235 +113 +30 +235 +113 +30 +238 +116 +34 +239 +117 +44 +238 +123 +45 +241 +132 +59 +241 +138 +68 +241 +145 +86 +241 +153 +96 +245 +162 +103 +245 +169 +119 +245 +169 +119 +249 +174 +124 +249 +174 +124 +245 +169 +119 +245 +169 +119 +245 +162 +103 +241 +153 +96 +241 +145 +86 +241 +138 +68 +241 +132 +59 +238 +123 +45 +239 +117 +44 +238 +116 +34 +235 +113 +30 +235 +113 +30 +238 +116 +34 +238 +123 +45 +241 +132 +59 +241 +138 +68 +241 +145 +86 +241 +153 +96 +245 +162 +103 +247 +165 +111 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +247 +165 +111 +247 +165 +111 +247 +165 +111 +245 +162 +103 +245 +162 +103 +245 +162 +103 +245 +162 +103 +245 +162 +103 +245 +162 +103 +245 +162 +103 +245 +162 +103 +241 +153 +96 +241 +153 +96 +241 +145 +86 +243 +141 +78 +241 +132 +59 +238 +123 +53 +239 +117 +44 +235 +113 +30 +236 +108 +29 +235 +107 +16 +235 +107 +16 +236 +108 +29 +235 +113 +30 +239 +117 +44 +238 +123 +53 +242 +133 +67 +241 +145 +79 +241 +153 +96 +245 +162 +103 +247 +165 +111 +245 +169 +119 +245 +169 +119 +249 +174 +124 +245 +169 +119 +245 +169 +119 +245 +169 +119 +245 +169 +119 +247 +165 +111 +247 +165 +111 +245 +162 +103 +245 +162 +103 +241 +153 +96 +241 +153 +96 +241 +153 +96 +241 +153 +96 +241 +153 +96 +241 +153 +96 +241 +153 +96 +241 +153 +96 +241 +153 +96 +241 +153 +96 +249 +152 +92 +241 +145 +86 +243 +141 +78 +241 +138 +68 +241 +138 +68 +241 +138 +68 +241 +138 +68 +243 +141 +78 +241 +145 +86 +241 +153 +96 +245 +162 +103 +245 +169 +119 +245 +169 +119 +249 +174 +124 +249 +174 +124 +249 +174 +124 +245 +169 +119 +247 +165 +111 +241 +153 +96 +241 +145 +86 +243 +141 +78 +241 +138 +68 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +138 +68 +243 +141 +78 +241 +145 +79 +241 +145 +79 +241 +145 +79 +243 +141 +78 +241 +138 +68 +241 +132 +59 +238 +123 +53 +238 +123 +53 +238 +123 +53 +242 +133 +67 +241 +145 +86 +247 +165 +111 +210 +156 +119 +63 +74 +74 +62 +63 +61 +69 +69 +61 +48 +58 +59 +63 +74 +74 +133 +120 +107 +194 +173 +157 +245 +212 +186 +255 +215 +190 +255 +215 +190 +255 +215 +190 +245 +212 +186 +176 +156 +141 +55 +66 +67 +76 +70 +64 +212 +120 +56 +227 +126 +50 +224 +123 +55 +234 +125 +52 +194 +112 +58 +56 +64 +60 +154 +133 +118 +250 +176 +132 +241 +153 +96 +242 +133 +67 +239 +117 +44 +236 +108 +29 +236 +102 +14 +235 +94 +9 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +235 +94 +9 +235 +94 +9 +236 +102 +14 +236 +102 +14 +236 +108 +29 +235 +113 +30 +239 +117 +44 +238 +123 +45 +238 +123 +53 +241 +132 +59 +241 +138 +68 +241 +138 +68 +243 +141 +78 +243 +141 +78 +241 +145 +79 +241 +145 +79 +241 +145 +79 +241 +145 +79 +241 +145 +79 +241 +145 +79 +241 +145 +79 +241 +145 +79 +241 +145 +79 +241 +145 +79 +241 +145 +79 +243 +141 +78 +243 +141 +78 +243 +141 +78 +241 +138 +68 +241 +138 +68 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +45 +238 +116 +34 +238 +116 +34 +236 +108 +29 +236 +108 +29 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +108 +29 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +123 +45 +238 +123 +53 +241 +132 +59 +242 +133 +67 +241 +138 +68 +243 +141 +78 +243 +141 +78 +241 +145 +79 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +243 +141 +78 +241 +138 +68 +241 +132 +59 +238 +123 +53 +239 +117 +44 +238 +116 +34 +236 +108 +29 +236 +108 +29 +235 +107 +16 +235 +107 +16 +236 +108 +29 +238 +116 +34 +239 +117 +44 +238 +123 +45 +241 +132 +59 +241 +138 +68 +243 +141 +78 +241 +145 +86 +249 +152 +92 +241 +153 +96 +241 +153 +96 +241 +153 +96 +249 +152 +92 +241 +145 +86 +243 +141 +78 +241 +138 +68 +241 +132 +59 +238 +123 +53 +238 +123 +45 +238 +116 +34 +235 +113 +30 +236 +108 +29 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +123 +45 +238 +123 +53 +241 +132 +59 +241 +138 +68 +241 +145 +79 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +79 +241 +145 +79 +241 +145 +79 +241 +145 +86 +241 +153 +96 +245 +162 +103 +245 +169 +119 +245 +179 +138 +144 +125 +110 +51 +62 +63 +117 +98 +55 +158 +125 +46 +145 +114 +49 +105 +93 +60 +69 +69 +61 +48 +58 +59 +58 +69 +70 +91 +92 +89 +120 +114 +108 +120 +114 +108 +91 +92 +89 +48 +58 +59 +56 +64 +60 +123 +102 +54 +171 +129 +45 +158 +125 +46 +158 +125 +46 +168 +127 +42 +137 +110 +49 +48 +58 +59 +161 +144 +134 +250 +197 +158 +248 +180 +134 +247 +165 +111 +241 +153 +96 +241 +145 +79 +241 +138 +68 +241 +132 +59 +238 +123 +53 +238 +123 +45 +239 +117 +44 +238 +116 +34 +238 +116 +34 +239 +117 +44 +238 +123 +45 +238 +123 +53 +241 +132 +59 +241 +138 +68 +243 +141 +78 +241 +145 +86 +249 +152 +92 +241 +153 +96 +241 +153 +96 +241 +153 +96 +241 +145 +86 +241 +145 +86 +243 +141 +78 +241 +138 +68 +241 +132 +59 +238 +123 +53 +238 +123 +45 +238 +123 +45 +239 +117 +44 +238 +123 +45 +238 +123 +45 +238 +123 +53 +241 +132 +59 +241 +132 +59 +241 +138 +68 +241 +138 +68 +243 +141 +78 +241 +145 +79 +241 +145 +79 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +79 +243 +141 +78 +242 +133 +67 +241 +132 +59 +238 +123 +45 +238 +116 +34 +235 +113 +30 +236 +108 +29 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +108 +29 +235 +113 +30 +239 +117 +44 +238 +123 +45 +241 +132 +59 +241 +138 +68 +243 +141 +78 +241 +145 +86 +241 +145 +86 +241 +153 +96 +241 +153 +96 +241 +145 +86 +241 +145 +86 +243 +141 +78 +241 +138 +68 +241 +132 +59 +238 +123 +45 +239 +117 +44 +235 +113 +30 +236 +108 +29 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +108 +29 +235 +113 +30 +239 +117 +44 +238 +123 +45 +241 +132 +59 +242 +133 +67 +243 +141 +78 +241 +145 +79 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +79 +241 +145 +79 +243 +141 +78 +243 +141 +78 +243 +141 +78 +243 +141 +78 +241 +138 +68 +241 +138 +68 +241 +138 +68 +241 +138 +68 +241 +138 +68 +241 +138 +68 +242 +133 +67 +241 +132 +59 +238 +123 +53 +238 +123 +45 +238 +116 +34 +236 +108 +29 +235 +107 +16 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +238 +116 +34 +238 +123 +45 +238 +123 +53 +242 +133 +67 +241 +138 +68 +241 +145 +79 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +86 +241 +145 +79 +243 +141 +78 +243 +141 +78 +241 +138 +68 +241 +138 +68 +241 +138 +68 +242 +133 +67 +242 +133 +67 +242 +133 +67 +241 +138 +68 +241 +138 +68 +241 +138 +68 +241 +138 +68 +242 +133 +67 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +53 +241 +132 +59 +241 +138 +68 +243 +141 +78 +241 +145 +86 +241 +145 +86 +241 +153 +96 +241 +153 +96 +241 +145 +86 +241 +145 +86 +243 +141 +78 +241 +138 +68 +241 +132 +59 +238 +123 +53 +238 +123 +45 +239 +117 +44 +239 +117 +44 +239 +117 +44 +239 +117 +44 +238 +123 +45 +238 +123 +53 +238 +123 +53 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +45 +239 +117 +44 +239 +117 +44 +239 +117 +44 +238 +123 +53 +242 +133 +67 +241 +145 +86 +238 +159 +107 +84 +85 +82 +69 +69 +61 +188 +112 +56 +214 +121 +50 +173 +106 +60 +112 +85 +63 +62 +63 +61 +41 +58 +57 +63 +74 +74 +97 +98 +96 +120 +114 +108 +109 +106 +99 +77 +85 +81 +41 +58 +57 +81 +73 +62 +194 +112 +58 +234 +125 +52 +224 +123 +55 +224 +123 +55 +234 +126 +45 +125 +90 +64 +51 +62 +63 +209 +171 +139 +245 +169 +119 +241 +145 +86 +241 +132 +59 +238 +116 +34 +235 +107 +16 +236 +102 +14 +235 +94 +9 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +237 +95 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +235 +94 +9 +235 +94 +9 +236 +102 +14 +235 +107 +16 +236 +108 +29 +235 +113 +30 +238 +116 +34 +239 +117 +44 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +45 +238 +123 +45 +239 +117 +44 +239 +117 +44 +238 +116 +34 +235 +113 +30 +236 +108 +29 +235 +107 +16 +235 +107 +16 +236 +102 +14 +236 +102 +14 +235 +94 +9 +235 +94 +9 +235 +94 +9 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +236 +108 +29 +238 +116 +34 +239 +117 +44 +239 +117 +44 +238 +123 +45 +238 +123 +45 +238 +123 +53 +238 +123 +53 +238 +123 +53 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +53 +238 +123 +45 +239 +117 +44 +238 +116 +34 +236 +108 +29 +235 +107 +16 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +123 +45 +238 +123 +53 +238 +123 +53 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +45 +239 +117 +44 +238 +116 +34 +236 +108 +29 +235 +107 +16 +235 +107 +16 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +236 +108 +29 +238 +116 +34 +239 +117 +44 +238 +123 +45 +238 +123 +53 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +241 +132 +59 +241 +138 +68 +241 +145 +86 +238 +159 +107 +234 +168 +124 +84 +85 +82 +83 +78 +61 +171 +129 +45 +158 +125 +46 +168 +127 +42 +168 +127 +42 +158 +125 +46 +129 +106 +52 +100 +89 +56 +83 +78 +61 +75 +74 +61 +69 +69 +61 +83 +78 +61 +105 +93 +60 +152 +119 +47 +168 +127 +42 +158 +125 +46 +158 +125 +46 +161 +127 +40 +168 +127 +42 +75 +74 +61 +63 +74 +74 +236 +186 +153 +245 +179 +138 +238 +159 +107 +241 +145 +86 +241 +138 +68 +241 +132 +59 +238 +123 +45 +238 +116 +34 +235 +113 +30 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +238 +116 +34 +239 +117 +44 +238 +123 +45 +238 +123 +53 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +53 +238 +123 +45 +239 +117 +44 +238 +116 +34 +235 +113 +30 +236 +108 +29 +236 +108 +29 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +116 +34 +239 +117 +44 +238 +123 +45 +238 +123 +45 +238 +123 +53 +238 +123 +53 +238 +123 +53 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +45 +239 +117 +44 +238 +116 +34 +235 +113 +30 +236 +108 +29 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +94 +9 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +123 +45 +238 +123 +53 +238 +123 +53 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +53 +238 +123 +45 +238 +116 +34 +235 +113 +30 +236 +108 +29 +235 +107 +16 +236 +102 +14 +236 +102 +14 +235 +94 +9 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +123 +45 +238 +123 +53 +238 +123 +53 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +45 +239 +117 +44 +239 +117 +44 +238 +116 +34 +236 +108 +29 +236 +108 +29 +235 +107 +16 +236 +102 +14 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +238 +116 +34 +239 +117 +44 +238 +123 +45 +238 +123 +53 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +53 +238 +123 +53 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +45 +239 +117 +44 +239 +117 +44 +239 +117 +44 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +45 +238 +123 +45 +239 +117 +44 +239 +117 +44 +238 +116 +34 +235 +113 +30 +236 +108 +29 +236 +108 +29 +235 +113 +30 +238 +116 +34 +239 +117 +44 +238 +123 +45 +238 +123 +53 +238 +123 +53 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +241 +132 +59 +238 +123 +53 +238 +123 +45 +239 +117 +44 +238 +116 +34 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +235 +113 +30 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +123 +45 +241 +132 +59 +241 +145 +86 +204 +141 +99 +41 +58 +57 +155 +100 +63 +234 +126 +45 +227 +126 +50 +227 +126 +50 +234 +125 +52 +209 +117 +53 +155 +100 +63 +118 +86 +65 +89 +75 +66 +81 +73 +62 +81 +73 +62 +106 +82 +65 +155 +100 +63 +214 +121 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +194 +112 +58 +56 +64 +60 +109 +106 +99 +245 +179 +138 +245 +162 +103 +241 +138 +68 +238 +123 +45 +235 +113 +30 +236 +102 +14 +235 +94 +9 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +235 +94 +9 +235 +94 +9 +235 +94 +9 +236 +102 +14 +236 +102 +14 +235 +107 +16 +235 +107 +16 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +235 +113 +30 +235 +113 +30 +235 +113 +30 +235 +113 +30 +235 +113 +30 +235 +113 +30 +235 +113 +30 +235 +113 +30 +235 +113 +30 +235 +113 +30 +235 +113 +30 +235 +113 +30 +235 +113 +30 +235 +113 +30 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +235 +107 +16 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +94 +9 +235 +94 +9 +235 +94 +9 +230 +97 +5 +230 +97 +5 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +236 +108 +29 +236 +108 +29 +235 +113 +30 +235 +113 +30 +235 +113 +30 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +235 +113 +30 +236 +108 +29 +236 +108 +29 +235 +107 +16 +236 +102 +14 +236 +102 +14 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +236 +102 +14 +235 +107 +16 +236 +108 +29 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +116 +34 +239 +117 +44 +239 +117 +44 +239 +117 +44 +238 +116 +34 +238 +116 +34 +235 +113 +30 +236 +108 +29 +236 +108 +29 +235 +107 +16 +236 +102 +14 +236 +102 +14 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +235 +113 +30 +235 +113 +30 +238 +116 +34 +238 +123 +45 +238 +123 +53 +241 +138 +68 +241 +145 +86 +238 +159 +107 +89 +84 +82 +75 +74 +61 +168 +127 +42 +168 +127 +42 +158 +125 +46 +158 +125 +46 +161 +127 +40 +168 +127 +42 +171 +129 +45 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +168 +127 +42 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +95 +87 +59 +48 +58 +59 +167 +142 +123 +245 +179 +138 +238 +159 +107 +241 +145 +86 +242 +133 +67 +238 +123 +45 +238 +116 +34 +236 +108 +29 +236 +108 +29 +235 +107 +16 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +116 +34 +239 +117 +44 +239 +117 +44 +239 +117 +44 +238 +116 +34 +238 +116 +34 +235 +113 +30 +236 +108 +29 +236 +108 +29 +235 +107 +16 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +107 +16 +235 +107 +16 +236 +108 +29 +236 +108 +29 +236 +108 +29 +235 +113 +30 +235 +113 +30 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +235 +113 +30 +236 +108 +29 +235 +107 +16 +236 +102 +14 +236 +102 +14 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +236 +102 +14 +235 +107 +16 +236 +108 +29 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +235 +113 +30 +236 +108 +29 +236 +108 +29 +235 +107 +16 +236 +102 +14 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +235 +113 +30 +235 +113 +30 +235 +113 +30 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +235 +107 +16 +235 +107 +16 +236 +102 +14 +236 +102 +14 +235 +94 +9 +235 +94 +9 +235 +94 +9 +230 +97 +5 +235 +94 +9 +235 +94 +9 +235 +94 +9 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +235 +113 +30 +235 +113 +30 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +236 +108 +29 +235 +107 +16 +235 +107 +16 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +107 +16 +236 +108 +29 +236 +108 +29 +235 +113 +30 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +238 +116 +34 +235 +113 +30 +236 +108 +29 +236 +108 +29 +235 +107 +16 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +107 +16 +235 +107 +16 +236 +108 +29 +236 +108 +29 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +108 +29 +235 +113 +30 +239 +117 +44 +241 +132 +59 +241 +145 +79 +204 +141 +99 +48 +58 +59 +139 +96 +61 +234 +126 +45 +224 +123 +55 +224 +123 +55 +224 +123 +55 +227 +126 +50 +234 +126 +45 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +126 +45 +234 +126 +45 +227 +126 +50 +224 +123 +55 +224 +123 +55 +234 +125 +52 +214 +121 +50 +81 +73 +62 +58 +69 +70 +219 +170 +138 +245 +169 +119 +241 +145 +86 +241 +132 +59 +239 +117 +44 +236 +108 +29 +236 +102 +14 +235 +94 +9 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +235 +94 +9 +230 +97 +5 +229 +102 +7 +229 +102 +7 +236 +102 +14 +236 +102 +14 +224 +98 +18 +224 +98 +18 +224 +98 +18 +236 +102 +14 +224 +98 +18 +236 +102 +14 +236 +102 +14 +224 +98 +18 +224 +98 +18 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +224 +98 +18 +236 +102 +14 +236 +102 +14 +229 +102 +7 +229 +102 +7 +230 +97 +5 +235 +94 +9 +235 +94 +9 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +235 +94 +9 +230 +97 +5 +235 +94 +9 +235 +94 +9 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +102 +14 +224 +98 +18 +236 +102 +14 +235 +94 +9 +235 +94 +9 +235 +94 +9 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +235 +94 +9 +230 +97 +5 +229 +102 +7 +236 +102 +14 +236 +102 +14 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +102 +14 +224 +98 +18 +236 +102 +14 +229 +102 +7 +230 +97 +5 +235 +94 +9 +235 +94 +9 +230 +97 +5 +231 +91 +2 +230 +97 +5 +235 +94 +9 +235 +94 +9 +235 +94 +9 +230 +97 +5 +229 +102 +7 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +102 +14 +224 +98 +18 +236 +102 +14 +235 +107 +16 +236 +108 +29 +239 +117 +44 +234 +125 +52 +231 +136 +72 +241 +153 +96 +162 +125 +96 +48 +58 +59 +95 +87 +59 +158 +125 +46 +171 +129 +45 +168 +127 +42 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +158 +125 +46 +168 +127 +42 +171 +129 +45 +158 +125 +46 +95 +87 +59 +48 +58 +59 +124 +111 +99 +245 +179 +138 +247 +165 +111 +241 +145 +86 +241 +132 +59 +238 +123 +45 +238 +116 +34 +236 +108 +29 +224 +98 +18 +229 +102 +7 +230 +97 +5 +235 +94 +9 +235 +94 +9 +230 +97 +5 +230 +97 +5 +230 +97 +5 +235 +94 +9 +230 +97 +5 +229 +102 +7 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +94 +9 +230 +97 +5 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +236 +102 +14 +236 +102 +14 +236 +102 +14 +224 +98 +18 +224 +98 +18 +236 +102 +14 +236 +102 +14 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +224 +98 +18 +236 +102 +14 +229 +102 +7 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +229 +102 +7 +236 +102 +14 +224 +98 +18 +236 +102 +14 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +102 +14 +224 +98 +18 +236 +102 +14 +229 +102 +7 +230 +97 +5 +235 +94 +9 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +235 +94 +9 +235 +94 +9 +229 +102 +7 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +102 +14 +235 +107 +16 +236 +102 +14 +224 +98 +18 +224 +98 +18 +236 +102 +14 +224 +98 +18 +224 +98 +18 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +229 +102 +7 +236 +102 +14 +235 +94 +9 +230 +97 +5 +235 +94 +9 +235 +94 +9 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +235 +94 +9 +230 +97 +5 +230 +97 +5 +229 +102 +7 +236 +102 +14 +224 +98 +18 +236 +102 +14 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +102 +14 +236 +102 +14 +236 +102 +14 +224 +98 +18 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +236 +102 +14 +224 +98 +18 +236 +102 +14 +236 +102 +14 +236 +102 +14 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +236 +102 +14 +236 +102 +14 +224 +98 +18 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +235 +107 +16 +236 +102 +14 +236 +102 +14 +236 +102 +14 +229 +102 +7 +230 +97 +5 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +235 +94 +9 +230 +97 +5 +235 +94 +9 +236 +102 +14 +236 +102 +14 +236 +102 +14 +229 +102 +7 +230 +97 +5 +229 +102 +7 +224 +98 +18 +236 +108 +29 +238 +116 +34 +238 +123 +53 +243 +141 +78 +241 +153 +96 +99 +90 +79 +56 +64 +60 +155 +100 +63 +234 +126 +45 +234 +126 +45 +227 +126 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +227 +126 +50 +224 +123 +55 +224 +123 +55 +227 +126 +50 +227 +126 +50 +234 +126 +45 +194 +112 +58 +81 +73 +62 +48 +58 +59 +178 +146 +122 +249 +174 +124 +241 +153 +96 +231 +136 +72 +234 +125 +52 +238 +116 +34 +235 +107 +16 +229 +102 +7 +235 +94 +9 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +229 +102 +7 +236 +102 +14 +235 +113 +30 +239 +117 +44 +230 +128 +60 +236 +147 +85 +238 +159 +107 +139 +115 +96 +48 +58 +59 +69 +69 +61 +111 +94 +57 +145 +114 +49 +158 +125 +46 +168 +127 +42 +171 +129 +45 +168 +127 +42 +168 +127 +42 +168 +127 +42 +168 +127 +42 +171 +129 +45 +168 +127 +42 +152 +119 +47 +117 +98 +55 +69 +69 +61 +48 +58 +59 +144 +125 +110 +240 +181 +138 +247 +165 +111 +236 +147 +85 +242 +133 +67 +238 +123 +45 +235 +113 +30 +235 +107 +16 +236 +102 +14 +230 +97 +5 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +230 +97 +5 +229 +102 +7 +235 +107 +16 +235 +113 +30 +238 +123 +45 +242 +133 +67 +241 +153 +96 +214 +151 +109 +99 +90 +79 +48 +58 +59 +95 +78 +64 +155 +100 +63 +209 +117 +53 +227 +126 +50 +234 +125 +52 +234 +125 +52 +234 +125 +52 +234 +125 +52 +234 +125 +52 +234 +126 +45 +234 +126 +45 +227 +126 +50 +194 +112 +58 +125 +90 +64 +56 +64 +60 +58 +69 +70 +178 +146 +122 +250 +176 +132 +238 +159 +107 +241 +145 +79 +234 +125 +52 +239 +117 +44 +236 +108 +29 +224 +98 +18 +230 +97 +5 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +231 +91 +2 +230 +97 +5 +229 +102 +7 +223 +103 +18 +226 +110 +35 +234 +125 +52 +231 +136 +72 +241 +153 +96 +245 +169 +119 +178 +146 +122 +101 +100 +92 +48 +58 +59 +56 +64 +60 +69 +69 +61 +95 +87 +59 +111 +94 +57 +123 +102 +54 +129 +106 +52 +129 +106 +52 +123 +102 +54 +105 +93 +60 +88 +82 +59 +62 +63 +61 +48 +58 +59 +91 +92 +89 +186 +157 +134 +245 +179 +138 +238 +159 +107 +236 +147 +85 +230 +128 +60 +234 +125 +52 +226 +110 +35 +223 +103 +18 +224 +98 +18 +230 +97 +5 +226 +93 +0 +226 +93 +0 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +230 +97 +5 +224 +98 +18 +236 +108 +29 +239 +117 +44 +230 +123 +57 +243 +141 +78 +238 +159 +107 +234 +168 +124 +158 +130 +108 +76 +78 +76 +41 +58 +57 +62 +63 +61 +95 +78 +64 +125 +90 +64 +146 +97 +64 +163 +104 +61 +173 +106 +60 +163 +104 +61 +155 +100 +63 +125 +90 +64 +95 +78 +64 +56 +64 +60 +43 +57 +62 +124 +111 +99 +209 +171 +139 +234 +168 +124 +238 +159 +107 +241 +145 +79 +230 +128 +60 +239 +117 +44 +236 +108 +29 +236 +102 +14 +229 +102 +7 +230 +97 +5 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +231 +91 +2 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +226 +93 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +230 +97 +5 +230 +97 +5 +224 +98 +18 +236 +108 +29 +226 +110 +35 +230 +123 +57 +231 +136 +72 +241 +153 +96 +238 +159 +107 +240 +181 +138 +203 +161 +131 +150 +125 +114 +101 +100 +92 +76 +78 +76 +55 +66 +67 +48 +58 +59 +48 +58 +59 +48 +58 +59 +48 +58 +59 +58 +69 +70 +84 +85 +82 +124 +111 +99 +178 +146 +122 +240 +181 +138 +234 +168 +124 +238 +159 +107 +236 +147 +85 +230 +128 +60 +234 +125 +52 +226 +110 +35 +223 +103 +18 +224 +98 +18 +230 +97 +5 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +230 +97 +5 +224 +98 +18 +223 +103 +18 +226 +110 +35 +225 +124 +48 +230 +128 +60 +236 +147 +85 +241 +153 +96 +234 +168 +124 +230 +173 +136 +186 +157 +134 +133 +120 +107 +91 +92 +89 +63 +74 +74 +51 +62 +63 +48 +58 +59 +48 +58 +59 +48 +58 +59 +51 +62 +63 +63 +74 +74 +91 +92 +89 +144 +125 +110 +203 +161 +131 +240 +181 +138 +245 +169 +119 +241 +153 +96 +241 +145 +79 +230 +128 +60 +225 +124 +48 +226 +110 +35 +223 +103 +18 +224 +98 +18 +230 +97 +5 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +230 +97 +5 +224 +98 +18 +223 +103 +18 +226 +110 +35 +239 +117 +44 +230 +123 +57 +231 +136 +72 +236 +147 +85 +238 +159 +107 +245 +169 +119 +234 +168 +124 +240 +181 +138 +239 +182 +144 +236 +186 +153 +250 +197 +158 +250 +197 +158 +250 +197 +158 +251 +192 +154 +236 +186 +153 +239 +182 +144 +245 +179 +138 +234 +168 +124 +238 +159 +107 +241 +153 +96 +231 +136 +72 +230 +128 +60 +225 +124 +48 +226 +110 +35 +223 +103 +18 +224 +98 +18 +230 +97 +5 +230 +97 +5 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +230 +97 +5 +224 +98 +18 +223 +103 +18 +226 +110 +35 +225 +124 +48 +230 +128 +60 +231 +136 +72 +241 +153 +96 +238 +159 +107 +234 +168 +124 +240 +181 +138 +239 +182 +144 +236 +186 +153 +251 +192 +154 +250 +197 +158 +250 +197 +158 +250 +197 +158 +236 +186 +153 +239 +182 +144 +240 +181 +138 +234 +168 +124 +245 +169 +119 +238 +159 +107 +236 +147 +85 +231 +136 +72 +230 +123 +57 +239 +117 +44 +226 +110 +35 +223 +103 +18 +224 +98 +18 +230 +97 +5 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +225 +92 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +220 +93 +11 +220 +93 +11 +224 +98 +18 +223 +103 +18 +226 +110 +35 +226 +110 +35 +225 +124 +48 +230 +128 +60 +231 +136 +72 +236 +147 +85 +241 +153 +96 +238 +159 +107 +238 +159 +107 +234 +168 +124 +234 +168 +124 +234 +168 +124 +234 +168 +124 +234 +168 +124 +238 +159 +107 +238 +159 +107 +241 +153 +96 +236 +147 +85 +231 +136 +72 +230 +128 +60 +230 +123 +57 +226 +110 +35 +226 +110 +35 +223 +103 +18 +224 +98 +18 +220 +93 +11 +220 +93 +11 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +220 +93 +11 +220 +93 +11 +224 +98 +18 +223 +103 +18 +226 +110 +35 +225 +124 +48 +230 +123 +57 +230 +128 +60 +231 +136 +72 +236 +147 +85 +241 +153 +96 +238 +159 +107 +238 +159 +107 +234 +168 +124 +234 +168 +124 +234 +168 +124 +234 +168 +124 +234 +168 +124 +238 +159 +107 +238 +159 +107 +241 +153 +96 +236 +147 +85 +231 +136 +72 +230 +128 +60 +225 +124 +48 +226 +110 +35 +226 +110 +35 +223 +103 +18 +224 +98 +18 +220 +93 +11 +220 +93 +11 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +220 +93 +11 +220 +93 +11 +220 +93 +11 +224 +98 +18 +223 +103 +18 +226 +110 +35 +226 +110 +35 +225 +124 +48 +230 +128 +60 +230 +128 +60 +231 +136 +72 +231 +136 +72 +236 +147 +85 +236 +147 +85 +236 +147 +85 +236 +147 +85 +236 +147 +85 +231 +136 +72 +231 +136 +72 +231 +136 +72 +230 +128 +60 +227 +126 +50 +225 +124 +48 +226 +110 +35 +223 +103 +18 +223 +103 +18 +224 +98 +18 +220 +93 +11 +220 +93 +11 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +218 +87 +5 +220 +93 +11 +220 +93 +11 +224 +98 +18 +223 +103 +18 +226 +110 +35 +226 +110 +35 +225 +124 +48 +230 +123 +57 +230 +128 +60 +231 +136 +72 +231 +136 +72 +231 +136 +72 +236 +147 +85 +236 +147 +85 +236 +147 +85 +236 +147 +85 +236 +147 +85 +231 +136 +72 +231 +136 +72 +230 +128 +60 +230 +123 +57 +225 +124 +48 +226 +110 +35 +226 +110 +35 +223 +103 +18 +224 +98 +18 +220 +93 +11 +220 +93 +11 +220 +93 +11 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +217 +86 +3 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +217 +86 +3 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +218 +87 +5 +218 +87 +5 +220 +93 +11 +220 +93 +11 +224 +98 +18 +223 +103 +18 +223 +103 +18 +226 +110 +35 +226 +110 +35 +225 +124 +48 +225 +124 +48 +225 +124 +48 +224 +123 +55 +224 +123 +55 +224 +123 +55 +230 +123 +57 +224 +123 +55 +224 +123 +55 +225 +124 +48 +225 +124 +48 +226 +110 +35 +226 +110 +35 +223 +103 +18 +223 +103 +18 +224 +98 +18 +220 +93 +11 +220 +93 +11 +218 +87 +5 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +217 +86 +3 +218 +87 +5 +218 +87 +5 +220 +93 +11 +220 +93 +11 +220 +93 +11 +224 +98 +18 +223 +103 +18 +226 +110 +35 +226 +110 +35 +226 +110 +35 +225 +124 +48 +225 +124 +48 +224 +123 +55 +230 +123 +57 +230 +123 +57 +230 +123 +57 +230 +123 +57 +230 +123 +57 +225 +124 +48 +225 +124 +48 +226 +110 +35 +226 +110 +35 +226 +110 +35 +223 +103 +18 +224 +98 +18 +224 +98 +18 +220 +93 +11 +220 +93 +11 +218 +87 +5 +218 +87 +5 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +221 +89 +0 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +218 +87 +5 +218 +87 +5 +218 +87 +5 +220 +93 +11 +220 +93 +11 +224 +98 +18 +224 +98 +18 +224 +98 +18 +223 +103 +18 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +223 +103 +18 +223 +103 +18 +224 +98 +18 +224 +98 +18 +220 +93 +11 +220 +93 +11 +218 +87 +5 +218 +87 +5 +218 +87 +5 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +220 +93 +11 +220 +93 +11 +224 +98 +18 +224 +98 +18 +223 +103 +18 +223 +103 +18 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +226 +110 +35 +223 +103 +18 +224 +98 +18 +224 +98 +18 +220 +93 +11 +220 +93 +11 +220 +93 +11 +218 +87 +5 +218 +87 +5 +218 +87 +5 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +220 +93 +11 +220 +93 +11 +220 +93 +11 +220 +93 +11 +224 +98 +18 +224 +98 +18 +224 +98 +18 +224 +98 +18 +224 +98 +18 +224 +98 +18 +220 +93 +11 +224 +98 +18 +220 +93 +11 +220 +93 +11 +220 +93 +11 +218 +87 +5 +218 +87 +5 +218 +87 +5 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +218 +87 +5 +217 +86 +3 +218 +87 +5 +218 +87 +5 +218 +87 +5 +220 +93 +11 +220 +93 +11 +220 +93 +11 +220 +93 +11 +220 +93 +11 +224 +98 +18 +224 +98 +18 +224 +98 +18 +224 +98 +18 +224 +98 +18 +220 +93 +11 +220 +93 +11 +220 +93 +11 +220 +93 +11 +220 +93 +11 +218 +87 +5 +218 +87 +5 +218 +87 +5 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +218 +87 +5 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +217 +86 +3 +217 +86 +3 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +217 +86 +3 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +217 +86 +3 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +217 +86 +3 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +217 +86 +3 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +217 +86 +3 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +217 +86 +3 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +217 +86 +3 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +217 +86 +3 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +217 +86 +3 +217 +86 +3 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 +214 +84 +0 diff --git a/recipes/linux/linux-omap-2.6.31/cache/copy-page-tweak.patch b/recipes/linux/linux-omap-2.6.31/cache/copy-page-tweak.patch new file mode 100644 index 0000000000..9da374041c --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/cache/copy-page-tweak.patch @@ -0,0 +1,169 @@ +Path: news.gmane.org!not-for-mail +From: "Kirill A. Shutemov" <kirill@shutemov.name> +Newsgroups: gmane.linux.ports.arm.kernel +Subject: [PATCH] ARM: copy_page.S: take into account the size of the cache line +Date: Wed, 2 Sep 2009 20:19:58 +0300 +Lines: 92 +Approved: news@gmane.org +Message-ID: <1251911998-3112-1-git-send-email-kirill__11898.5180197798$1251901300$gmane$org@shutemov.name> +References: <20090902132423.GA12595@n2100.arm.linux.org.uk> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +X-Trace: ger.gmane.org 1251901300 3930 80.91.229.12 (2 Sep 2009 14:21:40 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 2 Sep 2009 14:21:40 +0000 (UTC) +Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>, + "Kirill A. Shutemov" <kirill@shutemov.name>, + Siarhei Siamashka <siarhei.siamashka@nokia.com>, + Moiseichuk Leonid <leonid.moiseichuk@nokia.com>, + Koskinen Aaro <aaro.koskinen@nokia.com> +To: linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org +Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 16:21:32 2009 +Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org> +Envelope-to: linux-arm-kernel@m.gmane.org +Original-Received: from bombadil.infradead.org ([18.85.46.34]) + by lo.gmane.org with esmtp (Exim 4.50) + id 1MiqiI-0003K3-An + for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 16:21:30 +0200 +Original-Received: from localhost ([::1] helo=bombadil.infradead.org) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1MiqhG-0005iZ-OK; Wed, 02 Sep 2009 14:20:26 +0000 +Original-Received: from mail-bw0-f222.google.com ([209.85.218.222]) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1Miqh8-0005LP-ED for linux-arm-kernel@lists.infradead.org; + Wed, 02 Sep 2009 14:20:23 +0000 +Original-Received: by bwz22 with SMTP id 22so788877bwz.18 + for <linux-arm-kernel@lists.infradead.org>; + Wed, 02 Sep 2009 07:20:06 -0700 (PDT) +Original-Received: by 10.204.162.143 with SMTP id v15mr6724283bkx.50.1251901206540; + Wed, 02 Sep 2009 07:20:06 -0700 (PDT) +Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14]) + by mx.google.com with ESMTPS id d13sm11540576fka.2.2009.09.02.07.20.05 + (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 07:20:05 -0700 (PDT) +X-Mailer: git-send-email 1.6.4.2 +In-Reply-To: <20090902132423.GA12595@n2100.arm.linux.org.uk> +X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) ) + MR-646709E3 +X-CRM114-CacheID: sfid-20090902_102018_607316_8AE98A04 +X-CRM114-Status: UNSURE ( 9.59 ) +X-CRM114-Notice: Please train this message. +X-Spam-Score: -4.2 (----) +X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary: + Content analysis details: (-4.2 points) + pts rule name description + ---- ---------------------- + -------------------------------------------------- + -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1% + [score: 0.0000] + -1.6 AWL AWL: From: address is in the auto white-list +X-BeenThere: linux-arm-kernel@lists.infradead.org +X-Mailman-Version: 2.1.12 +Precedence: list +List-Id: <linux-arm-kernel.lists.infradead.org> +List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe> +List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/> +List-Post: <mailto:linux-arm-kernel@lists.infradead.org> +List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help> +List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe> +Original-Sender: linux-arm-kernel-bounces@lists.infradead.org +Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org +Xref: news.gmane.org gmane.linux.ports.arm.kernel:65025 +Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65025> + +Optimized version of copy_page() was written with assumption that cache +line size is 32 bytes. On Cortex-A8 cache line size is 64 bytes. + +This patch tries to generalize copy_page() to work with any cache line +size if cache line size is multiple of 16 and page size is multiple of +two cache line size. + +After this optimization we've got ~25% speedup on OMAP3(tested in +userspace). + +There is test for kernelspace which trigger copy-on-write after fork(): + + #include <stdlib.h> + #include <string.h> + #include <unistd.h> + + #define BUF_SIZE (10000*4096) + #define NFORK 200 + + int main(int argc, char **argv) + { + char *buf = malloc(BUF_SIZE); + int i; + + memset(buf, 0, BUF_SIZE); + + for(i = 0; i < NFORK; i++) { + if (fork()) { + wait(NULL); + } else { + int j; + + for(j = 0; j < BUF_SIZE; j+= 4096) + buf[j] = (j & 0xFF) + 1; + break; + } + } + + free(buf); + return 0; + } + +Before optimization this test takes ~66 seconds, after optimization +takes ~56 seconds. + +Signed-off-by: Siarhei Siamashka <siarhei.siamashka@nokia.com> +Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> +--- + arch/arm/lib/copy_page.S | 16 ++++++++-------- + 1 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S +index 6ae04db..6ee2f67 100644 +--- a/arch/arm/lib/copy_page.S ++++ b/arch/arm/lib/copy_page.S +@@ -12,8 +12,9 @@ + #include <linux/linkage.h> + #include <asm/assembler.h> + #include <asm/asm-offsets.h> ++#include <asm/cache.h> + +-#define COPY_COUNT (PAGE_SZ/64 PLD( -1 )) ++#define COPY_COUNT (PAGE_SZ / (2 * L1_CACHE_BYTES) PLD( -1 )) + + .text + .align 5 +@@ -26,17 +27,16 @@ + ENTRY(copy_page) + stmfd sp!, {r4, lr} @ 2 + PLD( pld [r1, #0] ) +- PLD( pld [r1, #32] ) ++ PLD( pld [r1, #L1_CACHE_BYTES] ) + mov r2, #COPY_COUNT @ 1 + ldmia r1!, {r3, r4, ip, lr} @ 4+1 +-1: PLD( pld [r1, #64] ) +- PLD( pld [r1, #96] ) +-2: stmia r0!, {r3, r4, ip, lr} @ 4 +- ldmia r1!, {r3, r4, ip, lr} @ 4+1 +- stmia r0!, {r3, r4, ip, lr} @ 4 +- ldmia r1!, {r3, r4, ip, lr} @ 4+1 ++1: PLD( pld [r1, #2 * L1_CACHE_BYTES]) ++ PLD( pld [r1, #3 * L1_CACHE_BYTES]) ++2: ++ .rept (2 * L1_CACHE_BYTES / 16 - 1) + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmia r1!, {r3, r4, ip, lr} @ 4 ++ .endr + subs r2, r2, #1 @ 1 + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmgtia r1!, {r3, r4, ip, lr} @ 4 +-- +1.6.4.2 diff --git a/recipes/linux/linux-omap-2.6.31/cache/l1cache-shift.patch b/recipes/linux/linux-omap-2.6.31/cache/l1cache-shift.patch new file mode 100644 index 0000000000..e58d49c7a3 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/cache/l1cache-shift.patch @@ -0,0 +1,115 @@ +Path: news.gmane.org!not-for-mail +From: "Kirill A. Shutemov" <kirill@shutemov.name> +Newsgroups: gmane.linux.ports.arm.kernel +Subject: [PATCH 1/2] ARM: Introduce ARM_L1_CACHE_SHIFT to define cache line + size +Date: Wed, 2 Sep 2009 19:11:52 +0300 +Lines: 39 +Approved: news@gmane.org +Message-ID: <1251907913-16261-1-git-send-email-kirill__21953.4654439942$1251897245$gmane$org@shutemov.name> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +X-Trace: ger.gmane.org 1251897245 21910 80.91.229.12 (2 Sep 2009 13:14:05 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 2 Sep 2009 13:14:05 +0000 (UTC) +Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>, + "Kirill A. Shutemov" <kirill@shutemov.name>, + Siarhei Siamashka <siarhei.siamashka@nokia.com>, + Moiseichuk Leonid <leonid.moiseichuk@nokia.com>, + Koskinen Aaro <aaro.koskinen@nokia.com> +To: linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org +Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 15:13:57 2009 +Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org> +Envelope-to: linux-arm-kernel@m.gmane.org +Original-Received: from bombadil.infradead.org ([18.85.46.34]) + by lo.gmane.org with esmtp (Exim 4.50) + id 1Mipeu-0000ZH-G2 + for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 15:13:56 +0200 +Original-Received: from localhost ([::1] helo=bombadil.infradead.org) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1MipdW-00035E-AP; Wed, 02 Sep 2009 13:12:30 +0000 +Original-Received: from mail-bw0-f222.google.com ([209.85.218.222]) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1Mipd1-00031v-Ga for linux-arm-kernel@lists.infradead.org; + Wed, 02 Sep 2009 13:12:04 +0000 +Original-Received: by bwz22 with SMTP id 22so735896bwz.18 + for <linux-arm-kernel@lists.infradead.org>; + Wed, 02 Sep 2009 06:11:56 -0700 (PDT) +Original-Received: by 10.204.34.199 with SMTP id m7mr6687295bkd.48.1251897116013; + Wed, 02 Sep 2009 06:11:56 -0700 (PDT) +Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14]) + by mx.google.com with ESMTPS id c28sm2027077fka.19.2009.09.02.06.11.54 + (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 06:11:55 -0700 (PDT) +X-Mailer: git-send-email 1.6.3.4 +X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) ) + MR-646709E3 +X-CRM114-CacheID: sfid-20090902_091159_726883_CEFBECD2 +X-CRM114-Status: UNSURE ( 8.83 ) +X-CRM114-Notice: Please train this message. +X-Spam-Score: -4.6 (----) +X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary: + Content analysis details: (-4.6 points) + pts rule name description + ---- ---------------------- + -------------------------------------------------- + -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1% + [score: 0.0000] + -2.0 AWL AWL: From: address is in the auto white-list +X-BeenThere: linux-arm-kernel@lists.infradead.org +X-Mailman-Version: 2.1.12 +Precedence: list +List-Id: <linux-arm-kernel.lists.infradead.org> +List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe> +List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/> +List-Post: <mailto:linux-arm-kernel@lists.infradead.org> +List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help> +List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe> +Original-Sender: linux-arm-kernel-bounces@lists.infradead.org +Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org +Xref: news.gmane.org gmane.linux.ports.arm.kernel:65017 +Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65017> + +Currently kernel believes that all ARM CPUs have L1_CACHE_SHIFT == 5. +It's not true at least for CPUs based on Cortex-A8. + +List of CPUs with cache line size != 32 should be expanded later. + +Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> +--- + arch/arm/include/asm/cache.h | 2 +- + arch/arm/mm/Kconfig | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h +index feaa75f..2ee7743 100644 +--- a/arch/arm/include/asm/cache.h ++++ b/arch/arm/include/asm/cache.h +@@ -4,7 +4,7 @@ + #ifndef __ASMARM_CACHE_H + #define __ASMARM_CACHE_H + +-#define L1_CACHE_SHIFT 5 ++#define L1_CACHE_SHIFT (CONFIG_ARM_L1_CACHE_SHIFT) + #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) + + /* +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index 83c025e..3c37d4c 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -771,3 +771,8 @@ config CACHE_XSC3L2 + select OUTER_CACHE + help + This option enables the L2 cache on XScale3. ++ ++config ARM_L1_CACHE_SHIFT ++ int ++ default 6 if ARCH_OMAP3 ++ default 5 +-- +1.6.3.4 diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP2-Add-funcs-for-writing-SMS_ROT_-registers.patch b/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP2-Add-funcs-for-writing-SMS_ROT_-registers.patch new file mode 100644 index 0000000000..8880c8b37d --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP2-Add-funcs-for-writing-SMS_ROT_-registers.patch @@ -0,0 +1,69 @@ +From 17091382ab8f92a366e7e1267c30f83711ccd9f8 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Fri, 7 Aug 2009 11:26:12 +0300 +Subject: [PATCH 01/18] OMAP2: Add funcs for writing SMS_ROT_* registers + +SMS_ROT_* registers are used by VRFB rotation engine. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Acked-by: Tony Lindgren <tony@atomide.com> +Acked-by: Paul Walmsley <paul@pwsan.com> +--- + arch/arm/mach-omap2/sdrc.c | 16 ++++++++++++++++ + arch/arm/plat-omap/include/mach/sdrc.h | 9 ++++++++- + 2 files changed, 24 insertions(+), 1 deletions(-) + +diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c +index 9e3bd4f..6a5a2c5 100644 +--- a/arch/arm/mach-omap2/sdrc.c ++++ b/arch/arm/mach-omap2/sdrc.c +@@ -133,3 +133,19 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0, + (1 << SDRC_POWER_PAGEPOLICY_SHIFT); + sdrc_write_reg(l, SDRC_POWER); + } ++ ++void omap2_sms_write_rot_control(u32 val, unsigned ctx) ++{ ++ sms_write_reg(val, SMS_ROT_CONTROL(ctx)); ++} ++ ++void omap2_sms_write_rot_size(u32 val, unsigned ctx) ++{ ++ sms_write_reg(val, SMS_ROT_SIZE(ctx)); ++} ++ ++void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx) ++{ ++ sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx)); ++} ++ +diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h +index 0be18e4..6438f0f 100644 +--- a/arch/arm/plat-omap/include/mach/sdrc.h ++++ b/arch/arm/plat-omap/include/mach/sdrc.h +@@ -79,7 +79,10 @@ + + /* SMS register offsets - read/write with sms_{read,write}_reg() */ + +-#define SMS_SYSCONFIG 0x010 ++#define SMS_SYSCONFIG 0x010 ++#define SMS_ROT_CONTROL(context) (0x180 + 0x10 * context) ++#define SMS_ROT_SIZE(context) (0x184 + 0x10 * context) ++#define SMS_ROT_PHYSICAL_BA(context) (0x188 + 0x10 * context) + /* REVISIT: fill in other SMS registers here */ + + +@@ -112,6 +115,10 @@ int omap2_sdrc_get_params(unsigned long r, + struct omap_sdrc_params **sdrc_cs0, + struct omap_sdrc_params **sdrc_cs1); + ++void omap2_sms_write_rot_control(u32 val, unsigned ctx); ++void omap2_sms_write_rot_size(u32 val, unsigned ctx); ++void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx); ++ + #ifdef CONFIG_ARCH_OMAP2 + + struct memory_timings { +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP3-Enable-DSS2-for-OMAP3EVM-board.patch b/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP3-Enable-DSS2-for-OMAP3EVM-board.patch new file mode 100644 index 0000000000..9a4ea8b9ad --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0001-OMAP3-Enable-DSS2-for-OMAP3EVM-board.patch @@ -0,0 +1,387 @@ +From 798f9b1bc478c7ded724fc190c65e413c2401314 Mon Sep 17 00:00:00 2001 +From: Vaibhav Hiremath <hvaibhav@ti.com> +Date: Tue, 11 Aug 2009 15:52:04 +0530 +Subject: [PATCH 1/5] OMAP3: Enable DSS2 for OMAP3EVM board + +Tested - + - Validated all three outut interfaces (LCD, DVI and TV) +TODO: + - Support for Backlight control range (0 - 100) + - Enable selection for both S-Video and Composite TV out + - DVI color (VPLL2_DEV_GRP should be equal to 0x7) + +Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com> +--- + arch/arm/configs/omap3_evm_defconfig | 51 +++++++- + arch/arm/mach-omap2/board-omap3evm.c | 234 ++++++++++++++++++++++++++++++++-- + 2 files changed, 273 insertions(+), 12 deletions(-) + +diff --git a/arch/arm/configs/omap3_evm_defconfig b/arch/arm/configs/omap3_evm_defconfig +index d5ff477..ba395a2 100644 +--- a/arch/arm/configs/omap3_evm_defconfig ++++ b/arch/arm/configs/omap3_evm_defconfig +@@ -903,7 +903,56 @@ CONFIG_DAB=y + # + # CONFIG_VGASTATE is not set + CONFIG_VIDEO_OUTPUT_CONTROL=m +-# CONFIG_FB is not set ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++CONFIG_FB_CFB_FILLRECT=y ++CONFIG_FB_CFB_COPYAREA=y ++CONFIG_FB_CFB_IMAGEBLIT=y ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set ++CONFIG_OMAP2_VRAM=y ++CONFIG_OMAP2_VRFB=y ++CONFIG_OMAP2_DSS=y ++CONFIG_OMAP2_VRAM_SIZE=4 ++# CONFIG_OMAP2_DSS_DEBUG_SUPPORT is not set ++# CONFIG_OMAP2_DSS_RFBI is not set ++CONFIG_OMAP2_DSS_VENC=y ++# CONFIG_OMAP2_DSS_SDI is not set ++# CONFIG_OMAP2_DSS_DSI is not set ++# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set ++CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 ++CONFIG_FB_OMAP2=y ++# CONFIG_FB_OMAP2_DEBUG_SUPPORT is not set ++# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set ++CONFIG_FB_OMAP2_NUM_FBS=3 ++ ++# ++# OMAP2/3 Display Device Drivers ++# ++CONFIG_PANEL_GENERIC=y ++# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set ++CONFIG_PANEL_SHARP_LS037V7DW01=y + # CONFIG_BACKLIGHT_LCD_SUPPORT is not set + + # +diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c +index c0cb29d..0bc26b3 100644 +--- a/arch/arm/mach-omap2/board-omap3evm.c ++++ b/arch/arm/mach-omap2/board-omap3evm.c +@@ -22,6 +22,7 @@ + #include <linux/input.h> + #include <linux/leds.h> + ++#include <linux/regulator/machine.h> + #include <linux/spi/spi.h> + #include <linux/spi/ads7846.h> + #include <linux/i2c/twl4030.h> +@@ -38,6 +39,7 @@ + #include <mach/common.h> + #include <mach/mcspi.h> + #include <mach/keypad.h> ++#include <mach/display.h> + + #include "sdram-micron-mt46h32m32lf-6.h" + #include "mmc-twl4030.h" +@@ -91,6 +93,174 @@ static inline void __init omap3evm_init_smc911x(void) + + gpio_direction_input(OMAP3EVM_ETHR_GPIO_IRQ); + } ++/* ++ * OMAP3EVM LCD Panel control signals ++ */ ++#define OMAP3EVM_LCD_PANEL_LR 2 ++#define OMAP3EVM_LCD_PANEL_UD 3 ++#define OMAP3EVM_LCD_PANEL_INI 152 ++#define OMAP3EVM_LCD_PANEL_ENVDD 153 ++#define OMAP3EVM_LCD_PANEL_QVGA 154 ++#define OMAP3EVM_LCD_PANEL_RESB 155 ++#define OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO 210 ++#define OMAP3EVM_DVI_PANEL_EN_GPIO 199 ++ ++static int lcd_enabled; ++static int dvi_enabled; ++ ++static void __init omap3_evm_display_init(void) ++{ ++ int r; ++ r = gpio_request(OMAP3EVM_LCD_PANEL_RESB, "lcd_panel_resb"); ++ if (r) { ++ printk(KERN_ERR "failed to get lcd_panel_resb\n"); ++ return; ++ } ++ gpio_direction_output(OMAP3EVM_LCD_PANEL_RESB, 1); ++ ++ r = gpio_request(OMAP3EVM_LCD_PANEL_INI, "lcd_panel_ini"); ++ if (r) { ++ printk(KERN_ERR "failed to get lcd_panel_ini\n"); ++ goto err_1; ++ } ++ gpio_direction_output(OMAP3EVM_LCD_PANEL_INI, 1); ++ ++ r = gpio_request(OMAP3EVM_LCD_PANEL_QVGA, "lcd_panel_qvga"); ++ if (r) { ++ printk(KERN_ERR "failed to get lcd_panel_qvga\n"); ++ goto err_2; ++ } ++ gpio_direction_output(OMAP3EVM_LCD_PANEL_QVGA, 0); ++ ++ r = gpio_request(OMAP3EVM_LCD_PANEL_LR, "lcd_panel_lr"); ++ if (r) { ++ printk(KERN_ERR "failed to get lcd_panel_lr\n"); ++ goto err_3; ++ } ++ gpio_direction_output(OMAP3EVM_LCD_PANEL_LR, 1); ++ ++ r = gpio_request(OMAP3EVM_LCD_PANEL_UD, "lcd_panel_ud"); ++ if (r) { ++ printk(KERN_ERR "failed to get lcd_panel_ud\n"); ++ goto err_4; ++ } ++ gpio_direction_output(OMAP3EVM_LCD_PANEL_UD, 1); ++ ++ r = gpio_request(OMAP3EVM_LCD_PANEL_ENVDD, "lcd_panel_envdd"); ++ if (r) { ++ printk(KERN_ERR "failed to get lcd_panel_envdd\n"); ++ goto err_5; ++ } ++ ++ return; ++ ++err_5: ++ gpio_free(OMAP3EVM_LCD_PANEL_UD); ++err_4: ++ gpio_free(OMAP3EVM_LCD_PANEL_LR); ++err_3: ++ gpio_free(OMAP3EVM_LCD_PANEL_QVGA); ++err_2: ++ gpio_free(OMAP3EVM_LCD_PANEL_INI); ++err_1: ++ gpio_free(OMAP3EVM_LCD_PANEL_RESB); ++ ++} ++ ++static int omap3_evm_enable_lcd(struct omap_dss_device *dssdev) ++{ ++ if (dvi_enabled) { ++ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); ++ return -EINVAL; ++ } ++ ++ gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 0); ++ gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1); ++ lcd_enabled = 1; ++ return 0; ++} ++ ++static void omap3_evm_disable_lcd(struct omap_dss_device *dssdev) ++{ ++ gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 1); ++ gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0); ++ lcd_enabled = 0; ++} ++ ++static struct omap_dss_device omap3_evm_lcd_device = { ++ .type = OMAP_DISPLAY_TYPE_DPI, ++ .name = "lcd", ++ .driver_name = "sharp_ls_panel", ++ .phy.dpi.data_lines = 18, ++ .platform_enable = omap3_evm_enable_lcd, ++ .platform_disable = omap3_evm_disable_lcd, ++}; ++ ++static int omap3_evm_enable_tv(struct omap_dss_device *dssdev) ++{ ++ return 0; ++} ++ ++static void omap3_evm_disable_tv(struct omap_dss_device *dssdev) ++{ ++} ++ ++static struct omap_dss_device omap3_evm_tv_device = { ++ .type = OMAP_DISPLAY_TYPE_VENC, ++ .name = "tv", ++ .driver_name = "venc", ++ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, ++ .platform_enable = omap3_evm_enable_tv, ++ .platform_disable = omap3_evm_disable_tv, ++}; ++ ++static int omap3_evm_enable_dvi(struct omap_dss_device *dssdev) ++{ ++ if (lcd_enabled) { ++ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n"); ++ return -EINVAL; ++ } ++ ++ gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 1); ++ dvi_enabled = 1; ++ ++ return 0; ++} ++ ++static void omap3_evm_disable_dvi(struct omap_dss_device *dssdev) ++{ ++ gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 0); ++ dvi_enabled = 0; ++} ++ ++static struct omap_dss_device omap3_evm_dvi_device = { ++ .type = OMAP_DISPLAY_TYPE_DPI, ++ .name = "dvi", ++ .driver_name = "generic_panel", ++ .phy.dpi.data_lines = 24, ++ .platform_enable = omap3_evm_enable_dvi, ++ .platform_disable = omap3_evm_disable_dvi, ++}; ++ ++static struct omap_dss_device *omap3_evm_dss_devices[] = { ++ &omap3_evm_lcd_device, ++ &omap3_evm_tv_device, ++ &omap3_evm_dvi_device, ++}; ++ ++static struct omap_dss_board_info omap3_evm_dss_data = { ++ .num_devices = ARRAY_SIZE(omap3_evm_dss_devices), ++ .devices = omap3_evm_dss_devices, ++ .default_device = &omap3_evm_lcd_device, ++}; ++ ++static struct platform_device omap3_evm_dss_device = { ++ .name = "omapdss", ++ .id = -1, ++ .dev = { ++ .platform_data = &omap3_evm_dss_data, ++ }, ++}; + + static struct omap_uart_platform_data omap3_evm_uart_config __initdata = { + .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), +@@ -143,6 +313,14 @@ static int omap3evm_twl_gpio_setup(struct device *dev, + * the P2 connector; notably LEDA for the LCD backlight. + */ + ++ /* TWL4030_GPIO_MAX + 0 == ledA, LCD Backlight control */ ++ gpio_request(gpio + TWL4030_GPIO_MAX, "EN_LCD_BKL"); ++ gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); ++ ++ /* gpio + 7 == DVI Enable */ ++ gpio_request(gpio + 7, "EN_DVI"); ++ gpio_direction_output(gpio + 7, 0); ++ + /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */ + gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; + +@@ -194,6 +372,47 @@ static struct twl4030_madc_platform_data omap3evm_madc_data = { + .irq_line = 1, + }; + ++static struct regulator_consumer_supply omap3_evm_vdda_dac_supply = { ++ .supply = "vdda_dac", ++ .dev = &omap3_evm_dss_device.dev, ++}; ++ ++/* VDAC for DSS driving S-Video */ ++static struct regulator_init_data omap3_evm_vdac = { ++ .constraints = { ++ .min_uV = 1800000, ++ .max_uV = 1800000, ++ .apply_uV = true, ++ .valid_modes_mask = REGULATOR_MODE_NORMAL ++ | REGULATOR_MODE_STANDBY, ++ .valid_ops_mask = REGULATOR_CHANGE_MODE ++ | REGULATOR_CHANGE_STATUS, ++ }, ++ .num_consumer_supplies = 1, ++ .consumer_supplies = &omap3_evm_vdda_dac_supply, ++}; ++ ++/* VPLL2 for digital video outputs */ ++static struct regulator_consumer_supply omap3_evm_vpll2_supply = { ++ .supply = "vdvi", ++ .dev = &omap3_evm_lcd_device.dev, ++}; ++ ++static struct regulator_init_data omap3_evm_vpll2 = { ++ .constraints = { ++ .name = "VDVI", ++ .min_uV = 1800000, ++ .max_uV = 1800000, ++ .apply_uV = true, ++ .valid_modes_mask = REGULATOR_MODE_NORMAL ++ | REGULATOR_MODE_STANDBY, ++ .valid_ops_mask = REGULATOR_CHANGE_MODE ++ | REGULATOR_CHANGE_STATUS, ++ }, ++ .num_consumer_supplies = 1, ++ .consumer_supplies = &omap3_evm_vpll2_supply, ++}; ++ + static struct twl4030_platform_data omap3evm_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, +@@ -203,6 +422,8 @@ static struct twl4030_platform_data omap3evm_twldata = { + .madc = &omap3evm_madc_data, + .usb = &omap3evm_usb_data, + .gpio = &omap3evm_gpio_data, ++ .vdac = &omap3_evm_vdac, ++ .vpll2 = &omap3_evm_vpll2, + }; + + static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = { +@@ -223,15 +444,6 @@ static int __init omap3_evm_i2c_init(void) + return 0; + } + +-static struct platform_device omap3_evm_lcd_device = { +- .name = "omap3evm_lcd", +- .id = -1, +-}; +- +-static struct omap_lcd_config omap3_evm_lcd_config __initdata = { +- .ctrl_name = "internal", +-}; +- + static void ads7846_dev_init(void) + { + if (gpio_request(OMAP3_EVM_TS_GPIO, "ADS7846 pendown") < 0) +@@ -287,11 +499,10 @@ static void __init omap3_evm_init_irq(void) + } + + static struct omap_board_config_kernel omap3_evm_config[] __initdata = { +- { OMAP_TAG_LCD, &omap3_evm_lcd_config }, + }; + + static struct platform_device *omap3_evm_devices[] __initdata = { +- &omap3_evm_lcd_device, ++ &omap3_evm_dss_device, + &omap3evm_smc911x_device, + }; + +@@ -314,6 +525,7 @@ static void __init omap3_evm_init(void) + usb_musb_init(); + usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61); + ads7846_dev_init(); ++ omap3_evm_display_init(); + } + + static void __init omap3_evm_map_io(void) +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0002-OMAP-OMAPFB-split-omapfb.h.patch b/recipes/linux/linux-omap-2.6.31/dss2/0002-OMAP-OMAPFB-split-omapfb.h.patch new file mode 100644 index 0000000000..405ea72fec --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0002-OMAP-OMAPFB-split-omapfb.h.patch @@ -0,0 +1,1151 @@ +From c87b390673167a65a52c0e8da22e2842862227f1 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Mon, 3 Aug 2009 15:06:36 +0300 +Subject: [PATCH 02/18] OMAP: OMAPFB: split omapfb.h + +Split arch/arm/plat-omap/include/mach/omapfb.h into two files: + +include/linux/omapfb.h - ioctls etc for userspace and some kernel + stuff for board files +drivers/video/omap/omapfb.h - for omapfb internal use + +This cleans up omapfb.h and also makes it easier for the upcoming new +DSS driver to co-exist with the old driver. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Acked-by: Tony Lindgren <tony@atomide.com> +--- + arch/arm/mach-omap1/board-nokia770.c | 2 +- + arch/arm/mach-omap2/io.c | 2 +- + arch/arm/plat-omap/fb.c | 2 +- + arch/arm/plat-omap/include/mach/omapfb.h | 398 ------------------------------ + drivers/video/omap/blizzard.c | 2 +- + drivers/video/omap/dispc.c | 2 +- + drivers/video/omap/hwa742.c | 2 +- + drivers/video/omap/lcd_h3.c | 2 +- + drivers/video/omap/lcd_h4.c | 2 +- + drivers/video/omap/lcd_inn1510.c | 2 +- + drivers/video/omap/lcd_inn1610.c | 2 +- + drivers/video/omap/lcd_osk.c | 2 +- + drivers/video/omap/lcd_palmte.c | 2 +- + drivers/video/omap/lcd_palmtt.c | 2 +- + drivers/video/omap/lcd_palmz71.c | 2 +- + drivers/video/omap/lcdc.c | 3 +- + drivers/video/omap/omapfb.h | 227 +++++++++++++++++ + drivers/video/omap/omapfb_main.c | 2 +- + drivers/video/omap/rfbi.c | 3 +- + drivers/video/omap/sossi.c | 2 +- + include/linux/omapfb.h | 197 +++++++++++++++ + 21 files changed, 443 insertions(+), 417 deletions(-) + delete mode 100644 arch/arm/plat-omap/include/mach/omapfb.h + create mode 100644 drivers/video/omap/omapfb.h + create mode 100644 include/linux/omapfb.h + +diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c +index ed2a48a..6fbde33 100644 +--- a/arch/arm/mach-omap1/board-nokia770.c ++++ b/arch/arm/mach-omap1/board-nokia770.c +@@ -14,6 +14,7 @@ + #include <linux/platform_device.h> + #include <linux/input.h> + #include <linux/clk.h> ++#include <linux/omapfb.h> + + #include <linux/spi/spi.h> + #include <linux/spi/ads7846.h> +@@ -32,7 +33,6 @@ + #include <mach/keypad.h> + #include <mach/common.h> + #include <mach/dsp_common.h> +-#include <mach/omapfb.h> + #include <mach/hwa742.h> + #include <mach/lcd_mipid.h> + #include <mach/mmc.h> +diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c +index e9b9bcb..49199a3 100644 +--- a/arch/arm/mach-omap2/io.c ++++ b/arch/arm/mach-omap2/io.c +@@ -22,13 +22,13 @@ + #include <linux/init.h> + #include <linux/io.h> + #include <linux/clk.h> ++#include <linux/omapfb.h> + + #include <asm/tlb.h> + + #include <asm/mach/map.h> + + #include <mach/mux.h> +-#include <mach/omapfb.h> + #include <mach/sram.h> + #include <mach/sdrc.h> + #include <mach/gpmc.h> +diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c +index 3746222..40615a6 100644 +--- a/arch/arm/plat-omap/fb.c ++++ b/arch/arm/plat-omap/fb.c +@@ -28,13 +28,13 @@ + #include <linux/platform_device.h> + #include <linux/bootmem.h> + #include <linux/io.h> ++#include <linux/omapfb.h> + + #include <mach/hardware.h> + #include <asm/mach/map.h> + + #include <mach/board.h> + #include <mach/sram.h> +-#include <mach/omapfb.h> + + #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) + +diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h +deleted file mode 100644 +index 7b74d12..0000000 +--- a/arch/arm/plat-omap/include/mach/omapfb.h ++++ /dev/null +@@ -1,398 +0,0 @@ +-/* +- * File: arch/arm/plat-omap/include/mach/omapfb.h +- * +- * Framebuffer driver for TI OMAP boards +- * +- * Copyright (C) 2004 Nokia Corporation +- * Author: Imre Deak <imre.deak@nokia.com> +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- */ +- +-#ifndef __OMAPFB_H +-#define __OMAPFB_H +- +-#include <asm/ioctl.h> +-#include <asm/types.h> +- +-/* IOCTL commands. */ +- +-#define OMAP_IOW(num, dtype) _IOW('O', num, dtype) +-#define OMAP_IOR(num, dtype) _IOR('O', num, dtype) +-#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype) +-#define OMAP_IO(num) _IO('O', num) +- +-#define OMAPFB_MIRROR OMAP_IOW(31, int) +-#define OMAPFB_SYNC_GFX OMAP_IO(37) +-#define OMAPFB_VSYNC OMAP_IO(38) +-#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) +-#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps) +-#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) +-#define OMAPFB_LCD_TEST OMAP_IOW(45, int) +-#define OMAPFB_CTRL_TEST OMAP_IOW(46, int) +-#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old) +-#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) +-#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key) +-#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info) +-#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info) +-#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window) +-#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info) +-#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info) +- +-#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff +-#define OMAPFB_CAPS_LCDC_MASK 0x00fff000 +-#define OMAPFB_CAPS_PANEL_MASK 0xff000000 +- +-#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000 +-#define OMAPFB_CAPS_TEARSYNC 0x00002000 +-#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000 +-#define OMAPFB_CAPS_PLANE_SCALE 0x00008000 +-#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000 +-#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000 +-#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000 +-#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000 +-#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000 +- +-/* Values from DSP must map to lower 16-bits */ +-#define OMAPFB_FORMAT_MASK 0x00ff +-#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 +-#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200 +-#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400 +-#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800 +-#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000 +- +-#define OMAPFB_EVENT_READY 1 +-#define OMAPFB_EVENT_DISABLED 2 +- +-#define OMAPFB_MEMTYPE_SDRAM 0 +-#define OMAPFB_MEMTYPE_SRAM 1 +-#define OMAPFB_MEMTYPE_MAX 1 +- +-enum omapfb_color_format { +- OMAPFB_COLOR_RGB565 = 0, +- OMAPFB_COLOR_YUV422, +- OMAPFB_COLOR_YUV420, +- OMAPFB_COLOR_CLUT_8BPP, +- OMAPFB_COLOR_CLUT_4BPP, +- OMAPFB_COLOR_CLUT_2BPP, +- OMAPFB_COLOR_CLUT_1BPP, +- OMAPFB_COLOR_RGB444, +- OMAPFB_COLOR_YUY422, +-}; +- +-struct omapfb_update_window { +- __u32 x, y; +- __u32 width, height; +- __u32 format; +- __u32 out_x, out_y; +- __u32 out_width, out_height; +- __u32 reserved[8]; +-}; +- +-struct omapfb_update_window_old { +- __u32 x, y; +- __u32 width, height; +- __u32 format; +-}; +- +-enum omapfb_plane { +- OMAPFB_PLANE_GFX = 0, +- OMAPFB_PLANE_VID1, +- OMAPFB_PLANE_VID2, +-}; +- +-enum omapfb_channel_out { +- OMAPFB_CHANNEL_OUT_LCD = 0, +- OMAPFB_CHANNEL_OUT_DIGIT, +-}; +- +-struct omapfb_plane_info { +- __u32 pos_x; +- __u32 pos_y; +- __u8 enabled; +- __u8 channel_out; +- __u8 mirror; +- __u8 reserved1; +- __u32 out_width; +- __u32 out_height; +- __u32 reserved2[12]; +-}; +- +-struct omapfb_mem_info { +- __u32 size; +- __u8 type; +- __u8 reserved[3]; +-}; +- +-struct omapfb_caps { +- __u32 ctrl; +- __u32 plane_color; +- __u32 wnd_color; +-}; +- +-enum omapfb_color_key_type { +- OMAPFB_COLOR_KEY_DISABLED = 0, +- OMAPFB_COLOR_KEY_GFX_DST, +- OMAPFB_COLOR_KEY_VID_SRC, +-}; +- +-struct omapfb_color_key { +- __u8 channel_out; +- __u32 background; +- __u32 trans_key; +- __u8 key_type; +-}; +- +-enum omapfb_update_mode { +- OMAPFB_UPDATE_DISABLED = 0, +- OMAPFB_AUTO_UPDATE, +- OMAPFB_MANUAL_UPDATE +-}; +- +-#ifdef __KERNEL__ +- +-#include <linux/completion.h> +-#include <linux/interrupt.h> +-#include <linux/fb.h> +-#include <linux/mutex.h> +- +-#include <mach/board.h> +- +-#define OMAP_LCDC_INV_VSYNC 0x0001 +-#define OMAP_LCDC_INV_HSYNC 0x0002 +-#define OMAP_LCDC_INV_PIX_CLOCK 0x0004 +-#define OMAP_LCDC_INV_OUTPUT_EN 0x0008 +-#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010 +-#define OMAP_LCDC_HSVS_OPPOSITE 0x0020 +- +-#define OMAP_LCDC_SIGNAL_MASK 0x003f +- +-#define OMAP_LCDC_PANEL_TFT 0x0100 +- +-#define OMAPFB_PLANE_XRES_MIN 8 +-#define OMAPFB_PLANE_YRES_MIN 8 +- +-#ifdef CONFIG_ARCH_OMAP1 +-#define OMAPFB_PLANE_NUM 1 +-#else +-#define OMAPFB_PLANE_NUM 3 +-#endif +- +-struct omapfb_device; +- +-struct lcd_panel { +- const char *name; +- int config; /* TFT/STN, signal inversion */ +- int bpp; /* Pixel format in fb mem */ +- int data_lines; /* Lines on LCD HW interface */ +- +- int x_res, y_res; +- int pixel_clock; /* In kHz */ +- int hsw; /* Horizontal synchronization +- pulse width */ +- int hfp; /* Horizontal front porch */ +- int hbp; /* Horizontal back porch */ +- int vsw; /* Vertical synchronization +- pulse width */ +- int vfp; /* Vertical front porch */ +- int vbp; /* Vertical back porch */ +- int acb; /* ac-bias pin frequency */ +- int pcd; /* pixel clock divider. +- Obsolete use pixel_clock instead */ +- +- int (*init) (struct lcd_panel *panel, +- struct omapfb_device *fbdev); +- void (*cleanup) (struct lcd_panel *panel); +- int (*enable) (struct lcd_panel *panel); +- void (*disable) (struct lcd_panel *panel); +- unsigned long (*get_caps) (struct lcd_panel *panel); +- int (*set_bklight_level)(struct lcd_panel *panel, +- unsigned int level); +- unsigned int (*get_bklight_level)(struct lcd_panel *panel); +- unsigned int (*get_bklight_max) (struct lcd_panel *panel); +- int (*run_test) (struct lcd_panel *panel, int test_num); +-}; +- +-struct extif_timings { +- int cs_on_time; +- int cs_off_time; +- int we_on_time; +- int we_off_time; +- int re_on_time; +- int re_off_time; +- int we_cycle_time; +- int re_cycle_time; +- int cs_pulse_width; +- int access_time; +- +- int clk_div; +- +- u32 tim[5]; /* set by extif->convert_timings */ +- +- int converted; +-}; +- +-struct lcd_ctrl_extif { +- int (*init) (struct omapfb_device *fbdev); +- void (*cleanup) (void); +- void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div); +- unsigned long (*get_max_tx_rate)(void); +- int (*convert_timings) (struct extif_timings *timings); +- void (*set_timings) (const struct extif_timings *timings); +- void (*set_bits_per_cycle)(int bpc); +- void (*write_command) (const void *buf, unsigned int len); +- void (*read_data) (void *buf, unsigned int len); +- void (*write_data) (const void *buf, unsigned int len); +- void (*transfer_area) (int width, int height, +- void (callback)(void * data), void *data); +- int (*setup_tearsync) (unsigned pin_cnt, +- unsigned hs_pulse_time, unsigned vs_pulse_time, +- int hs_pol_inv, int vs_pol_inv, int div); +- int (*enable_tearsync) (int enable, unsigned line); +- +- unsigned long max_transmit_size; +-}; +- +-struct omapfb_notifier_block { +- struct notifier_block nb; +- void *data; +- int plane_idx; +-}; +- +-typedef int (*omapfb_notifier_callback_t)(struct notifier_block *, +- unsigned long event, +- void *fbi); +- +-struct omapfb_mem_region { +- dma_addr_t paddr; +- void *vaddr; +- unsigned long size; +- u8 type; /* OMAPFB_PLANE_MEM_* */ +- unsigned alloc:1; /* allocated by the driver */ +- unsigned map:1; /* kernel mapped by the driver */ +-}; +- +-struct omapfb_mem_desc { +- int region_cnt; +- struct omapfb_mem_region region[OMAPFB_PLANE_NUM]; +-}; +- +-struct lcd_ctrl { +- const char *name; +- void *data; +- +- int (*init) (struct omapfb_device *fbdev, +- int ext_mode, +- struct omapfb_mem_desc *req_md); +- void (*cleanup) (void); +- void (*bind_client) (struct omapfb_notifier_block *nb); +- void (*get_caps) (int plane, struct omapfb_caps *caps); +- int (*set_update_mode)(enum omapfb_update_mode mode); +- enum omapfb_update_mode (*get_update_mode)(void); +- int (*setup_plane) (int plane, int channel_out, +- unsigned long offset, +- int screen_width, +- int pos_x, int pos_y, int width, +- int height, int color_mode); +- int (*set_rotate) (int angle); +- int (*setup_mem) (int plane, size_t size, +- int mem_type, unsigned long *paddr); +- int (*mmap) (struct fb_info *info, +- struct vm_area_struct *vma); +- int (*set_scale) (int plane, +- int orig_width, int orig_height, +- int out_width, int out_height); +- int (*enable_plane) (int plane, int enable); +- int (*update_window) (struct fb_info *fbi, +- struct omapfb_update_window *win, +- void (*callback)(void *), +- void *callback_data); +- void (*sync) (void); +- void (*suspend) (void); +- void (*resume) (void); +- int (*run_test) (int test_num); +- int (*setcolreg) (u_int regno, u16 red, u16 green, +- u16 blue, u16 transp, +- int update_hw_mem); +- int (*set_color_key) (struct omapfb_color_key *ck); +- int (*get_color_key) (struct omapfb_color_key *ck); +-}; +- +-enum omapfb_state { +- OMAPFB_DISABLED = 0, +- OMAPFB_SUSPENDED= 99, +- OMAPFB_ACTIVE = 100 +-}; +- +-struct omapfb_plane_struct { +- int idx; +- struct omapfb_plane_info info; +- enum omapfb_color_format color_mode; +- struct omapfb_device *fbdev; +-}; +- +-struct omapfb_device { +- int state; +- int ext_lcdc; /* Using external +- LCD controller */ +- struct mutex rqueue_mutex; +- +- int palette_size; +- u32 pseudo_palette[17]; +- +- struct lcd_panel *panel; /* LCD panel */ +- const struct lcd_ctrl *ctrl; /* LCD controller */ +- const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */ +- struct lcd_ctrl_extif *ext_if; /* LCD ctrl external +- interface */ +- struct device *dev; +- struct fb_var_screeninfo new_var; /* for mode changes */ +- +- struct omapfb_mem_desc mem_desc; +- struct fb_info *fb_info[OMAPFB_PLANE_NUM]; +-}; +- +-struct omapfb_platform_data { +- struct omap_lcd_config lcd; +- struct omapfb_mem_desc mem_desc; +- void *ctrl_platform_data; +-}; +- +-#ifdef CONFIG_ARCH_OMAP1 +-extern struct lcd_ctrl omap1_lcd_ctrl; +-#else +-extern struct lcd_ctrl omap2_disp_ctrl; +-#endif +- +-extern void omapfb_reserve_sdram(void); +-extern void omapfb_register_panel(struct lcd_panel *panel); +-extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); +-extern void omapfb_notify_clients(struct omapfb_device *fbdev, +- unsigned long event); +-extern int omapfb_register_client(struct omapfb_notifier_block *nb, +- omapfb_notifier_callback_t callback, +- void *callback_data); +-extern int omapfb_unregister_client(struct omapfb_notifier_block *nb); +-extern int omapfb_update_window_async(struct fb_info *fbi, +- struct omapfb_update_window *win, +- void (*callback)(void *), +- void *callback_data); +- +-/* in arch/arm/plat-omap/fb.c */ +-extern void omapfb_set_ctrl_platform_data(void *pdata); +- +-#endif /* __KERNEL__ */ +- +-#endif /* __OMAPFB_H */ +diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c +index 9dfcf39..38de019 100644 +--- a/drivers/video/omap/blizzard.c ++++ b/drivers/video/omap/blizzard.c +@@ -27,9 +27,9 @@ + #include <linux/clk.h> + + #include <mach/dma.h> +-#include <mach/omapfb.h> + #include <mach/blizzard.h> + ++#include "omapfb.h" + #include "dispc.h" + + #define MODULE_NAME "blizzard" +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index 148cbcc..f021770 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -26,9 +26,9 @@ + #include <linux/io.h> + + #include <mach/sram.h> +-#include <mach/omapfb.h> + #include <mach/board.h> + ++#include "omapfb.h" + #include "dispc.h" + + #define MODULE_NAME "dispc" +diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c +index 5d4f348..f5c5bfb 100644 +--- a/drivers/video/omap/hwa742.c ++++ b/drivers/video/omap/hwa742.c +@@ -27,8 +27,8 @@ + #include <linux/clk.h> + + #include <mach/dma.h> +-#include <mach/omapfb.h> + #include <mach/hwa742.h> ++#include "omapfb.h" + + #define HWA742_REV_CODE_REG 0x0 + #define HWA742_CONFIG_REG 0x2 +diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c +index 2486237..fb4cc4b 100644 +--- a/drivers/video/omap/lcd_h3.c ++++ b/drivers/video/omap/lcd_h3.c +@@ -24,7 +24,7 @@ + #include <linux/i2c/tps65010.h> + + #include <mach/gpio.h> +-#include <mach/omapfb.h> ++#include "omapfb.h" + + #define MODULE_NAME "omapfb-lcd_h3" + +diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c +index 6ff5643..d7e9b36 100644 +--- a/drivers/video/omap/lcd_h4.c ++++ b/drivers/video/omap/lcd_h4.c +@@ -22,7 +22,7 @@ + #include <linux/module.h> + #include <linux/platform_device.h> + +-#include <mach/omapfb.h> ++#include "omapfb.h" + + static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) + { +diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c +index 6953ed4..bc34607 100644 +--- a/drivers/video/omap/lcd_inn1510.c ++++ b/drivers/video/omap/lcd_inn1510.c +@@ -24,7 +24,7 @@ + #include <linux/io.h> + + #include <mach/fpga.h> +-#include <mach/omapfb.h> ++#include "omapfb.h" + + static int innovator1510_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c +index 4c4f7ee..3e0abda 100644 +--- a/drivers/video/omap/lcd_inn1610.c ++++ b/drivers/video/omap/lcd_inn1610.c +@@ -23,7 +23,7 @@ + #include <linux/platform_device.h> + + #include <mach/gpio.h> +-#include <mach/omapfb.h> ++#include "omapfb.h" + + #define MODULE_NAME "omapfb-lcd_h3" + +diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c +index 379c96d..68b8668 100644 +--- a/drivers/video/omap/lcd_osk.c ++++ b/drivers/video/omap/lcd_osk.c +@@ -25,7 +25,7 @@ + + #include <mach/gpio.h> + #include <mach/mux.h> +-#include <mach/omapfb.h> ++#include "omapfb.h" + + static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) + { +diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c +index 2183173..f993457 100644 +--- a/drivers/video/omap/lcd_palmte.c ++++ b/drivers/video/omap/lcd_palmte.c +@@ -24,7 +24,7 @@ + #include <linux/io.h> + + #include <mach/fpga.h> +-#include <mach/omapfb.h> ++#include "omapfb.h" + + static int palmte_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c +index 57b0f6c..d4cf822 100644 +--- a/drivers/video/omap/lcd_palmtt.c ++++ b/drivers/video/omap/lcd_palmtt.c +@@ -30,7 +30,7 @@ GPIO13 - screen blanking + #include <linux/io.h> + + #include <mach/gpio.h> +-#include <mach/omapfb.h> ++#include "omapfb.h" + + static int palmtt_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c +index d33d78b..1382891 100644 +--- a/drivers/video/omap/lcd_palmz71.c ++++ b/drivers/video/omap/lcd_palmz71.c +@@ -24,7 +24,7 @@ + #include <linux/platform_device.h> + #include <linux/io.h> + +-#include <mach/omapfb.h> ++#include "omapfb.h" + + static int palmz71_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c +index ab39492..520ed97 100644 +--- a/drivers/video/omap/lcdc.c ++++ b/drivers/video/omap/lcdc.c +@@ -30,10 +30,11 @@ + #include <linux/clk.h> + + #include <mach/dma.h> +-#include <mach/omapfb.h> + + #include <asm/mach-types.h> + ++#include "omapfb.h" ++ + #include "lcdc.h" + + #define MODULE_NAME "lcdc" +diff --git a/drivers/video/omap/omapfb.h b/drivers/video/omap/omapfb.h +new file mode 100644 +index 0000000..46e4714 +--- /dev/null ++++ b/drivers/video/omap/omapfb.h +@@ -0,0 +1,227 @@ ++/* ++ * File: drivers/video/omap/omapfb.h ++ * ++ * Framebuffer driver for TI OMAP boards ++ * ++ * Copyright (C) 2004 Nokia Corporation ++ * Author: Imre Deak <imre.deak@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#ifndef __OMAPFB_H ++#define __OMAPFB_H ++ ++#include <linux/fb.h> ++#include <linux/mutex.h> ++#include <linux/omapfb.h> ++ ++#define OMAPFB_EVENT_READY 1 ++#define OMAPFB_EVENT_DISABLED 2 ++ ++#define OMAP_LCDC_INV_VSYNC 0x0001 ++#define OMAP_LCDC_INV_HSYNC 0x0002 ++#define OMAP_LCDC_INV_PIX_CLOCK 0x0004 ++#define OMAP_LCDC_INV_OUTPUT_EN 0x0008 ++#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010 ++#define OMAP_LCDC_HSVS_OPPOSITE 0x0020 ++ ++#define OMAP_LCDC_SIGNAL_MASK 0x003f ++ ++#define OMAP_LCDC_PANEL_TFT 0x0100 ++ ++#define OMAPFB_PLANE_XRES_MIN 8 ++#define OMAPFB_PLANE_YRES_MIN 8 ++ ++struct omapfb_device; ++ ++struct lcd_panel { ++ const char *name; ++ int config; /* TFT/STN, signal inversion */ ++ int bpp; /* Pixel format in fb mem */ ++ int data_lines; /* Lines on LCD HW interface */ ++ ++ int x_res, y_res; ++ int pixel_clock; /* In kHz */ ++ int hsw; /* Horizontal synchronization ++ pulse width */ ++ int hfp; /* Horizontal front porch */ ++ int hbp; /* Horizontal back porch */ ++ int vsw; /* Vertical synchronization ++ pulse width */ ++ int vfp; /* Vertical front porch */ ++ int vbp; /* Vertical back porch */ ++ int acb; /* ac-bias pin frequency */ ++ int pcd; /* pixel clock divider. ++ Obsolete use pixel_clock instead */ ++ ++ int (*init) (struct lcd_panel *panel, ++ struct omapfb_device *fbdev); ++ void (*cleanup) (struct lcd_panel *panel); ++ int (*enable) (struct lcd_panel *panel); ++ void (*disable) (struct lcd_panel *panel); ++ unsigned long (*get_caps) (struct lcd_panel *panel); ++ int (*set_bklight_level)(struct lcd_panel *panel, ++ unsigned int level); ++ unsigned int (*get_bklight_level)(struct lcd_panel *panel); ++ unsigned int (*get_bklight_max) (struct lcd_panel *panel); ++ int (*run_test) (struct lcd_panel *panel, int test_num); ++}; ++ ++struct extif_timings { ++ int cs_on_time; ++ int cs_off_time; ++ int we_on_time; ++ int we_off_time; ++ int re_on_time; ++ int re_off_time; ++ int we_cycle_time; ++ int re_cycle_time; ++ int cs_pulse_width; ++ int access_time; ++ ++ int clk_div; ++ ++ u32 tim[5]; /* set by extif->convert_timings */ ++ ++ int converted; ++}; ++ ++struct lcd_ctrl_extif { ++ int (*init) (struct omapfb_device *fbdev); ++ void (*cleanup) (void); ++ void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div); ++ unsigned long (*get_max_tx_rate)(void); ++ int (*convert_timings) (struct extif_timings *timings); ++ void (*set_timings) (const struct extif_timings *timings); ++ void (*set_bits_per_cycle)(int bpc); ++ void (*write_command) (const void *buf, unsigned int len); ++ void (*read_data) (void *buf, unsigned int len); ++ void (*write_data) (const void *buf, unsigned int len); ++ void (*transfer_area) (int width, int height, ++ void (callback)(void *data), void *data); ++ int (*setup_tearsync) (unsigned pin_cnt, ++ unsigned hs_pulse_time, unsigned vs_pulse_time, ++ int hs_pol_inv, int vs_pol_inv, int div); ++ int (*enable_tearsync) (int enable, unsigned line); ++ ++ unsigned long max_transmit_size; ++}; ++ ++struct omapfb_notifier_block { ++ struct notifier_block nb; ++ void *data; ++ int plane_idx; ++}; ++ ++typedef int (*omapfb_notifier_callback_t)(struct notifier_block *, ++ unsigned long event, ++ void *fbi); ++ ++struct lcd_ctrl { ++ const char *name; ++ void *data; ++ ++ int (*init) (struct omapfb_device *fbdev, ++ int ext_mode, ++ struct omapfb_mem_desc *req_md); ++ void (*cleanup) (void); ++ void (*bind_client) (struct omapfb_notifier_block *nb); ++ void (*get_caps) (int plane, struct omapfb_caps *caps); ++ int (*set_update_mode)(enum omapfb_update_mode mode); ++ enum omapfb_update_mode (*get_update_mode)(void); ++ int (*setup_plane) (int plane, int channel_out, ++ unsigned long offset, ++ int screen_width, ++ int pos_x, int pos_y, int width, ++ int height, int color_mode); ++ int (*set_rotate) (int angle); ++ int (*setup_mem) (int plane, size_t size, ++ int mem_type, unsigned long *paddr); ++ int (*mmap) (struct fb_info *info, ++ struct vm_area_struct *vma); ++ int (*set_scale) (int plane, ++ int orig_width, int orig_height, ++ int out_width, int out_height); ++ int (*enable_plane) (int plane, int enable); ++ int (*update_window) (struct fb_info *fbi, ++ struct omapfb_update_window *win, ++ void (*callback)(void *), ++ void *callback_data); ++ void (*sync) (void); ++ void (*suspend) (void); ++ void (*resume) (void); ++ int (*run_test) (int test_num); ++ int (*setcolreg) (u_int regno, u16 red, u16 green, ++ u16 blue, u16 transp, ++ int update_hw_mem); ++ int (*set_color_key) (struct omapfb_color_key *ck); ++ int (*get_color_key) (struct omapfb_color_key *ck); ++}; ++ ++enum omapfb_state { ++ OMAPFB_DISABLED = 0, ++ OMAPFB_SUSPENDED = 99, ++ OMAPFB_ACTIVE = 100 ++}; ++ ++struct omapfb_plane_struct { ++ int idx; ++ struct omapfb_plane_info info; ++ enum omapfb_color_format color_mode; ++ struct omapfb_device *fbdev; ++}; ++ ++struct omapfb_device { ++ int state; ++ int ext_lcdc; /* Using external ++ LCD controller */ ++ struct mutex rqueue_mutex; ++ ++ int palette_size; ++ u32 pseudo_palette[17]; ++ ++ struct lcd_panel *panel; /* LCD panel */ ++ const struct lcd_ctrl *ctrl; /* LCD controller */ ++ const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */ ++ struct lcd_ctrl_extif *ext_if; /* LCD ctrl external ++ interface */ ++ struct device *dev; ++ struct fb_var_screeninfo new_var; /* for mode changes */ ++ ++ struct omapfb_mem_desc mem_desc; ++ struct fb_info *fb_info[OMAPFB_PLANE_NUM]; ++}; ++ ++#ifdef CONFIG_ARCH_OMAP1 ++extern struct lcd_ctrl omap1_lcd_ctrl; ++#else ++extern struct lcd_ctrl omap2_disp_ctrl; ++#endif ++ ++extern void omapfb_register_panel(struct lcd_panel *panel); ++extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); ++extern void omapfb_notify_clients(struct omapfb_device *fbdev, ++ unsigned long event); ++extern int omapfb_register_client(struct omapfb_notifier_block *nb, ++ omapfb_notifier_callback_t callback, ++ void *callback_data); ++extern int omapfb_unregister_client(struct omapfb_notifier_block *nb); ++extern int omapfb_update_window_async(struct fb_info *fbi, ++ struct omapfb_update_window *win, ++ void (*callback)(void *), ++ void *callback_data); ++ ++#endif /* __OMAPFB_H */ +diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c +index 8862233..a6c4abe 100644 +--- a/drivers/video/omap/omapfb_main.c ++++ b/drivers/video/omap/omapfb_main.c +@@ -29,8 +29,8 @@ + #include <linux/uaccess.h> + + #include <mach/dma.h> +-#include <mach/omapfb.h> + ++#include "omapfb.h" + #include "lcdc.h" + #include "dispc.h" + +diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c +index 9332d6c..2e71446 100644 +--- a/drivers/video/omap/rfbi.c ++++ b/drivers/video/omap/rfbi.c +@@ -27,8 +27,7 @@ + #include <linux/clk.h> + #include <linux/io.h> + +-#include <mach/omapfb.h> +- ++#include "omapfb.h" + #include "dispc.h" + + /* To work around an RFBI transfer rate limitation */ +diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c +index a769462..6853627 100644 +--- a/drivers/video/omap/sossi.c ++++ b/drivers/video/omap/sossi.c +@@ -25,8 +25,8 @@ + #include <linux/io.h> + + #include <mach/dma.h> +-#include <mach/omapfb.h> + ++#include "omapfb.h" + #include "lcdc.h" + + #define MODULE_NAME "omapfb-sossi" +diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h +new file mode 100644 +index 0000000..a3611d3 +--- /dev/null ++++ b/include/linux/omapfb.h +@@ -0,0 +1,197 @@ ++/* ++ * File: include/linux/omapfb.h ++ * ++ * Framebuffer driver for TI OMAP boards ++ * ++ * Copyright (C) 2004 Nokia Corporation ++ * Author: Imre Deak <imre.deak@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#ifndef __LINUX_OMAPFB_H__ ++#define __LINUX_OMAPFB_H__ ++ ++#include <linux/ioctl.h> ++#include <linux/types.h> ++ ++/* IOCTL commands. */ ++ ++#define OMAP_IOW(num, dtype) _IOW('O', num, dtype) ++#define OMAP_IOR(num, dtype) _IOR('O', num, dtype) ++#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype) ++#define OMAP_IO(num) _IO('O', num) ++ ++#define OMAPFB_MIRROR OMAP_IOW(31, int) ++#define OMAPFB_SYNC_GFX OMAP_IO(37) ++#define OMAPFB_VSYNC OMAP_IO(38) ++#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) ++#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps) ++#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) ++#define OMAPFB_LCD_TEST OMAP_IOW(45, int) ++#define OMAPFB_CTRL_TEST OMAP_IOW(46, int) ++#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old) ++#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) ++#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key) ++#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info) ++#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info) ++#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window) ++#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info) ++#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info) ++ ++#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff ++#define OMAPFB_CAPS_LCDC_MASK 0x00fff000 ++#define OMAPFB_CAPS_PANEL_MASK 0xff000000 ++ ++#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000 ++#define OMAPFB_CAPS_TEARSYNC 0x00002000 ++#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000 ++#define OMAPFB_CAPS_PLANE_SCALE 0x00008000 ++#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000 ++#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000 ++#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000 ++#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000 ++#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000 ++ ++/* Values from DSP must map to lower 16-bits */ ++#define OMAPFB_FORMAT_MASK 0x00ff ++#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 ++#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200 ++#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400 ++#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800 ++#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000 ++ ++#define OMAPFB_MEMTYPE_SDRAM 0 ++#define OMAPFB_MEMTYPE_SRAM 1 ++#define OMAPFB_MEMTYPE_MAX 1 ++ ++enum omapfb_color_format { ++ OMAPFB_COLOR_RGB565 = 0, ++ OMAPFB_COLOR_YUV422, ++ OMAPFB_COLOR_YUV420, ++ OMAPFB_COLOR_CLUT_8BPP, ++ OMAPFB_COLOR_CLUT_4BPP, ++ OMAPFB_COLOR_CLUT_2BPP, ++ OMAPFB_COLOR_CLUT_1BPP, ++ OMAPFB_COLOR_RGB444, ++ OMAPFB_COLOR_YUY422, ++}; ++ ++struct omapfb_update_window { ++ __u32 x, y; ++ __u32 width, height; ++ __u32 format; ++ __u32 out_x, out_y; ++ __u32 out_width, out_height; ++ __u32 reserved[8]; ++}; ++ ++struct omapfb_update_window_old { ++ __u32 x, y; ++ __u32 width, height; ++ __u32 format; ++}; ++ ++enum omapfb_plane { ++ OMAPFB_PLANE_GFX = 0, ++ OMAPFB_PLANE_VID1, ++ OMAPFB_PLANE_VID2, ++}; ++ ++enum omapfb_channel_out { ++ OMAPFB_CHANNEL_OUT_LCD = 0, ++ OMAPFB_CHANNEL_OUT_DIGIT, ++}; ++ ++struct omapfb_plane_info { ++ __u32 pos_x; ++ __u32 pos_y; ++ __u8 enabled; ++ __u8 channel_out; ++ __u8 mirror; ++ __u8 reserved1; ++ __u32 out_width; ++ __u32 out_height; ++ __u32 reserved2[12]; ++}; ++ ++struct omapfb_mem_info { ++ __u32 size; ++ __u8 type; ++ __u8 reserved[3]; ++}; ++ ++struct omapfb_caps { ++ __u32 ctrl; ++ __u32 plane_color; ++ __u32 wnd_color; ++}; ++ ++enum omapfb_color_key_type { ++ OMAPFB_COLOR_KEY_DISABLED = 0, ++ OMAPFB_COLOR_KEY_GFX_DST, ++ OMAPFB_COLOR_KEY_VID_SRC, ++}; ++ ++struct omapfb_color_key { ++ __u8 channel_out; ++ __u32 background; ++ __u32 trans_key; ++ __u8 key_type; ++}; ++ ++enum omapfb_update_mode { ++ OMAPFB_UPDATE_DISABLED = 0, ++ OMAPFB_AUTO_UPDATE, ++ OMAPFB_MANUAL_UPDATE ++}; ++ ++#ifdef __KERNEL__ ++ ++#include <mach/board.h> ++ ++#ifdef CONFIG_ARCH_OMAP1 ++#define OMAPFB_PLANE_NUM 1 ++#else ++#define OMAPFB_PLANE_NUM 3 ++#endif ++ ++struct omapfb_mem_region { ++ u32 paddr; ++ void __iomem *vaddr; ++ unsigned long size; ++ u8 type; /* OMAPFB_PLANE_MEM_* */ ++ unsigned alloc:1; /* allocated by the driver */ ++ unsigned map:1; /* kernel mapped by the driver */ ++}; ++ ++struct omapfb_mem_desc { ++ int region_cnt; ++ struct omapfb_mem_region region[OMAPFB_PLANE_NUM]; ++}; ++ ++struct omapfb_platform_data { ++ struct omap_lcd_config lcd; ++ struct omapfb_mem_desc mem_desc; ++ void *ctrl_platform_data; ++}; ++ ++/* in arch/arm/plat-omap/fb.c */ ++extern void omapfb_set_ctrl_platform_data(void *pdata); ++extern void omapfb_reserve_sdram(void); ++ ++#endif ++ ++#endif /* __OMAPFB_H */ +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0002-V4L2-Added-New-V4L2-CIDs-for-omap-devices-V4L2-IOCT.patch b/recipes/linux/linux-omap-2.6.31/dss2/0002-V4L2-Added-New-V4L2-CIDs-for-omap-devices-V4L2-IOCT.patch new file mode 100644 index 0000000000..f05929088f --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0002-V4L2-Added-New-V4L2-CIDs-for-omap-devices-V4L2-IOCT.patch @@ -0,0 +1,152 @@ +From bcb3cd3f6dd8d80a4f7cc524b769d711addfc48d Mon Sep 17 00:00:00 2001 +From: Vaibhav Hiremath <hvaibhav@ti.com> +Date: Wed, 22 Jul 2009 23:49:29 +0530 +Subject: [PATCH 2/5] V4L2: Added New V4L2 CIDs for omap devices V4L2 IOCTL + +Changes - + - Renamed V4L2_CID_ROTATION to V4L2_CID_ROTATE + - Implementationadded for VIDIOC_S/G_COLOR_SPACE_CONV + +Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com> +--- + drivers/media/video/v4l2-ioctl.c | 19 +++++++++++++++++++ + include/linux/videodev2.h | 21 ++++++++++++++++++--- + include/media/v4l2-ioctl.h | 4 ++++ + 3 files changed, 41 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c +index f2afc4e..74d2ed9 100644 +--- a/drivers/media/video/v4l2-ioctl.c ++++ b/drivers/media/video/v4l2-ioctl.c +@@ -278,6 +278,8 @@ static const char *v4l2_ioctls[] = { + [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT", + [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK", + #endif ++ [_IOC_NR(VIDIOC_S_COLOR_SPACE_CONV)] = "VIDIOC_S_COLOR_SPACE_CONV", ++ [_IOC_NR(VIDIOC_G_COLOR_SPACE_CONV)] = "VIDIOC_G_COLOR_SPACE_CONV", + }; + #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) + +@@ -1784,6 +1786,23 @@ static long __video_do_ioctl(struct file *file, + break; + } + ++ /*---------------Color space conversion------------------------------*/ ++ case VIDIOC_S_COLOR_SPACE_CONV: ++ { ++ struct v4l2_color_space_conversion *p = arg; ++ if (!ops->vidioc_s_color_space_conv) ++ break; ++ ret = ops->vidioc_s_color_space_conv(file, fh, p); ++ break; ++ } ++ case VIDIOC_G_COLOR_SPACE_CONV: ++ { ++ struct v4l2_color_space_conversion *p = arg; ++ if (!ops->vidioc_g_color_space_conv) ++ break; ++ ret = ops->vidioc_g_color_space_conv(file, fh, p); ++ break; ++ } + default: + { + if (!ops->vidioc_default) +diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h +index 74f1687..78e8158 100644 +--- a/include/linux/videodev2.h ++++ b/include/linux/videodev2.h +@@ -554,6 +554,7 @@ struct v4l2_framebuffer { + #define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010 + #define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020 + #define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040 ++#define V4L2_FBUF_CAP_SRC_CHROMAKEY 0x0080 + /* Flags for the 'flags' field. */ + #define V4L2_FBUF_FLAG_PRIMARY 0x0001 + #define V4L2_FBUF_FLAG_OVERLAY 0x0002 +@@ -561,6 +562,7 @@ struct v4l2_framebuffer { + #define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008 + #define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010 + #define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020 ++#define V4L2_FBUF_FLAG_SRC_CHROMAKEY 0x0040 + + struct v4l2_clip { + struct v4l2_rect c; +@@ -902,6 +904,8 @@ enum v4l2_colorfx { + + /* last CID + 1 */ + #define V4L2_CID_LASTP1 (V4L2_CID_BASE+33) ++#define V4L2_CID_ROTATE (V4L2_CID_BASE+34) ++#define V4L2_CID_BG_COLOR (V4L2_CID_BASE+35) + + /* MPEG-class control IDs defined by V4L2 */ + #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) +@@ -1213,6 +1217,18 @@ struct v4l2_hw_freq_seek { + }; + + /* ++ * Color conversion ++ * User needs to pass pointer to color conversion matrix ++ * defined by hardware ++ */ ++struct v4l2_color_space_conversion { ++ __s32 coefficients[3][3]; ++ __s32 const_factor; ++ __s32 input_offs[3]; ++ __s32 output_offs[3]; ++}; ++ ++/* + * A U D I O + */ + struct v4l2_audio { +@@ -1265,7 +1281,6 @@ struct v4l2_enc_idx { + struct v4l2_enc_idx_entry entry[V4L2_ENC_IDX_ENTRIES]; + }; + +- + #define V4L2_ENC_CMD_START (0) + #define V4L2_ENC_CMD_STOP (1) + #define V4L2_ENC_CMD_PAUSE (2) +@@ -1286,7 +1301,6 @@ struct v4l2_encoder_cmd { + + #endif + +- + /* + * D A T A S E R V I C E S ( V B I ) + * +@@ -1423,7 +1437,6 @@ struct v4l2_format { + } fmt; + }; + +- + /* Stream type-dependent parameters + */ + struct v4l2_streamparm { +@@ -1551,6 +1564,8 @@ struct v4l2_dbg_chip_ident { + #endif + + #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) ++#define VIDIOC_S_COLOR_SPACE_CONV _IOW('V', 83, struct v4l2_color_space_conversion) ++#define VIDIOC_G_COLOR_SPACE_CONV _IOR('V', 84, struct v4l2_color_space_conversion) + /* Reminder: when adding new ioctls please add support for them to + drivers/media/video/v4l2-compat-ioctl32.c as well! */ + +diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h +index 7a4529d..6f46d09 100644 +--- a/include/media/v4l2-ioctl.h ++++ b/include/media/v4l2-ioctl.h +@@ -242,6 +242,10 @@ struct v4l2_ioctl_ops { + /* For other private ioctls */ + long (*vidioc_default) (struct file *file, void *fh, + int cmd, void *arg); ++ int (*vidioc_s_color_space_conv) (struct file *file, void *fh, ++ struct v4l2_color_space_conversion *a); ++ int (*vidioc_g_color_space_conv) (struct file *file, void *fh, ++ struct v4l2_color_space_conversion *a); + }; + + +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0003-OMAP-OMAPFB-add-omapdss-device.patch b/recipes/linux/linux-omap-2.6.31/dss2/0003-OMAP-OMAPFB-add-omapdss-device.patch new file mode 100644 index 0000000000..fb9928cfce --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0003-OMAP-OMAPFB-add-omapdss-device.patch @@ -0,0 +1,136 @@ +From 40b33143283fda49f0be9113b952c1d77e1c709a Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Thu, 18 Jun 2009 13:02:39 +0300 +Subject: [PATCH 03/18] OMAP: OMAPFB: add omapdss device + +The upcoming new display subsystem driver is divided to two devices, +omapdss and omapfb, of which omapdss handles the actual hardware. + +This patch adds a dummy omapdss platform device for the current omapfb +driver, which is then used to get the clocks. This will make it possible +for the current and the new display drivers to co-exist. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Acked-by: Tony Lindgren <tony@atomide.com> +--- + arch/arm/mach-omap2/clock24xx.c | 8 ++++---- + arch/arm/mach-omap2/clock34xx.c | 14 +++++++------- + drivers/video/omap/dispc.c | 19 ++++++++++++++++--- + 3 files changed, 27 insertions(+), 14 deletions(-) + +diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c +index bc5d3ac..8cb8368 100644 +--- a/arch/arm/mach-omap2/clock24xx.c ++++ b/arch/arm/mach-omap2/clock24xx.c +@@ -116,10 +116,10 @@ static struct omap_clk omap24xx_clks[] = { + CLK(NULL, "mdm_ick", &mdm_ick, CK_243X), + CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X), + /* DSS domain clocks */ +- CLK("omapfb", "ick", &dss_ick, CK_243X | CK_242X), +- CLK("omapfb", "dss1_fck", &dss1_fck, CK_243X | CK_242X), +- CLK("omapfb", "dss2_fck", &dss2_fck, CK_243X | CK_242X), +- CLK("omapfb", "tv_fck", &dss_54m_fck, CK_243X | CK_242X), ++ CLK("omapdss", "ick", &dss_ick, CK_243X | CK_242X), ++ CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X | CK_242X), ++ CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X | CK_242X), ++ CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X | CK_242X), + /* L3 domain clocks */ + CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X | CK_242X), + CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X | CK_242X), +diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c +index cd7819c..aff72ea 100644 +--- a/arch/arm/mach-omap2/clock34xx.c ++++ b/arch/arm/mach-omap2/clock34xx.c +@@ -235,13 +235,13 @@ static struct omap_clk omap34xx_clks[] = { + CLK("omap_rng", "ick", &rng_ick, CK_343X), + CLK(NULL, "sha11_ick", &sha11_ick, CK_343X), + CLK(NULL, "des1_ick", &des1_ick, CK_343X), +- CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), +- CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2), +- CLK("omapfb", "tv_fck", &dss_tv_fck, CK_343X), +- CLK("omapfb", "video_fck", &dss_96m_fck, CK_343X), +- CLK("omapfb", "dss2_fck", &dss2_alwon_fck, CK_343X), +- CLK("omapfb", "ick", &dss_ick_3430es1, CK_3430ES1), +- CLK("omapfb", "ick", &dss_ick_3430es2, CK_3430ES2), ++ CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), ++ CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2), ++ CLK("omapdss", "tv_fck", &dss_tv_fck, CK_343X), ++ CLK("omapdss", "video_fck", &dss_96m_fck, CK_343X), ++ CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_343X), ++ CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1), ++ CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2), + CLK(NULL, "cam_mclk", &cam_mclk, CK_343X), + CLK(NULL, "cam_ick", &cam_ick, CK_343X), + CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X), +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index f021770..d383888 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -24,6 +24,7 @@ + #include <linux/vmalloc.h> + #include <linux/clk.h> + #include <linux/io.h> ++#include <linux/platform_device.h> + + #include <mach/sram.h> + #include <mach/board.h> +@@ -184,6 +185,11 @@ static struct { + struct omapfb_color_key color_key; + } dispc; + ++static struct platform_device omapdss_device = { ++ .name = "omapdss", ++ .id = -1, ++}; ++ + static void enable_lcd_clocks(int enable); + + static void inline dispc_write_reg(int idx, u32 val) +@@ -880,20 +886,20 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) + + static int get_dss_clocks(void) + { +- dispc.dss_ick = clk_get(dispc.fbdev->dev, "ick"); ++ dispc.dss_ick = clk_get(&omapdss_device.dev, "ick"); + if (IS_ERR(dispc.dss_ick)) { + dev_err(dispc.fbdev->dev, "can't get ick\n"); + return PTR_ERR(dispc.dss_ick); + } + +- dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck"); ++ dispc.dss1_fck = clk_get(&omapdss_device.dev, "dss1_fck"); + if (IS_ERR(dispc.dss1_fck)) { + dev_err(dispc.fbdev->dev, "can't get dss1_fck\n"); + clk_put(dispc.dss_ick); + return PTR_ERR(dispc.dss1_fck); + } + +- dispc.dss_54m_fck = clk_get(dispc.fbdev->dev, "tv_fck"); ++ dispc.dss_54m_fck = clk_get(&omapdss_device.dev, "tv_fck"); + if (IS_ERR(dispc.dss_54m_fck)) { + dev_err(dispc.fbdev->dev, "can't get tv_fck\n"); + clk_put(dispc.dss_ick); +@@ -1349,6 +1355,12 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, + int skip_init = 0; + int i; + ++ r = platform_device_register(&omapdss_device); ++ if (r) { ++ dev_err(fbdev->dev, "can't register omapdss device\n"); ++ return r; ++ } ++ + memset(&dispc, 0, sizeof(dispc)); + + dispc.base = ioremap(DISPC_BASE, SZ_1K); +@@ -1490,6 +1502,7 @@ static void omap_dispc_cleanup(void) + enable_interface_clocks(0); + put_dss_clocks(); + iounmap(dispc.base); ++ platform_device_unregister(&omapdss_device); + } + + const struct lcd_ctrl omap2_int_ctrl = { +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0003-V4L2-Updated-v4l2_common-for-new-V4L2-CIDs.patch b/recipes/linux/linux-omap-2.6.31/dss2/0003-V4L2-Updated-v4l2_common-for-new-V4L2-CIDs.patch new file mode 100644 index 0000000000..0fd8135bb1 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0003-V4L2-Updated-v4l2_common-for-new-V4L2-CIDs.patch @@ -0,0 +1,40 @@ +From 691a4534df820b6c90a37de1941197efbe86984a Mon Sep 17 00:00:00 2001 +From: Vaibhav Hiremath <hvaibhav@ti.com> +Date: Fri, 21 Aug 2009 11:19:46 +0530 +Subject: [PATCH 3/5] V4L2: Updated v4l2_common for new V4L2 CIDs. + +Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com> +--- + drivers/media/video/v4l2-common.c | 9 +++++++++ + 1 files changed, 9 insertions(+), 0 deletions(-) + +diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c +index b91d66a..5dae426 100644 +--- a/drivers/media/video/v4l2-common.c ++++ b/drivers/media/video/v4l2-common.c +@@ -421,6 +421,8 @@ const char *v4l2_ctrl_get_name(u32 id) + case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; + case V4L2_CID_COLOR_KILLER: return "Color Killer"; + case V4L2_CID_COLORFX: return "Color Effects"; ++ case V4L2_CID_ROTATE: return "Rotate"; ++ case V4L2_CID_BG_COLOR: return "Background color"; + + /* MPEG controls */ + case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; +@@ -546,6 +548,13 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste + qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + min = max = step = def = 0; + break; ++ case V4L2_CID_BG_COLOR: ++ qctrl->type = V4L2_CTRL_TYPE_INTEGER; ++ step = 1; ++ min = 0; ++ /* Max is calculated as RGB888 that is 2^12*/ ++ max = 0xFFFFFF; ++ break; + default: + qctrl->type = V4L2_CTRL_TYPE_INTEGER; + break; +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP-Add-VRAM-manager.patch b/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP-Add-VRAM-manager.patch new file mode 100644 index 0000000000..13fe0b0234 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP-Add-VRAM-manager.patch @@ -0,0 +1,854 @@ +From cb8ce54283e64bd30636b7bcd2d7bb4e200825d2 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Fri, 7 Aug 2009 12:01:55 +0300 +Subject: [PATCH 04/18] OMAP: Add VRAM manager + +Add a Video RAM manager for OMAP 2 and 3 platforms. VRAM manager is used +to allocate large continuous blocks of SDRAM or SRAM. The features VRAM +manager has that are missing from dma_alloc_* functions are: + +- Support for OMAP2's SRAM +- Allocate without ioremapping +- Allocate at defined physical addresses +- Allows larger VRAM area and larger allocations + +The upcoming DSS2 uses VRAM manager. + +VRAM area size can be defined in kernel config, board file or with +kernel boot parameters. Board file definition overrides kernel config, +and boot parameter overrides kernel config and board file. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + arch/arm/mach-omap2/io.c | 2 + + arch/arm/plat-omap/include/mach/vram.h | 63 +++ + arch/arm/plat-omap/sram.c | 8 + + drivers/video/Kconfig | 1 + + drivers/video/Makefile | 1 + + drivers/video/omap2/Kconfig | 2 + + drivers/video/omap2/Makefile | 1 + + drivers/video/omap2/vram.c | 655 ++++++++++++++++++++++++++++++++ + 8 files changed, 733 insertions(+), 0 deletions(-) + create mode 100644 arch/arm/plat-omap/include/mach/vram.h + create mode 100644 drivers/video/omap2/Kconfig + create mode 100644 drivers/video/omap2/Makefile + create mode 100644 drivers/video/omap2/vram.c + +diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c +index 49199a3..f837063 100644 +--- a/arch/arm/mach-omap2/io.c ++++ b/arch/arm/mach-omap2/io.c +@@ -32,6 +32,7 @@ + #include <mach/sram.h> + #include <mach/sdrc.h> + #include <mach/gpmc.h> ++#include <mach/vram.h> + + #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdev is ready */ + #include "clock.h" +@@ -240,6 +241,7 @@ void __init omap2_map_common_io(void) + omap2_check_revision(); + omap_sram_init(); + omapfb_reserve_sdram(); ++ omap_vram_reserve_sdram(); + } + + /* +diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h +new file mode 100644 +index 0000000..fe72f81 +--- /dev/null ++++ b/arch/arm/plat-omap/include/mach/vram.h +@@ -0,0 +1,63 @@ ++/* ++ * VRAM manager for OMAP ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#ifndef __OMAP_VRAM_H__ ++#define __OMAP_VRAM_H__ ++ ++#include <linux/autoconf.h> ++#include <linux/types.h> ++ ++#define OMAP_VRAM_MEMTYPE_SDRAM 0 ++#define OMAP_VRAM_MEMTYPE_SRAM 1 ++#define OMAP_VRAM_MEMTYPE_MAX 1 ++ ++extern int omap_vram_add_region(unsigned long paddr, size_t size); ++extern int omap_vram_free(unsigned long paddr, size_t size); ++extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr); ++extern int omap_vram_reserve(unsigned long paddr, size_t size); ++extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram, ++ unsigned long *largest_free_block); ++ ++#ifdef CONFIG_OMAP2_VRAM ++extern void omap_vram_set_sdram_vram(u32 size, u32 start); ++extern void omap_vram_set_sram_vram(u32 size, u32 start); ++ ++extern void omap_vram_reserve_sdram(void); ++extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, ++ unsigned long sram_vstart, ++ unsigned long sram_size, ++ unsigned long pstart_avail, ++ unsigned long size_avail); ++#else ++static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { } ++static inline void omap_vram_set_sram_vram(u32 size, u32 start) { } ++ ++static inline void omap_vram_reserve_sdram(void) { } ++static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, ++ unsigned long sram_vstart, ++ unsigned long sram_size, ++ unsigned long pstart_avail, ++ unsigned long size_avail) ++{ ++ return 0; ++} ++#endif ++ ++#endif +diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c +index 5eae787..c9b89cd 100644 +--- a/arch/arm/plat-omap/sram.c ++++ b/arch/arm/plat-omap/sram.c +@@ -28,6 +28,7 @@ + #include <mach/sram.h> + #include <mach/board.h> + #include <mach/cpu.h> ++#include <mach/vram.h> + + #include <mach/control.h> + +@@ -185,6 +186,13 @@ void __init omap_detect_sram(void) + omap_sram_start + SRAM_BOOTLOADER_SZ, + omap_sram_size - SRAM_BOOTLOADER_SZ); + omap_sram_size -= reserved; ++ ++ reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base, ++ omap_sram_size, ++ omap_sram_start + SRAM_BOOTLOADER_SZ, ++ omap_sram_size - SRAM_BOOTLOADER_SZ); ++ omap_sram_size -= reserved; ++ + omap_sram_ceil = omap_sram_base + omap_sram_size; + } + +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index 3b54b39..e09367a 100644 +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -2149,6 +2149,7 @@ config FB_BROADSHEET + a bridge adapter. + + source "drivers/video/omap/Kconfig" ++source "drivers/video/omap2/Kconfig" + + source "drivers/video/backlight/Kconfig" + source "drivers/video/display/Kconfig" +diff --git a/drivers/video/Makefile b/drivers/video/Makefile +index 01a819f..cc7f5c8 100644 +--- a/drivers/video/Makefile ++++ b/drivers/video/Makefile +@@ -123,6 +123,7 @@ obj-$(CONFIG_FB_SM501) += sm501fb.o + obj-$(CONFIG_FB_XILINX) += xilinxfb.o + obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o + obj-$(CONFIG_FB_OMAP) += omap/ ++obj-y += omap2/ + obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o + obj-$(CONFIG_FB_CARMINE) += carminefb.o + obj-$(CONFIG_FB_MB862XX) += mb862xx/ +diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig +new file mode 100644 +index 0000000..7a6c4c9 +--- /dev/null ++++ b/drivers/video/omap2/Kconfig +@@ -0,0 +1,2 @@ ++config OMAP2_VRAM ++ bool +diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile +new file mode 100644 +index 0000000..7fdf7bd +--- /dev/null ++++ b/drivers/video/omap2/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_OMAP2_VRAM) += vram.o +diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c +new file mode 100644 +index 0000000..634ce23 +--- /dev/null ++++ b/drivers/video/omap2/vram.c +@@ -0,0 +1,655 @@ ++/* ++ * VRAM manager for OMAP ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++/*#define DEBUG*/ ++ ++#include <linux/kernel.h> ++#include <linux/mm.h> ++#include <linux/list.h> ++#include <linux/seq_file.h> ++#include <linux/bootmem.h> ++#include <linux/completion.h> ++#include <linux/debugfs.h> ++#include <linux/jiffies.h> ++#include <linux/module.h> ++ ++#include <asm/setup.h> ++ ++#include <mach/sram.h> ++#include <mach/vram.h> ++#include <mach/dma.h> ++ ++#ifdef DEBUG ++#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__) ++#else ++#define DBG(format, ...) ++#endif ++ ++#define OMAP2_SRAM_START 0x40200000 ++/* Maximum size, in reality this is smaller if SRAM is partially locked. */ ++#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */ ++ ++/* postponed regions are used to temporarily store region information at boot ++ * time when we cannot yet allocate the region list */ ++#define MAX_POSTPONED_REGIONS 10 ++ ++static bool vram_initialized; ++static int postponed_cnt; ++static struct { ++ unsigned long paddr; ++ size_t size; ++} postponed_regions[MAX_POSTPONED_REGIONS]; ++ ++struct vram_alloc { ++ struct list_head list; ++ unsigned long paddr; ++ unsigned pages; ++}; ++ ++struct vram_region { ++ struct list_head list; ++ struct list_head alloc_list; ++ unsigned long paddr; ++ unsigned pages; ++}; ++ ++static DEFINE_MUTEX(region_mutex); ++static LIST_HEAD(region_list); ++ ++static inline int region_mem_type(unsigned long paddr) ++{ ++ if (paddr >= OMAP2_SRAM_START && ++ paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE) ++ return OMAP_VRAM_MEMTYPE_SRAM; ++ else ++ return OMAP_VRAM_MEMTYPE_SDRAM; ++} ++ ++static struct vram_region *omap_vram_create_region(unsigned long paddr, ++ unsigned pages) ++{ ++ struct vram_region *rm; ++ ++ rm = kzalloc(sizeof(*rm), GFP_KERNEL); ++ ++ if (rm) { ++ INIT_LIST_HEAD(&rm->alloc_list); ++ rm->paddr = paddr; ++ rm->pages = pages; ++ } ++ ++ return rm; ++} ++ ++#if 0 ++static void omap_vram_free_region(struct vram_region *vr) ++{ ++ list_del(&vr->list); ++ kfree(vr); ++} ++#endif ++ ++static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr, ++ unsigned long paddr, unsigned pages) ++{ ++ struct vram_alloc *va; ++ struct vram_alloc *new; ++ ++ new = kzalloc(sizeof(*va), GFP_KERNEL); ++ ++ if (!new) ++ return NULL; ++ ++ new->paddr = paddr; ++ new->pages = pages; ++ ++ list_for_each_entry(va, &vr->alloc_list, list) { ++ if (va->paddr > new->paddr) ++ break; ++ } ++ ++ list_add_tail(&new->list, &va->list); ++ ++ return new; ++} ++ ++static void omap_vram_free_allocation(struct vram_alloc *va) ++{ ++ list_del(&va->list); ++ kfree(va); ++} ++ ++int omap_vram_add_region(unsigned long paddr, size_t size) ++{ ++ struct vram_region *rm; ++ unsigned pages; ++ ++ if (vram_initialized) { ++ DBG("adding region paddr %08lx size %d\n", ++ paddr, size); ++ ++ size &= PAGE_MASK; ++ pages = size >> PAGE_SHIFT; ++ ++ rm = omap_vram_create_region(paddr, pages); ++ if (rm == NULL) ++ return -ENOMEM; ++ ++ list_add(&rm->list, ®ion_list); ++ } else { ++ if (postponed_cnt == MAX_POSTPONED_REGIONS) ++ return -ENOMEM; ++ ++ postponed_regions[postponed_cnt].paddr = paddr; ++ postponed_regions[postponed_cnt].size = size; ++ ++ ++postponed_cnt; ++ } ++ return 0; ++} ++ ++int omap_vram_free(unsigned long paddr, size_t size) ++{ ++ struct vram_region *rm; ++ struct vram_alloc *alloc; ++ unsigned start, end; ++ ++ DBG("free mem paddr %08lx size %d\n", paddr, size); ++ ++ size = PAGE_ALIGN(size); ++ ++ mutex_lock(®ion_mutex); ++ ++ list_for_each_entry(rm, ®ion_list, list) { ++ list_for_each_entry(alloc, &rm->alloc_list, list) { ++ start = alloc->paddr; ++ end = alloc->paddr + (alloc->pages >> PAGE_SHIFT); ++ ++ if (start >= paddr && end < paddr + size) ++ goto found; ++ } ++ } ++ ++ mutex_unlock(®ion_mutex); ++ return -EINVAL; ++ ++found: ++ omap_vram_free_allocation(alloc); ++ ++ mutex_unlock(®ion_mutex); ++ return 0; ++} ++EXPORT_SYMBOL(omap_vram_free); ++ ++static int _omap_vram_reserve(unsigned long paddr, unsigned pages) ++{ ++ struct vram_region *rm; ++ struct vram_alloc *alloc; ++ size_t size; ++ ++ size = pages << PAGE_SHIFT; ++ ++ list_for_each_entry(rm, ®ion_list, list) { ++ unsigned long start, end; ++ ++ DBG("checking region %lx %d\n", rm->paddr, rm->pages); ++ ++ if (region_mem_type(rm->paddr) != region_mem_type(paddr)) ++ continue; ++ ++ start = rm->paddr; ++ end = start + (rm->pages << PAGE_SHIFT) - 1; ++ if (start > paddr || end < paddr + size - 1) ++ continue; ++ ++ DBG("block ok, checking allocs\n"); ++ ++ list_for_each_entry(alloc, &rm->alloc_list, list) { ++ end = alloc->paddr - 1; ++ ++ if (start <= paddr && end >= paddr + size - 1) ++ goto found; ++ ++ start = alloc->paddr + (alloc->pages << PAGE_SHIFT); ++ } ++ ++ end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1; ++ ++ if (!(start <= paddr && end >= paddr + size - 1)) ++ continue; ++found: ++ DBG("found area start %lx, end %lx\n", start, end); ++ ++ if (omap_vram_create_allocation(rm, paddr, pages) == NULL) ++ return -ENOMEM; ++ ++ return 0; ++ } ++ ++ return -ENOMEM; ++} ++ ++int omap_vram_reserve(unsigned long paddr, size_t size) ++{ ++ unsigned pages; ++ int r; ++ ++ DBG("reserve mem paddr %08lx size %d\n", paddr, size); ++ ++ size = PAGE_ALIGN(size); ++ pages = size >> PAGE_SHIFT; ++ ++ mutex_lock(®ion_mutex); ++ ++ r = _omap_vram_reserve(paddr, pages); ++ ++ mutex_unlock(®ion_mutex); ++ ++ return r; ++} ++EXPORT_SYMBOL(omap_vram_reserve); ++ ++static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data) ++{ ++ struct completion *compl = data; ++ complete(compl); ++} ++ ++static int _omap_vram_clear(u32 paddr, unsigned pages) ++{ ++ struct completion compl; ++ unsigned elem_count; ++ unsigned frame_count; ++ int r; ++ int lch; ++ ++ init_completion(&compl); ++ ++ r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA", ++ _omap_vram_dma_cb, ++ &compl, &lch); ++ if (r) { ++ pr_err("VRAM: request_dma failed for memory clear\n"); ++ return -EBUSY; ++ } ++ ++ elem_count = pages * PAGE_SIZE / 4; ++ frame_count = 1; ++ ++ omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32, ++ elem_count, frame_count, ++ OMAP_DMA_SYNC_ELEMENT, ++ 0, 0); ++ ++ omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC, ++ paddr, 0, 0); ++ ++ omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000); ++ ++ omap_start_dma(lch); ++ ++ if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) { ++ omap_stop_dma(lch); ++ pr_err("VRAM: dma timeout while clearing memory\n"); ++ r = -EIO; ++ goto err; ++ } ++ ++ r = 0; ++err: ++ omap_free_dma(lch); ++ ++ return r; ++} ++ ++static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr) ++{ ++ struct vram_region *rm; ++ struct vram_alloc *alloc; ++ ++ list_for_each_entry(rm, ®ion_list, list) { ++ unsigned long start, end; ++ ++ DBG("checking region %lx %d\n", rm->paddr, rm->pages); ++ ++ if (region_mem_type(rm->paddr) != mtype) ++ continue; ++ ++ start = rm->paddr; ++ ++ list_for_each_entry(alloc, &rm->alloc_list, list) { ++ end = alloc->paddr; ++ ++ if (end - start >= pages << PAGE_SHIFT) ++ goto found; ++ ++ start = alloc->paddr + (alloc->pages << PAGE_SHIFT); ++ } ++ ++ end = rm->paddr + (rm->pages << PAGE_SHIFT); ++found: ++ if (end - start < pages << PAGE_SHIFT) ++ continue; ++ ++ DBG("found %lx, end %lx\n", start, end); ++ ++ alloc = omap_vram_create_allocation(rm, start, pages); ++ if (alloc == NULL) ++ return -ENOMEM; ++ ++ *paddr = start; ++ ++ _omap_vram_clear(start, pages); ++ ++ return 0; ++ } ++ ++ return -ENOMEM; ++} ++ ++int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr) ++{ ++ unsigned pages; ++ int r; ++ ++ BUG_ON(mtype > OMAP_VRAM_MEMTYPE_MAX || !size); ++ ++ DBG("alloc mem type %d size %d\n", mtype, size); ++ ++ size = PAGE_ALIGN(size); ++ pages = size >> PAGE_SHIFT; ++ ++ mutex_lock(®ion_mutex); ++ ++ r = _omap_vram_alloc(mtype, pages, paddr); ++ ++ mutex_unlock(®ion_mutex); ++ ++ return r; ++} ++EXPORT_SYMBOL(omap_vram_alloc); ++ ++void omap_vram_get_info(unsigned long *vram, ++ unsigned long *free_vram, ++ unsigned long *largest_free_block) ++{ ++ struct vram_region *vr; ++ struct vram_alloc *va; ++ ++ *vram = 0; ++ *free_vram = 0; ++ *largest_free_block = 0; ++ ++ mutex_lock(®ion_mutex); ++ ++ list_for_each_entry(vr, ®ion_list, list) { ++ unsigned free; ++ unsigned long pa; ++ ++ pa = vr->paddr; ++ *vram += vr->pages << PAGE_SHIFT; ++ ++ list_for_each_entry(va, &vr->alloc_list, list) { ++ free = va->paddr - pa; ++ *free_vram += free; ++ if (free > *largest_free_block) ++ *largest_free_block = free; ++ pa = va->paddr + (va->pages << PAGE_SHIFT); ++ } ++ ++ free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa; ++ *free_vram += free; ++ if (free > *largest_free_block) ++ *largest_free_block = free; ++ } ++ ++ mutex_unlock(®ion_mutex); ++} ++EXPORT_SYMBOL(omap_vram_get_info); ++ ++#if defined(CONFIG_DEBUG_FS) ++static int vram_debug_show(struct seq_file *s, void *unused) ++{ ++ struct vram_region *vr; ++ struct vram_alloc *va; ++ unsigned size; ++ ++ mutex_lock(®ion_mutex); ++ ++ list_for_each_entry(vr, ®ion_list, list) { ++ size = vr->pages << PAGE_SHIFT; ++ seq_printf(s, "%08lx-%08lx (%d bytes)\n", ++ vr->paddr, vr->paddr + size - 1, ++ size); ++ ++ list_for_each_entry(va, &vr->alloc_list, list) { ++ size = va->pages << PAGE_SHIFT; ++ seq_printf(s, " %08lx-%08lx (%d bytes)\n", ++ va->paddr, va->paddr + size - 1, ++ size); ++ } ++ } ++ ++ mutex_unlock(®ion_mutex); ++ ++ return 0; ++} ++ ++static int vram_debug_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, vram_debug_show, inode->i_private); ++} ++ ++static const struct file_operations vram_debug_fops = { ++ .open = vram_debug_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int __init omap_vram_create_debugfs(void) ++{ ++ struct dentry *d; ++ ++ d = debugfs_create_file("vram", S_IRUGO, NULL, ++ NULL, &vram_debug_fops); ++ if (IS_ERR(d)) ++ return PTR_ERR(d); ++ ++ return 0; ++} ++#endif ++ ++static __init int omap_vram_init(void) ++{ ++ int i; ++ ++ vram_initialized = 1; ++ ++ for (i = 0; i < postponed_cnt; i++) ++ omap_vram_add_region(postponed_regions[i].paddr, ++ postponed_regions[i].size); ++ ++#ifdef CONFIG_DEBUG_FS ++ if (omap_vram_create_debugfs()) ++ pr_err("VRAM: Failed to create debugfs file\n"); ++#endif ++ ++ return 0; ++} ++ ++arch_initcall(omap_vram_init); ++ ++/* boottime vram alloc stuff */ ++ ++/* set from board file */ ++static u32 omap_vram_sram_start __initdata; ++static u32 omap_vram_sram_size __initdata; ++ ++/* set from board file */ ++static u32 omap_vram_sdram_start __initdata; ++static u32 omap_vram_sdram_size __initdata; ++ ++/* set from kernel cmdline */ ++static u32 omap_vram_def_sdram_size __initdata; ++static u32 omap_vram_def_sdram_start __initdata; ++ ++static void __init omap_vram_early_vram(char **p) ++{ ++ omap_vram_def_sdram_size = memparse(*p, p); ++ if (**p == ',') ++ omap_vram_def_sdram_start = simple_strtoul((*p) + 1, p, 16); ++} ++__early_param("vram=", omap_vram_early_vram); ++ ++/* ++ * Called from map_io. We need to call to this early enough so that we ++ * can reserve the fixed SDRAM regions before VM could get hold of them. ++ */ ++void __init omap_vram_reserve_sdram(void) ++{ ++ struct bootmem_data *bdata; ++ unsigned long sdram_start, sdram_size; ++ u32 paddr; ++ u32 size = 0; ++ ++ /* cmdline arg overrides the board file definition */ ++ if (omap_vram_def_sdram_size) { ++ size = omap_vram_def_sdram_size; ++ paddr = omap_vram_def_sdram_start; ++ } ++ ++ if (!size) { ++ size = omap_vram_sdram_size; ++ paddr = omap_vram_sdram_start; ++ } ++ ++#ifdef CONFIG_OMAP2_VRAM_SIZE ++ if (!size) { ++ size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024; ++ paddr = 0; ++ } ++#endif ++ ++ if (!size) ++ return; ++ ++ size = PAGE_ALIGN(size); ++ ++ bdata = NODE_DATA(0)->bdata; ++ sdram_start = bdata->node_min_pfn << PAGE_SHIFT; ++ sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; ++ ++ if (paddr) { ++ if ((paddr & ~PAGE_MASK) || paddr < sdram_start || ++ paddr + size > sdram_start + sdram_size) { ++ pr_err("Illegal SDRAM region for VRAM\n"); ++ return; ++ } ++ ++ if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) { ++ pr_err("FB: failed to reserve VRAM\n"); ++ return; ++ } ++ } else { ++ if (size > sdram_size) { ++ pr_err("Illegal SDRAM size for VRAM\n"); ++ return; ++ } ++ ++ paddr = virt_to_phys(alloc_bootmem_pages(size)); ++ BUG_ON(paddr & ~PAGE_MASK); ++ } ++ ++ omap_vram_add_region(paddr, size); ++ ++ pr_info("Reserving %u bytes SDRAM for VRAM\n", size); ++} ++ ++/* ++ * Called at sram init time, before anything is pushed to the SRAM stack. ++ * Because of the stack scheme, we will allocate everything from the ++ * start of the lowest address region to the end of SRAM. This will also ++ * include padding for page alignment and possible holes between regions. ++ * ++ * As opposed to the SDRAM case, we'll also do any dynamic allocations at ++ * this point, since the driver built as a module would have problem with ++ * freeing / reallocating the regions. ++ */ ++unsigned long __init omap_vram_reserve_sram(unsigned long sram_pstart, ++ unsigned long sram_vstart, ++ unsigned long sram_size, ++ unsigned long pstart_avail, ++ unsigned long size_avail) ++{ ++ unsigned long pend_avail; ++ unsigned long reserved; ++ u32 paddr; ++ u32 size; ++ ++ paddr = omap_vram_sram_start; ++ size = omap_vram_sram_size; ++ ++ if (!size) ++ return 0; ++ ++ reserved = 0; ++ pend_avail = pstart_avail + size_avail; ++ ++ if (!paddr) { ++ /* Dynamic allocation */ ++ if ((size_avail & PAGE_MASK) < size) { ++ pr_err("Not enough SRAM for VRAM\n"); ++ return 0; ++ } ++ size_avail = (size_avail - size) & PAGE_MASK; ++ paddr = pstart_avail + size_avail; ++ } ++ ++ if (paddr < sram_pstart || ++ paddr + size > sram_pstart + sram_size) { ++ pr_err("Illegal SRAM region for VRAM\n"); ++ return 0; ++ } ++ ++ /* Reserve everything above the start of the region. */ ++ if (pend_avail - paddr > reserved) ++ reserved = pend_avail - paddr; ++ size_avail = pend_avail - reserved - pstart_avail; ++ ++ omap_vram_add_region(paddr, size); ++ ++ if (reserved) ++ pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved); ++ ++ return reserved; ++} ++ ++void __init omap_vram_set_sdram_vram(u32 size, u32 start) ++{ ++ omap_vram_sdram_start = start; ++ omap_vram_sdram_size = size; ++} ++ ++void __init omap_vram_set_sram_vram(u32 size, u32 start) ++{ ++ omap_vram_sram_start = start; ++ omap_vram_sram_size = size; ++} +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP2-3-V4L2-Add-support-for-OMAP2-3-V4L2-driver-on.patch b/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP2-3-V4L2-Add-support-for-OMAP2-3-V4L2-driver-on.patch new file mode 100644 index 0000000000..5db9c65d41 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0004-OMAP2-3-V4L2-Add-support-for-OMAP2-3-V4L2-driver-on.patch @@ -0,0 +1,3248 @@ +From 2ae2dbacb82c5f0cb0fbcde7b49510d5cf2d45b5 Mon Sep 17 00:00:00 2001 +From: Vaibhav Hiremath <hvaibhav@ti.com> +Date: Wed, 12 Aug 2009 19:38:30 +0530 +Subject: [PATCH 4/5] OMAP2/3 V4L2: Add support for OMAP2/3 V4L2 driver on top of DSS2 + +Features Supported - + 1. Provides V4L2 user interface for the video pipelines of DSS + 2. Basic streaming working on LCD, DVI and TV. + 3. Works on latest DSS2 library from Tomi + 4. Support for various pixel formats like YUV, UYVY, RGB32, RGB24, + RGB565 + 5. Supports Alpha blending. + 6. Supports Color keying both source and destination. + 7. Supports rotation. + 8. Supports cropping. + 9. Supports Background color setting. + +TODO: + 1. Complete Testing is pending, only basic test passed. + +Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com> +--- + arch/arm/plat-omap/devices.c | 29 + + drivers/media/video/Kconfig | 12 + + drivers/media/video/Makefile | 2 + + drivers/media/video/omap/Kconfig | 22 + + drivers/media/video/omap/Makefile | 2 + + drivers/media/video/omap/omap_vout.c | 2623 +++++++++++++++++++++++++++++++ + drivers/media/video/omap/omap_voutdef.h | 148 ++ + drivers/media/video/omap/omap_voutlib.c | 258 +++ + drivers/media/video/omap/omap_voutlib.h | 34 + + 9 files changed, 3130 insertions(+), 0 deletions(-) + create mode 100644 drivers/media/video/omap/Kconfig + create mode 100644 drivers/media/video/omap/Makefile + create mode 100644 drivers/media/video/omap/omap_vout.c + create mode 100644 drivers/media/video/omap/omap_voutdef.h + create mode 100644 drivers/media/video/omap/omap_voutlib.c + create mode 100644 drivers/media/video/omap/omap_voutlib.h + +diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c +index a64b692..8b6a9a0 100644 +--- a/arch/arm/plat-omap/devices.c ++++ b/arch/arm/plat-omap/devices.c +@@ -357,6 +357,34 @@ static void omap_init_rng(void) + static inline void omap_init_rng(void) {} + #endif + ++/*---------------------------------------------------------------------------*/ ++ ++#if defined(CONFIG_VIDEO_OMAP_VIDEOOUT) || \ ++ defined(CONFIG_VIDEO_OMAP_VIDEOOUT_MODULE) ++#ifdef CONFIG_FB_OMAP2 ++static struct resource omap3evm_vout_resource[3 - CONFIG_FB_OMAP2_NUM_FBS] = { ++}; ++#else ++static struct resource omap3evm_vout_resource[2] = { ++}; ++#endif ++ ++static struct platform_device omap3evm_vout_device = { ++ .name = "omap_vout", ++ .num_resources = ARRAY_SIZE(omap3evm_vout_resource), ++ .resource = &omap3evm_vout_resource[0], ++ .id = -1, ++}; ++static void omap_init_vout(void) ++{ ++ (void) platform_device_register(&omap3evm_vout_device); ++} ++#else ++static inline void omap_init_vout(void) {} ++#endif ++ ++/*---------------------------------------------------------------------------*/ ++ + /* + * This gets called after board-specific INIT_MACHINE, and initializes most + * on-chip peripherals accessible on this board (except for few like USB): +@@ -387,6 +415,7 @@ static int __init omap_init_devices(void) + omap_init_uwire(); + omap_init_wdt(); + omap_init_rng(); ++ omap_init_vout(); + return 0; + } + arch_initcall(omap_init_devices); +diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig +index dcf9fa9..afb4478 100644 +--- a/drivers/media/video/Kconfig ++++ b/drivers/media/video/Kconfig +@@ -718,6 +718,18 @@ config VIDEO_CAFE_CCIC + CMOS camera controller. This is the controller found on first- + generation OLPC systems. + ++config VIDEO_OMAP3 ++ bool "OMAP2/OMAP3 Camera and V4L2-DSS drivers" ++ select VIDEOBUF_GEN ++ select VIDEOBUF_DMA_SG ++ select OMAP2_DSS ++ depends on VIDEO_DEV && (ARCH_OMAP24XX || ARCH_OMAP34XX) ++ default y ++ ---help--- ++ V4L2 DSS and Camera driver support for OMAP2/3 based boards. ++ ++source "drivers/media/video/omap/Kconfig" ++ + config SOC_CAMERA + tristate "SoC camera support" + depends on VIDEO_V4L2 && HAS_DMA && I2C +diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile +index 9f2e321..36040b9 100644 +--- a/drivers/media/video/Makefile ++++ b/drivers/media/video/Makefile +@@ -117,6 +117,8 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o + + obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o + ++obj-$(CONFIG_VIDEO_OMAP3) += omap/ ++ + obj-$(CONFIG_USB_DABUSB) += dabusb.o + obj-$(CONFIG_USB_OV511) += ov511.o + obj-$(CONFIG_USB_SE401) += se401.o +diff --git a/drivers/media/video/omap/Kconfig b/drivers/media/video/omap/Kconfig +new file mode 100644 +index 0000000..5b86db3 +--- /dev/null ++++ b/drivers/media/video/omap/Kconfig +@@ -0,0 +1,22 @@ ++config VIDEO_OMAP_VIDEOOUT ++ tristate "OMAP Video out driver" ++ select VIDEOBUF_DMA_SG ++ select VIDEOBUF_GEN ++ depends on VIDEO_OMAP3 ++ default VIDEO_OMAP3 ++ ++choice ++ prompt "TV Mode" ++ default NTSC_M ++ ++config NTSC_M ++ bool "Use NTSC_M mode" ++ help ++ Select this option if you want NTSC_M mode on TV ++ ++config PAL_BDGHI ++ bool "Use PAL_BDGHI mode" ++ help ++ Select this option if you want PAL_BDGHI mode on TV ++ ++endchoice +diff --git a/drivers/media/video/omap/Makefile b/drivers/media/video/omap/Makefile +new file mode 100644 +index 0000000..18854c7 +--- /dev/null ++++ b/drivers/media/video/omap/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_VIDEO_OMAP_VIDEOOUT) += omap_vout.o omap_voutlib.o ++ +diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c +new file mode 100644 +index 0000000..7e15db2 +--- /dev/null ++++ b/drivers/media/video/omap/omap_vout.c +@@ -0,0 +1,2623 @@ ++/* ++ * drivers/media/video/omap/omap_vout.c ++ * ++ * Copyright (C) 2005-2009 Texas Instruments. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ * ++ * Leveraged code from the OMAP2 camera driver ++ * Video-for-Linux (Version 2) camera capture driver for ++ * the OMAP24xx camera controller. ++ * ++ * Author: Andy Lowe (source@mvista.com) ++ * ++ * Copyright (C) 2004 MontaVista Software, Inc. ++ * Copyright (C) 2009 Texas Instruments. ++ * ++ * History: ++ * 20-APR-2006 Khasim Modified VRFB based Rotation, ++ * The image data is always read from 0 degree ++ * view and written ++ * to the virtual space of desired rotation angle ++ * 4-DEC-2006 Jian Changed to support better memory management ++ * ++ * 17-Nov-2008 Hardik Changed to used the new DSS paches by Tomi ++ * Changed driver to use video_ioctl2 ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/errno.h> ++#include <linux/fs.h> ++#include <linux/kernel.h> ++#include <linux/vmalloc.h> ++#include <linux/interrupt.h> ++#include <linux/kdev_t.h> ++#include <linux/types.h> ++#include <linux/wait.h> ++#include <linux/videodev2.h> ++#include <linux/platform_device.h> ++#include <linux/dma-mapping.h> ++#include <linux/irq.h> ++ ++#include <media/videobuf-dma-sg.h> ++#include <media/v4l2-dev.h> ++#include <media/v4l2-ioctl.h> ++#include <media/v4l2-common.h> ++#include <media/v4l2-device.h> ++ ++#include <asm/processor.h> ++#include <mach/dma.h> ++#include <mach/vram.h> ++#include <mach/vrfb.h> ++#include <mach/display.h> ++ ++#include "omap_voutlib.h" ++#include "omap_voutdef.h" ++ ++MODULE_AUTHOR("Texas Instruments."); ++MODULE_DESCRIPTION("OMAP Video for Linux Video out driver"); ++MODULE_LICENSE("GPL"); ++ ++#define OMAP_VIDEO1 0 ++#define OMAP_VIDEO2 1 ++ ++/* configuration macros */ ++#define VOUT_NAME "omap_vout" ++ ++#define QQVGA_WIDTH 160 ++#define QQVGA_HEIGHT 120 ++ ++#define NUM_OF_VIDEO_CHANNELS 2 ++ ++#define VID_MAX_WIDTH 1280 /* Largest width */ ++#define VID_MAX_HEIGHT 720/* Largest height */ ++ ++/* Mimimum requirement is 2x2 for DSS */ ++#define VID_MIN_WIDTH 2 ++#define VID_MIN_HEIGHT 2 ++ ++/* 2048 x 2048 is max res supported by OMAP display controller */ ++#define DMA_CHAN_ALLOTED 1 ++#define DMA_CHAN_NOT_ALLOTED 0 ++#define MAX_PIXELS_PER_LINE 2048 ++#define VRFB_TX_TIMEOUT 1000 ++ ++/* IRQ Bits mask of DSS */ ++#define OMAP_VOUT_MAX_BUF_SIZE (VID_MAX_WIDTH*VID_MAX_HEIGHT*4) ++ ++static struct videobuf_queue_ops video_vbq_ops; ++ ++static u32 video1_numbuffers = 3; ++static u32 video2_numbuffers = 3; ++static u32 video1_bufsize = OMAP_VOUT_MAX_BUF_SIZE; ++static u32 video2_bufsize = OMAP_VOUT_MAX_BUF_SIZE; ++static u32 vid1_static_vrfb_alloc; ++static u32 vid2_static_vrfb_alloc; ++static int debug; ++ ++/* Module parameters */ ++module_param(video1_numbuffers, uint, S_IRUGO); ++MODULE_PARM_DESC(video1_numbuffers, ++ "Number of buffers to be allocated at init time for Video1 device."); ++ ++module_param(video2_numbuffers, uint, S_IRUGO); ++MODULE_PARM_DESC(video2_numbuffers, ++ "Number of buffers to be allocated at init time for Video2 device."); ++ ++module_param(video1_bufsize, uint, S_IRUGO); ++MODULE_PARM_DESC(video1_bufsize, ++ "Size of the buffer to be allocated for video1 device"); ++ ++module_param(video2_bufsize, uint, S_IRUGO); ++MODULE_PARM_DESC(video2_bufsize, ++ "Size of the buffer to be allocated for video2 device"); ++ ++module_param(vid1_static_vrfb_alloc, bool, S_IRUGO); ++MODULE_PARM_DESC(vid1_static_vrfb_alloc, ++ "Static allocation of the VRFB buffer for video1 device"); ++ ++module_param(vid2_static_vrfb_alloc, bool, S_IRUGO); ++MODULE_PARM_DESC(vid2_static_vrfb_alloc, ++ "Static allocation of the VRFB buffer for video2 device"); ++ ++module_param(debug, bool, S_IRUGO); ++MODULE_PARM_DESC(debug, "Debug level (0-1)"); ++ ++/* Local Helper functions */ ++static void omap_vout_isr(void *arg, unsigned int irqstatus); ++static void omap_vout_cleanup_device(struct omap_vout_device *vout); ++/* ++ * Maximum amount of memory to use for rendering buffers. ++ * Default is enough to four (RGB24) DVI 720P buffers. ++ */ ++#define MAX_ALLOWED_VIDBUFFERS 4 ++ ++/* list of image formats supported by OMAP2 video pipelines */ ++const static struct v4l2_fmtdesc omap_formats[] = { ++ { ++ /* Note: V4L2 defines RGB565 as: ++ * ++ * Byte 0 Byte 1 ++ * g2 g1 g0 r4 r3 r2 r1 r0 b4 b3 b2 b1 b0 g5 g4 g3 ++ * ++ * We interpret RGB565 as: ++ * ++ * Byte 0 Byte 1 ++ * g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3 ++ */ ++ .description = "RGB565, le", ++ .pixelformat = V4L2_PIX_FMT_RGB565, ++ }, ++ { ++ /* Note: V4L2 defines RGB32 as: RGB-8-8-8-8 we use ++ * this for RGB24 unpack mode, the last 8 bits are ignored ++ * */ ++ .description = "RGB32, le", ++ .pixelformat = V4L2_PIX_FMT_RGB32, ++ }, ++ { ++ /* Note: V4L2 defines RGB24 as: RGB-8-8-8 we use ++ * this for RGB24 packed mode ++ * ++ */ ++ .description = "RGB24, le", ++ .pixelformat = V4L2_PIX_FMT_RGB24, ++ }, ++ { ++ .description = "YUYV (YUV 4:2:2), packed", ++ .pixelformat = V4L2_PIX_FMT_YUYV, ++ }, ++ { ++ .description = "UYVY, packed", ++ .pixelformat = V4L2_PIX_FMT_UYVY, ++ }, ++}; ++ ++#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats)) ++ ++/* Allocate buffers */ ++static unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr) ++{ ++ unsigned long virt_addr, addr; ++ u32 order, size; ++ ++ size = PAGE_ALIGN(buf_size); ++ order = get_order(size); ++ virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, order); ++ addr = virt_addr; ++ ++ if (virt_addr) { ++ while (size > 0) { ++ SetPageReserved(virt_to_page(addr)); ++ addr += PAGE_SIZE; ++ size -= PAGE_SIZE; ++ } ++ } ++ *phys_addr = (u32) virt_to_phys((void *) virt_addr); ++ return virt_addr; ++} ++ ++/* Free buffers */ ++static void omap_vout_free_buffer(unsigned long virtaddr, u32 phys_addr, ++ u32 buf_size) ++{ ++ unsigned long addr = virtaddr; ++ u32 order, size; ++ ++ size = PAGE_ALIGN(buf_size); ++ order = get_order(size); ++ ++ while (size > 0) { ++ ClearPageReserved(virt_to_page(addr)); ++ addr += PAGE_SIZE; ++ size -= PAGE_SIZE; ++ } ++ free_pages((unsigned long) virtaddr, order); ++} ++ ++/* Function for allocating video buffers */ ++static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout, ++ unsigned int *count, int startindex) ++{ ++ int i, j; ++ ++ for (i = 0; i < *count; i++) { ++ if (!vout->smsshado_virt_addr[i]) { ++ vout->smsshado_virt_addr[i] = ++ omap_vout_alloc_buffer(vout->smsshado_size, ++ &vout->smsshado_phy_addr[i]); ++ } ++ if (!vout->smsshado_virt_addr[i] && startindex != -1) { ++ if (V4L2_MEMORY_MMAP == vout->memory ++ && i >= startindex) ++ break; ++ } ++ if (!vout->smsshado_virt_addr[i]) { ++ for (j = 0; j < i; j++) { ++ omap_vout_free_buffer( ++ vout->smsshado_virt_addr[j], ++ vout->smsshado_phy_addr[j], ++ vout->smsshado_size); ++ vout->smsshado_virt_addr[j] = 0; ++ vout->smsshado_phy_addr[j] = 0; ++ } ++ *count = 0; ++ return -ENOMEM; ++ } ++ memset((void *) vout->smsshado_virt_addr[i], 0, ++ vout->smsshado_size); ++ } ++ return 0; ++} ++ ++/* Try format */ ++static int omap_vout_try_format(struct v4l2_pix_format *pix) ++{ ++ int ifmt, bpp = 0; ++ ++ pix->height = clamp(pix->height, (u32)VID_MIN_HEIGHT, ++ (u32)VID_MAX_HEIGHT); ++ pix->width = clamp(pix->width, (u32)VID_MIN_WIDTH, (u32)VID_MAX_WIDTH); ++ ++ for (ifmt = 0; ifmt < NUM_OUTPUT_FORMATS; ifmt++) { ++ if (pix->pixelformat == omap_formats[ifmt].pixelformat) ++ break; ++ } ++ ++ if (ifmt == NUM_OUTPUT_FORMATS) ++ ifmt = 0; ++ ++ pix->pixelformat = omap_formats[ifmt].pixelformat; ++ pix->field = V4L2_FIELD_ANY; ++ pix->priv = 0; ++ ++ switch (pix->pixelformat) { ++ case V4L2_PIX_FMT_YUYV: ++ case V4L2_PIX_FMT_UYVY: ++ default: ++ pix->colorspace = V4L2_COLORSPACE_JPEG; ++ bpp = YUYV_BPP; ++ break; ++ case V4L2_PIX_FMT_RGB565: ++ case V4L2_PIX_FMT_RGB565X: ++ pix->colorspace = V4L2_COLORSPACE_SRGB; ++ bpp = RGB565_BPP; ++ break; ++ case V4L2_PIX_FMT_RGB24: ++ pix->colorspace = V4L2_COLORSPACE_SRGB; ++ bpp = RGB24_BPP; ++ break; ++ case V4L2_PIX_FMT_RGB32: ++ case V4L2_PIX_FMT_BGR32: ++ pix->colorspace = V4L2_COLORSPACE_SRGB; ++ bpp = RGB32_BPP; ++ break; ++ } ++ pix->bytesperline = pix->width * bpp; ++ pix->sizeimage = pix->bytesperline * pix->height; ++ return bpp; ++} ++ ++/* ++ * omap_vout_uservirt_to_phys: This inline function is used to convert user ++ * space virtual address to physical address. ++ */ ++static inline u32 omap_vout_uservirt_to_phys(u32 virtp) ++{ ++ unsigned long physp = 0; ++ struct mm_struct *mm = current->mm; ++ struct vm_area_struct *vma; ++ ++ vma = find_vma(mm, virtp); ++ /* For kernel direct-mapped memory, take the easy way */ ++ if (virtp >= PAGE_OFFSET) { ++ physp = virt_to_phys((void *) virtp); ++ } else if (vma && (vma->vm_flags & VM_IO) ++ && vma->vm_pgoff) { ++ /* this will catch, kernel-allocated, ++ mmaped-to-usermode addresses */ ++ physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); ++ } else { ++ /* otherwise, use get_user_pages() for general userland pages */ ++ int res, nr_pages = 1; ++ struct page *pages; ++ down_read(¤t->mm->mmap_sem); ++ ++ res = get_user_pages(current, current->mm, virtp, nr_pages, ++ 1, 0, &pages, NULL); ++ up_read(¤t->mm->mmap_sem); ++ ++ if (res == nr_pages) { ++ physp = __pa(page_address(&pages[0]) + ++ (virtp & ~PAGE_MASK)); ++ } else { ++ printk(KERN_WARNING VOUT_NAME ++ "get_user_pages failed\n"); ++ return 0; ++ } ++ } ++ ++ return physp; ++} ++ ++/* This functions wakes up the application once ++ * the DMA transfer to VRFB space is completed. */ ++static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data) ++{ ++ struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data; ++ ++ t->tx_status = 1; ++ wake_up_interruptible(&t->wait); ++} ++ ++/* Release the VRFB context once the module exits */ ++static void omap_vout_release_vrfb(struct omap_vout_device *vout) ++{ ++ int i; ++ ++ for (i = 0; i < 4; i++) ++ omap_vrfb_release_ctx(&vout->vrfb_context[i]); ++ ++ if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) { ++ vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED; ++ omap_free_dma(vout->vrfb_dma_tx.dma_ch); ++ } ++ ++} ++ ++/* Return true if rotation is 90 or 270 */ ++static inline int rotate_90_or_270(const struct omap_vout_device *vout) ++{ ++ return (vout->rotation == dss_rotation_90_degree || ++ vout->rotation == dss_rotation_270_degree); ++} ++ ++/* Return true if rotation is enabled */ ++static inline int rotation_enabled(const struct omap_vout_device *vout) ++{ ++ return vout->rotation || vout->mirror; ++} ++ ++/* Reverse the rotation degree if mirroring is enabled */ ++static inline int calc_rotation(const struct omap_vout_device *vout) ++{ ++ if (!vout->mirror) ++ return vout->rotation; ++ ++ switch (vout->rotation) { ++ case dss_rotation_90_degree: ++ return dss_rotation_270_degree; ++ case dss_rotation_270_degree: ++ return dss_rotation_90_degree; ++ case dss_rotation_180_degree: ++ return dss_rotation_0_degree; ++ default: ++ return dss_rotation_180_degree; ++ } ++} ++ ++/* Free the V4L2 buffers */ ++static void omap_vout_free_buffers(struct omap_vout_device *vout) ++{ ++ int i, numbuffers; ++ ++ /* Allocate memory for the buffers */ ++ numbuffers = (vout->vid) ? video2_numbuffers : video1_numbuffers; ++ vout->buffer_size = (vout->vid) ? video2_bufsize : video1_bufsize; ++ ++ for (i = 0; i < numbuffers; i++) { ++ omap_vout_free_buffer(vout->buf_virt_addr[i], ++ vout->buf_phy_addr[i], vout->buffer_size); ++ vout->buf_phy_addr[i] = 0; ++ vout->buf_virt_addr[i] = 0; ++ } ++} ++ ++/* Free VRFB buffers */ ++static void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout) ++{ ++ int j; ++ ++ for (j = 0; j < 4; j++) { ++ omap_vout_free_buffer(vout->smsshado_virt_addr[j], ++ vout->smsshado_phy_addr[j], ++ vout->smsshado_size); ++ vout->smsshado_virt_addr[j] = 0; ++ vout->smsshado_phy_addr[j] = 0; ++ } ++} ++ ++/* Allocate the buffers for the VRFB space. Data is copied from V4L2 ++ * buffers to the VRFB buffers using the DMA engine.*/ ++static int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout, ++ unsigned int *count, unsigned int startindex) ++{ ++ int i; ++ bool yuv_mode; ++ ++ /* Allocate the VRFB buffers only if the buffers are not ++ * allocated during init time. ++ */ ++ if ((rotation_enabled(vout)) && ++ !vout->vrfb_static_allocation) ++ if (omap_vout_allocate_vrfb_buffers(vout, count, startindex)) ++ return -ENOMEM; ++ ++ if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 || ++ vout->dss_mode == OMAP_DSS_COLOR_UYVY) ++ yuv_mode = true; ++ else ++ yuv_mode = false; ++ ++ for (i = 0; i < *count; i++) { ++ omap_vrfb_setup(&vout->vrfb_context[i], ++ vout->smsshado_phy_addr[i], ++ vout->pix.width, vout->pix.height, ++ vout->bpp, yuv_mode); ++ } ++ return 0; ++} ++ ++/* Convert V4L2 rotation to DSS rotation ++ * V4L2 understand 0, 90, 180, 270. ++ * convert to 0, 1, 2 and 3 repsectively for DSS */ ++static int v4l2_rot_to_dss_rot(int v4l2_rotation, enum dss_rotation *rotation, ++ bool mirror) ++{ ++ switch (v4l2_rotation) { ++ case 90: ++ *rotation = dss_rotation_90_degree; ++ return 0; ++ case 180: ++ *rotation = dss_rotation_180_degree; ++ return 0; ++ case 270: ++ *rotation = dss_rotation_270_degree; ++ return 0; ++ case 0: ++ *rotation = dss_rotation_0_degree; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++ ++} ++ ++/* Calculate the buffer offsets from which the streaming should ++ * start. This offset calculation is mainly required because of ++ * the VRFB 32 pixels alignment with rotation ++ */ ++static int omap_vout_calculate_offset(struct omap_vout_device *vout) ++{ ++ struct v4l2_pix_format *pix = &vout->pix; ++ struct v4l2_rect *crop = &vout->crop; ++ enum dss_rotation rotation; ++ bool mirroring = vout->mirror; ++ int vr_ps = 1, ps = 2, temp_ps = 2; ++ int offset = 0, ctop = 0, cleft = 0, line_length = 0; ++ struct omapvideo_info *ovid; ++ struct omap_overlay *ovl; ++ struct omap_dss_device *cur_display; ++ int *cropped_offset = &vout->cropped_offset; ++ ++ ovid = &vout->vid_info; ++ ovl = ovid->overlays[0]; ++ /* get the display device attached to the overlay */ ++ if (!ovl->manager || !ovl->manager->device) ++ return -1; ++ cur_display = ovl->manager->device; ++ ++ rotation = calc_rotation(vout); ++ ++ if (V4L2_PIX_FMT_YUYV == pix->pixelformat || ++ V4L2_PIX_FMT_UYVY == pix->pixelformat) { ++ if (rotation_enabled(vout)) { ++ /* ++ * ps - Actual pixel size for YUYV/UYVY for ++ * VRFB/Mirroring is 4 bytes ++ * vr_ps - Virtually pixel size for YUYV/UYVY is ++ * 2 bytes ++ */ ++ ps = 4; ++ vr_ps = 2; ++ } else { ++ ps = 2; /* otherwise the pixel size is 2 byte */ ++ } ++ } else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat) { ++ ps = 4; ++ } else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat) { ++ ps = 3; ++ } ++ vout->ps = ps; ++ vout->vr_ps = vr_ps; ++ if (rotation_enabled(vout)) { ++ line_length = MAX_PIXELS_PER_LINE; ++ ctop = (pix->height - crop->height) - crop->top; ++ cleft = (pix->width - crop->width) - crop->left; ++ } else { ++ line_length = pix->width; ++ } ++ vout->line_length = line_length; ++ switch (rotation) { ++ case dss_rotation_90_degree: ++ offset = vout->vrfb_context[0].yoffset * ++ vout->vrfb_context[0].bytespp; ++ temp_ps = ps / vr_ps; ++ if (mirroring == 0) { ++ *cropped_offset = offset + line_length * ++ temp_ps * cleft + crop->top * temp_ps; ++ } else { ++ *cropped_offset = offset + line_length * temp_ps * ++ cleft + crop->top * temp_ps + (line_length * ++ ((crop->width / (vr_ps)) - 1) * ps); ++ } ++ break; ++ case dss_rotation_180_degree: ++ offset = ((MAX_PIXELS_PER_LINE * vout->vrfb_context[0].yoffset * ++ vout->vrfb_context[0].bytespp) + ++ (vout->vrfb_context[0].xoffset * ++ vout->vrfb_context[0].bytespp)); ++ if (mirroring == 0) { ++ *cropped_offset = offset + (line_length * ps * ctop) + ++ (cleft / vr_ps) * ps; ++ ++ } else { ++ *cropped_offset = offset + (line_length * ps * ctop) + ++ (cleft / vr_ps) * ps + (line_length * ++ (crop->height - 1) * ps); ++ } ++ break; ++ case dss_rotation_270_degree: ++ offset = MAX_PIXELS_PER_LINE * vout->vrfb_context[0].xoffset * ++ vout->vrfb_context[0].bytespp; ++ temp_ps = ps / vr_ps; ++ if (mirroring == 0) { ++ *cropped_offset = offset + line_length * ++ temp_ps * crop->left + ctop * ps; ++ } else { ++ *cropped_offset = offset + line_length * ++ temp_ps * crop->left + ctop * ps + ++ (line_length * ((crop->width / vr_ps) - 1) * ++ ps); ++ } ++ break; ++ case dss_rotation_0_degree: ++ if (mirroring == 0) { ++ *cropped_offset = (line_length * ps) * ++ crop->top + (crop->left / vr_ps) * ps; ++ } else { ++ *cropped_offset = (line_length * ps) * ++ crop->top + (crop->left / vr_ps) * ps + ++ (line_length * (crop->height - 1) * ps); ++ } ++ break; ++ default: ++ *cropped_offset = (line_length * ps * crop->top) / ++ vr_ps + (crop->left * ps) / vr_ps + ++ ((crop->width / vr_ps) - 1) * ps; ++ break; ++ } ++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, ++ "%s Offset:%x\n", __func__, *cropped_offset); ++ return 0; ++} ++ ++/* convert V4L2 pixel format to DSS pixel format */ ++static enum omap_color_mode video_mode_to_dss_mode(struct omap_vout_device ++ *vout) ++{ ++ struct omap_overlay *ovl; ++ struct omapvideo_info *ovid; ++ struct v4l2_pix_format *pix = &vout->pix; ++ ++ ovid = &vout->vid_info; ++ ovl = ovid->overlays[0]; ++ ++ switch (pix->pixelformat) { ++ case 0: ++ break; ++ case V4L2_PIX_FMT_YUYV: ++ return OMAP_DSS_COLOR_YUV2; ++ ++ case V4L2_PIX_FMT_UYVY: ++ return OMAP_DSS_COLOR_UYVY; ++ ++ case V4L2_PIX_FMT_RGB565: ++ return OMAP_DSS_COLOR_RGB16; ++ ++ case V4L2_PIX_FMT_RGB24: ++ return OMAP_DSS_COLOR_RGB24P; ++ ++ case V4L2_PIX_FMT_RGB32: ++ return (ovl->id == OMAP_DSS_VIDEO1) ? ++ OMAP_DSS_COLOR_RGB24U : OMAP_DSS_COLOR_ARGB32; ++ case V4L2_PIX_FMT_BGR32: ++ return OMAP_DSS_COLOR_RGBX32; ++ ++ default: ++ return -EINVAL; ++ } ++ return -EINVAL; ++} ++ ++/* Setup the overlay */ ++int omapvid_setup_overlay(struct omap_vout_device *vout, ++ struct omap_overlay *ovl, int posx, int posy, int outw, ++ int outh, u32 addr) ++{ ++ int r = 0; ++ enum omap_color_mode mode = 0; ++ enum dss_rotation rotation; ++ bool mirror; ++ int cropheight, cropwidth, pixheight, pixwidth; ++ struct omap_overlay_info info; ++ ++ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 && ++ (outw != vout->pix.width || outh != vout->pix.height)) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ vout->dss_mode = video_mode_to_dss_mode(vout); ++ ++ if (mode == -EINVAL) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ rotation = vout->rotation; ++ mirror = vout->mirror; ++ ++ /* Setup the input plane parameters according to ++ * rotation value selected. ++ */ ++ if (rotate_90_or_270(vout)) { ++ cropheight = vout->crop.width; ++ cropwidth = vout->crop.height; ++ pixheight = vout->pix.width; ++ pixwidth = vout->pix.height; ++ } else { ++ cropheight = vout->crop.height; ++ cropwidth = vout->crop.width; ++ pixheight = vout->pix.height; ++ pixwidth = vout->pix.width; ++ } ++ ++ ovl->get_overlay_info(ovl, &info); ++ info.paddr = addr; ++ info.vaddr = NULL; ++ info.width = cropwidth; ++ info.height = cropheight; ++ info.color_mode = vout->dss_mode; ++ info.mirror = mirror; ++ info.pos_x = posx; ++ info.pos_y = posy; ++ info.out_width = outw; ++ info.out_height = outh; ++ info.global_alpha = vout->win.global_alpha; ++ if (!rotation_enabled(vout)) { ++ info.rotation = 0; ++ info.rotation_type = OMAP_DSS_ROT_DMA; ++ info.screen_width = pixwidth; ++ } else { ++ info.rotation = vout->rotation; ++ info.rotation_type = OMAP_DSS_ROT_VRFB; ++ info.screen_width = 2048; ++ } ++ ++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, ++ "%s info.enable=%d info.addr=%x info.width=%d\n info.height=%d " ++ "info.color_mode=%d info.rotation=%d info.mirror=%d\n " ++ "info.posx=%d info.posy=%d info.out_width = %d info.out_height=%d\n " ++ "info.rotation_type=%d info.screen_width=%d\n", __func__, info.enabled, ++ info.paddr, info.width, info.height, info.color_mode, info.rotation, ++ info.mirror, info.pos_x, info.pos_y, info.out_width, info.out_height, ++ info.rotation_type, info.screen_width); ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) ++ goto err; ++ ++ return 0; ++err: ++ printk(KERN_WARNING VOUT_NAME "setup_overlay failed\n"); ++ return r; ++} ++ ++/* Initialize the overlay structure */ ++int omapvid_init(struct omap_vout_device *vout, u32 addr) ++{ ++ int r = 0; ++ struct omapvideo_info *ovid = &vout->vid_info; ++ struct omap_overlay *ovl; ++ int posx, posy; ++ int outw, outh, temp, rotation; ++ int i; ++ struct v4l2_window *win; ++ struct omap_video_timings *timing; ++ ++ win = &vout->win; ++ rotation = vout->rotation; ++ for (i = 0; i < ovid->num_overlays; i++) { ++ ovl = ovid->overlays[i]; ++ if (!ovl->manager || !ovl->manager->device) ++ return -EINVAL; ++ ++ timing = &ovl->manager->device->panel.timings; ++ ++ outw = win->w.width; ++ outh = win->w.height; ++ switch (rotation) { ++ case dss_rotation_90_degree: ++ /* Invert the height and width for 90 ++ * and 270 degree rotation ++ */ ++ temp = outw; ++ outw = outh; ++ outh = temp; ++ posy = (timing->y_res - win->w.width)- ++ win->w.left; ++ posx = win->w.top; ++ break; ++ ++ case dss_rotation_180_degree: ++ posx = (timing->x_res - win->w.width) - ++ win->w.left; ++ posy = (timing->y_res - win->w.height) - ++ win->w.top; ++ break; ++ ++ case dss_rotation_270_degree: ++ temp = outw; ++ outw = outh; ++ outh = temp; ++ posy = win->w.left; ++ posx = (timing->x_res - win->w.height) ++ - win->w.top; ++ break; ++ ++ default: ++ posx = win->w.left; ++ posy = win->w.top; ++ break; ++ } ++ ++ r = omapvid_setup_overlay(vout, ovl, posx, posy, outw, ++ outh, addr); ++ if (r) ++ goto err; ++ } ++ return 0; ++err: ++ printk(KERN_WARNING VOUT_NAME "apply_changes failed\n"); ++ return r; ++} ++ ++/* Apply the changes set the go bit of DSS */ ++int omapvid_apply_changes(struct omap_vout_device *vout) ++{ ++ struct omapvideo_info *ovid = &vout->vid_info; ++ struct omap_overlay *ovl; ++ int i; ++ ++ for (i = 0; i < ovid->num_overlays; i++) { ++ ovl = ovid->overlays[i]; ++ if (!ovl->manager || !ovl->manager->device) ++ return -EINVAL; ++ ovl->manager->apply(ovl->manager); ++ } ++ return 0; ++ ++} ++ ++/* Video buffer call backs */ ++ ++/* Buffer setup function is called by videobuf layer when REQBUF ioctl is ++ * called. This is used to setup buffers and return size and count of ++ * buffers allocated. After the call to this buffer, videobuf layer will ++ * setup buffer queue depending on the size and count of buffers ++ */ ++static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, ++ unsigned int *size) ++{ ++ struct omap_vout_device *vout = q->priv_data; ++ int startindex = 0, i, j; ++ u32 phy_addr = 0, virt_addr = 0; ++ ++ if (!vout) ++ return -EINVAL; ++ ++ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type) ++ return -EINVAL; ++ ++ startindex = (vout->vid == OMAP_VIDEO1) ? ++ video1_numbuffers : video2_numbuffers; ++ if (V4L2_MEMORY_MMAP == vout->memory && *count < startindex) ++ *count = startindex; ++ ++ if ((rotation_enabled(vout)) ++ && *count > 4) ++ *count = 4; ++ ++ /* If rotation is enabled, allocate memory for VRFB space also */ ++ if (rotation_enabled(vout)) { ++ if (omap_vout_vrfb_buffer_setup(vout, count, startindex)) ++ return -ENOMEM; ++ } ++ ++ if (V4L2_MEMORY_MMAP != vout->memory) ++ return 0; ++ ++ /* Now allocated the V4L2 buffers */ ++ *size = vout->buffer_size; ++ startindex = (vout->vid == OMAP_VIDEO1) ? ++ video1_numbuffers : video2_numbuffers; ++ for (i = startindex; i < *count; i++) { ++ vout->buffer_size = *size; ++ ++ virt_addr = omap_vout_alloc_buffer(vout->buffer_size, ++ &phy_addr); ++ if (!virt_addr) { ++ if (!rotation_enabled(vout)) ++ break; ++ /* Free the VRFB buffers if no space for V4L2 buffers */ ++ for (j = i; j < *count; j++) { ++ omap_vout_free_buffer( ++ vout->smsshado_virt_addr[j], ++ vout->smsshado_phy_addr[j], ++ vout->smsshado_size); ++ vout->smsshado_virt_addr[j] = 0; ++ vout->smsshado_phy_addr[j] = 0; ++ } ++ } ++ vout->buf_virt_addr[i] = virt_addr; ++ vout->buf_phy_addr[i] = phy_addr; ++ } ++ *count = vout->buffer_allocated = i; ++ return 0; ++} ++ ++/* Free the V4L2 buffers additionally allocated than default ++ * number of buffers and free all the VRFB buffers */ ++static void omap_vout_free_allbuffers(struct omap_vout_device *vout) ++{ ++ int num_buffers = 0, i; ++ ++ num_buffers = (vout->vid == OMAP_VIDEO1) ? ++ video1_numbuffers : video2_numbuffers; ++ for (i = num_buffers; i < vout->buffer_allocated; i++) { ++ if (vout->buf_virt_addr[i]) { ++ omap_vout_free_buffer(vout->buf_virt_addr[i], ++ vout->buf_phy_addr[i], vout->buffer_size); ++ } ++ vout->buf_virt_addr[i] = 0; ++ vout->buf_phy_addr[i] = 0; ++ } ++ /* Free the VRFB buffers only if they are allocated ++ * during reqbufs. Don't free if init time allocated ++ */ ++ if (!vout->vrfb_static_allocation) { ++ for (i = 0; i < 4; i++) { ++ if (vout->smsshado_virt_addr[i]) { ++ omap_vout_free_buffer( ++ vout->smsshado_virt_addr[i], ++ vout->smsshado_phy_addr[i], ++ vout->smsshado_size); ++ vout->smsshado_virt_addr[i] = 0; ++ vout->smsshado_phy_addr[i] = 0; ++ } ++ } ++ } ++ vout->buffer_allocated = num_buffers; ++} ++ ++/* This function will be called when VIDIOC_QBUF ioctl is called. ++ * It prepare buffers before give out for the display. This function ++ * user space virtual address into physical address if userptr memory ++ * exchange mechanism is used. If rotation is enabled, it copies entire ++ * buffer into VRFB memory space before giving it to the DSS. ++ */ ++static int omap_vout_buffer_prepare(struct videobuf_queue *q, ++ struct videobuf_buffer *vb, ++ enum v4l2_field field) ++{ ++ struct omap_vout_device *vout = q->priv_data; ++ u32 dest_frame_index = 0, src_element_index = 0; ++ u32 dest_element_index = 0, src_frame_index = 0; ++ u32 elem_count = 0, frame_count = 0, pixsize = 2; ++ struct videobuf_dmabuf *dmabuf = NULL; ++ enum dss_rotation rotation; ++ struct vid_vrfb_dma *tx; ++ ++ if (VIDEOBUF_NEEDS_INIT == vb->state) { ++ vb->width = vout->pix.width; ++ vb->height = vout->pix.height; ++ vb->size = vb->width * vb->height * vout->bpp; ++ vb->field = field; ++ } ++ vb->state = VIDEOBUF_PREPARED; ++ /* if user pointer memory mechanism is used, get the physical ++ * address of the buffer ++ */ ++ if (V4L2_MEMORY_USERPTR == vb->memory) { ++ if (0 == vb->baddr) ++ return -EINVAL; ++ /* Virtual address */ ++ /* priv points to struct videobuf_pci_sg_memory. But we went ++ * pointer to videobuf_dmabuf, which is member of ++ * videobuf_pci_sg_memory */ ++ dmabuf = videobuf_to_dma(q->bufs[vb->i]); ++ dmabuf->vmalloc = (void *) vb->baddr; ++ ++ /* Physical address */ ++ dmabuf->bus_addr = ++ (dma_addr_t) omap_vout_uservirt_to_phys(vb->baddr); ++ } ++ ++ if (!rotation_enabled(vout)) { ++ dmabuf = videobuf_to_dma(q->bufs[vb->i]); ++ ++ vout->queued_buf_addr[vb->i] = (u8 *) dmabuf->bus_addr; ++ return 0; ++ } ++ dmabuf = videobuf_to_dma(q->bufs[vb->i]); ++ /* If rotation is enabled, copy input buffer into VRFB ++ * memory space using DMA. We are copying input buffer ++ * into VRFB memory space of desired angle and DSS will ++ * read image VRFB memory for 0 degree angle ++ */ ++ pixsize = vout->bpp * vout->vrfb_bpp; ++ /* ++ * DMA transfer in double index mode ++ */ ++ ++ /* Frame index */ ++ dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) - ++ (vout->pix.width * vout->bpp)) + 1; ++ ++ /* Source and destination parameters */ ++ src_element_index = 0; ++ src_frame_index = 0; ++ dest_element_index = 1; ++ /* Number of elements per frame */ ++ elem_count = vout->pix.width * vout->bpp; ++ frame_count = vout->pix.height; ++ tx = &vout->vrfb_dma_tx; ++ tx->tx_status = 0; ++ omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32, ++ (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT, ++ tx->dev_id, 0x0); ++ /* src_port required only for OMAP1 */ ++ omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, ++ dmabuf->bus_addr, src_element_index, src_frame_index); ++ /*set dma source burst mode for VRFB */ ++ omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); ++ rotation = calc_rotation(vout); ++ ++ /* dest_port required only for OMAP1 */ ++ omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, ++ vout->vrfb_context[vb->i].paddr[0], dest_element_index, ++ dest_frame_index); ++ /*set dma dest burst mode for VRFB */ ++ omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); ++ omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0); ++ ++ omap_start_dma(tx->dma_ch); ++ interruptible_sleep_on_timeout(&tx->wait, VRFB_TX_TIMEOUT); ++ ++ if (tx->tx_status == 0) { ++ omap_stop_dma(tx->dma_ch); ++ return -EINVAL; ++ } ++ /* Store buffers physical address into an array. Addresses ++ * from this array will be used to configure DSS */ ++ vout->queued_buf_addr[vb->i] = (u8 *) ++ vout->vrfb_context[vb->i].paddr[rotation]; ++ return 0; ++} ++ ++/* Buffer queue funtion will be called from the videobuf layer when _QBUF ++ * ioctl is called. It is used to enqueue buffer, which is ready to be ++ * displayed. */ ++static void omap_vout_buffer_queue(struct videobuf_queue *q, ++ struct videobuf_buffer *vb) ++{ ++ struct omap_vout_device *vout = q->priv_data; ++ ++ /* Driver is also maintainig a queue. So enqueue buffer in the driver ++ * queue */ ++ list_add_tail(&vb->queue, &vout->dma_queue); ++ ++ vb->state = VIDEOBUF_PREPARED; ++} ++ ++/* Buffer release function is called from videobuf layer to release buffer ++ * which are already allocated */ ++static void omap_vout_buffer_release(struct videobuf_queue *q, ++ struct videobuf_buffer *vb) ++{ ++ struct omap_vout_device *vout = q->priv_data; ++ ++ vb->state = VIDEOBUF_NEEDS_INIT; ++ ++ if (V4L2_MEMORY_MMAP != vout->memory) ++ return; ++} ++ ++/* ++ * File operations ++ */ ++static void omap_vout_vm_open(struct vm_area_struct *vma) ++{ ++ struct omap_vout_device *vout = vma->vm_private_data; ++ ++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, ++ "vm_open [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end); ++ vout->mmap_count++; ++} ++ ++static void omap_vout_vm_close(struct vm_area_struct *vma) ++{ ++ struct omap_vout_device *vout = vma->vm_private_data; ++ ++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, ++ "vm_close [vma=%08lx-%08lx]\n", vma->vm_start, vma->vm_end); ++ vout->mmap_count--; ++} ++ ++static struct vm_operations_struct omap_vout_vm_ops = { ++ .open = omap_vout_vm_open, ++ .close = omap_vout_vm_close, ++}; ++ ++static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct omap_vout_device *vout = file->private_data; ++ struct videobuf_queue *q = &vout->vbq; ++ unsigned long size = (vma->vm_end - vma->vm_start); ++ unsigned long start = vma->vm_start; ++ int i; ++ void *pos; ++ struct videobuf_dmabuf *dmabuf = NULL; ++ ++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, ++ " %s pgoff=0x%lx, start=0x%lx, end=0x%lx\n", __func__, ++ vma->vm_pgoff, vma->vm_start, vma->vm_end); ++ ++ /* look for the buffer to map */ ++ for (i = 0; i < VIDEO_MAX_FRAME; i++) { ++ if (NULL == q->bufs[i]) ++ continue; ++ if (V4L2_MEMORY_MMAP != q->bufs[i]->memory) ++ continue; ++ if (q->bufs[i]->boff == (vma->vm_pgoff << PAGE_SHIFT)) ++ break; ++ } ++ ++ if (VIDEO_MAX_FRAME == i) { ++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, ++ "offset invalid [offset=0x%lx]\n", ++ (vma->vm_pgoff << PAGE_SHIFT)); ++ return -EINVAL; ++ } ++ q->bufs[i]->baddr = vma->vm_start; ++ ++ vma->vm_flags |= VM_RESERVED; ++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); ++ vma->vm_ops = &omap_vout_vm_ops; ++ vma->vm_private_data = (void *) vout; ++ dmabuf = videobuf_to_dma(q->bufs[i]); ++ pos = dmabuf->vmalloc; ++ vma->vm_pgoff = virt_to_phys((void *)pos) >> PAGE_SHIFT; ++ while (size > 0) { ++ unsigned long pfn; ++ pfn = virt_to_phys((void *) pos) >> PAGE_SHIFT; ++ if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) ++ return -EAGAIN; ++ start += PAGE_SIZE; ++ pos += PAGE_SIZE; ++ size -= PAGE_SIZE; ++ } ++ vout->mmap_count++; ++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__); ++ return 0; ++} ++ ++static int omap_vout_release(struct file *file) ++{ ++ ++ struct omap_vout_device *vout = file->private_data; ++ struct videobuf_queue *q; ++ unsigned int t; ++ struct omapvideo_info *ovid; ++ unsigned int r; ++ ++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__); ++ ovid = &vout->vid_info; ++ ++ if (!vout) ++ return 0; ++ q = &vout->vbq; ++ ++ /* Disable all the overlay managers connected with this interface */ ++ for (t = 0; t < ovid->num_overlays; t++) { ++ struct omap_overlay *ovl = ovid->overlays[t]; ++ if (ovl->manager && ovl->manager->device) { ++ struct omap_overlay_info info; ++ ovl->get_overlay_info(ovl, &info); ++ info.enabled = 0; ++ ovl->set_overlay_info(ovl, &info); ++ } ++ ++ } ++ /* Turn off the pipeline */ ++ r = omapvid_apply_changes(vout); ++ if (r) ++ printk(KERN_WARNING VOUT_NAME "Unable to apply changes\n"); ++ ++ /* Free all buffers */ ++ omap_vout_free_allbuffers(vout); ++ videobuf_mmap_free(q); ++ ++ /* Even if apply changes fails we should continue ++ freeing allocated memeory */ ++ if (vout->streaming) { ++ u32 mask = 0; ++ ++ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | ++ DISPC_IRQ_EVSYNC_ODD; ++ omap_dispc_unregister_isr(omap_vout_isr, vout, mask); ++ vout->streaming = 0; ++ ++ videobuf_streamoff(q); ++ videobuf_queue_cancel(q); ++ ++ } ++ ++ if (vout->mmap_count != 0) ++ vout->mmap_count = 0; ++ ++ vout->opened -= 1; ++ file->private_data = NULL; ++ ++ if (vout->buffer_allocated) ++ videobuf_mmap_free(q); ++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__); ++ return r; ++} ++ ++static int omap_vout_open(struct file *file) ++{ ++ struct omap_vout_device *vout = NULL; ++ struct videobuf_queue *q; ++ ++ vout = video_drvdata(file); ++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__); ++ ++ if (vout == NULL) ++ return -ENODEV; ++ ++ /* for now, we only support single open */ ++ if (vout->opened) ++ return -EBUSY; ++ ++ vout->opened += 1; ++ ++ file->private_data = vout; ++ vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ ++ q = &vout->vbq; ++ video_vbq_ops.buf_setup = omap_vout_buffer_setup; ++ video_vbq_ops.buf_prepare = omap_vout_buffer_prepare; ++ video_vbq_ops.buf_release = omap_vout_buffer_release; ++ video_vbq_ops.buf_queue = omap_vout_buffer_queue; ++ spin_lock_init(&vout->vbq_lock); ++ ++ videobuf_queue_sg_init(q, &video_vbq_ops, NULL, &vout->vbq_lock, ++ vout->type, V4L2_FIELD_NONE, sizeof ++ (struct videobuf_buffer), vout); ++ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__); ++ return 0; ++} ++ ++/* V4L2 ioctls */ ++static int vidioc_querycap(struct file *file, void *fh, ++ struct v4l2_capability *cap) ++{ ++ struct omap_vout_device *vout = fh; ++ ++ strlcpy(cap->driver, VOUT_NAME, ++ sizeof(cap->driver)); ++ strlcpy(cap->card, vout->vfd->name, sizeof(cap->card)); ++ cap->bus_info[0] = '\0'; ++ cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT; ++ return 0; ++} ++ ++static int vidioc_enum_fmt_vid_out(struct file *file, void *fh, ++ struct v4l2_fmtdesc *fmt) ++{ ++ int index = fmt->index; ++ enum v4l2_buf_type type = fmt->type; ++ ++ fmt->index = index; ++ fmt->type = type; ++ if (index >= NUM_OUTPUT_FORMATS) ++ return -EINVAL; ++ ++ fmt->flags = omap_formats[index].flags; ++ strlcpy(fmt->description, omap_formats[index].description, ++ sizeof(fmt->description)); ++ fmt->pixelformat = omap_formats[index].pixelformat; ++ return 0; ++} ++ ++static int vidioc_g_fmt_vid_out(struct file *file, void *fh, ++ struct v4l2_format *f) ++{ ++ struct omap_vout_device *vout = fh; ++ ++ f->fmt.pix = vout->pix; ++ return 0; ++ ++} ++ ++static int vidioc_try_fmt_vid_out(struct file *file, void *fh, ++ struct v4l2_format *f) ++{ ++ struct omap_vout_device *vout = fh; ++ struct omapvideo_info *ovid; ++ struct omap_overlay *ovl; ++ struct omap_video_timings *timing; ++ ++ if (vout->streaming) ++ return -EBUSY; ++ ++ ovid = &vout->vid_info; ++ ovl = ovid->overlays[0]; ++ ++ if (!ovl->manager || !ovl->manager->device) ++ return -EINVAL; ++ /* get the display device attached to the overlay */ ++ timing = &ovl->manager->device->panel.timings; ++ ++ vout->fbuf.fmt.height = timing->y_res; ++ vout->fbuf.fmt.width = timing->x_res; ++ ++ omap_vout_try_format(&f->fmt.pix); ++ return 0; ++} ++ ++static int vidioc_s_fmt_vid_out(struct file *file, void *fh, ++ struct v4l2_format *f) ++{ ++ struct omap_vout_device *vout = fh; ++ int bpp; ++ int r; ++ struct omapvideo_info *ovid; ++ struct omap_overlay *ovl; ++ struct omap_video_timings *timing; ++ ++ if (vout->streaming) ++ return -EBUSY; ++ ++ mutex_lock(&vout->lock); ++ ++ ovid = &vout->vid_info; ++ ovl = ovid->overlays[0]; ++ ++ /* get the display device attached to the overlay */ ++ if (!ovl->manager || !ovl->manager->device) { ++ mutex_unlock(&vout->lock); ++ return -EINVAL; ++ } ++ timing = &ovl->manager->device->panel.timings; ++ ++ /* We dont support RGB24-packed mode if vrfb rotation ++ * is enabled*/ ++ if ((rotation_enabled(vout)) && ++ f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { ++ mutex_unlock(&vout->lock); ++ return -EINVAL; ++ } ++ ++ /* get the framebuffer parameters */ ++ ++ if (rotate_90_or_270(vout)) { ++ vout->fbuf.fmt.height = timing->x_res; ++ vout->fbuf.fmt.width = timing->y_res; ++ } else { ++ vout->fbuf.fmt.height = timing->y_res; ++ vout->fbuf.fmt.width = timing->x_res; ++ } ++ ++ /* change to samller size is OK */ ++ ++ bpp = omap_vout_try_format(&f->fmt.pix); ++ f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * bpp; ++ ++ /* try & set the new output format */ ++ vout->bpp = bpp; ++ vout->pix = f->fmt.pix; ++ vout->vrfb_bpp = 1; ++ ++ /* If YUYV then vrfb bpp is 2, for others its 1 */ ++ if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat || ++ V4L2_PIX_FMT_UYVY == vout->pix.pixelformat) ++ vout->vrfb_bpp = 2; ++ ++ /* set default crop and win */ ++ omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win); ++ ++ /* Save the changes in the overlay strcuture */ ++ r = omapvid_init(vout, 0); ++ if (r) { ++ printk(KERN_ERR VOUT_NAME "failed to change mode\n"); ++ mutex_unlock(&vout->lock); ++ return -EINVAL; ++ } ++ mutex_unlock(&vout->lock); ++ return 0; ++} ++ ++static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, ++ struct v4l2_format *f) ++{ ++ int err = -EINVAL; ++ struct omap_vout_device *vout = fh; ++ struct v4l2_window *win = &f->fmt.win; ++ ++ err = omap_vout_try_window(&vout->fbuf, win); ++ ++ if (err) ++ return err; ++ ++ if (vout->vid == OMAP_VIDEO1) ++ win->global_alpha = 255; ++ else ++ win->global_alpha = f->fmt.win.global_alpha; ++ ++ return 0; ++} ++ ++static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh, ++ struct v4l2_format *f) ++{ ++ struct omap_vout_device *vout = fh; ++ int err = -EINVAL; ++ struct omap_overlay *ovl; ++ struct omapvideo_info *ovid; ++ struct v4l2_window *win = &f->fmt.win; ++ ++ mutex_lock(&vout->lock); ++ ovid = &vout->vid_info; ++ ovl = ovid->overlays[0]; ++ ++ err = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win); ++ if (err) { ++ mutex_unlock(&vout->lock); ++ return err; ++ } ++ /* Video1 plane does not support global alpha */ ++ if (ovl->id == OMAP_DSS_VIDEO1) ++ vout->win.global_alpha = 255; ++ else ++ vout->win.global_alpha = f->fmt.win.global_alpha; ++ ++ vout->win.chromakey = f->fmt.win.chromakey; ++ mutex_unlock(&vout->lock); ++ return 0; ++} ++ ++static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh, ++ struct v4l2_fmtdesc *fmt) ++{ ++ int index = fmt->index; ++ enum v4l2_buf_type type = fmt->type; ++ ++ fmt->index = index; ++ fmt->type = type; ++ if (index >= NUM_OUTPUT_FORMATS) ++ return -EINVAL; ++ ++ fmt->flags = omap_formats[index].flags; ++ strlcpy(fmt->description, omap_formats[index].description, ++ sizeof(fmt->description)); ++ fmt->pixelformat = omap_formats[index].pixelformat; ++ return 0; ++} ++ ++static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, ++ struct v4l2_format *f) ++{ ++ struct omap_vout_device *vout = fh; ++ struct omap_overlay *ovl; ++ struct omapvideo_info *ovid; ++ struct omap_overlay_manager_info info; ++ struct v4l2_window *win = &f->fmt.win; ++ u32 key_value = 0; ++ ++ ovid = &vout->vid_info; ++ ovl = ovid->overlays[0]; ++ ++ win->w = vout->win.w; ++ win->field = vout->win.field; ++ win->global_alpha = vout->win.global_alpha; ++ ++ if (ovl->manager && ovl->manager->get_manager_info) { ++ ovl->manager->get_manager_info(ovl->manager, &info); ++ key_value = info.trans_key; ++ } ++ win->chromakey = key_value; ++ return 0; ++} ++ ++static int vidioc_cropcap(struct file *file, void *fh, ++ struct v4l2_cropcap *cropcap) ++{ ++ struct omap_vout_device *vout = fh; ++ enum v4l2_buf_type type = cropcap->type; ++ struct v4l2_pix_format *pix = &vout->pix; ++ ++ cropcap->type = type; ++ if (type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return -EINVAL; ++ ++ /* Width and height are always even */ ++ cropcap->bounds.width = pix->width & ~1; ++ cropcap->bounds.height = pix->height & ~1; ++ ++ omap_vout_default_crop(&vout->pix, &vout->fbuf, &cropcap->defrect); ++ cropcap->pixelaspect.numerator = 1; ++ cropcap->pixelaspect.denominator = 1; ++ return 0; ++} ++ ++static int vidioc_g_crop(struct file *file, void *fh, ++ struct v4l2_crop *crop) ++{ ++ struct omap_vout_device *vout = fh; ++ ++ if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return -EINVAL; ++ crop->c = vout->crop; ++ return 0; ++} ++ ++static int vidioc_s_crop(struct file *file, void *fh, ++ struct v4l2_crop *crop) ++{ ++ struct omap_vout_device *vout = fh; ++ int err = -EINVAL; ++ struct omapvideo_info *ovid; ++ struct omap_overlay *ovl; ++ struct omap_video_timings *timing; ++ ++ if (vout->streaming) ++ return -EBUSY; ++ ++ mutex_lock(&vout->lock); ++ ovid = &vout->vid_info; ++ ovl = ovid->overlays[0]; ++ ++ if (!ovl->manager || !ovl->manager->device) { ++ mutex_unlock(&vout->lock); ++ return -EINVAL; ++ } ++ /* get the display device attached to the overlay */ ++ timing = &ovl->manager->device->panel.timings; ++ ++ if (rotate_90_or_270(vout)) { ++ vout->fbuf.fmt.height = timing->x_res; ++ vout->fbuf.fmt.width = timing->y_res; ++ } else { ++ vout->fbuf.fmt.height = timing->y_res; ++ vout->fbuf.fmt.width = timing->x_res; ++ } ++ ++ if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { ++ err = omap_vout_new_crop(&vout->pix, &vout->crop, &vout->win, ++ &vout->fbuf, &crop->c); ++ mutex_unlock(&vout->lock); ++ return err; ++ } else { ++ mutex_unlock(&vout->lock); ++ return -EINVAL; ++ } ++} ++ ++static int vidioc_queryctrl(struct file *file, void *fh, ++ struct v4l2_queryctrl *ctrl) ++{ ++ switch (ctrl->id) { ++ case V4L2_CID_ROTATE: ++ v4l2_ctrl_query_fill(ctrl, 0, 270, 90, 0); ++ break; ++ case V4L2_CID_BG_COLOR: ++ v4l2_ctrl_query_fill(ctrl, 0, 0xFFFFFF, 1, 0); ++ break; ++ case V4L2_CID_VFLIP: ++ v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0); ++ default: ++ ctrl->name[0] = '\0'; ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl) ++{ ++ struct omap_vout_device *vout = fh; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_ROTATE: ++ ctrl->value = vout->control[0].value; ++ return 0; ++ case V4L2_CID_BG_COLOR: ++ { ++ struct omap_overlay_manager_info info; ++ struct omap_overlay *ovl; ++ ovl = vout->vid_info.overlays[0]; ++ ++ if (!ovl->manager || !ovl->manager->get_manager_info) ++ return -EINVAL; ++ ++ ovl->manager->get_manager_info(ovl->manager, &info); ++ ctrl->value = info.default_color; ++ return 0; ++ } ++ ++ case V4L2_CID_VFLIP: ++ ctrl->value = vout->control[2].value; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a) ++{ ++ struct omap_vout_device *vout = fh; ++ ++ switch (a->id) { ++ case V4L2_CID_ROTATE: ++ { ++ int rotation = a->value; ++ ++ mutex_lock(&vout->lock); ++ ++ if (rotation && ++ vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { ++ mutex_unlock(&vout->lock); ++ return -EINVAL; ++ } ++ ++ if ((v4l2_rot_to_dss_rot(rotation, &vout->rotation, ++ vout->mirror))) { ++ mutex_unlock(&vout->lock); ++ return -EINVAL; ++ } ++ ++ vout->control[0].value = rotation; ++ mutex_unlock(&vout->lock); ++ return 0; ++ } ++ case V4L2_CID_BG_COLOR: ++ { ++ unsigned int color = a->value; ++ struct omap_overlay_manager_info info; ++ struct omap_overlay *ovl; ++ ovl = vout->vid_info.overlays[0]; ++ ++ mutex_lock(&vout->lock); ++ if (!ovl->manager || !ovl->manager->get_manager_info) { ++ mutex_unlock(&vout->lock); ++ return -EINVAL; ++ } ++ ++ ovl->manager->get_manager_info(ovl->manager, &info); ++ info.default_color = color; ++ if (ovl->manager->set_manager_info(ovl->manager, &info)) { ++ mutex_unlock(&vout->lock); ++ return -EINVAL; ++ } ++ ++ vout->control[1].value = color; ++ mutex_unlock(&vout->lock); ++ return 0; ++ } ++ case V4L2_CID_VFLIP: ++ { ++ unsigned int mirror = a->value; ++ struct omapvideo_info *ovid; ++ struct omap_overlay *ovl; ++ ovid = &vout->vid_info; ++ ovl = ovid->overlays[0]; ++ ++ mutex_lock(&vout->lock); ++ ++ if (mirror && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) { ++ mutex_unlock(&vout->lock); ++ return -EINVAL; ++ } ++ vout->mirror = mirror; ++ vout->control[2].value = mirror; ++ mutex_unlock(&vout->lock); ++ return 0; ++ } ++ ++ default: ++ return -EINVAL; ++ } ++ ++} ++ ++static int vidioc_reqbufs(struct file *file, void *fh, ++ struct v4l2_requestbuffers *req) ++{ ++ struct omap_vout_device *vout = fh; ++ struct videobuf_queue *q = &vout->vbq; ++ unsigned int i, num_buffers = 0; ++ int ret = 0; ++ struct videobuf_dmabuf *dmabuf = NULL; ++ ++ if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) || (req->count < 0)) ++ return -EINVAL; ++ /* if memory is not mmp or userptr ++ return error */ ++ if ((V4L2_MEMORY_MMAP != req->memory) && ++ (V4L2_MEMORY_USERPTR != req->memory)) ++ return -EINVAL; ++ ++ mutex_lock(&vout->lock); ++ /* Cannot be requested when streaming is on */ ++ if (vout->streaming) { ++ mutex_unlock(&vout->lock); ++ return -EBUSY; ++ } ++ ++ /* If buffers are already allocated free them */ ++ if (q->bufs[0] && (V4L2_MEMORY_MMAP == q->bufs[0]->memory)) { ++ if (vout->mmap_count) { ++ mutex_unlock(&vout->lock); ++ return -EBUSY; ++ } ++ num_buffers = (vout->vid == OMAP_VIDEO1) ? ++ video1_numbuffers : video2_numbuffers; ++ for (i = num_buffers; i < vout->buffer_allocated; i++) { ++ dmabuf = videobuf_to_dma(q->bufs[i]); ++ omap_vout_free_buffer((u32)dmabuf->vmalloc, ++ dmabuf->bus_addr, vout->buffer_size); ++ vout->buf_virt_addr[i] = 0; ++ vout->buf_phy_addr[i] = 0; ++ } ++ vout->buffer_allocated = num_buffers; ++ videobuf_mmap_free(q); ++ } else if (q->bufs[0] && (V4L2_MEMORY_USERPTR == q->bufs[0]->memory)) { ++ if (vout->buffer_allocated) { ++ videobuf_mmap_free(q); ++ for (i = 0; i < vout->buffer_allocated; i++) { ++ kfree(q->bufs[i]); ++ q->bufs[i] = NULL; ++ } ++ vout->buffer_allocated = 0; ++ } ++ } ++ ++ /*store the memory type in data structure */ ++ vout->memory = req->memory; ++ ++ INIT_LIST_HEAD(&vout->dma_queue); ++ ++ /* call videobuf_reqbufs api */ ++ ret = videobuf_reqbufs(q, req); ++ if (ret < 0) { ++ mutex_unlock(&vout->lock); ++ return ret; ++ } ++ ++ vout->buffer_allocated = req->count; ++ for (i = 0; i < req->count; i++) { ++ dmabuf = videobuf_to_dma(q->bufs[i]); ++ dmabuf->vmalloc = (void *) vout->buf_virt_addr[i]; ++ dmabuf->bus_addr = (dma_addr_t) vout->buf_phy_addr[i]; ++ dmabuf->sglen = 1; ++ } ++ mutex_unlock(&vout->lock); ++ return 0; ++} ++ ++static int vidioc_querybuf(struct file *file, void *fh, ++ struct v4l2_buffer *b) ++{ ++ struct omap_vout_device *vout = fh; ++ ++ return videobuf_querybuf(&vout->vbq, b); ++} ++ ++static int vidioc_qbuf(struct file *file, void *fh, ++ struct v4l2_buffer *buffer) ++{ ++ struct omap_vout_device *vout = fh; ++ struct videobuf_queue *q = &vout->vbq; ++ int ret = 0; ++ ++ if ((V4L2_BUF_TYPE_VIDEO_OUTPUT != buffer->type) || ++ (buffer->index >= vout->buffer_allocated) || ++ (q->bufs[buffer->index]->memory != buffer->memory)) { ++ return -EINVAL; ++ } ++ if (V4L2_MEMORY_USERPTR == buffer->memory) { ++ if ((buffer->length < vout->pix.sizeimage) || ++ (0 == buffer->m.userptr)) { ++ return -EINVAL; ++ } ++ } ++ ++ if ((rotation_enabled(vout)) && ++ vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED) { ++ printk(KERN_WARNING VOUT_NAME ++ "DMA Channel not allocated for Rotation\n"); ++ return -EINVAL; ++ } ++ ++ ret = videobuf_qbuf(q, buffer); ++ return ret; ++} ++ ++static int vidioc_dqbuf(struct file *file, void *fh, ++ struct v4l2_buffer *b) ++{ ++ struct omap_vout_device *vout = fh; ++ struct videobuf_queue *q = &vout->vbq; ++ int ret = 0; ++ ++ if (!vout->streaming) ++ return -EINVAL; ++ ++ if (file->f_flags & O_NONBLOCK) ++ /* Call videobuf_dqbuf for non blocking mode */ ++ ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1); ++ else ++ /* Call videobuf_dqbuf for blocking mode */ ++ ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0); ++ return ret; ++} ++ ++static int vidioc_streamon(struct file *file, void *fh, ++ enum v4l2_buf_type i) ++{ ++ struct omap_vout_device *vout = fh; ++ struct videobuf_queue *q = &vout->vbq; ++ u32 addr = 0; ++ int r = 0; ++ int t; ++ struct omapvideo_info *ovid = &vout->vid_info; ++ u32 mask = 0; ++ ++ mutex_lock(&vout->lock); ++ ++ if (vout->streaming) { ++ mutex_unlock(&vout->lock); ++ return -EBUSY; ++ } ++ ++ r = videobuf_streamon(q); ++ if (r < 0) { ++ mutex_unlock(&vout->lock); ++ return r; ++ } ++ ++ if (list_empty(&vout->dma_queue)) { ++ mutex_unlock(&vout->lock); ++ return -EIO; ++ } ++ /* Get the next frame from the buffer queue */ ++ vout->next_frm = vout->cur_frm = list_entry(vout->dma_queue.next, ++ struct videobuf_buffer, queue); ++ /* Remove buffer from the buffer queue */ ++ list_del(&vout->cur_frm->queue); ++ /* Mark state of the current frame to active */ ++ vout->cur_frm->state = VIDEOBUF_ACTIVE; ++ /* Initialize field_id and started member */ ++ vout->field_id = 0; ++ ++ /* set flag here. Next QBUF will start DMA */ ++ vout->streaming = 1; ++ ++ vout->first_int = 1; ++ ++ if (omap_vout_calculate_offset(vout)) { ++ mutex_unlock(&vout->lock); ++ return -EINVAL; ++ } ++ addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i] ++ + vout->cropped_offset; ++ ++ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | ++ DISPC_IRQ_EVSYNC_ODD; ++ ++ omap_dispc_register_isr(omap_vout_isr, vout, mask); ++ ++ for (t = 0; t < ovid->num_overlays; t++) { ++ struct omap_overlay *ovl = ovid->overlays[t]; ++ if (ovl->manager && ovl->manager->device) { ++ struct omap_overlay_info info; ++ ovl->get_overlay_info(ovl, &info); ++ info.enabled = 1; ++ info.paddr = addr; ++ if (ovl->set_overlay_info(ovl, &info)) ++ return -EINVAL; ++ } ++ } ++ ++ /* First save the configuration in ovelray structure */ ++ r = omapvid_init(vout, addr); ++ if (r) ++ printk(KERN_ERR VOUT_NAME "failed to set overlay info\n"); ++ /* Enable the pipeline and set the Go bit */ ++ r = omapvid_apply_changes(vout); ++ if (r) ++ printk(KERN_ERR VOUT_NAME "failed to change mode\n"); ++ ++ mutex_unlock(&vout->lock); ++ return r; ++} ++ ++static int vidioc_streamoff(struct file *file, void *fh, ++ enum v4l2_buf_type i) ++{ ++ struct omap_vout_device *vout = fh; ++ int t, r = 0; ++ struct omapvideo_info *ovid = &vout->vid_info; ++ u32 mask = 0; ++ ++ if (!vout->streaming) ++ return -EINVAL; ++ ++ vout->streaming = 0; ++ mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | ++ DISPC_IRQ_EVSYNC_ODD; ++ ++ omap_dispc_unregister_isr(omap_vout_isr, vout, mask); ++ ++ for (t = 0; t < ovid->num_overlays; t++) { ++ struct omap_overlay *ovl = ovid->overlays[t]; ++ if (ovl->manager && ovl->manager->device) { ++ struct omap_overlay_info info; ++ ++ ovl->get_overlay_info(ovl, &info); ++ info.enabled = 0; ++ return ovl->set_overlay_info(ovl, &info); ++ } ++ } ++ ++ /* Turn of the pipeline */ ++ r = omapvid_apply_changes(vout); ++ if (r) { ++ printk(KERN_ERR VOUT_NAME "failed to change mode\n"); ++ return r; ++ } ++ videobuf_streamoff(&vout->vbq); ++ videobuf_queue_cancel(&vout->vbq); ++ return 0; ++} ++ ++static int vidioc_s_fbuf(struct file *file, void *fh, ++ struct v4l2_framebuffer *a) ++{ ++ struct omap_vout_device *vout = fh; ++ struct omap_overlay_manager_info info; ++ struct omapvideo_info *ovid; ++ struct omap_overlay *ovl; ++ enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST; ++ int enable = 0; ++ ++ ovid = &vout->vid_info; ++ ovl = ovid->overlays[0]; ++ ++ /* OMAP DSS doesn't support Source and Destination color ++ key together */ ++ if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) && ++ (a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) ++ return -EINVAL; ++ /* OMAP DSS Doesn't support the Destination color key ++ and alpha blending together */ ++ if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY) && ++ (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA)) ++ return -EINVAL; ++ ++ if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)) { ++ vout->fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY; ++ key_type = OMAP_DSS_COLOR_KEY_VID_SRC; ++ } else ++ vout->fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY; ++ ++ if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) { ++ vout->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; ++ key_type = OMAP_DSS_COLOR_KEY_GFX_DST; ++ } else ++ vout->fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; ++ ++ if (a->flags & (V4L2_FBUF_FLAG_CHROMAKEY | ++ V4L2_FBUF_FLAG_SRC_CHROMAKEY)) ++ enable = 1; ++ else ++ enable = 0; ++ if (ovl->manager && ovl->manager->get_manager_info && ++ ovl->manager->set_manager_info) { ++ ++ ovl->manager->get_manager_info(ovl->manager, &info); ++ info.trans_enabled = enable; ++ info.trans_key_type = key_type; ++ info.trans_key = vout->win.chromakey; ++ ++ if (ovl->manager->set_manager_info(ovl->manager, &info)) ++ return -EINVAL; ++ } ++ if (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) { ++ vout->fbuf.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; ++ enable = 1; ++ } else { ++ vout->fbuf.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA; ++ enable = 0; ++ } ++ if (ovl->manager && ovl->manager->get_manager_info && ++ ovl->manager->set_manager_info) { ++ ovl->manager->get_manager_info(ovl->manager, &info); ++ info.alpha_enabled = enable; ++ if (ovl->manager->set_manager_info(ovl->manager, &info)) ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int vidioc_g_fbuf(struct file *file, void *fh, ++ struct v4l2_framebuffer *a) ++{ ++ struct omap_vout_device *vout = fh; ++ struct omap_overlay_manager_info info; ++ struct omapvideo_info *ovid; ++ struct omap_overlay *ovl; ++ ++ ovid = &vout->vid_info; ++ ovl = ovid->overlays[0]; ++ ++ a->flags = 0x0; ++ ++ a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY ++ | V4L2_FBUF_CAP_SRC_CHROMAKEY; ++ ++ if (ovl->manager && ovl->manager->get_manager_info) { ++ ovl->manager->get_manager_info(ovl->manager, &info); ++ if (info.trans_key_type == OMAP_DSS_COLOR_KEY_VID_SRC) ++ a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY; ++ if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST) ++ a->flags |= V4L2_FBUF_FLAG_CHROMAKEY; ++ } ++ if (ovl->manager && ovl->manager->get_manager_info) { ++ ovl->manager->get_manager_info(ovl->manager, &info); ++ if (info.alpha_enabled) ++ a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; ++ } ++ ++ return 0; ++} ++ ++static const struct v4l2_ioctl_ops vout_ioctl_ops = { ++ .vidioc_querycap = vidioc_querycap, ++ .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, ++ .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, ++ .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, ++ .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, ++ .vidioc_queryctrl = vidioc_queryctrl, ++ .vidioc_g_ctrl = vidioc_g_ctrl, ++ .vidioc_s_fbuf = vidioc_s_fbuf, ++ .vidioc_g_fbuf = vidioc_g_fbuf, ++ .vidioc_s_ctrl = vidioc_s_ctrl, ++ .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, ++ .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, ++ .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay, ++ .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, ++ .vidioc_cropcap = vidioc_cropcap, ++ .vidioc_g_crop = vidioc_g_crop, ++ .vidioc_s_crop = vidioc_s_crop, ++ .vidioc_reqbufs = vidioc_reqbufs, ++ .vidioc_querybuf = vidioc_querybuf, ++ .vidioc_qbuf = vidioc_qbuf, ++ .vidioc_dqbuf = vidioc_dqbuf, ++ .vidioc_streamon = vidioc_streamon, ++ .vidioc_streamoff = vidioc_streamoff, ++}; ++ ++static const struct v4l2_file_operations omap_vout_fops = { ++ .owner = THIS_MODULE, ++ .ioctl = video_ioctl2, ++ .mmap = omap_vout_mmap, ++ .open = omap_vout_open, ++ .release = omap_vout_release, ++}; ++ ++/* Init functions used during driver intitalization */ ++/* Initial setup of video_data */ ++static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) ++{ ++ struct v4l2_pix_format *pix; ++ struct video_device *vfd; ++ struct v4l2_control *control; ++ struct omap_dss_device *display = ++ vout->vid_info.overlays[0]->manager->device; ++ ++ /* set the default pix */ ++ pix = &vout->pix; ++ ++ /* Set the default picture of QVGA */ ++ pix->width = QQVGA_WIDTH; ++ pix->height = QQVGA_HEIGHT; ++ ++ /* Default pixel format is RGB 5-6-5 */ ++ pix->pixelformat = V4L2_PIX_FMT_RGB565; ++ pix->field = V4L2_FIELD_ANY; ++ pix->bytesperline = pix->width * 2; ++ pix->sizeimage = pix->bytesperline * pix->height; ++ pix->priv = 0; ++ pix->colorspace = V4L2_COLORSPACE_JPEG; ++ ++ vout->bpp = RGB565_BPP; ++ vout->fbuf.fmt.width = display->panel.timings.x_res; ++ vout->fbuf.fmt.height = display->panel.timings.y_res; ++ ++ /* Set the data structures for the overlay parameters*/ ++ vout->win.global_alpha = 255; ++ vout->fbuf.flags = 0; ++ vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA | ++ V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY; ++ vout->win.chromakey = 0; ++ ++ omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win); ++ ++ /*Initialize the control variables for ++ rotation, flipping and background color. */ ++ control = vout->control; ++ control[0].id = V4L2_CID_ROTATE; ++ control[0].value = 0; ++ vout->rotation = 0; ++ vout->mirror = 0; ++ vout->control[2].id = V4L2_CID_HFLIP; ++ vout->control[2].value = 0; ++ vout->vrfb_bpp = 2; ++ ++ control[1].id = V4L2_CID_BG_COLOR; ++ control[1].value = 0; ++ ++ /* initialize the video_device struct */ ++ vfd = vout->vfd = video_device_alloc(); ++ ++ if (!vfd) { ++ printk(KERN_ERR VOUT_NAME ": could not allocate" ++ " video device struct\n"); ++ return -ENOMEM; ++ } ++ vfd->release = video_device_release; ++ vfd->ioctl_ops = &vout_ioctl_ops; ++ ++ strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name)); ++ vfd->vfl_type = VFL_TYPE_GRABBER; ++ ++ /* need to register for a VID_HARDWARE_* ID in videodev.h */ ++ vfd->fops = &omap_vout_fops; ++ mutex_init(&vout->lock); ++ ++ vfd->minor = -1; ++ return 0; ++ ++} ++ ++/* Setup video buffers */ ++static int __init omap_vout_setup_video_bufs(struct platform_device *pdev, ++ int vid_num) ++{ ++ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); ++ struct omap2video_device *vid_dev = container_of(v4l2_dev, struct ++ omap2video_device, v4l2_dev); ++ struct omap_vout_device *vout; ++ int i, j, r = 0; ++ int image_width, image_height; ++ unsigned numbuffers; ++ struct video_device *vfd; ++ int static_vrfb_allocation = 0, vrfb_num_bufs = 4; ++ ++ vout = vid_dev->vouts[vid_num]; ++ vfd = vout->vfd; ++ ++ numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers; ++ vout->buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize; ++ printk(KERN_INFO VOUT_NAME "Buffer Size = %d\n", vout->buffer_size); ++ for (i = 0; i < numbuffers; i++) { ++ vout->buf_virt_addr[i] = ++ omap_vout_alloc_buffer(vout->buffer_size, ++ (u32 *) &vout->buf_phy_addr[i]); ++ if (!vout->buf_virt_addr[i]) { ++ numbuffers = i; ++ r = -ENOMEM; ++ goto free_buffers; ++ } ++ } ++ ++ for (i = 0; i < 4; i++) { ++ if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) { ++ printk(KERN_INFO VOUT_NAME ": VRFB Region allocation " ++ "for rotation failed\n"); ++ r = -ENOMEM; ++ break; ++ } ++ } ++ if (r == -ENOMEM) { ++ for (j = 0; j < i; j++) ++ omap_vrfb_release_ctx(&vout->vrfb_context[j]); ++ ++ goto free_buffers; ++ } ++ ++ vout->cropped_offset = 0; ++ ++ /* Calculate VRFB memory size */ ++ /* allocate for worst case size */ ++ image_width = VID_MAX_WIDTH / TILE_SIZE; ++ if (VID_MAX_WIDTH % TILE_SIZE) ++ image_width++; ++ ++ image_width = image_width * TILE_SIZE; ++ image_height = VID_MAX_HEIGHT / TILE_SIZE; ++ ++ if (VID_MAX_HEIGHT % TILE_SIZE) ++ image_height++; ++ ++ image_height = image_height * TILE_SIZE; ++ vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2); ++ ++ /* ++ * Request and Initialize DMA, for DMA based VRFB transfer ++ */ ++ vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE; ++ vout->vrfb_dma_tx.dma_ch = -1; ++ vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED; ++ r = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX", ++ omap_vout_vrfb_dma_tx_callback, ++ (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch); ++ if (r < 0) { ++ vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED; ++ printk(KERN_INFO VOUT_NAME ": DMA Channel not alloted " ++ "for video%d [v4l2]\n", vfd->minor); ++ } ++ init_waitqueue_head(&vout->vrfb_dma_tx.wait); ++ ++ /* Allocate VRFB buffers if selected through bootargs */ ++ static_vrfb_allocation = (vid_num == 0) ? ++ vid1_static_vrfb_alloc : vid2_static_vrfb_alloc; ++ ++ /* statically allocated the VRFB buffer is done through ++ commands line aruments */ ++ if (static_vrfb_allocation) { ++ if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) { ++ r = -ENOMEM; ++ goto free_buffers; ++ } ++ vout->vrfb_static_allocation = 1; ++ } ++ return 0; ++ ++free_buffers: ++ for (i = 0; i < numbuffers; i++) { ++ omap_vout_free_buffer(vout->buf_virt_addr[i], ++ vout->buf_phy_addr[i], vout->buffer_size); ++ vout->buf_virt_addr[i] = 0; ++ vout->buf_phy_addr[i] = 0; ++ } ++ return r; ++ ++} ++ ++/* Create video out devices */ ++static int __init omap_vout_create_video_devices(struct platform_device *pdev) ++{ ++ int r = 0, k; ++ struct omap_vout_device *vout; ++ struct video_device *vfd = NULL; ++ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); ++ ++ struct omap2video_device *vid_dev = container_of(v4l2_dev, struct ++ omap2video_device, v4l2_dev); ++ ++ for (k = 0; k < pdev->num_resources; k++) { ++ ++ vout = kmalloc(sizeof(struct omap_vout_device), GFP_KERNEL); ++ if (!vout) { ++ printk(KERN_ERR VOUT_NAME ++ ": could not allocate memory\n"); ++ return -ENOMEM; ++ } ++ ++ memset(vout, 0, sizeof(struct omap_vout_device)); ++ ++ vout->vid = k; ++ vid_dev->vouts[k] = vout; ++ vout->vid_dev = vid_dev; ++ /* Select video2 if only 1 overlay is controlled by V4L2 */ ++ if (pdev->num_resources == 1) ++ vout->vid_info.overlays[0] = vid_dev->overlays[k + 2]; ++ else ++ /* Else select video1 and video2 one by one. */ ++ vout->vid_info.overlays[0] = vid_dev->overlays[k + 1]; ++ vout->vid_info.num_overlays = 1; ++ vout->vid_info.id = k + 1; ++ vid_dev->num_videos++; ++ ++ /* Setup the default configuration for the video devices ++ */ ++ if (omap_vout_setup_video_data(vout) != 0) { ++ r = -ENOMEM; ++ goto error; ++ } ++ ++ /* Allocate default number of buffers for the video streaming ++ * and reserve the VRFB space for rotation ++ */ ++ if (omap_vout_setup_video_bufs(pdev, k) != 0) { ++ r = -ENOMEM; ++ goto error1; ++ } ++ ++ /* Register the Video device with V4L2 ++ */ ++ vfd = vout->vfd; ++ if (video_register_device(vfd, VFL_TYPE_GRABBER, k + 1) < 0) { ++ printk(KERN_ERR VOUT_NAME ": could not register " ++ "Video for Linux device\n"); ++ vfd->minor = -1; ++ r = -ENODEV; ++ goto error2; ++ } ++ video_set_drvdata(vfd, vout); ++ ++ /* Configure the overlay structure */ ++ r = omapvid_init(vid_dev->vouts[k], 0); ++ ++ if (r) ++ goto error2; ++ else ++ goto success; ++error2: ++ omap_vout_release_vrfb(vout); ++ omap_vout_free_buffers(vout); ++error1: ++ video_device_release(vfd); ++error: ++ kfree(vout); ++ return r; ++ ++success: ++ printk(KERN_INFO VOUT_NAME ": registered and initialized " ++ "video device %d [v4l2]\n", vfd->minor); ++ if (k == (pdev->num_resources - 1)) ++ return 0; ++ } ++ return -ENODEV; ++ ++} ++/* Driver functions */ ++static int omap_vout_remove(struct platform_device *pdev) ++{ ++ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); ++ struct omap2video_device *vid_dev = container_of(v4l2_dev, struct ++ omap2video_device, v4l2_dev); ++ int k; ++ ++ v4l2_device_unregister(v4l2_dev); ++ for (k = 0; k < pdev->num_resources; k++) ++ omap_vout_cleanup_device(vid_dev->vouts[k]); ++ ++ for (k = 0; k < vid_dev->num_displays; k++) { ++ if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED) ++ vid_dev->displays[k]->disable(vid_dev->displays[k]); ++ ++ omap_dss_put_device(vid_dev->displays[k]); ++ } ++ kfree(vid_dev); ++ return 0; ++} ++ ++static int __init omap_vout_probe(struct platform_device *pdev) ++{ ++ int r = 0, i; ++ struct omap2video_device *vid_dev = NULL; ++ struct omap_overlay *ovl; ++ struct omap_dss_device *def_display; ++ struct omap_dss_device *dssdev; ++ ++ if (pdev->num_resources == 0) { ++ dev_err(&pdev->dev, "probed for an unknown device\n"); ++ r = -ENODEV; ++ return r; ++ } ++ ++ vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL); ++ if (vid_dev == NULL) { ++ r = -ENOMEM; ++ return r; ++ } ++ ++ vid_dev->num_displays = 0; ++ dssdev = NULL; ++ for_each_dss_dev(dssdev) { ++ omap_dss_get_device(dssdev); ++ vid_dev->displays[vid_dev->num_displays++] = dssdev; ++ } ++ ++ if (vid_dev->num_displays == 0) { ++ dev_err(&pdev->dev, "no displays\n"); ++ r = -EINVAL; ++ goto error0; ++ } ++ ++ vid_dev->num_overlays = omap_dss_get_num_overlays(); ++ for (i = 0; i < vid_dev->num_overlays; i++) ++ vid_dev->overlays[i] = omap_dss_get_overlay(i); ++ ++ vid_dev->num_managers = omap_dss_get_num_overlay_managers(); ++ for (i = 0; i < vid_dev->num_managers; i++) ++ vid_dev->managers[i] = omap_dss_get_overlay_manager(i); ++ ++ /* Get the Video1 overlay and video2 overlay. ++ * Setup the Display attached to that overlays ++ */ ++ for (i = 1; i < 3; i++) { ++ ovl = omap_dss_get_overlay(i); ++ if (ovl->manager && ovl->manager->device) { ++ def_display = ovl->manager->device; ++ } else { ++ dev_warn(&pdev->dev, "cannot find display\n"); ++ def_display = NULL; ++ } ++ if (def_display) { ++ r = def_display->enable(def_display); ++ if (r) { ++ /* Here we are not considering a error ++ * as display may be enabled by frame ++ * buffer driver ++ */ ++ dev_warn(&pdev->dev, ++ "'%s' Display already enabled\n", ++ def_display->name); ++ } ++ /* set the update mode */ ++ if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { ++#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE ++ if (def_display->enable_te) ++ def_display->enable_te(def_display, 1); ++ if (def_display->set_update_mode) ++ def_display->set_update_mode(def_display, ++ OMAP_DSS_UPDATE_AUTO); ++#else /* MANUAL_UPDATE */ ++ if (def_display->enable_te) ++ def_display->enable_te(def_display, 0); ++ if (def_display->set_update_mode) ++ def_display->set_update_mode(def_display, ++ OMAP_DSS_UPDATE_MANUAL); ++#endif ++ } else { ++ if (def_display->set_update_mode) ++ def_display->set_update_mode(def_display, ++ OMAP_DSS_UPDATE_AUTO); ++ } ++ } ++ } ++ ++ if (v4l2_device_register(&pdev->dev, &vid_dev->v4l2_dev) < 0) { ++ printk(KERN_ERR VOUT_NAME "v4l2_device_register failed\n"); ++ return -ENODEV; ++ } ++ ++ r = omap_vout_create_video_devices(pdev); ++ if (r) ++ goto error0; ++ ++ for (i = 0; i < vid_dev->num_displays; i++) { ++ struct omap_dss_device *display = vid_dev->displays[i]; ++ ++ if (display->update) ++ display->update(display, 0, 0, ++ display->panel.timings.x_res, ++ display->panel.timings.y_res); ++ } ++ return 0; ++ ++error0: ++ kfree(vid_dev); ++ return r; ++} ++ ++static struct platform_driver omap_vout_driver = { ++ .driver = { ++ .name = VOUT_NAME, ++ }, ++ .probe = omap_vout_probe, ++ .remove = omap_vout_remove, ++}; ++ ++void omap_vout_isr(void *arg, unsigned int irqstatus) ++{ ++ int r; ++ struct timeval timevalue; ++ struct omap_vout_device *vout = ++ (struct omap_vout_device *) arg; ++ u32 addr, fid; ++ struct omapvideo_info *ovid; ++ struct omap_overlay *ovl; ++ struct omap_dss_device *cur_display; ++ ++ if (!vout->streaming) ++ return; ++ ++ ovid = &vout->vid_info; ++ ovl = ovid->overlays[0]; ++ /* get the display device attached to the overlay */ ++ if (!ovl->manager || !ovl->manager->device) ++ return; ++ cur_display = ovl->manager->device; ++ ++ spin_lock(&vout->vbq_lock); ++ do_gettimeofday(&timevalue); ++ if (cur_display->type == OMAP_DISPLAY_TYPE_DPI) { ++ if (!(irqstatus & DISPC_IRQ_VSYNC)) ++ return; ++ if (!vout->first_int && (vout->cur_frm != vout->next_frm)) { ++ vout->cur_frm->ts = timevalue; ++ vout->cur_frm->state = VIDEOBUF_DONE; ++ wake_up_interruptible(&vout->cur_frm->done); ++ vout->cur_frm = vout->next_frm; ++ } ++ vout->first_int = 0; ++ if (list_empty(&vout->dma_queue)) { ++ spin_unlock(&vout->vbq_lock); ++ return; ++ } ++ ++ vout->next_frm = list_entry(vout->dma_queue.next, ++ struct videobuf_buffer, queue); ++ list_del(&vout->next_frm->queue); ++ ++ vout->next_frm->state = VIDEOBUF_ACTIVE; ++ ++ addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i] ++ + vout->cropped_offset; ++ ++ /* First save the configuration in ovelray structure */ ++ r = omapvid_init(vout, addr); ++ if (r) ++ printk(KERN_ERR VOUT_NAME "failed to set overlay info\n"); ++ /* Enable the pipeline and set the Go bit */ ++ r = omapvid_apply_changes(vout); ++ if (r) ++ printk(KERN_ERR VOUT_NAME "failed to change mode\n"); ++ } else { ++ ++ if (vout->first_int) { ++ vout->first_int = 0; ++ spin_unlock(&vout->vbq_lock); ++ return; ++ } ++ if (irqstatus & DISPC_IRQ_EVSYNC_ODD) { ++ fid = 1; ++ } else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) { ++ fid = 0; ++ } else { ++ spin_unlock(&vout->vbq_lock); ++ return; ++ } ++ vout->field_id ^= 1; ++ if (fid != vout->field_id) { ++ if (0 == fid) ++ vout->field_id = fid; ++ ++ spin_unlock(&vout->vbq_lock); ++ return; ++ } ++ if (0 == fid) { ++ if (vout->cur_frm == vout->next_frm) { ++ spin_unlock(&vout->vbq_lock); ++ return; ++ } ++ vout->cur_frm->ts = timevalue; ++ vout->cur_frm->state = VIDEOBUF_DONE; ++ wake_up_interruptible(&vout->cur_frm->done); ++ vout->cur_frm = vout->next_frm; ++ } else if (1 == fid) { ++ if (list_empty(&vout->dma_queue) || ++ (vout->cur_frm != vout->next_frm)) { ++ spin_unlock(&vout->vbq_lock); ++ return; ++ } ++ vout->next_frm = list_entry(vout->dma_queue.next, ++ struct videobuf_buffer, queue); ++ list_del(&vout->next_frm->queue); ++ ++ vout->next_frm->state = VIDEOBUF_ACTIVE; ++ addr = (unsigned long) ++ vout->queued_buf_addr[vout->next_frm->i] + ++ vout->cropped_offset; ++ /* First save the configuration in ovelray structure */ ++ r = omapvid_init(vout, addr); ++ if (r) ++ printk(KERN_ERR VOUT_NAME ++ "failed to set overlay info\n"); ++ /* Enable the pipeline and set the Go bit */ ++ r = omapvid_apply_changes(vout); ++ if (r) ++ printk(KERN_ERR VOUT_NAME ++ "failed to change mode\n"); ++ } ++ ++ } ++ spin_unlock(&vout->vbq_lock); ++} ++ ++static void omap_vout_cleanup_device(struct omap_vout_device *vout) ++{ ++ struct video_device *vfd; ++ ++ if (!vout) ++ return; ++ vfd = vout->vfd; ++ ++ if (vfd) { ++ if (vfd->minor == -1) { ++ /* ++ * The device was never registered, so release the ++ * video_device struct directly. ++ */ ++ video_device_release(vfd); ++ } else { ++ /* ++ * The unregister function will release the video_device ++ * struct as well as unregistering it. ++ */ ++ video_unregister_device(vfd); ++ } ++ } ++ ++ omap_vout_release_vrfb(vout); ++ ++ omap_vout_free_buffers(vout); ++ /* Free the VRFB buffer if allocated ++ * init time ++ */ ++ if (vout->vrfb_static_allocation) ++ omap_vout_free_vrfb_buffers(vout); ++ ++ kfree(vout); ++} ++ ++static int __init omap_vout_init(void) ++{ ++ ++ if (platform_driver_register(&omap_vout_driver) != 0) { ++ printk(KERN_ERR VOUT_NAME ": could not register \ ++ Video driver\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static void omap_vout_cleanup(void) ++{ ++ platform_driver_unregister(&omap_vout_driver); ++} ++ ++late_initcall(omap_vout_init); ++module_exit(omap_vout_cleanup); +diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h +new file mode 100644 +index 0000000..57743e5 +--- /dev/null ++++ b/drivers/media/video/omap/omap_voutdef.h +@@ -0,0 +1,148 @@ ++/* ++ * drivers/media/video/omap/omap_voutdef.h ++ * ++ * Copyright (C) 2009 Texas Instruments. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#ifndef OMAP_VOUTDEF_H ++#define OMAP_VOUTDEF_H ++ ++#include <mach/display.h> ++ ++#define YUYV_BPP 2 ++#define RGB565_BPP 2 ++#define RGB24_BPP 3 ++#define RGB32_BPP 4 ++#define TILE_SIZE 32 ++#define YUYV_VRFB_BPP 2 ++#define RGB_VRFB_BPP 1 ++#define MAX_CID 3 ++#define MAC_VRFB_CTXS 4 ++#define MAX_VOUT_DEV 2 ++#define MAX_OVLS 3 ++#define MAX_DISPLAYS 3 ++#define MAX_MANAGERS 3 ++ ++/* Enum for Rotation ++ * DSS understands rotation in 0, 1, 2, 3 context ++ * while V4L2 driver understands it as 0, 90, 180, 270 ++ */ ++enum dss_rotation { ++ dss_rotation_0_degree = 0, ++ dss_rotation_90_degree = 1, ++ dss_rotation_180_degree = 2, ++ dss_rotation_270_degree = 3, ++}; ++/* ++ * This structure is used to store the DMA transfer parameters ++ * for VRFB hidden buffer ++ */ ++struct vid_vrfb_dma { ++ int dev_id; ++ int dma_ch; ++ int req_status; ++ int tx_status; ++ wait_queue_head_t wait; ++}; ++ ++struct omapvideo_info { ++ int id; ++ int num_overlays; ++ struct omap_overlay *overlays[MAX_OVLS]; ++}; ++ ++struct omap2video_device { ++ struct mutex mtx; ++ ++ int state; ++ ++ struct v4l2_device v4l2_dev; ++ int num_videos; ++ struct omap_vout_device *vouts[MAX_VOUT_DEV]; ++ ++ int num_displays; ++ struct omap_dss_device *displays[MAX_DISPLAYS]; ++ int num_overlays; ++ struct omap_overlay *overlays[MAX_OVLS]; ++ int num_managers; ++ struct omap_overlay_manager *managers[MAX_MANAGERS]; ++}; ++ ++/* per-device data structure */ ++struct omap_vout_device { ++ ++ struct omapvideo_info vid_info; ++ struct video_device *vfd; ++ struct omap2video_device *vid_dev; ++ int vid; ++ int opened; ++ ++ /* we don't allow to change image fmt/size once buffer has ++ * been allocated ++ */ ++ int buffer_allocated; ++ /* allow to reuse previously allocated buffer which is big enough */ ++ int buffer_size; ++ /* keep buffer info across opens */ ++ unsigned long buf_virt_addr[VIDEO_MAX_FRAME]; ++ unsigned long buf_phy_addr[VIDEO_MAX_FRAME]; ++ enum omap_color_mode dss_mode; ++ ++ /* we don't allow to request new buffer when old buffers are ++ * still mmaped ++ */ ++ int mmap_count; ++ ++ spinlock_t vbq_lock; /* spinlock for videobuf queues */ ++ unsigned long field_count; /* field counter for videobuf_buffer */ ++ ++ /* non-NULL means streaming is in progress. */ ++ bool streaming; ++ ++ struct v4l2_pix_format pix; ++ struct v4l2_rect crop; ++ struct v4l2_window win; ++ struct v4l2_framebuffer fbuf; ++ ++ /* Lock to protect the shared data structures in ioctl */ ++ struct mutex lock; ++ ++ /* V4L2 control structure for different control id */ ++ struct v4l2_control control[MAX_CID]; ++ enum dss_rotation rotation; ++ bool mirror; ++ int flicker_filter; ++ /* V4L2 control structure for different control id */ ++ ++ int bpp; /* bytes per pixel */ ++ int vrfb_bpp; /* bytes per pixel with respect to VRFB */ ++ ++ struct vid_vrfb_dma vrfb_dma_tx; ++ unsigned int smsshado_phy_addr[MAC_VRFB_CTXS]; ++ unsigned int smsshado_virt_addr[MAC_VRFB_CTXS]; ++ struct vrfb vrfb_context[MAC_VRFB_CTXS]; ++ bool vrfb_static_allocation; ++ unsigned int smsshado_size; ++ unsigned char pos; ++ ++ int ps, vr_ps, line_length, first_int, field_id; ++ enum v4l2_memory memory; ++ struct videobuf_buffer *cur_frm, *next_frm; ++ struct list_head dma_queue; ++ u8 *queued_buf_addr[VIDEO_MAX_FRAME]; ++ u32 cropped_offset; ++ s32 tv_field1_offset; ++ void *isr_handle; ++ ++ /* Buffer queue variables */ ++ struct omap_vout_device *vout; ++ enum v4l2_buf_type type; ++ struct videobuf_queue vbq; ++ int io_allowed; ++ ++}; ++#endif /* ifndef OMAP_VOUTDEF_H */ +diff --git a/drivers/media/video/omap/omap_voutlib.c b/drivers/media/video/omap/omap_voutlib.c +new file mode 100644 +index 0000000..bce5072 +--- /dev/null ++++ b/drivers/media/video/omap/omap_voutlib.c +@@ -0,0 +1,258 @@ ++/* ++ * drivers/media/video/omap/omap_voutlib.c ++ * ++ * Copyright (C) 2005-2009 Texas Instruments. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ * ++ * Based on the OMAP2 camera driver ++ * Video-for-Linux (Version 2) camera capture driver for ++ * the OMAP24xx camera controller. ++ * ++ * Author: Andy Lowe (source@mvista.com) ++ * ++ * Copyright (C) 2004 MontaVista Software, Inc. ++ * Copyright (C) 2009 Texas Instruments. ++ * ++ */ ++ ++#include <linux/module.h> ++#include <linux/errno.h> ++#include <linux/kernel.h> ++#include <linux/types.h> ++#include <linux/videodev2.h> ++ ++MODULE_AUTHOR("Texas Instruments."); ++MODULE_DESCRIPTION("OMAP Video library"); ++MODULE_LICENSE("GPL"); ++ ++/* Return the default overlay cropping rectangle in crop given the image ++ * size in pix and the video display size in fbuf. The default ++ * cropping rectangle is the largest rectangle no larger than the capture size ++ * that will fit on the display. The default cropping rectangle is centered in ++ * the image. All dimensions and offsets are rounded down to even numbers. ++ */ ++void omap_vout_default_crop(struct v4l2_pix_format *pix, ++ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop) ++{ ++ crop->width = (pix->width < fbuf->fmt.width) ? ++ pix->width : fbuf->fmt.width; ++ crop->height = (pix->height < fbuf->fmt.height) ? ++ pix->height : fbuf->fmt.height; ++ crop->width &= ~1; ++ crop->height &= ~1; ++ crop->left = ((pix->width - crop->width) >> 1) & ~1; ++ crop->top = ((pix->height - crop->height) >> 1) & ~1; ++} ++EXPORT_SYMBOL_GPL(omap_vout_default_crop); ++ ++/* Given a new render window in new_win, adjust the window to the ++ * nearest supported configuration. The adjusted window parameters are ++ * returned in new_win. ++ * Returns zero if succesful, or -EINVAL if the requested window is ++ * impossible and cannot reasonably be adjusted. ++ */ ++int omap_vout_try_window(struct v4l2_framebuffer *fbuf, ++ struct v4l2_window *new_win) ++{ ++ struct v4l2_rect try_win; ++ ++ /* make a working copy of the new_win rectangle */ ++ try_win = new_win->w; ++ ++ /* adjust the preview window so it fits on the display by clipping any ++ * offscreen areas ++ */ ++ if (try_win.left < 0) { ++ try_win.width += try_win.left; ++ try_win.left = 0; ++ } ++ if (try_win.top < 0) { ++ try_win.height += try_win.top; ++ try_win.top = 0; ++ } ++ try_win.width = (try_win.width < fbuf->fmt.width) ? ++ try_win.width : fbuf->fmt.width; ++ try_win.height = (try_win.height < fbuf->fmt.height) ? ++ try_win.height : fbuf->fmt.height; ++ if (try_win.left + try_win.width > fbuf->fmt.width) ++ try_win.width = fbuf->fmt.width - try_win.left; ++ if (try_win.top + try_win.height > fbuf->fmt.height) ++ try_win.height = fbuf->fmt.height - try_win.top; ++ try_win.width &= ~1; ++ try_win.height &= ~1; ++ ++ if (try_win.width <= 0 || try_win.height <= 0) ++ return -EINVAL; ++ ++ /* We now have a valid preview window, so go with it */ ++ new_win->w = try_win; ++ new_win->field = V4L2_FIELD_ANY; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(omap_vout_try_window); ++ ++/* Given a new render window in new_win, adjust the window to the ++ * nearest supported configuration. The image cropping window in crop ++ * will also be adjusted if necessary. Preference is given to keeping the ++ * the window as close to the requested configuration as possible. If ++ * successful, new_win, vout->win, and crop are updated. ++ * Returns zero if succesful, or -EINVAL if the requested preview window is ++ * impossible and cannot reasonably be adjusted. ++ */ ++int omap_vout_new_window(struct v4l2_rect *crop, ++ struct v4l2_window *win, struct v4l2_framebuffer *fbuf, ++ struct v4l2_window *new_win) ++{ ++ int err; ++ ++ err = omap_vout_try_window(fbuf, new_win); ++ if (err) ++ return err; ++ ++ /* update our preview window */ ++ win->w = new_win->w; ++ win->field = new_win->field; ++ win->chromakey = new_win->chromakey; ++ ++ /* adjust the cropping window to allow for resizing limitations */ ++ if ((crop->height/win->w.height) >= 4) { ++ /* The maximum vertical downsizing ratio is 4:1 */ ++ crop->height = win->w.height * 4; ++ } ++ if ((crop->width/win->w.width) >= 4) { ++ /* The maximum horizontal downsizing ratio is 4:1 */ ++ crop->width = win->w.width * 4; ++ } ++ return 0; ++} ++EXPORT_SYMBOL_GPL(omap_vout_new_window); ++ ++/* Given a new cropping rectangle in new_crop, adjust the cropping rectangle to ++ * the nearest supported configuration. The image render window in win will ++ * also be adjusted if necessary. The preview window is adjusted such that the ++ * horizontal and vertical rescaling ratios stay constant. If the render ++ * window would fall outside the display boundaries, the cropping rectangle ++ * will also be adjusted to maintain the rescaling ratios. If successful, crop ++ * and win are updated. ++ * Returns zero if succesful, or -EINVAL if the requested cropping rectangle is ++ * impossible and cannot reasonably be adjusted. ++ */ ++int omap_vout_new_crop(struct v4l2_pix_format *pix, ++ struct v4l2_rect *crop, struct v4l2_window *win, ++ struct v4l2_framebuffer *fbuf, const struct v4l2_rect *new_crop) ++{ ++ struct v4l2_rect try_crop; ++ unsigned long vresize, hresize; ++ ++ /* make a working copy of the new_crop rectangle */ ++ try_crop = *new_crop; ++ ++ /* adjust the cropping rectangle so it fits in the image */ ++ if (try_crop.left < 0) { ++ try_crop.width += try_crop.left; ++ try_crop.left = 0; ++ } ++ if (try_crop.top < 0) { ++ try_crop.height += try_crop.top; ++ try_crop.top = 0; ++ } ++ try_crop.width = (try_crop.width < pix->width) ? ++ try_crop.width : pix->width; ++ try_crop.height = (try_crop.height < pix->height) ? ++ try_crop.height : pix->height; ++ if (try_crop.left + try_crop.width > pix->width) ++ try_crop.width = pix->width - try_crop.left; ++ if (try_crop.top + try_crop.height > pix->height) ++ try_crop.height = pix->height - try_crop.top; ++ try_crop.width &= ~1; ++ try_crop.height &= ~1; ++ if (try_crop.width <= 0 || try_crop.height <= 0) ++ return -EINVAL; ++ ++ if (crop->height != win->w.height) { ++ /* If we're resizing vertically, we can't support a crop width ++ * wider than 768 pixels. ++ */ ++ if (try_crop.width > 768) ++ try_crop.width = 768; ++ } ++ /* vertical resizing */ ++ vresize = (1024 * crop->height) / win->w.height; ++ if (vresize > 4096) ++ vresize = 4096; ++ else if (vresize == 0) ++ vresize = 1; ++ win->w.height = ((1024 * try_crop.height) / vresize) & ~1; ++ if (win->w.height == 0) ++ win->w.height = 2; ++ if (win->w.height + win->w.top > fbuf->fmt.height) { ++ /* We made the preview window extend below the bottom of the ++ * display, so clip it to the display boundary and resize the ++ * cropping height to maintain the vertical resizing ratio. ++ */ ++ win->w.height = (fbuf->fmt.height - win->w.top) & ~1; ++ if (try_crop.height == 0) ++ try_crop.height = 2; ++ } ++ /* horizontal resizing */ ++ hresize = (1024 * crop->width) / win->w.width; ++ if (hresize > 4096) ++ hresize = 4096; ++ else if (hresize == 0) ++ hresize = 1; ++ win->w.width = ((1024 * try_crop.width) / hresize) & ~1; ++ if (win->w.width == 0) ++ win->w.width = 2; ++ if (win->w.width + win->w.left > fbuf->fmt.width) { ++ /* We made the preview window extend past the right side of the ++ * display, so clip it to the display boundary and resize the ++ * cropping width to maintain the horizontal resizing ratio. ++ */ ++ win->w.width = (fbuf->fmt.width - win->w.left) & ~1; ++ if (try_crop.width == 0) ++ try_crop.width = 2; ++ } ++ ++ /* Check for resizing constraints */ ++ if ((try_crop.height/win->w.height) >= 4) { ++ /* The maximum vertical downsizing ratio is 4:1 */ ++ try_crop.height = win->w.height * 4; ++ } ++ if ((try_crop.width/win->w.width) >= 4) { ++ /* The maximum horizontal downsizing ratio is 4:1 */ ++ try_crop.width = win->w.width * 4; ++ } ++ ++ /* update our cropping rectangle and we're done */ ++ *crop = try_crop; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(omap_vout_new_crop); ++ ++/* Given a new format in pix and fbuf, crop and win ++ * structures are initialized to default values. crop ++ * is initialized to the largest window size that will fit on the display. The ++ * crop window is centered in the image. win is initialized to ++ * the same size as crop and is centered on the display. ++ * All sizes and offsets are constrained to be even numbers. ++ */ ++void omap_vout_new_format(struct v4l2_pix_format *pix, ++ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop, ++ struct v4l2_window *win) ++{ ++ /* crop defines the preview source window in the image capture ++ * buffer ++ */ ++ omap_vout_default_crop(pix, fbuf, crop); ++ ++ /* win defines the preview target window on the display */ ++ win->w.width = crop->width; ++ win->w.height = crop->height; ++ win->w.left = ((fbuf->fmt.width - win->w.width) >> 1) & ~1; ++ win->w.top = ((fbuf->fmt.height - win->w.height) >> 1) & ~1; ++} ++EXPORT_SYMBOL_GPL(omap_vout_new_format); ++ +diff --git a/drivers/media/video/omap/omap_voutlib.h b/drivers/media/video/omap/omap_voutlib.h +new file mode 100644 +index 0000000..8ef6e25 +--- /dev/null ++++ b/drivers/media/video/omap/omap_voutlib.h +@@ -0,0 +1,34 @@ ++/* ++ * drivers/media/video/omap/omap_voutlib.h ++ * ++ * Copyright (C) 2009 Texas Instruments. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ * ++ */ ++ ++#ifndef OMAP_VOUTLIB_H ++#define OMAP_VOUTLIB_H ++ ++extern void omap_vout_default_crop(struct v4l2_pix_format *pix, ++ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop); ++ ++extern int omap_vout_new_crop(struct v4l2_pix_format *pix, ++ struct v4l2_rect *crop, struct v4l2_window *win, ++ struct v4l2_framebuffer *fbuf, ++ const struct v4l2_rect *new_crop); ++ ++extern int omap_vout_try_window(struct v4l2_framebuffer *fbuf, ++ struct v4l2_window *new_win); ++ ++extern int omap_vout_new_window(struct v4l2_rect *crop, ++ struct v4l2_window *win, struct v4l2_framebuffer *fbuf, ++ struct v4l2_window *new_win); ++ ++extern void omap_vout_new_format(struct v4l2_pix_format *pix, ++ struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop, ++ struct v4l2_window *win); ++#endif /* #ifndef OMAP_LIB_H */ ++ +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0005-OMAP-Add-support-for-VRFB-rotation-engine.patch b/recipes/linux/linux-omap-2.6.31/dss2/0005-OMAP-Add-support-for-VRFB-rotation-engine.patch new file mode 100644 index 0000000000..0a38a31d76 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0005-OMAP-Add-support-for-VRFB-rotation-engine.patch @@ -0,0 +1,378 @@ +From 4df5684fb6c8cab641a843d890bd010cb32ccc97 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Fri, 7 Aug 2009 12:04:26 +0300 +Subject: [PATCH 05/18] OMAP: Add support for VRFB rotation engine + +VRFB rotation engine is a block in OMAP2/3 that offers 12 independent +contexts that can be used for framebuffer rotation. + +Each context has a backend area of real memory, where it stores the +pixels in undisclosed format. This memory is offered to users via 4 +virtual memory areas, which see the same memory area in different +rotation angles (0, 90, 180 and 270 degrees). + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + arch/arm/plat-omap/include/mach/vrfb.h | 46 ++++++ + drivers/video/omap2/Kconfig | 3 + + drivers/video/omap2/Makefile | 1 + + drivers/video/omap2/vrfb.c | 277 ++++++++++++++++++++++++++++++++ + 4 files changed, 327 insertions(+), 0 deletions(-) + create mode 100644 arch/arm/plat-omap/include/mach/vrfb.h + create mode 100644 drivers/video/omap2/vrfb.c + +diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h +new file mode 100644 +index 0000000..8790612 +--- /dev/null ++++ b/arch/arm/plat-omap/include/mach/vrfb.h +@@ -0,0 +1,46 @@ ++/* ++ * VRFB Rotation Engine ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#ifndef __OMAP_VRFB_H__ ++#define __OMAP_VRFB_H__ ++ ++#define OMAP_VRFB_LINE_LEN 2048 ++ ++struct vrfb { ++ u8 context; ++ void __iomem *vaddr[4]; ++ unsigned long paddr[4]; ++ u16 xoffset; ++ u16 yoffset; ++ u8 bytespp; ++}; ++ ++extern int omap_vrfb_request_ctx(struct vrfb *vrfb); ++extern void omap_vrfb_release_ctx(struct vrfb *vrfb); ++extern void omap_vrfb_suspend_ctx(struct vrfb *vrfb); ++extern void omap_vrfb_resume_ctx(struct vrfb *vrfb); ++extern void omap_vrfb_adjust_size(u16 *width, u16 *height, ++ u8 bytespp); ++extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, ++ u16 width, u16 height, ++ unsigned bytespp, bool yuv_mode); ++extern void omap_vrfb_restore_context(void); ++ ++#endif /* __VRFB_H */ +diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig +index 7a6c4c9..ac8b650 100644 +--- a/drivers/video/omap2/Kconfig ++++ b/drivers/video/omap2/Kconfig +@@ -1,2 +1,5 @@ + config OMAP2_VRAM + bool ++ ++config OMAP2_VRFB ++ bool +diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile +index 7fdf7bd..aa3751b 100644 +--- a/drivers/video/omap2/Makefile ++++ b/drivers/video/omap2/Makefile +@@ -1 +1,2 @@ + obj-$(CONFIG_OMAP2_VRAM) += vram.o ++obj-$(CONFIG_OMAP2_VRFB) += vrfb.o +diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c +new file mode 100644 +index 0000000..8726689 +--- /dev/null ++++ b/drivers/video/omap2/vrfb.c +@@ -0,0 +1,277 @@ ++/* ++ * VRFB Rotation Engine ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/ioport.h> ++#include <linux/io.h> ++#include <linux/bitops.h> ++#include <linux/mutex.h> ++ ++#include <mach/io.h> ++#include <mach/vrfb.h> ++#include <mach/sdrc.h> ++/*#define DEBUG*/ ++ ++#ifdef DEBUG ++#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__) ++#else ++#define DBG(format, ...) ++#endif ++ ++#define SMS_ROT_VIRT_BASE(context, rot) \ ++ (((context >= 4) ? 0xD0000000 : 0x70000000) \ ++ + (0x4000000 * (context)) \ ++ + (0x1000000 * (rot))) ++ ++#define OMAP_VRFB_SIZE (2048 * 2048 * 4) ++ ++#define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */ ++#define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */ ++#define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP) ++#define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP) ++#define SMS_IMAGEHEIGHT_OFFSET 16 ++#define SMS_IMAGEWIDTH_OFFSET 0 ++#define SMS_PH_OFFSET 8 ++#define SMS_PW_OFFSET 4 ++#define SMS_PS_OFFSET 0 ++ ++#define VRFB_NUM_CTXS 12 ++/* bitmap of reserved contexts */ ++static unsigned long ctx_map; ++/* bitmap of contexts for which we have to keep the HW context valid */ ++static unsigned long ctx_map_active; ++ ++static DEFINE_MUTEX(ctx_lock); ++ ++/* ++ * Access to this happens from client drivers or the PM core after wake-up. ++ * For the first case we require locking at the driver level, for the second ++ * we don't need locking, since no drivers will run until after the wake-up ++ * has finished. ++ */ ++static struct { ++ u32 physical_ba; ++ u32 control; ++ u32 size; ++} vrfb_hw_context[VRFB_NUM_CTXS]; ++ ++static inline void restore_hw_context(int ctx) ++{ ++ omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx); ++ omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx); ++ omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx); ++} ++ ++void omap_vrfb_restore_context(void) ++{ ++ int i; ++ unsigned long map = ctx_map_active; ++ ++ for (i = ffs(map); i; i = ffs(map)) { ++ /* i=1..32 */ ++ i--; ++ map &= ~(1 << i); ++ restore_hw_context(i); ++ } ++} ++ ++void omap_vrfb_adjust_size(u16 *width, u16 *height, ++ u8 bytespp) ++{ ++ *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp; ++ *height = ALIGN(*height, VRFB_PAGE_HEIGHT); ++} ++EXPORT_SYMBOL(omap_vrfb_adjust_size); ++ ++void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, ++ u16 width, u16 height, ++ unsigned bytespp, bool yuv_mode) ++{ ++ unsigned pixel_size_exp; ++ u16 vrfb_width; ++ u16 vrfb_height; ++ u8 ctx = vrfb->context; ++ u32 size; ++ u32 control; ++ ++ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr, ++ width, height, color_mode); ++ ++ /* For YUV2 and UYVY modes VRFB needs to handle pixels a bit ++ * differently. See TRM. */ ++ if (yuv_mode) { ++ bytespp *= 2; ++ width /= 2; ++ } ++ ++ if (bytespp == 4) ++ pixel_size_exp = 2; ++ else if (bytespp == 2) ++ pixel_size_exp = 1; ++ else ++ BUG(); ++ ++ vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp; ++ vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT); ++ ++ DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp); ++ ++ size = vrfb_width << SMS_IMAGEWIDTH_OFFSET; ++ size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET; ++ ++ control = pixel_size_exp << SMS_PS_OFFSET; ++ control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET; ++ control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET; ++ ++ vrfb_hw_context[ctx].physical_ba = paddr; ++ vrfb_hw_context[ctx].size = size; ++ vrfb_hw_context[ctx].control = control; ++ ++ omap2_sms_write_rot_physical_ba(paddr, ctx); ++ omap2_sms_write_rot_size(size, ctx); ++ omap2_sms_write_rot_control(control, ctx); ++ ++ DBG("vrfb offset pixels %d, %d\n", ++ vrfb_width - width, vrfb_height - height); ++ ++ vrfb->xoffset = vrfb_width - width; ++ vrfb->yoffset = vrfb_height - height; ++ vrfb->bytespp = bytespp; ++} ++EXPORT_SYMBOL(omap_vrfb_setup); ++ ++void omap_vrfb_release_ctx(struct vrfb *vrfb) ++{ ++ int rot; ++ int ctx = vrfb->context; ++ ++ if (ctx == 0xff) ++ return; ++ ++ DBG("release ctx %d\n", ctx); ++ ++ mutex_lock(&ctx_lock); ++ ++ BUG_ON(!(ctx_map & (1 << ctx))); ++ ++ clear_bit(ctx, &ctx_map_active); ++ clear_bit(ctx, &ctx_map); ++ ++ for (rot = 0; rot < 4; ++rot) { ++ if (vrfb->paddr[rot]) { ++ release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE); ++ vrfb->paddr[rot] = 0; ++ } ++ } ++ ++ vrfb->context = 0xff; ++ ++ mutex_unlock(&ctx_lock); ++} ++EXPORT_SYMBOL(omap_vrfb_release_ctx); ++ ++int omap_vrfb_request_ctx(struct vrfb *vrfb) ++{ ++ int rot; ++ u32 paddr; ++ u8 ctx; ++ int r; ++ ++ DBG("request ctx\n"); ++ ++ mutex_lock(&ctx_lock); ++ ++ for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx) ++ if ((ctx_map & (1 << ctx)) == 0) ++ break; ++ ++ if (ctx == VRFB_NUM_CTXS) { ++ pr_err("vrfb: no free contexts\n"); ++ r = -EBUSY; ++ goto out; ++ } ++ ++ DBG("found free ctx %d\n", ctx); ++ ++ set_bit(ctx, &ctx_map); ++ WARN_ON(ctx_map_active & (1 << ctx)); ++ set_bit(ctx, &ctx_map_active); ++ ++ memset(vrfb, 0, sizeof(*vrfb)); ++ ++ vrfb->context = ctx; ++ ++ for (rot = 0; rot < 4; ++rot) { ++ paddr = SMS_ROT_VIRT_BASE(ctx, rot); ++ if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) { ++ pr_err("vrfb: failed to reserve VRFB " ++ "area for ctx %d, rotation %d\n", ++ ctx, rot * 90); ++ omap_vrfb_release_ctx(vrfb); ++ r = -ENOMEM; ++ goto out; ++ } ++ ++ vrfb->paddr[rot] = paddr; ++ ++ DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]); ++ } ++ ++ r = 0; ++out: ++ mutex_unlock(&ctx_lock); ++ return r; ++} ++EXPORT_SYMBOL(omap_vrfb_request_ctx); ++ ++void omap_vrfb_suspend_ctx(struct vrfb *vrfb) ++{ ++ DBG("suspend ctx %d\n", vrfb->context); ++ mutex_lock(&ctx_lock); ++ ++ BUG_ON(vrfb->context >= VRFB_NUM_CTXS); ++ BUG_ON(!((1 << vrfb->context) & ctx_map_active)); ++ ++ clear_bit(vrfb->context, &ctx_map_active); ++ mutex_unlock(&ctx_lock); ++} ++EXPORT_SYMBOL(omap_vrfb_suspend_ctx); ++ ++void omap_vrfb_resume_ctx(struct vrfb *vrfb) ++{ ++ DBG("resume ctx %d\n", vrfb->context); ++ mutex_lock(&ctx_lock); ++ ++ BUG_ON(vrfb->context >= VRFB_NUM_CTXS); ++ BUG_ON((1 << vrfb->context) & ctx_map_active); ++ ++ /* ++ * omap_vrfb_restore_context is normally called by the core domain ++ * save / restore logic, but since this VRFB context was suspended ++ * those calls didn't actually restore the context and now we might ++ * have an invalid context. Do an explicit restore here. ++ */ ++ restore_hw_context(vrfb->context); ++ set_bit(vrfb->context, &ctx_map_active); ++ mutex_unlock(&ctx_lock); ++} ++EXPORT_SYMBOL(omap_vrfb_resume_ctx); ++ +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0006-OMAP-DSS2-Documentation-for-DSS2.patch b/recipes/linux/linux-omap-2.6.31/dss2/0006-OMAP-DSS2-Documentation-for-DSS2.patch new file mode 100644 index 0000000000..ab159d5183 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0006-OMAP-DSS2-Documentation-for-DSS2.patch @@ -0,0 +1,337 @@ +From f7ffb36c21956befc2b8b51cf4db0e99f954ae06 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Tue, 4 Aug 2009 15:47:11 +0300 +Subject: [PATCH 06/18] OMAP: DSS2: Documentation for DSS2 + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + Documentation/arm/OMAP/DSS | 317 ++++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 317 insertions(+), 0 deletions(-) + create mode 100644 Documentation/arm/OMAP/DSS + +diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS +new file mode 100644 +index 0000000..0af0e9e +--- /dev/null ++++ b/Documentation/arm/OMAP/DSS +@@ -0,0 +1,317 @@ ++OMAP2/3 Display Subsystem ++------------------------- ++ ++This is an almost total rewrite of the OMAP FB driver in drivers/video/omap ++(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI, ++TV-out and multiple display support, but there are lots of small improvements ++also. ++ ++The DSS2 driver (omapdss module) is in arch/arm/plat-omap/dss/, and the FB, ++panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live ++currently side by side, you can choose which one to use. ++ ++Features ++-------- ++ ++Working and tested features include: ++ ++- MIPI DPI (parallel) output ++- MIPI DSI output in command mode ++- MIPI DBI (RFBI) output ++- SDI output ++- TV output ++- All pieces can be compiled as a module or inside kernel ++- Use DISPC to update any of the outputs ++- Use CPU to update RFBI or DSI output ++- OMAP DISPC planes ++- RGB16, RGB24 packed, RGB24 unpacked ++- YUV2, UYVY ++- Scaling ++- Adjusting DSS FCK to find a good pixel clock ++- Use DSI DPLL to create DSS FCK ++ ++Tested boards include: ++- OMAP3 SDP board ++- Beagle board ++- N810 ++ ++omapdss driver ++-------------- ++ ++The DSS driver does not itself have any support for Linux framebuffer, V4L or ++such like the current ones, but it has an internal kernel API that upper level ++drivers can use. ++ ++The DSS driver models OMAP's overlays, overlay managers and displays in a ++flexible way to enable non-common multi-display configuration. In addition to ++modelling the hardware overlays, omapdss supports virtual overlays and overlay ++managers. These can be used when updating a display with CPU or system DMA. ++ ++Panel and controller drivers ++---------------------------- ++ ++The drivers implement panel or controller specific functionality and are not ++usually visible to users except through omapfb driver. They register ++themselves to the DSS driver. ++ ++omapfb driver ++------------- ++ ++The omapfb driver implements arbitrary number of standard linux framebuffers. ++These framebuffers can be routed flexibly to any overlays, thus allowing very ++dynamic display architecture. ++ ++The driver exports some omapfb specific ioctls, which are compatible with the ++ioctls in the old driver. ++ ++The rest of the non standard features are exported via sysfs. Whether the final ++implementation will use sysfs, or ioctls, is still open. ++ ++V4L2 drivers ++------------ ++ ++V4L2 is being implemented in TI. ++ ++From omapdss point of view the V4L2 drivers should be similar to framebuffer ++driver. ++ ++Architecture ++-------------------- ++ ++Some clarification what the different components do: ++ ++ - Framebuffer is a memory area inside OMAP's SRAM/SDRAM that contains the ++ pixel data for the image. Framebuffer has width and height and color ++ depth. ++ - Overlay defines where the pixels are read from and where they go on the ++ screen. The overlay may be smaller than framebuffer, thus displaying only ++ part of the framebuffer. The position of the overlay may be changed if ++ the overlay is smaller than the display. ++ - Overlay manager combines the overlays in to one image and feeds them to ++ display. ++ - Display is the actual physical display device. ++ ++A framebuffer can be connected to multiple overlays to show the same pixel data ++on all of the overlays. Note that in this case the overlay input sizes must be ++the same, but, in case of video overlays, the output size can be different. Any ++framebuffer can be connected to any overlay. ++ ++An overlay can be connected to one overlay manager. Also DISPC overlays can be ++connected only to DISPC overlay managers, and virtual overlays can be only ++connected to virtual overlays. ++ ++An overlay manager can be connected to one display. There are certain ++restrictions which kinds of displays an overlay manager can be connected: ++ ++ - DISPC TV overlay manager can be only connected to TV display. ++ - Virtual overlay managers can only be connected to DBI or DSI displays. ++ - DISPC LCD overlay manager can be connected to all displays, except TV ++ display. ++ ++Sysfs ++----- ++The sysfs interface is mainly used for testing. I don't think sysfs ++interface is the best for this in the final version, but I don't quite know ++what would be the best interfaces for these things. ++ ++The sysfs interface is divided to two parts: DSS and FB. ++ ++/sys/class/graphics/fb? directory: ++mirror 0=off, 1=on ++rotate Rotation 0-3 for 0, 90, 180, 270 degrees ++rotate_type 0 = DMA rotation, 1 = VRFB rotation ++overlays List of overlay numbers to which framebuffer pixels go ++phys_addr Physical address of the framebuffer ++virt_addr Virtual address of the framebuffer ++size Size of the framebuffer ++ ++/sys/devices/platform/omapdss/overlay? directory: ++enabled 0=off, 1=on ++input_size width,height (ie. the framebuffer size) ++manager Destination overlay manager name ++name ++output_size width,height ++position x,y ++screen_width width ++global_alpha global alpha 0-255 0=transparent 255=opaque ++ ++/sys/devices/platform/omapdss/manager? directory: ++display Destination display ++name ++alpha_blending_enabled 0=off, 1=on ++trans_key_enabled 0=off, 1=on ++trans_key_type gfx-destination, video-source ++trans_key_value transparency color key (RGB24) ++default_color default background color (RGB24) ++ ++/sys/devices/platform/omapdss/display? directory: ++ctrl_name Controller name ++mirror 0=off, 1=on ++update_mode 0=off, 1=auto, 2=manual ++enabled 0=off, 1=on ++name ++rotate Rotation 0-3 for 0, 90, 180, 270 degrees ++timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw) ++ When writing, two special timings are accepted for tv-out: ++ "pal" and "ntsc" ++panel_name ++tear_elim Tearing elimination 0=off, 1=on ++ ++There are also some debugfs files at <debugfs>/omapdss/ which show information ++about clocks and registers. ++ ++Examples ++-------- ++ ++The following definitions have been made for the examples below: ++ ++ovl0=/sys/devices/platform/omapdss/overlay0 ++ovl1=/sys/devices/platform/omapdss/overlay1 ++ovl2=/sys/devices/platform/omapdss/overlay2 ++ ++mgr0=/sys/devices/platform/omapdss/manager0 ++mgr1=/sys/devices/platform/omapdss/manager1 ++ ++lcd=/sys/devices/platform/omapdss/display0 ++dvi=/sys/devices/platform/omapdss/display1 ++tv=/sys/devices/platform/omapdss/display2 ++ ++fb0=/sys/class/graphics/fb0 ++fb1=/sys/class/graphics/fb1 ++fb2=/sys/class/graphics/fb2 ++ ++Default setup on OMAP3 SDP ++-------------------------- ++ ++Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI ++and TV-out are not in use. The columns from left to right are: ++framebuffers, overlays, overlay managers, displays. Framebuffers are ++handled by omapfb, and the rest by the DSS. ++ ++FB0 --- GFX -\ DVI ++FB1 --- VID1 --+- LCD ---- LCD ++FB2 --- VID2 -/ TV ----- TV ++ ++Example: Switch from LCD to DVI ++---------------------- ++ ++w=`cat $dvi/timings | cut -d "," -f 2 | cut -d "/" -f 1` ++h=`cat $dvi/timings | cut -d "," -f 3 | cut -d "/" -f 1` ++ ++echo "0" > $lcd/enabled ++echo "" > $mgr0/display ++fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h ++# at this point you have to switch the dvi/lcd dip-switch from the omap board ++echo "dvi" > $mgr0/display ++echo "1" > $dvi/enabled ++ ++After this the configuration looks like: ++ ++FB0 --- GFX -\ -- DVI ++FB1 --- VID1 --+- LCD -/ LCD ++FB2 --- VID2 -/ TV ----- TV ++ ++Example: Clone GFX overlay to LCD and TV ++------------------------------- ++ ++w=`cat $tv/timings | cut -d "," -f 2 | cut -d "/" -f 1` ++h=`cat $tv/timings | cut -d "," -f 3 | cut -d "/" -f 1` ++ ++echo "0" > $ovl0/enabled ++echo "0" > $ovl1/enabled ++ ++echo "" > $fb1/overlays ++echo "0,1" > $fb0/overlays ++ ++echo "$w,$h" > $ovl1/output_size ++echo "tv" > $ovl1/manager ++ ++echo "1" > $ovl0/enabled ++echo "1" > $ovl1/enabled ++ ++echo "1" > $tv/enabled ++ ++After this the configuration looks like (only relevant parts shown): ++ ++FB0 +-- GFX ---- LCD ---- LCD ++ \- VID1 ---- TV ---- TV ++ ++Misc notes ++---------- ++ ++OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator. ++ ++Using DSI DPLL to generate pixel clock it is possible produce the pixel clock ++of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI. ++ ++Rotation and mirroring currently only supports RGB565 and RGB8888 modes. VRFB ++does not support mirroring. ++ ++VRFB rotation requires much more memory than non-rotated framebuffer, so you ++probably need to increase your vram setting before using VRFB rotation. Also, ++many applications may not work with VRFB if they do not pay attention to all ++framebuffer parameters. ++ ++Kernel boot arguments ++--------------------- ++ ++vram=<size> ++ - Amount of total VRAM to preallocate. For example, "10M". omapfb ++ allocates memory for framebuffers from VRAM. ++ ++omapfb.mode=<display>:<mode>[,...] ++ - Default video mode for specified displays. For example, ++ "dvi:800x400MR-24@60". See drivers/video/modedb.c. ++ There are also two special modes: "pal" and "ntsc" that ++ can be used to tv out. ++ ++omapfb.vram=<fbnum>:<size>[@<physaddr>][,...] ++ - VRAM allocated for a framebuffer. Normally omapfb allocates vram ++ depending on the display size. With this you can manually allocate ++ more or define the physical address of each framebuffer. For example, ++ "1:4M" to allocate 4M for fb1. ++ ++omapfb.debug=<y|n> ++ - Enable debug printing. You have to have OMAPFB debug support enabled ++ in kernel config. ++ ++omapfb.test=<y|n> ++ - Draw test pattern to framebuffer whenever framebuffer settings change. ++ You need to have OMAPFB debug support enabled in kernel config. ++ ++omapfb.vrfb=<y|n> ++ - Use VRFB rotation for all framebuffers. ++ ++omapfb.rotate=<angle> ++ - Default rotation applied to all framebuffers. ++ 0 - 0 degree rotation ++ 1 - 90 degree rotation ++ 2 - 180 degree rotation ++ 3 - 270 degree rotation ++ ++omapfb.mirror=<y|n> ++ - Default mirror for all framebuffers. Only works with DMA rotation. ++ ++omapdss.def_disp=<display> ++ - Name of default display, to which all overlays will be connected. ++ Common examples are "lcd" or "tv". ++ ++omapdss.debug=<y|n> ++ - Enable debug printing. You have to have DSS debug support enabled in ++ kernel config. ++ ++TODO ++---- ++ ++DSS locking ++ ++Error checking ++- Lots of checks are missing or implemented just as BUG() ++ ++System DMA update for DSI ++- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how ++ to skip the empty byte?) ++ ++OMAP1 support ++- Not sure if needed ++ +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0007-OMAP-DSS2-Display-Subsystem-Driver-core.patch b/recipes/linux/linux-omap-2.6.31/dss2/0007-OMAP-DSS2-Display-Subsystem-Driver-core.patch new file mode 100644 index 0000000000..8692200e02 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0007-OMAP-DSS2-Display-Subsystem-Driver-core.patch @@ -0,0 +1,2341 @@ +From 17254fca49c4f3a8897a6afb10af3416a691cb8a Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Fri, 7 Aug 2009 13:42:34 +0300 +Subject: [PATCH 07/18] OMAP: DSS2: Display Subsystem Driver core + +The core files of DSS2. DSS2 commits are split a bit artificially to +make the individual commits smaller, and DSS2 doesn't compile properly +without the rest of the core commits. This shouldn't be a problem, as no +configuration uses DSS2 yet. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + arch/arm/plat-omap/include/mach/display.h | 540 +++++++++++++++++ + drivers/video/omap2/Kconfig | 2 + + drivers/video/omap2/Makefile | 2 + + drivers/video/omap2/dss/Kconfig | 89 +++ + drivers/video/omap2/dss/Makefile | 6 + + drivers/video/omap2/dss/core.c | 917 +++++++++++++++++++++++++++++ + drivers/video/omap2/dss/dss.c | 347 +++++++++++ + drivers/video/omap2/dss/dss.h | 356 +++++++++++ + 8 files changed, 2259 insertions(+), 0 deletions(-) + create mode 100644 arch/arm/plat-omap/include/mach/display.h + create mode 100644 drivers/video/omap2/dss/Kconfig + create mode 100644 drivers/video/omap2/dss/Makefile + create mode 100644 drivers/video/omap2/dss/core.c + create mode 100644 drivers/video/omap2/dss/dss.c + create mode 100644 drivers/video/omap2/dss/dss.h + +diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h +new file mode 100644 +index 0000000..4c7422e +--- /dev/null ++++ b/arch/arm/plat-omap/include/mach/display.h +@@ -0,0 +1,540 @@ ++/* ++ * linux/include/asm-arm/arch-omap/display.h ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#ifndef __ASM_ARCH_OMAP_DISPLAY_H ++#define __ASM_ARCH_OMAP_DISPLAY_H ++ ++#include <linux/list.h> ++#include <linux/kobject.h> ++#include <linux/device.h> ++#include <asm/atomic.h> ++ ++#define DISPC_IRQ_FRAMEDONE (1 << 0) ++#define DISPC_IRQ_VSYNC (1 << 1) ++#define DISPC_IRQ_EVSYNC_EVEN (1 << 2) ++#define DISPC_IRQ_EVSYNC_ODD (1 << 3) ++#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4) ++#define DISPC_IRQ_PROG_LINE_NUM (1 << 5) ++#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6) ++#define DISPC_IRQ_GFX_END_WIN (1 << 7) ++#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8) ++#define DISPC_IRQ_OCP_ERR (1 << 9) ++#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10) ++#define DISPC_IRQ_VID1_END_WIN (1 << 11) ++#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12) ++#define DISPC_IRQ_VID2_END_WIN (1 << 13) ++#define DISPC_IRQ_SYNC_LOST (1 << 14) ++#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15) ++#define DISPC_IRQ_WAKEUP (1 << 16) ++ ++struct omap_dss_device; ++struct omap_overlay_manager; ++ ++enum omap_display_type { ++ OMAP_DISPLAY_TYPE_NONE = 0, ++ OMAP_DISPLAY_TYPE_DPI = 1 << 0, ++ OMAP_DISPLAY_TYPE_DBI = 1 << 1, ++ OMAP_DISPLAY_TYPE_SDI = 1 << 2, ++ OMAP_DISPLAY_TYPE_DSI = 1 << 3, ++ OMAP_DISPLAY_TYPE_VENC = 1 << 4, ++}; ++ ++enum omap_plane { ++ OMAP_DSS_GFX = 0, ++ OMAP_DSS_VIDEO1 = 1, ++ OMAP_DSS_VIDEO2 = 2 ++}; ++ ++enum omap_channel { ++ OMAP_DSS_CHANNEL_LCD = 0, ++ OMAP_DSS_CHANNEL_DIGIT = 1, ++}; ++ ++enum omap_color_mode { ++ OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */ ++ OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */ ++ OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */ ++ OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */ ++ OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */ ++ OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */ ++ OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */ ++ OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */ ++ OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */ ++ OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */ ++ OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */ ++ OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */ ++ OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */ ++ OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */ ++ ++ OMAP_DSS_COLOR_GFX_OMAP3 = ++ OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | ++ OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 | ++ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | ++ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | ++ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | ++ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, ++ ++ OMAP_DSS_COLOR_VID_OMAP3 = ++ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | ++ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | ++ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | ++ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 | ++ OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY, ++}; ++ ++enum omap_lcd_display_type { ++ OMAP_DSS_LCD_DISPLAY_STN, ++ OMAP_DSS_LCD_DISPLAY_TFT, ++}; ++ ++enum omap_dss_load_mode { ++ OMAP_DSS_LOAD_CLUT_AND_FRAME = 0, ++ OMAP_DSS_LOAD_CLUT_ONLY = 1, ++ OMAP_DSS_LOAD_FRAME_ONLY = 2, ++ OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3, ++}; ++ ++enum omap_dss_trans_key_type { ++ OMAP_DSS_COLOR_KEY_GFX_DST = 0, ++ OMAP_DSS_COLOR_KEY_VID_SRC = 1, ++}; ++ ++enum omap_rfbi_te_mode { ++ OMAP_DSS_RFBI_TE_MODE_1 = 1, ++ OMAP_DSS_RFBI_TE_MODE_2 = 2, ++}; ++ ++enum omap_panel_config { ++ OMAP_DSS_LCD_IVS = 1<<0, ++ OMAP_DSS_LCD_IHS = 1<<1, ++ OMAP_DSS_LCD_IPC = 1<<2, ++ OMAP_DSS_LCD_IEO = 1<<3, ++ OMAP_DSS_LCD_RF = 1<<4, ++ OMAP_DSS_LCD_ONOFF = 1<<5, ++ ++ OMAP_DSS_LCD_TFT = 1<<20, ++}; ++ ++enum omap_dss_venc_type { ++ OMAP_DSS_VENC_TYPE_COMPOSITE, ++ OMAP_DSS_VENC_TYPE_SVIDEO, ++}; ++ ++enum omap_display_caps { ++ OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0, ++}; ++ ++enum omap_dss_update_mode { ++ OMAP_DSS_UPDATE_DISABLED = 0, ++ OMAP_DSS_UPDATE_AUTO, ++ OMAP_DSS_UPDATE_MANUAL, ++}; ++ ++enum omap_dss_display_state { ++ OMAP_DSS_DISPLAY_DISABLED = 0, ++ OMAP_DSS_DISPLAY_ACTIVE, ++ OMAP_DSS_DISPLAY_SUSPENDED, ++}; ++ ++/* XXX perhaps this should be removed */ ++enum omap_dss_overlay_managers { ++ OMAP_DSS_OVL_MGR_LCD, ++ OMAP_DSS_OVL_MGR_TV, ++}; ++ ++enum omap_dss_rotation_type { ++ OMAP_DSS_ROT_DMA = 0, ++ OMAP_DSS_ROT_VRFB = 1, ++}; ++ ++enum omap_overlay_caps { ++ OMAP_DSS_OVL_CAP_SCALE = 1 << 0, ++ OMAP_DSS_OVL_CAP_DISPC = 1 << 1, ++}; ++ ++enum omap_overlay_manager_caps { ++ OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0, ++}; ++ ++/* RFBI */ ++ ++struct rfbi_timings { ++ int cs_on_time; ++ int cs_off_time; ++ int we_on_time; ++ int we_off_time; ++ int re_on_time; ++ int re_off_time; ++ int we_cycle_time; ++ int re_cycle_time; ++ int cs_pulse_width; ++ int access_time; ++ ++ int clk_div; ++ ++ u32 tim[5]; /* set by rfbi_convert_timings() */ ++ ++ int converted; ++}; ++ ++void omap_rfbi_write_command(const void *buf, u32 len); ++void omap_rfbi_read_data(void *buf, u32 len); ++void omap_rfbi_write_data(const void *buf, u32 len); ++void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, ++ u16 x, u16 y, ++ u16 w, u16 h); ++int omap_rfbi_enable_te(bool enable, unsigned line); ++int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, ++ unsigned hs_pulse_time, unsigned vs_pulse_time, ++ int hs_pol_inv, int vs_pol_inv, int extif_div); ++ ++/* DSI */ ++void dsi_bus_lock(void); ++void dsi_bus_unlock(void); ++int dsi_vc_dcs_write(int channel, u8 *data, int len); ++int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len); ++int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen); ++int dsi_vc_set_max_rx_packet_size(int channel, u16 len); ++int dsi_vc_send_null(int channel); ++int dsi_vc_send_bta_sync(int channel); ++ ++/* Board specific data */ ++struct omap_dss_board_info { ++ int (*get_last_off_on_transaction_id)(struct device *dev); ++ int num_devices; ++ struct omap_dss_device **devices; ++ struct omap_dss_device *default_device; ++}; ++ ++struct omap_video_timings { ++ /* Unit: pixels */ ++ u16 x_res; ++ /* Unit: pixels */ ++ u16 y_res; ++ /* Unit: KHz */ ++ u32 pixel_clock; ++ /* Unit: pixel clocks */ ++ u16 hsw; /* Horizontal synchronization pulse width */ ++ /* Unit: pixel clocks */ ++ u16 hfp; /* Horizontal front porch */ ++ /* Unit: pixel clocks */ ++ u16 hbp; /* Horizontal back porch */ ++ /* Unit: line clocks */ ++ u16 vsw; /* Vertical synchronization pulse width */ ++ /* Unit: line clocks */ ++ u16 vfp; /* Vertical front porch */ ++ /* Unit: line clocks */ ++ u16 vbp; /* Vertical back porch */ ++}; ++ ++#ifdef CONFIG_OMAP2_DSS_VENC ++/* Hardcoded timings for tv modes. Venc only uses these to ++ * identify the mode, and does not actually use the configs ++ * itself. However, the configs should be something that ++ * a normal monitor can also show */ ++const extern struct omap_video_timings omap_dss_pal_timings; ++const extern struct omap_video_timings omap_dss_ntsc_timings; ++#endif ++ ++struct omap_overlay_info { ++ bool enabled; ++ ++ u32 paddr; ++ void __iomem *vaddr; ++ u16 screen_width; ++ u16 width; ++ u16 height; ++ enum omap_color_mode color_mode; ++ u8 rotation; ++ enum omap_dss_rotation_type rotation_type; ++ bool mirror; ++ ++ u16 pos_x; ++ u16 pos_y; ++ u16 out_width; /* if 0, out_width == width */ ++ u16 out_height; /* if 0, out_height == height */ ++ u8 global_alpha; ++}; ++ ++struct omap_overlay { ++ struct kobject kobj; ++ struct list_head list; ++ ++ /* static fields */ ++ const char *name; ++ int id; ++ enum omap_color_mode supported_modes; ++ enum omap_overlay_caps caps; ++ ++ /* dynamic fields */ ++ struct omap_overlay_manager *manager; ++ struct omap_overlay_info info; ++ ++ /* if true, info has been changed, but not applied() yet */ ++ bool info_dirty; ++ ++ int (*set_manager)(struct omap_overlay *ovl, ++ struct omap_overlay_manager *mgr); ++ int (*unset_manager)(struct omap_overlay *ovl); ++ ++ int (*set_overlay_info)(struct omap_overlay *ovl, ++ struct omap_overlay_info *info); ++ void (*get_overlay_info)(struct omap_overlay *ovl, ++ struct omap_overlay_info *info); ++ ++ int (*wait_for_go)(struct omap_overlay *ovl); ++}; ++ ++struct omap_overlay_manager_info { ++ u32 default_color; ++ ++ enum omap_dss_trans_key_type trans_key_type; ++ u32 trans_key; ++ bool trans_enabled; ++ ++ bool alpha_enabled; ++}; ++ ++struct omap_overlay_manager { ++ struct kobject kobj; ++ struct list_head list; ++ ++ /* static fields */ ++ const char *name; ++ int id; ++ enum omap_overlay_manager_caps caps; ++ int num_overlays; ++ struct omap_overlay **overlays; ++ enum omap_display_type supported_displays; ++ ++ /* dynamic fields */ ++ struct omap_dss_device *device; ++ struct omap_overlay_manager_info info; ++ ++ bool device_changed; ++ /* if true, info has been changed but not applied() yet */ ++ bool info_dirty; ++ ++ int (*set_device)(struct omap_overlay_manager *mgr, ++ struct omap_dss_device *dssdev); ++ int (*unset_device)(struct omap_overlay_manager *mgr); ++ ++ int (*set_manager_info)(struct omap_overlay_manager *mgr, ++ struct omap_overlay_manager_info *info); ++ void (*get_manager_info)(struct omap_overlay_manager *mgr, ++ struct omap_overlay_manager_info *info); ++ ++ int (*apply)(struct omap_overlay_manager *mgr); ++ int (*wait_for_go)(struct omap_overlay_manager *mgr); ++}; ++ ++struct omap_dss_device { ++ struct device dev; ++ ++ enum omap_display_type type; ++ ++ union { ++ struct { ++ u8 data_lines; ++ } dpi; ++ ++ struct { ++ u8 channel; ++ u8 data_lines; ++ } rfbi; ++ ++ struct { ++ u8 datapairs; ++ } sdi; ++ ++ struct { ++ u8 clk_lane; ++ u8 clk_pol; ++ u8 data1_lane; ++ u8 data1_pol; ++ u8 data2_lane; ++ u8 data2_pol; ++ unsigned long lp_clk_hz; ++ unsigned long ddr_clk_hz; ++ ++ bool ext_te; ++ u8 ext_te_gpio; ++ } dsi; ++ ++ struct { ++ enum omap_dss_venc_type type; ++ bool invert_polarity; ++ } venc; ++ } phy; ++ ++ struct { ++ struct omap_video_timings timings; ++ ++ int acbi; /* ac-bias pin transitions per interrupt */ ++ /* Unit: line clocks */ ++ int acb; /* ac-bias pin frequency */ ++ ++ enum omap_panel_config config; ++ ++ u8 recommended_bpp; ++ ++ struct omap_dss_device *ctrl; ++ } panel; ++ ++ struct { ++ u8 pixel_size; ++ struct rfbi_timings rfbi_timings; ++ struct omap_dss_device *panel; ++ } ctrl; ++ ++ int reset_gpio; ++ ++ int max_backlight_level; ++ ++ const char *name; ++ ++ /* used to match device to driver */ ++ const char *driver_name; ++ ++ void *data; ++ ++ struct omap_dss_driver *driver; ++ ++ /* helper variable for driver suspend/resume */ ++ bool activate_after_resume; ++ ++ enum omap_display_caps caps; ++ ++ struct omap_overlay_manager *manager; ++ ++ enum omap_dss_display_state state; ++ ++ int (*enable)(struct omap_dss_device *dssdev); ++ void (*disable)(struct omap_dss_device *dssdev); ++ ++ int (*suspend)(struct omap_dss_device *dssdev); ++ int (*resume)(struct omap_dss_device *dssdev); ++ ++ void (*get_resolution)(struct omap_dss_device *dssdev, ++ u16 *xres, u16 *yres); ++ int (*get_recommended_bpp)(struct omap_dss_device *dssdev); ++ ++ int (*check_timings)(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings); ++ void (*set_timings)(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings); ++ void (*get_timings)(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings); ++ int (*update)(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h); ++ int (*sync)(struct omap_dss_device *dssdev); ++ int (*wait_vsync)(struct omap_dss_device *dssdev); ++ ++ int (*set_update_mode)(struct omap_dss_device *dssdev, ++ enum omap_dss_update_mode); ++ enum omap_dss_update_mode (*get_update_mode) ++ (struct omap_dss_device *dssdev); ++ ++ int (*enable_te)(struct omap_dss_device *dssdev, bool enable); ++ int (*get_te)(struct omap_dss_device *dssdev); ++ ++ u8 (*get_rotate)(struct omap_dss_device *dssdev); ++ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate); ++ ++ bool (*get_mirror)(struct omap_dss_device *dssdev); ++ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable); ++ ++ int (*run_test)(struct omap_dss_device *dssdev, int test); ++ int (*memory_read)(struct omap_dss_device *dssdev, ++ void *buf, size_t size, ++ u16 x, u16 y, u16 w, u16 h); ++ ++ int (*set_wss)(struct omap_dss_device *dssdev, u32 wss); ++ u32 (*get_wss)(struct omap_dss_device *dssdev); ++ ++ /* platform specific */ ++ int (*platform_enable)(struct omap_dss_device *dssdev); ++ void (*platform_disable)(struct omap_dss_device *dssdev); ++ int (*set_backlight)(struct omap_dss_device *dssdev, int level); ++ int (*get_backlight)(struct omap_dss_device *dssdev); ++}; ++ ++struct omap_dss_driver { ++ struct device_driver driver; ++ ++ int (*probe)(struct omap_dss_device *); ++ void (*remove)(struct omap_dss_device *); ++ ++ int (*enable)(struct omap_dss_device *display); ++ void (*disable)(struct omap_dss_device *display); ++ int (*suspend)(struct omap_dss_device *display); ++ int (*resume)(struct omap_dss_device *display); ++ int (*run_test)(struct omap_dss_device *display, int test); ++ ++ void (*setup_update)(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h); ++ ++ int (*enable_te)(struct omap_dss_device *dssdev, bool enable); ++ int (*wait_for_te)(struct omap_dss_device *dssdev); ++ ++ u8 (*get_rotate)(struct omap_dss_device *dssdev); ++ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate); ++ ++ bool (*get_mirror)(struct omap_dss_device *dssdev); ++ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable); ++ ++ int (*memory_read)(struct omap_dss_device *dssdev, ++ void *buf, size_t size, ++ u16 x, u16 y, u16 w, u16 h); ++}; ++ ++int omap_dss_register_driver(struct omap_dss_driver *); ++void omap_dss_unregister_driver(struct omap_dss_driver *); ++ ++int omap_dss_register_device(struct omap_dss_device *); ++void omap_dss_unregister_device(struct omap_dss_device *); ++ ++void omap_dss_get_device(struct omap_dss_device *dssdev); ++void omap_dss_put_device(struct omap_dss_device *dssdev); ++#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL) ++struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from); ++struct omap_dss_device *omap_dss_find_device(void *data, ++ int (*match)(struct omap_dss_device *dssdev, void *data)); ++ ++int omap_dss_start_device(struct omap_dss_device *dssdev); ++void omap_dss_stop_device(struct omap_dss_device *dssdev); ++ ++int omap_dss_get_num_overlay_managers(void); ++struct omap_overlay_manager *omap_dss_get_overlay_manager(int num); ++ ++int omap_dss_get_num_overlays(void); ++struct omap_overlay *omap_dss_get_overlay(int num); ++ ++typedef void (*omap_dispc_isr_t) (void *arg, u32 mask); ++int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); ++int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask); ++ ++int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout); ++int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, ++ unsigned long timeout); ++ ++#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver) ++#define to_dss_device(x) container_of((x), struct omap_dss_device, dev) ++ ++#endif +diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig +index ac8b650..55b4c42 100644 +--- a/drivers/video/omap2/Kconfig ++++ b/drivers/video/omap2/Kconfig +@@ -3,3 +3,5 @@ config OMAP2_VRAM + + config OMAP2_VRFB + bool ++ ++source "drivers/video/omap2/dss/Kconfig" +diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile +index aa3751b..ee0644f 100644 +--- a/drivers/video/omap2/Makefile ++++ b/drivers/video/omap2/Makefile +@@ -1,2 +1,4 @@ + obj-$(CONFIG_OMAP2_VRAM) += vram.o + obj-$(CONFIG_OMAP2_VRFB) += vrfb.o ++ ++obj-y += dss/ +diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig +new file mode 100644 +index 0000000..71d8dec +--- /dev/null ++++ b/drivers/video/omap2/dss/Kconfig +@@ -0,0 +1,89 @@ ++menuconfig OMAP2_DSS ++ tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" ++ depends on ARCH_OMAP2 || ARCH_OMAP3 ++ help ++ OMAP2/3 Display Subsystem support. ++ ++if OMAP2_DSS ++ ++config OMAP2_VRAM_SIZE ++ int "VRAM size (MB)" ++ range 0 32 ++ default 0 ++ help ++ The amount of SDRAM to reserve at boot time for video RAM use. ++ This VRAM will be used by omapfb and other drivers that need ++ large continuous RAM area for video use. ++ ++ You can also set this with "vram=<bytes>" kernel argument, or ++ in the board file. ++ ++config OMAP2_DSS_DEBUG_SUPPORT ++ bool "Debug support" ++ default y ++ help ++ This enables debug messages. You need to enable printing ++ with 'debug' module parameter. ++ ++config OMAP2_DSS_RFBI ++ bool "RFBI support" ++ default n ++ help ++ MIPI DBI, or RFBI (Remote Framebuffer Interface), support. ++ ++config OMAP2_DSS_VENC ++ bool "VENC support" ++ default y ++ help ++ OMAP Video Encoder support. ++ ++config OMAP2_DSS_SDI ++ bool "SDI support" ++ depends on ARCH_OMAP3 ++ default n ++ help ++ SDI (Serial Display Interface) support. ++ ++config OMAP2_DSS_DSI ++ bool "DSI support" ++ depends on ARCH_OMAP3 ++ default n ++ help ++ MIPI DSI support. ++ ++config OMAP2_DSS_USE_DSI_PLL ++ bool "Use DSI PLL for PCLK (EXPERIMENTAL)" ++ default n ++ depends on OMAP2_DSS_DSI ++ help ++ Use DSI PLL to generate pixel clock. Currently only for DPI output. ++ DSI PLL can be used to generate higher and more precise pixel clocks. ++ ++config OMAP2_DSS_FAKE_VSYNC ++ bool "Fake VSYNC irq from manual update displays" ++ default n ++ help ++ If this is selected, DSI will generate a fake DISPC VSYNC interrupt ++ when DSI has sent a frame. This is only needed with DSI or RFBI ++ displays using manual mode, and you want VSYNC to, for example, ++ time animation. ++ ++config OMAP2_DSS_MIN_FCK_PER_PCK ++ int "Minimum FCK/PCK ratio (for scaling)" ++ range 0 32 ++ default 0 ++ help ++ This can be used to adjust the minimum FCK/PCK ratio. ++ ++ With this you can make sure that DISPC FCK is at least ++ n x PCK. Video plane scaling requires higher FCK than ++ normally. ++ ++ If this is set to 0, there's no extra constraint on the ++ DISPC FCK. However, the FCK will at minimum be ++ 2xPCK (if active matrix) or 3xPCK (if passive matrix). ++ ++ Max FCK is 173MHz, so this doesn't work if your PCK ++ is very high. ++ ++endif +diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile +new file mode 100644 +index 0000000..980c72c +--- /dev/null ++++ b/drivers/video/omap2/dss/Makefile +@@ -0,0 +1,6 @@ ++obj-$(CONFIG_OMAP2_DSS) += omapdss.o ++omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o ++omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o ++omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o ++omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o ++omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o +diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c +new file mode 100644 +index 0000000..e8d430c +--- /dev/null ++++ b/drivers/video/omap2/dss/core.c +@@ -0,0 +1,917 @@ ++/* ++ * linux/drivers/video/omap2/dss/core.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "CORE" ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/platform_device.h> ++#include <linux/seq_file.h> ++#include <linux/debugfs.h> ++#include <linux/io.h> ++#include <linux/device.h> ++ ++#include <mach/display.h> ++#include <mach/clock.h> ++ ++#include "dss.h" ++ ++static struct { ++ struct platform_device *pdev; ++ int ctx_id; ++ ++ struct clk *dss_ick; ++ struct clk *dss1_fck; ++ struct clk *dss2_fck; ++ struct clk *dss_54m_fck; ++ struct clk *dss_96m_fck; ++ unsigned num_clks_enabled; ++} core; ++ ++static void dss_clk_enable_all_no_ctx(void); ++static void dss_clk_disable_all_no_ctx(void); ++static void dss_clk_enable_no_ctx(enum dss_clock clks); ++static void dss_clk_disable_no_ctx(enum dss_clock clks); ++ ++static char *def_disp_name; ++module_param_named(def_disp, def_disp_name, charp, 0); ++MODULE_PARM_DESC(def_disp_name, "default display name"); ++ ++#ifdef DEBUG ++unsigned int dss_debug; ++module_param_named(debug, dss_debug, bool, 0644); ++#endif ++ ++/* CONTEXT */ ++static int dss_get_ctx_id(void) ++{ ++ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; ++ int r; ++ ++ if (!pdata->get_last_off_on_transaction_id) ++ return 0; ++ r = pdata->get_last_off_on_transaction_id(&core.pdev->dev); ++ if (r < 0) { ++ dev_err(&core.pdev->dev, "getting transaction ID failed, " ++ "will force context restore\n"); ++ r = -1; ++ } ++ return r; ++} ++ ++int dss_need_ctx_restore(void) ++{ ++ int id = dss_get_ctx_id(); ++ ++ if (id < 0 || id != core.ctx_id) { ++ DSSDBG("ctx id %d -> id %d\n", ++ core.ctx_id, id); ++ core.ctx_id = id; ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++static void save_all_ctx(void) ++{ ++ DSSDBG("save context\n"); ++ ++ dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dss_save_context(); ++ dispc_save_context(); ++#ifdef CONFIG_OMAP2_DSS_DSI ++ dsi_save_context(); ++#endif ++ ++ dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); ++} ++ ++static void restore_all_ctx(void) ++{ ++ DSSDBG("restore context\n"); ++ ++ dss_clk_enable_all_no_ctx(); ++ ++ dss_restore_context(); ++ dispc_restore_context(); ++#ifdef CONFIG_OMAP2_DSS_DSI ++ dsi_restore_context(); ++#endif ++ ++ dss_clk_disable_all_no_ctx(); ++} ++ ++/* CLOCKS */ ++void dss_dump_clocks(struct seq_file *s) ++{ ++ int i; ++ struct clk *clocks[5] = { ++ core.dss_ick, ++ core.dss1_fck, ++ core.dss2_fck, ++ core.dss_54m_fck, ++ core.dss_96m_fck ++ }; ++ ++ seq_printf(s, "- dss -\n"); ++ ++ seq_printf(s, "internal clk count\t%u\n", core.num_clks_enabled); ++ ++ for (i = 0; i < 5; i++) { ++ if (!clocks[i]) ++ continue; ++ seq_printf(s, "%-15s\t%lu\t%d\n", ++ clocks[i]->name, ++ clk_get_rate(clocks[i]), ++ clocks[i]->usecount); ++ } ++} ++ ++static int dss_get_clock(struct clk **clock, const char *clk_name) ++{ ++ struct clk *clk; ++ ++ clk = clk_get(&core.pdev->dev, clk_name); ++ ++ if (IS_ERR(clk)) { ++ DSSERR("can't get clock %s", clk_name); ++ return PTR_ERR(clk); ++ } ++ ++ *clock = clk; ++ ++ DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); ++ ++ return 0; ++} ++ ++static int dss_get_clocks(void) ++{ ++ int r; ++ ++ core.dss_ick = NULL; ++ core.dss1_fck = NULL; ++ core.dss2_fck = NULL; ++ core.dss_54m_fck = NULL; ++ core.dss_96m_fck = NULL; ++ ++ r = dss_get_clock(&core.dss_ick, "ick"); ++ if (r) ++ goto err; ++ ++ r = dss_get_clock(&core.dss1_fck, "dss1_fck"); ++ if (r) ++ goto err; ++ ++ r = dss_get_clock(&core.dss2_fck, "dss2_fck"); ++ if (r) ++ goto err; ++ ++ r = dss_get_clock(&core.dss_54m_fck, "tv_fck"); ++ if (r) ++ goto err; ++ ++ r = dss_get_clock(&core.dss_96m_fck, "video_fck"); ++ if (r) ++ goto err; ++ ++ return 0; ++ ++err: ++ if (core.dss_ick) ++ clk_put(core.dss_ick); ++ if (core.dss1_fck) ++ clk_put(core.dss1_fck); ++ if (core.dss2_fck) ++ clk_put(core.dss2_fck); ++ if (core.dss_54m_fck) ++ clk_put(core.dss_54m_fck); ++ if (core.dss_96m_fck) ++ clk_put(core.dss_96m_fck); ++ ++ return r; ++} ++ ++static void dss_put_clocks(void) ++{ ++ if (core.dss_96m_fck) ++ clk_put(core.dss_96m_fck); ++ clk_put(core.dss_54m_fck); ++ clk_put(core.dss1_fck); ++ clk_put(core.dss2_fck); ++ clk_put(core.dss_ick); ++} ++ ++unsigned long dss_clk_get_rate(enum dss_clock clk) ++{ ++ switch (clk) { ++ case DSS_CLK_ICK: ++ return clk_get_rate(core.dss_ick); ++ case DSS_CLK_FCK1: ++ return clk_get_rate(core.dss1_fck); ++ case DSS_CLK_FCK2: ++ return clk_get_rate(core.dss2_fck); ++ case DSS_CLK_54M: ++ return clk_get_rate(core.dss_54m_fck); ++ case DSS_CLK_96M: ++ return clk_get_rate(core.dss_96m_fck); ++ } ++ ++ BUG(); ++ return 0; ++} ++ ++static unsigned count_clk_bits(enum dss_clock clks) ++{ ++ unsigned num_clks = 0; ++ ++ if (clks & DSS_CLK_ICK) ++ ++num_clks; ++ if (clks & DSS_CLK_FCK1) ++ ++num_clks; ++ if (clks & DSS_CLK_FCK2) ++ ++num_clks; ++ if (clks & DSS_CLK_54M) ++ ++num_clks; ++ if (clks & DSS_CLK_96M) ++ ++num_clks; ++ ++ return num_clks; ++} ++ ++static void dss_clk_enable_no_ctx(enum dss_clock clks) ++{ ++ unsigned num_clks = count_clk_bits(clks); ++ ++ if (clks & DSS_CLK_ICK) ++ clk_enable(core.dss_ick); ++ if (clks & DSS_CLK_FCK1) ++ clk_enable(core.dss1_fck); ++ if (clks & DSS_CLK_FCK2) ++ clk_enable(core.dss2_fck); ++ if (clks & DSS_CLK_54M) ++ clk_enable(core.dss_54m_fck); ++ if (clks & DSS_CLK_96M) ++ clk_enable(core.dss_96m_fck); ++ ++ core.num_clks_enabled += num_clks; ++} ++ ++void dss_clk_enable(enum dss_clock clks) ++{ ++ dss_clk_enable_no_ctx(clks); ++ ++ if (cpu_is_omap34xx() && dss_need_ctx_restore()) ++ restore_all_ctx(); ++} ++ ++static void dss_clk_disable_no_ctx(enum dss_clock clks) ++{ ++ unsigned num_clks = count_clk_bits(clks); ++ ++ if (clks & DSS_CLK_ICK) ++ clk_disable(core.dss_ick); ++ if (clks & DSS_CLK_FCK1) ++ clk_disable(core.dss1_fck); ++ if (clks & DSS_CLK_FCK2) ++ clk_disable(core.dss2_fck); ++ if (clks & DSS_CLK_54M) ++ clk_disable(core.dss_54m_fck); ++ if (clks & DSS_CLK_96M) ++ clk_disable(core.dss_96m_fck); ++ ++ core.num_clks_enabled -= num_clks; ++} ++ ++void dss_clk_disable(enum dss_clock clks) ++{ ++ if (cpu_is_omap34xx()) { ++ unsigned num_clks = count_clk_bits(clks); ++ ++ BUG_ON(core.num_clks_enabled < num_clks); ++ ++ if (core.num_clks_enabled == num_clks) ++ save_all_ctx(); ++ } ++ ++ dss_clk_disable_no_ctx(clks); ++} ++ ++static void dss_clk_enable_all_no_ctx(void) ++{ ++ enum dss_clock clks; ++ ++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; ++ if (cpu_is_omap34xx()) ++ clks |= DSS_CLK_96M; ++ dss_clk_enable_no_ctx(clks); ++} ++ ++static void dss_clk_disable_all_no_ctx(void) ++{ ++ enum dss_clock clks; ++ ++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; ++ if (cpu_is_omap34xx()) ++ clks |= DSS_CLK_96M; ++ dss_clk_disable_no_ctx(clks); ++} ++ ++static void dss_clk_disable_all(void) ++{ ++ enum dss_clock clks; ++ ++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; ++ if (cpu_is_omap34xx()) ++ clks |= DSS_CLK_96M; ++ dss_clk_disable(clks); ++} ++ ++/* DEBUGFS */ ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) ++static void dss_debug_dump_clocks(struct seq_file *s) ++{ ++ dss_dump_clocks(s); ++ dispc_dump_clocks(s); ++#ifdef CONFIG_OMAP2_DSS_DSI ++ dsi_dump_clocks(s); ++#endif ++} ++ ++static int dss_debug_show(struct seq_file *s, void *unused) ++{ ++ void (*func)(struct seq_file *) = s->private; ++ func(s); ++ return 0; ++} ++ ++static int dss_debug_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, dss_debug_show, inode->i_private); ++} ++ ++static const struct file_operations dss_debug_fops = { ++ .open = dss_debug_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static struct dentry *dss_debugfs_dir; ++ ++static int dss_initialize_debugfs(void) ++{ ++ dss_debugfs_dir = debugfs_create_dir("omapdss", NULL); ++ if (IS_ERR(dss_debugfs_dir)) { ++ int err = PTR_ERR(dss_debugfs_dir); ++ dss_debugfs_dir = NULL; ++ return err; ++ } ++ ++ debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, ++ &dss_debug_dump_clocks, &dss_debug_fops); ++ ++ debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, ++ &dss_dump_regs, &dss_debug_fops); ++ debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir, ++ &dispc_dump_regs, &dss_debug_fops); ++#ifdef CONFIG_OMAP2_DSS_RFBI ++ debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir, ++ &rfbi_dump_regs, &dss_debug_fops); ++#endif ++#ifdef CONFIG_OMAP2_DSS_DSI ++ debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir, ++ &dsi_dump_regs, &dss_debug_fops); ++#endif ++#ifdef CONFIG_OMAP2_DSS_VENC ++ debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, ++ &venc_dump_regs, &dss_debug_fops); ++#endif ++ return 0; ++} ++ ++static void dss_uninitialize_debugfs(void) ++{ ++ if (dss_debugfs_dir) ++ debugfs_remove_recursive(dss_debugfs_dir); ++} ++#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ ++ ++/* PLATFORM DEVICE */ ++static int omap_dss_probe(struct platform_device *pdev) ++{ ++ struct omap_dss_board_info *pdata = pdev->dev.platform_data; ++ int skip_init = 0; ++ int r; ++ int i; ++ ++ core.pdev = pdev; ++ ++ dss_init_overlay_managers(pdev); ++ dss_init_overlays(pdev); ++ ++ r = dss_get_clocks(); ++ if (r) ++ goto fail0; ++ ++ dss_clk_enable_all_no_ctx(); ++ ++ core.ctx_id = dss_get_ctx_id(); ++ DSSDBG("initial ctx id %u\n", core.ctx_id); ++ ++#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT ++ /* DISPC_CONTROL */ ++ if (omap_readl(0x48050440) & 1) /* LCD enabled? */ ++ skip_init = 1; ++#endif ++ ++ r = dss_init(skip_init); ++ if (r) { ++ DSSERR("Failed to initialize DSS\n"); ++ goto fail0; ++ } ++ ++#ifdef CONFIG_OMAP2_DSS_RFBI ++ r = rfbi_init(); ++ if (r) { ++ DSSERR("Failed to initialize rfbi\n"); ++ goto fail0; ++ } ++#endif ++ ++ r = dpi_init(); ++ if (r) { ++ DSSERR("Failed to initialize dpi\n"); ++ goto fail0; ++ } ++ ++ r = dispc_init(); ++ if (r) { ++ DSSERR("Failed to initialize dispc\n"); ++ goto fail0; ++ } ++#ifdef CONFIG_OMAP2_DSS_VENC ++ r = venc_init(pdev); ++ if (r) { ++ DSSERR("Failed to initialize venc\n"); ++ goto fail0; ++ } ++#endif ++ if (cpu_is_omap34xx()) { ++#ifdef CONFIG_OMAP2_DSS_SDI ++ r = sdi_init(skip_init); ++ if (r) { ++ DSSERR("Failed to initialize SDI\n"); ++ goto fail0; ++ } ++#endif ++#ifdef CONFIG_OMAP2_DSS_DSI ++ r = dsi_init(pdev); ++ if (r) { ++ DSSERR("Failed to initialize DSI\n"); ++ goto fail0; ++ } ++#endif ++ } ++ ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) ++ r = dss_initialize_debugfs(); ++ if (r) ++ goto fail0; ++#endif ++ ++ for (i = 0; i < pdata->num_devices; ++i) { ++ struct omap_dss_device *dssdev = pdata->devices[i]; ++ ++ r = omap_dss_register_device(dssdev); ++ if (r) ++ DSSERR("device reg failed %d\n", i); ++ ++ if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) ++ pdata->default_device = dssdev; ++ } ++ ++ dss_clk_disable_all(); ++ ++ return 0; ++ ++ /* XXX fail correctly */ ++fail0: ++ return r; ++} ++ ++static int omap_dss_remove(struct platform_device *pdev) ++{ ++ struct omap_dss_board_info *pdata = pdev->dev.platform_data; ++ int i; ++ int c; ++ ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) ++ dss_uninitialize_debugfs(); ++#endif ++ ++#ifdef CONFIG_OMAP2_DSS_VENC ++ venc_exit(); ++#endif ++ dispc_exit(); ++ dpi_exit(); ++#ifdef CONFIG_OMAP2_DSS_RFBI ++ rfbi_exit(); ++#endif ++ if (cpu_is_omap34xx()) { ++#ifdef CONFIG_OMAP2_DSS_DSI ++ dsi_exit(); ++#endif ++#ifdef CONFIG_OMAP2_DSS_SDI ++ sdi_exit(); ++#endif ++ } ++ ++ dss_exit(); ++ ++ /* these should be removed at some point */ ++ c = core.dss_ick->usecount; ++ if (c > 0) { ++ DSSERR("warning: dss_ick usecount %d, disabling\n", c); ++ while (c-- > 0) ++ clk_disable(core.dss_ick); ++ } ++ ++ c = core.dss1_fck->usecount; ++ if (c > 0) { ++ DSSERR("warning: dss1_fck usecount %d, disabling\n", c); ++ while (c-- > 0) ++ clk_disable(core.dss1_fck); ++ } ++ ++ c = core.dss2_fck->usecount; ++ if (c > 0) { ++ DSSERR("warning: dss2_fck usecount %d, disabling\n", c); ++ while (c-- > 0) ++ clk_disable(core.dss2_fck); ++ } ++ ++ c = core.dss_54m_fck->usecount; ++ if (c > 0) { ++ DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c); ++ while (c-- > 0) ++ clk_disable(core.dss_54m_fck); ++ } ++ ++ if (core.dss_96m_fck) { ++ c = core.dss_96m_fck->usecount; ++ if (c > 0) { ++ DSSERR("warning: dss_96m_fck usecount %d, disabling\n", ++ c); ++ while (c-- > 0) ++ clk_disable(core.dss_96m_fck); ++ } ++ } ++ ++ dss_put_clocks(); ++ ++ dss_uninit_overlays(pdev); ++ dss_uninit_overlay_managers(pdev); ++ ++ for (i = 0; i < pdata->num_devices; ++i) ++ omap_dss_unregister_device(pdata->devices[i]); ++ ++ return 0; ++} ++ ++static void omap_dss_shutdown(struct platform_device *pdev) ++{ ++ DSSDBG("shutdown\n"); ++} ++ ++static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ DSSDBG("suspend %d\n", state.event); ++ ++ return dss_suspend_all_devices(); ++} ++ ++static int omap_dss_resume(struct platform_device *pdev) ++{ ++ DSSDBG("resume\n"); ++ ++ return dss_resume_all_devices(); ++} ++ ++static struct platform_driver omap_dss_driver = { ++ .probe = omap_dss_probe, ++ .remove = omap_dss_remove, ++ .shutdown = omap_dss_shutdown, ++ .suspend = omap_dss_suspend, ++ .resume = omap_dss_resume, ++ .driver = { ++ .name = "omapdss", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++/* BUS */ ++static int dss_bus_match(struct device *dev, struct device_driver *driver) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ ++ DSSDBG("bus_match. dev %s/%s, drv %s\n", ++ dev_name(dev), dssdev->driver_name, driver->name); ++ ++ return strcmp(dssdev->driver_name, driver->name) == 0; ++} ++ ++static ssize_t device_name_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ dssdev->name ? ++ dssdev->name : ""); ++} ++ ++static struct device_attribute default_dev_attrs[] = { ++ __ATTR(name, S_IRUGO, device_name_show, NULL), ++ __ATTR_NULL, ++}; ++ ++static ssize_t driver_name_show(struct device_driver *drv, char *buf) ++{ ++ struct omap_dss_driver *dssdrv = to_dss_driver(drv); ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ dssdrv->driver.name ? ++ dssdrv->driver.name : ""); ++} ++static struct driver_attribute default_drv_attrs[] = { ++ __ATTR(name, S_IRUGO, driver_name_show, NULL), ++ __ATTR_NULL, ++}; ++ ++static struct bus_type dss_bus_type = { ++ .name = "omapdss", ++ .match = dss_bus_match, ++ .dev_attrs = default_dev_attrs, ++ .drv_attrs = default_drv_attrs, ++}; ++ ++static void dss_bus_release(struct device *dev) ++{ ++ DSSDBG("bus_release\n"); ++} ++ ++static struct device dss_bus = { ++ .release = dss_bus_release, ++}; ++ ++struct bus_type *dss_get_bus(void) ++{ ++ return &dss_bus_type; ++} ++ ++/* DRIVER */ ++static int dss_driver_probe(struct device *dev) ++{ ++ int r; ++ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; ++ bool force; ++ ++ DSSDBG("driver_probe: dev %s/%s, drv %s\n", ++ dev_name(dev), dssdev->driver_name, ++ dssdrv->driver.name); ++ ++ dss_init_device(core.pdev, dssdev); ++ ++ /* skip this if the device is behind a ctrl */ ++ if (!dssdev->panel.ctrl) { ++ force = pdata->default_device == dssdev; ++ dss_recheck_connections(dssdev, force); ++ } ++ ++ r = dssdrv->probe(dssdev); ++ ++ if (r) { ++ DSSERR("driver probe failed: %d\n", r); ++ return r; ++ } ++ ++ DSSDBG("probe done for device %s\n", dev_name(dev)); ++ ++ dssdev->driver = dssdrv; ++ ++ return 0; ++} ++ ++static int dss_driver_remove(struct device *dev) ++{ ++ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ ++ DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev), ++ dssdev->driver_name); ++ ++ dssdrv->remove(dssdev); ++ ++ dss_uninit_device(core.pdev, dssdev); ++ ++ dssdev->driver = NULL; ++ ++ return 0; ++} ++ ++int omap_dss_register_driver(struct omap_dss_driver *dssdriver) ++{ ++ dssdriver->driver.bus = &dss_bus_type; ++ dssdriver->driver.probe = dss_driver_probe; ++ dssdriver->driver.remove = dss_driver_remove; ++ return driver_register(&dssdriver->driver); ++} ++EXPORT_SYMBOL(omap_dss_register_driver); ++ ++void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver) ++{ ++ driver_unregister(&dssdriver->driver); ++} ++EXPORT_SYMBOL(omap_dss_unregister_driver); ++ ++/* DEVICE */ ++static void reset_device(struct device *dev, int check) ++{ ++ u8 *dev_p = (u8 *)dev; ++ u8 *dev_end = dev_p + sizeof(*dev); ++ void *saved_pdata; ++ ++ saved_pdata = dev->platform_data; ++ if (check) { ++ /* ++ * Check if there is any other setting than platform_data ++ * in struct device; warn that these will be reset by our ++ * init. ++ */ ++ dev->platform_data = NULL; ++ while (dev_p < dev_end) { ++ if (*dev_p) { ++ WARN("%s: struct device fields will be " ++ "discarded\n", ++ __func__); ++ break; ++ } ++ dev_p++; ++ } ++ } ++ memset(dev, 0, sizeof(*dev)); ++ dev->platform_data = saved_pdata; ++} ++ ++ ++static void omap_dss_dev_release(struct device *dev) ++{ ++ reset_device(dev, 0); ++} ++ ++int omap_dss_register_device(struct omap_dss_device *dssdev) ++{ ++ static int dev_num; ++ static int panel_num; ++ int r; ++ ++ WARN_ON(!dssdev->driver_name); ++ ++ reset_device(&dssdev->dev, 1); ++ dssdev->dev.bus = &dss_bus_type; ++ dssdev->dev.parent = &dss_bus; ++ dssdev->dev.release = omap_dss_dev_release; ++ dev_set_name(&dssdev->dev, "display%d", dev_num++); ++ r = device_register(&dssdev->dev); ++ if (r) ++ return r; ++ ++ if (dssdev->ctrl.panel) { ++ struct omap_dss_device *panel = dssdev->ctrl.panel; ++ ++ panel->panel.ctrl = dssdev; ++ ++ reset_device(&panel->dev, 1); ++ panel->dev.bus = &dss_bus_type; ++ panel->dev.parent = &dssdev->dev; ++ panel->dev.release = omap_dss_dev_release; ++ dev_set_name(&panel->dev, "panel%d", panel_num++); ++ r = device_register(&panel->dev); ++ if (r) ++ return r; ++ } ++ ++ return 0; ++} ++ ++void omap_dss_unregister_device(struct omap_dss_device *dssdev) ++{ ++ device_unregister(&dssdev->dev); ++ ++ if (dssdev->ctrl.panel) { ++ struct omap_dss_device *panel = dssdev->ctrl.panel; ++ device_unregister(&panel->dev); ++ } ++} ++ ++/* BUS */ ++static int omap_dss_bus_register(void) ++{ ++ int r; ++ ++ r = bus_register(&dss_bus_type); ++ if (r) { ++ DSSERR("bus register failed\n"); ++ return r; ++ } ++ ++ dev_set_name(&dss_bus, "omapdss"); ++ r = device_register(&dss_bus); ++ if (r) { ++ DSSERR("bus driver register failed\n"); ++ bus_unregister(&dss_bus_type); ++ return r; ++ } ++ ++ return 0; ++} ++ ++/* INIT */ ++ ++#ifdef CONFIG_OMAP2_DSS_MODULE ++static void omap_dss_bus_unregister(void) ++{ ++ device_unregister(&dss_bus); ++ ++ bus_unregister(&dss_bus_type); ++} ++ ++static int __init omap_dss_init(void) ++{ ++ int r; ++ ++ r = omap_dss_bus_register(); ++ if (r) ++ return r; ++ ++ r = platform_driver_register(&omap_dss_driver); ++ if (r) { ++ omap_dss_bus_unregister(); ++ return r; ++ } ++ ++ return 0; ++} ++ ++static void __exit omap_dss_exit(void) ++{ ++ platform_driver_unregister(&omap_dss_driver); ++ ++ omap_dss_bus_unregister(); ++} ++ ++module_init(omap_dss_init); ++module_exit(omap_dss_exit); ++#else ++static int __init omap_dss_init(void) ++{ ++ return omap_dss_bus_register(); ++} ++ ++static int __init omap_dss_init2(void) ++{ ++ return platform_driver_register(&omap_dss_driver); ++} ++ ++core_initcall(omap_dss_init); ++device_initcall(omap_dss_init2); ++#endif ++ ++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); ++MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); ++MODULE_LICENSE("GPL v2"); ++ +diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c +new file mode 100644 +index 0000000..aab9758 +--- /dev/null ++++ b/drivers/video/omap2/dss/dss.c +@@ -0,0 +1,347 @@ ++/* ++ * linux/drivers/video/omap2/dss/dss.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "DSS" ++ ++#include <linux/kernel.h> ++#include <linux/io.h> ++#include <linux/err.h> ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++#include <linux/seq_file.h> ++ ++#include <mach/display.h> ++#include "dss.h" ++ ++#define DSS_BASE 0x48050000 ++ ++#define DSS_SZ_REGS SZ_512 ++ ++struct dss_reg { ++ u16 idx; ++}; ++ ++#define DSS_REG(idx) ((const struct dss_reg) { idx }) ++ ++#define DSS_REVISION DSS_REG(0x0000) ++#define DSS_SYSCONFIG DSS_REG(0x0010) ++#define DSS_SYSSTATUS DSS_REG(0x0014) ++#define DSS_IRQSTATUS DSS_REG(0x0018) ++#define DSS_CONTROL DSS_REG(0x0040) ++#define DSS_SDI_CONTROL DSS_REG(0x0044) ++#define DSS_PLL_CONTROL DSS_REG(0x0048) ++#define DSS_SDI_STATUS DSS_REG(0x005C) ++ ++#define REG_GET(idx, start, end) \ ++ FLD_GET(dss_read_reg(idx), start, end) ++ ++#define REG_FLD_MOD(idx, val, start, end) \ ++ dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) ++ ++static struct { ++ void __iomem *base; ++ ++ u32 ctx[DSS_SZ_REGS / sizeof(u32)]; ++} dss; ++ ++static int _omap_dss_wait_reset(void); ++ ++static inline void dss_write_reg(const struct dss_reg idx, u32 val) ++{ ++ __raw_writel(val, dss.base + idx.idx); ++} ++ ++static inline u32 dss_read_reg(const struct dss_reg idx) ++{ ++ return __raw_readl(dss.base + idx.idx); ++} ++ ++#define SR(reg) \ ++ dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg) ++#define RR(reg) \ ++ dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)]) ++ ++void dss_save_context(void) ++{ ++ if (cpu_is_omap24xx()) ++ return; ++ ++ SR(SYSCONFIG); ++ SR(CONTROL); ++ ++#ifdef CONFIG_OMAP2_DSS_SDI ++ SR(SDI_CONTROL); ++ SR(PLL_CONTROL); ++#endif ++} ++ ++void dss_restore_context(void) ++{ ++ if (_omap_dss_wait_reset()) ++ DSSERR("DSS not coming out of reset after sleep\n"); ++ ++ RR(SYSCONFIG); ++ RR(CONTROL); ++ ++#ifdef CONFIG_OMAP2_DSS_SDI ++ RR(SDI_CONTROL); ++ RR(PLL_CONTROL); ++#endif ++} ++ ++#undef SR ++#undef RR ++ ++void dss_sdi_init(u8 datapairs) ++{ ++ u32 l; ++ ++ BUG_ON(datapairs > 3 || datapairs < 1); ++ ++ l = dss_read_reg(DSS_SDI_CONTROL); ++ l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */ ++ l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */ ++ l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */ ++ dss_write_reg(DSS_SDI_CONTROL, l); ++ ++ l = dss_read_reg(DSS_PLL_CONTROL); ++ l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */ ++ l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */ ++ l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */ ++ dss_write_reg(DSS_PLL_CONTROL, l); ++} ++ ++void dss_sdi_enable(void) ++{ ++ dispc_pck_free_enable(1); ++ ++ /* Reset SDI PLL */ ++ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */ ++ udelay(1); /* wait 2x PCLK */ ++ ++ /* Lock SDI PLL */ ++ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */ ++ ++ /* Waiting for PLL lock request to complete */ ++ while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) ++ ; ++ ++ /* Clearing PLL_GO bit */ ++ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28); ++ ++ /* Waiting for PLL to lock */ ++ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) ++ ; ++ ++ dispc_lcd_enable_signal(1); ++ ++ /* Waiting for SDI reset to complete */ ++ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) ++ ; ++} ++ ++void dss_sdi_disable(void) ++{ ++ dispc_lcd_enable_signal(0); ++ ++ dispc_pck_free_enable(0); ++ ++ /* Reset SDI PLL */ ++ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ ++} ++ ++void dss_dump_regs(struct seq_file *s) ++{ ++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ DUMPREG(DSS_REVISION); ++ DUMPREG(DSS_SYSCONFIG); ++ DUMPREG(DSS_SYSSTATUS); ++ DUMPREG(DSS_IRQSTATUS); ++ DUMPREG(DSS_CONTROL); ++ DUMPREG(DSS_SDI_CONTROL); ++ DUMPREG(DSS_PLL_CONTROL); ++ DUMPREG(DSS_SDI_STATUS); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++#undef DUMPREG ++} ++ ++void dss_select_clk_source(bool dsi, bool dispc) ++{ ++ u32 r; ++ r = dss_read_reg(DSS_CONTROL); ++ r = FLD_MOD(r, dsi, 1, 1); /* DSI_CLK_SWITCH */ ++ r = FLD_MOD(r, dispc, 0, 0); /* DISPC_CLK_SWITCH */ ++ dss_write_reg(DSS_CONTROL, r); ++} ++ ++int dss_get_dsi_clk_source(void) ++{ ++ return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1); ++} ++ ++int dss_get_dispc_clk_source(void) ++{ ++ return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0); ++} ++ ++static irqreturn_t dss_irq_handler_omap2(int irq, void *arg) ++{ ++ dispc_irq_handler(); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t dss_irq_handler_omap3(int irq, void *arg) ++{ ++ u32 irqstatus; ++ ++ irqstatus = dss_read_reg(DSS_IRQSTATUS); ++ ++ if (irqstatus & (1<<0)) /* DISPC_IRQ */ ++ dispc_irq_handler(); ++#ifdef CONFIG_OMAP2_DSS_DSI ++ if (irqstatus & (1<<1)) /* DSI_IRQ */ ++ dsi_irq_handler(); ++#endif ++ ++ return IRQ_HANDLED; ++} ++ ++static int _omap_dss_wait_reset(void) ++{ ++ unsigned timeout = 1000; ++ ++ while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) { ++ udelay(1); ++ if (!--timeout) { ++ DSSERR("soft reset failed\n"); ++ return -ENODEV; ++ } ++ } ++ ++ return 0; ++} ++ ++static int _omap_dss_reset(void) ++{ ++ /* Soft reset */ ++ REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1); ++ return _omap_dss_wait_reset(); ++} ++ ++void dss_set_venc_output(enum omap_dss_venc_type type) ++{ ++ int l = 0; ++ ++ if (type == OMAP_DSS_VENC_TYPE_COMPOSITE) ++ l = 0; ++ else if (type == OMAP_DSS_VENC_TYPE_SVIDEO) ++ l = 1; ++ else ++ BUG(); ++ ++ /* venc out selection. 0 = comp, 1 = svideo */ ++ REG_FLD_MOD(DSS_CONTROL, l, 6, 6); ++} ++ ++void dss_set_dac_pwrdn_bgz(bool enable) ++{ ++ REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ ++} ++ ++int dss_init(bool skip_init) ++{ ++ int r; ++ u32 rev; ++ ++ dss.base = ioremap(DSS_BASE, DSS_SZ_REGS); ++ if (!dss.base) { ++ DSSERR("can't ioremap DSS\n"); ++ r = -ENOMEM; ++ goto fail0; ++ } ++ ++ if (!skip_init) { ++ /* disable LCD and DIGIT output. This seems to fix the synclost ++ * problem that we get, if the bootloader starts the DSS and ++ * the kernel resets it */ ++ omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); ++ ++ /* We need to wait here a bit, otherwise we sometimes start to ++ * get synclost errors, and after that only power cycle will ++ * restore DSS functionality. I have no idea why this happens. ++ * And we have to wait _before_ resetting the DSS, but after ++ * enabling clocks. ++ */ ++ msleep(50); ++ ++ _omap_dss_reset(); ++ } ++ ++ /* autoidle */ ++ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); ++ ++ /* Select DPLL */ ++ REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); ++ ++#ifdef CONFIG_OMAP2_DSS_VENC ++ REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ ++ REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ ++ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ ++#endif ++ ++ r = request_irq(INT_24XX_DSS_IRQ, ++ cpu_is_omap24xx() ++ ? dss_irq_handler_omap2 ++ : dss_irq_handler_omap3, ++ 0, "OMAP DSS", NULL); ++ ++ if (r < 0) { ++ DSSERR("omap2 dss: request_irq failed\n"); ++ goto fail1; ++ } ++ ++ dss_save_context(); ++ ++ rev = dss_read_reg(DSS_REVISION); ++ printk(KERN_INFO "OMAP DSS rev %d.%d\n", ++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); ++ ++ return 0; ++ ++fail1: ++ iounmap(dss.base); ++fail0: ++ return r; ++} ++ ++void dss_exit(void) ++{ ++ free_irq(INT_24XX_DSS_IRQ, NULL); ++ ++ iounmap(dss.base); ++} ++ +diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h +new file mode 100644 +index 0000000..50f7f5f +--- /dev/null ++++ b/drivers/video/omap2/dss/dss.h +@@ -0,0 +1,356 @@ ++/* ++ * linux/drivers/video/omap2/dss/dss.h ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#ifndef __OMAP2_DSS_H ++#define __OMAP2_DSS_H ++ ++#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT ++#define DEBUG ++#endif ++ ++#ifdef DEBUG ++extern unsigned int dss_debug; ++#ifdef DSS_SUBSYS_NAME ++#define DSSDBG(format, ...) \ ++ if (dss_debug) \ ++ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \ ++ ## __VA_ARGS__) ++#else ++#define DSSDBG(format, ...) \ ++ if (dss_debug) \ ++ printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__) ++#endif ++ ++#ifdef DSS_SUBSYS_NAME ++#define DSSDBGF(format, ...) \ ++ if (dss_debug) \ ++ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \ ++ ": %s(" format ")\n", \ ++ __func__, \ ++ ## __VA_ARGS__) ++#else ++#define DSSDBGF(format, ...) \ ++ if (dss_debug) \ ++ printk(KERN_DEBUG "omapdss: " \ ++ ": %s(" format ")\n", \ ++ __func__, \ ++ ## __VA_ARGS__) ++#endif ++ ++#else /* DEBUG */ ++#define DSSDBG(format, ...) ++#define DSSDBGF(format, ...) ++#endif ++ ++ ++#ifdef DSS_SUBSYS_NAME ++#define DSSERR(format, ...) \ ++ printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \ ++ ## __VA_ARGS__) ++#else ++#define DSSERR(format, ...) \ ++ printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__) ++#endif ++ ++#ifdef DSS_SUBSYS_NAME ++#define DSSINFO(format, ...) \ ++ printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \ ++ ## __VA_ARGS__) ++#else ++#define DSSINFO(format, ...) \ ++ printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__) ++#endif ++ ++#ifdef DSS_SUBSYS_NAME ++#define DSSWARN(format, ...) \ ++ printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \ ++ ## __VA_ARGS__) ++#else ++#define DSSWARN(format, ...) \ ++ printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__) ++#endif ++ ++/* OMAP TRM gives bitfields as start:end, where start is the higher bit ++ number. For example 7:0 */ ++#define FLD_MASK(start, end) (((1 << (start - end + 1)) - 1) << (end)) ++#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end)) ++#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end)) ++#define FLD_MOD(orig, val, start, end) \ ++ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) ++ ++#define DISPC_MAX_FCK 173000000 ++ ++enum omap_burst_size { ++ OMAP_DSS_BURST_4x32 = 0, ++ OMAP_DSS_BURST_8x32 = 1, ++ OMAP_DSS_BURST_16x32 = 2, ++}; ++ ++enum omap_parallel_interface_mode { ++ OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */ ++ OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */ ++ OMAP_DSS_PARALLELMODE_DSI, ++}; ++ ++enum dss_clock { ++ DSS_CLK_ICK = 1 << 0, ++ DSS_CLK_FCK1 = 1 << 1, ++ DSS_CLK_FCK2 = 1 << 2, ++ DSS_CLK_54M = 1 << 3, ++ DSS_CLK_96M = 1 << 4, ++}; ++ ++struct dispc_clock_info { ++ /* rates that we get with dividers below */ ++ unsigned long fck; ++ unsigned long lck; ++ unsigned long pck; ++ ++ /* dividers */ ++ u16 fck_div; ++ u16 lck_div; ++ u16 pck_div; ++}; ++ ++struct dsi_clock_info { ++ /* rates that we get with dividers below */ ++ unsigned long fint; ++ unsigned long dsiphy; ++ unsigned long clkin; ++ unsigned long dsi1_pll_fclk; ++ unsigned long dsi2_pll_fclk; ++ unsigned long lck; ++ unsigned long pck; ++ ++ /* dividers */ ++ u16 regn; ++ u16 regm; ++ u16 regm3; ++ u16 regm4; ++ ++ u16 lck_div; ++ u16 pck_div; ++ ++ u8 highfreq; ++ bool use_dss2_fck; ++}; ++ ++struct seq_file; ++struct platform_device; ++ ++/* core */ ++void dss_clk_enable(enum dss_clock clks); ++void dss_clk_disable(enum dss_clock clks); ++unsigned long dss_clk_get_rate(enum dss_clock clk); ++int dss_need_ctx_restore(void); ++void dss_dump_clocks(struct seq_file *s); ++struct bus_type *dss_get_bus(void); ++ ++/* display */ ++int dss_suspend_all_devices(void); ++int dss_resume_all_devices(void); ++ ++void dss_init_device(struct platform_device *pdev, ++ struct omap_dss_device *dssdev); ++void dss_uninit_device(struct platform_device *pdev, ++ struct omap_dss_device *dssdev); ++bool dss_use_replication(struct omap_dss_device *dssdev, ++ enum omap_color_mode mode); ++void default_get_overlay_fifo_thresholds(enum omap_plane plane, ++ u32 fifo_size, enum omap_burst_size *burst_size, ++ u32 *fifo_low, u32 *fifo_high); ++ ++/* manager */ ++int dss_init_overlay_managers(struct platform_device *pdev); ++void dss_uninit_overlay_managers(struct platform_device *pdev); ++int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); ++void dss_setup_partial_planes(struct omap_dss_device *dssdev, ++ u16 *x, u16 *y, u16 *w, u16 *h); ++void dss_start_update(struct omap_dss_device *dssdev); ++ ++/* overlay */ ++void dss_init_overlays(struct platform_device *pdev); ++void dss_uninit_overlays(struct platform_device *pdev); ++int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev); ++void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); ++#ifdef L4_EXAMPLE ++void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr); ++#endif ++void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); ++ ++/* DSS */ ++int dss_init(bool skip_init); ++void dss_exit(void); ++ ++void dss_save_context(void); ++void dss_restore_context(void); ++ ++void dss_dump_regs(struct seq_file *s); ++ ++void dss_sdi_init(u8 datapairs); ++void dss_sdi_enable(void); ++void dss_sdi_disable(void); ++ ++void dss_select_clk_source(bool dsi, bool dispc); ++int dss_get_dsi_clk_source(void); ++int dss_get_dispc_clk_source(void); ++void dss_set_venc_output(enum omap_dss_venc_type type); ++void dss_set_dac_pwrdn_bgz(bool enable); ++ ++/* SDI */ ++int sdi_init(bool skip_init); ++void sdi_exit(void); ++int sdi_init_display(struct omap_dss_device *display); ++ ++/* DSI */ ++int dsi_init(struct platform_device *pdev); ++void dsi_exit(void); ++ ++void dsi_dump_clocks(struct seq_file *s); ++void dsi_dump_regs(struct seq_file *s); ++ ++void dsi_save_context(void); ++void dsi_restore_context(void); ++ ++int dsi_init_display(struct omap_dss_device *display); ++void dsi_irq_handler(void); ++unsigned long dsi_get_dsi1_pll_rate(void); ++unsigned long dsi_get_dsi2_pll_rate(void); ++int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck, ++ struct dsi_clock_info *cinfo); ++int dsi_pll_program(struct dsi_clock_info *cinfo); ++int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv); ++void dsi_pll_uninit(void); ++void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, ++ u32 fifo_size, enum omap_burst_size *burst_size, ++ u32 *fifo_low, u32 *fifo_high); ++ ++/* DPI */ ++int dpi_init(void); ++void dpi_exit(void); ++int dpi_init_display(struct omap_dss_device *dssdev); ++ ++/* DISPC */ ++int dispc_init(void); ++void dispc_exit(void); ++void dispc_dump_clocks(struct seq_file *s); ++void dispc_dump_regs(struct seq_file *s); ++void dispc_irq_handler(void); ++void dispc_fake_vsync_irq(void); ++ ++void dispc_save_context(void); ++void dispc_restore_context(void); ++ ++void dispc_enable_sidle(void); ++void dispc_disable_sidle(void); ++ ++void dispc_lcd_enable_signal_polarity(bool act_high); ++void dispc_lcd_enable_signal(bool enable); ++void dispc_pck_free_enable(bool enable); ++void dispc_enable_fifohandcheck(bool enable); ++ ++void dispc_set_lcd_size(u16 width, u16 height); ++void dispc_set_digit_size(u16 width, u16 height); ++u32 dispc_get_plane_fifo_size(enum omap_plane plane); ++void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high); ++void dispc_enable_fifomerge(bool enable); ++void dispc_set_burst_size(enum omap_plane plane, ++ enum omap_burst_size burst_size); ++ ++void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr); ++void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr); ++void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y); ++void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); ++void dispc_set_channel_out(enum omap_plane plane, ++ enum omap_channel channel_out); ++ ++int dispc_setup_plane(enum omap_plane plane, ++ u32 paddr, u16 screen_width, ++ u16 pos_x, u16 pos_y, ++ u16 width, u16 height, ++ u16 out_width, u16 out_height, ++ enum omap_color_mode color_mode, ++ bool ilace, ++ enum omap_dss_rotation_type rotation_type, ++ u8 rotation, bool mirror, ++ u8 global_alpha); ++ ++bool dispc_go_busy(enum omap_channel channel); ++void dispc_go(enum omap_channel channel); ++void dispc_enable_lcd_out(bool enable); ++void dispc_enable_digit_out(bool enable); ++int dispc_enable_plane(enum omap_plane plane, bool enable); ++void dispc_enable_replication(enum omap_plane plane, bool enable); ++ ++void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode); ++void dispc_set_tft_data_lines(u8 data_lines); ++void dispc_set_lcd_display_type(enum omap_lcd_display_type type); ++void dispc_set_loadmode(enum omap_dss_load_mode mode); ++ ++void dispc_set_default_color(enum omap_channel channel, u32 color); ++u32 dispc_get_default_color(enum omap_channel channel); ++void dispc_set_trans_key(enum omap_channel ch, ++ enum omap_dss_trans_key_type type, ++ u32 trans_key); ++void dispc_get_trans_key(enum omap_channel ch, ++ enum omap_dss_trans_key_type *type, ++ u32 *trans_key); ++void dispc_enable_trans_key(enum omap_channel ch, bool enable); ++void dispc_enable_alpha_blending(enum omap_channel ch, bool enable); ++bool dispc_trans_key_enabled(enum omap_channel ch); ++bool dispc_alpha_blending_enabled(enum omap_channel ch); ++ ++bool dispc_lcd_timings_ok(struct omap_video_timings *timings); ++void dispc_set_lcd_timings(struct omap_video_timings *timings); ++unsigned long dispc_fclk_rate(void); ++unsigned long dispc_lclk_rate(void); ++unsigned long dispc_pclk_rate(void); ++void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb); ++void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck, ++ u16 *lck_div, u16 *pck_div); ++int dispc_calc_clock_div(bool is_tft, unsigned long req_pck, ++ struct dispc_clock_info *cinfo); ++int dispc_set_clock_div(struct dispc_clock_info *cinfo); ++int dispc_get_clock_div(struct dispc_clock_info *cinfo); ++void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div); ++ ++ ++/* VENC */ ++int venc_init(struct platform_device *pdev); ++void venc_exit(void); ++void venc_dump_regs(struct seq_file *s); ++int venc_init_display(struct omap_dss_device *display); ++ ++/* RFBI */ ++int rfbi_init(void); ++void rfbi_exit(void); ++void rfbi_dump_regs(struct seq_file *s); ++ ++int rfbi_configure(int rfbi_module, int bpp, int lines); ++void rfbi_enable_rfbi(bool enable); ++void rfbi_transfer_area(u16 width, u16 height, ++ void (callback)(void *data), void *data); ++void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); ++unsigned long rfbi_get_max_tx_rate(void); ++int rfbi_init_display(struct omap_dss_device *display); ++ ++#endif +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0008-OMAP-DSS2-Add-more-core-files.patch b/recipes/linux/linux-omap-2.6.31/dss2/0008-OMAP-DSS2-Add-more-core-files.patch new file mode 100644 index 0000000000..3237d49eae --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0008-OMAP-DSS2-Add-more-core-files.patch @@ -0,0 +1,2856 @@ +From 9e37324c13a58b705b85e63b0779f7efbd94342a Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Fri, 7 Aug 2009 13:43:20 +0300 +Subject: [PATCH 08/18] OMAP: DSS2: Add more core files + +Add more core files to DSS2. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + drivers/video/omap2/dss/display.c | 658 ++++++++++++++++ + drivers/video/omap2/dss/manager.c | 1487 +++++++++++++++++++++++++++++++++++++ + drivers/video/omap2/dss/overlay.c | 673 +++++++++++++++++ + 3 files changed, 2818 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/dss/display.c + create mode 100644 drivers/video/omap2/dss/manager.c + create mode 100644 drivers/video/omap2/dss/overlay.c + +diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c +new file mode 100644 +index 0000000..6b5d0cf +--- /dev/null ++++ b/drivers/video/omap2/dss/display.c +@@ -0,0 +1,658 @@ ++/* ++ * linux/drivers/video/omap2/dss/display.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "DISPLAY" ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/jiffies.h> ++#include <linux/list.h> ++#include <linux/platform_device.h> ++ ++#include <mach/display.h> ++#include "dss.h" ++ ++static LIST_HEAD(display_list); ++ ++static ssize_t display_enabled_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED; ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", enabled); ++} ++ ++static ssize_t display_enabled_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ bool enabled, r; ++ ++ enabled = simple_strtoul(buf, NULL, 10); ++ ++ if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { ++ if (enabled) { ++ r = dssdev->enable(dssdev); ++ if (r) ++ return r; ++ } else { ++ dssdev->disable(dssdev); ++ } ++ } ++ ++ return size; ++} ++ ++static ssize_t display_upd_mode_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO; ++ if (dssdev->get_update_mode) ++ mode = dssdev->get_update_mode(dssdev); ++ return snprintf(buf, PAGE_SIZE, "%d\n", mode); ++} ++ ++static ssize_t display_upd_mode_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ int val, r; ++ enum omap_dss_update_mode mode; ++ ++ val = simple_strtoul(buf, NULL, 10); ++ ++ switch (val) { ++ case OMAP_DSS_UPDATE_DISABLED: ++ case OMAP_DSS_UPDATE_AUTO: ++ case OMAP_DSS_UPDATE_MANUAL: ++ mode = (enum omap_dss_update_mode)val; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ r = dssdev->set_update_mode(dssdev, mode); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t display_tear_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ return snprintf(buf, PAGE_SIZE, "%d\n", ++ dssdev->get_te ? dssdev->get_te(dssdev) : 0); ++} ++ ++static ssize_t display_tear_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ unsigned long te; ++ int r; ++ ++ if (!dssdev->enable_te || !dssdev->get_te) ++ return -ENOENT; ++ ++ te = simple_strtoul(buf, NULL, 0); ++ ++ r = dssdev->enable_te(dssdev, te); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t display_timings_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct omap_video_timings t; ++ ++ if (!dssdev->get_timings) ++ return -ENOENT; ++ ++ dssdev->get_timings(dssdev, &t); ++ ++ return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n", ++ t.pixel_clock, ++ t.x_res, t.hfp, t.hbp, t.hsw, ++ t.y_res, t.vfp, t.vbp, t.vsw); ++} ++ ++static ssize_t display_timings_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct omap_video_timings t; ++ int r, found; ++ ++ if (!dssdev->set_timings || !dssdev->check_timings) ++ return -ENOENT; ++ ++ found = 0; ++#ifdef CONFIG_OMAP2_DSS_VENC ++ if (strncmp("pal", buf, 3) == 0) { ++ t = omap_dss_pal_timings; ++ found = 1; ++ } else if (strncmp("ntsc", buf, 4) == 0) { ++ t = omap_dss_ntsc_timings; ++ found = 1; ++ } ++#endif ++ if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu", ++ &t.pixel_clock, ++ &t.x_res, &t.hfp, &t.hbp, &t.hsw, ++ &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9) ++ return -EINVAL; ++ ++ r = dssdev->check_timings(dssdev, &t); ++ if (r) ++ return r; ++ ++ dssdev->set_timings(dssdev, &t); ++ ++ return size; ++} ++ ++static ssize_t display_rotate_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ int rotate; ++ if (!dssdev->get_rotate) ++ return -ENOENT; ++ rotate = dssdev->get_rotate(dssdev); ++ return snprintf(buf, PAGE_SIZE, "%u\n", rotate); ++} ++ ++static ssize_t display_rotate_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ unsigned long rot; ++ int r; ++ ++ if (!dssdev->set_rotate || !dssdev->get_rotate) ++ return -ENOENT; ++ ++ rot = simple_strtoul(buf, NULL, 0); ++ ++ r = dssdev->set_rotate(dssdev, rot); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t display_mirror_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ int mirror; ++ if (!dssdev->get_mirror) ++ return -ENOENT; ++ mirror = dssdev->get_mirror(dssdev); ++ return snprintf(buf, PAGE_SIZE, "%u\n", mirror); ++} ++ ++static ssize_t display_mirror_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ unsigned long mirror; ++ int r; ++ ++ if (!dssdev->set_mirror || !dssdev->get_mirror) ++ return -ENOENT; ++ ++ mirror = simple_strtoul(buf, NULL, 0); ++ ++ r = dssdev->set_mirror(dssdev, mirror); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t display_wss_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ unsigned int wss; ++ ++ if (!dssdev->get_wss) ++ return -ENOENT; ++ ++ wss = dssdev->get_wss(dssdev); ++ ++ return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss); ++} ++ ++static ssize_t display_wss_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ unsigned long wss; ++ int r; ++ ++ if (!dssdev->get_wss || !dssdev->set_wss) ++ return -ENOENT; ++ ++ if (strict_strtoul(buf, 0, &wss)) ++ return -EINVAL; ++ ++ if (wss > 0xfffff) ++ return -EINVAL; ++ ++ r = dssdev->set_wss(dssdev, wss); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR, ++ display_enabled_show, display_enabled_store); ++static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR, ++ display_upd_mode_show, display_upd_mode_store); ++static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR, ++ display_tear_show, display_tear_store); ++static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR, ++ display_timings_show, display_timings_store); ++static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR, ++ display_rotate_show, display_rotate_store); ++static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR, ++ display_mirror_show, display_mirror_store); ++static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR, ++ display_wss_show, display_wss_store); ++ ++static struct device_attribute *display_sysfs_attrs[] = { ++ &dev_attr_enabled, ++ &dev_attr_update_mode, ++ &dev_attr_tear_elim, ++ &dev_attr_timings, ++ &dev_attr_rotate, ++ &dev_attr_mirror, ++ &dev_attr_wss, ++ NULL ++}; ++ ++static void default_get_resolution(struct omap_dss_device *dssdev, ++ u16 *xres, u16 *yres) ++{ ++ *xres = dssdev->panel.timings.x_res; ++ *yres = dssdev->panel.timings.y_res; ++} ++ ++void default_get_overlay_fifo_thresholds(enum omap_plane plane, ++ u32 fifo_size, enum omap_burst_size *burst_size, ++ u32 *fifo_low, u32 *fifo_high) ++{ ++ unsigned burst_size_bytes; ++ ++ *burst_size = OMAP_DSS_BURST_16x32; ++ burst_size_bytes = 16 * 32 / 8; ++ ++ *fifo_high = fifo_size - 1; ++ *fifo_low = fifo_size - burst_size_bytes; ++} ++ ++static int default_wait_vsync(struct omap_dss_device *dssdev) ++{ ++ unsigned long timeout = msecs_to_jiffies(500); ++ u32 irq; ++ ++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) ++ irq = DISPC_IRQ_EVSYNC_ODD; ++ else ++ irq = DISPC_IRQ_VSYNC; ++ ++ return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); ++} ++ ++static int default_get_recommended_bpp(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->panel.recommended_bpp) ++ return dssdev->panel.recommended_bpp; ++ ++ switch (dssdev->type) { ++ case OMAP_DISPLAY_TYPE_DPI: ++ if (dssdev->phy.dpi.data_lines == 24) ++ return 24; ++ else ++ return 16; ++ ++ case OMAP_DISPLAY_TYPE_DBI: ++ case OMAP_DISPLAY_TYPE_DSI: ++ if (dssdev->ctrl.pixel_size == 24) ++ return 24; ++ else ++ return 16; ++ case OMAP_DISPLAY_TYPE_VENC: ++ case OMAP_DISPLAY_TYPE_SDI: ++ return 24; ++ return 24; ++ default: ++ BUG(); ++ } ++} ++ ++/* Checks if replication logic should be used. Only use for active matrix, ++ * when overlay is in RGB12U or RGB16 mode, and LCD interface is ++ * 18bpp or 24bpp */ ++bool dss_use_replication(struct omap_dss_device *dssdev, ++ enum omap_color_mode mode) ++{ ++ int bpp; ++ ++ if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16) ++ return false; ++ ++ if (dssdev->type == OMAP_DISPLAY_TYPE_DPI && ++ (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0) ++ return false; ++ ++ switch (dssdev->type) { ++ case OMAP_DISPLAY_TYPE_DPI: ++ bpp = dssdev->phy.dpi.data_lines; ++ break; ++ case OMAP_DISPLAY_TYPE_VENC: ++ case OMAP_DISPLAY_TYPE_SDI: ++ bpp = 24; ++ break; ++ case OMAP_DISPLAY_TYPE_DBI: ++ case OMAP_DISPLAY_TYPE_DSI: ++ bpp = dssdev->ctrl.pixel_size; ++ break; ++ default: ++ BUG(); ++ } ++ ++ return bpp > 16; ++} ++ ++void dss_init_device(struct platform_device *pdev, ++ struct omap_dss_device *dssdev) ++{ ++ struct device_attribute *attr; ++ int i; ++ int r; ++ ++ switch (dssdev->type) { ++ case OMAP_DISPLAY_TYPE_DPI: ++#ifdef CONFIG_OMAP2_DSS_RFBI ++ case OMAP_DISPLAY_TYPE_DBI: ++#endif ++#ifdef CONFIG_OMAP2_DSS_SDI ++ case OMAP_DISPLAY_TYPE_SDI: ++#endif ++#ifdef CONFIG_OMAP2_DSS_DSI ++ case OMAP_DISPLAY_TYPE_DSI: ++#endif ++#ifdef CONFIG_OMAP2_DSS_VENC ++ case OMAP_DISPLAY_TYPE_VENC: ++#endif ++ break; ++ default: ++ DSSERR("Support for display '%s' not compiled in.\n", ++ dssdev->name); ++ return; ++ } ++ ++ dssdev->get_resolution = default_get_resolution; ++ dssdev->get_recommended_bpp = default_get_recommended_bpp; ++ dssdev->wait_vsync = default_wait_vsync; ++ ++ switch (dssdev->type) { ++ case OMAP_DISPLAY_TYPE_DPI: ++ r = dpi_init_display(dssdev); ++ break; ++#ifdef CONFIG_OMAP2_DSS_RFBI ++ case OMAP_DISPLAY_TYPE_DBI: ++ r = rfbi_init_display(dssdev); ++ break; ++#endif ++#ifdef CONFIG_OMAP2_DSS_VENC ++ case OMAP_DISPLAY_TYPE_VENC: ++ r = venc_init_display(dssdev); ++ break; ++#endif ++#ifdef CONFIG_OMAP2_DSS_SDI ++ case OMAP_DISPLAY_TYPE_SDI: ++ r = sdi_init_display(dssdev); ++ break; ++#endif ++#ifdef CONFIG_OMAP2_DSS_DSI ++ case OMAP_DISPLAY_TYPE_DSI: ++ r = dsi_init_display(dssdev); ++ break; ++#endif ++ default: ++ BUG(); ++ } ++ ++ if (r) { ++ DSSERR("failed to init display %s\n", dssdev->name); ++ return; ++ } ++ ++ /* create device sysfs files */ ++ i = 0; ++ while ((attr = display_sysfs_attrs[i++]) != NULL) { ++ r = device_create_file(&dssdev->dev, attr); ++ if (r) ++ DSSERR("failed to create sysfs file\n"); ++ } ++ ++ /* create display? sysfs links */ ++ r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj, ++ dev_name(&dssdev->dev)); ++ if (r) ++ DSSERR("failed to create sysfs display link\n"); ++} ++ ++void dss_uninit_device(struct platform_device *pdev, ++ struct omap_dss_device *dssdev) ++{ ++ struct device_attribute *attr; ++ int i = 0; ++ ++ sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev)); ++ ++ while ((attr = display_sysfs_attrs[i++]) != NULL) ++ device_remove_file(&dssdev->dev, attr); ++ ++ if (dssdev->manager) ++ dssdev->manager->unset_device(dssdev->manager); ++} ++ ++static int dss_suspend_device(struct device *dev, void *data) ++{ ++ int r; ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { ++ dssdev->activate_after_resume = false; ++ return 0; ++ } ++ ++ if (!dssdev->suspend) { ++ DSSERR("display '%s' doesn't implement suspend\n", ++ dssdev->name); ++ return -ENOSYS; ++ } ++ ++ r = dssdev->suspend(dssdev); ++ if (r) ++ return r; ++ ++ dssdev->activate_after_resume = true; ++ ++ return 0; ++} ++ ++int dss_suspend_all_devices(void) ++{ ++ int r; ++ struct bus_type *bus = dss_get_bus(); ++ ++ r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device); ++ if (r) { ++ /* resume all displays that were suspended */ ++ dss_resume_all_devices(); ++ return r; ++ } ++ ++ return 0; ++} ++ ++static int dss_resume_device(struct device *dev, void *data) ++{ ++ int r; ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ ++ if (dssdev->activate_after_resume && dssdev->resume) { ++ r = dssdev->resume(dssdev); ++ if (r) ++ return r; ++ } ++ ++ dssdev->activate_after_resume = false; ++ ++ return 0; ++} ++ ++int dss_resume_all_devices(void) ++{ ++ struct bus_type *bus = dss_get_bus(); ++ ++ return bus_for_each_dev(bus, NULL, NULL, dss_resume_device); ++} ++ ++ ++void omap_dss_get_device(struct omap_dss_device *dssdev) ++{ ++ get_device(&dssdev->dev); ++} ++EXPORT_SYMBOL(omap_dss_get_device); ++ ++void omap_dss_put_device(struct omap_dss_device *dssdev) ++{ ++ put_device(&dssdev->dev); ++} ++EXPORT_SYMBOL(omap_dss_put_device); ++ ++/* ref count of the found device is incremented. ref count ++ * of from-device is decremented. */ ++struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from) ++{ ++ struct device *dev; ++ struct device *dev_start = NULL; ++ struct omap_dss_device *dssdev = NULL; ++ ++ int match(struct device *dev, void *data) ++ { ++ /* skip panels connected to controllers */ ++ if (to_dss_device(dev)->panel.ctrl) ++ return 0; ++ ++ return 1; ++ } ++ ++ if (from) ++ dev_start = &from->dev; ++ dev = bus_find_device(dss_get_bus(), dev_start, NULL, match); ++ if (dev) ++ dssdev = to_dss_device(dev); ++ if (from) ++ put_device(&from->dev); ++ ++ return dssdev; ++} ++EXPORT_SYMBOL(omap_dss_get_next_device); ++ ++struct omap_dss_device *omap_dss_find_device(void *data, ++ int (*match)(struct omap_dss_device *dssdev, void *data)) ++{ ++ struct omap_dss_device *dssdev = NULL; ++ ++ while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) { ++ if (match(dssdev, data)) ++ return dssdev; ++ } ++ ++ return NULL; ++} ++EXPORT_SYMBOL(omap_dss_find_device); ++ ++int omap_dss_start_device(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ if (!dssdev->driver) { ++ DSSDBG("no driver\n"); ++ r = -ENODEV; ++ goto err0; ++ } ++ ++ if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) { ++ DSSDBG("no panel driver\n"); ++ r = -ENODEV; ++ goto err0; ++ } ++ ++ if (!try_module_get(dssdev->dev.driver->owner)) { ++ r = -ENODEV; ++ goto err0; ++ } ++ ++ if (dssdev->ctrl.panel) { ++ if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) { ++ r = -ENODEV; ++ goto err1; ++ } ++ } ++ ++ return 0; ++err1: ++ module_put(dssdev->dev.driver->owner); ++err0: ++ return r; ++} ++EXPORT_SYMBOL(omap_dss_start_device); ++ ++void omap_dss_stop_device(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->ctrl.panel) ++ module_put(dssdev->ctrl.panel->dev.driver->owner); ++ ++ module_put(dssdev->dev.driver->owner); ++} ++EXPORT_SYMBOL(omap_dss_stop_device); ++ +diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c +new file mode 100644 +index 0000000..7ee0b2b +--- /dev/null ++++ b/drivers/video/omap2/dss/manager.c +@@ -0,0 +1,1487 @@ ++/* ++ * linux/drivers/video/omap2/dss/manager.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "MANAGER" ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/spinlock.h> ++#include <linux/jiffies.h> ++ ++#include <mach/display.h> ++#include <mach/cpu.h> ++ ++#include "dss.h" ++ ++static int num_managers; ++static struct list_head manager_list; ++ ++static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name); ++} ++ ++static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ mgr->device ? mgr->device->name : "<none>"); ++} ++ ++static ssize_t manager_display_store(struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ int r = 0; ++ size_t len = size; ++ struct omap_dss_device *dssdev = NULL; ++ ++ int match(struct omap_dss_device *dssdev, void *data) ++ { ++ const char *str = data; ++ return sysfs_streq(dssdev->name, str); ++ } ++ ++ if (buf[size-1] == '\n') ++ --len; ++ ++ if (len > 0) ++ dssdev = omap_dss_find_device((void *)buf, match); ++ ++ if (len > 0 && dssdev == NULL) ++ return -EINVAL; ++ ++ if (dssdev) ++ DSSDBG("display %s found\n", dssdev->name); ++ ++ if (mgr->device) { ++ r = mgr->unset_device(mgr); ++ if (r) { ++ DSSERR("failed to unset display\n"); ++ goto put_device; ++ } ++ } ++ ++ if (dssdev) { ++ r = mgr->set_device(mgr, dssdev); ++ if (r) { ++ DSSERR("failed to set manager\n"); ++ goto put_device; ++ } ++ ++ r = mgr->apply(mgr); ++ if (r) { ++ DSSERR("failed to apply dispc config\n"); ++ goto put_device; ++ } ++ } ++ ++put_device: ++ if (dssdev) ++ omap_dss_put_device(dssdev); ++ ++ return r ? r : size; ++} ++ ++static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, ++ char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color); ++} ++ ++static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay_manager_info info; ++ u32 color; ++ int r; ++ ++ if (sscanf(buf, "%d", &color) != 1) ++ return -EINVAL; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ info.default_color = color; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static const char *trans_key_type_str[] = { ++ "gfx-destination", ++ "video-source", ++}; ++ ++static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr, ++ char *buf) ++{ ++ enum omap_dss_trans_key_type key_type; ++ ++ key_type = mgr->info.trans_key_type; ++ BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str)); ++ ++ return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]); ++} ++ ++static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ enum omap_dss_trans_key_type key_type; ++ struct omap_overlay_manager_info info; ++ int r; ++ ++ for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST; ++ key_type < ARRAY_SIZE(trans_key_type_str); key_type++) { ++ if (sysfs_streq(buf, trans_key_type_str[key_type])) ++ break; ++ } ++ ++ if (key_type == ARRAY_SIZE(trans_key_type_str)) ++ return -EINVAL; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ info.trans_key_type = key_type; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, ++ char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key); ++} ++ ++static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay_manager_info info; ++ u32 key_value; ++ int r; ++ ++ if (sscanf(buf, "%d", &key_value) != 1) ++ return -EINVAL; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ info.trans_key = key_value; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr, ++ char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled); ++} ++ ++static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay_manager_info info; ++ int enable; ++ int r; ++ ++ if (sscanf(buf, "%d", &enable) != 1) ++ return -EINVAL; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ info.trans_enabled = enable ? true : false; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t manager_alpha_blending_enabled_show( ++ struct omap_overlay_manager *mgr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled); ++} ++ ++static ssize_t manager_alpha_blending_enabled_store( ++ struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay_manager_info info; ++ int enable; ++ int r; ++ ++ if (sscanf(buf, "%d", &enable) != 1) ++ return -EINVAL; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ info.alpha_enabled = enable ? true : false; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++struct manager_attribute { ++ struct attribute attr; ++ ssize_t (*show)(struct omap_overlay_manager *, char *); ++ ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t); ++}; ++ ++#define MANAGER_ATTR(_name, _mode, _show, _store) \ ++ struct manager_attribute manager_attr_##_name = \ ++ __ATTR(_name, _mode, _show, _store) ++ ++static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL); ++static MANAGER_ATTR(display, S_IRUGO|S_IWUSR, ++ manager_display_show, manager_display_store); ++static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR, ++ manager_default_color_show, manager_default_color_store); ++static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR, ++ manager_trans_key_type_show, manager_trans_key_type_store); ++static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR, ++ manager_trans_key_value_show, manager_trans_key_value_store); ++static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR, ++ manager_trans_key_enabled_show, ++ manager_trans_key_enabled_store); ++static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR, ++ manager_alpha_blending_enabled_show, ++ manager_alpha_blending_enabled_store); ++ ++ ++static struct attribute *manager_sysfs_attrs[] = { ++ &manager_attr_name.attr, ++ &manager_attr_display.attr, ++ &manager_attr_default_color.attr, ++ &manager_attr_trans_key_type.attr, ++ &manager_attr_trans_key_value.attr, ++ &manager_attr_trans_key_enabled.attr, ++ &manager_attr_alpha_blending_enabled.attr, ++ NULL ++}; ++ ++static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr, ++ char *buf) ++{ ++ struct omap_overlay_manager *manager; ++ struct manager_attribute *manager_attr; ++ ++ manager = container_of(kobj, struct omap_overlay_manager, kobj); ++ manager_attr = container_of(attr, struct manager_attribute, attr); ++ ++ if (!manager_attr->show) ++ return -ENOENT; ++ ++ return manager_attr->show(manager, buf); ++} ++ ++static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay_manager *manager; ++ struct manager_attribute *manager_attr; ++ ++ manager = container_of(kobj, struct omap_overlay_manager, kobj); ++ manager_attr = container_of(attr, struct manager_attribute, attr); ++ ++ if (!manager_attr->store) ++ return -ENOENT; ++ ++ return manager_attr->store(manager, buf, size); ++} ++ ++static struct sysfs_ops manager_sysfs_ops = { ++ .show = manager_attr_show, ++ .store = manager_attr_store, ++}; ++ ++static struct kobj_type manager_ktype = { ++ .sysfs_ops = &manager_sysfs_ops, ++ .default_attrs = manager_sysfs_attrs, ++}; ++ ++/* ++ * We have 4 levels of cache for the dispc settings. First two are in SW and ++ * the latter two in HW. ++ * ++ * +--------------------+ ++ * |overlay/manager_info| ++ * +--------------------+ ++ * v ++ * apply() ++ * v ++ * +--------------------+ ++ * | dss_cache | ++ * +--------------------+ ++ * v ++ * configure() ++ * v ++ * +--------------------+ ++ * | shadow registers | ++ * +--------------------+ ++ * v ++ * VFP or lcd/digit_enable ++ * v ++ * +--------------------+ ++ * | registers | ++ * +--------------------+ ++ */ ++ ++struct overlay_cache_data { ++ /* If true, cache changed, but not written to shadow registers. Set ++ * in apply(), cleared when registers written. */ ++ bool dirty; ++ /* If true, shadow registers contain changed values not yet in real ++ * registers. Set when writing to shadow registers, cleared at ++ * VSYNC/EVSYNC */ ++ bool shadow_dirty; ++ ++ bool enabled; ++ ++ u32 paddr; ++ void __iomem *vaddr; ++ u16 screen_width; ++ u16 width; ++ u16 height; ++ enum omap_color_mode color_mode; ++ u8 rotation; ++ enum omap_dss_rotation_type rotation_type; ++ bool mirror; ++ ++ u16 pos_x; ++ u16 pos_y; ++ u16 out_width; /* if 0, out_width == width */ ++ u16 out_height; /* if 0, out_height == height */ ++ u8 global_alpha; ++ ++ enum omap_channel channel; ++ bool replication; ++ bool ilace; ++ ++ enum omap_burst_size burst_size; ++ u32 fifo_low; ++ u32 fifo_high; ++ ++ bool manual_update; ++}; ++ ++struct manager_cache_data { ++ /* If true, cache changed, but not written to shadow registers. Set ++ * in apply(), cleared when registers written. */ ++ bool dirty; ++ /* If true, shadow registers contain changed values not yet in real ++ * registers. Set when writing to shadow registers, cleared at ++ * VSYNC/EVSYNC */ ++ bool shadow_dirty; ++ ++ u32 default_color; ++ ++ enum omap_dss_trans_key_type trans_key_type; ++ u32 trans_key; ++ bool trans_enabled; ++ ++ bool alpha_enabled; ++ ++ bool manual_upd_display; ++ bool manual_update; ++ bool do_manual_update; ++ ++ /* manual update region */ ++ u16 x, y, w, h; ++}; ++ ++static struct { ++ spinlock_t lock; ++ struct overlay_cache_data overlay_cache[3]; ++ struct manager_cache_data manager_cache[2]; ++ ++ bool irq_enabled; ++} dss_cache; ++ ++ ++ ++static int omap_dss_set_device(struct omap_overlay_manager *mgr, ++ struct omap_dss_device *dssdev) ++{ ++ int i; ++ int r; ++ ++ if (dssdev->manager) { ++ DSSERR("display '%s' already has a manager '%s'\n", ++ dssdev->name, dssdev->manager->name); ++ return -EINVAL; ++ } ++ ++ if ((mgr->supported_displays & dssdev->type) == 0) { ++ DSSERR("display '%s' does not support manager '%s'\n", ++ dssdev->name, mgr->name); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < mgr->num_overlays; i++) { ++ struct omap_overlay *ovl = mgr->overlays[i]; ++ ++ if (ovl->manager != mgr || !ovl->info.enabled) ++ continue; ++ ++ r = dss_check_overlay(ovl, dssdev); ++ if (r) ++ return r; ++ } ++ ++ dssdev->manager = mgr; ++ mgr->device = dssdev; ++ mgr->device_changed = true; ++ ++ return 0; ++} ++ ++static int omap_dss_unset_device(struct omap_overlay_manager *mgr) ++{ ++ if (!mgr->device) { ++ DSSERR("failed to unset display, display not set.\n"); ++ return -EINVAL; ++ } ++ ++ mgr->device->manager = NULL; ++ mgr->device = NULL; ++ mgr->device_changed = true; ++ ++ return 0; ++} ++ ++static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) ++{ ++ unsigned long timeout = msecs_to_jiffies(500); ++ struct manager_cache_data *mc; ++ enum omap_channel channel; ++ u32 irq; ++ int r; ++ int i; ++ ++ if (!mgr->device) ++ return 0; ++ ++ if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { ++ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; ++ channel = OMAP_DSS_CHANNEL_DIGIT; ++ } else { ++ if (mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { ++ enum omap_dss_update_mode mode; ++ mode = mgr->device->get_update_mode(mgr->device); ++ if (mode != OMAP_DSS_UPDATE_AUTO) ++ return 0; ++ ++ irq = DISPC_IRQ_FRAMEDONE; ++ } else { ++ irq = DISPC_IRQ_VSYNC; ++ } ++ channel = OMAP_DSS_CHANNEL_LCD; ++ } ++ ++ mc = &dss_cache.manager_cache[mgr->id]; ++ i = 0; ++ while (1) { ++ unsigned long flags; ++ bool shadow_dirty, dirty; ++ ++ spin_lock_irqsave(&dss_cache.lock, flags); ++ dirty = mc->dirty; ++ shadow_dirty = mc->shadow_dirty; ++ spin_unlock_irqrestore(&dss_cache.lock, flags); ++ ++ if (!dirty && !shadow_dirty) { ++ r = 0; ++ break; ++ } ++ ++ /* 4 iterations is the worst case: ++ * 1 - initial iteration, dirty = true (between VFP and VSYNC) ++ * 2 - first VSYNC, dirty = true ++ * 3 - dirty = false, shadow_dirty = true ++ * 4 - shadow_dirty = false */ ++ if (i++ == 3) { ++ DSSERR("mgr(%d)->wait_for_go() not finishing\n", ++ mgr->id); ++ r = 0; ++ break; ++ } ++ ++ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); ++ if (r == -ERESTARTSYS) ++ break; ++ ++ if (r) { ++ DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id); ++ break; ++ } ++ } ++ ++ return r; ++} ++ ++int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) ++{ ++ unsigned long timeout = msecs_to_jiffies(500); ++ enum omap_channel channel; ++ struct overlay_cache_data *oc; ++ struct omap_dss_device *dssdev; ++ u32 irq; ++ int r; ++ int i; ++ ++ if (!ovl->manager || !ovl->manager->device) ++ return 0; ++ ++ dssdev = ovl->manager->device; ++ ++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { ++ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; ++ channel = OMAP_DSS_CHANNEL_DIGIT; ++ } else { ++ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { ++ enum omap_dss_update_mode mode; ++ mode = dssdev->get_update_mode(dssdev); ++ if (mode != OMAP_DSS_UPDATE_AUTO) ++ return 0; ++ ++ irq = DISPC_IRQ_FRAMEDONE; ++ } else { ++ irq = DISPC_IRQ_VSYNC; ++ } ++ channel = OMAP_DSS_CHANNEL_LCD; ++ } ++ ++ oc = &dss_cache.overlay_cache[ovl->id]; ++ i = 0; ++ while (1) { ++ unsigned long flags; ++ bool shadow_dirty, dirty; ++ ++ spin_lock_irqsave(&dss_cache.lock, flags); ++ dirty = oc->dirty; ++ shadow_dirty = oc->shadow_dirty; ++ spin_unlock_irqrestore(&dss_cache.lock, flags); ++ ++ if (!dirty && !shadow_dirty) { ++ r = 0; ++ break; ++ } ++ ++ /* 4 iterations is the worst case: ++ * 1 - initial iteration, dirty = true (between VFP and VSYNC) ++ * 2 - first VSYNC, dirty = true ++ * 3 - dirty = false, shadow_dirty = true ++ * 4 - shadow_dirty = false */ ++ if (i++ == 3) { ++ DSSERR("ovl(%d)->wait_for_go() not finishing\n", ++ ovl->id); ++ r = 0; ++ break; ++ } ++ ++ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); ++ if (r == -ERESTARTSYS) ++ break; ++ ++ if (r) { ++ DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id); ++ break; ++ } ++ } ++ ++ return r; ++} ++ ++static int overlay_enabled(struct omap_overlay *ovl) ++{ ++ return ovl->info.enabled && ovl->manager && ovl->manager->device; ++} ++ ++/* Is rect1 a subset of rect2? */ ++static bool rectangle_subset(int x1, int y1, int w1, int h1, ++ int x2, int y2, int w2, int h2) ++{ ++ if (x1 < x2 || y1 < y2) ++ return false; ++ ++ if (x1 + w1 > x2 + w2) ++ return false; ++ ++ if (y1 + h1 > y2 + h2) ++ return false; ++ ++ return true; ++} ++ ++/* Do rect1 and rect2 overlap? */ ++static bool rectangle_intersects(int x1, int y1, int w1, int h1, ++ int x2, int y2, int w2, int h2) ++{ ++ if (x1 >= x2 + w2) ++ return false; ++ ++ if (x2 >= x1 + w1) ++ return false; ++ ++ if (y1 >= y2 + h2) ++ return false; ++ ++ if (y2 >= y1 + h1) ++ return false; ++ ++ return true; ++} ++ ++static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc) ++{ ++ if (oc->out_width != 0 && oc->width != oc->out_width) ++ return true; ++ ++ if (oc->out_height != 0 && oc->height != oc->out_height) ++ return true; ++ ++ return false; ++} ++ ++static int configure_overlay(enum omap_plane plane) ++{ ++ struct overlay_cache_data *c; ++ struct manager_cache_data *mc; ++ u16 outw, outh; ++ u16 x, y, w, h; ++ u32 paddr; ++ int r; ++ ++ DSSDBGF("%d", plane); ++ ++ c = &dss_cache.overlay_cache[plane]; ++ ++ if (!c->enabled) { ++ dispc_enable_plane(plane, 0); ++ return 0; ++ } ++ ++ mc = &dss_cache.manager_cache[c->channel]; ++ ++ x = c->pos_x; ++ y = c->pos_y; ++ w = c->width; ++ h = c->height; ++ outw = c->out_width == 0 ? c->width : c->out_width; ++ outh = c->out_height == 0 ? c->height : c->out_height; ++ paddr = c->paddr; ++ ++ if (c->manual_update && mc->do_manual_update) { ++ unsigned bpp; ++ /* If the overlay is outside the update region, disable it */ ++ if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, ++ x, y, outw, outh)) { ++ dispc_enable_plane(plane, 0); ++ return 0; ++ } ++ ++ switch (c->color_mode) { ++ case OMAP_DSS_COLOR_RGB16: ++ case OMAP_DSS_COLOR_ARGB16: ++ case OMAP_DSS_COLOR_YUV2: ++ case OMAP_DSS_COLOR_UYVY: ++ bpp = 16; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24P: ++ bpp = 24; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24U: ++ case OMAP_DSS_COLOR_ARGB32: ++ case OMAP_DSS_COLOR_RGBA32: ++ case OMAP_DSS_COLOR_RGBX32: ++ bpp = 32; ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ if (dispc_is_overlay_scaled(c)) { ++ /* If the overlay is scaled, the update area has ++ * already been enlarged to cover the whole overlay. We ++ * only need to adjust x/y here */ ++ x = c->pos_x - mc->x; ++ y = c->pos_y - mc->y; ++ } else { ++ if (mc->x > c->pos_x) { ++ x = 0; ++ w -= (mc->x - c->pos_x); ++ paddr += (mc->x - c->pos_x) * bpp / 8; ++ } else { ++ x = c->pos_x - mc->x; ++ } ++ ++ if (mc->y > c->pos_y) { ++ y = 0; ++ h -= (mc->y - c->pos_y); ++ paddr += (mc->y - c->pos_y) * c->screen_width * ++ bpp / 8; ++ } else { ++ y = c->pos_y - mc->y; ++ } ++ ++ if (mc->w < (x+w)) ++ w -= (x+w) - (mc->w); ++ ++ if (mc->h < (y+h)) ++ h -= (y+h) - (mc->h); ++ ++ outw = w; ++ outh = h; ++ } ++ } ++ ++ r = dispc_setup_plane(plane, ++ paddr, ++ c->screen_width, ++ x, y, ++ w, h, ++ outw, outh, ++ c->color_mode, ++ c->ilace, ++ c->rotation_type, ++ c->rotation, ++ c->mirror, ++ c->global_alpha); ++ ++ if (r) { ++ /* this shouldn't happen */ ++ DSSERR("dispc_setup_plane failed for ovl %d\n", plane); ++ dispc_enable_plane(plane, 0); ++ return r; ++ } ++ ++ dispc_enable_replication(plane, c->replication); ++ ++ dispc_set_burst_size(plane, c->burst_size); ++ dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high); ++ ++ dispc_enable_plane(plane, 1); ++ ++ return 0; ++} ++ ++static void configure_manager(enum omap_channel channel) ++{ ++ struct manager_cache_data *c; ++ ++ DSSDBGF("%d", channel); ++ ++ c = &dss_cache.manager_cache[channel]; ++ ++ dispc_set_trans_key(channel, c->trans_key_type, c->trans_key); ++ dispc_enable_trans_key(channel, c->trans_enabled); ++ dispc_enable_alpha_blending(channel, c->alpha_enabled); ++} ++ ++/* configure_dispc() tries to write values from cache to shadow registers. ++ * It writes only to those managers/overlays that are not busy. ++ * returns 0 if everything could be written to shadow registers. ++ * returns 1 if not everything could be written to shadow registers. */ ++static int configure_dispc(void) ++{ ++ struct overlay_cache_data *oc; ++ struct manager_cache_data *mc; ++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); ++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); ++ int i; ++ int r; ++ bool mgr_busy[2]; ++ bool mgr_go[2]; ++ bool busy; ++ ++ r = 0; ++ busy = false; ++ ++ mgr_busy[0] = dispc_go_busy(0); ++ mgr_busy[1] = dispc_go_busy(1); ++ mgr_go[0] = false; ++ mgr_go[1] = false; ++ ++ /* Commit overlay settings */ ++ for (i = 0; i < num_ovls; ++i) { ++ oc = &dss_cache.overlay_cache[i]; ++ mc = &dss_cache.manager_cache[oc->channel]; ++ ++ if (!oc->dirty) ++ continue; ++ ++ if (oc->manual_update && !mc->do_manual_update) ++ continue; ++ ++ if (mgr_busy[oc->channel]) { ++ busy = true; ++ continue; ++ } ++ ++ r = configure_overlay(i); ++ if (r) ++ DSSERR("configure_overlay %d failed\n", i); ++ ++ oc->dirty = false; ++ oc->shadow_dirty = true; ++ mgr_go[oc->channel] = true; ++ } ++ ++ /* Commit manager settings */ ++ for (i = 0; i < num_mgrs; ++i) { ++ mc = &dss_cache.manager_cache[i]; ++ ++ if (!mc->dirty) ++ continue; ++ ++ if (mc->manual_update && !mc->do_manual_update) ++ continue; ++ ++ if (mgr_busy[i]) { ++ busy = true; ++ continue; ++ } ++ ++ configure_manager(i); ++ mc->dirty = false; ++ mc->shadow_dirty = true; ++ mgr_go[i] = true; ++ } ++ ++ /* set GO */ ++ for (i = 0; i < num_mgrs; ++i) { ++ mc = &dss_cache.manager_cache[i]; ++ ++ if (!mgr_go[i]) ++ continue; ++ ++ /* We don't need GO with manual update display. LCD iface will ++ * always be turned off after frame, and new settings will be ++ * taken in to use at next update */ ++ if (!mc->manual_upd_display) ++ dispc_go(i); ++ } ++ ++ if (busy) ++ r = 1; ++ else ++ r = 0; ++ ++ return r; ++} ++ ++/* Configure dispc for partial update. Return possibly modified update ++ * area */ ++void dss_setup_partial_planes(struct omap_dss_device *dssdev, ++ u16 *xi, u16 *yi, u16 *wi, u16 *hi) ++{ ++ struct overlay_cache_data *oc; ++ struct manager_cache_data *mc; ++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); ++ struct omap_overlay_manager *mgr; ++ int i; ++ u16 x, y, w, h; ++ unsigned long flags; ++ ++ x = *xi; ++ y = *yi; ++ w = *wi; ++ h = *hi; ++ ++ DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n", ++ *xi, *yi, *wi, *hi); ++ ++ mgr = dssdev->manager; ++ ++ if (!mgr) { ++ DSSDBG("no manager\n"); ++ return; ++ } ++ ++ spin_lock_irqsave(&dss_cache.lock, flags); ++ ++ /* We need to show the whole overlay if it is scaled. So look for ++ * those, and make the update area larger if found. ++ * Also mark the overlay cache dirty */ ++ for (i = 0; i < num_ovls; ++i) { ++ unsigned x1, y1, x2, y2; ++ unsigned outw, outh; ++ ++ oc = &dss_cache.overlay_cache[i]; ++ ++ if (oc->channel != mgr->id) ++ continue; ++ ++ oc->dirty = true; ++ ++ if (!oc->enabled) ++ continue; ++ ++ if (!dispc_is_overlay_scaled(oc)) ++ continue; ++ ++ outw = oc->out_width == 0 ? oc->width : oc->out_width; ++ outh = oc->out_height == 0 ? oc->height : oc->out_height; ++ ++ /* is the overlay outside the update region? */ ++ if (!rectangle_intersects(x, y, w, h, ++ oc->pos_x, oc->pos_y, ++ outw, outh)) ++ continue; ++ ++ /* if the overlay totally inside the update region? */ ++ if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh, ++ x, y, w, h)) ++ continue; ++ ++ if (x > oc->pos_x) ++ x1 = oc->pos_x; ++ else ++ x1 = x; ++ ++ if (y > oc->pos_y) ++ y1 = oc->pos_y; ++ else ++ y1 = y; ++ ++ if ((x + w) < (oc->pos_x + outw)) ++ x2 = oc->pos_x + outw; ++ else ++ x2 = x + w; ++ ++ if ((y + h) < (oc->pos_y + outh)) ++ y2 = oc->pos_y + outh; ++ else ++ y2 = y + h; ++ ++ x = x1; ++ y = y1; ++ w = x2 - x1; ++ h = y2 - y1; ++ ++ DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n", ++ i, x, y, w, h); ++ } ++ ++ mc = &dss_cache.manager_cache[mgr->id]; ++ mc->do_manual_update = true; ++ mc->x = x; ++ mc->y = y; ++ mc->w = w; ++ mc->h = h; ++ ++ configure_dispc(); ++ ++ mc->do_manual_update = false; ++ ++ spin_unlock_irqrestore(&dss_cache.lock, flags); ++ ++ *xi = x; ++ *yi = y; ++ *wi = w; ++ *hi = h; ++} ++ ++void dss_start_update(struct omap_dss_device *dssdev) ++{ ++ struct manager_cache_data *mc; ++ struct overlay_cache_data *oc; ++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); ++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); ++ struct omap_overlay_manager *mgr; ++ int i; ++ ++ mgr = dssdev->manager; ++ ++ for (i = 0; i < num_ovls; ++i) { ++ oc = &dss_cache.overlay_cache[i]; ++ if (oc->channel != mgr->id) ++ continue; ++ ++ oc->shadow_dirty = false; ++ } ++ ++ for (i = 0; i < num_mgrs; ++i) { ++ mc = &dss_cache.manager_cache[i]; ++ if (mgr->id != i) ++ continue; ++ ++ mc->shadow_dirty = false; ++ } ++ ++ dispc_enable_lcd_out(1); ++} ++ ++static void dss_apply_irq_handler(void *data, u32 mask) ++{ ++ struct manager_cache_data *mc; ++ struct overlay_cache_data *oc; ++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); ++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); ++ int i, r; ++ bool mgr_busy[2]; ++ ++ mgr_busy[0] = dispc_go_busy(0); ++ mgr_busy[1] = dispc_go_busy(1); ++ ++ spin_lock(&dss_cache.lock); ++ ++ for (i = 0; i < num_ovls; ++i) { ++ oc = &dss_cache.overlay_cache[i]; ++ if (!mgr_busy[oc->channel]) ++ oc->shadow_dirty = false; ++ } ++ ++ for (i = 0; i < num_mgrs; ++i) { ++ mc = &dss_cache.manager_cache[i]; ++ if (!mgr_busy[i]) ++ mc->shadow_dirty = false; ++ } ++ ++ r = configure_dispc(); ++ if (r == 1) ++ goto end; ++ ++ /* re-read busy flags */ ++ mgr_busy[0] = dispc_go_busy(0); ++ mgr_busy[1] = dispc_go_busy(1); ++ ++ /* keep running as long as there are busy managers, so that ++ * we can collect overlay-applied information */ ++ for (i = 0; i < num_mgrs; ++i) { ++ if (mgr_busy[i]) ++ goto end; ++ } ++ ++ omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, ++ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | ++ DISPC_IRQ_EVSYNC_EVEN); ++ dss_cache.irq_enabled = false; ++ ++end: ++ spin_unlock(&dss_cache.lock); ++} ++ ++static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) ++{ ++ struct overlay_cache_data *oc; ++ struct manager_cache_data *mc; ++ int i; ++ struct omap_overlay *ovl; ++ int num_planes_enabled = 0; ++ bool use_fifomerge; ++ unsigned long flags; ++ int r; ++ ++ DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); ++ ++ spin_lock_irqsave(&dss_cache.lock, flags); ++ ++ /* Configure overlays */ ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_dss_device *dssdev; ++ ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ oc = &dss_cache.overlay_cache[ovl->id]; ++ ++ if (!overlay_enabled(ovl)) { ++ if (oc->enabled) { ++ oc->enabled = false; ++ oc->dirty = true; ++ } ++ continue; ++ } ++ ++ if (!ovl->info_dirty) { ++ if (oc->enabled) ++ ++num_planes_enabled; ++ continue; ++ } ++ ++ dssdev = ovl->manager->device; ++ ++ if (dss_check_overlay(ovl, dssdev)) { ++ if (oc->enabled) { ++ oc->enabled = false; ++ oc->dirty = true; ++ } ++ continue; ++ } ++ ++ ovl->info_dirty = false; ++ oc->dirty = true; ++ ++ oc->paddr = ovl->info.paddr; ++ oc->vaddr = ovl->info.vaddr; ++ oc->screen_width = ovl->info.screen_width; ++ oc->width = ovl->info.width; ++ oc->height = ovl->info.height; ++ oc->color_mode = ovl->info.color_mode; ++ oc->rotation = ovl->info.rotation; ++ oc->rotation_type = ovl->info.rotation_type; ++ oc->mirror = ovl->info.mirror; ++ oc->pos_x = ovl->info.pos_x; ++ oc->pos_y = ovl->info.pos_y; ++ oc->out_width = ovl->info.out_width; ++ oc->out_height = ovl->info.out_height; ++ oc->global_alpha = ovl->info.global_alpha; ++ ++ oc->replication = ++ dss_use_replication(dssdev, ovl->info.color_mode); ++ ++ oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC; ++ ++ oc->channel = ovl->manager->id; ++ ++ oc->enabled = true; ++ ++ oc->manual_update = ++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE && ++ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO; ++ ++ ++num_planes_enabled; ++ } ++ ++ /* Configure managers */ ++ list_for_each_entry(mgr, &manager_list, list) { ++ struct omap_dss_device *dssdev; ++ ++ if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC)) ++ continue; ++ ++ mc = &dss_cache.manager_cache[mgr->id]; ++ ++ if (mgr->device_changed) { ++ mgr->device_changed = false; ++ mgr->info_dirty = true; ++ } ++ ++ if (!mgr->info_dirty) ++ continue; ++ ++ if (!mgr->device) ++ continue; ++ ++ dssdev = mgr->device; ++ ++ mgr->info_dirty = false; ++ mc->dirty = true; ++ ++ mc->default_color = mgr->info.default_color; ++ mc->trans_key_type = mgr->info.trans_key_type; ++ mc->trans_key = mgr->info.trans_key; ++ mc->trans_enabled = mgr->info.trans_enabled; ++ mc->alpha_enabled = mgr->info.alpha_enabled; ++ ++ mc->manual_upd_display = ++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; ++ ++ mc->manual_update = ++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE && ++ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO; ++ } ++ ++ /* XXX TODO: Try to get fifomerge working. The problem is that it ++ * affects both managers, not individually but at the same time. This ++ * means the change has to be well synchronized. I guess the proper way ++ * is to have a two step process for fifo merge: ++ * fifomerge enable: ++ * 1. disable other planes, leaving one plane enabled ++ * 2. wait until the planes are disabled on HW ++ * 3. config merged fifo thresholds, enable fifomerge ++ * fifomerge disable: ++ * 1. config unmerged fifo thresholds, disable fifomerge ++ * 2. wait until fifo changes are in HW ++ * 3. enable planes ++ */ ++ use_fifomerge = false; ++ ++ /* Configure overlay fifos */ ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_dss_device *dssdev; ++ u32 size; ++ ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ oc = &dss_cache.overlay_cache[ovl->id]; ++ ++ if (!oc->enabled) ++ continue; ++ ++ dssdev = ovl->manager->device; ++ ++ size = dispc_get_plane_fifo_size(ovl->id); ++ if (use_fifomerge) ++ size *= 3; ++ ++ switch (dssdev->type) { ++ case OMAP_DISPLAY_TYPE_DPI: ++ case OMAP_DISPLAY_TYPE_DBI: ++ case OMAP_DISPLAY_TYPE_SDI: ++ case OMAP_DISPLAY_TYPE_VENC: ++ default_get_overlay_fifo_thresholds(ovl->id, size, ++ &oc->burst_size, &oc->fifo_low, ++ &oc->fifo_high); ++ break; ++#ifdef CONFIG_OMAP2_DSS_DSI ++ case OMAP_DISPLAY_TYPE_DSI: ++ dsi_get_overlay_fifo_thresholds(ovl->id, size, ++ &oc->burst_size, &oc->fifo_low, ++ &oc->fifo_high); ++ break; ++#endif ++ default: ++ BUG(); ++ } ++ } ++ ++ r = 0; ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ if (!dss_cache.irq_enabled) { ++ r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, ++ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | ++ DISPC_IRQ_EVSYNC_EVEN); ++ dss_cache.irq_enabled = true; ++ } ++ configure_dispc(); ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ spin_unlock_irqrestore(&dss_cache.lock, flags); ++ ++ return r; ++} ++ ++static int dss_check_manager(struct omap_overlay_manager *mgr) ++{ ++ /* OMAP supports only graphics source transparency color key and alpha ++ * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */ ++ ++ if (mgr->info.alpha_enabled && mgr->info.trans_enabled && ++ mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr, ++ struct omap_overlay_manager_info *info) ++{ ++ int r; ++ struct omap_overlay_manager_info old_info; ++ ++ old_info = mgr->info; ++ mgr->info = *info; ++ ++ r = dss_check_manager(mgr); ++ if (r) { ++ mgr->info = old_info; ++ return r; ++ } ++ ++ mgr->info_dirty = true; ++ ++ return 0; ++} ++ ++static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr, ++ struct omap_overlay_manager_info *info) ++{ ++ *info = mgr->info; ++} ++ ++static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager) ++{ ++ ++num_managers; ++ list_add_tail(&manager->list, &manager_list); ++} ++ ++int dss_init_overlay_managers(struct platform_device *pdev) ++{ ++ int i, r; ++ ++ spin_lock_init(&dss_cache.lock); ++ ++ INIT_LIST_HEAD(&manager_list); ++ ++ num_managers = 0; ++ ++ for (i = 0; i < 2; ++i) { ++ struct omap_overlay_manager *mgr; ++ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); ++ ++ BUG_ON(mgr == NULL); ++ ++ switch (i) { ++ case 0: ++ mgr->name = "lcd"; ++ mgr->id = OMAP_DSS_CHANNEL_LCD; ++ mgr->supported_displays = ++ OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | ++ OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI; ++ break; ++ case 1: ++ mgr->name = "tv"; ++ mgr->id = OMAP_DSS_CHANNEL_DIGIT; ++ mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC; ++ break; ++ } ++ ++ mgr->set_device = &omap_dss_set_device; ++ mgr->unset_device = &omap_dss_unset_device; ++ mgr->apply = &omap_dss_mgr_apply; ++ mgr->set_manager_info = &omap_dss_mgr_set_info; ++ mgr->get_manager_info = &omap_dss_mgr_get_info; ++ mgr->wait_for_go = &dss_mgr_wait_for_go; ++ ++ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; ++ ++ dss_overlay_setup_dispc_manager(mgr); ++ ++ omap_dss_add_overlay_manager(mgr); ++ ++ r = kobject_init_and_add(&mgr->kobj, &manager_ktype, ++ &pdev->dev.kobj, "manager%d", i); ++ ++ if (r) { ++ DSSERR("failed to create sysfs file\n"); ++ continue; ++ } ++ } ++ ++#ifdef L4_EXAMPLE ++ { ++ int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr) ++ { ++ DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name); ++ ++ return 0; ++ } ++ ++ struct omap_overlay_manager *mgr; ++ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); ++ ++ BUG_ON(mgr == NULL); ++ ++ mgr->name = "l4"; ++ mgr->supported_displays = ++ OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI; ++ ++ mgr->set_device = &omap_dss_set_device; ++ mgr->unset_device = &omap_dss_unset_device; ++ mgr->apply = &omap_dss_mgr_apply_l4; ++ mgr->set_manager_info = &omap_dss_mgr_set_info; ++ mgr->get_manager_info = &omap_dss_mgr_get_info; ++ ++ dss_overlay_setup_l4_manager(mgr); ++ ++ omap_dss_add_overlay_manager(mgr); ++ ++ r = kobject_init_and_add(&mgr->kobj, &manager_ktype, ++ &pdev->dev.kobj, "managerl4"); ++ ++ if (r) ++ DSSERR("failed to create sysfs file\n"); ++ } ++#endif ++ ++ return 0; ++} ++ ++void dss_uninit_overlay_managers(struct platform_device *pdev) ++{ ++ struct omap_overlay_manager *mgr; ++ ++ while (!list_empty(&manager_list)) { ++ mgr = list_first_entry(&manager_list, ++ struct omap_overlay_manager, list); ++ list_del(&mgr->list); ++ kobject_del(&mgr->kobj); ++ kobject_put(&mgr->kobj); ++ kfree(mgr); ++ } ++ ++ num_managers = 0; ++} ++ ++int omap_dss_get_num_overlay_managers(void) ++{ ++ return num_managers; ++} ++EXPORT_SYMBOL(omap_dss_get_num_overlay_managers); ++ ++struct omap_overlay_manager *omap_dss_get_overlay_manager(int num) ++{ ++ int i = 0; ++ struct omap_overlay_manager *mgr; ++ ++ list_for_each_entry(mgr, &manager_list, list) { ++ if (i++ == num) ++ return mgr; ++ } ++ ++ return NULL; ++} ++EXPORT_SYMBOL(omap_dss_get_overlay_manager); ++ +diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c +new file mode 100644 +index 0000000..c7cb81b +--- /dev/null ++++ b/drivers/video/omap2/dss/overlay.c +@@ -0,0 +1,673 @@ ++/* ++ * linux/drivers/video/omap2/dss/overlay.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "OVERLAY" ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/err.h> ++#include <linux/sysfs.h> ++#include <linux/kobject.h> ++#include <linux/platform_device.h> ++#include <linux/delay.h> ++ ++#include <mach/display.h> ++ ++#include "dss.h" ++ ++static int num_overlays; ++static struct list_head overlay_list; ++ ++static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name); ++} ++ ++static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ ovl->manager ? ovl->manager->name : "<none>"); ++} ++ ++static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, ++ size_t size) ++{ ++ int i, r; ++ struct omap_overlay_manager *mgr = NULL; ++ struct omap_overlay_manager *old_mgr; ++ int len = size; ++ ++ if (buf[size-1] == '\n') ++ --len; ++ ++ if (len > 0) { ++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { ++ mgr = omap_dss_get_overlay_manager(i); ++ ++ if (strncmp(buf, mgr->name, len) == 0) ++ break; ++ ++ mgr = NULL; ++ } ++ } ++ ++ if (len > 0 && mgr == NULL) ++ return -EINVAL; ++ ++ if (mgr) ++ DSSDBG("manager %s found\n", mgr->name); ++ ++ if (mgr == ovl->manager) ++ return size; ++ ++ old_mgr = ovl->manager; ++ ++ /* detach old manager */ ++ if (old_mgr) { ++ r = ovl->unset_manager(ovl); ++ if (r) { ++ DSSERR("detach failed\n"); ++ return r; ++ } ++ ++ r = old_mgr->apply(old_mgr); ++ if (r) ++ return r; ++ } ++ ++ if (mgr) { ++ r = ovl->set_manager(ovl, mgr); ++ if (r) { ++ DSSERR("Failed to attach overlay\n"); ++ return r; ++ } ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ } ++ ++ return size; ++} ++ ++static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d,%d\n", ++ ovl->info.width, ovl->info.height); ++} ++ ++static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width); ++} ++ ++static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d,%d\n", ++ ovl->info.pos_x, ovl->info.pos_y); ++} ++ ++static ssize_t overlay_position_store(struct omap_overlay *ovl, ++ const char *buf, size_t size) ++{ ++ int r; ++ char *last; ++ struct omap_overlay_info info; ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ info.pos_x = simple_strtoul(buf, &last, 10); ++ ++last; ++ if (last - buf >= size) ++ return -EINVAL; ++ ++ info.pos_y = simple_strtoul(last, &last, 10); ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) ++ return r; ++ ++ if (ovl->manager) { ++ r = ovl->manager->apply(ovl->manager); ++ if (r) ++ return r; ++ } ++ ++ return size; ++} ++ ++static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d,%d\n", ++ ovl->info.out_width, ovl->info.out_height); ++} ++ ++static ssize_t overlay_output_size_store(struct omap_overlay *ovl, ++ const char *buf, size_t size) ++{ ++ int r; ++ char *last; ++ struct omap_overlay_info info; ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ info.out_width = simple_strtoul(buf, &last, 10); ++ ++last; ++ if (last - buf >= size) ++ return -EINVAL; ++ ++ info.out_height = simple_strtoul(last, &last, 10); ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) ++ return r; ++ ++ if (ovl->manager) { ++ r = ovl->manager->apply(ovl->manager); ++ if (r) ++ return r; ++ } ++ ++ return size; ++} ++ ++static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled); ++} ++ ++static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, ++ size_t size) ++{ ++ int r; ++ struct omap_overlay_info info; ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ info.enabled = simple_strtoul(buf, NULL, 10); ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) ++ return r; ++ ++ if (ovl->manager) { ++ r = ovl->manager->apply(ovl->manager); ++ if (r) ++ return r; ++ } ++ ++ return size; ++} ++ ++static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", ++ ovl->info.global_alpha); ++} ++ ++static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, ++ const char *buf, size_t size) ++{ ++ int r; ++ struct omap_overlay_info info; ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ /* Video1 plane does not support global alpha ++ * to always make it 255 completely opaque ++ */ ++ if (ovl->id == OMAP_DSS_VIDEO1) ++ info.global_alpha = 255; ++ else ++ info.global_alpha = simple_strtoul(buf, NULL, 10); ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) ++ return r; ++ ++ if (ovl->manager) { ++ r = ovl->manager->apply(ovl->manager); ++ if (r) ++ return r; ++ } ++ ++ return size; ++} ++ ++struct overlay_attribute { ++ struct attribute attr; ++ ssize_t (*show)(struct omap_overlay *, char *); ++ ssize_t (*store)(struct omap_overlay *, const char *, size_t); ++}; ++ ++#define OVERLAY_ATTR(_name, _mode, _show, _store) \ ++ struct overlay_attribute overlay_attr_##_name = \ ++ __ATTR(_name, _mode, _show, _store) ++ ++static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL); ++static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR, ++ overlay_manager_show, overlay_manager_store); ++static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL); ++static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL); ++static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR, ++ overlay_position_show, overlay_position_store); ++static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR, ++ overlay_output_size_show, overlay_output_size_store); ++static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR, ++ overlay_enabled_show, overlay_enabled_store); ++static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, ++ overlay_global_alpha_show, overlay_global_alpha_store); ++ ++static struct attribute *overlay_sysfs_attrs[] = { ++ &overlay_attr_name.attr, ++ &overlay_attr_manager.attr, ++ &overlay_attr_input_size.attr, ++ &overlay_attr_screen_width.attr, ++ &overlay_attr_position.attr, ++ &overlay_attr_output_size.attr, ++ &overlay_attr_enabled.attr, ++ &overlay_attr_global_alpha.attr, ++ NULL ++}; ++ ++static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr, ++ char *buf) ++{ ++ struct omap_overlay *overlay; ++ struct overlay_attribute *overlay_attr; ++ ++ overlay = container_of(kobj, struct omap_overlay, kobj); ++ overlay_attr = container_of(attr, struct overlay_attribute, attr); ++ ++ if (!overlay_attr->show) ++ return -ENOENT; ++ ++ return overlay_attr->show(overlay, buf); ++} ++ ++static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay *overlay; ++ struct overlay_attribute *overlay_attr; ++ ++ overlay = container_of(kobj, struct omap_overlay, kobj); ++ overlay_attr = container_of(attr, struct overlay_attribute, attr); ++ ++ if (!overlay_attr->store) ++ return -ENOENT; ++ ++ return overlay_attr->store(overlay, buf, size); ++} ++ ++static struct sysfs_ops overlay_sysfs_ops = { ++ .show = overlay_attr_show, ++ .store = overlay_attr_store, ++}; ++ ++static struct kobj_type overlay_ktype = { ++ .sysfs_ops = &overlay_sysfs_ops, ++ .default_attrs = overlay_sysfs_attrs, ++}; ++ ++/* Check if overlay parameters are compatible with display */ ++int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev) ++{ ++ struct omap_overlay_info *info; ++ u16 outw, outh; ++ u16 dw, dh; ++ ++ if (!dssdev) ++ return 0; ++ ++ if (!ovl->info.enabled) ++ return 0; ++ ++ info = &ovl->info; ++ ++ if (info->paddr == 0) { ++ DSSDBG("check_overlay failed: paddr 0\n"); ++ return -EINVAL; ++ } ++ ++ dssdev->get_resolution(dssdev, &dw, &dh); ++ ++ DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n", ++ ovl->id, ++ info->pos_x, info->pos_y, ++ info->width, info->height, ++ info->out_width, info->out_height, ++ dw, dh); ++ ++ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { ++ outw = info->width; ++ outh = info->height; ++ } else { ++ if (info->out_width == 0) ++ outw = info->width; ++ else ++ outw = info->out_width; ++ ++ if (info->out_height == 0) ++ outh = info->height; ++ else ++ outh = info->out_height; ++ } ++ ++ if (dw < info->pos_x + outw) { ++ DSSDBG("check_overlay failed 1: %d < %d + %d\n", ++ dw, info->pos_x, outw); ++ return -EINVAL; ++ } ++ ++ if (dh < info->pos_y + outh) { ++ DSSDBG("check_overlay failed 2: %d < %d + %d\n", ++ dh, info->pos_y, outh); ++ return -EINVAL; ++ } ++ ++ if ((ovl->supported_modes & info->color_mode) == 0) { ++ DSSERR("overlay doesn't support mode %d\n", info->color_mode); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int dss_ovl_set_overlay_info(struct omap_overlay *ovl, ++ struct omap_overlay_info *info) ++{ ++ int r; ++ struct omap_overlay_info old_info; ++ ++ old_info = ovl->info; ++ ovl->info = *info; ++ ++ if (ovl->manager) { ++ r = dss_check_overlay(ovl, ovl->manager->device); ++ if (r) { ++ ovl->info = old_info; ++ return r; ++ } ++ } ++ ++ ovl->info_dirty = true; ++ ++ return 0; ++} ++ ++static void dss_ovl_get_overlay_info(struct omap_overlay *ovl, ++ struct omap_overlay_info *info) ++{ ++ *info = ovl->info; ++} ++ ++static int dss_ovl_wait_for_go(struct omap_overlay *ovl) ++{ ++ return dss_mgr_wait_for_go_ovl(ovl); ++} ++ ++static int omap_dss_set_manager(struct omap_overlay *ovl, ++ struct omap_overlay_manager *mgr) ++{ ++ if (!mgr) ++ return -EINVAL; ++ ++ if (ovl->manager) { ++ DSSERR("overlay '%s' already has a manager '%s'\n", ++ ovl->name, ovl->manager->name); ++ return -EINVAL; ++ } ++ ++ if (ovl->info.enabled) { ++ DSSERR("overlay has to be disabled to change the manager\n"); ++ return -EINVAL; ++ } ++ ++ ovl->manager = mgr; ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ /* XXX: on manual update display, in auto update mode, a bug happens ++ * here. When an overlay is first enabled on LCD, then it's disabled, ++ * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT ++ * errors. Waiting before changing the channel_out fixes it. I'm ++ * guessing that the overlay is still somehow being used for the LCD, ++ * but I don't understand how or why. */ ++ msleep(40); ++ dispc_set_channel_out(ovl->id, mgr->id); ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ return 0; ++} ++ ++static int omap_dss_unset_manager(struct omap_overlay *ovl) ++{ ++ int r; ++ ++ if (!ovl->manager) { ++ DSSERR("failed to detach overlay: manager not set\n"); ++ return -EINVAL; ++ } ++ ++ if (ovl->info.enabled) { ++ DSSERR("overlay has to be disabled to unset the manager\n"); ++ return -EINVAL; ++ } ++ ++ r = ovl->wait_for_go(ovl); ++ if (r) ++ return r; ++ ++ ovl->manager = NULL; ++ ++ return 0; ++} ++ ++int omap_dss_get_num_overlays(void) ++{ ++ return num_overlays; ++} ++EXPORT_SYMBOL(omap_dss_get_num_overlays); ++ ++struct omap_overlay *omap_dss_get_overlay(int num) ++{ ++ int i = 0; ++ struct omap_overlay *ovl; ++ ++ list_for_each_entry(ovl, &overlay_list, list) { ++ if (i++ == num) ++ return ovl; ++ } ++ ++ return NULL; ++} ++EXPORT_SYMBOL(omap_dss_get_overlay); ++ ++static void omap_dss_add_overlay(struct omap_overlay *overlay) ++{ ++ ++num_overlays; ++ list_add_tail(&overlay->list, &overlay_list); ++} ++ ++static struct omap_overlay *dispc_overlays[3]; ++ ++void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr) ++{ ++ mgr->num_overlays = 3; ++ mgr->overlays = dispc_overlays; ++} ++ ++#ifdef L4_EXAMPLE ++static struct omap_overlay *l4_overlays[1]; ++void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr) ++{ ++ mgr->num_overlays = 1; ++ mgr->overlays = l4_overlays; ++} ++#endif ++ ++void dss_init_overlays(struct platform_device *pdev) ++{ ++ int i, r; ++ ++ INIT_LIST_HEAD(&overlay_list); ++ ++ num_overlays = 0; ++ ++ for (i = 0; i < 3; ++i) { ++ struct omap_overlay *ovl; ++ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); ++ ++ BUG_ON(ovl == NULL); ++ ++ switch (i) { ++ case 0: ++ ovl->name = "gfx"; ++ ovl->id = OMAP_DSS_GFX; ++ ovl->supported_modes = OMAP_DSS_COLOR_GFX_OMAP3; ++ ovl->caps = OMAP_DSS_OVL_CAP_DISPC; ++ ovl->info.global_alpha = 255; ++ break; ++ case 1: ++ ovl->name = "vid1"; ++ ovl->id = OMAP_DSS_VIDEO1; ++ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3; ++ ovl->caps = OMAP_DSS_OVL_CAP_SCALE | ++ OMAP_DSS_OVL_CAP_DISPC; ++ ovl->info.global_alpha = 255; ++ break; ++ case 2: ++ ovl->name = "vid2"; ++ ovl->id = OMAP_DSS_VIDEO2; ++ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3; ++ ovl->caps = OMAP_DSS_OVL_CAP_SCALE | ++ OMAP_DSS_OVL_CAP_DISPC; ++ ovl->info.global_alpha = 255; ++ break; ++ } ++ ++ ovl->set_manager = &omap_dss_set_manager; ++ ovl->unset_manager = &omap_dss_unset_manager; ++ ovl->set_overlay_info = &dss_ovl_set_overlay_info; ++ ovl->get_overlay_info = &dss_ovl_get_overlay_info; ++ ovl->wait_for_go = &dss_ovl_wait_for_go; ++ ++ omap_dss_add_overlay(ovl); ++ ++ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, ++ &pdev->dev.kobj, "overlay%d", i); ++ ++ if (r) { ++ DSSERR("failed to create sysfs file\n"); ++ continue; ++ } ++ ++ dispc_overlays[i] = ovl; ++ } ++ ++#ifdef L4_EXAMPLE ++ { ++ struct omap_overlay *ovl; ++ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); ++ ++ BUG_ON(ovl == NULL); ++ ++ ovl->name = "l4"; ++ ovl->supported_modes = OMAP_DSS_COLOR_RGB24U; ++ ++ ovl->set_manager = &omap_dss_set_manager; ++ ovl->unset_manager = &omap_dss_unset_manager; ++ ovl->set_overlay_info = &dss_ovl_set_overlay_info; ++ ovl->get_overlay_info = &dss_ovl_get_overlay_info; ++ ++ omap_dss_add_overlay(ovl); ++ ++ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, ++ &pdev->dev.kobj, "overlayl4"); ++ ++ if (r) ++ DSSERR("failed to create sysfs file\n"); ++ ++ l4_overlays[0] = ovl; ++ } ++#endif ++} ++ ++/* connect overlays to the new device, if not already connected. if force ++ * selected, connect always. */ ++void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) ++{ ++ int i; ++ struct omap_overlay_manager *lcd_mgr; ++ struct omap_overlay_manager *tv_mgr; ++ struct omap_overlay_manager *mgr = NULL; ++ ++ lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD); ++ tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV); ++ ++ if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { ++ if (!lcd_mgr->device || force) { ++ if (lcd_mgr->device) ++ lcd_mgr->unset_device(lcd_mgr); ++ lcd_mgr->set_device(lcd_mgr, dssdev); ++ mgr = lcd_mgr; ++ } ++ } ++ ++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { ++ if (!tv_mgr->device || force) { ++ if (tv_mgr->device) ++ tv_mgr->unset_device(tv_mgr); ++ tv_mgr->set_device(tv_mgr, dssdev); ++ mgr = tv_mgr; ++ } ++ } ++ ++ if (mgr) { ++ for (i = 0; i < 3; i++) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ if (!ovl->manager || force) { ++ if (ovl->manager) ++ omap_dss_unset_manager(ovl); ++ omap_dss_set_manager(ovl, mgr); ++ } ++ } ++ } ++} ++ ++void dss_uninit_overlays(struct platform_device *pdev) ++{ ++ struct omap_overlay *ovl; ++ ++ while (!list_empty(&overlay_list)) { ++ ovl = list_first_entry(&overlay_list, ++ struct omap_overlay, list); ++ list_del(&ovl->list); ++ kobject_del(&ovl->kobj); ++ kobject_put(&ovl->kobj); ++ kfree(ovl); ++ } ++ ++ num_overlays = 0; ++} ++ +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0009-OMAP-DSS2-DISPC.patch b/recipes/linux/linux-omap-2.6.31/dss2/0009-OMAP-DSS2-DISPC.patch new file mode 100644 index 0000000000..a558223c11 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0009-OMAP-DSS2-DISPC.patch @@ -0,0 +1,3204 @@ +From 8ec6585980444513ee55fbdf462dc36ca5fcbef4 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Fri, 7 Aug 2009 13:15:32 +0300 +Subject: [PATCH 09/18] OMAP: DSS2: DISPC + +This file implements DISPC (display controller) block of the OMAP DSS. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + drivers/video/omap2/dss/dispc.c | 3182 +++++++++++++++++++++++++++++++++++++++ + 1 files changed, 3182 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/dss/dispc.c + +diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c +new file mode 100644 +index 0000000..d648475 +--- /dev/null ++++ b/drivers/video/omap2/dss/dispc.c +@@ -0,0 +1,3182 @@ ++/* ++ * linux/drivers/video/omap2/dss/dispc.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "DISPC" ++ ++#include <linux/kernel.h> ++#include <linux/dma-mapping.h> ++#include <linux/vmalloc.h> ++#include <linux/clk.h> ++#include <linux/io.h> ++#include <linux/jiffies.h> ++#include <linux/seq_file.h> ++#include <linux/delay.h> ++#include <linux/workqueue.h> ++ ++#include <mach/sram.h> ++#include <mach/board.h> ++#include <mach/clock.h> ++ ++#include <mach/display.h> ++ ++#include "dss.h" ++ ++/* DISPC */ ++#define DISPC_BASE 0x48050400 ++ ++#define DISPC_SZ_REGS SZ_1K ++ ++struct dispc_reg { u16 idx; }; ++ ++#define DISPC_REG(idx) ((const struct dispc_reg) { idx }) ++ ++/* DISPC common */ ++#define DISPC_REVISION DISPC_REG(0x0000) ++#define DISPC_SYSCONFIG DISPC_REG(0x0010) ++#define DISPC_SYSSTATUS DISPC_REG(0x0014) ++#define DISPC_IRQSTATUS DISPC_REG(0x0018) ++#define DISPC_IRQENABLE DISPC_REG(0x001C) ++#define DISPC_CONTROL DISPC_REG(0x0040) ++#define DISPC_CONFIG DISPC_REG(0x0044) ++#define DISPC_CAPABLE DISPC_REG(0x0048) ++#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C) ++#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050) ++#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054) ++#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058) ++#define DISPC_LINE_STATUS DISPC_REG(0x005C) ++#define DISPC_LINE_NUMBER DISPC_REG(0x0060) ++#define DISPC_TIMING_H DISPC_REG(0x0064) ++#define DISPC_TIMING_V DISPC_REG(0x0068) ++#define DISPC_POL_FREQ DISPC_REG(0x006C) ++#define DISPC_DIVISOR DISPC_REG(0x0070) ++#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) ++#define DISPC_SIZE_DIG DISPC_REG(0x0078) ++#define DISPC_SIZE_LCD DISPC_REG(0x007C) ++ ++/* DISPC GFX plane */ ++#define DISPC_GFX_BA0 DISPC_REG(0x0080) ++#define DISPC_GFX_BA1 DISPC_REG(0x0084) ++#define DISPC_GFX_POSITION DISPC_REG(0x0088) ++#define DISPC_GFX_SIZE DISPC_REG(0x008C) ++#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0) ++#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4) ++#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8) ++#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC) ++#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0) ++#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4) ++#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8) ++ ++#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4) ++#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8) ++#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC) ++ ++#define DISPC_CPR_COEF_R DISPC_REG(0x0220) ++#define DISPC_CPR_COEF_G DISPC_REG(0x0224) ++#define DISPC_CPR_COEF_B DISPC_REG(0x0228) ++ ++#define DISPC_GFX_PRELOAD DISPC_REG(0x022C) ++ ++/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */ ++#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx) ++ ++#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000) ++#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004) ++#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008) ++#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C) ++#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010) ++#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014) ++#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018) ++#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C) ++#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020) ++#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024) ++#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028) ++#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C) ++#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030) ++ ++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ ++#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8) ++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ ++#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8) ++/* coef index i = {0, 1, 2, 3, 4} */ ++#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4) ++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ ++#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4) ++ ++#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) ++ ++ ++#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ ++ DISPC_IRQ_OCP_ERR | \ ++ DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ ++ DISPC_IRQ_VID2_FIFO_UNDERFLOW | \ ++ DISPC_IRQ_SYNC_LOST | \ ++ DISPC_IRQ_SYNC_LOST_DIGIT) ++ ++#define DISPC_MAX_NR_ISRS 8 ++ ++struct omap_dispc_isr_data { ++ omap_dispc_isr_t isr; ++ void *arg; ++ u32 mask; ++}; ++ ++#define REG_GET(idx, start, end) \ ++ FLD_GET(dispc_read_reg(idx), start, end) ++ ++#define REG_FLD_MOD(idx, val, start, end) \ ++ dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) ++ ++static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES, ++ DISPC_VID_ATTRIBUTES(0), ++ DISPC_VID_ATTRIBUTES(1) }; ++ ++static struct { ++ void __iomem *base; ++ ++ struct clk *dpll4_m4_ck; ++ ++ unsigned long cache_req_pck; ++ unsigned long cache_prate; ++ struct dispc_clock_info cache_cinfo; ++ ++ u32 fifo_size[3]; ++ ++ spinlock_t irq_lock; ++ u32 irq_error_mask; ++ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; ++ u32 error_irqs; ++ struct work_struct error_work; ++ ++ u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; ++} dispc; ++ ++static void _omap_dispc_set_irqs(void); ++ ++static inline void dispc_write_reg(const struct dispc_reg idx, u32 val) ++{ ++ __raw_writel(val, dispc.base + idx.idx); ++} ++ ++static inline u32 dispc_read_reg(const struct dispc_reg idx) ++{ ++ return __raw_readl(dispc.base + idx.idx); ++} ++ ++#define SR(reg) \ ++ dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg) ++#define RR(reg) \ ++ dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)]) ++ ++void dispc_save_context(void) ++{ ++ if (cpu_is_omap24xx()) ++ return; ++ ++ SR(SYSCONFIG); ++ SR(IRQENABLE); ++ SR(CONTROL); ++ SR(CONFIG); ++ SR(DEFAULT_COLOR0); ++ SR(DEFAULT_COLOR1); ++ SR(TRANS_COLOR0); ++ SR(TRANS_COLOR1); ++ SR(LINE_NUMBER); ++ SR(TIMING_H); ++ SR(TIMING_V); ++ SR(POL_FREQ); ++ SR(DIVISOR); ++ SR(GLOBAL_ALPHA); ++ SR(SIZE_DIG); ++ SR(SIZE_LCD); ++ ++ SR(GFX_BA0); ++ SR(GFX_BA1); ++ SR(GFX_POSITION); ++ SR(GFX_SIZE); ++ SR(GFX_ATTRIBUTES); ++ SR(GFX_FIFO_THRESHOLD); ++ SR(GFX_ROW_INC); ++ SR(GFX_PIXEL_INC); ++ SR(GFX_WINDOW_SKIP); ++ SR(GFX_TABLE_BA); ++ ++ SR(DATA_CYCLE1); ++ SR(DATA_CYCLE2); ++ SR(DATA_CYCLE3); ++ ++ SR(CPR_COEF_R); ++ SR(CPR_COEF_G); ++ SR(CPR_COEF_B); ++ ++ SR(GFX_PRELOAD); ++ ++ /* VID1 */ ++ SR(VID_BA0(0)); ++ SR(VID_BA1(0)); ++ SR(VID_POSITION(0)); ++ SR(VID_SIZE(0)); ++ SR(VID_ATTRIBUTES(0)); ++ SR(VID_FIFO_THRESHOLD(0)); ++ SR(VID_ROW_INC(0)); ++ SR(VID_PIXEL_INC(0)); ++ SR(VID_FIR(0)); ++ SR(VID_PICTURE_SIZE(0)); ++ SR(VID_ACCU0(0)); ++ SR(VID_ACCU1(0)); ++ ++ SR(VID_FIR_COEF_H(0, 0)); ++ SR(VID_FIR_COEF_H(0, 1)); ++ SR(VID_FIR_COEF_H(0, 2)); ++ SR(VID_FIR_COEF_H(0, 3)); ++ SR(VID_FIR_COEF_H(0, 4)); ++ SR(VID_FIR_COEF_H(0, 5)); ++ SR(VID_FIR_COEF_H(0, 6)); ++ SR(VID_FIR_COEF_H(0, 7)); ++ ++ SR(VID_FIR_COEF_HV(0, 0)); ++ SR(VID_FIR_COEF_HV(0, 1)); ++ SR(VID_FIR_COEF_HV(0, 2)); ++ SR(VID_FIR_COEF_HV(0, 3)); ++ SR(VID_FIR_COEF_HV(0, 4)); ++ SR(VID_FIR_COEF_HV(0, 5)); ++ SR(VID_FIR_COEF_HV(0, 6)); ++ SR(VID_FIR_COEF_HV(0, 7)); ++ ++ SR(VID_CONV_COEF(0, 0)); ++ SR(VID_CONV_COEF(0, 1)); ++ SR(VID_CONV_COEF(0, 2)); ++ SR(VID_CONV_COEF(0, 3)); ++ SR(VID_CONV_COEF(0, 4)); ++ ++ SR(VID_FIR_COEF_V(0, 0)); ++ SR(VID_FIR_COEF_V(0, 1)); ++ SR(VID_FIR_COEF_V(0, 2)); ++ SR(VID_FIR_COEF_V(0, 3)); ++ SR(VID_FIR_COEF_V(0, 4)); ++ SR(VID_FIR_COEF_V(0, 5)); ++ SR(VID_FIR_COEF_V(0, 6)); ++ SR(VID_FIR_COEF_V(0, 7)); ++ ++ SR(VID_PRELOAD(0)); ++ ++ /* VID2 */ ++ SR(VID_BA0(1)); ++ SR(VID_BA1(1)); ++ SR(VID_POSITION(1)); ++ SR(VID_SIZE(1)); ++ SR(VID_ATTRIBUTES(1)); ++ SR(VID_FIFO_THRESHOLD(1)); ++ SR(VID_ROW_INC(1)); ++ SR(VID_PIXEL_INC(1)); ++ SR(VID_FIR(1)); ++ SR(VID_PICTURE_SIZE(1)); ++ SR(VID_ACCU0(1)); ++ SR(VID_ACCU1(1)); ++ ++ SR(VID_FIR_COEF_H(1, 0)); ++ SR(VID_FIR_COEF_H(1, 1)); ++ SR(VID_FIR_COEF_H(1, 2)); ++ SR(VID_FIR_COEF_H(1, 3)); ++ SR(VID_FIR_COEF_H(1, 4)); ++ SR(VID_FIR_COEF_H(1, 5)); ++ SR(VID_FIR_COEF_H(1, 6)); ++ SR(VID_FIR_COEF_H(1, 7)); ++ ++ SR(VID_FIR_COEF_HV(1, 0)); ++ SR(VID_FIR_COEF_HV(1, 1)); ++ SR(VID_FIR_COEF_HV(1, 2)); ++ SR(VID_FIR_COEF_HV(1, 3)); ++ SR(VID_FIR_COEF_HV(1, 4)); ++ SR(VID_FIR_COEF_HV(1, 5)); ++ SR(VID_FIR_COEF_HV(1, 6)); ++ SR(VID_FIR_COEF_HV(1, 7)); ++ ++ SR(VID_CONV_COEF(1, 0)); ++ SR(VID_CONV_COEF(1, 1)); ++ SR(VID_CONV_COEF(1, 2)); ++ SR(VID_CONV_COEF(1, 3)); ++ SR(VID_CONV_COEF(1, 4)); ++ ++ SR(VID_FIR_COEF_V(1, 0)); ++ SR(VID_FIR_COEF_V(1, 1)); ++ SR(VID_FIR_COEF_V(1, 2)); ++ SR(VID_FIR_COEF_V(1, 3)); ++ SR(VID_FIR_COEF_V(1, 4)); ++ SR(VID_FIR_COEF_V(1, 5)); ++ SR(VID_FIR_COEF_V(1, 6)); ++ SR(VID_FIR_COEF_V(1, 7)); ++ ++ SR(VID_PRELOAD(1)); ++} ++ ++void dispc_restore_context(void) ++{ ++ RR(SYSCONFIG); ++ RR(IRQENABLE); ++ /*RR(CONTROL);*/ ++ RR(CONFIG); ++ RR(DEFAULT_COLOR0); ++ RR(DEFAULT_COLOR1); ++ RR(TRANS_COLOR0); ++ RR(TRANS_COLOR1); ++ RR(LINE_NUMBER); ++ RR(TIMING_H); ++ RR(TIMING_V); ++ RR(POL_FREQ); ++ RR(DIVISOR); ++ RR(GLOBAL_ALPHA); ++ RR(SIZE_DIG); ++ RR(SIZE_LCD); ++ ++ RR(GFX_BA0); ++ RR(GFX_BA1); ++ RR(GFX_POSITION); ++ RR(GFX_SIZE); ++ RR(GFX_ATTRIBUTES); ++ RR(GFX_FIFO_THRESHOLD); ++ RR(GFX_ROW_INC); ++ RR(GFX_PIXEL_INC); ++ RR(GFX_WINDOW_SKIP); ++ RR(GFX_TABLE_BA); ++ ++ RR(DATA_CYCLE1); ++ RR(DATA_CYCLE2); ++ RR(DATA_CYCLE3); ++ ++ RR(CPR_COEF_R); ++ RR(CPR_COEF_G); ++ RR(CPR_COEF_B); ++ ++ RR(GFX_PRELOAD); ++ ++ /* VID1 */ ++ RR(VID_BA0(0)); ++ RR(VID_BA1(0)); ++ RR(VID_POSITION(0)); ++ RR(VID_SIZE(0)); ++ RR(VID_ATTRIBUTES(0)); ++ RR(VID_FIFO_THRESHOLD(0)); ++ RR(VID_ROW_INC(0)); ++ RR(VID_PIXEL_INC(0)); ++ RR(VID_FIR(0)); ++ RR(VID_PICTURE_SIZE(0)); ++ RR(VID_ACCU0(0)); ++ RR(VID_ACCU1(0)); ++ ++ RR(VID_FIR_COEF_H(0, 0)); ++ RR(VID_FIR_COEF_H(0, 1)); ++ RR(VID_FIR_COEF_H(0, 2)); ++ RR(VID_FIR_COEF_H(0, 3)); ++ RR(VID_FIR_COEF_H(0, 4)); ++ RR(VID_FIR_COEF_H(0, 5)); ++ RR(VID_FIR_COEF_H(0, 6)); ++ RR(VID_FIR_COEF_H(0, 7)); ++ ++ RR(VID_FIR_COEF_HV(0, 0)); ++ RR(VID_FIR_COEF_HV(0, 1)); ++ RR(VID_FIR_COEF_HV(0, 2)); ++ RR(VID_FIR_COEF_HV(0, 3)); ++ RR(VID_FIR_COEF_HV(0, 4)); ++ RR(VID_FIR_COEF_HV(0, 5)); ++ RR(VID_FIR_COEF_HV(0, 6)); ++ RR(VID_FIR_COEF_HV(0, 7)); ++ ++ RR(VID_CONV_COEF(0, 0)); ++ RR(VID_CONV_COEF(0, 1)); ++ RR(VID_CONV_COEF(0, 2)); ++ RR(VID_CONV_COEF(0, 3)); ++ RR(VID_CONV_COEF(0, 4)); ++ ++ RR(VID_FIR_COEF_V(0, 0)); ++ RR(VID_FIR_COEF_V(0, 1)); ++ RR(VID_FIR_COEF_V(0, 2)); ++ RR(VID_FIR_COEF_V(0, 3)); ++ RR(VID_FIR_COEF_V(0, 4)); ++ RR(VID_FIR_COEF_V(0, 5)); ++ RR(VID_FIR_COEF_V(0, 6)); ++ RR(VID_FIR_COEF_V(0, 7)); ++ ++ RR(VID_PRELOAD(0)); ++ ++ /* VID2 */ ++ RR(VID_BA0(1)); ++ RR(VID_BA1(1)); ++ RR(VID_POSITION(1)); ++ RR(VID_SIZE(1)); ++ RR(VID_ATTRIBUTES(1)); ++ RR(VID_FIFO_THRESHOLD(1)); ++ RR(VID_ROW_INC(1)); ++ RR(VID_PIXEL_INC(1)); ++ RR(VID_FIR(1)); ++ RR(VID_PICTURE_SIZE(1)); ++ RR(VID_ACCU0(1)); ++ RR(VID_ACCU1(1)); ++ ++ RR(VID_FIR_COEF_H(1, 0)); ++ RR(VID_FIR_COEF_H(1, 1)); ++ RR(VID_FIR_COEF_H(1, 2)); ++ RR(VID_FIR_COEF_H(1, 3)); ++ RR(VID_FIR_COEF_H(1, 4)); ++ RR(VID_FIR_COEF_H(1, 5)); ++ RR(VID_FIR_COEF_H(1, 6)); ++ RR(VID_FIR_COEF_H(1, 7)); ++ ++ RR(VID_FIR_COEF_HV(1, 0)); ++ RR(VID_FIR_COEF_HV(1, 1)); ++ RR(VID_FIR_COEF_HV(1, 2)); ++ RR(VID_FIR_COEF_HV(1, 3)); ++ RR(VID_FIR_COEF_HV(1, 4)); ++ RR(VID_FIR_COEF_HV(1, 5)); ++ RR(VID_FIR_COEF_HV(1, 6)); ++ RR(VID_FIR_COEF_HV(1, 7)); ++ ++ RR(VID_CONV_COEF(1, 0)); ++ RR(VID_CONV_COEF(1, 1)); ++ RR(VID_CONV_COEF(1, 2)); ++ RR(VID_CONV_COEF(1, 3)); ++ RR(VID_CONV_COEF(1, 4)); ++ ++ RR(VID_FIR_COEF_V(1, 0)); ++ RR(VID_FIR_COEF_V(1, 1)); ++ RR(VID_FIR_COEF_V(1, 2)); ++ RR(VID_FIR_COEF_V(1, 3)); ++ RR(VID_FIR_COEF_V(1, 4)); ++ RR(VID_FIR_COEF_V(1, 5)); ++ RR(VID_FIR_COEF_V(1, 6)); ++ RR(VID_FIR_COEF_V(1, 7)); ++ ++ RR(VID_PRELOAD(1)); ++ ++ /* enable last, because LCD & DIGIT enable are here */ ++ RR(CONTROL); ++} ++ ++#undef SR ++#undef RR ++ ++static inline void enable_clocks(bool enable) ++{ ++ if (enable) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ else ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++} ++ ++bool dispc_go_busy(enum omap_channel channel) ++{ ++ int bit; ++ ++ if (channel == OMAP_DSS_CHANNEL_LCD) ++ bit = 5; /* GOLCD */ ++ else ++ bit = 6; /* GODIGIT */ ++ ++ return REG_GET(DISPC_CONTROL, bit, bit) == 1; ++} ++ ++void dispc_go(enum omap_channel channel) ++{ ++ int bit; ++ ++ enable_clocks(1); ++ ++ if (channel == OMAP_DSS_CHANNEL_LCD) ++ bit = 0; /* LCDENABLE */ ++ else ++ bit = 1; /* DIGITALENABLE */ ++ ++ /* if the channel is not enabled, we don't need GO */ ++ if (REG_GET(DISPC_CONTROL, bit, bit) == 0) ++ goto end; ++ ++ if (channel == OMAP_DSS_CHANNEL_LCD) ++ bit = 5; /* GOLCD */ ++ else ++ bit = 6; /* GODIGIT */ ++ ++ if (REG_GET(DISPC_CONTROL, bit, bit) == 1) { ++ DSSERR("GO bit not down for channel %d\n", channel); ++ goto end; ++ } ++ ++ DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT"); ++ ++ REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); ++end: ++ enable_clocks(0); ++} ++ ++static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) ++{ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value); ++} ++ ++static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) ++{ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value); ++} ++ ++static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) ++{ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value); ++} ++ ++static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, ++ int vscaleup, int five_taps) ++{ ++ /* Coefficients for horizontal up-sampling */ ++ static const u32 coef_hup[8] = { ++ 0x00800000, ++ 0x0D7CF800, ++ 0x1E70F5FF, ++ 0x335FF5FE, ++ 0xF74949F7, ++ 0xF55F33FB, ++ 0xF5701EFE, ++ 0xF87C0DFF, ++ }; ++ ++ /* Coefficients for horizontal down-sampling */ ++ static const u32 coef_hdown[8] = { ++ 0x24382400, ++ 0x28371FFE, ++ 0x2C361BFB, ++ 0x303516F9, ++ 0x11343311, ++ 0x1635300C, ++ 0x1B362C08, ++ 0x1F372804, ++ }; ++ ++ /* Coefficients for horizontal and vertical up-sampling */ ++ static const u32 coef_hvup[2][8] = { ++ { ++ 0x00800000, ++ 0x037B02FF, ++ 0x0C6F05FE, ++ 0x205907FB, ++ 0x00404000, ++ 0x075920FE, ++ 0x056F0CFF, ++ 0x027B0300, ++ }, ++ { ++ 0x00800000, ++ 0x0D7CF8FF, ++ 0x1E70F5FE, ++ 0x335FF5FB, ++ 0xF7404000, ++ 0xF55F33FE, ++ 0xF5701EFF, ++ 0xF87C0D00, ++ }, ++ }; ++ ++ /* Coefficients for horizontal and vertical down-sampling */ ++ static const u32 coef_hvdown[2][8] = { ++ { ++ 0x24382400, ++ 0x28391F04, ++ 0x2D381B08, ++ 0x3237170C, ++ 0x123737F7, ++ 0x173732F9, ++ 0x1B382DFB, ++ 0x1F3928FE, ++ }, ++ { ++ 0x24382400, ++ 0x28371F04, ++ 0x2C361B08, ++ 0x3035160C, ++ 0x113433F7, ++ 0x163530F9, ++ 0x1B362CFB, ++ 0x1F3728FE, ++ }, ++ }; ++ ++ /* Coefficients for vertical up-sampling */ ++ static const u32 coef_vup[8] = { ++ 0x00000000, ++ 0x0000FF00, ++ 0x0000FEFF, ++ 0x0000FBFE, ++ 0x000000F7, ++ 0x0000FEFB, ++ 0x0000FFFE, ++ 0x000000FF, ++ }; ++ ++ ++ /* Coefficients for vertical down-sampling */ ++ static const u32 coef_vdown[8] = { ++ 0x00000000, ++ 0x000004FE, ++ 0x000008FB, ++ 0x00000CF9, ++ 0x0000F711, ++ 0x0000F90C, ++ 0x0000FB08, ++ 0x0000FE04, ++ }; ++ ++ const u32 *h_coef; ++ const u32 *hv_coef; ++ const u32 *hv_coef_mod; ++ const u32 *v_coef; ++ int i; ++ ++ if (hscaleup) ++ h_coef = coef_hup; ++ else ++ h_coef = coef_hdown; ++ ++ if (vscaleup) { ++ hv_coef = coef_hvup[five_taps]; ++ v_coef = coef_vup; ++ ++ if (hscaleup) ++ hv_coef_mod = NULL; ++ else ++ hv_coef_mod = coef_hvdown[five_taps]; ++ } else { ++ hv_coef = coef_hvdown[five_taps]; ++ v_coef = coef_vdown; ++ ++ if (hscaleup) ++ hv_coef_mod = coef_hvup[five_taps]; ++ else ++ hv_coef_mod = NULL; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ u32 h, hv; ++ ++ h = h_coef[i]; ++ ++ hv = hv_coef[i]; ++ ++ if (hv_coef_mod) { ++ hv &= 0xffffff00; ++ hv |= (hv_coef_mod[i] & 0xff); ++ } ++ ++ _dispc_write_firh_reg(plane, i, h); ++ _dispc_write_firhv_reg(plane, i, hv); ++ } ++ ++ if (!five_taps) ++ return; ++ ++ for (i = 0; i < 8; i++) { ++ u32 v; ++ v = v_coef[i]; ++ _dispc_write_firv_reg(plane, i, v); ++ } ++} ++ ++static void _dispc_setup_color_conv_coef(void) ++{ ++ const struct color_conv_coef { ++ int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; ++ int full_range; ++ } ctbl_bt601_5 = { ++ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, ++ }; ++ ++ const struct color_conv_coef *ct; ++ ++#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) ++ ++ ct = &ctbl_bt601_5; ++ ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb)); ++ ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb)); ++ ++#undef CVAL ++ ++ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11); ++ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11); ++} ++ ++ ++static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) ++{ ++ const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0, ++ DISPC_VID_BA0(0), ++ DISPC_VID_BA0(1) }; ++ ++ dispc_write_reg(ba0_reg[plane], paddr); ++} ++ ++static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) ++{ ++ const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1, ++ DISPC_VID_BA1(0), ++ DISPC_VID_BA1(1) }; ++ ++ dispc_write_reg(ba1_reg[plane], paddr); ++} ++ ++static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) ++{ ++ const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION, ++ DISPC_VID_POSITION(0), ++ DISPC_VID_POSITION(1) }; ++ ++ u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); ++ dispc_write_reg(pos_reg[plane], val); ++} ++ ++static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) ++{ ++ const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE, ++ DISPC_VID_PICTURE_SIZE(0), ++ DISPC_VID_PICTURE_SIZE(1) }; ++ u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ dispc_write_reg(siz_reg[plane], val); ++} ++ ++static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) ++{ ++ u32 val; ++ const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0), ++ DISPC_VID_SIZE(1) }; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ dispc_write_reg(vsi_reg[plane-1], val); ++} ++ ++static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) ++{ ++ ++ BUG_ON(plane == OMAP_DSS_VIDEO1); ++ ++ if (plane == OMAP_DSS_GFX) ++ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0); ++ else if (plane == OMAP_DSS_VIDEO2) ++ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16); ++} ++ ++static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) ++{ ++ const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC, ++ DISPC_VID_PIXEL_INC(0), ++ DISPC_VID_PIXEL_INC(1) }; ++ ++ dispc_write_reg(ri_reg[plane], inc); ++} ++ ++static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) ++{ ++ const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC, ++ DISPC_VID_ROW_INC(0), ++ DISPC_VID_ROW_INC(1) }; ++ ++ dispc_write_reg(ri_reg[plane], inc); ++} ++ ++static void _dispc_set_color_mode(enum omap_plane plane, ++ enum omap_color_mode color_mode) ++{ ++ u32 m = 0; ++ ++ switch (color_mode) { ++ case OMAP_DSS_COLOR_CLUT1: ++ m = 0x0; break; ++ case OMAP_DSS_COLOR_CLUT2: ++ m = 0x1; break; ++ case OMAP_DSS_COLOR_CLUT4: ++ m = 0x2; break; ++ case OMAP_DSS_COLOR_CLUT8: ++ m = 0x3; break; ++ case OMAP_DSS_COLOR_RGB12U: ++ m = 0x4; break; ++ case OMAP_DSS_COLOR_ARGB16: ++ m = 0x5; break; ++ case OMAP_DSS_COLOR_RGB16: ++ m = 0x6; break; ++ case OMAP_DSS_COLOR_RGB24U: ++ m = 0x8; break; ++ case OMAP_DSS_COLOR_RGB24P: ++ m = 0x9; break; ++ case OMAP_DSS_COLOR_YUV2: ++ m = 0xa; break; ++ case OMAP_DSS_COLOR_UYVY: ++ m = 0xb; break; ++ case OMAP_DSS_COLOR_ARGB32: ++ m = 0xc; break; ++ case OMAP_DSS_COLOR_RGBA32: ++ m = 0xd; break; ++ case OMAP_DSS_COLOR_RGBX32: ++ m = 0xe; break; ++ default: ++ BUG(); break; ++ } ++ ++ REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1); ++} ++ ++static void _dispc_set_channel_out(enum omap_plane plane, ++ enum omap_channel channel) ++{ ++ int shift; ++ u32 val; ++ ++ switch (plane) { ++ case OMAP_DSS_GFX: ++ shift = 8; ++ break; ++ case OMAP_DSS_VIDEO1: ++ case OMAP_DSS_VIDEO2: ++ shift = 16; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ val = dispc_read_reg(dispc_reg_att[plane]); ++ val = FLD_MOD(val, channel, shift, shift); ++ dispc_write_reg(dispc_reg_att[plane], val); ++} ++ ++void dispc_set_burst_size(enum omap_plane plane, ++ enum omap_burst_size burst_size) ++{ ++ int shift; ++ u32 val; ++ ++ enable_clocks(1); ++ ++ switch (plane) { ++ case OMAP_DSS_GFX: ++ shift = 6; ++ break; ++ case OMAP_DSS_VIDEO1: ++ case OMAP_DSS_VIDEO2: ++ shift = 14; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ val = dispc_read_reg(dispc_reg_att[plane]); ++ val = FLD_MOD(val, burst_size, shift+1, shift); ++ dispc_write_reg(dispc_reg_att[plane], val); ++ ++ enable_clocks(0); ++} ++ ++static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) ++{ ++ u32 val; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ val = dispc_read_reg(dispc_reg_att[plane]); ++ val = FLD_MOD(val, enable, 9, 9); ++ dispc_write_reg(dispc_reg_att[plane], val); ++} ++ ++void dispc_enable_replication(enum omap_plane plane, bool enable) ++{ ++ int bit; ++ ++ if (plane == OMAP_DSS_GFX) ++ bit = 5; ++ else ++ bit = 10; ++ ++ enable_clocks(1); ++ REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit); ++ enable_clocks(0); ++} ++ ++void dispc_set_lcd_size(u16 width, u16 height) ++{ ++ u32 val; ++ BUG_ON((width > (1 << 11)) || (height > (1 << 11))); ++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ enable_clocks(1); ++ dispc_write_reg(DISPC_SIZE_LCD, val); ++ enable_clocks(0); ++} ++ ++void dispc_set_digit_size(u16 width, u16 height) ++{ ++ u32 val; ++ BUG_ON((width > (1 << 11)) || (height > (1 << 11))); ++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ enable_clocks(1); ++ dispc_write_reg(DISPC_SIZE_DIG, val); ++ enable_clocks(0); ++} ++ ++static void dispc_read_plane_fifo_sizes(void) ++{ ++ const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, ++ DISPC_VID_FIFO_SIZE_STATUS(0), ++ DISPC_VID_FIFO_SIZE_STATUS(1) }; ++ u32 size; ++ int plane; ++ ++ enable_clocks(1); ++ ++ for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { ++ if (cpu_is_omap24xx()) ++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0); ++ else if (cpu_is_omap34xx()) ++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0); ++ else ++ BUG(); ++ ++ dispc.fifo_size[plane] = size; ++ } ++ ++ enable_clocks(0); ++} ++ ++u32 dispc_get_plane_fifo_size(enum omap_plane plane) ++{ ++ return dispc.fifo_size[plane]; ++} ++ ++void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) ++{ ++ const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, ++ DISPC_VID_FIFO_THRESHOLD(0), ++ DISPC_VID_FIFO_THRESHOLD(1) }; ++ enable_clocks(1); ++ ++ DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", ++ plane, ++ REG_GET(ftrs_reg[plane], 11, 0), ++ REG_GET(ftrs_reg[plane], 27, 16), ++ low, high); ++ ++ if (cpu_is_omap24xx()) ++ dispc_write_reg(ftrs_reg[plane], ++ FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0)); ++ else ++ dispc_write_reg(ftrs_reg[plane], ++ FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0)); ++ ++ enable_clocks(0); ++} ++ ++void dispc_enable_fifomerge(bool enable) ++{ ++ enable_clocks(1); ++ ++ DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); ++ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); ++ ++ enable_clocks(0); ++} ++ ++static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc) ++{ ++ u32 val; ++ const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0), ++ DISPC_VID_FIR(1) }; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ if (cpu_is_omap24xx()) ++ val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0); ++ else ++ val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0); ++ dispc_write_reg(fir_reg[plane-1], val); ++} ++ ++static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) ++{ ++ u32 val; ++ const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), ++ DISPC_VID_ACCU0(1) }; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); ++ dispc_write_reg(ac0_reg[plane-1], val); ++} ++ ++static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) ++{ ++ u32 val; ++ const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), ++ DISPC_VID_ACCU1(1) }; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); ++ dispc_write_reg(ac1_reg[plane-1], val); ++} ++ ++ ++static void _dispc_set_scaling(enum omap_plane plane, ++ u16 orig_width, u16 orig_height, ++ u16 out_width, u16 out_height, ++ bool ilace, bool five_taps, ++ bool fieldmode) ++{ ++ int fir_hinc; ++ int fir_vinc; ++ int hscaleup, vscaleup; ++ int accu0 = 0; ++ int accu1 = 0; ++ u32 l; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ hscaleup = orig_width <= out_width; ++ vscaleup = orig_height <= out_height; ++ ++ _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps); ++ ++ if (!orig_width || orig_width == out_width) ++ fir_hinc = 0; ++ else ++ fir_hinc = 1024 * orig_width / out_width; ++ ++ if (!orig_height || orig_height == out_height) ++ fir_vinc = 0; ++ else ++ fir_vinc = 1024 * orig_height / out_height; ++ ++ _dispc_set_fir(plane, fir_hinc, fir_vinc); ++ ++ l = dispc_read_reg(dispc_reg_att[plane]); ++ l &= ~((0x0f << 5) | (0x3 << 21)); ++ ++ l |= fir_hinc ? (1 << 5) : 0; ++ l |= fir_vinc ? (1 << 6) : 0; ++ ++ l |= hscaleup ? 0 : (1 << 7); ++ l |= vscaleup ? 0 : (1 << 8); ++ ++ l |= five_taps ? (1 << 21) : 0; ++ l |= five_taps ? (1 << 22) : 0; ++ ++ dispc_write_reg(dispc_reg_att[plane], l); ++ ++ /* ++ * field 0 = even field = bottom field ++ * field 1 = odd field = top field ++ */ ++ if (ilace && !fieldmode) { ++ accu1 = 0; ++ accu0 = (fir_vinc / 2) & 0x3ff; ++ if (accu0 >= 1024/2) { ++ accu1 = 1024/2; ++ accu0 -= accu1; ++ } ++ } ++ ++ _dispc_set_vid_accu0(plane, 0, accu0); ++ _dispc_set_vid_accu1(plane, 0, accu1); ++} ++ ++static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, ++ bool mirroring, enum omap_color_mode color_mode) ++{ ++ if (color_mode == OMAP_DSS_COLOR_YUV2 || ++ color_mode == OMAP_DSS_COLOR_UYVY) { ++ int vidrot = 0; ++ ++ if (mirroring) { ++ switch (rotation) { ++ case 0: ++ vidrot = 2; ++ break; ++ case 1: ++ vidrot = 1; ++ break; ++ case 2: ++ vidrot = 0; ++ break; ++ case 3: ++ vidrot = 3; ++ break; ++ } ++ } else { ++ switch (rotation) { ++ case 0: ++ vidrot = 0; ++ break; ++ case 1: ++ vidrot = 1; ++ break; ++ case 2: ++ vidrot = 2; ++ break; ++ case 3: ++ vidrot = 3; ++ break; ++ } ++ } ++ ++ REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); ++ ++ if (rotation == 1 || rotation == 3) ++ REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18); ++ else ++ REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18); ++ } else { ++ REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12); ++ REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18); ++ } ++} ++ ++static s32 pixinc(int pixels, u8 ps) ++{ ++ if (pixels == 1) ++ return 1; ++ else if (pixels > 1) ++ return 1 + (pixels - 1) * ps; ++ else if (pixels < 0) ++ return 1 - (-pixels + 1) * ps; ++ else ++ BUG(); ++} ++ ++static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, ++ u16 screen_width, ++ u16 width, u16 height, ++ enum omap_color_mode color_mode, bool fieldmode, ++ unsigned int field_offset, ++ unsigned *offset0, unsigned *offset1, ++ s32 *row_inc, s32 *pix_inc) ++{ ++ u8 ps; ++ ++ switch (color_mode) { ++ case OMAP_DSS_COLOR_RGB16: ++ case OMAP_DSS_COLOR_ARGB16: ++ ps = 2; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24P: ++ ps = 3; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24U: ++ case OMAP_DSS_COLOR_ARGB32: ++ case OMAP_DSS_COLOR_RGBA32: ++ case OMAP_DSS_COLOR_RGBX32: ++ case OMAP_DSS_COLOR_YUV2: ++ case OMAP_DSS_COLOR_UYVY: ++ ps = 4; ++ break; ++ ++ default: ++ BUG(); ++ return; ++ } ++ ++ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width, ++ width, height); ++ ++ /* ++ * field 0 = even field = bottom field ++ * field 1 = odd field = top field ++ */ ++ switch (rotation + mirror * 4) { ++ case 0: ++ case 2: ++ /* ++ * If the pixel format is YUV or UYVY divide the width ++ * of the image by 2 for 0 and 180 degree rotation. ++ */ ++ if (color_mode == OMAP_DSS_COLOR_YUV2 || ++ color_mode == OMAP_DSS_COLOR_UYVY) ++ width = width >> 1; ++ case 1: ++ case 3: ++ *offset1 = 0; ++ if (field_offset) ++ *offset0 = field_offset * screen_width * ps; ++ else ++ *offset0 = 0; ++ ++ *row_inc = pixinc(1 + (screen_width - width) + ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(1, ps); ++ break; ++ ++ case 4: ++ case 6: ++ /* If the pixel format is YUV or UYVY divide the width ++ * of the image by 2 for 0 degree and 180 degree ++ */ ++ if (color_mode == OMAP_DSS_COLOR_YUV2 || ++ color_mode == OMAP_DSS_COLOR_UYVY) ++ width = width >> 1; ++ case 5: ++ case 7: ++ *offset1 = 0; ++ if (field_offset) ++ *offset0 = field_offset * screen_width * ps; ++ else ++ *offset0 = 0; ++ *row_inc = pixinc(1 - (screen_width + width) - ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(1, ps); ++ break; ++ ++ default: ++ BUG(); ++ } ++} ++ ++static void calc_dma_rotation_offset(u8 rotation, bool mirror, ++ u16 screen_width, ++ u16 width, u16 height, ++ enum omap_color_mode color_mode, bool fieldmode, ++ unsigned int field_offset, ++ unsigned *offset0, unsigned *offset1, ++ s32 *row_inc, s32 *pix_inc) ++{ ++ u8 ps; ++ u16 fbw, fbh; ++ ++ switch (color_mode) { ++ case OMAP_DSS_COLOR_RGB16: ++ case OMAP_DSS_COLOR_ARGB16: ++ ps = 2; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24P: ++ ps = 3; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24U: ++ case OMAP_DSS_COLOR_ARGB32: ++ case OMAP_DSS_COLOR_RGBA32: ++ case OMAP_DSS_COLOR_RGBX32: ++ ps = 4; ++ break; ++ ++ case OMAP_DSS_COLOR_YUV2: ++ case OMAP_DSS_COLOR_UYVY: ++ ps = 2; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width, ++ width, height); ++ ++ /* width & height are overlay sizes, convert to fb sizes */ ++ ++ if (rotation == 0 || rotation == 2) { ++ fbw = width; ++ fbh = height; ++ } else { ++ fbw = height; ++ fbh = width; ++ } ++ ++ /* ++ * field 0 = even field = bottom field ++ * field 1 = odd field = top field ++ */ ++ switch (rotation + mirror * 4) { ++ case 0: ++ *offset1 = 0; ++ if (field_offset) ++ *offset0 = *offset1 + field_offset * screen_width * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(1 + (screen_width - fbw) + ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(1, ps); ++ break; ++ case 1: ++ *offset1 = screen_width * (fbh - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 + field_offset * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(screen_width * (fbh - 1) + 1 + ++ (fieldmode ? 1 : 0), ps); ++ *pix_inc = pixinc(-screen_width, ps); ++ break; ++ case 2: ++ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 - field_offset * screen_width * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(-1 - ++ (screen_width - fbw) - ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(-1, ps); ++ break; ++ case 3: ++ *offset1 = (fbw - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 - field_offset * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(-screen_width * (fbh - 1) - 1 - ++ (fieldmode ? 1 : 0), ps); ++ *pix_inc = pixinc(screen_width, ps); ++ break; ++ ++ /* mirroring */ ++ case 0 + 4: ++ *offset1 = (fbw - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 + field_offset * screen_width * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(screen_width * 2 - 1 + ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(-1, ps); ++ break; ++ ++ case 1 + 4: ++ *offset1 = 0; ++ if (field_offset) ++ *offset0 = *offset1 + field_offset * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(-screen_width * (fbh - 1) + 1 + ++ (fieldmode ? 1 : 0), ++ ps); ++ *pix_inc = pixinc(screen_width, ps); ++ break; ++ ++ case 2 + 4: ++ *offset1 = screen_width * (fbh - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 - field_offset * screen_width * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(1 - screen_width * 2 - ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(1, ps); ++ break; ++ ++ case 3 + 4: ++ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 - field_offset * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(screen_width * (fbh - 1) - 1 - ++ (fieldmode ? 1 : 0), ++ ps); ++ *pix_inc = pixinc(-screen_width, ps); ++ break; ++ ++ default: ++ BUG(); ++ } ++} ++ ++static unsigned long calc_fclk_five_taps(u16 width, u16 height, ++ u16 out_width, u16 out_height, enum omap_color_mode color_mode) ++{ ++ u32 fclk = 0; ++ /* FIXME venc pclk? */ ++ u64 tmp, pclk = dispc_pclk_rate(); ++ ++ if (height > out_height) { ++ /* FIXME get real display PPL */ ++ unsigned int ppl = 800; ++ ++ tmp = pclk * height * out_width; ++ do_div(tmp, 2 * out_height * ppl); ++ fclk = tmp; ++ ++ if (height > 2 * out_height && ppl != out_width) { ++ tmp = pclk * (height - 2 * out_height) * out_width; ++ do_div(tmp, 2 * out_height * (ppl - out_width)); ++ fclk = max(fclk, (u32) tmp); ++ } ++ } ++ ++ if (width > out_width) { ++ tmp = pclk * width; ++ do_div(tmp, out_width); ++ fclk = max(fclk, (u32) tmp); ++ ++ if (color_mode == OMAP_DSS_COLOR_RGB24U) ++ fclk <<= 1; ++ } ++ ++ return fclk; ++} ++ ++static unsigned long calc_fclk(u16 width, u16 height, ++ u16 out_width, u16 out_height) ++{ ++ unsigned int hf, vf; ++ ++ /* ++ * FIXME how to determine the 'A' factor ++ * for the no downscaling case ? ++ */ ++ ++ if (width > 3 * out_width) ++ hf = 4; ++ else if (width > 2 * out_width) ++ hf = 3; ++ else if (width > out_width) ++ hf = 2; ++ else ++ hf = 1; ++ ++ if (height > out_height) ++ vf = 2; ++ else ++ vf = 1; ++ ++ /* FIXME venc pclk? */ ++ return dispc_pclk_rate() * vf * hf; ++} ++ ++void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) ++{ ++ enable_clocks(1); ++ _dispc_set_channel_out(plane, channel_out); ++ enable_clocks(0); ++} ++ ++static int _dispc_setup_plane(enum omap_plane plane, ++ u32 paddr, u16 screen_width, ++ u16 pos_x, u16 pos_y, ++ u16 width, u16 height, ++ u16 out_width, u16 out_height, ++ enum omap_color_mode color_mode, ++ bool ilace, ++ enum omap_dss_rotation_type rotation_type, ++ u8 rotation, int mirror, ++ u8 global_alpha) ++{ ++ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; ++ bool five_taps = 0; ++ bool fieldmode = 0; ++ int cconv = 0; ++ unsigned offset0, offset1; ++ s32 row_inc; ++ s32 pix_inc; ++ u16 frame_height = height; ++ unsigned int field_offset = 0; ++ ++ if (paddr == 0) ++ return -EINVAL; ++ ++ if (ilace && height == out_height) ++ fieldmode = 1; ++ ++ if (ilace) { ++ if (fieldmode) ++ height /= 2; ++ pos_y /= 2; ++ out_height /= 2; ++ ++ DSSDBG("adjusting for ilace: height %d, pos_y %d, " ++ "out_height %d\n", ++ height, pos_y, out_height); ++ } ++ ++ if (plane == OMAP_DSS_GFX) { ++ if (width != out_width || height != out_height) ++ return -EINVAL; ++ ++ switch (color_mode) { ++ case OMAP_DSS_COLOR_ARGB16: ++ case OMAP_DSS_COLOR_RGB16: ++ case OMAP_DSS_COLOR_RGB24P: ++ case OMAP_DSS_COLOR_RGB24U: ++ case OMAP_DSS_COLOR_ARGB32: ++ case OMAP_DSS_COLOR_RGBA32: ++ case OMAP_DSS_COLOR_RGBX32: ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ } else { ++ /* video plane */ ++ ++ unsigned long fclk = 0; ++ ++ if (out_width < width / maxdownscale || ++ out_width > width * 8) ++ return -EINVAL; ++ ++ if (out_height < height / maxdownscale || ++ out_height > height * 8) ++ return -EINVAL; ++ ++ switch (color_mode) { ++ case OMAP_DSS_COLOR_RGB16: ++ case OMAP_DSS_COLOR_RGB24P: ++ case OMAP_DSS_COLOR_RGB24U: ++ case OMAP_DSS_COLOR_RGBX32: ++ break; ++ ++ case OMAP_DSS_COLOR_ARGB16: ++ case OMAP_DSS_COLOR_ARGB32: ++ case OMAP_DSS_COLOR_RGBA32: ++ if (plane == OMAP_DSS_VIDEO1) ++ return -EINVAL; ++ break; ++ ++ case OMAP_DSS_COLOR_YUV2: ++ case OMAP_DSS_COLOR_UYVY: ++ cconv = 1; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ /* Must use 5-tap filter? */ ++ five_taps = height > out_height * 2; ++ ++ if (!five_taps) { ++ fclk = calc_fclk(width, height, ++ out_width, out_height); ++ ++ /* Try 5-tap filter if 3-tap fclk is too high */ ++ if (cpu_is_omap34xx() && height > out_height && ++ fclk > dispc_fclk_rate()) ++ five_taps = true; ++ } ++ ++ if (width > (2048 >> five_taps)) ++ return -EINVAL; ++ ++ if (five_taps) ++ fclk = calc_fclk_five_taps(width, height, ++ out_width, out_height, color_mode); ++ ++ DSSDBG("required fclk rate = %lu Hz\n", fclk); ++ DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); ++ ++ if (fclk > dispc_fclk_rate()) { ++ DSSERR("failed to set up scaling, " ++ "required fclk rate = %lu Hz, " ++ "current fclk rate = %lu Hz\n", ++ fclk, dispc_fclk_rate()); ++ return -EINVAL; ++ } ++ } ++ ++ if (ilace && !fieldmode) { ++ /* ++ * when downscaling the bottom field may have to start several ++ * source lines below the top field. Unfortunately ACCUI ++ * registers will only hold the fractional part of the offset ++ * so the integer part must be added to the base address of the ++ * bottom field. ++ */ ++ if (!height || height == out_height) ++ field_offset = 0; ++ else ++ field_offset = height / out_height / 2; ++ } ++ ++ /* Fields are independent but interleaved in memory. */ ++ if (fieldmode) ++ field_offset = 1; ++ ++ if (rotation_type == OMAP_DSS_ROT_DMA) ++ calc_dma_rotation_offset(rotation, mirror, ++ screen_width, width, frame_height, color_mode, ++ fieldmode, field_offset, ++ &offset0, &offset1, &row_inc, &pix_inc); ++ else ++ calc_vrfb_rotation_offset(rotation, mirror, ++ screen_width, width, frame_height, color_mode, ++ fieldmode, field_offset, ++ &offset0, &offset1, &row_inc, &pix_inc); ++ ++ DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", ++ offset0, offset1, row_inc, pix_inc); ++ ++ _dispc_set_color_mode(plane, color_mode); ++ ++ _dispc_set_plane_ba0(plane, paddr + offset0); ++ _dispc_set_plane_ba1(plane, paddr + offset1); ++ ++ _dispc_set_row_inc(plane, row_inc); ++ _dispc_set_pix_inc(plane, pix_inc); ++ ++ DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height, ++ out_width, out_height); ++ ++ _dispc_set_plane_pos(plane, pos_x, pos_y); ++ ++ _dispc_set_pic_size(plane, width, height); ++ ++ if (plane != OMAP_DSS_GFX) { ++ _dispc_set_scaling(plane, width, height, ++ out_width, out_height, ++ ilace, five_taps, fieldmode); ++ _dispc_set_vid_size(plane, out_width, out_height); ++ _dispc_set_vid_color_conv(plane, cconv); ++ } ++ ++ _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); ++ ++ if (plane != OMAP_DSS_VIDEO1) ++ _dispc_setup_global_alpha(plane, global_alpha); ++ ++ return 0; ++} ++ ++static void _dispc_enable_plane(enum omap_plane plane, bool enable) ++{ ++ REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0); ++} ++ ++static void dispc_disable_isr(void *data, u32 mask) ++{ ++ struct completion *compl = data; ++ complete(compl); ++} ++ ++static void _enable_lcd_out(bool enable) ++{ ++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); ++} ++ ++void dispc_enable_lcd_out(bool enable) ++{ ++ struct completion frame_done_completion; ++ bool is_on; ++ int r; ++ ++ enable_clocks(1); ++ ++ /* When we disable LCD output, we need to wait until frame is done. ++ * Otherwise the DSS is still working, and turning off the clocks ++ * prevents DSS from going to OFF mode */ ++ is_on = REG_GET(DISPC_CONTROL, 0, 0); ++ ++ if (!enable && is_on) { ++ init_completion(&frame_done_completion); ++ ++ r = omap_dispc_register_isr(dispc_disable_isr, ++ &frame_done_completion, ++ DISPC_IRQ_FRAMEDONE); ++ ++ if (r) ++ DSSERR("failed to register FRAMEDONE isr\n"); ++ } ++ ++ _enable_lcd_out(enable); ++ ++ if (!enable && is_on) { ++ if (!wait_for_completion_timeout(&frame_done_completion, ++ msecs_to_jiffies(100))) ++ DSSERR("timeout waiting for FRAME DONE\n"); ++ ++ r = omap_dispc_unregister_isr(dispc_disable_isr, ++ &frame_done_completion, ++ DISPC_IRQ_FRAMEDONE); ++ ++ if (r) ++ DSSERR("failed to unregister FRAMEDONE isr\n"); ++ } ++ ++ enable_clocks(0); ++} ++ ++static void _enable_digit_out(bool enable) ++{ ++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); ++} ++ ++void dispc_enable_digit_out(bool enable) ++{ ++ struct completion frame_done_completion; ++ int r; ++ ++ enable_clocks(1); ++ ++ if (REG_GET(DISPC_CONTROL, 1, 1) == enable) { ++ enable_clocks(0); ++ return; ++ } ++ ++ if (enable) { ++ unsigned long flags; ++ /* When we enable digit output, we'll get an extra digit ++ * sync lost interrupt, that we need to ignore */ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT; ++ _omap_dispc_set_irqs(); ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ } ++ ++ /* When we disable digit output, we need to wait until fields are done. ++ * Otherwise the DSS is still working, and turning off the clocks ++ * prevents DSS from going to OFF mode. And when enabling, we need to ++ * wait for the extra sync losts */ ++ init_completion(&frame_done_completion); ++ ++ r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, ++ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); ++ if (r) ++ DSSERR("failed to register EVSYNC isr\n"); ++ ++ _enable_digit_out(enable); ++ ++ /* XXX I understand from TRM that we should only wait for the ++ * current field to complete. But it seems we have to wait ++ * for both fields */ ++ if (!wait_for_completion_timeout(&frame_done_completion, ++ msecs_to_jiffies(100))) ++ DSSERR("timeout waiting for EVSYNC\n"); ++ ++ if (!wait_for_completion_timeout(&frame_done_completion, ++ msecs_to_jiffies(100))) ++ DSSERR("timeout waiting for EVSYNC\n"); ++ ++ r = omap_dispc_unregister_isr(dispc_disable_isr, ++ &frame_done_completion, ++ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); ++ if (r) ++ DSSERR("failed to unregister EVSYNC isr\n"); ++ ++ if (enable) { ++ unsigned long flags; ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; ++ dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); ++ _omap_dispc_set_irqs(); ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ } ++ ++ enable_clocks(0); ++} ++ ++void dispc_lcd_enable_signal_polarity(bool act_high) ++{ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); ++ enable_clocks(0); ++} ++ ++void dispc_lcd_enable_signal(bool enable) ++{ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); ++ enable_clocks(0); ++} ++ ++void dispc_pck_free_enable(bool enable) ++{ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); ++ enable_clocks(0); ++} ++ ++void dispc_enable_fifohandcheck(bool enable) ++{ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); ++ enable_clocks(0); ++} ++ ++ ++void dispc_set_lcd_display_type(enum omap_lcd_display_type type) ++{ ++ int mode; ++ ++ switch (type) { ++ case OMAP_DSS_LCD_DISPLAY_STN: ++ mode = 0; ++ break; ++ ++ case OMAP_DSS_LCD_DISPLAY_TFT: ++ mode = 1; ++ break; ++ ++ default: ++ BUG(); ++ return; ++ } ++ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); ++ enable_clocks(0); ++} ++ ++void dispc_set_loadmode(enum omap_dss_load_mode mode) ++{ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1); ++ enable_clocks(0); ++} ++ ++ ++void dispc_set_default_color(enum omap_channel channel, u32 color) ++{ ++ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, ++ DISPC_DEFAULT_COLOR1 }; ++ ++ enable_clocks(1); ++ dispc_write_reg(def_reg[channel], color); ++ enable_clocks(0); ++} ++ ++u32 dispc_get_default_color(enum omap_channel channel) ++{ ++ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, ++ DISPC_DEFAULT_COLOR1 }; ++ u32 l; ++ ++ BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT && ++ channel != OMAP_DSS_CHANNEL_LCD); ++ ++ enable_clocks(1); ++ l = dispc_read_reg(def_reg[channel]); ++ enable_clocks(0); ++ ++ return l; ++} ++ ++void dispc_set_trans_key(enum omap_channel ch, ++ enum omap_dss_trans_key_type type, ++ u32 trans_key) ++{ ++ const struct dispc_reg tr_reg[] = { ++ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; ++ ++ enable_clocks(1); ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); ++ else /* OMAP_DSS_CHANNEL_DIGIT */ ++ REG_FLD_MOD(DISPC_CONFIG, type, 13, 13); ++ ++ dispc_write_reg(tr_reg[ch], trans_key); ++ enable_clocks(0); ++} ++ ++void dispc_get_trans_key(enum omap_channel ch, ++ enum omap_dss_trans_key_type *type, ++ u32 *trans_key) ++{ ++ const struct dispc_reg tr_reg[] = { ++ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; ++ ++ enable_clocks(1); ++ if (type) { ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ *type = REG_GET(DISPC_CONFIG, 11, 11); ++ else if (ch == OMAP_DSS_CHANNEL_DIGIT) ++ *type = REG_GET(DISPC_CONFIG, 13, 13); ++ else ++ BUG(); ++ } ++ ++ if (trans_key) ++ *trans_key = dispc_read_reg(tr_reg[ch]); ++ enable_clocks(0); ++} ++ ++void dispc_enable_trans_key(enum omap_channel ch, bool enable) ++{ ++ enable_clocks(1); ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); ++ else /* OMAP_DSS_CHANNEL_DIGIT */ ++ REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); ++ enable_clocks(0); ++} ++void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) ++{ ++ enable_clocks(1); ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); ++ else /* OMAP_DSS_CHANNEL_DIGIT */ ++ REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); ++ enable_clocks(0); ++} ++bool dispc_alpha_blending_enabled(enum omap_channel ch) ++{ ++ bool enabled; ++ ++ enable_clocks(1); ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ enabled = REG_GET(DISPC_CONFIG, 18, 18); ++ else if (ch == OMAP_DSS_CHANNEL_DIGIT) ++ enabled = REG_GET(DISPC_CONFIG, 18, 18); ++ else ++ BUG(); ++ enable_clocks(0); ++ ++ return enabled; ++ ++} ++ ++ ++bool dispc_trans_key_enabled(enum omap_channel ch) ++{ ++ bool enabled; ++ ++ enable_clocks(1); ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ enabled = REG_GET(DISPC_CONFIG, 10, 10); ++ else if (ch == OMAP_DSS_CHANNEL_DIGIT) ++ enabled = REG_GET(DISPC_CONFIG, 12, 12); ++ else ++ BUG(); ++ enable_clocks(0); ++ ++ return enabled; ++} ++ ++ ++void dispc_set_tft_data_lines(u8 data_lines) ++{ ++ int code; ++ ++ switch (data_lines) { ++ case 12: ++ code = 0; ++ break; ++ case 16: ++ code = 1; ++ break; ++ case 18: ++ code = 2; ++ break; ++ case 24: ++ code = 3; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); ++ enable_clocks(0); ++} ++ ++void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode) ++{ ++ u32 l; ++ int stallmode; ++ int gpout0 = 1; ++ int gpout1; ++ ++ switch (mode) { ++ case OMAP_DSS_PARALLELMODE_BYPASS: ++ stallmode = 0; ++ gpout1 = 1; ++ break; ++ ++ case OMAP_DSS_PARALLELMODE_RFBI: ++ stallmode = 1; ++ gpout1 = 0; ++ break; ++ ++ case OMAP_DSS_PARALLELMODE_DSI: ++ stallmode = 1; ++ gpout1 = 1; ++ break; ++ ++ default: ++ BUG(); ++ return; ++ } ++ ++ enable_clocks(1); ++ ++ l = dispc_read_reg(DISPC_CONTROL); ++ ++ l = FLD_MOD(l, stallmode, 11, 11); ++ l = FLD_MOD(l, gpout0, 15, 15); ++ l = FLD_MOD(l, gpout1, 16, 16); ++ ++ dispc_write_reg(DISPC_CONTROL, l); ++ ++ enable_clocks(0); ++} ++ ++static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, ++ int vsw, int vfp, int vbp) ++{ ++ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { ++ if (hsw < 1 || hsw > 64 || ++ hfp < 1 || hfp > 256 || ++ hbp < 1 || hbp > 256 || ++ vsw < 1 || vsw > 64 || ++ vfp < 0 || vfp > 255 || ++ vbp < 0 || vbp > 255) ++ return false; ++ } else { ++ if (hsw < 1 || hsw > 256 || ++ hfp < 1 || hfp > 4096 || ++ hbp < 1 || hbp > 4096 || ++ vsw < 1 || vsw > 256 || ++ vfp < 0 || vfp > 4095 || ++ vbp < 0 || vbp > 4095) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool dispc_lcd_timings_ok(struct omap_video_timings *timings) ++{ ++ return _dispc_lcd_timings_ok(timings->hsw, timings->hfp, ++ timings->hbp, timings->vsw, ++ timings->vfp, timings->vbp); ++} ++ ++static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp, ++ int vsw, int vfp, int vbp) ++{ ++ u32 timing_h, timing_v; ++ ++ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { ++ timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | ++ FLD_VAL(hbp-1, 27, 20); ++ ++ timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) | ++ FLD_VAL(vbp, 27, 20); ++ } else { ++ timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) | ++ FLD_VAL(hbp-1, 31, 20); ++ ++ timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) | ++ FLD_VAL(vbp, 31, 20); ++ } ++ ++ enable_clocks(1); ++ dispc_write_reg(DISPC_TIMING_H, timing_h); ++ dispc_write_reg(DISPC_TIMING_V, timing_v); ++ enable_clocks(0); ++} ++ ++/* change name to mode? */ ++void dispc_set_lcd_timings(struct omap_video_timings *timings) ++{ ++ unsigned xtot, ytot; ++ unsigned long ht, vt; ++ ++ if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp, ++ timings->hbp, timings->vsw, ++ timings->vfp, timings->vbp)) ++ BUG(); ++ ++ _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp, ++ timings->vsw, timings->vfp, timings->vbp); ++ ++ dispc_set_lcd_size(timings->x_res, timings->y_res); ++ ++ xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; ++ ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; ++ ++ ht = (timings->pixel_clock * 1000) / xtot; ++ vt = (timings->pixel_clock * 1000) / xtot / ytot; ++ ++ DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res); ++ DSSDBG("pck %u\n", timings->pixel_clock); ++ DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", ++ timings->hsw, timings->hfp, timings->hbp, ++ timings->vsw, timings->vfp, timings->vbp); ++ ++ DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); ++} ++ ++void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div) ++{ ++ BUG_ON(lck_div < 1); ++ BUG_ON(pck_div < 2); ++ ++ enable_clocks(1); ++ dispc_write_reg(DISPC_DIVISOR, ++ FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); ++ enable_clocks(0); ++} ++ ++static void dispc_get_lcd_divisor(int *lck_div, int *pck_div) ++{ ++ u32 l; ++ l = dispc_read_reg(DISPC_DIVISOR); ++ *lck_div = FLD_GET(l, 23, 16); ++ *pck_div = FLD_GET(l, 7, 0); ++} ++ ++unsigned long dispc_fclk_rate(void) ++{ ++ unsigned long r = 0; ++ ++ if (dss_get_dispc_clk_source() == 0) ++ r = dss_clk_get_rate(DSS_CLK_FCK1); ++ else ++#ifdef CONFIG_OMAP2_DSS_DSI ++ r = dsi_get_dsi1_pll_rate(); ++#else ++ BUG(); ++#endif ++ return r; ++} ++ ++unsigned long dispc_lclk_rate(void) ++{ ++ int lcd; ++ unsigned long r; ++ u32 l; ++ ++ l = dispc_read_reg(DISPC_DIVISOR); ++ ++ lcd = FLD_GET(l, 23, 16); ++ ++ r = dispc_fclk_rate(); ++ ++ return r / lcd; ++} ++ ++unsigned long dispc_pclk_rate(void) ++{ ++ int lcd, pcd; ++ unsigned long r; ++ u32 l; ++ ++ l = dispc_read_reg(DISPC_DIVISOR); ++ ++ lcd = FLD_GET(l, 23, 16); ++ pcd = FLD_GET(l, 7, 0); ++ ++ r = dispc_fclk_rate(); ++ ++ return r / lcd / pcd; ++} ++ ++void dispc_dump_clocks(struct seq_file *s) ++{ ++ int lcd, pcd; ++ ++ enable_clocks(1); ++ ++ dispc_get_lcd_divisor(&lcd, &pcd); ++ ++ seq_printf(s, "- dispc -\n"); ++ ++ seq_printf(s, "dispc fclk source = %s\n", ++ dss_get_dispc_clk_source() == 0 ? ++ "dss1_alwon_fclk" : "dsi1_pll_fclk"); ++ ++ seq_printf(s, "pixel clk = %lu / %d / %d = %lu\n", ++ dispc_fclk_rate(), ++ lcd, pcd, ++ dispc_pclk_rate()); ++ ++ enable_clocks(0); ++} ++ ++void dispc_dump_regs(struct seq_file *s) ++{ ++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ DUMPREG(DISPC_REVISION); ++ DUMPREG(DISPC_SYSCONFIG); ++ DUMPREG(DISPC_SYSSTATUS); ++ DUMPREG(DISPC_IRQSTATUS); ++ DUMPREG(DISPC_IRQENABLE); ++ DUMPREG(DISPC_CONTROL); ++ DUMPREG(DISPC_CONFIG); ++ DUMPREG(DISPC_CAPABLE); ++ DUMPREG(DISPC_DEFAULT_COLOR0); ++ DUMPREG(DISPC_DEFAULT_COLOR1); ++ DUMPREG(DISPC_TRANS_COLOR0); ++ DUMPREG(DISPC_TRANS_COLOR1); ++ DUMPREG(DISPC_LINE_STATUS); ++ DUMPREG(DISPC_LINE_NUMBER); ++ DUMPREG(DISPC_TIMING_H); ++ DUMPREG(DISPC_TIMING_V); ++ DUMPREG(DISPC_POL_FREQ); ++ DUMPREG(DISPC_DIVISOR); ++ DUMPREG(DISPC_GLOBAL_ALPHA); ++ DUMPREG(DISPC_SIZE_DIG); ++ DUMPREG(DISPC_SIZE_LCD); ++ ++ DUMPREG(DISPC_GFX_BA0); ++ DUMPREG(DISPC_GFX_BA1); ++ DUMPREG(DISPC_GFX_POSITION); ++ DUMPREG(DISPC_GFX_SIZE); ++ DUMPREG(DISPC_GFX_ATTRIBUTES); ++ DUMPREG(DISPC_GFX_FIFO_THRESHOLD); ++ DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS); ++ DUMPREG(DISPC_GFX_ROW_INC); ++ DUMPREG(DISPC_GFX_PIXEL_INC); ++ DUMPREG(DISPC_GFX_WINDOW_SKIP); ++ DUMPREG(DISPC_GFX_TABLE_BA); ++ ++ DUMPREG(DISPC_DATA_CYCLE1); ++ DUMPREG(DISPC_DATA_CYCLE2); ++ DUMPREG(DISPC_DATA_CYCLE3); ++ ++ DUMPREG(DISPC_CPR_COEF_R); ++ DUMPREG(DISPC_CPR_COEF_G); ++ DUMPREG(DISPC_CPR_COEF_B); ++ ++ DUMPREG(DISPC_GFX_PRELOAD); ++ ++ DUMPREG(DISPC_VID_BA0(0)); ++ DUMPREG(DISPC_VID_BA1(0)); ++ DUMPREG(DISPC_VID_POSITION(0)); ++ DUMPREG(DISPC_VID_SIZE(0)); ++ DUMPREG(DISPC_VID_ATTRIBUTES(0)); ++ DUMPREG(DISPC_VID_FIFO_THRESHOLD(0)); ++ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0)); ++ DUMPREG(DISPC_VID_ROW_INC(0)); ++ DUMPREG(DISPC_VID_PIXEL_INC(0)); ++ DUMPREG(DISPC_VID_FIR(0)); ++ DUMPREG(DISPC_VID_PICTURE_SIZE(0)); ++ DUMPREG(DISPC_VID_ACCU0(0)); ++ DUMPREG(DISPC_VID_ACCU1(0)); ++ ++ DUMPREG(DISPC_VID_BA0(1)); ++ DUMPREG(DISPC_VID_BA1(1)); ++ DUMPREG(DISPC_VID_POSITION(1)); ++ DUMPREG(DISPC_VID_SIZE(1)); ++ DUMPREG(DISPC_VID_ATTRIBUTES(1)); ++ DUMPREG(DISPC_VID_FIFO_THRESHOLD(1)); ++ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1)); ++ DUMPREG(DISPC_VID_ROW_INC(1)); ++ DUMPREG(DISPC_VID_PIXEL_INC(1)); ++ DUMPREG(DISPC_VID_FIR(1)); ++ DUMPREG(DISPC_VID_PICTURE_SIZE(1)); ++ DUMPREG(DISPC_VID_ACCU0(1)); ++ DUMPREG(DISPC_VID_ACCU1(1)); ++ ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 7)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7)); ++ DUMPREG(DISPC_VID_CONV_COEF(0, 0)); ++ DUMPREG(DISPC_VID_CONV_COEF(0, 1)); ++ DUMPREG(DISPC_VID_CONV_COEF(0, 2)); ++ DUMPREG(DISPC_VID_CONV_COEF(0, 3)); ++ DUMPREG(DISPC_VID_CONV_COEF(0, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 7)); ++ ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 7)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7)); ++ DUMPREG(DISPC_VID_CONV_COEF(1, 0)); ++ DUMPREG(DISPC_VID_CONV_COEF(1, 1)); ++ DUMPREG(DISPC_VID_CONV_COEF(1, 2)); ++ DUMPREG(DISPC_VID_CONV_COEF(1, 3)); ++ DUMPREG(DISPC_VID_CONV_COEF(1, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 7)); ++ ++ DUMPREG(DISPC_VID_PRELOAD(0)); ++ DUMPREG(DISPC_VID_PRELOAD(1)); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++#undef DUMPREG ++} ++ ++static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc, ++ bool ihs, bool ivs, u8 acbi, u8 acb) ++{ ++ u32 l = 0; ++ ++ DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n", ++ onoff, rf, ieo, ipc, ihs, ivs, acbi, acb); ++ ++ l |= FLD_VAL(onoff, 17, 17); ++ l |= FLD_VAL(rf, 16, 16); ++ l |= FLD_VAL(ieo, 15, 15); ++ l |= FLD_VAL(ipc, 14, 14); ++ l |= FLD_VAL(ihs, 13, 13); ++ l |= FLD_VAL(ivs, 12, 12); ++ l |= FLD_VAL(acbi, 11, 8); ++ l |= FLD_VAL(acb, 7, 0); ++ ++ enable_clocks(1); ++ dispc_write_reg(DISPC_POL_FREQ, l); ++ enable_clocks(0); ++} ++ ++void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb) ++{ ++ _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0, ++ (config & OMAP_DSS_LCD_RF) != 0, ++ (config & OMAP_DSS_LCD_IEO) != 0, ++ (config & OMAP_DSS_LCD_IPC) != 0, ++ (config & OMAP_DSS_LCD_IHS) != 0, ++ (config & OMAP_DSS_LCD_IVS) != 0, ++ acbi, acb); ++} ++ ++void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck, ++ u16 *lck_div, u16 *pck_div) ++{ ++ u16 pcd_min = is_tft ? 2 : 3; ++ unsigned long best_pck; ++ u16 best_ld, cur_ld; ++ u16 best_pd, cur_pd; ++ ++ best_pck = 0; ++ best_ld = 0; ++ best_pd = 0; ++ ++ for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { ++ unsigned long lck = fck / cur_ld; ++ ++ for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) { ++ unsigned long pck = lck / cur_pd; ++ long old_delta = abs(best_pck - req_pck); ++ long new_delta = abs(pck - req_pck); ++ ++ if (best_pck == 0 || new_delta < old_delta) { ++ best_pck = pck; ++ best_ld = cur_ld; ++ best_pd = cur_pd; ++ ++ if (pck == req_pck) ++ goto found; ++ } ++ ++ if (pck < req_pck) ++ break; ++ } ++ ++ if (lck / pcd_min < req_pck) ++ break; ++ } ++ ++found: ++ *lck_div = best_ld; ++ *pck_div = best_pd; ++} ++ ++int dispc_calc_clock_div(bool is_tft, unsigned long req_pck, ++ struct dispc_clock_info *cinfo) ++{ ++ unsigned long prate; ++ struct dispc_clock_info cur, best; ++ int match = 0; ++ int min_fck_per_pck; ++ unsigned long fck_rate = dss_clk_get_rate(DSS_CLK_FCK1); ++ ++ if (cpu_is_omap34xx()) ++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); ++ else ++ prate = 0; ++ ++ if (req_pck == dispc.cache_req_pck && ++ ((cpu_is_omap34xx() && prate == dispc.cache_prate) || ++ dispc.cache_cinfo.fck == fck_rate)) { ++ DSSDBG("dispc clock info found from cache.\n"); ++ *cinfo = dispc.cache_cinfo; ++ return 0; ++ } ++ ++ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; ++ ++ if (min_fck_per_pck && ++ req_pck * min_fck_per_pck > DISPC_MAX_FCK) { ++ DSSERR("Requested pixel clock not possible with the current " ++ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " ++ "the constraint off.\n"); ++ min_fck_per_pck = 0; ++ } ++ ++retry: ++ memset(&cur, 0, sizeof(cur)); ++ memset(&best, 0, sizeof(best)); ++ ++ if (cpu_is_omap24xx()) { ++ /* XXX can we change the clock on omap2? */ ++ cur.fck = dss_clk_get_rate(DSS_CLK_FCK1); ++ cur.fck_div = 1; ++ ++ match = 1; ++ ++ find_lck_pck_divs(is_tft, req_pck, cur.fck, ++ &cur.lck_div, &cur.pck_div); ++ ++ cur.lck = cur.fck / cur.lck_div; ++ cur.pck = cur.lck / cur.pck_div; ++ ++ best = cur; ++ ++ goto found; ++ } else if (cpu_is_omap34xx()) { ++ for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) { ++ cur.fck = prate / cur.fck_div * 2; ++ ++ if (cur.fck > DISPC_MAX_FCK) ++ continue; ++ ++ if (min_fck_per_pck && ++ cur.fck < req_pck * min_fck_per_pck) ++ continue; ++ ++ match = 1; ++ ++ find_lck_pck_divs(is_tft, req_pck, cur.fck, ++ &cur.lck_div, &cur.pck_div); ++ ++ cur.lck = cur.fck / cur.lck_div; ++ cur.pck = cur.lck / cur.pck_div; ++ ++ if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) { ++ best = cur; ++ ++ if (cur.pck == req_pck) ++ goto found; ++ } ++ } ++ } else { ++ BUG(); ++ } ++ ++found: ++ if (!match) { ++ if (min_fck_per_pck) { ++ DSSERR("Could not find suitable clock settings.\n" ++ "Turning FCK/PCK constraint off and" ++ "trying again.\n"); ++ min_fck_per_pck = 0; ++ goto retry; ++ } ++ ++ DSSERR("Could not find suitable clock settings.\n"); ++ ++ return -EINVAL; ++ } ++ ++ if (cinfo) ++ *cinfo = best; ++ ++ dispc.cache_req_pck = req_pck; ++ dispc.cache_prate = prate; ++ dispc.cache_cinfo = best; ++ ++ return 0; ++} ++ ++int dispc_set_clock_div(struct dispc_clock_info *cinfo) ++{ ++ unsigned long prate; ++ int r; ++ ++ if (cpu_is_omap34xx()) { ++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); ++ DSSDBG("dpll4_m4 = %ld\n", prate); ++ } ++ ++ DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); ++ DSSDBG("lck = %ld (%d)\n", cinfo->lck, cinfo->lck_div); ++ DSSDBG("pck = %ld (%d)\n", cinfo->pck, cinfo->pck_div); ++ ++ if (cpu_is_omap34xx()) { ++ r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div); ++ if (r) ++ return r; ++ } ++ ++ dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div); ++ ++ return 0; ++} ++ ++int dispc_get_clock_div(struct dispc_clock_info *cinfo) ++{ ++ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1); ++ ++ if (cpu_is_omap34xx()) { ++ unsigned long prate; ++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); ++ cinfo->fck_div = prate / (cinfo->fck / 2); ++ } else { ++ cinfo->fck_div = 0; ++ } ++ ++ cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16); ++ cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0); ++ ++ cinfo->lck = cinfo->fck / cinfo->lck_div; ++ cinfo->pck = cinfo->lck / cinfo->pck_div; ++ ++ return 0; ++} ++ ++/* dispc.irq_lock has to be locked by the caller */ ++static void _omap_dispc_set_irqs(void) ++{ ++ u32 mask; ++ u32 old_mask; ++ int i; ++ struct omap_dispc_isr_data *isr_data; ++ ++ mask = dispc.irq_error_mask; ++ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ isr_data = &dispc.registered_isr[i]; ++ ++ if (isr_data->isr == NULL) ++ continue; ++ ++ mask |= isr_data->mask; ++ } ++ ++ enable_clocks(1); ++ ++ old_mask = dispc_read_reg(DISPC_IRQENABLE); ++ /* clear the irqstatus for newly enabled irqs */ ++ dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask); ++ ++ dispc_write_reg(DISPC_IRQENABLE, mask); ++ ++ enable_clocks(0); ++} ++ ++int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) ++{ ++ int i; ++ int ret; ++ unsigned long flags; ++ struct omap_dispc_isr_data *isr_data; ++ ++ if (isr == NULL) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ ++ /* check for duplicate entry */ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ isr_data = &dispc.registered_isr[i]; ++ if (isr_data->isr == isr && isr_data->arg == arg && ++ isr_data->mask == mask) { ++ ret = -EINVAL; ++ goto err; ++ } ++ } ++ ++ isr_data = NULL; ++ ret = -EBUSY; ++ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ isr_data = &dispc.registered_isr[i]; ++ ++ if (isr_data->isr != NULL) ++ continue; ++ ++ isr_data->isr = isr; ++ isr_data->arg = arg; ++ isr_data->mask = mask; ++ ret = 0; ++ ++ break; ++ } ++ ++ _omap_dispc_set_irqs(); ++ ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ ++ return 0; ++err: ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ ++ return ret; ++} ++EXPORT_SYMBOL(omap_dispc_register_isr); ++ ++int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask) ++{ ++ int i; ++ unsigned long flags; ++ int ret = -EINVAL; ++ struct omap_dispc_isr_data *isr_data; ++ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ isr_data = &dispc.registered_isr[i]; ++ if (isr_data->isr != isr || isr_data->arg != arg || ++ isr_data->mask != mask) ++ continue; ++ ++ /* found the correct isr */ ++ ++ isr_data->isr = NULL; ++ isr_data->arg = NULL; ++ isr_data->mask = 0; ++ ++ ret = 0; ++ break; ++ } ++ ++ if (ret == 0) ++ _omap_dispc_set_irqs(); ++ ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ ++ return ret; ++} ++EXPORT_SYMBOL(omap_dispc_unregister_isr); ++ ++#ifdef DEBUG ++static void print_irq_status(u32 status) ++{ ++ if ((status & dispc.irq_error_mask) == 0) ++ return; ++ ++ printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status); ++ ++#define PIS(x) \ ++ if (status & DISPC_IRQ_##x) \ ++ printk(#x " "); ++ PIS(GFX_FIFO_UNDERFLOW); ++ PIS(OCP_ERR); ++ PIS(VID1_FIFO_UNDERFLOW); ++ PIS(VID2_FIFO_UNDERFLOW); ++ PIS(SYNC_LOST); ++ PIS(SYNC_LOST_DIGIT); ++#undef PIS ++ ++ printk("\n"); ++} ++#endif ++ ++/* Called from dss.c. Note that we don't touch clocks here, ++ * but we presume they are on because we got an IRQ. However, ++ * an irq handler may turn the clocks off, so we may not have ++ * clock later in the function. */ ++void dispc_irq_handler(void) ++{ ++ int i; ++ u32 irqstatus; ++ u32 handledirqs = 0; ++ u32 unhandled_errors; ++ struct omap_dispc_isr_data *isr_data; ++ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; ++ ++ spin_lock(&dispc.irq_lock); ++ ++ irqstatus = dispc_read_reg(DISPC_IRQSTATUS); ++ ++#ifdef DEBUG ++ if (dss_debug) ++ print_irq_status(irqstatus); ++#endif ++ /* Ack the interrupt. Do it here before clocks are possibly turned ++ * off */ ++ dispc_write_reg(DISPC_IRQSTATUS, irqstatus); ++ ++ /* make a copy and unlock, so that isrs can unregister ++ * themselves */ ++ memcpy(registered_isr, dispc.registered_isr, ++ sizeof(registered_isr)); ++ ++ spin_unlock(&dispc.irq_lock); ++ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ isr_data = ®istered_isr[i]; ++ ++ if (!isr_data->isr) ++ continue; ++ ++ if (isr_data->mask & irqstatus) { ++ isr_data->isr(isr_data->arg, irqstatus); ++ handledirqs |= isr_data->mask; ++ } ++ } ++ ++ spin_lock(&dispc.irq_lock); ++ ++ unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask; ++ ++ if (unhandled_errors) { ++ dispc.error_irqs |= unhandled_errors; ++ ++ dispc.irq_error_mask &= ~unhandled_errors; ++ _omap_dispc_set_irqs(); ++ ++ schedule_work(&dispc.error_work); ++ } ++ ++ spin_unlock(&dispc.irq_lock); ++} ++ ++static void dispc_error_worker(struct work_struct *work) ++{ ++ int i; ++ u32 errors; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ errors = dispc.error_irqs; ++ dispc.error_irqs = 0; ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ ++ if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) { ++ DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n"); ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ if (ovl->id == 0) { ++ dispc_enable_plane(ovl->id, 0); ++ dispc_go(ovl->manager->id); ++ mdelay(50); ++ break; ++ } ++ } ++ } ++ ++ if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) { ++ DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n"); ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ if (ovl->id == 1) { ++ dispc_enable_plane(ovl->id, 0); ++ dispc_go(ovl->manager->id); ++ mdelay(50); ++ break; ++ } ++ } ++ } ++ ++ if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) { ++ DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n"); ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ if (ovl->id == 2) { ++ dispc_enable_plane(ovl->id, 0); ++ dispc_go(ovl->manager->id); ++ mdelay(50); ++ break; ++ } ++ } ++ } ++ ++ if (errors & DISPC_IRQ_SYNC_LOST) { ++ struct omap_overlay_manager *manager = NULL; ++ bool enable = false; ++ ++ DSSERR("SYNC_LOST, disabling LCD\n"); ++ ++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { ++ struct omap_overlay_manager *mgr; ++ mgr = omap_dss_get_overlay_manager(i); ++ ++ if (mgr->id == OMAP_DSS_CHANNEL_LCD) { ++ manager = mgr; ++ enable = mgr->device->state == ++ OMAP_DSS_DISPLAY_ACTIVE; ++ mgr->device->disable(mgr->device); ++ break; ++ } ++ } ++ ++ if (manager) { ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ if (ovl->id != 0 && ovl->manager == manager) ++ dispc_enable_plane(ovl->id, 0); ++ } ++ ++ dispc_go(manager->id); ++ mdelay(50); ++ if (enable) ++ manager->device->enable(manager->device); ++ } ++ } ++ ++ if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) { ++ struct omap_overlay_manager *manager = NULL; ++ bool enable = false; ++ ++ DSSERR("SYNC_LOST_DIGIT, disabling TV\n"); ++ ++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { ++ struct omap_overlay_manager *mgr; ++ mgr = omap_dss_get_overlay_manager(i); ++ ++ if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) { ++ manager = mgr; ++ enable = mgr->device->state == ++ OMAP_DSS_DISPLAY_ACTIVE; ++ mgr->device->disable(mgr->device); ++ break; ++ } ++ } ++ ++ if (manager) { ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ if (ovl->id != 0 && ovl->manager == manager) ++ dispc_enable_plane(ovl->id, 0); ++ } ++ ++ dispc_go(manager->id); ++ mdelay(50); ++ if (enable) ++ manager->device->enable(manager->device); ++ } ++ } ++ ++ if (errors & DISPC_IRQ_OCP_ERR) { ++ DSSERR("OCP_ERR\n"); ++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { ++ struct omap_overlay_manager *mgr; ++ mgr = omap_dss_get_overlay_manager(i); ++ ++ if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC) ++ mgr->device->disable(mgr->device); ++ } ++ } ++ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ dispc.irq_error_mask |= errors; ++ _omap_dispc_set_irqs(); ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++} ++ ++int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout) ++{ ++ void dispc_irq_wait_handler(void *data, u32 mask) ++ { ++ complete((struct completion *)data); ++ } ++ ++ int r; ++ DECLARE_COMPLETION_ONSTACK(completion); ++ ++ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, ++ irqmask); ++ ++ if (r) ++ return r; ++ ++ timeout = wait_for_completion_timeout(&completion, timeout); ++ ++ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); ++ ++ if (timeout == 0) ++ return -ETIMEDOUT; ++ ++ if (timeout == -ERESTARTSYS) ++ return -ERESTARTSYS; ++ ++ return 0; ++} ++ ++int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, ++ unsigned long timeout) ++{ ++ void dispc_irq_wait_handler(void *data, u32 mask) ++ { ++ complete((struct completion *)data); ++ } ++ ++ int r; ++ DECLARE_COMPLETION_ONSTACK(completion); ++ ++ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, ++ irqmask); ++ ++ if (r) ++ return r; ++ ++ timeout = wait_for_completion_interruptible_timeout(&completion, ++ timeout); ++ ++ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); ++ ++ if (timeout == 0) ++ return -ETIMEDOUT; ++ ++ if (timeout == -ERESTARTSYS) ++ return -ERESTARTSYS; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC ++void dispc_fake_vsync_irq(void) ++{ ++ u32 irqstatus = DISPC_IRQ_VSYNC; ++ int i; ++ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ struct omap_dispc_isr_data *isr_data; ++ isr_data = &dispc.registered_isr[i]; ++ ++ if (!isr_data->isr) ++ continue; ++ ++ if (isr_data->mask & irqstatus) ++ isr_data->isr(isr_data->arg, irqstatus); ++ } ++} ++#endif ++ ++static void _omap_dispc_initialize_irq(void) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ ++ memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr)); ++ ++ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; ++ ++ /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, ++ * so clear it */ ++ dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS)); ++ ++ _omap_dispc_set_irqs(); ++ ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++} ++ ++void dispc_enable_sidle(void) ++{ ++ REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */ ++} ++ ++void dispc_disable_sidle(void) ++{ ++ REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */ ++} ++ ++static void _omap_dispc_initial_config(void) ++{ ++ u32 l; ++ ++ l = dispc_read_reg(DISPC_SYSCONFIG); ++ l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */ ++ l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */ ++ l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */ ++ l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ ++ dispc_write_reg(DISPC_SYSCONFIG, l); ++ ++ /* FUNCGATED */ ++ REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); ++ ++ /* L3 firewall setting: enable access to OCM RAM */ ++ if (cpu_is_omap24xx()) ++ __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0)); ++ ++ _dispc_setup_color_conv_coef(); ++ ++ dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); ++ ++ dispc_read_plane_fifo_sizes(); ++} ++ ++int dispc_init(void) ++{ ++ u32 rev; ++ ++ spin_lock_init(&dispc.irq_lock); ++ ++ INIT_WORK(&dispc.error_work, dispc_error_worker); ++ ++ dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); ++ if (!dispc.base) { ++ DSSERR("can't ioremap DISPC\n"); ++ return -ENOMEM; ++ } ++ ++ if (cpu_is_omap34xx()) { ++ dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); ++ if (IS_ERR(dispc.dpll4_m4_ck)) { ++ DSSERR("Failed to get dpll4_m4_ck\n"); ++ return -ENODEV; ++ } ++ } ++ ++ enable_clocks(1); ++ ++ _omap_dispc_initial_config(); ++ ++ _omap_dispc_initialize_irq(); ++ ++ dispc_save_context(); ++ ++ rev = dispc_read_reg(DISPC_REVISION); ++ printk(KERN_INFO "OMAP DISPC rev %d.%d\n", ++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); ++ ++ enable_clocks(0); ++ ++ return 0; ++} ++ ++void dispc_exit(void) ++{ ++ if (cpu_is_omap34xx()) ++ clk_put(dispc.dpll4_m4_ck); ++ iounmap(dispc.base); ++} ++ ++int dispc_enable_plane(enum omap_plane plane, bool enable) ++{ ++ DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); ++ ++ enable_clocks(1); ++ _dispc_enable_plane(plane, enable); ++ enable_clocks(0); ++ ++ return 0; ++} ++ ++int dispc_setup_plane(enum omap_plane plane, ++ u32 paddr, u16 screen_width, ++ u16 pos_x, u16 pos_y, ++ u16 width, u16 height, ++ u16 out_width, u16 out_height, ++ enum omap_color_mode color_mode, ++ bool ilace, ++ enum omap_dss_rotation_type rotation_type, ++ u8 rotation, bool mirror, u8 global_alpha) ++{ ++ int r = 0; ++ ++ DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " ++ "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n", ++ plane, paddr, screen_width, pos_x, pos_y, ++ width, height, ++ out_width, out_height, ++ ilace, color_mode, ++ rotation, mirror); ++ ++ enable_clocks(1); ++ ++ r = _dispc_setup_plane(plane, ++ paddr, screen_width, ++ pos_x, pos_y, ++ width, height, ++ out_width, out_height, ++ color_mode, ilace, ++ rotation_type, ++ rotation, mirror, ++ global_alpha); ++ ++ enable_clocks(0); ++ ++ return r; ++} +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0010-OMAP-DSS2-DPI-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0010-OMAP-DSS2-DPI-driver.patch new file mode 100644 index 0000000000..db6d780552 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0010-OMAP-DSS2-DPI-driver.patch @@ -0,0 +1,410 @@ +From 544b715d21a38a64bcafe850e31ae0dfd5227e9f Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Fri, 7 Aug 2009 13:15:50 +0300 +Subject: [PATCH 10/18] OMAP: DSS2: DPI driver + +This implements MIPI DPI interface. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + drivers/video/omap2/dss/dpi.c | 388 +++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 388 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/dss/dpi.c + +diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c +new file mode 100644 +index 0000000..b6543c8 +--- /dev/null ++++ b/drivers/video/omap2/dss/dpi.c +@@ -0,0 +1,388 @@ ++/* ++ * linux/drivers/video/omap2/dss/dpi.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "DPI" ++ ++#include <linux/kernel.h> ++#include <linux/clk.h> ++#include <linux/delay.h> ++#include <linux/errno.h> ++ ++#include <mach/board.h> ++#include <mach/display.h> ++#include <mach/cpu.h> ++ ++#include "dss.h" ++ ++static struct { ++ int update_enabled; ++} dpi; ++ ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req, ++ unsigned long *fck, int *lck_div, int *pck_div) ++{ ++ struct dsi_clock_info cinfo; ++ int r; ++ ++ r = dsi_pll_calc_pck(is_tft, pck_req, &cinfo); ++ if (r) ++ return r; ++ ++ r = dsi_pll_program(&cinfo); ++ if (r) ++ return r; ++ ++ dss_select_clk_source(0, 1); ++ ++ dispc_set_lcd_divisor(cinfo.lck_div, cinfo.pck_div); ++ ++ *fck = cinfo.dsi1_pll_fclk; ++ *lck_div = cinfo.lck_div; ++ *pck_div = cinfo.pck_div; ++ ++ return 0; ++} ++#else ++static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, ++ unsigned long *fck, int *lck_div, int *pck_div) ++{ ++ struct dispc_clock_info cinfo; ++ int r; ++ ++ r = dispc_calc_clock_div(is_tft, pck_req, &cinfo); ++ if (r) ++ return r; ++ ++ r = dispc_set_clock_div(&cinfo); ++ if (r) ++ return r; ++ ++ *fck = cinfo.fck; ++ *lck_div = cinfo.lck_div; ++ *pck_div = cinfo.pck_div; ++ ++ return 0; ++} ++#endif ++ ++static int dpi_set_mode(struct omap_dss_device *dssdev) ++{ ++ struct omap_video_timings *t = &dssdev->panel.timings; ++ int lck_div, pck_div; ++ unsigned long fck; ++ unsigned long pck; ++ bool is_tft; ++ int r = 0; ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, ++ dssdev->panel.acb); ++ ++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; ++ ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++ r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000, ++ &fck, &lck_div, &pck_div); ++#else ++ r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000, ++ &fck, &lck_div, &pck_div); ++#endif ++ if (r) ++ goto err0; ++ ++ pck = fck / lck_div / pck_div / 1000; ++ ++ if (pck != t->pixel_clock) { ++ DSSWARN("Could not find exact pixel clock. " ++ "Requested %d kHz, got %lu kHz\n", ++ t->pixel_clock, pck); ++ ++ t->pixel_clock = pck; ++ } ++ ++ dispc_set_lcd_timings(t); ++ ++err0: ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ return r; ++} ++ ++static int dpi_basic_init(struct omap_dss_device *dssdev) ++{ ++ bool is_tft; ++ ++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; ++ ++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); ++ dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT : ++ OMAP_DSS_LCD_DISPLAY_STN); ++ dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines); ++ ++ return 0; ++} ++ ++static int dpi_display_enable(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ r = omap_dss_start_device(dssdev); ++ if (r) { ++ DSSERR("failed to start device\n"); ++ goto err0; ++ } ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { ++ DSSERR("display already enabled\n"); ++ r = -EINVAL; ++ goto err1; ++ } ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ r = dpi_basic_init(dssdev); ++ if (r) ++ goto err2; ++ ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++ dss_clk_enable(DSS_CLK_FCK2); ++ r = dsi_pll_init(0, 1); ++ if (r) ++ goto err3; ++#endif ++ r = dpi_set_mode(dssdev); ++ if (r) ++ goto err4; ++ ++ mdelay(2); ++ ++ dispc_enable_lcd_out(1); ++ ++ r = dssdev->driver->enable(dssdev); ++ if (r) ++ goto err5; ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ return 0; ++ ++err5: ++ dispc_enable_lcd_out(0); ++err4: ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++ dsi_pll_uninit(); ++err3: ++ dss_clk_disable(DSS_CLK_FCK2); ++#endif ++err2: ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++err1: ++ omap_dss_stop_device(dssdev); ++err0: ++ return r; ++} ++ ++static int dpi_display_resume(struct omap_dss_device *dssdev); ++ ++static void dpi_display_disable(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) ++ return; ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) ++ dpi_display_resume(dssdev); ++ ++ dssdev->driver->disable(dssdev); ++ ++ dispc_enable_lcd_out(0); ++ ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++ dss_select_clk_source(0, 0); ++ dsi_pll_uninit(); ++ dss_clk_disable(DSS_CLK_FCK2); ++#endif ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++ ++ omap_dss_stop_device(dssdev); ++} ++ ++static int dpi_display_suspend(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ return -EINVAL; ++ ++ DSSDBG("dpi_display_suspend\n"); ++ ++ if (dssdev->driver->suspend) ++ dssdev->driver->suspend(dssdev); ++ ++ dispc_enable_lcd_out(0); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; ++ ++ return 0; ++} ++ ++static int dpi_display_resume(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) ++ return -EINVAL; ++ ++ DSSDBG("dpi_display_resume\n"); ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dispc_enable_lcd_out(1); ++ ++ if (dssdev->driver->resume) ++ dssdev->driver->resume(dssdev); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ return 0; ++} ++ ++static void dpi_set_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ DSSDBG("dpi_set_timings\n"); ++ dssdev->panel.timings = *timings; ++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { ++ dpi_set_mode(dssdev); ++ dispc_go(OMAP_DSS_CHANNEL_LCD); ++ } ++} ++ ++static int dpi_check_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ bool is_tft; ++ int r; ++ int lck_div, pck_div; ++ unsigned long fck; ++ unsigned long pck; ++ ++ if (!dispc_lcd_timings_ok(timings)) ++ return -EINVAL; ++ ++ if (timings->pixel_clock == 0) ++ return -EINVAL; ++ ++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; ++ ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++ { ++ struct dsi_clock_info cinfo; ++ r = dsi_pll_calc_pck(is_tft, timings->pixel_clock * 1000, ++ &cinfo); ++ ++ if (r) ++ return r; ++ ++ fck = cinfo.dsi1_pll_fclk; ++ lck_div = cinfo.lck_div; ++ pck_div = cinfo.pck_div; ++ } ++#else ++ { ++ struct dispc_clock_info cinfo; ++ r = dispc_calc_clock_div(is_tft, timings->pixel_clock * 1000, ++ &cinfo); ++ ++ if (r) ++ return r; ++ ++ fck = cinfo.fck; ++ lck_div = cinfo.lck_div; ++ pck_div = cinfo.pck_div; ++ } ++#endif ++ ++ pck = fck / lck_div / pck_div / 1000; ++ ++ timings->pixel_clock = pck; ++ ++ return 0; ++} ++ ++static void dpi_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ *timings = dssdev->panel.timings; ++} ++ ++static int dpi_display_set_update_mode(struct omap_dss_device *dssdev, ++ enum omap_dss_update_mode mode) ++{ ++ if (mode == OMAP_DSS_UPDATE_MANUAL) ++ return -EINVAL; ++ ++ if (mode == OMAP_DSS_UPDATE_DISABLED) { ++ dispc_enable_lcd_out(0); ++ dpi.update_enabled = 0; ++ } else { ++ dispc_enable_lcd_out(1); ++ dpi.update_enabled = 1; ++ } ++ ++ return 0; ++} ++ ++static enum omap_dss_update_mode dpi_display_get_update_mode( ++ struct omap_dss_device *dssdev) ++{ ++ return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO : ++ OMAP_DSS_UPDATE_DISABLED; ++} ++ ++int dpi_init_display(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("init_display\n"); ++ ++ dssdev->enable = dpi_display_enable; ++ dssdev->disable = dpi_display_disable; ++ dssdev->suspend = dpi_display_suspend; ++ dssdev->resume = dpi_display_resume; ++ dssdev->set_timings = dpi_set_timings; ++ dssdev->check_timings = dpi_check_timings; ++ dssdev->get_timings = dpi_get_timings; ++ dssdev->set_update_mode = dpi_display_set_update_mode; ++ dssdev->get_update_mode = dpi_display_get_update_mode; ++ ++ return 0; ++} ++ ++int dpi_init(void) ++{ ++ return 0; ++} ++ ++void dpi_exit(void) ++{ ++} ++ +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0011-OMAP-DSS2-Video-encoder-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0011-OMAP-DSS2-Video-encoder-driver.patch new file mode 100644 index 0000000000..f3cb9ab56f --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0011-OMAP-DSS2-Video-encoder-driver.patch @@ -0,0 +1,821 @@ +From e954e1ef739c39ffe671981ee8adbc7e9bb0249e Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Wed, 5 Aug 2009 16:18:06 +0300 +Subject: [PATCH 11/18] OMAP: DSS2: Video encoder driver + +VENC (video encoder) driver implements OMAP's analog S-Video/Composite +TV-out. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Acked-by: Tony Lindgren <tony@atomide.com> +--- + drivers/video/omap2/dss/venc.c | 797 ++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 797 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/dss/venc.c + +diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c +new file mode 100644 +index 0000000..cf7827e +--- /dev/null ++++ b/drivers/video/omap2/dss/venc.c +@@ -0,0 +1,797 @@ ++/* ++ * linux/drivers/video/omap2/dss/venc.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * VENC settings from TI's DSS driver ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "VENC" ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/io.h> ++#include <linux/mutex.h> ++#include <linux/completion.h> ++#include <linux/delay.h> ++#include <linux/string.h> ++#include <linux/seq_file.h> ++#include <linux/platform_device.h> ++#include <linux/regulator/consumer.h> ++ ++#include <mach/display.h> ++#include <mach/cpu.h> ++ ++#include "dss.h" ++ ++#define VENC_BASE 0x48050C00 ++ ++/* Venc registers */ ++#define VENC_REV_ID 0x00 ++#define VENC_STATUS 0x04 ++#define VENC_F_CONTROL 0x08 ++#define VENC_VIDOUT_CTRL 0x10 ++#define VENC_SYNC_CTRL 0x14 ++#define VENC_LLEN 0x1C ++#define VENC_FLENS 0x20 ++#define VENC_HFLTR_CTRL 0x24 ++#define VENC_CC_CARR_WSS_CARR 0x28 ++#define VENC_C_PHASE 0x2C ++#define VENC_GAIN_U 0x30 ++#define VENC_GAIN_V 0x34 ++#define VENC_GAIN_Y 0x38 ++#define VENC_BLACK_LEVEL 0x3C ++#define VENC_BLANK_LEVEL 0x40 ++#define VENC_X_COLOR 0x44 ++#define VENC_M_CONTROL 0x48 ++#define VENC_BSTAMP_WSS_DATA 0x4C ++#define VENC_S_CARR 0x50 ++#define VENC_LINE21 0x54 ++#define VENC_LN_SEL 0x58 ++#define VENC_L21__WC_CTL 0x5C ++#define VENC_HTRIGGER_VTRIGGER 0x60 ++#define VENC_SAVID__EAVID 0x64 ++#define VENC_FLEN__FAL 0x68 ++#define VENC_LAL__PHASE_RESET 0x6C ++#define VENC_HS_INT_START_STOP_X 0x70 ++#define VENC_HS_EXT_START_STOP_X 0x74 ++#define VENC_VS_INT_START_X 0x78 ++#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C ++#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80 ++#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84 ++#define VENC_VS_EXT_STOP_Y 0x88 ++#define VENC_AVID_START_STOP_X 0x90 ++#define VENC_AVID_START_STOP_Y 0x94 ++#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0 ++#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4 ++#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8 ++#define VENC_TVDETGP_INT_START_STOP_X 0xB0 ++#define VENC_TVDETGP_INT_START_STOP_Y 0xB4 ++#define VENC_GEN_CTRL 0xB8 ++#define VENC_OUTPUT_CONTROL 0xC4 ++#define VENC_OUTPUT_TEST 0xC8 ++#define VENC_DAC_B__DAC_C 0xC8 ++ ++struct venc_config { ++ u32 f_control; ++ u32 vidout_ctrl; ++ u32 sync_ctrl; ++ u32 llen; ++ u32 flens; ++ u32 hfltr_ctrl; ++ u32 cc_carr_wss_carr; ++ u32 c_phase; ++ u32 gain_u; ++ u32 gain_v; ++ u32 gain_y; ++ u32 black_level; ++ u32 blank_level; ++ u32 x_color; ++ u32 m_control; ++ u32 bstamp_wss_data; ++ u32 s_carr; ++ u32 line21; ++ u32 ln_sel; ++ u32 l21__wc_ctl; ++ u32 htrigger_vtrigger; ++ u32 savid__eavid; ++ u32 flen__fal; ++ u32 lal__phase_reset; ++ u32 hs_int_start_stop_x; ++ u32 hs_ext_start_stop_x; ++ u32 vs_int_start_x; ++ u32 vs_int_stop_x__vs_int_start_y; ++ u32 vs_int_stop_y__vs_ext_start_x; ++ u32 vs_ext_stop_x__vs_ext_start_y; ++ u32 vs_ext_stop_y; ++ u32 avid_start_stop_x; ++ u32 avid_start_stop_y; ++ u32 fid_int_start_x__fid_int_start_y; ++ u32 fid_int_offset_y__fid_ext_start_x; ++ u32 fid_ext_start_y__fid_ext_offset_y; ++ u32 tvdetgp_int_start_stop_x; ++ u32 tvdetgp_int_start_stop_y; ++ u32 gen_ctrl; ++}; ++ ++/* from TRM */ ++static const struct venc_config venc_config_pal_trm = { ++ .f_control = 0, ++ .vidout_ctrl = 1, ++ .sync_ctrl = 0x40, ++ .llen = 0x35F, /* 863 */ ++ .flens = 0x270, /* 624 */ ++ .hfltr_ctrl = 0, ++ .cc_carr_wss_carr = 0x2F7225ED, ++ .c_phase = 0, ++ .gain_u = 0x111, ++ .gain_v = 0x181, ++ .gain_y = 0x140, ++ .black_level = 0x3B, ++ .blank_level = 0x3B, ++ .x_color = 0x7, ++ .m_control = 0x2, ++ .bstamp_wss_data = 0x3F, ++ .s_carr = 0x2A098ACB, ++ .line21 = 0, ++ .ln_sel = 0x01290015, ++ .l21__wc_ctl = 0x0000F603, ++ .htrigger_vtrigger = 0, ++ ++ .savid__eavid = 0x06A70108, ++ .flen__fal = 0x00180270, ++ .lal__phase_reset = 0x00040135, ++ .hs_int_start_stop_x = 0x00880358, ++ .hs_ext_start_stop_x = 0x000F035F, ++ .vs_int_start_x = 0x01A70000, ++ .vs_int_stop_x__vs_int_start_y = 0x000001A7, ++ .vs_int_stop_y__vs_ext_start_x = 0x01AF0000, ++ .vs_ext_stop_x__vs_ext_start_y = 0x000101AF, ++ .vs_ext_stop_y = 0x00000025, ++ .avid_start_stop_x = 0x03530083, ++ .avid_start_stop_y = 0x026C002E, ++ .fid_int_start_x__fid_int_start_y = 0x0001008A, ++ .fid_int_offset_y__fid_ext_start_x = 0x002E0138, ++ .fid_ext_start_y__fid_ext_offset_y = 0x01380001, ++ ++ .tvdetgp_int_start_stop_x = 0x00140001, ++ .tvdetgp_int_start_stop_y = 0x00010001, ++ .gen_ctrl = 0x00FF0000, ++}; ++ ++/* from TRM */ ++static const struct venc_config venc_config_ntsc_trm = { ++ .f_control = 0, ++ .vidout_ctrl = 1, ++ .sync_ctrl = 0x8040, ++ .llen = 0x359, ++ .flens = 0x20C, ++ .hfltr_ctrl = 0, ++ .cc_carr_wss_carr = 0x043F2631, ++ .c_phase = 0, ++ .gain_u = 0x102, ++ .gain_v = 0x16C, ++ .gain_y = 0x12F, ++ .black_level = 0x43, ++ .blank_level = 0x38, ++ .x_color = 0x7, ++ .m_control = 0x1, ++ .bstamp_wss_data = 0x38, ++ .s_carr = 0x21F07C1F, ++ .line21 = 0, ++ .ln_sel = 0x01310011, ++ .l21__wc_ctl = 0x0000F003, ++ .htrigger_vtrigger = 0, ++ ++ .savid__eavid = 0x069300F4, ++ .flen__fal = 0x0016020C, ++ .lal__phase_reset = 0x00060107, ++ .hs_int_start_stop_x = 0x008E0350, ++ .hs_ext_start_stop_x = 0x000F0359, ++ .vs_int_start_x = 0x01A00000, ++ .vs_int_stop_x__vs_int_start_y = 0x020701A0, ++ .vs_int_stop_y__vs_ext_start_x = 0x01AC0024, ++ .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC, ++ .vs_ext_stop_y = 0x00000006, ++ .avid_start_stop_x = 0x03480078, ++ .avid_start_stop_y = 0x02060024, ++ .fid_int_start_x__fid_int_start_y = 0x0001008A, ++ .fid_int_offset_y__fid_ext_start_x = 0x01AC0106, ++ .fid_ext_start_y__fid_ext_offset_y = 0x01060006, ++ ++ .tvdetgp_int_start_stop_x = 0x00140001, ++ .tvdetgp_int_start_stop_y = 0x00010001, ++ .gen_ctrl = 0x00F90000, ++}; ++ ++static const struct venc_config venc_config_pal_bdghi = { ++ .f_control = 0, ++ .vidout_ctrl = 0, ++ .sync_ctrl = 0, ++ .hfltr_ctrl = 0, ++ .x_color = 0, ++ .line21 = 0, ++ .ln_sel = 21, ++ .htrigger_vtrigger = 0, ++ .tvdetgp_int_start_stop_x = 0x00140001, ++ .tvdetgp_int_start_stop_y = 0x00010001, ++ .gen_ctrl = 0x00FB0000, ++ ++ .llen = 864-1, ++ .flens = 625-1, ++ .cc_carr_wss_carr = 0x2F7625ED, ++ .c_phase = 0xDF, ++ .gain_u = 0x111, ++ .gain_v = 0x181, ++ .gain_y = 0x140, ++ .black_level = 0x3e, ++ .blank_level = 0x3e, ++ .m_control = 0<<2 | 1<<1, ++ .bstamp_wss_data = 0x42, ++ .s_carr = 0x2a098acb, ++ .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0, ++ .savid__eavid = 0x06A70108, ++ .flen__fal = 23<<16 | 624<<0, ++ .lal__phase_reset = 2<<17 | 310<<0, ++ .hs_int_start_stop_x = 0x00920358, ++ .hs_ext_start_stop_x = 0x000F035F, ++ .vs_int_start_x = 0x1a7<<16, ++ .vs_int_stop_x__vs_int_start_y = 0x000601A7, ++ .vs_int_stop_y__vs_ext_start_x = 0x01AF0036, ++ .vs_ext_stop_x__vs_ext_start_y = 0x27101af, ++ .vs_ext_stop_y = 0x05, ++ .avid_start_stop_x = 0x03530082, ++ .avid_start_stop_y = 0x0270002E, ++ .fid_int_start_x__fid_int_start_y = 0x0005008A, ++ .fid_int_offset_y__fid_ext_start_x = 0x002E0138, ++ .fid_ext_start_y__fid_ext_offset_y = 0x01380005, ++}; ++ ++const struct omap_video_timings omap_dss_pal_timings = { ++ .x_res = 720, ++ .y_res = 574, ++ .pixel_clock = 13500, ++ .hsw = 64, ++ .hfp = 12, ++ .hbp = 68, ++ .vsw = 5, ++ .vfp = 5, ++ .vbp = 41, ++}; ++EXPORT_SYMBOL(omap_dss_pal_timings); ++ ++const struct omap_video_timings omap_dss_ntsc_timings = { ++ .x_res = 720, ++ .y_res = 482, ++ .pixel_clock = 13500, ++ .hsw = 64, ++ .hfp = 16, ++ .hbp = 58, ++ .vsw = 6, ++ .vfp = 6, ++ .vbp = 31, ++}; ++EXPORT_SYMBOL(omap_dss_ntsc_timings); ++ ++static struct { ++ void __iomem *base; ++ struct mutex venc_lock; ++ u32 wss_data; ++ struct regulator *vdda_dac_reg; ++} venc; ++ ++static inline void venc_write_reg(int idx, u32 val) ++{ ++ __raw_writel(val, venc.base + idx); ++} ++ ++static inline u32 venc_read_reg(int idx) ++{ ++ u32 l = __raw_readl(venc.base + idx); ++ return l; ++} ++ ++static void venc_write_config(const struct venc_config *config) ++{ ++ DSSDBG("write venc conf\n"); ++ ++ venc_write_reg(VENC_LLEN, config->llen); ++ venc_write_reg(VENC_FLENS, config->flens); ++ venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr); ++ venc_write_reg(VENC_C_PHASE, config->c_phase); ++ venc_write_reg(VENC_GAIN_U, config->gain_u); ++ venc_write_reg(VENC_GAIN_V, config->gain_v); ++ venc_write_reg(VENC_GAIN_Y, config->gain_y); ++ venc_write_reg(VENC_BLACK_LEVEL, config->black_level); ++ venc_write_reg(VENC_BLANK_LEVEL, config->blank_level); ++ venc_write_reg(VENC_M_CONTROL, config->m_control); ++ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | ++ venc.wss_data); ++ venc_write_reg(VENC_S_CARR, config->s_carr); ++ venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl); ++ venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid); ++ venc_write_reg(VENC_FLEN__FAL, config->flen__fal); ++ venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset); ++ venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x); ++ venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x); ++ venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x); ++ venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y, ++ config->vs_int_stop_x__vs_int_start_y); ++ venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X, ++ config->vs_int_stop_y__vs_ext_start_x); ++ venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y, ++ config->vs_ext_stop_x__vs_ext_start_y); ++ venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y); ++ venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x); ++ venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y); ++ venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y, ++ config->fid_int_start_x__fid_int_start_y); ++ venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X, ++ config->fid_int_offset_y__fid_ext_start_x); ++ venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y, ++ config->fid_ext_start_y__fid_ext_offset_y); ++ ++ venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C)); ++ venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl); ++ venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl); ++ venc_write_reg(VENC_X_COLOR, config->x_color); ++ venc_write_reg(VENC_LINE21, config->line21); ++ venc_write_reg(VENC_LN_SEL, config->ln_sel); ++ venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger); ++ venc_write_reg(VENC_TVDETGP_INT_START_STOP_X, ++ config->tvdetgp_int_start_stop_x); ++ venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y, ++ config->tvdetgp_int_start_stop_y); ++ venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl); ++ venc_write_reg(VENC_F_CONTROL, config->f_control); ++ venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl); ++} ++ ++static void venc_reset(void) ++{ ++ int t = 1000; ++ ++ venc_write_reg(VENC_F_CONTROL, 1<<8); ++ while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) { ++ if (--t == 0) { ++ DSSERR("Failed to reset venc\n"); ++ return; ++ } ++ } ++ ++ /* the magical sleep that makes things work */ ++ msleep(20); ++} ++ ++static void venc_enable_clocks(int enable) ++{ ++ if (enable) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | ++ DSS_CLK_96M); ++ else ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | ++ DSS_CLK_96M); ++} ++ ++static const struct venc_config *venc_timings_to_config( ++ struct omap_video_timings *timings) ++{ ++ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0) ++ return &venc_config_pal_trm; ++ ++ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0) ++ return &venc_config_ntsc_trm; ++ ++ BUG(); ++} ++ ++ ++ ++ ++ ++/* driver */ ++static int venc_panel_probe(struct omap_dss_device *dssdev) ++{ ++ dssdev->panel.timings = omap_dss_pal_timings; ++ ++ return 0; ++} ++ ++static void venc_panel_remove(struct omap_dss_device *dssdev) ++{ ++} ++ ++static int venc_panel_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ /* wait couple of vsyncs until enabling the LCD */ ++ msleep(50); ++ ++ if (dssdev->platform_enable) ++ r = dssdev->platform_enable(dssdev); ++ ++ return r; ++} ++ ++static void venc_panel_disable(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++ ++ /* wait at least 5 vsyncs after disabling the LCD */ ++ ++ msleep(100); ++} ++ ++static int venc_panel_suspend(struct omap_dss_device *dssdev) ++{ ++ venc_panel_disable(dssdev); ++ return 0; ++} ++ ++static int venc_panel_resume(struct omap_dss_device *dssdev) ++{ ++ return venc_panel_enable(dssdev); ++} ++ ++static struct omap_dss_driver venc_driver = { ++ .probe = venc_panel_probe, ++ .remove = venc_panel_remove, ++ ++ .enable = venc_panel_enable, ++ .disable = venc_panel_disable, ++ .suspend = venc_panel_suspend, ++ .resume = venc_panel_resume, ++ ++ .driver = { ++ .name = "venc", ++ .owner = THIS_MODULE, ++ }, ++}; ++/* driver end */ ++ ++ ++ ++int venc_init(struct platform_device *pdev) ++{ ++ u8 rev_id; ++ ++ mutex_init(&venc.venc_lock); ++ ++ venc.wss_data = 0; ++ ++ venc.base = ioremap(VENC_BASE, SZ_1K); ++ if (!venc.base) { ++ DSSERR("can't ioremap VENC\n"); ++ return -ENOMEM; ++ } ++ ++ venc.vdda_dac_reg = regulator_get(&pdev->dev, "vdda_dac"); ++ if (IS_ERR(venc.vdda_dac_reg)) { ++ iounmap(venc.base); ++ DSSERR("can't get VDDA_DAC regulator\n"); ++ return PTR_ERR(venc.vdda_dac_reg); ++ } ++ ++ venc_enable_clocks(1); ++ ++ rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); ++ printk(KERN_INFO "OMAP VENC rev %d\n", rev_id); ++ ++ venc_enable_clocks(0); ++ ++ return omap_dss_register_driver(&venc_driver); ++} ++ ++void venc_exit(void) ++{ ++ omap_dss_unregister_driver(&venc_driver); ++ ++ regulator_put(venc.vdda_dac_reg); ++ ++ iounmap(venc.base); ++} ++ ++static void venc_power_on(struct omap_dss_device *dssdev) ++{ ++ u32 l; ++ ++ venc_enable_clocks(1); ++ ++ venc_reset(); ++ venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); ++ ++ dss_set_venc_output(dssdev->phy.venc.type); ++ dss_set_dac_pwrdn_bgz(1); ++ ++ l = 0; ++ ++ if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) ++ l |= 1 << 1; ++ else /* S-Video */ ++ l |= (1 << 0) | (1 << 2); ++ ++ if (dssdev->phy.venc.invert_polarity == false) ++ l |= 1 << 3; ++ ++ venc_write_reg(VENC_OUTPUT_CONTROL, l); ++ ++ dispc_set_digit_size(dssdev->panel.timings.x_res, ++ dssdev->panel.timings.y_res/2); ++ ++ regulator_enable(venc.vdda_dac_reg); ++ ++ if (dssdev->platform_enable) ++ dssdev->platform_enable(dssdev); ++ ++ dispc_enable_digit_out(1); ++} ++ ++static void venc_power_off(struct omap_dss_device *dssdev) ++{ ++ venc_write_reg(VENC_OUTPUT_CONTROL, 0); ++ dss_set_dac_pwrdn_bgz(0); ++ ++ dispc_enable_digit_out(0); ++ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++ ++ regulator_disable(venc.vdda_dac_reg); ++ ++ venc_enable_clocks(0); ++} ++ ++static int venc_enable_display(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("venc_enable_display\n"); ++ ++ mutex_lock(&venc.venc_lock); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ venc_power_on(dssdev); ++ ++ venc.wss_data = 0; ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++err: ++ mutex_unlock(&venc.venc_lock); ++ ++ return r; ++} ++ ++static void venc_disable_display(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("venc_disable_display\n"); ++ ++ mutex_lock(&venc.venc_lock); ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) ++ goto end; ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) { ++ /* suspended is the same as disabled with venc */ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++ goto end; ++ } ++ ++ venc_power_off(dssdev); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++end: ++ mutex_unlock(&venc.venc_lock); ++} ++ ++static int venc_display_suspend(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("venc_display_suspend\n"); ++ ++ mutex_lock(&venc.venc_lock); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ venc_power_off(dssdev); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; ++err: ++ mutex_unlock(&venc.venc_lock); ++ ++ return r; ++} ++ ++static int venc_display_resume(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("venc_display_resume\n"); ++ ++ mutex_lock(&venc.venc_lock); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ venc_power_on(dssdev); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++err: ++ mutex_unlock(&venc.venc_lock); ++ ++ return r; ++} ++ ++static void venc_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ *timings = dssdev->panel.timings; ++} ++ ++static void venc_set_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ DSSDBG("venc_set_timings\n"); ++ ++ /* Reset WSS data when the TV standard changes. */ ++ if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings))) ++ venc.wss_data = 0; ++ ++ dssdev->panel.timings = *timings; ++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { ++ /* turn the venc off and on to get new timings to use */ ++ venc_disable_display(dssdev); ++ venc_enable_display(dssdev); ++ } ++} ++ ++static int venc_check_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ DSSDBG("venc_check_timings\n"); ++ ++ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0) ++ return 0; ++ ++ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0) ++ return 0; ++ ++ return -EINVAL; ++} ++ ++static u32 venc_get_wss(struct omap_dss_device *dssdev) ++{ ++ /* Invert due to VENC_L21_WC_CTL:INV=1 */ ++ return (venc.wss_data >> 8) ^ 0xfffff; ++} ++ ++static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) ++{ ++ const struct venc_config *config; ++ ++ DSSDBG("venc_set_wss\n"); ++ ++ mutex_lock(&venc.venc_lock); ++ ++ config = venc_timings_to_config(&dssdev->panel.timings); ++ ++ /* Invert due to VENC_L21_WC_CTL:INV=1 */ ++ venc.wss_data = (wss ^ 0xfffff) << 8; ++ ++ venc_enable_clocks(1); ++ ++ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | ++ venc.wss_data); ++ ++ venc_enable_clocks(0); ++ ++ mutex_unlock(&venc.venc_lock); ++ ++ return 0; ++} ++ ++static enum omap_dss_update_mode venc_display_get_update_mode( ++ struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) ++ return OMAP_DSS_UPDATE_AUTO; ++ else ++ return OMAP_DSS_UPDATE_DISABLED; ++} ++ ++int venc_init_display(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("init_display\n"); ++ ++ dssdev->enable = venc_enable_display; ++ dssdev->disable = venc_disable_display; ++ dssdev->suspend = venc_display_suspend; ++ dssdev->resume = venc_display_resume; ++ dssdev->get_timings = venc_get_timings; ++ dssdev->set_timings = venc_set_timings; ++ dssdev->check_timings = venc_check_timings; ++ dssdev->get_wss = venc_get_wss; ++ dssdev->set_wss = venc_set_wss; ++ dssdev->get_update_mode = venc_display_get_update_mode; ++ ++ return 0; ++} ++ ++void venc_dump_regs(struct seq_file *s) ++{ ++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) ++ ++ venc_enable_clocks(1); ++ ++ DUMPREG(VENC_F_CONTROL); ++ DUMPREG(VENC_VIDOUT_CTRL); ++ DUMPREG(VENC_SYNC_CTRL); ++ DUMPREG(VENC_LLEN); ++ DUMPREG(VENC_FLENS); ++ DUMPREG(VENC_HFLTR_CTRL); ++ DUMPREG(VENC_CC_CARR_WSS_CARR); ++ DUMPREG(VENC_C_PHASE); ++ DUMPREG(VENC_GAIN_U); ++ DUMPREG(VENC_GAIN_V); ++ DUMPREG(VENC_GAIN_Y); ++ DUMPREG(VENC_BLACK_LEVEL); ++ DUMPREG(VENC_BLANK_LEVEL); ++ DUMPREG(VENC_X_COLOR); ++ DUMPREG(VENC_M_CONTROL); ++ DUMPREG(VENC_BSTAMP_WSS_DATA); ++ DUMPREG(VENC_S_CARR); ++ DUMPREG(VENC_LINE21); ++ DUMPREG(VENC_LN_SEL); ++ DUMPREG(VENC_L21__WC_CTL); ++ DUMPREG(VENC_HTRIGGER_VTRIGGER); ++ DUMPREG(VENC_SAVID__EAVID); ++ DUMPREG(VENC_FLEN__FAL); ++ DUMPREG(VENC_LAL__PHASE_RESET); ++ DUMPREG(VENC_HS_INT_START_STOP_X); ++ DUMPREG(VENC_HS_EXT_START_STOP_X); ++ DUMPREG(VENC_VS_INT_START_X); ++ DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y); ++ DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X); ++ DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y); ++ DUMPREG(VENC_VS_EXT_STOP_Y); ++ DUMPREG(VENC_AVID_START_STOP_X); ++ DUMPREG(VENC_AVID_START_STOP_Y); ++ DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y); ++ DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X); ++ DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y); ++ DUMPREG(VENC_TVDETGP_INT_START_STOP_X); ++ DUMPREG(VENC_TVDETGP_INT_START_STOP_Y); ++ DUMPREG(VENC_GEN_CTRL); ++ DUMPREG(VENC_OUTPUT_CONTROL); ++ DUMPREG(VENC_OUTPUT_TEST); ++ ++ venc_enable_clocks(0); ++ ++#undef DUMPREG ++} +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0012-OMAP-DSS2-RFBI-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0012-OMAP-DSS2-RFBI-driver.patch new file mode 100644 index 0000000000..7fe06c3843 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0012-OMAP-DSS2-RFBI-driver.patch @@ -0,0 +1,1332 @@ +From 6770052329a65dd34cf0a9d6356b650aacb3a535 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Wed, 5 Aug 2009 16:18:31 +0300 +Subject: [PATCH 12/18] OMAP: DSS2: RFBI driver + +RFBI (Remote FrameBuffer Interface) implements MIPI DBI interface. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + drivers/video/omap2/dss/rfbi.c | 1310 ++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 1310 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/dss/rfbi.c + +diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c +new file mode 100644 +index 0000000..9dd2349 +--- /dev/null ++++ b/drivers/video/omap2/dss/rfbi.c +@@ -0,0 +1,1310 @@ ++/* ++ * linux/drivers/video/omap2/dss/rfbi.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "RFBI" ++ ++#include <linux/kernel.h> ++#include <linux/dma-mapping.h> ++#include <linux/vmalloc.h> ++#include <linux/clk.h> ++#include <linux/io.h> ++#include <linux/delay.h> ++#include <linux/kfifo.h> ++#include <linux/ktime.h> ++#include <linux/hrtimer.h> ++#include <linux/seq_file.h> ++ ++#include <mach/board.h> ++#include <mach/display.h> ++#include "dss.h" ++ ++/*#define MEASURE_PERF*/ ++ ++#define RFBI_BASE 0x48050800 ++ ++struct rfbi_reg { u16 idx; }; ++ ++#define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) ++ ++#define RFBI_REVISION RFBI_REG(0x0000) ++#define RFBI_SYSCONFIG RFBI_REG(0x0010) ++#define RFBI_SYSSTATUS RFBI_REG(0x0014) ++#define RFBI_CONTROL RFBI_REG(0x0040) ++#define RFBI_PIXEL_CNT RFBI_REG(0x0044) ++#define RFBI_LINE_NUMBER RFBI_REG(0x0048) ++#define RFBI_CMD RFBI_REG(0x004c) ++#define RFBI_PARAM RFBI_REG(0x0050) ++#define RFBI_DATA RFBI_REG(0x0054) ++#define RFBI_READ RFBI_REG(0x0058) ++#define RFBI_STATUS RFBI_REG(0x005c) ++ ++#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18) ++#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18) ++#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18) ++#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18) ++#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18) ++#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18) ++ ++#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090) ++#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094) ++ ++#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param)) ++ ++#define REG_FLD_MOD(idx, val, start, end) \ ++ rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) ++ ++/* To work around an RFBI transfer rate limitation */ ++#define OMAP_RFBI_RATE_LIMIT 1 ++ ++enum omap_rfbi_cycleformat { ++ OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0, ++ OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1, ++ OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2, ++ OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3, ++}; ++ ++enum omap_rfbi_datatype { ++ OMAP_DSS_RFBI_DATATYPE_12 = 0, ++ OMAP_DSS_RFBI_DATATYPE_16 = 1, ++ OMAP_DSS_RFBI_DATATYPE_18 = 2, ++ OMAP_DSS_RFBI_DATATYPE_24 = 3, ++}; ++ ++enum omap_rfbi_parallelmode { ++ OMAP_DSS_RFBI_PARALLELMODE_8 = 0, ++ OMAP_DSS_RFBI_PARALLELMODE_9 = 1, ++ OMAP_DSS_RFBI_PARALLELMODE_12 = 2, ++ OMAP_DSS_RFBI_PARALLELMODE_16 = 3, ++}; ++ ++enum update_cmd { ++ RFBI_CMD_UPDATE = 0, ++ RFBI_CMD_SYNC = 1, ++}; ++ ++static int rfbi_convert_timings(struct rfbi_timings *t); ++static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); ++static void process_cmd_fifo(void); ++ ++static struct { ++ void __iomem *base; ++ ++ unsigned long l4_khz; ++ ++ enum omap_rfbi_datatype datatype; ++ enum omap_rfbi_parallelmode parallelmode; ++ ++ enum omap_rfbi_te_mode te_mode; ++ int te_enabled; ++ ++ void (*framedone_callback)(void *data); ++ void *framedone_callback_data; ++ ++ struct omap_dss_device *dssdev[2]; ++ ++ struct kfifo *cmd_fifo; ++ spinlock_t cmd_lock; ++ struct completion cmd_done; ++ atomic_t cmd_fifo_full; ++ atomic_t cmd_pending; ++#ifdef MEASURE_PERF ++ unsigned perf_bytes; ++ ktime_t perf_setup_time; ++ ktime_t perf_start_time; ++#endif ++} rfbi; ++ ++struct update_region { ++ u16 x; ++ u16 y; ++ u16 w; ++ u16 h; ++}; ++ ++struct update_param { ++ u8 rfbi_module; ++ u8 cmd; ++ ++ union { ++ struct update_region r; ++ struct completion *sync; ++ } par; ++}; ++ ++static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) ++{ ++ __raw_writel(val, rfbi.base + idx.idx); ++} ++ ++static inline u32 rfbi_read_reg(const struct rfbi_reg idx) ++{ ++ return __raw_readl(rfbi.base + idx.idx); ++} ++ ++static void rfbi_enable_clocks(bool enable) ++{ ++ if (enable) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ else ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++} ++ ++void omap_rfbi_write_command(const void *buf, u32 len) ++{ ++ rfbi_enable_clocks(1); ++ switch (rfbi.parallelmode) { ++ case OMAP_DSS_RFBI_PARALLELMODE_8: ++ { ++ const u8 *b = buf; ++ for (; len; len--) ++ rfbi_write_reg(RFBI_CMD, *b++); ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_16: ++ { ++ const u16 *w = buf; ++ BUG_ON(len & 1); ++ for (; len; len -= 2) ++ rfbi_write_reg(RFBI_CMD, *w++); ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_9: ++ case OMAP_DSS_RFBI_PARALLELMODE_12: ++ default: ++ BUG(); ++ } ++ rfbi_enable_clocks(0); ++} ++EXPORT_SYMBOL(omap_rfbi_write_command); ++ ++void omap_rfbi_read_data(void *buf, u32 len) ++{ ++ rfbi_enable_clocks(1); ++ switch (rfbi.parallelmode) { ++ case OMAP_DSS_RFBI_PARALLELMODE_8: ++ { ++ u8 *b = buf; ++ for (; len; len--) { ++ rfbi_write_reg(RFBI_READ, 0); ++ *b++ = rfbi_read_reg(RFBI_READ); ++ } ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_16: ++ { ++ u16 *w = buf; ++ BUG_ON(len & ~1); ++ for (; len; len -= 2) { ++ rfbi_write_reg(RFBI_READ, 0); ++ *w++ = rfbi_read_reg(RFBI_READ); ++ } ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_9: ++ case OMAP_DSS_RFBI_PARALLELMODE_12: ++ default: ++ BUG(); ++ } ++ rfbi_enable_clocks(0); ++} ++EXPORT_SYMBOL(omap_rfbi_read_data); ++ ++void omap_rfbi_write_data(const void *buf, u32 len) ++{ ++ rfbi_enable_clocks(1); ++ switch (rfbi.parallelmode) { ++ case OMAP_DSS_RFBI_PARALLELMODE_8: ++ { ++ const u8 *b = buf; ++ for (; len; len--) ++ rfbi_write_reg(RFBI_PARAM, *b++); ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_16: ++ { ++ const u16 *w = buf; ++ BUG_ON(len & 1); ++ for (; len; len -= 2) ++ rfbi_write_reg(RFBI_PARAM, *w++); ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_9: ++ case OMAP_DSS_RFBI_PARALLELMODE_12: ++ default: ++ BUG(); ++ ++ } ++ rfbi_enable_clocks(0); ++} ++EXPORT_SYMBOL(omap_rfbi_write_data); ++ ++void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, ++ u16 x, u16 y, ++ u16 w, u16 h) ++{ ++ int start_offset = scr_width * y + x; ++ int horiz_offset = scr_width - w; ++ int i; ++ ++ rfbi_enable_clocks(1); ++ ++ if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && ++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { ++ const u16 __iomem *pd = buf; ++ pd += start_offset; ++ ++ for (; h; --h) { ++ for (i = 0; i < w; ++i) { ++ const u8 __iomem *b = (const u8 __iomem *)pd; ++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1)); ++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0)); ++ ++pd; ++ } ++ pd += horiz_offset; ++ } ++ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 && ++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { ++ const u32 __iomem *pd = buf; ++ pd += start_offset; ++ ++ for (; h; --h) { ++ for (i = 0; i < w; ++i) { ++ const u8 __iomem *b = (const u8 __iomem *)pd; ++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2)); ++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1)); ++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0)); ++ ++pd; ++ } ++ pd += horiz_offset; ++ } ++ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && ++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) { ++ const u16 __iomem *pd = buf; ++ pd += start_offset; ++ ++ for (; h; --h) { ++ for (i = 0; i < w; ++i) { ++ rfbi_write_reg(RFBI_PARAM, __raw_readw(pd)); ++ ++pd; ++ } ++ pd += horiz_offset; ++ } ++ } else { ++ BUG(); ++ } ++ ++ rfbi_enable_clocks(0); ++} ++EXPORT_SYMBOL(omap_rfbi_write_pixels); ++ ++#ifdef MEASURE_PERF ++static void perf_mark_setup(void) ++{ ++ rfbi.perf_setup_time = ktime_get(); ++} ++ ++static void perf_mark_start(void) ++{ ++ rfbi.perf_start_time = ktime_get(); ++} ++ ++static void perf_show(const char *name) ++{ ++ ktime_t t, setup_time, trans_time; ++ u32 total_bytes; ++ u32 setup_us, trans_us, total_us; ++ ++ t = ktime_get(); ++ ++ setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time); ++ setup_us = (u32)ktime_to_us(setup_time); ++ if (setup_us == 0) ++ setup_us = 1; ++ ++ trans_time = ktime_sub(t, rfbi.perf_start_time); ++ trans_us = (u32)ktime_to_us(trans_time); ++ if (trans_us == 0) ++ trans_us = 1; ++ ++ total_us = setup_us + trans_us; ++ ++ total_bytes = rfbi.perf_bytes; ++ ++ DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, " ++ "%u kbytes/sec\n", ++ name, ++ setup_us, ++ trans_us, ++ total_us, ++ 1000*1000 / total_us, ++ total_bytes, ++ total_bytes * 1000 / total_us); ++} ++#else ++#define perf_mark_setup() ++#define perf_mark_start() ++#define perf_show(x) ++#endif ++ ++void rfbi_transfer_area(u16 width, u16 height, ++ void (callback)(void *data), void *data) ++{ ++ u32 l; ++ ++ /*BUG_ON(callback == 0);*/ ++ BUG_ON(rfbi.framedone_callback != NULL); ++ ++ DSSDBG("rfbi_transfer_area %dx%d\n", width, height); ++ ++ dispc_set_lcd_size(width, height); ++ ++ dispc_enable_lcd_out(1); ++ ++ rfbi.framedone_callback = callback; ++ rfbi.framedone_callback_data = data; ++ ++ rfbi_enable_clocks(1); ++ ++ rfbi_write_reg(RFBI_PIXEL_CNT, width * height); ++ ++ l = rfbi_read_reg(RFBI_CONTROL); ++ l = FLD_MOD(l, 1, 0, 0); /* enable */ ++ if (!rfbi.te_enabled) ++ l = FLD_MOD(l, 1, 4, 4); /* ITE */ ++ ++ perf_mark_start(); ++ ++ rfbi_write_reg(RFBI_CONTROL, l); ++} ++ ++static void framedone_callback(void *data, u32 mask) ++{ ++ void (*callback)(void *data); ++ ++ DSSDBG("FRAMEDONE\n"); ++ ++ perf_show("DISPC"); ++ ++ REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); ++ ++ rfbi_enable_clocks(0); ++ ++ callback = rfbi.framedone_callback; ++ rfbi.framedone_callback = NULL; ++ ++ /*callback(rfbi.framedone_callback_data);*/ ++ ++ atomic_set(&rfbi.cmd_pending, 0); ++ ++ process_cmd_fifo(); ++} ++ ++#if 1 /* VERBOSE */ ++static void rfbi_print_timings(void) ++{ ++ u32 l; ++ u32 time; ++ ++ l = rfbi_read_reg(RFBI_CONFIG(0)); ++ time = 1000000000 / rfbi.l4_khz; ++ if (l & (1 << 4)) ++ time *= 2; ++ ++ DSSDBG("Tick time %u ps\n", time); ++ l = rfbi_read_reg(RFBI_ONOFF_TIME(0)); ++ DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, " ++ "REONTIME %d, REOFFTIME %d\n", ++ l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f, ++ (l >> 20) & 0x0f, (l >> 24) & 0x3f); ++ ++ l = rfbi_read_reg(RFBI_CYCLE_TIME(0)); ++ DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, " ++ "ACCESSTIME %d\n", ++ (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, ++ (l >> 22) & 0x3f); ++} ++#else ++static void rfbi_print_timings(void) {} ++#endif ++ ++ ++ ++ ++static u32 extif_clk_period; ++ ++static inline unsigned long round_to_extif_ticks(unsigned long ps, int div) ++{ ++ int bus_tick = extif_clk_period * div; ++ return (ps + bus_tick - 1) / bus_tick * bus_tick; ++} ++ ++static int calc_reg_timing(struct rfbi_timings *t, int div) ++{ ++ t->clk_div = div; ++ ++ t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div); ++ ++ t->we_on_time = round_to_extif_ticks(t->we_on_time, div); ++ t->we_off_time = round_to_extif_ticks(t->we_off_time, div); ++ t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div); ++ ++ t->re_on_time = round_to_extif_ticks(t->re_on_time, div); ++ t->re_off_time = round_to_extif_ticks(t->re_off_time, div); ++ t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div); ++ ++ t->access_time = round_to_extif_ticks(t->access_time, div); ++ t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div); ++ t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div); ++ ++ DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n", ++ t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); ++ DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n", ++ t->we_on_time, t->we_off_time, t->re_cycle_time, ++ t->we_cycle_time); ++ DSSDBG("[reg]rdaccess %d cspulse %d\n", ++ t->access_time, t->cs_pulse_width); ++ ++ return rfbi_convert_timings(t); ++} ++ ++static int calc_extif_timings(struct rfbi_timings *t) ++{ ++ u32 max_clk_div; ++ int div; ++ ++ rfbi_get_clk_info(&extif_clk_period, &max_clk_div); ++ for (div = 1; div <= max_clk_div; div++) { ++ if (calc_reg_timing(t, div) == 0) ++ break; ++ } ++ ++ if (div <= max_clk_div) ++ return 0; ++ ++ DSSERR("can't setup timings\n"); ++ return -1; ++} ++ ++ ++void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) ++{ ++ int r; ++ ++ if (!t->converted) { ++ r = calc_extif_timings(t); ++ if (r < 0) ++ DSSERR("Failed to calc timings\n"); ++ } ++ ++ BUG_ON(!t->converted); ++ ++ rfbi_enable_clocks(1); ++ rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]); ++ rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]); ++ ++ /* TIMEGRANULARITY */ ++ REG_FLD_MOD(RFBI_CONFIG(rfbi_module), ++ (t->tim[2] ? 1 : 0), 4, 4); ++ ++ rfbi_print_timings(); ++ rfbi_enable_clocks(0); ++} ++ ++static int ps_to_rfbi_ticks(int time, int div) ++{ ++ unsigned long tick_ps; ++ int ret; ++ ++ /* Calculate in picosecs to yield more exact results */ ++ tick_ps = 1000000000 / (rfbi.l4_khz) * div; ++ ++ ret = (time + tick_ps - 1) / tick_ps; ++ ++ return ret; ++} ++ ++#ifdef OMAP_RFBI_RATE_LIMIT ++unsigned long rfbi_get_max_tx_rate(void) ++{ ++ unsigned long l4_rate, dss1_rate; ++ int min_l4_ticks = 0; ++ int i; ++ ++ /* According to TI this can't be calculated so make the ++ * adjustments for a couple of known frequencies and warn for ++ * others. ++ */ ++ static const struct { ++ unsigned long l4_clk; /* HZ */ ++ unsigned long dss1_clk; /* HZ */ ++ unsigned long min_l4_ticks; ++ } ftab[] = { ++ { 55, 132, 7, }, /* 7.86 MPix/s */ ++ { 110, 110, 12, }, /* 9.16 MPix/s */ ++ { 110, 132, 10, }, /* 11 Mpix/s */ ++ { 120, 120, 10, }, /* 12 Mpix/s */ ++ { 133, 133, 10, }, /* 13.3 Mpix/s */ ++ }; ++ ++ l4_rate = rfbi.l4_khz / 1000; ++ dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000; ++ ++ for (i = 0; i < ARRAY_SIZE(ftab); i++) { ++ /* Use a window instead of an exact match, to account ++ * for different DPLL multiplier / divider pairs. ++ */ ++ if (abs(ftab[i].l4_clk - l4_rate) < 3 && ++ abs(ftab[i].dss1_clk - dss1_rate) < 3) { ++ min_l4_ticks = ftab[i].min_l4_ticks; ++ break; ++ } ++ } ++ if (i == ARRAY_SIZE(ftab)) { ++ /* Can't be sure, return anyway the maximum not ++ * rate-limited. This might cause a problem only for the ++ * tearing synchronisation. ++ */ ++ DSSERR("can't determine maximum RFBI transfer rate\n"); ++ return rfbi.l4_khz * 1000; ++ } ++ return rfbi.l4_khz * 1000 / min_l4_ticks; ++} ++#else ++int rfbi_get_max_tx_rate(void) ++{ ++ return rfbi.l4_khz * 1000; ++} ++#endif ++ ++static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) ++{ ++ *clk_period = 1000000000 / rfbi.l4_khz; ++ *max_clk_div = 2; ++} ++ ++static int rfbi_convert_timings(struct rfbi_timings *t) ++{ ++ u32 l; ++ int reon, reoff, weon, weoff, cson, csoff, cs_pulse; ++ int actim, recyc, wecyc; ++ int div = t->clk_div; ++ ++ if (div <= 0 || div > 2) ++ return -1; ++ ++ /* Make sure that after conversion it still holds that: ++ * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff, ++ * csoff > cson, csoff >= max(weoff, reoff), actim > reon ++ */ ++ weon = ps_to_rfbi_ticks(t->we_on_time, div); ++ weoff = ps_to_rfbi_ticks(t->we_off_time, div); ++ if (weoff <= weon) ++ weoff = weon + 1; ++ if (weon > 0x0f) ++ return -1; ++ if (weoff > 0x3f) ++ return -1; ++ ++ reon = ps_to_rfbi_ticks(t->re_on_time, div); ++ reoff = ps_to_rfbi_ticks(t->re_off_time, div); ++ if (reoff <= reon) ++ reoff = reon + 1; ++ if (reon > 0x0f) ++ return -1; ++ if (reoff > 0x3f) ++ return -1; ++ ++ cson = ps_to_rfbi_ticks(t->cs_on_time, div); ++ csoff = ps_to_rfbi_ticks(t->cs_off_time, div); ++ if (csoff <= cson) ++ csoff = cson + 1; ++ if (csoff < max(weoff, reoff)) ++ csoff = max(weoff, reoff); ++ if (cson > 0x0f) ++ return -1; ++ if (csoff > 0x3f) ++ return -1; ++ ++ l = cson; ++ l |= csoff << 4; ++ l |= weon << 10; ++ l |= weoff << 14; ++ l |= reon << 20; ++ l |= reoff << 24; ++ ++ t->tim[0] = l; ++ ++ actim = ps_to_rfbi_ticks(t->access_time, div); ++ if (actim <= reon) ++ actim = reon + 1; ++ if (actim > 0x3f) ++ return -1; ++ ++ wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div); ++ if (wecyc < weoff) ++ wecyc = weoff; ++ if (wecyc > 0x3f) ++ return -1; ++ ++ recyc = ps_to_rfbi_ticks(t->re_cycle_time, div); ++ if (recyc < reoff) ++ recyc = reoff; ++ if (recyc > 0x3f) ++ return -1; ++ ++ cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div); ++ if (cs_pulse > 0x3f) ++ return -1; ++ ++ l = wecyc; ++ l |= recyc << 6; ++ l |= cs_pulse << 12; ++ l |= actim << 22; ++ ++ t->tim[1] = l; ++ ++ t->tim[2] = div - 1; ++ ++ t->converted = 1; ++ ++ return 0; ++} ++ ++/* xxx FIX module selection missing */ ++int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, ++ unsigned hs_pulse_time, unsigned vs_pulse_time, ++ int hs_pol_inv, int vs_pol_inv, int extif_div) ++{ ++ int hs, vs; ++ int min; ++ u32 l; ++ ++ hs = ps_to_rfbi_ticks(hs_pulse_time, 1); ++ vs = ps_to_rfbi_ticks(vs_pulse_time, 1); ++ if (hs < 2) ++ return -EDOM; ++ if (mode == OMAP_DSS_RFBI_TE_MODE_2) ++ min = 2; ++ else /* OMAP_DSS_RFBI_TE_MODE_1 */ ++ min = 4; ++ if (vs < min) ++ return -EDOM; ++ if (vs == hs) ++ return -EINVAL; ++ rfbi.te_mode = mode; ++ DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n", ++ mode, hs, vs, hs_pol_inv, vs_pol_inv); ++ ++ rfbi_enable_clocks(1); ++ rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); ++ rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); ++ ++ l = rfbi_read_reg(RFBI_CONFIG(0)); ++ if (hs_pol_inv) ++ l &= ~(1 << 21); ++ else ++ l |= 1 << 21; ++ if (vs_pol_inv) ++ l &= ~(1 << 20); ++ else ++ l |= 1 << 20; ++ rfbi_enable_clocks(0); ++ ++ return 0; ++} ++EXPORT_SYMBOL(omap_rfbi_setup_te); ++ ++/* xxx FIX module selection missing */ ++int omap_rfbi_enable_te(bool enable, unsigned line) ++{ ++ u32 l; ++ ++ DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode); ++ if (line > (1 << 11) - 1) ++ return -EINVAL; ++ ++ rfbi_enable_clocks(1); ++ l = rfbi_read_reg(RFBI_CONFIG(0)); ++ l &= ~(0x3 << 2); ++ if (enable) { ++ rfbi.te_enabled = 1; ++ l |= rfbi.te_mode << 2; ++ } else ++ rfbi.te_enabled = 0; ++ rfbi_write_reg(RFBI_CONFIG(0), l); ++ rfbi_write_reg(RFBI_LINE_NUMBER, line); ++ rfbi_enable_clocks(0); ++ ++ return 0; ++} ++EXPORT_SYMBOL(omap_rfbi_enable_te); ++ ++#if 0 ++static void rfbi_enable_config(int enable1, int enable2) ++{ ++ u32 l; ++ int cs = 0; ++ ++ if (enable1) ++ cs |= 1<<0; ++ if (enable2) ++ cs |= 1<<1; ++ ++ rfbi_enable_clocks(1); ++ ++ l = rfbi_read_reg(RFBI_CONTROL); ++ ++ l = FLD_MOD(l, cs, 3, 2); ++ l = FLD_MOD(l, 0, 1, 1); ++ ++ rfbi_write_reg(RFBI_CONTROL, l); ++ ++ ++ l = rfbi_read_reg(RFBI_CONFIG(0)); ++ l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */ ++ /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ ++ /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */ ++ ++ l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */ ++ l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */ ++ l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */ ++ ++ l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0); ++ rfbi_write_reg(RFBI_CONFIG(0), l); ++ ++ rfbi_enable_clocks(0); ++} ++#endif ++ ++int rfbi_configure(int rfbi_module, int bpp, int lines) ++{ ++ u32 l; ++ int cycle1 = 0, cycle2 = 0, cycle3 = 0; ++ enum omap_rfbi_cycleformat cycleformat; ++ enum omap_rfbi_datatype datatype; ++ enum omap_rfbi_parallelmode parallelmode; ++ ++ switch (bpp) { ++ case 12: ++ datatype = OMAP_DSS_RFBI_DATATYPE_12; ++ break; ++ case 16: ++ datatype = OMAP_DSS_RFBI_DATATYPE_16; ++ break; ++ case 18: ++ datatype = OMAP_DSS_RFBI_DATATYPE_18; ++ break; ++ case 24: ++ datatype = OMAP_DSS_RFBI_DATATYPE_24; ++ break; ++ default: ++ BUG(); ++ return 1; ++ } ++ rfbi.datatype = datatype; ++ ++ switch (lines) { ++ case 8: ++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8; ++ break; ++ case 9: ++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9; ++ break; ++ case 12: ++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12; ++ break; ++ case 16: ++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16; ++ break; ++ default: ++ BUG(); ++ return 1; ++ } ++ rfbi.parallelmode = parallelmode; ++ ++ if ((bpp % lines) == 0) { ++ switch (bpp / lines) { ++ case 1: ++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1; ++ break; ++ case 2: ++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1; ++ break; ++ case 3: ++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1; ++ break; ++ default: ++ BUG(); ++ return 1; ++ } ++ } else if ((2 * bpp % lines) == 0) { ++ if ((2 * bpp / lines) == 3) ++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2; ++ else { ++ BUG(); ++ return 1; ++ } ++ } else { ++ BUG(); ++ return 1; ++ } ++ ++ switch (cycleformat) { ++ case OMAP_DSS_RFBI_CYCLEFORMAT_1_1: ++ cycle1 = lines; ++ break; ++ ++ case OMAP_DSS_RFBI_CYCLEFORMAT_2_1: ++ cycle1 = lines; ++ cycle2 = lines; ++ break; ++ ++ case OMAP_DSS_RFBI_CYCLEFORMAT_3_1: ++ cycle1 = lines; ++ cycle2 = lines; ++ cycle3 = lines; ++ break; ++ ++ case OMAP_DSS_RFBI_CYCLEFORMAT_3_2: ++ cycle1 = lines; ++ cycle2 = (lines / 2) | ((lines / 2) << 16); ++ cycle3 = (lines << 16); ++ break; ++ } ++ ++ rfbi_enable_clocks(1); ++ ++ REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */ ++ ++ l = 0; ++ l |= FLD_VAL(parallelmode, 1, 0); ++ l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */ ++ l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */ ++ l |= FLD_VAL(datatype, 6, 5); ++ /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ ++ l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */ ++ l |= FLD_VAL(cycleformat, 10, 9); ++ l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */ ++ l |= FLD_VAL(0, 16, 16); /* A0POLARITY */ ++ l |= FLD_VAL(0, 17, 17); /* REPOLARITY */ ++ l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */ ++ l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */ ++ l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */ ++ l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */ ++ rfbi_write_reg(RFBI_CONFIG(rfbi_module), l); ++ ++ rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1); ++ rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2); ++ rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3); ++ ++ ++ l = rfbi_read_reg(RFBI_CONTROL); ++ l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */ ++ l = FLD_MOD(l, 0, 1, 1); /* clear bypass */ ++ rfbi_write_reg(RFBI_CONTROL, l); ++ ++ ++ DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n", ++ bpp, lines, cycle1, cycle2, cycle3); ++ ++ rfbi_enable_clocks(0); ++ ++ return 0; ++} ++EXPORT_SYMBOL(rfbi_configure); ++ ++static int rfbi_find_display(struct omap_dss_device *dssdev) ++{ ++ if (dssdev == rfbi.dssdev[0]) ++ return 0; ++ ++ if (dssdev == rfbi.dssdev[1]) ++ return 1; ++ ++ BUG(); ++ return -1; ++} ++ ++ ++static void signal_fifo_waiters(void) ++{ ++ if (atomic_read(&rfbi.cmd_fifo_full) > 0) { ++ /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */ ++ complete(&rfbi.cmd_done); ++ atomic_dec(&rfbi.cmd_fifo_full); ++ } ++} ++ ++/* returns 1 for async op, and 0 for sync op */ ++static int do_update(struct omap_dss_device *dssdev, struct update_region *upd) ++{ ++ u16 x = upd->x; ++ u16 y = upd->y; ++ u16 w = upd->w; ++ u16 h = upd->h; ++ ++ perf_mark_setup(); ++ ++ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { ++ /*dssdev->driver->enable_te(dssdev, 1); */ ++ dss_setup_partial_planes(dssdev, &x, &y, &w, &h); ++ } ++ ++#ifdef MEASURE_PERF ++ rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */ ++#endif ++ ++ dssdev->driver->setup_update(dssdev, x, y, w, h); ++ ++ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { ++ rfbi_transfer_area(w, h, NULL, NULL); ++ return 1; ++ } else { ++ struct omap_overlay *ovl; ++ void __iomem *addr; ++ int scr_width; ++ ++ ovl = dssdev->manager->overlays[0]; ++ scr_width = ovl->info.screen_width; ++ addr = ovl->info.vaddr; ++ ++ omap_rfbi_write_pixels(addr, scr_width, x, y, w, h); ++ ++ perf_show("L4"); ++ ++ return 0; ++ } ++} ++ ++static void process_cmd_fifo(void) ++{ ++ int len; ++ struct update_param p; ++ struct omap_dss_device *dssdev; ++ unsigned long flags; ++ ++ if (atomic_inc_return(&rfbi.cmd_pending) != 1) ++ return; ++ ++ while (true) { ++ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags); ++ ++ len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p, ++ sizeof(struct update_param)); ++ if (len == 0) { ++ DSSDBG("nothing more in fifo\n"); ++ atomic_set(&rfbi.cmd_pending, 0); ++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); ++ break; ++ } ++ ++ /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/ ++ ++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); ++ ++ BUG_ON(len != sizeof(struct update_param)); ++ BUG_ON(p.rfbi_module > 1); ++ ++ dssdev = rfbi.dssdev[p.rfbi_module]; ++ ++ if (p.cmd == RFBI_CMD_UPDATE) { ++ if (do_update(dssdev, &p.par.r)) ++ break; /* async op */ ++ } else if (p.cmd == RFBI_CMD_SYNC) { ++ DSSDBG("Signaling SYNC done!\n"); ++ complete(p.par.sync); ++ } else ++ BUG(); ++ } ++ ++ signal_fifo_waiters(); ++} ++ ++static void rfbi_push_cmd(struct update_param *p) ++{ ++ int ret; ++ ++ while (1) { ++ unsigned long flags; ++ int available; ++ ++ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags); ++ available = RFBI_CMD_FIFO_LEN_BYTES - ++ __kfifo_len(rfbi.cmd_fifo); ++ ++/* DSSDBG("%d bytes left in fifo\n", available); */ ++ if (available < sizeof(struct update_param)) { ++ DSSDBG("Going to wait because FIFO FULL..\n"); ++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); ++ atomic_inc(&rfbi.cmd_fifo_full); ++ wait_for_completion(&rfbi.cmd_done); ++ /*DSSDBG("Woke up because fifo not full anymore\n");*/ ++ continue; ++ } ++ ++ ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p, ++ sizeof(struct update_param)); ++/* DSSDBG("pushed %d bytes\n", ret);*/ ++ ++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); ++ ++ BUG_ON(ret != sizeof(struct update_param)); ++ ++ break; ++ } ++} ++ ++static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h) ++{ ++ struct update_param p; ++ ++ p.rfbi_module = rfbi_module; ++ p.cmd = RFBI_CMD_UPDATE; ++ ++ p.par.r.x = x; ++ p.par.r.y = y; ++ p.par.r.w = w; ++ p.par.r.h = h; ++ ++ DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h); ++ ++ rfbi_push_cmd(&p); ++ ++ process_cmd_fifo(); ++} ++ ++static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp) ++{ ++ struct update_param p; ++ ++ p.rfbi_module = rfbi_module; ++ p.cmd = RFBI_CMD_SYNC; ++ p.par.sync = sync_comp; ++ ++ rfbi_push_cmd(&p); ++ ++ DSSDBG("RFBI sync pushed to cmd fifo\n"); ++ ++ process_cmd_fifo(); ++} ++ ++void rfbi_dump_regs(struct seq_file *s) ++{ ++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ DUMPREG(RFBI_REVISION); ++ DUMPREG(RFBI_SYSCONFIG); ++ DUMPREG(RFBI_SYSSTATUS); ++ DUMPREG(RFBI_CONTROL); ++ DUMPREG(RFBI_PIXEL_CNT); ++ DUMPREG(RFBI_LINE_NUMBER); ++ DUMPREG(RFBI_CMD); ++ DUMPREG(RFBI_PARAM); ++ DUMPREG(RFBI_DATA); ++ DUMPREG(RFBI_READ); ++ DUMPREG(RFBI_STATUS); ++ ++ DUMPREG(RFBI_CONFIG(0)); ++ DUMPREG(RFBI_ONOFF_TIME(0)); ++ DUMPREG(RFBI_CYCLE_TIME(0)); ++ DUMPREG(RFBI_DATA_CYCLE1(0)); ++ DUMPREG(RFBI_DATA_CYCLE2(0)); ++ DUMPREG(RFBI_DATA_CYCLE3(0)); ++ ++ DUMPREG(RFBI_CONFIG(1)); ++ DUMPREG(RFBI_ONOFF_TIME(1)); ++ DUMPREG(RFBI_CYCLE_TIME(1)); ++ DUMPREG(RFBI_DATA_CYCLE1(1)); ++ DUMPREG(RFBI_DATA_CYCLE2(1)); ++ DUMPREG(RFBI_DATA_CYCLE3(1)); ++ ++ DUMPREG(RFBI_VSYNC_WIDTH); ++ DUMPREG(RFBI_HSYNC_WIDTH); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++#undef DUMPREG ++} ++ ++int rfbi_init(void) ++{ ++ u32 rev; ++ u32 l; ++ ++ spin_lock_init(&rfbi.cmd_lock); ++ rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL, ++ &rfbi.cmd_lock); ++ if (IS_ERR(rfbi.cmd_fifo)) ++ return -ENOMEM; ++ ++ init_completion(&rfbi.cmd_done); ++ atomic_set(&rfbi.cmd_fifo_full, 0); ++ atomic_set(&rfbi.cmd_pending, 0); ++ ++ rfbi.base = ioremap(RFBI_BASE, SZ_256); ++ if (!rfbi.base) { ++ DSSERR("can't ioremap RFBI\n"); ++ return -ENOMEM; ++ } ++ ++ rfbi_enable_clocks(1); ++ ++ msleep(10); ++ ++ rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; ++ ++ /* Enable autoidle and smart-idle */ ++ l = rfbi_read_reg(RFBI_SYSCONFIG); ++ l |= (1 << 0) | (2 << 3); ++ rfbi_write_reg(RFBI_SYSCONFIG, l); ++ ++ rev = rfbi_read_reg(RFBI_REVISION); ++ printk(KERN_INFO "OMAP RFBI rev %d.%d\n", ++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); ++ ++ rfbi_enable_clocks(0); ++ ++ return 0; ++} ++ ++void rfbi_exit(void) ++{ ++ DSSDBG("rfbi_exit\n"); ++ ++ kfifo_free(rfbi.cmd_fifo); ++ ++ iounmap(rfbi.base); ++} ++ ++/* struct omap_display support */ ++static int rfbi_display_update(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ int rfbi_module; ++ ++ if (w == 0 || h == 0) ++ return 0; ++ ++ rfbi_module = rfbi_find_display(dssdev); ++ ++ rfbi_push_update(rfbi_module, x, y, w, h); ++ ++ return 0; ++} ++ ++static int rfbi_display_sync(struct omap_dss_device *dssdev) ++{ ++ struct completion sync_comp; ++ int rfbi_module; ++ ++ rfbi_module = rfbi_find_display(dssdev); ++ ++ init_completion(&sync_comp); ++ rfbi_push_sync(rfbi_module, &sync_comp); ++ DSSDBG("Waiting for SYNC to happen...\n"); ++ wait_for_completion(&sync_comp); ++ DSSDBG("Released from SYNC\n"); ++ return 0; ++} ++ ++static int rfbi_display_enable_te(struct omap_dss_device *dssdev, bool enable) ++{ ++ dssdev->driver->enable_te(dssdev, enable); ++ return 0; ++} ++ ++static int rfbi_display_enable(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ r = omap_dss_start_device(dssdev); ++ if (r) { ++ DSSERR("failed to start device\n"); ++ goto err0; ++ } ++ ++ r = omap_dispc_register_isr(framedone_callback, NULL, ++ DISPC_IRQ_FRAMEDONE); ++ if (r) { ++ DSSERR("can't get FRAMEDONE irq\n"); ++ goto err1; ++ } ++ ++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); ++ ++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI); ++ ++ dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); ++ ++ rfbi_configure(dssdev->phy.rfbi.channel, ++ dssdev->ctrl.pixel_size, ++ dssdev->phy.rfbi.data_lines); ++ ++ rfbi_set_timings(dssdev->phy.rfbi.channel, ++ &dssdev->ctrl.rfbi_timings); ++ ++ ++ if (dssdev->driver->enable) { ++ r = dssdev->driver->enable(dssdev); ++ if (r) ++ goto err2; ++ } ++ ++ return 0; ++err2: ++ omap_dispc_unregister_isr(framedone_callback, NULL, ++ DISPC_IRQ_FRAMEDONE); ++err1: ++ omap_dss_stop_device(dssdev); ++err0: ++ return r; ++} ++ ++static void rfbi_display_disable(struct omap_dss_device *dssdev) ++{ ++ dssdev->driver->disable(dssdev); ++ omap_dispc_unregister_isr(framedone_callback, NULL, ++ DISPC_IRQ_FRAMEDONE); ++ omap_dss_stop_device(dssdev); ++} ++ ++int rfbi_init_display(struct omap_dss_device *dssdev) ++{ ++ dssdev->enable = rfbi_display_enable; ++ dssdev->disable = rfbi_display_disable; ++ dssdev->update = rfbi_display_update; ++ dssdev->sync = rfbi_display_sync; ++ dssdev->enable_te = rfbi_display_enable_te; ++ ++ rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; ++ ++ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; ++ ++ return 0; ++} +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0013-OMAP-DSS2-SDI-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0013-OMAP-DSS2-SDI-driver.patch new file mode 100644 index 0000000000..698d4fb893 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0013-OMAP-DSS2-SDI-driver.patch @@ -0,0 +1,284 @@ +From 6191570efd848a073fcdfb619ba28cc0d66b2842 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Wed, 5 Aug 2009 16:18:44 +0300 +Subject: [PATCH 13/18] OMAP: DSS2: SDI driver + +SDI (Serial Display Interface) implements TI Flatlink 3G display +interface. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + drivers/video/omap2/dss/sdi.c | 261 +++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 261 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/dss/sdi.c + +diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c +new file mode 100644 +index 0000000..a9c727e +--- /dev/null ++++ b/drivers/video/omap2/dss/sdi.c +@@ -0,0 +1,261 @@ ++/* ++ * linux/drivers/video/omap2/dss/sdi.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "SDI" ++ ++#include <linux/kernel.h> ++#include <linux/clk.h> ++#include <linux/delay.h> ++#include <linux/err.h> ++ ++#include <mach/board.h> ++#include <mach/display.h> ++#include "dss.h" ++ ++static struct { ++ bool skip_init; ++ bool update_enabled; ++} sdi; ++ ++static void sdi_basic_init(void) ++{ ++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); ++ ++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); ++ dispc_set_tft_data_lines(24); ++ dispc_lcd_enable_signal_polarity(1); ++} ++ ++static int sdi_display_enable(struct omap_dss_device *dssdev) ++{ ++ struct omap_video_timings *t = &dssdev->panel.timings; ++ struct dispc_clock_info cinfo; ++ u16 lck_div, pck_div; ++ unsigned long fck; ++ unsigned long pck; ++ int r; ++ ++ r = omap_dss_start_device(dssdev); ++ if (r) { ++ DSSERR("failed to start device\n"); ++ goto err0; ++ } ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { ++ DSSERR("dssdev already enabled\n"); ++ r = -EINVAL; ++ goto err1; ++ } ++ ++ /* In case of skip_init sdi_init has already enabled the clocks */ ++ if (!sdi.skip_init) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ sdi_basic_init(); ++ ++ /* 15.5.9.1.2 */ ++ dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; ++ ++ dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, ++ dssdev->panel.acb); ++ ++ if (!sdi.skip_init) ++ r = dispc_calc_clock_div(1, t->pixel_clock * 1000, ++ &cinfo); ++ else ++ r = dispc_get_clock_div(&cinfo); ++ ++ if (r) ++ goto err2; ++ ++ fck = cinfo.fck; ++ lck_div = cinfo.lck_div; ++ pck_div = cinfo.pck_div; ++ ++ pck = fck / lck_div / pck_div / 1000; ++ ++ if (pck != t->pixel_clock) { ++ DSSWARN("Could not find exact pixel clock. Requested %d kHz, " ++ "got %lu kHz\n", ++ t->pixel_clock, pck); ++ ++ t->pixel_clock = pck; ++ } ++ ++ ++ dispc_set_lcd_timings(t); ++ ++ r = dispc_set_clock_div(&cinfo); ++ if (r) ++ goto err2; ++ ++ if (!sdi.skip_init) { ++ dss_sdi_init(dssdev->phy.sdi.datapairs); ++ dss_sdi_enable(); ++ mdelay(2); ++ } ++ ++ dispc_enable_lcd_out(1); ++ ++ if (dssdev->driver->enable) { ++ r = dssdev->driver->enable(dssdev); ++ if (r) ++ goto err3; ++ } ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ sdi.skip_init = 0; ++ ++ return 0; ++err3: ++ dispc_enable_lcd_out(0); ++err2: ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++err1: ++ omap_dss_stop_device(dssdev); ++err0: ++ return r; ++} ++ ++static int sdi_display_resume(struct omap_dss_device *dssdev); ++ ++static void sdi_display_disable(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) ++ return; ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) ++ sdi_display_resume(dssdev); ++ ++ if (dssdev->driver->disable) ++ dssdev->driver->disable(dssdev); ++ ++ dispc_enable_lcd_out(0); ++ ++ dss_sdi_disable(); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++ ++ omap_dss_stop_device(dssdev); ++} ++ ++static int sdi_display_suspend(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ return -EINVAL; ++ ++ if (dssdev->driver->suspend) ++ dssdev->driver->suspend(dssdev); ++ ++ dispc_enable_lcd_out(0); ++ ++ dss_sdi_disable(); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; ++ ++ return 0; ++} ++ ++static int sdi_display_resume(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) ++ return -EINVAL; ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dss_sdi_enable(); ++ mdelay(2); ++ ++ dispc_enable_lcd_out(1); ++ ++ if (dssdev->driver->resume) ++ dssdev->driver->resume(dssdev); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ return 0; ++} ++ ++static int sdi_display_set_update_mode(struct omap_dss_device *dssdev, ++ enum omap_dss_update_mode mode) ++{ ++ if (mode == OMAP_DSS_UPDATE_MANUAL) ++ return -EINVAL; ++ ++ if (mode == OMAP_DSS_UPDATE_DISABLED) { ++ dispc_enable_lcd_out(0); ++ sdi.update_enabled = 0; ++ } else { ++ dispc_enable_lcd_out(1); ++ sdi.update_enabled = 1; ++ } ++ ++ return 0; ++} ++ ++static enum omap_dss_update_mode sdi_display_get_update_mode( ++ struct omap_dss_device *dssdev) ++{ ++ return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO : ++ OMAP_DSS_UPDATE_DISABLED; ++} ++ ++static void sdi_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ *timings = dssdev->panel.timings; ++} ++ ++int sdi_init_display(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("SDI init\n"); ++ ++ dssdev->enable = sdi_display_enable; ++ dssdev->disable = sdi_display_disable; ++ dssdev->suspend = sdi_display_suspend; ++ dssdev->resume = sdi_display_resume; ++ dssdev->set_update_mode = sdi_display_set_update_mode; ++ dssdev->get_update_mode = sdi_display_get_update_mode; ++ dssdev->get_timings = sdi_get_timings; ++ ++ return 0; ++} ++ ++int sdi_init(bool skip_init) ++{ ++ /* we store this for first display enable, then clear it */ ++ sdi.skip_init = skip_init; ++ ++ /* ++ * Enable clocks already here, otherwise there would be a toggle ++ * of them until sdi_display_enable is called. ++ */ ++ if (skip_init) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ return 0; ++} ++ ++void sdi_exit(void) ++{ ++} +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0014-OMAP-DSS2-DSI-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0014-OMAP-DSS2-DSI-driver.patch new file mode 100644 index 0000000000..51020416fe --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0014-OMAP-DSS2-DSI-driver.patch @@ -0,0 +1,3531 @@ +From 1452422be43114972e71ac2bbb9e1055f4616602 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Wed, 5 Aug 2009 16:18:57 +0300 +Subject: [PATCH 14/18] OMAP: DSS2: DSI driver + +DSI (Display Serial Interface) driver implements MIPI DSI interface. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + drivers/video/omap2/dss/dsi.c | 3509 +++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 3509 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/dss/dsi.c + +diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c +new file mode 100644 +index 0000000..d43b9ce +--- /dev/null ++++ b/drivers/video/omap2/dss/dsi.c +@@ -0,0 +1,3509 @@ ++/* ++ * linux/drivers/video/omap2/dss/dsi.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "DSI" ++ ++#include <linux/kernel.h> ++#include <linux/io.h> ++#include <linux/clk.h> ++#include <linux/device.h> ++#include <linux/err.h> ++#include <linux/interrupt.h> ++#include <linux/delay.h> ++#include <linux/mutex.h> ++#include <linux/seq_file.h> ++#include <linux/platform_device.h> ++#include <linux/regulator/consumer.h> ++#include <linux/kthread.h> ++#include <linux/wait.h> ++ ++#include <mach/board.h> ++#include <mach/display.h> ++#include <mach/clock.h> ++ ++#include "dss.h" ++ ++/*#define VERBOSE_IRQ*/ ++ ++#define DSI_BASE 0x4804FC00 ++ ++struct dsi_reg { u16 idx; }; ++ ++#define DSI_REG(idx) ((const struct dsi_reg) { idx }) ++ ++#define DSI_SZ_REGS SZ_1K ++/* DSI Protocol Engine */ ++ ++#define DSI_REVISION DSI_REG(0x0000) ++#define DSI_SYSCONFIG DSI_REG(0x0010) ++#define DSI_SYSSTATUS DSI_REG(0x0014) ++#define DSI_IRQSTATUS DSI_REG(0x0018) ++#define DSI_IRQENABLE DSI_REG(0x001C) ++#define DSI_CTRL DSI_REG(0x0040) ++#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) ++#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) ++#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) ++#define DSI_CLK_CTRL DSI_REG(0x0054) ++#define DSI_TIMING1 DSI_REG(0x0058) ++#define DSI_TIMING2 DSI_REG(0x005C) ++#define DSI_VM_TIMING1 DSI_REG(0x0060) ++#define DSI_VM_TIMING2 DSI_REG(0x0064) ++#define DSI_VM_TIMING3 DSI_REG(0x0068) ++#define DSI_CLK_TIMING DSI_REG(0x006C) ++#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070) ++#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074) ++#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078) ++#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C) ++#define DSI_VM_TIMING4 DSI_REG(0x0080) ++#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084) ++#define DSI_VM_TIMING5 DSI_REG(0x0088) ++#define DSI_VM_TIMING6 DSI_REG(0x008C) ++#define DSI_VM_TIMING7 DSI_REG(0x0090) ++#define DSI_STOPCLK_TIMING DSI_REG(0x0094) ++#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20)) ++#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20)) ++#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20)) ++#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20)) ++#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20)) ++#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20)) ++#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20)) ++ ++/* DSIPHY_SCP */ ++ ++#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000) ++#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004) ++#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008) ++#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014) ++ ++/* DSI_PLL_CTRL_SCP */ ++ ++#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000) ++#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004) ++#define DSI_PLL_GO DSI_REG(0x300 + 0x0008) ++#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C) ++#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010) ++ ++#define REG_GET(idx, start, end) \ ++ FLD_GET(dsi_read_reg(idx), start, end) ++ ++#define REG_FLD_MOD(idx, val, start, end) \ ++ dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end)) ++ ++/* Global interrupts */ ++#define DSI_IRQ_VC0 (1 << 0) ++#define DSI_IRQ_VC1 (1 << 1) ++#define DSI_IRQ_VC2 (1 << 2) ++#define DSI_IRQ_VC3 (1 << 3) ++#define DSI_IRQ_WAKEUP (1 << 4) ++#define DSI_IRQ_RESYNC (1 << 5) ++#define DSI_IRQ_PLL_LOCK (1 << 7) ++#define DSI_IRQ_PLL_UNLOCK (1 << 8) ++#define DSI_IRQ_PLL_RECALL (1 << 9) ++#define DSI_IRQ_COMPLEXIO_ERR (1 << 10) ++#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14) ++#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15) ++#define DSI_IRQ_TE_TRIGGER (1 << 16) ++#define DSI_IRQ_ACK_TRIGGER (1 << 17) ++#define DSI_IRQ_SYNC_LOST (1 << 18) ++#define DSI_IRQ_LDO_POWER_GOOD (1 << 19) ++#define DSI_IRQ_TA_TIMEOUT (1 << 20) ++#define DSI_IRQ_ERROR_MASK \ ++ (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ ++ DSI_IRQ_TA_TIMEOUT) ++#define DSI_IRQ_CHANNEL_MASK 0xf ++ ++/* Virtual channel interrupts */ ++#define DSI_VC_IRQ_CS (1 << 0) ++#define DSI_VC_IRQ_ECC_CORR (1 << 1) ++#define DSI_VC_IRQ_PACKET_SENT (1 << 2) ++#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3) ++#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4) ++#define DSI_VC_IRQ_BTA (1 << 5) ++#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6) ++#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7) ++#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8) ++#define DSI_VC_IRQ_ERROR_MASK \ ++ (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \ ++ DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \ ++ DSI_VC_IRQ_FIFO_TX_UDF) ++ ++/* ComplexIO interrupts */ ++#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0) ++#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1) ++#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2) ++#define DSI_CIO_IRQ_ERRESC1 (1 << 5) ++#define DSI_CIO_IRQ_ERRESC2 (1 << 6) ++#define DSI_CIO_IRQ_ERRESC3 (1 << 7) ++#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10) ++#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11) ++#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12) ++#define DSI_CIO_IRQ_STATEULPS1 (1 << 15) ++#define DSI_CIO_IRQ_STATEULPS2 (1 << 16) ++#define DSI_CIO_IRQ_STATEULPS3 (1 << 17) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) ++#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) ++#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) ++ ++#define DSI_DT_DCS_SHORT_WRITE_0 0x05 ++#define DSI_DT_DCS_SHORT_WRITE_1 0x15 ++#define DSI_DT_DCS_READ 0x06 ++#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37 ++#define DSI_DT_NULL_PACKET 0x09 ++#define DSI_DT_DCS_LONG_WRITE 0x39 ++ ++#define DSI_DT_RX_ACK_WITH_ERR 0x02 ++#define DSI_DT_RX_DCS_LONG_READ 0x1c ++#define DSI_DT_RX_SHORT_READ_1 0x21 ++#define DSI_DT_RX_SHORT_READ_2 0x22 ++ ++#define FINT_MAX 2100000 ++#define FINT_MIN 750000 ++#define REGN_MAX (1 << 7) ++#define REGM_MAX ((1 << 11) - 1) ++#define REGM3_MAX (1 << 4) ++#define REGM4_MAX (1 << 4) ++ ++enum fifo_size { ++ DSI_FIFO_SIZE_0 = 0, ++ DSI_FIFO_SIZE_32 = 1, ++ DSI_FIFO_SIZE_64 = 2, ++ DSI_FIFO_SIZE_96 = 3, ++ DSI_FIFO_SIZE_128 = 4, ++}; ++ ++enum dsi_vc_mode { ++ DSI_VC_MODE_L4 = 0, ++ DSI_VC_MODE_VP, ++}; ++ ++struct dsi_update_region { ++ bool dirty; ++ u16 x, y, w, h; ++ struct omap_dss_device *device; ++}; ++ ++static struct ++{ ++ void __iomem *base; ++ ++ unsigned long dsi1_pll_fclk; /* Hz */ ++ unsigned long dsi2_pll_fclk; /* Hz */ ++ unsigned long dsiphy; /* Hz */ ++ unsigned long ddr_clk; /* Hz */ ++ ++ struct regulator *vdds_dsi_reg; ++ ++ struct { ++ enum dsi_vc_mode mode; ++ struct omap_dss_device *dssdev; ++ enum fifo_size fifo_size; ++ int dest_per; /* destination peripheral 0-3 */ ++ } vc[4]; ++ ++ struct mutex lock; ++ struct mutex bus_lock; ++ ++ unsigned pll_locked; ++ ++ struct completion bta_completion; ++ ++ struct task_struct *thread; ++ wait_queue_head_t waitqueue; ++ ++ spinlock_t update_lock; ++ bool framedone_received; ++ struct dsi_update_region update_region; ++ struct dsi_update_region active_update_region; ++ struct completion update_completion; ++ ++ enum omap_dss_update_mode user_update_mode; ++ enum omap_dss_update_mode update_mode; ++ bool te_enabled; ++ bool use_ext_te; ++ ++ unsigned long cache_req_pck; ++ unsigned long cache_clk_freq; ++ struct dsi_clock_info cache_cinfo; ++ ++ u32 errors; ++ spinlock_t errors_lock; ++#ifdef DEBUG ++ ktime_t perf_setup_time; ++ ktime_t perf_start_time; ++ ktime_t perf_start_time_auto; ++ int perf_measure_frames; ++#endif ++ int debug_read; ++ int debug_write; ++} dsi; ++ ++#ifdef DEBUG ++static unsigned int dsi_perf; ++module_param_named(dsi_perf, dsi_perf, bool, 0644); ++#endif ++ ++static inline void dsi_write_reg(const struct dsi_reg idx, u32 val) ++{ ++ __raw_writel(val, dsi.base + idx.idx); ++} ++ ++static inline u32 dsi_read_reg(const struct dsi_reg idx) ++{ ++ return __raw_readl(dsi.base + idx.idx); ++} ++ ++ ++void dsi_save_context(void) ++{ ++} ++ ++void dsi_restore_context(void) ++{ ++} ++ ++void dsi_bus_lock(void) ++{ ++ mutex_lock(&dsi.bus_lock); ++} ++EXPORT_SYMBOL(dsi_bus_lock); ++ ++void dsi_bus_unlock(void) ++{ ++ mutex_unlock(&dsi.bus_lock); ++} ++EXPORT_SYMBOL(dsi_bus_unlock); ++ ++static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, ++ int value) ++{ ++ int t = 100000; ++ ++ while (REG_GET(idx, bitnum, bitnum) != value) { ++ if (--t == 0) ++ return !value; ++ } ++ ++ return value; ++} ++ ++#ifdef DEBUG ++static void dsi_perf_mark_setup(void) ++{ ++ dsi.perf_setup_time = ktime_get(); ++} ++ ++static void dsi_perf_mark_start(void) ++{ ++ dsi.perf_start_time = ktime_get(); ++} ++ ++static void dsi_perf_mark_start_auto(void) ++{ ++ dsi.perf_measure_frames = 0; ++ dsi.perf_start_time_auto = ktime_get(); ++} ++ ++static void dsi_perf_show(const char *name) ++{ ++ ktime_t t, setup_time, trans_time; ++ u32 total_bytes; ++ u32 setup_us, trans_us, total_us; ++ ++ if (!dsi_perf) ++ return; ++ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED) ++ return; ++ ++ t = ktime_get(); ++ ++ setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time); ++ setup_us = (u32)ktime_to_us(setup_time); ++ if (setup_us == 0) ++ setup_us = 1; ++ ++ trans_time = ktime_sub(t, dsi.perf_start_time); ++ trans_us = (u32)ktime_to_us(trans_time); ++ if (trans_us == 0) ++ trans_us = 1; ++ ++ total_us = setup_us + trans_us; ++ ++ total_bytes = dsi.active_update_region.w * ++ dsi.active_update_region.h * ++ dsi.active_update_region.device->ctrl.pixel_size / 8; ++ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) { ++ static u32 s_total_trans_us, s_total_setup_us; ++ static u32 s_min_trans_us = 0xffffffff, s_min_setup_us; ++ static u32 s_max_trans_us, s_max_setup_us; ++ const int numframes = 100; ++ ktime_t total_time_auto; ++ u32 total_time_auto_us; ++ ++ dsi.perf_measure_frames++; ++ ++ if (setup_us < s_min_setup_us) ++ s_min_setup_us = setup_us; ++ ++ if (setup_us > s_max_setup_us) ++ s_max_setup_us = setup_us; ++ ++ s_total_setup_us += setup_us; ++ ++ if (trans_us < s_min_trans_us) ++ s_min_trans_us = trans_us; ++ ++ if (trans_us > s_max_trans_us) ++ s_max_trans_us = trans_us; ++ ++ s_total_trans_us += trans_us; ++ ++ if (dsi.perf_measure_frames < numframes) ++ return; ++ ++ total_time_auto = ktime_sub(t, dsi.perf_start_time_auto); ++ total_time_auto_us = (u32)ktime_to_us(total_time_auto); ++ ++ printk(KERN_INFO "DSI(%s): %u fps, setup %u/%u/%u, " ++ "trans %u/%u/%u\n", ++ name, ++ 1000 * 1000 * numframes / total_time_auto_us, ++ s_min_setup_us, ++ s_max_setup_us, ++ s_total_setup_us / numframes, ++ s_min_trans_us, ++ s_max_trans_us, ++ s_total_trans_us / numframes); ++ ++ s_total_setup_us = 0; ++ s_min_setup_us = 0xffffffff; ++ s_max_setup_us = 0; ++ s_total_trans_us = 0; ++ s_min_trans_us = 0xffffffff; ++ s_max_trans_us = 0; ++ dsi_perf_mark_start_auto(); ++ } else { ++ printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " ++ "%u bytes, %u kbytes/sec\n", ++ name, ++ setup_us, ++ trans_us, ++ total_us, ++ 1000*1000 / total_us, ++ total_bytes, ++ total_bytes * 1000 / total_us); ++ } ++} ++#else ++#define dsi_perf_mark_setup() ++#define dsi_perf_mark_start() ++#define dsi_perf_mark_start_auto() ++#define dsi_perf_show(x) ++#endif ++ ++static void print_irq_status(u32 status) ++{ ++#ifndef VERBOSE_IRQ ++ if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) ++ return; ++#endif ++ printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status); ++ ++#define PIS(x) \ ++ if (status & DSI_IRQ_##x) \ ++ printk(#x " "); ++#ifdef VERBOSE_IRQ ++ PIS(VC0); ++ PIS(VC1); ++ PIS(VC2); ++ PIS(VC3); ++#endif ++ PIS(WAKEUP); ++ PIS(RESYNC); ++ PIS(PLL_LOCK); ++ PIS(PLL_UNLOCK); ++ PIS(PLL_RECALL); ++ PIS(COMPLEXIO_ERR); ++ PIS(HS_TX_TIMEOUT); ++ PIS(LP_RX_TIMEOUT); ++ PIS(TE_TRIGGER); ++ PIS(ACK_TRIGGER); ++ PIS(SYNC_LOST); ++ PIS(LDO_POWER_GOOD); ++ PIS(TA_TIMEOUT); ++#undef PIS ++ ++ printk("\n"); ++} ++ ++static void print_irq_status_vc(int channel, u32 status) ++{ ++#ifndef VERBOSE_IRQ ++ if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) ++ return; ++#endif ++ printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status); ++ ++#define PIS(x) \ ++ if (status & DSI_VC_IRQ_##x) \ ++ printk(#x " "); ++ PIS(CS); ++ PIS(ECC_CORR); ++#ifdef VERBOSE_IRQ ++ PIS(PACKET_SENT); ++#endif ++ PIS(FIFO_TX_OVF); ++ PIS(FIFO_RX_OVF); ++ PIS(BTA); ++ PIS(ECC_NO_CORR); ++ PIS(FIFO_TX_UDF); ++ PIS(PP_BUSY_CHANGE); ++#undef PIS ++ printk("\n"); ++} ++ ++static void print_irq_status_cio(u32 status) ++{ ++ printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); ++ ++#define PIS(x) \ ++ if (status & DSI_CIO_IRQ_##x) \ ++ printk(#x " "); ++ PIS(ERRSYNCESC1); ++ PIS(ERRSYNCESC2); ++ PIS(ERRSYNCESC3); ++ PIS(ERRESC1); ++ PIS(ERRESC2); ++ PIS(ERRESC3); ++ PIS(ERRCONTROL1); ++ PIS(ERRCONTROL2); ++ PIS(ERRCONTROL3); ++ PIS(STATEULPS1); ++ PIS(STATEULPS2); ++ PIS(STATEULPS3); ++ PIS(ERRCONTENTIONLP0_1); ++ PIS(ERRCONTENTIONLP1_1); ++ PIS(ERRCONTENTIONLP0_2); ++ PIS(ERRCONTENTIONLP1_2); ++ PIS(ERRCONTENTIONLP0_3); ++ PIS(ERRCONTENTIONLP1_3); ++ PIS(ULPSACTIVENOT_ALL0); ++ PIS(ULPSACTIVENOT_ALL1); ++#undef PIS ++ ++ printk("\n"); ++} ++ ++static int debug_irq; ++ ++/* called from dss */ ++void dsi_irq_handler(void) ++{ ++ u32 irqstatus, vcstatus, ciostatus; ++ int i; ++ ++ irqstatus = dsi_read_reg(DSI_IRQSTATUS); ++ ++ if (irqstatus & DSI_IRQ_ERROR_MASK) { ++ DSSERR("DSI error, irqstatus %x\n", irqstatus); ++ print_irq_status(irqstatus); ++ spin_lock(&dsi.errors_lock); ++ dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK; ++ spin_unlock(&dsi.errors_lock); ++ } else if (debug_irq) { ++ print_irq_status(irqstatus); ++ } ++ ++ for (i = 0; i < 4; ++i) { ++ if ((irqstatus & (1<<i)) == 0) ++ continue; ++ ++ vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i)); ++ ++ if (vcstatus & DSI_VC_IRQ_BTA) ++ complete(&dsi.bta_completion); ++ ++ if (vcstatus & DSI_VC_IRQ_ERROR_MASK) { ++ DSSERR("DSI VC(%d) error, vc irqstatus %x\n", ++ i, vcstatus); ++ print_irq_status_vc(i, vcstatus); ++ } else if (debug_irq) { ++ print_irq_status_vc(i, vcstatus); ++ } ++ ++ dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus); ++ } ++ ++ if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { ++ ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); ++ ++ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); ++ ++ DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); ++ print_irq_status_cio(ciostatus); ++ } ++ ++ dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); ++} ++ ++ ++static void _dsi_initialize_irq(void) ++{ ++ u32 l; ++ int i; ++ ++ /* disable all interrupts */ ++ dsi_write_reg(DSI_IRQENABLE, 0); ++ for (i = 0; i < 4; ++i) ++ dsi_write_reg(DSI_VC_IRQENABLE(i), 0); ++ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0); ++ ++ /* clear interrupt status */ ++ l = dsi_read_reg(DSI_IRQSTATUS); ++ dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK); ++ ++ for (i = 0; i < 4; ++i) { ++ l = dsi_read_reg(DSI_VC_IRQSTATUS(i)); ++ dsi_write_reg(DSI_VC_IRQSTATUS(i), l); ++ } ++ ++ l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); ++ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l); ++ ++ /* enable error irqs */ ++ l = DSI_IRQ_ERROR_MASK; ++ dsi_write_reg(DSI_IRQENABLE, l); ++ ++ l = DSI_VC_IRQ_ERROR_MASK; ++ for (i = 0; i < 4; ++i) ++ dsi_write_reg(DSI_VC_IRQENABLE(i), l); ++ ++ /* XXX zonda responds incorrectly, causing control error: ++ Exit from LP-ESC mode to LP11 uses wrong transition states on the ++ data lines LP0 and LN0. */ ++ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, ++ -1 & (~DSI_CIO_IRQ_ERRCONTROL2)); ++} ++ ++static u32 dsi_get_errors(void) ++{ ++ unsigned long flags; ++ u32 e; ++ spin_lock_irqsave(&dsi.errors_lock, flags); ++ e = dsi.errors; ++ dsi.errors = 0; ++ spin_unlock_irqrestore(&dsi.errors_lock, flags); ++ return e; ++} ++ ++static void dsi_vc_enable_bta_irq(int channel) ++{ ++ u32 l; ++ ++ dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA); ++ ++ l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); ++ l |= DSI_VC_IRQ_BTA; ++ dsi_write_reg(DSI_VC_IRQENABLE(channel), l); ++} ++ ++static void dsi_vc_disable_bta_irq(int channel) ++{ ++ u32 l; ++ ++ l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); ++ l &= ~DSI_VC_IRQ_BTA; ++ dsi_write_reg(DSI_VC_IRQENABLE(channel), l); ++} ++ ++/* DSI func clock. this could also be DSI2_PLL_FCLK */ ++static inline void enable_clocks(bool enable) ++{ ++ if (enable) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ else ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++} ++ ++/* source clock for DSI PLL. this could also be PCLKFREE */ ++static inline void dsi_enable_pll_clock(bool enable) ++{ ++ if (enable) ++ dss_clk_enable(DSS_CLK_FCK2); ++ else ++ dss_clk_disable(DSS_CLK_FCK2); ++ ++ if (enable && dsi.pll_locked) { ++ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) ++ DSSERR("cannot lock PLL when enabling clocks\n"); ++ } ++} ++ ++#ifdef DEBUG ++static void _dsi_print_reset_status(void) ++{ ++ u32 l; ++ ++ if (!dss_debug) ++ return; ++ ++ /* A dummy read using the SCP interface to any DSIPHY register is ++ * required after DSIPHY reset to complete the reset of the DSI complex ++ * I/O. */ ++ l = dsi_read_reg(DSI_DSIPHY_CFG5); ++ ++ printk(KERN_DEBUG "DSI resets: "); ++ ++ l = dsi_read_reg(DSI_PLL_STATUS); ++ printk("PLL (%d) ", FLD_GET(l, 0, 0)); ++ ++ l = dsi_read_reg(DSI_COMPLEXIO_CFG1); ++ printk("CIO (%d) ", FLD_GET(l, 29, 29)); ++ ++ l = dsi_read_reg(DSI_DSIPHY_CFG5); ++ printk("PHY (%x, %d, %d, %d)\n", ++ FLD_GET(l, 28, 26), ++ FLD_GET(l, 29, 29), ++ FLD_GET(l, 30, 30), ++ FLD_GET(l, 31, 31)); ++} ++#else ++#define _dsi_print_reset_status() ++#endif ++ ++static inline int dsi_if_enable(bool enable) ++{ ++ DSSDBG("dsi_if_enable(%d)\n", enable); ++ ++ enable = enable ? 1 : 0; ++ REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */ ++ ++ if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) { ++ DSSERR("Failed to set dsi_if_enable to %d\n", enable); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static unsigned long dsi_fclk_rate(void) ++{ ++ unsigned long r; ++ ++ if (dss_get_dsi_clk_source() == 0) { ++ /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */ ++ r = dss_clk_get_rate(DSS_CLK_FCK1); ++ } else { ++ /* DSI FCLK source is DSI2_PLL_FCLK */ ++ r = dsi.dsi2_pll_fclk; ++ } ++ ++ return r; ++} ++ ++static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) ++{ ++ unsigned n; ++ unsigned long dsi_fclk; ++ unsigned long lp_clk, lp_clk_req; ++ ++ dsi_fclk = dsi_fclk_rate(); ++ ++ lp_clk_req = dssdev->phy.dsi.lp_clk_hz; ++ ++ for (n = 1; n < (1 << 13) - 1; ++n) { ++ lp_clk = dsi_fclk / 2 / n; ++ if (lp_clk <= lp_clk_req) ++ break; ++ } ++ ++ if (n == (1 << 13) - 1) { ++ DSSERR("Failed to find LP_CLK_DIVISOR\n"); ++ return -EINVAL; ++ } ++ ++ DSSDBG("LP_CLK_DIV %u, LP_CLK %lu (req %lu)\n", n, lp_clk, lp_clk_req); ++ ++ REG_FLD_MOD(DSI_CLK_CTRL, n, 12, 0); /* LP_CLK_DIVISOR */ ++ if (dsi_fclk > 30*1000*1000) ++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 21, 21); /* LP_RX_SYNCHRO_ENABLE */ ++ ++ return 0; ++} ++ ++ ++enum dsi_pll_power_state { ++ DSI_PLL_POWER_OFF = 0x0, ++ DSI_PLL_POWER_ON_HSCLK = 0x1, ++ DSI_PLL_POWER_ON_ALL = 0x2, ++ DSI_PLL_POWER_ON_DIV = 0x3, ++}; ++ ++static int dsi_pll_power(enum dsi_pll_power_state state) ++{ ++ int t = 0; ++ ++ REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */ ++ ++ /* PLL_PWR_STATUS */ ++ while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) { ++ udelay(1); ++ if (t++ > 1000) { ++ DSSERR("Failed to set DSI PLL power mode to %d\n", ++ state); ++ return -ENODEV; ++ } ++ } ++ ++ return 0; ++} ++ ++int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck, ++ struct dsi_clock_info *cinfo) ++{ ++ struct dsi_clock_info cur, best; ++ int min_fck_per_pck; ++ int match = 0; ++ unsigned long dss_clk_fck2; ++ ++ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); ++ ++ if (req_pck == dsi.cache_req_pck && ++ dsi.cache_cinfo.clkin == dss_clk_fck2) { ++ DSSDBG("DSI clock info found from cache\n"); ++ *cinfo = dsi.cache_cinfo; ++ return 0; ++ } ++ ++ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; ++ ++ if (min_fck_per_pck && ++ req_pck * min_fck_per_pck > DISPC_MAX_FCK) { ++ DSSERR("Requested pixel clock not possible with the current " ++ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " ++ "the constraint off.\n"); ++ min_fck_per_pck = 0; ++ } ++ ++ DSSDBG("dsi_pll_calc\n"); ++ ++retry: ++ memset(&best, 0, sizeof(best)); ++ ++ memset(&cur, 0, sizeof(cur)); ++ cur.clkin = dss_clk_fck2; ++ cur.use_dss2_fck = 1; ++ cur.highfreq = 0; ++ ++ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ ++ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ ++ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ ++ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { ++ if (cur.highfreq == 0) ++ cur.fint = cur.clkin / cur.regn; ++ else ++ cur.fint = cur.clkin / (2 * cur.regn); ++ ++ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) ++ continue; ++ ++ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ ++ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { ++ unsigned long a, b; ++ ++ a = 2 * cur.regm * (cur.clkin/1000); ++ b = cur.regn * (cur.highfreq + 1); ++ cur.dsiphy = a / b * 1000; ++ ++ if (cur.dsiphy > 1800 * 1000 * 1000) ++ break; ++ ++ /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */ ++ for (cur.regm3 = 1; cur.regm3 < REGM3_MAX; ++ ++cur.regm3) { ++ cur.dsi1_pll_fclk = cur.dsiphy / cur.regm3; ++ ++ /* this will narrow down the search a bit, ++ * but still give pixclocks below what was ++ * requested */ ++ if (cur.dsi1_pll_fclk < req_pck) ++ break; ++ ++ if (cur.dsi1_pll_fclk > DISPC_MAX_FCK) ++ continue; ++ ++ if (min_fck_per_pck && ++ cur.dsi1_pll_fclk < ++ req_pck * min_fck_per_pck) ++ continue; ++ ++ match = 1; ++ ++ find_lck_pck_divs(is_tft, req_pck, ++ cur.dsi1_pll_fclk, ++ &cur.lck_div, ++ &cur.pck_div); ++ ++ cur.lck = cur.dsi1_pll_fclk / cur.lck_div; ++ cur.pck = cur.lck / cur.pck_div; ++ ++ if (abs(cur.pck - req_pck) < ++ abs(best.pck - req_pck)) { ++ best = cur; ++ ++ if (cur.pck == req_pck) ++ goto found; ++ } ++ } ++ } ++ } ++found: ++ if (!match) { ++ if (min_fck_per_pck) { ++ DSSERR("Could not find suitable clock settings.\n" ++ "Turning FCK/PCK constraint off and" ++ "trying again.\n"); ++ min_fck_per_pck = 0; ++ goto retry; ++ } ++ ++ DSSERR("Could not find suitable clock settings.\n"); ++ ++ return -EINVAL; ++ } ++ ++ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */ ++ best.regm4 = best.dsiphy / 48000000; ++ if (best.regm4 > REGM4_MAX) ++ best.regm4 = REGM4_MAX; ++ else if (best.regm4 == 0) ++ best.regm4 = 1; ++ best.dsi2_pll_fclk = best.dsiphy / best.regm4; ++ ++ if (cinfo) ++ *cinfo = best; ++ ++ dsi.cache_req_pck = req_pck; ++ dsi.cache_clk_freq = 0; ++ dsi.cache_cinfo = best; ++ ++ return 0; ++} ++ ++static int dsi_pll_calc_ddrfreq(unsigned long clk_freq, ++ struct dsi_clock_info *cinfo) ++{ ++ struct dsi_clock_info cur, best; ++ const bool use_dss2_fck = 1; ++ unsigned long datafreq; ++ unsigned long dss_clk_fck2; ++ ++ DSSDBG("dsi_pll_calc_ddrfreq\n"); ++ ++ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); ++ ++ if (clk_freq == dsi.cache_clk_freq && ++ dsi.cache_cinfo.clkin == dss_clk_fck2) { ++ DSSDBG("DSI clock info found from cache\n"); ++ *cinfo = dsi.cache_cinfo; ++ return 0; ++ } ++ ++ datafreq = clk_freq * 4; ++ ++ memset(&best, 0, sizeof(best)); ++ ++ memset(&cur, 0, sizeof(cur)); ++ cur.use_dss2_fck = use_dss2_fck; ++ if (use_dss2_fck) { ++ cur.clkin = dss_clk_fck2; ++ cur.highfreq = 0; ++ } else { ++ cur.clkin = dispc_pclk_rate(); ++ if (cur.clkin < 32000000) ++ cur.highfreq = 0; ++ else ++ cur.highfreq = 1; ++ } ++ ++ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ ++ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ ++ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ ++ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { ++ if (cur.highfreq == 0) ++ cur.fint = cur.clkin / cur.regn; ++ else ++ cur.fint = cur.clkin / (2 * cur.regn); ++ ++ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) ++ continue; ++ ++ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ ++ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { ++ unsigned long a, b; ++ ++ a = 2 * cur.regm * (cur.clkin/1000); ++ b = cur.regn * (cur.highfreq + 1); ++ cur.dsiphy = a / b * 1000; ++ ++ if (cur.dsiphy > 1800 * 1000 * 1000) ++ break; ++ ++ if (abs(cur.dsiphy - datafreq) < ++ abs(best.dsiphy - datafreq)) { ++ best = cur; ++ /* DSSDBG("best %ld\n", best.dsiphy); */ ++ } ++ ++ if (cur.dsiphy == datafreq) ++ goto found; ++ } ++ } ++found: ++ /* DSI1_PLL_FCLK (regm3) is not used. Set it to something sane. */ ++ best.regm3 = best.dsiphy / 48000000; ++ if (best.regm3 > REGM3_MAX) ++ best.regm3 = REGM3_MAX; ++ else if (best.regm3 == 0) ++ best.regm3 = 1; ++ best.dsi1_pll_fclk = best.dsiphy / best.regm3; ++ ++ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */ ++ best.regm4 = best.dsiphy / 48000000; ++ if (best.regm4 > REGM4_MAX) ++ best.regm4 = REGM4_MAX; ++ else if (best.regm4 == 0) ++ best.regm4 = 1; ++ best.dsi2_pll_fclk = best.dsiphy / best.regm4; ++ ++ if (cinfo) ++ *cinfo = best; ++ ++ dsi.cache_clk_freq = clk_freq; ++ dsi.cache_req_pck = 0; ++ dsi.cache_cinfo = best; ++ ++ return 0; ++} ++ ++int dsi_pll_program(struct dsi_clock_info *cinfo) ++{ ++ int r = 0; ++ u32 l; ++ ++ DSSDBG("dsi_pll_program\n"); ++ ++ dsi.dsiphy = cinfo->dsiphy; ++ dsi.ddr_clk = dsi.dsiphy / 4; ++ dsi.dsi1_pll_fclk = cinfo->dsi1_pll_fclk; ++ dsi.dsi2_pll_fclk = cinfo->dsi2_pll_fclk; ++ ++ DSSDBG("DSI Fint %ld\n", cinfo->fint); ++ ++ DSSDBG("clkin (%s) rate %ld, highfreq %d\n", ++ cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree", ++ cinfo->clkin, ++ cinfo->highfreq); ++ ++ /* DSIPHY == CLKIN4DDR */ ++ DSSDBG("DSIPHY = 2 * %d / %d * %lu / %d = %lu\n", ++ cinfo->regm, ++ cinfo->regn, ++ cinfo->clkin, ++ cinfo->highfreq + 1, ++ cinfo->dsiphy); ++ ++ DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", ++ dsi.dsiphy / 1000 / 1000 / 2); ++ ++ DSSDBG("Clock lane freq %ld Hz\n", dsi.ddr_clk); ++ ++ DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n", ++ cinfo->regm3, cinfo->dsi1_pll_fclk); ++ DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n", ++ cinfo->regm4, cinfo->dsi2_pll_fclk); ++ ++ REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ ++ ++ l = dsi_read_reg(DSI_PLL_CONFIGURATION1); ++ l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ ++ l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */ ++ l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ ++ l = FLD_MOD(l, cinfo->regm3 - 1, 22, 19); /* DSI_CLOCK_DIV */ ++ l = FLD_MOD(l, cinfo->regm4 - 1, 26, 23); /* DSIPROTO_CLOCK_DIV */ ++ dsi_write_reg(DSI_PLL_CONFIGURATION1, l); ++ ++ l = dsi_read_reg(DSI_PLL_CONFIGURATION2); ++ l = FLD_MOD(l, 7, 4, 1); /* DSI_PLL_FREQSEL */ ++ /* DSI_PLL_CLKSEL */ ++ l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, 11, 11); ++ l = FLD_MOD(l, cinfo->highfreq, 12, 12); /* DSI_PLL_HIGHFREQ */ ++ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ ++ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ ++ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ ++ dsi_write_reg(DSI_PLL_CONFIGURATION2, l); ++ ++ REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ ++ ++ if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) { ++ DSSERR("dsi pll go bit not going down.\n"); ++ r = -EIO; ++ goto err; ++ } ++ ++ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) { ++ DSSERR("cannot lock PLL\n"); ++ r = -EIO; ++ goto err; ++ } ++ ++ dsi.pll_locked = 1; ++ ++ l = dsi_read_reg(DSI_PLL_CONFIGURATION2); ++ l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */ ++ l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */ ++ l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */ ++ l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */ ++ l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */ ++ l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */ ++ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ ++ l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */ ++ l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */ ++ l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */ ++ l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */ ++ l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */ ++ l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */ ++ l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */ ++ dsi_write_reg(DSI_PLL_CONFIGURATION2, l); ++ ++ DSSDBG("PLL config done\n"); ++err: ++ return r; ++} ++ ++int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv) ++{ ++ int r = 0; ++ enum dsi_pll_power_state pwstate; ++ struct dispc_clock_info cinfo; ++ ++ DSSDBG("PLL init\n"); ++ ++ enable_clocks(1); ++ dsi_enable_pll_clock(1); ++ ++ /* XXX this should be calculated depending on the screen size, ++ * required framerate and DSI speed. ++ * For now 48MHz is enough for 864x480@60 with 360Mbps/lane ++ * with two lanes */ ++ r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo); ++ if (r) ++ goto err0; ++ ++ r = dispc_set_clock_div(&cinfo); ++ if (r) { ++ DSSERR("Failed to set basic clocks\n"); ++ goto err0; ++ } ++ ++ r = regulator_enable(dsi.vdds_dsi_reg); ++ if (r) ++ goto err0; ++ ++ /* XXX PLL does not come out of reset without this... */ ++ dispc_pck_free_enable(1); ++ ++ if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) { ++ DSSERR("PLL not coming out of reset.\n"); ++ r = -ENODEV; ++ goto err1; ++ } ++ ++ /* XXX ... but if left on, we get problems when planes do not ++ * fill the whole display. No idea about this */ ++ dispc_pck_free_enable(0); ++ ++ if (enable_hsclk && enable_hsdiv) ++ pwstate = DSI_PLL_POWER_ON_ALL; ++ else if (enable_hsclk) ++ pwstate = DSI_PLL_POWER_ON_HSCLK; ++ else if (enable_hsdiv) ++ pwstate = DSI_PLL_POWER_ON_DIV; ++ else ++ pwstate = DSI_PLL_POWER_OFF; ++ ++ r = dsi_pll_power(pwstate); ++ ++ if (r) ++ goto err1; ++ ++ DSSDBG("PLL init done\n"); ++ ++ return 0; ++err1: ++ regulator_disable(dsi.vdds_dsi_reg); ++err0: ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++ return r; ++} ++ ++void dsi_pll_uninit(void) ++{ ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++ ++ dsi.pll_locked = 0; ++ dsi_pll_power(DSI_PLL_POWER_OFF); ++ regulator_disable(dsi.vdds_dsi_reg); ++ DSSDBG("PLL uninit done\n"); ++} ++ ++unsigned long dsi_get_dsi1_pll_rate(void) ++{ ++ return dsi.dsi1_pll_fclk; ++} ++ ++unsigned long dsi_get_dsi2_pll_rate(void) ++{ ++ return dsi.dsi2_pll_fclk; ++} ++ ++void dsi_dump_clocks(struct seq_file *s) ++{ ++ int clksel; ++ ++ enable_clocks(1); ++ ++ clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11); ++ ++ seq_printf(s, "- dsi -\n"); ++ ++ seq_printf(s, "dsi fclk source = %s\n", ++ dss_get_dsi_clk_source() == 0 ? ++ "dss1_alwon_fclk" : "dsi2_pll_fclk"); ++ ++ seq_printf(s, "dsi pll source = %s\n", ++ clksel == 0 ? ++ "dss2_alwon_fclk" : "pclkfree"); ++ ++ seq_printf(s, "DSIPHY\t\t%lu\nDDR_CLK\t\t%lu\n", ++ dsi.dsiphy, dsi.ddr_clk); ++ ++ seq_printf(s, "dsi1_pll_fck\t%lu (%s)\n" ++ "dsi2_pll_fck\t%lu (%s)\n", ++ dsi.dsi1_pll_fclk, ++ dss_get_dispc_clk_source() == 0 ? "off" : "on", ++ dsi.dsi2_pll_fclk, ++ dss_get_dsi_clk_source() == 0 ? "off" : "on"); ++ ++ enable_clocks(0); ++} ++ ++void dsi_dump_regs(struct seq_file *s) ++{ ++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ DUMPREG(DSI_REVISION); ++ DUMPREG(DSI_SYSCONFIG); ++ DUMPREG(DSI_SYSSTATUS); ++ DUMPREG(DSI_IRQSTATUS); ++ DUMPREG(DSI_IRQENABLE); ++ DUMPREG(DSI_CTRL); ++ DUMPREG(DSI_COMPLEXIO_CFG1); ++ DUMPREG(DSI_COMPLEXIO_IRQ_STATUS); ++ DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE); ++ DUMPREG(DSI_CLK_CTRL); ++ DUMPREG(DSI_TIMING1); ++ DUMPREG(DSI_TIMING2); ++ DUMPREG(DSI_VM_TIMING1); ++ DUMPREG(DSI_VM_TIMING2); ++ DUMPREG(DSI_VM_TIMING3); ++ DUMPREG(DSI_CLK_TIMING); ++ DUMPREG(DSI_TX_FIFO_VC_SIZE); ++ DUMPREG(DSI_RX_FIFO_VC_SIZE); ++ DUMPREG(DSI_COMPLEXIO_CFG2); ++ DUMPREG(DSI_RX_FIFO_VC_FULLNESS); ++ DUMPREG(DSI_VM_TIMING4); ++ DUMPREG(DSI_TX_FIFO_VC_EMPTINESS); ++ DUMPREG(DSI_VM_TIMING5); ++ DUMPREG(DSI_VM_TIMING6); ++ DUMPREG(DSI_VM_TIMING7); ++ DUMPREG(DSI_STOPCLK_TIMING); ++ ++ DUMPREG(DSI_VC_CTRL(0)); ++ DUMPREG(DSI_VC_TE(0)); ++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(0)); ++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0)); ++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0)); ++ DUMPREG(DSI_VC_IRQSTATUS(0)); ++ DUMPREG(DSI_VC_IRQENABLE(0)); ++ ++ DUMPREG(DSI_VC_CTRL(1)); ++ DUMPREG(DSI_VC_TE(1)); ++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(1)); ++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1)); ++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1)); ++ DUMPREG(DSI_VC_IRQSTATUS(1)); ++ DUMPREG(DSI_VC_IRQENABLE(1)); ++ ++ DUMPREG(DSI_VC_CTRL(2)); ++ DUMPREG(DSI_VC_TE(2)); ++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(2)); ++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2)); ++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2)); ++ DUMPREG(DSI_VC_IRQSTATUS(2)); ++ DUMPREG(DSI_VC_IRQENABLE(2)); ++ ++ DUMPREG(DSI_VC_CTRL(3)); ++ DUMPREG(DSI_VC_TE(3)); ++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(3)); ++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3)); ++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3)); ++ DUMPREG(DSI_VC_IRQSTATUS(3)); ++ DUMPREG(DSI_VC_IRQENABLE(3)); ++ ++ DUMPREG(DSI_DSIPHY_CFG0); ++ DUMPREG(DSI_DSIPHY_CFG1); ++ DUMPREG(DSI_DSIPHY_CFG2); ++ DUMPREG(DSI_DSIPHY_CFG5); ++ ++ DUMPREG(DSI_PLL_CONTROL); ++ DUMPREG(DSI_PLL_STATUS); ++ DUMPREG(DSI_PLL_GO); ++ DUMPREG(DSI_PLL_CONFIGURATION1); ++ DUMPREG(DSI_PLL_CONFIGURATION2); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++#undef DUMPREG ++} ++ ++enum dsi_complexio_power_state { ++ DSI_COMPLEXIO_POWER_OFF = 0x0, ++ DSI_COMPLEXIO_POWER_ON = 0x1, ++ DSI_COMPLEXIO_POWER_ULPS = 0x2, ++}; ++ ++static int dsi_complexio_power(enum dsi_complexio_power_state state) ++{ ++ int t = 0; ++ ++ /* PWR_CMD */ ++ REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27); ++ ++ /* PWR_STATUS */ ++ while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) { ++ udelay(1); ++ if (t++ > 1000) { ++ DSSERR("failed to set complexio power state to " ++ "%d\n", state); ++ return -ENODEV; ++ } ++ } ++ ++ return 0; ++} ++ ++static void dsi_complexio_config(struct omap_dss_device *dssdev) ++{ ++ u32 r; ++ ++ int clk_lane = dssdev->phy.dsi.clk_lane; ++ int data1_lane = dssdev->phy.dsi.data1_lane; ++ int data2_lane = dssdev->phy.dsi.data2_lane; ++ int clk_pol = dssdev->phy.dsi.clk_pol; ++ int data1_pol = dssdev->phy.dsi.data1_pol; ++ int data2_pol = dssdev->phy.dsi.data2_pol; ++ ++ r = dsi_read_reg(DSI_COMPLEXIO_CFG1); ++ r = FLD_MOD(r, clk_lane, 2, 0); ++ r = FLD_MOD(r, clk_pol, 3, 3); ++ r = FLD_MOD(r, data1_lane, 6, 4); ++ r = FLD_MOD(r, data1_pol, 7, 7); ++ r = FLD_MOD(r, data2_lane, 10, 8); ++ r = FLD_MOD(r, data2_pol, 11, 11); ++ dsi_write_reg(DSI_COMPLEXIO_CFG1, r); ++ ++ /* The configuration of the DSI complex I/O (number of data lanes, ++ position, differential order) should not be changed while ++ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for ++ the hardware to take into account a new configuration of the complex ++ I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to ++ follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, ++ then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set ++ DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the ++ DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the ++ DSI complex I/O configuration is unknown. */ ++ ++ /* ++ REG_FLD_MOD(DSI_CTRL, 1, 0, 0); ++ REG_FLD_MOD(DSI_CTRL, 0, 0, 0); ++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); ++ REG_FLD_MOD(DSI_CTRL, 1, 0, 0); ++ */ ++} ++ ++static inline unsigned ns2ddr(unsigned ns) ++{ ++ /* convert time in ns to ddr ticks, rounding up */ ++ return (ns * (dsi.ddr_clk/1000/1000) + 999) / 1000; ++} ++ ++static inline unsigned ddr2ns(unsigned ddr) ++{ ++ return ddr * 1000 * 1000 / (dsi.ddr_clk / 1000); ++} ++ ++static void dsi_complexio_timings(void) ++{ ++ u32 r; ++ u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit; ++ u32 tlpx_half, tclk_trail, tclk_zero; ++ u32 tclk_prepare; ++ ++ /* calculate timings */ ++ ++ /* 1 * DDR_CLK = 2 * UI */ ++ ++ /* min 40ns + 4*UI max 85ns + 6*UI */ ++ ths_prepare = ns2ddr(70) + 2; ++ ++ /* min 145ns + 10*UI */ ++ ths_prepare_ths_zero = ns2ddr(175) + 2; ++ ++ /* min max(8*UI, 60ns+4*UI) */ ++ ths_trail = ns2ddr(60) + 5; ++ ++ /* min 100ns */ ++ ths_exit = ns2ddr(145); ++ ++ /* tlpx min 50n */ ++ tlpx_half = ns2ddr(25); ++ ++ /* min 60ns */ ++ tclk_trail = ns2ddr(60) + 2; ++ ++ /* min 38ns, max 95ns */ ++ tclk_prepare = ns2ddr(65); ++ ++ /* min tclk-prepare + tclk-zero = 300ns */ ++ tclk_zero = ns2ddr(260); ++ ++ DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n", ++ ths_prepare, ddr2ns(ths_prepare), ++ ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero)); ++ DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n", ++ ths_trail, ddr2ns(ths_trail), ++ ths_exit, ddr2ns(ths_exit)); ++ ++ DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), " ++ "tclk_zero %u (%uns)\n", ++ tlpx_half, ddr2ns(tlpx_half), ++ tclk_trail, ddr2ns(tclk_trail), ++ tclk_zero, ddr2ns(tclk_zero)); ++ DSSDBG("tclk_prepare %u (%uns)\n", ++ tclk_prepare, ddr2ns(tclk_prepare)); ++ ++ /* program timings */ ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG0); ++ r = FLD_MOD(r, ths_prepare, 31, 24); ++ r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16); ++ r = FLD_MOD(r, ths_trail, 15, 8); ++ r = FLD_MOD(r, ths_exit, 7, 0); ++ dsi_write_reg(DSI_DSIPHY_CFG0, r); ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG1); ++ r = FLD_MOD(r, tlpx_half, 22, 16); ++ r = FLD_MOD(r, tclk_trail, 15, 8); ++ r = FLD_MOD(r, tclk_zero, 7, 0); ++ dsi_write_reg(DSI_DSIPHY_CFG1, r); ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG2); ++ r = FLD_MOD(r, tclk_prepare, 7, 0); ++ dsi_write_reg(DSI_DSIPHY_CFG2, r); ++} ++ ++ ++static int dsi_complexio_init(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("dsi_complexio_init\n"); ++ ++ /* CIO_CLK_ICG, enable L3 clk to CIO */ ++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14); ++ ++ /* A dummy read using the SCP interface to any DSIPHY register is ++ * required after DSIPHY reset to complete the reset of the DSI complex ++ * I/O. */ ++ dsi_read_reg(DSI_DSIPHY_CFG5); ++ ++ if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) { ++ DSSERR("ComplexIO PHY not coming out of reset.\n"); ++ r = -ENODEV; ++ goto err; ++ } ++ ++ dsi_complexio_config(dssdev); ++ ++ r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON); ++ ++ if (r) ++ goto err; ++ ++ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) { ++ DSSERR("ComplexIO not coming out of reset.\n"); ++ r = -ENODEV; ++ goto err; ++ } ++ ++ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) { ++ DSSERR("ComplexIO LDO power down.\n"); ++ r = -ENODEV; ++ goto err; ++ } ++ ++ dsi_complexio_timings(); ++ ++ /* ++ The configuration of the DSI complex I/O (number of data lanes, ++ position, differential order) should not be changed while ++ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the ++ hardware to recognize a new configuration of the complex I/O (done ++ in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow ++ this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next ++ reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20] ++ LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN ++ bit to 1. If the sequence is not followed, the DSi complex I/O ++ configuration is undetermined. ++ */ ++ dsi_if_enable(1); ++ dsi_if_enable(0); ++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ ++ dsi_if_enable(1); ++ dsi_if_enable(0); ++ ++ DSSDBG("CIO init done\n"); ++err: ++ return r; ++} ++ ++static void dsi_complexio_uninit(void) ++{ ++ dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF); ++} ++ ++static int _dsi_wait_reset(void) ++{ ++ int i = 0; ++ ++ while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) { ++ if (i++ > 5) { ++ DSSERR("soft reset failed\n"); ++ return -ENODEV; ++ } ++ udelay(1); ++ } ++ ++ return 0; ++} ++ ++static int _dsi_reset(void) ++{ ++ /* Soft reset */ ++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1); ++ return _dsi_wait_reset(); ++} ++ ++ ++static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, ++ enum fifo_size size3, enum fifo_size size4) ++{ ++ u32 r = 0; ++ int add = 0; ++ int i; ++ ++ dsi.vc[0].fifo_size = size1; ++ dsi.vc[1].fifo_size = size2; ++ dsi.vc[2].fifo_size = size3; ++ dsi.vc[3].fifo_size = size4; ++ ++ for (i = 0; i < 4; i++) { ++ u8 v; ++ int size = dsi.vc[i].fifo_size; ++ ++ if (add + size > 4) { ++ DSSERR("Illegal FIFO configuration\n"); ++ BUG(); ++ } ++ ++ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); ++ r |= v << (8 * i); ++ /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */ ++ add += size; ++ } ++ ++ dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r); ++} ++ ++static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2, ++ enum fifo_size size3, enum fifo_size size4) ++{ ++ u32 r = 0; ++ int add = 0; ++ int i; ++ ++ dsi.vc[0].fifo_size = size1; ++ dsi.vc[1].fifo_size = size2; ++ dsi.vc[2].fifo_size = size3; ++ dsi.vc[3].fifo_size = size4; ++ ++ for (i = 0; i < 4; i++) { ++ u8 v; ++ int size = dsi.vc[i].fifo_size; ++ ++ if (add + size > 4) { ++ DSSERR("Illegal FIFO configuration\n"); ++ BUG(); ++ } ++ ++ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); ++ r |= v << (8 * i); ++ /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */ ++ add += size; ++ } ++ ++ dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r); ++} ++ ++static int dsi_force_tx_stop_mode_io(void) ++{ ++ u32 r; ++ ++ r = dsi_read_reg(DSI_TIMING1); ++ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ ++ dsi_write_reg(DSI_TIMING1, r); ++ ++ if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) { ++ DSSERR("TX_STOP bit not going down\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static void dsi_vc_print_status(int channel) ++{ ++ u32 r; ++ ++ r = dsi_read_reg(DSI_VC_CTRL(channel)); ++ DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, " ++ "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ", ++ channel, ++ FLD_GET(r, 5, 5), ++ FLD_GET(r, 6, 6), ++ FLD_GET(r, 15, 15), ++ FLD_GET(r, 16, 16), ++ FLD_GET(r, 20, 20)); ++ ++ r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS); ++ DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff); ++} ++ ++static int dsi_vc_enable(int channel, bool enable) ++{ ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) ++ DSSDBG("dsi_vc_enable channel %d, enable %d\n", ++ channel, enable); ++ ++ enable = enable ? 1 : 0; ++ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0); ++ ++ if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) { ++ DSSERR("Failed to set dsi_vc_enable to %d\n", enable); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static void dsi_vc_initial_config(int channel) ++{ ++ u32 r; ++ ++ DSSDBGF("%d", channel); ++ ++ r = dsi_read_reg(DSI_VC_CTRL(channel)); ++ ++ if (FLD_GET(r, 15, 15)) /* VC_BUSY */ ++ DSSERR("VC(%d) busy when trying to configure it!\n", ++ channel); ++ ++ r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */ ++ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */ ++ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */ ++ r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */ ++ r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */ ++ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */ ++ r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */ ++ ++ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ ++ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ ++ ++ dsi_write_reg(DSI_VC_CTRL(channel), r); ++ ++ dsi.vc[channel].mode = DSI_VC_MODE_L4; ++} ++ ++static void dsi_vc_config_l4(int channel) ++{ ++ if (dsi.vc[channel].mode == DSI_VC_MODE_L4) ++ return; ++ ++ DSSDBGF("%d", channel); ++ ++ dsi_vc_enable(channel, 0); ++ ++ if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ ++ DSSERR("vc(%d) busy when trying to config for L4\n", channel); ++ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ ++ ++ dsi_vc_enable(channel, 1); ++ ++ dsi.vc[channel].mode = DSI_VC_MODE_L4; ++} ++ ++static void dsi_vc_config_vp(int channel) ++{ ++ if (dsi.vc[channel].mode == DSI_VC_MODE_VP) ++ return; ++ ++ DSSDBGF("%d", channel); ++ ++ dsi_vc_enable(channel, 0); ++ ++ if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ ++ DSSERR("vc(%d) busy when trying to config for VP\n", channel); ++ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ ++ ++ dsi_vc_enable(channel, 1); ++ ++ dsi.vc[channel].mode = DSI_VC_MODE_VP; ++} ++ ++ ++static void dsi_vc_enable_hs(int channel, bool enable) ++{ ++ DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); ++ ++ dsi_vc_enable(channel, 0); ++ dsi_if_enable(0); ++ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9); ++ ++ dsi_vc_enable(channel, 1); ++ dsi_if_enable(1); ++ ++ dsi_force_tx_stop_mode_io(); ++} ++ ++static void dsi_vc_flush_long_data(int channel) ++{ ++ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { ++ u32 val; ++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); ++ DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n", ++ (val >> 0) & 0xff, ++ (val >> 8) & 0xff, ++ (val >> 16) & 0xff, ++ (val >> 24) & 0xff); ++ } ++} ++ ++static void dsi_show_rx_ack_with_err(u16 err) ++{ ++ DSSERR("\tACK with ERROR (%#x):\n", err); ++ if (err & (1 << 0)) ++ DSSERR("\t\tSoT Error\n"); ++ if (err & (1 << 1)) ++ DSSERR("\t\tSoT Sync Error\n"); ++ if (err & (1 << 2)) ++ DSSERR("\t\tEoT Sync Error\n"); ++ if (err & (1 << 3)) ++ DSSERR("\t\tEscape Mode Entry Command Error\n"); ++ if (err & (1 << 4)) ++ DSSERR("\t\tLP Transmit Sync Error\n"); ++ if (err & (1 << 5)) ++ DSSERR("\t\tHS Receive Timeout Error\n"); ++ if (err & (1 << 6)) ++ DSSERR("\t\tFalse Control Error\n"); ++ if (err & (1 << 7)) ++ DSSERR("\t\t(reserved7)\n"); ++ if (err & (1 << 8)) ++ DSSERR("\t\tECC Error, single-bit (corrected)\n"); ++ if (err & (1 << 9)) ++ DSSERR("\t\tECC Error, multi-bit (not corrected)\n"); ++ if (err & (1 << 10)) ++ DSSERR("\t\tChecksum Error\n"); ++ if (err & (1 << 11)) ++ DSSERR("\t\tData type not recognized\n"); ++ if (err & (1 << 12)) ++ DSSERR("\t\tInvalid VC ID\n"); ++ if (err & (1 << 13)) ++ DSSERR("\t\tInvalid Transmission Length\n"); ++ if (err & (1 << 14)) ++ DSSERR("\t\t(reserved14)\n"); ++ if (err & (1 << 15)) ++ DSSERR("\t\tDSI Protocol Violation\n"); ++} ++ ++static u16 dsi_vc_flush_receive_data(int channel) ++{ ++ /* RX_FIFO_NOT_EMPTY */ ++ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { ++ u32 val; ++ u8 dt; ++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); ++ DSSDBG("\trawval %#08x\n", val); ++ dt = FLD_GET(val, 5, 0); ++ if (dt == DSI_DT_RX_ACK_WITH_ERR) { ++ u16 err = FLD_GET(val, 23, 8); ++ dsi_show_rx_ack_with_err(err); ++ } else if (dt == DSI_DT_RX_SHORT_READ_1) { ++ DSSDBG("\tDCS short response, 1 byte: %#x\n", ++ FLD_GET(val, 23, 8)); ++ } else if (dt == DSI_DT_RX_SHORT_READ_2) { ++ DSSDBG("\tDCS short response, 2 byte: %#x\n", ++ FLD_GET(val, 23, 8)); ++ } else if (dt == DSI_DT_RX_DCS_LONG_READ) { ++ DSSDBG("\tDCS long response, len %d\n", ++ FLD_GET(val, 23, 8)); ++ dsi_vc_flush_long_data(channel); ++ } else { ++ DSSERR("\tunknown datatype 0x%02x\n", dt); ++ } ++ } ++ return 0; ++} ++ ++static int dsi_vc_send_bta(int channel) ++{ ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO && ++ (dsi.debug_write || dsi.debug_read)) ++ DSSDBG("dsi_vc_send_bta %d\n", channel); ++ ++ WARN_ON(!mutex_is_locked(&dsi.bus_lock)); ++ ++ if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */ ++ DSSERR("rx fifo not empty when sending BTA, dumping data:\n"); ++ dsi_vc_flush_receive_data(channel); ++ } ++ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ ++ ++ return 0; ++} ++ ++int dsi_vc_send_bta_sync(int channel) ++{ ++ int r = 0; ++ u32 err; ++ ++ INIT_COMPLETION(dsi.bta_completion); ++ ++ dsi_vc_enable_bta_irq(channel); ++ ++ r = dsi_vc_send_bta(channel); ++ if (r) ++ goto err; ++ ++ if (wait_for_completion_timeout(&dsi.bta_completion, ++ msecs_to_jiffies(500)) == 0) { ++ DSSERR("Failed to receive BTA\n"); ++ r = -EIO; ++ goto err; ++ } ++ ++ err = dsi_get_errors(); ++ if (err) { ++ DSSERR("Error while sending BTA: %x\n", err); ++ r = -EIO; ++ goto err; ++ } ++err: ++ dsi_vc_disable_bta_irq(channel); ++ ++ return r; ++} ++EXPORT_SYMBOL(dsi_vc_send_bta_sync); ++ ++static inline void dsi_vc_write_long_header(int channel, u8 data_type, ++ u16 len, u8 ecc) ++{ ++ u32 val; ++ u8 data_id; ++ ++ WARN_ON(!mutex_is_locked(&dsi.bus_lock)); ++ ++ /*data_id = data_type | channel << 6; */ ++ data_id = data_type | dsi.vc[channel].dest_per << 6; ++ ++ val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | ++ FLD_VAL(ecc, 31, 24); ++ ++ dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val); ++} ++ ++static inline void dsi_vc_write_long_payload(int channel, ++ u8 b1, u8 b2, u8 b3, u8 b4) ++{ ++ u32 val; ++ ++ val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0; ++ ++/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n", ++ b1, b2, b3, b4, val); */ ++ ++ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val); ++} ++ ++static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len, ++ u8 ecc) ++{ ++ /*u32 val; */ ++ int i; ++ u8 *p; ++ int r = 0; ++ u8 b1, b2, b3, b4; ++ ++ if (dsi.debug_write) ++ DSSDBG("dsi_vc_send_long, %d bytes\n", len); ++ ++ /* len + header */ ++ if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) { ++ DSSERR("unable to send long packet: packet too long.\n"); ++ return -EINVAL; ++ } ++ ++ dsi_vc_config_l4(channel); ++ ++ dsi_vc_write_long_header(channel, data_type, len, ecc); ++ ++ /*dsi_vc_print_status(0); */ ++ ++ p = data; ++ for (i = 0; i < len >> 2; i++) { ++ if (dsi.debug_write) ++ DSSDBG("\tsending full packet %d\n", i); ++ /*dsi_vc_print_status(0); */ ++ ++ b1 = *p++; ++ b2 = *p++; ++ b3 = *p++; ++ b4 = *p++; ++ ++ dsi_vc_write_long_payload(channel, b1, b2, b3, b4); ++ } ++ ++ i = len % 4; ++ if (i) { ++ b1 = 0; b2 = 0; b3 = 0; ++ ++ if (dsi.debug_write) ++ DSSDBG("\tsending remainder bytes %d\n", i); ++ ++ switch (i) { ++ case 3: ++ b1 = *p++; ++ b2 = *p++; ++ b3 = *p++; ++ break; ++ case 2: ++ b1 = *p++; ++ b2 = *p++; ++ break; ++ case 1: ++ b1 = *p++; ++ break; ++ } ++ ++ dsi_vc_write_long_payload(channel, b1, b2, b3, 0); ++ } ++ ++ return r; ++} ++ ++static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) ++{ ++ u32 r; ++ u8 data_id; ++ ++ WARN_ON(!mutex_is_locked(&dsi.bus_lock)); ++ ++ if (dsi.debug_write) ++ DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n", ++ channel, ++ data_type, data & 0xff, (data >> 8) & 0xff); ++ ++ dsi_vc_config_l4(channel); ++ ++ if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) { ++ DSSERR("ERROR FIFO FULL, aborting transfer\n"); ++ return -EINVAL; ++ } ++ ++ data_id = data_type | channel << 6; ++ ++ r = (data_id << 0) | (data << 8) | (ecc << 24); ++ ++ dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r); ++ ++ return 0; ++} ++ ++int dsi_vc_send_null(int channel) ++{ ++ u8 nullpkg[] = {0, 0, 0, 0}; ++ return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0); ++} ++EXPORT_SYMBOL(dsi_vc_send_null); ++ ++int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len) ++{ ++ int r; ++ ++ BUG_ON(len == 0); ++ ++ if (len == 1) { ++ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0, ++ data[0], 0); ++ } else if (len == 2) { ++ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1, ++ data[0] | (data[1] << 8), 0); ++ } else { ++ /* 0x39 = DCS Long Write */ ++ r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE, ++ data, len, 0); ++ } ++ ++ return r; ++} ++EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); ++ ++int dsi_vc_dcs_write(int channel, u8 *data, int len) ++{ ++ int r; ++ ++ r = dsi_vc_dcs_write_nosync(channel, data, len); ++ if (r) ++ return r; ++ ++ r = dsi_vc_send_bta_sync(channel); ++ ++ return r; ++} ++EXPORT_SYMBOL(dsi_vc_dcs_write); ++ ++int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) ++{ ++ u32 val; ++ u8 dt; ++ int r; ++ ++ if (dsi.debug_read) ++ DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd); ++ ++ r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0); ++ if (r) ++ return r; ++ ++ r = dsi_vc_send_bta_sync(channel); ++ if (r) ++ return r; ++ ++ /* RX_FIFO_NOT_EMPTY */ ++ if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) { ++ DSSERR("RX fifo empty when trying to read.\n"); ++ return -EIO; ++ } ++ ++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); ++ if (dsi.debug_read) ++ DSSDBG("\theader: %08x\n", val); ++ dt = FLD_GET(val, 5, 0); ++ if (dt == DSI_DT_RX_ACK_WITH_ERR) { ++ u16 err = FLD_GET(val, 23, 8); ++ dsi_show_rx_ack_with_err(err); ++ return -EIO; ++ ++ } else if (dt == DSI_DT_RX_SHORT_READ_1) { ++ u8 data = FLD_GET(val, 15, 8); ++ if (dsi.debug_read) ++ DSSDBG("\tDCS short response, 1 byte: %02x\n", data); ++ ++ if (buflen < 1) ++ return -EIO; ++ ++ buf[0] = data; ++ ++ return 1; ++ } else if (dt == DSI_DT_RX_SHORT_READ_2) { ++ u16 data = FLD_GET(val, 23, 8); ++ if (dsi.debug_read) ++ DSSDBG("\tDCS short response, 2 byte: %04x\n", data); ++ ++ if (buflen < 2) ++ return -EIO; ++ ++ buf[0] = data & 0xff; ++ buf[1] = (data >> 8) & 0xff; ++ ++ return 2; ++ } else if (dt == DSI_DT_RX_DCS_LONG_READ) { ++ int w; ++ int len = FLD_GET(val, 23, 8); ++ if (dsi.debug_read) ++ DSSDBG("\tDCS long response, len %d\n", len); ++ ++ if (len > buflen) ++ return -EIO; ++ ++ /* two byte checksum ends the packet, not included in len */ ++ for (w = 0; w < len + 2;) { ++ int b; ++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); ++ if (dsi.debug_read) ++ DSSDBG("\t\t%02x %02x %02x %02x\n", ++ (val >> 0) & 0xff, ++ (val >> 8) & 0xff, ++ (val >> 16) & 0xff, ++ (val >> 24) & 0xff); ++ ++ for (b = 0; b < 4; ++b) { ++ if (w < len) ++ buf[w] = (val >> (b * 8)) & 0xff; ++ /* we discard the 2 byte checksum */ ++ ++w; ++ } ++ } ++ ++ return len; ++ ++ } else { ++ DSSERR("\tunknown datatype 0x%02x\n", dt); ++ return -EIO; ++ } ++} ++EXPORT_SYMBOL(dsi_vc_dcs_read); ++ ++ ++int dsi_vc_set_max_rx_packet_size(int channel, u16 len) ++{ ++ return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE, ++ len, 0); ++} ++EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); ++ ++ ++static int dsi_set_lp_rx_timeout(int ns, int x4, int x16) ++{ ++ u32 r; ++ unsigned long fck; ++ int ticks; ++ ++ /* ticks in DSI_FCK */ ++ ++ fck = dsi_fclk_rate(); ++ ticks = (fck / 1000 / 1000) * ns / 1000; ++ ++ if (ticks > 0x1fff) { ++ DSSERR("LP_TX_TO too high\n"); ++ return -EINVAL; ++ } ++ ++ r = dsi_read_reg(DSI_TIMING2); ++ r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ ++ r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */ ++ r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */ ++ r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ ++ dsi_write_reg(DSI_TIMING2, r); ++ ++ DSSDBG("LP_RX_TO %ld ns (%#x ticks)\n", ++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / ++ (fck / 1000 / 1000), ++ ticks); ++ ++ return 0; ++} ++ ++static int dsi_set_ta_timeout(int ns, int x8, int x16) ++{ ++ u32 r; ++ unsigned long fck; ++ int ticks; ++ ++ /* ticks in DSI_FCK */ ++ ++ fck = dsi_fclk_rate(); ++ ticks = (fck / 1000 / 1000) * ns / 1000; ++ ++ if (ticks > 0x1fff) { ++ DSSERR("TA_TO too high\n"); ++ return -EINVAL; ++ } ++ ++ r = dsi_read_reg(DSI_TIMING1); ++ r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ ++ r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */ ++ r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */ ++ r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ ++ dsi_write_reg(DSI_TIMING1, r); ++ ++ DSSDBG("TA_TO %ld ns (%#x ticks)\n", ++ (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) / ++ (fck / 1000 / 1000), ++ ticks); ++ ++ return 0; ++} ++ ++static int dsi_set_stop_state_counter(int ns, int x4, int x16) ++{ ++ u32 r; ++ unsigned long fck; ++ int ticks; ++ ++ /* ticks in DSI_FCK */ ++ ++ fck = dsi_fclk_rate(); ++ ticks = (fck / 1000 / 1000) * ns / 1000; ++ ++ if (ticks > 0x1fff) { ++ DSSERR("STOP_STATE_COUNTER_IO too high\n"); ++ return -EINVAL; ++ } ++ ++ r = dsi_read_reg(DSI_TIMING1); ++ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ ++ r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */ ++ r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */ ++ r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ ++ dsi_write_reg(DSI_TIMING1, r); ++ ++ DSSDBG("STOP_STATE_COUNTER %ld ns (%#x ticks)\n", ++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / ++ (fck / 1000 / 1000), ++ ticks); ++ ++ return 0; ++} ++ ++static int dsi_set_hs_tx_timeout(int ns, int x4, int x16) ++{ ++ u32 r; ++ unsigned long fck; ++ int ticks; ++ ++ /* ticks in TxByteClkHS */ ++ ++ fck = dsi.ddr_clk / 4; ++ ticks = (fck / 1000 / 1000) * ns / 1000; ++ ++ if (ticks > 0x1fff) { ++ DSSERR("HS_TX_TO too high\n"); ++ return -EINVAL; ++ } ++ ++ r = dsi_read_reg(DSI_TIMING2); ++ r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ ++ r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */ ++ r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */ ++ r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ ++ dsi_write_reg(DSI_TIMING2, r); ++ ++ DSSDBG("HS_TX_TO %ld ns (%#x ticks)\n", ++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / ++ (fck / 1000 / 1000), ++ ticks); ++ ++ return 0; ++} ++static int dsi_proto_config(struct omap_dss_device *dssdev) ++{ ++ u32 r; ++ int buswidth = 0; ++ int div; ++ ++ dsi_config_tx_fifo(DSI_FIFO_SIZE_128, ++ DSI_FIFO_SIZE_0, ++ DSI_FIFO_SIZE_0, ++ DSI_FIFO_SIZE_0); ++ ++ dsi_config_rx_fifo(DSI_FIFO_SIZE_128, ++ DSI_FIFO_SIZE_0, ++ DSI_FIFO_SIZE_0, ++ DSI_FIFO_SIZE_0); ++ ++ /* XXX what values for the timeouts? */ ++ dsi_set_stop_state_counter(1000, 0, 0); ++ ++ dsi_set_ta_timeout(50000, 1, 1); ++ ++ /* 3000ns * 16 */ ++ dsi_set_lp_rx_timeout(3000, 0, 1); ++ ++ /* 10000ns * 4 */ ++ dsi_set_hs_tx_timeout(10000, 1, 0); ++ ++ switch (dssdev->ctrl.pixel_size) { ++ case 16: ++ buswidth = 0; ++ break; ++ case 18: ++ buswidth = 1; ++ break; ++ case 24: ++ buswidth = 2; ++ break; ++ default: ++ BUG(); ++ } ++ ++ r = dsi_read_reg(DSI_CTRL); ++ r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */ ++ r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */ ++ r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */ ++ ++ div = dispc_lclk_rate() / dispc_pclk_rate(); ++ r = FLD_MOD(r, div == 2 ? 0 : 1, 4, 4); /* VP_CLK_RATIO */ ++ r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */ ++ r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ ++ r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ ++ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ ++ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ ++ r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ ++ r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */ ++ ++ dsi_write_reg(DSI_CTRL, r); ++ ++ dsi_vc_initial_config(0); ++ ++ /* set all vc targets to peripheral 0 */ ++ dsi.vc[0].dest_per = 0; ++ dsi.vc[1].dest_per = 0; ++ dsi.vc[2].dest_per = 0; ++ dsi.vc[3].dest_per = 0; ++ ++ return 0; ++} ++ ++static void dsi_proto_timings(struct omap_dss_device *dssdev) ++{ ++ unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; ++ unsigned tclk_pre, tclk_post; ++ unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; ++ unsigned ths_trail, ths_exit; ++ unsigned ddr_clk_pre, ddr_clk_post; ++ unsigned enter_hs_mode_lat, exit_hs_mode_lat; ++ unsigned ths_eot; ++ u32 r; ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG0); ++ ths_prepare = FLD_GET(r, 31, 24); ++ ths_prepare_ths_zero = FLD_GET(r, 23, 16); ++ ths_zero = ths_prepare_ths_zero - ths_prepare; ++ ths_trail = FLD_GET(r, 15, 8); ++ ths_exit = FLD_GET(r, 7, 0); ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG1); ++ tlpx = FLD_GET(r, 22, 16) * 2; ++ tclk_trail = FLD_GET(r, 15, 8); ++ tclk_zero = FLD_GET(r, 7, 0); ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG2); ++ tclk_prepare = FLD_GET(r, 7, 0); ++ ++ /* min 8*UI */ ++ tclk_pre = 20; ++ /* min 60ns + 52*UI */ ++ tclk_post = ns2ddr(60) + 26; ++ ++ /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */ ++ if (dssdev->phy.dsi.data1_lane != 0 && ++ dssdev->phy.dsi.data2_lane != 0) ++ ths_eot = 2; ++ else ++ ths_eot = 4; ++ ++ ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, ++ 4); ++ ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4) + ths_eot; ++ ++ BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255); ++ BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255); ++ ++ r = dsi_read_reg(DSI_CLK_TIMING); ++ r = FLD_MOD(r, ddr_clk_pre, 15, 8); ++ r = FLD_MOD(r, ddr_clk_post, 7, 0); ++ dsi_write_reg(DSI_CLK_TIMING, r); ++ ++ DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n", ++ ddr_clk_pre, ++ ddr_clk_post); ++ ++ enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) + ++ DIV_ROUND_UP(ths_prepare, 4) + ++ DIV_ROUND_UP(ths_zero + 3, 4); ++ ++ exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot; ++ ++ r = FLD_VAL(enter_hs_mode_lat, 31, 16) | ++ FLD_VAL(exit_hs_mode_lat, 15, 0); ++ dsi_write_reg(DSI_VM_TIMING7, r); ++ ++ DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", ++ enter_hs_mode_lat, exit_hs_mode_lat); ++} ++ ++ ++#define DSI_DECL_VARS \ ++ int __dsi_cb = 0; u32 __dsi_cv = 0; ++ ++#define DSI_FLUSH(ch) \ ++ if (__dsi_cb > 0) { \ ++ /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ ++ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ ++ __dsi_cb = __dsi_cv = 0; \ ++ } ++ ++#define DSI_PUSH(ch, data) \ ++ do { \ ++ __dsi_cv |= (data) << (__dsi_cb * 8); \ ++ /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ ++ if (++__dsi_cb > 3) \ ++ DSI_FLUSH(ch); \ ++ } while (0) ++ ++static int dsi_update_screen_l4(struct omap_dss_device *dssdev, ++ int x, int y, int w, int h) ++{ ++ /* Note: supports only 24bit colors in 32bit container */ ++ int first = 1; ++ int fifo_stalls = 0; ++ int max_dsi_packet_size; ++ int max_data_per_packet; ++ int max_pixels_per_packet; ++ int pixels_left; ++ int bytespp = dssdev->ctrl.pixel_size / 8; ++ int scr_width; ++ u32 __iomem *data; ++ int start_offset; ++ int horiz_inc; ++ int current_x; ++ struct omap_overlay *ovl; ++ ++ debug_irq = 0; ++ ++ DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n", ++ x, y, w, h); ++ ++ ovl = dssdev->manager->overlays[0]; ++ ++ if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U) ++ return -EINVAL; ++ ++ if (dssdev->ctrl.pixel_size != 24) ++ return -EINVAL; ++ ++ scr_width = ovl->info.screen_width; ++ data = ovl->info.vaddr; ++ ++ start_offset = scr_width * y + x; ++ horiz_inc = scr_width - w; ++ current_x = x; ++ ++ /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes ++ * in fifo */ ++ ++ /* When using CPU, max long packet size is TX buffer size */ ++ max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4; ++ ++ /* we seem to get better perf if we divide the tx fifo to half, ++ and while the other half is being sent, we fill the other half ++ max_dsi_packet_size /= 2; */ ++ ++ max_data_per_packet = max_dsi_packet_size - 4 - 1; ++ ++ max_pixels_per_packet = max_data_per_packet / bytespp; ++ ++ DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet); ++ ++ pixels_left = w * h; ++ ++ DSSDBG("total pixels %d\n", pixels_left); ++ ++ data += start_offset; ++ ++ while (pixels_left > 0) { ++ /* 0x2c = write_memory_start */ ++ /* 0x3c = write_memory_continue */ ++ u8 dcs_cmd = first ? 0x2c : 0x3c; ++ int pixels; ++ DSI_DECL_VARS; ++ first = 0; ++ ++#if 1 ++ /* using fifo not empty */ ++ /* TX_FIFO_NOT_EMPTY */ ++ while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) { ++ udelay(1); ++ fifo_stalls++; ++ if (fifo_stalls > 0xfffff) { ++ DSSERR("fifo stalls overflow, pixels left %d\n", ++ pixels_left); ++ dsi_if_enable(0); ++ return -EIO; ++ } ++ } ++#elif 1 ++ /* using fifo emptiness */ ++ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < ++ max_dsi_packet_size) { ++ fifo_stalls++; ++ if (fifo_stalls > 0xfffff) { ++ DSSERR("fifo stalls overflow, pixels left %d\n", ++ pixels_left); ++ dsi_if_enable(0); ++ return -EIO; ++ } ++ } ++#else ++ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) { ++ fifo_stalls++; ++ if (fifo_stalls > 0xfffff) { ++ DSSERR("fifo stalls overflow, pixels left %d\n", ++ pixels_left); ++ dsi_if_enable(0); ++ return -EIO; ++ } ++ } ++#endif ++ pixels = min(max_pixels_per_packet, pixels_left); ++ ++ pixels_left -= pixels; ++ ++ dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE, ++ 1 + pixels * bytespp, 0); ++ ++ DSI_PUSH(0, dcs_cmd); ++ ++ while (pixels-- > 0) { ++ u32 pix = __raw_readl(data++); ++ ++ DSI_PUSH(0, (pix >> 16) & 0xff); ++ DSI_PUSH(0, (pix >> 8) & 0xff); ++ DSI_PUSH(0, (pix >> 0) & 0xff); ++ ++ current_x++; ++ if (current_x == x+w) { ++ current_x = x; ++ data += horiz_inc; ++ } ++ } ++ ++ DSI_FLUSH(0); ++ } ++ ++ return 0; ++} ++ ++static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ int bytespp = dssdev->ctrl.pixel_size / 8; ++ int len; ++ int total_len; ++ int packet_payload; ++ int packet_len; ++ u32 l; ++ bool use_te_trigger; ++ const int channel = 0; ++ ++ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te; ++ ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) ++ DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", ++ x, y, w, h); ++ ++ len = w * h * bytespp; ++ ++ /* XXX: one packet could be longer, I think? Line buffer is ++ * 1024 x 24bits, but we have to put DCS cmd there also. ++ * 1023 * 3 should work, but causes strange color effects. */ ++ packet_payload = min(w, (u16)1020) * bytespp; ++ ++ packet_len = packet_payload + 1; /* 1 byte for DCS cmd */ ++ total_len = (len / packet_payload) * packet_len; ++ ++ if (len % packet_payload) ++ total_len += (len % packet_payload) + 1; ++ ++ if (0) ++ dsi_vc_print_status(1); ++ ++ l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ ++ dsi_write_reg(DSI_VC_TE(channel), l); ++ ++ dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0); ++ ++ if (use_te_trigger) ++ l = FLD_MOD(l, 1, 30, 30); /* TE_EN */ ++ else ++ l = FLD_MOD(l, 1, 31, 31); /* TE_START */ ++ dsi_write_reg(DSI_VC_TE(channel), l); ++ ++ /* We put SIDLEMODE to no-idle for the duration of the transfer, ++ * because DSS interrupts are not capable of waking up the CPU and the ++ * framedone interrupt could be delayed for quite a long time. I think ++ * the same goes for any DSS interrupts, but for some reason I have not ++ * seen the problem anywhere else than here. ++ */ ++ dispc_disable_sidle(); ++ ++ dss_start_update(dssdev); ++ ++ if (use_te_trigger) { ++ /* disable LP_RX_TO, so that we can receive TE. Time to wait ++ * for TE is longer than the timer allows */ ++ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */ ++ ++ dsi_vc_send_bta(channel); ++ } ++} ++ ++static void dsi_framedone_irq_callback(void *data, u32 mask) ++{ ++ /* Note: We get FRAMEDONE when DISPC has finished sending pixels and ++ * turns itself off. However, DSI still has the pixels in its buffers, ++ * and is sending the data. ++ */ ++ ++ /* SIDLEMODE back to smart-idle */ ++ dispc_enable_sidle(); ++ ++ dsi.framedone_received = true; ++ wake_up(&dsi.waitqueue); ++} ++ ++static void dsi_set_update_region(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ spin_lock(&dsi.update_lock); ++ if (dsi.update_region.dirty) { ++ dsi.update_region.x = min(x, dsi.update_region.x); ++ dsi.update_region.y = min(y, dsi.update_region.y); ++ dsi.update_region.w = max(w, dsi.update_region.w); ++ dsi.update_region.h = max(h, dsi.update_region.h); ++ } else { ++ dsi.update_region.x = x; ++ dsi.update_region.y = y; ++ dsi.update_region.w = w; ++ dsi.update_region.h = h; ++ } ++ ++ dsi.update_region.device = dssdev; ++ dsi.update_region.dirty = true; ++ ++ spin_unlock(&dsi.update_lock); ++ ++} ++ ++static void dsi_start_auto_update(struct omap_dss_device *dssdev) ++{ ++ u16 w, h; ++ int i; ++ ++ DSSDBG("starting auto update\n"); ++ ++ /* In automatic mode the overlay settings are applied like on DPI/SDI. ++ * Mark the overlays dirty, so that we get the overlays configured, as ++ * manual mode has left them in bad shape after config partia planes */ ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ if (ovl->manager == dssdev->manager) ++ ovl->info_dirty = true; ++ } ++ dssdev->manager->apply(dssdev->manager); ++ ++ dssdev->get_resolution(dssdev, &w, &h); ++ ++ dsi_set_update_region(dssdev, 0, 0, w, h); ++ ++ dsi_perf_mark_start_auto(); ++ ++ wake_up(&dsi.waitqueue); ++} ++ ++static int dsi_set_te(struct omap_dss_device *dssdev, bool enable) ++{ ++ int r; ++ r = dssdev->driver->enable_te(dssdev, enable); ++ /* XXX for some reason, DSI TE breaks if we don't wait here. ++ * Panel bug? Needs more studying */ ++ msleep(100); ++ return r; ++} ++ ++static void dsi_handle_framedone(void) ++{ ++ int r; ++ const int channel = 0; ++ bool use_te_trigger; ++ ++ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te; ++ ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) ++ DSSDBG("FRAMEDONE\n"); ++ ++ if (use_te_trigger) { ++ /* enable LP_RX_TO again after the TE */ ++ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ ++ } ++ ++ /* Send BTA after the frame. We need this for the TE to work, as TE ++ * trigger is only sent for BTAs without preceding packet. Thus we need ++ * to BTA after the pixel packets so that next BTA will cause TE ++ * trigger. ++ * ++ * This is not needed when TE is not in use, but we do it anyway to ++ * make sure that the transfer has been completed. It would be more ++ * optimal, but more complex, to wait only just before starting next ++ * transfer. */ ++ r = dsi_vc_send_bta_sync(channel); ++ if (r) ++ DSSERR("BTA after framedone failed\n"); ++ ++#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC ++ dispc_fake_vsync_irq(); ++#endif ++} ++ ++static int dsi_update_thread(void *data) ++{ ++ unsigned long timeout; ++ struct omap_dss_device *device; ++ u16 x, y, w, h; ++ ++ while (1) { ++ bool sched; ++ ++ wait_event_interruptible(dsi.waitqueue, ++ dsi.update_mode == OMAP_DSS_UPDATE_AUTO || ++ (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL && ++ dsi.update_region.dirty == true) || ++ kthread_should_stop()); ++ ++ if (kthread_should_stop()) ++ break; ++ ++ dsi_bus_lock(); ++ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED || ++ kthread_should_stop()) { ++ dsi_bus_unlock(); ++ break; ++ } ++ ++ dsi_perf_mark_setup(); ++ ++ if (dsi.update_region.dirty) { ++ spin_lock(&dsi.update_lock); ++ dsi.active_update_region = dsi.update_region; ++ dsi.update_region.dirty = false; ++ spin_unlock(&dsi.update_lock); ++ } ++ ++ device = dsi.active_update_region.device; ++ x = dsi.active_update_region.x; ++ y = dsi.active_update_region.y; ++ w = dsi.active_update_region.w; ++ h = dsi.active_update_region.h; ++ ++ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { ++ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL) { ++ dss_setup_partial_planes(device, ++ &x, &y, &w, &h); ++#if 1 ++ /* XXX there seems to be a bug in this driver ++ * or OMAP hardware. Some updates with certain ++ * widths and x coordinates fail. These widths ++ * are always odd, so "fix" it here for now */ ++ if (w & 1) { ++ u16 dw, dh; ++ device->get_resolution(device, ++ &dw, &dh); ++ if (x + w == dw) ++ x &= ~1; ++ ++w; ++ ++ dss_setup_partial_planes(device, ++ &x, &y, &w, &h); ++ } ++#endif ++ } ++ ++ dispc_set_lcd_size(w, h); ++ } ++ ++ if (dsi.active_update_region.dirty) { ++ dsi.active_update_region.dirty = false; ++ /* XXX TODO we don't need to send the coords, if they ++ * are the same that are already programmed to the ++ * panel. That should speed up manual update a bit */ ++ device->driver->setup_update(device, x, y, w, h); ++ } ++ ++ dsi_perf_mark_start(); ++ ++ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { ++ dsi_vc_config_vp(0); ++ ++ if (dsi.te_enabled && dsi.use_ext_te) ++ device->driver->wait_for_te(device); ++ ++ dsi.framedone_received = false; ++ ++ dsi_update_screen_dispc(device, x, y, w, h); ++ ++ /* wait for framedone */ ++ timeout = msecs_to_jiffies(1000); ++ timeout = wait_event_timeout(dsi.waitqueue, ++ dsi.framedone_received == true, ++ timeout); ++ ++ if (timeout == 0) { ++ DSSERR("framedone timeout\n"); ++ DSSERR("failed update %d,%d %dx%d\n", ++ x, y, w, h); ++ ++ dispc_enable_sidle(); ++ dispc_enable_lcd_out(0); ++ } else { ++ dsi_handle_framedone(); ++ dsi_perf_show("DISPC"); ++ } ++ } else { ++ dsi_update_screen_l4(device, x, y, w, h); ++ dsi_perf_show("L4"); ++ } ++ ++ sched = atomic_read(&dsi.bus_lock.count) < 0; ++ ++ complete_all(&dsi.update_completion); ++ ++ dsi_bus_unlock(); ++ ++ /* XXX We need to give others chance to get the bus lock. Is ++ * there a better way for this? */ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO && sched) ++ schedule_timeout_interruptible(1); ++ } ++ ++ DSSDBG("update thread exiting\n"); ++ ++ return 0; ++} ++ ++ ++ ++/* Display funcs */ ++ ++static int dsi_display_init_dispc(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL, ++ DISPC_IRQ_FRAMEDONE); ++ if (r) { ++ DSSERR("can't get FRAMEDONE irq\n"); ++ return r; ++ } ++ ++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); ++ ++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI); ++ dispc_enable_fifohandcheck(1); ++ ++ dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); ++ ++ { ++ struct omap_video_timings timings = { ++ .hsw = 1, ++ .hfp = 1, ++ .hbp = 1, ++ .vsw = 1, ++ .vfp = 0, ++ .vbp = 0, ++ }; ++ ++ dispc_set_lcd_timings(&timings); ++ } ++ ++ return 0; ++} ++ ++static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) ++{ ++ omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL, ++ DISPC_IRQ_FRAMEDONE); ++} ++ ++static int dsi_display_init_dsi(struct omap_dss_device *dssdev) ++{ ++ struct dsi_clock_info cinfo; ++ int r; ++ ++ _dsi_print_reset_status(); ++ ++ r = dsi_pll_init(1, 0); ++ if (r) ++ goto err0; ++ ++ r = dsi_pll_calc_ddrfreq(dssdev->phy.dsi.ddr_clk_hz, &cinfo); ++ if (r) ++ goto err1; ++ ++ r = dsi_pll_program(&cinfo); ++ if (r) ++ goto err1; ++ ++ DSSDBG("PLL OK\n"); ++ ++ r = dsi_complexio_init(dssdev); ++ if (r) ++ goto err1; ++ ++ _dsi_print_reset_status(); ++ ++ dsi_proto_timings(dssdev); ++ dsi_set_lp_clk_divisor(dssdev); ++ ++ if (1) ++ _dsi_print_reset_status(); ++ ++ r = dsi_proto_config(dssdev); ++ if (r) ++ goto err2; ++ ++ /* enable interface */ ++ dsi_vc_enable(0, 1); ++ dsi_if_enable(1); ++ dsi_force_tx_stop_mode_io(); ++ ++ if (dssdev->driver->enable) { ++ r = dssdev->driver->enable(dssdev); ++ if (r) ++ goto err3; ++ } ++ ++ /* enable high-speed after initial config */ ++ dsi_vc_enable_hs(0, 1); ++ ++ return 0; ++err3: ++ dsi_if_enable(0); ++err2: ++ dsi_complexio_uninit(); ++err1: ++ dsi_pll_uninit(); ++err0: ++ return r; ++} ++ ++static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->driver->disable) ++ dssdev->driver->disable(dssdev); ++ ++ dsi_complexio_uninit(); ++ dsi_pll_uninit(); ++} ++ ++static int dsi_core_init(void) ++{ ++ /* Autoidle */ ++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0); ++ ++ /* ENWAKEUP */ ++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2); ++ ++ /* SIDLEMODE smart-idle */ ++ REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3); ++ ++ _dsi_initialize_irq(); ++ ++ return 0; ++} ++ ++static int dsi_display_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("dsi_display_enable\n"); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ r = omap_dss_start_device(dssdev); ++ if (r) { ++ DSSERR("failed to start device\n"); ++ goto err0; ++ } ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { ++ DSSERR("dssdev already enabled\n"); ++ r = -EINVAL; ++ goto err1; ++ } ++ ++ enable_clocks(1); ++ dsi_enable_pll_clock(1); ++ ++ r = _dsi_reset(); ++ if (r) ++ goto err2; ++ ++ dsi_core_init(); ++ ++ r = dsi_display_init_dispc(dssdev); ++ if (r) ++ goto err2; ++ ++ r = dsi_display_init_dsi(dssdev); ++ if (r) ++ goto err3; ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ dsi.use_ext_te = dssdev->phy.dsi.ext_te; ++ r = dsi_set_te(dssdev, dsi.te_enabled); ++ if (r) ++ goto err3; ++ ++ dsi.update_mode = dsi.user_update_mode; ++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) ++ dsi_start_auto_update(dssdev); ++ ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ ++ return 0; ++ ++err3: ++ dsi_display_uninit_dispc(dssdev); ++err2: ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++err1: ++ omap_dss_stop_device(dssdev); ++err0: ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ DSSDBG("dsi_display_enable FAILED\n"); ++ return r; ++} ++ ++static void dsi_display_disable(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("dsi_display_disable\n"); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || ++ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) ++ goto end; ++ ++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED; ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++ ++ dsi_display_uninit_dispc(dssdev); ++ ++ dsi_display_uninit_dsi(dssdev); ++ ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++ ++ omap_dss_stop_device(dssdev); ++end: ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++} ++ ++static int dsi_display_suspend(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("dsi_display_suspend\n"); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || ++ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) ++ goto end; ++ ++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED; ++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; ++ ++ dsi_display_uninit_dispc(dssdev); ++ ++ dsi_display_uninit_dsi(dssdev); ++ ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++end: ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ ++ return 0; ++} ++ ++static int dsi_display_resume(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ DSSDBG("dsi_display_resume\n"); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { ++ DSSERR("dssdev not suspended\n"); ++ r = -EINVAL; ++ goto err0; ++ } ++ ++ enable_clocks(1); ++ dsi_enable_pll_clock(1); ++ ++ r = _dsi_reset(); ++ if (r) ++ goto err1; ++ ++ dsi_core_init(); ++ ++ r = dsi_display_init_dispc(dssdev); ++ if (r) ++ goto err1; ++ ++ r = dsi_display_init_dsi(dssdev); ++ if (r) ++ goto err2; ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ r = dsi_set_te(dssdev, dsi.te_enabled); ++ if (r) ++ goto err2; ++ ++ dsi.update_mode = dsi.user_update_mode; ++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) ++ dsi_start_auto_update(dssdev); ++ ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ ++ return 0; ++ ++err2: ++ dsi_display_uninit_dispc(dssdev); ++err1: ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++err0: ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ DSSDBG("dsi_display_resume FAILED\n"); ++ return r; ++} ++ ++static int dsi_display_update(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ int r = 0; ++ u16 dw, dh; ++ ++ DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h); ++ ++ mutex_lock(&dsi.lock); ++ ++ if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL) ++ goto end; ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ goto end; ++ ++ dssdev->get_resolution(dssdev, &dw, &dh); ++ ++ if (x > dw || y > dh) ++ goto end; ++ ++ if (x + w > dw) ++ w = dw - x; ++ ++ if (y + h > dh) ++ h = dh - y; ++ ++ if (w == 0 || h == 0) ++ goto end; ++ ++ dsi_set_update_region(dssdev, x, y, w, h); ++ ++ wake_up(&dsi.waitqueue); ++ ++end: ++ mutex_unlock(&dsi.lock); ++ ++ return r; ++} ++ ++static int dsi_display_sync(struct omap_dss_device *dssdev) ++{ ++ bool wait; ++ ++ DSSDBG("dsi_display_sync()\n"); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL && ++ dsi.update_region.dirty) { ++ INIT_COMPLETION(dsi.update_completion); ++ wait = true; ++ } else { ++ wait = false; ++ } ++ ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ ++ if (wait) ++ wait_for_completion_interruptible(&dsi.update_completion); ++ ++ DSSDBG("dsi_display_sync() done\n"); ++ return 0; ++} ++ ++static int dsi_display_set_update_mode(struct omap_dss_device *dssdev, ++ enum omap_dss_update_mode mode) ++{ ++ DSSDBGF("%d", mode); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ if (dsi.update_mode != mode) { ++ dsi.user_update_mode = mode; ++ dsi.update_mode = mode; ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE && ++ mode == OMAP_DSS_UPDATE_AUTO) ++ dsi_start_auto_update(dssdev); ++ } ++ ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ ++ return 0; ++} ++ ++static enum omap_dss_update_mode dsi_display_get_update_mode( ++ struct omap_dss_device *dssdev) ++{ ++ return dsi.update_mode; ++} ++ ++ ++static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable) ++{ ++ int r = 0; ++ ++ DSSDBGF("%d", enable); ++ ++ if (!dssdev->driver->enable_te) ++ return -ENOENT; ++ ++ dsi_bus_lock(); ++ ++ dsi.te_enabled = enable; ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ goto end; ++ ++ r = dsi_set_te(dssdev, enable); ++end: ++ dsi_bus_unlock(); ++ ++ return r; ++} ++ ++static int dsi_display_get_te(struct omap_dss_device *dssdev) ++{ ++ return dsi.te_enabled; ++} ++ ++static int dsi_display_set_rotate(struct omap_dss_device *dssdev, u8 rotate) ++{ ++ ++ DSSDBGF("%d", rotate); ++ ++ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) ++ return -EINVAL; ++ ++ dsi_bus_lock(); ++ dssdev->driver->set_rotate(dssdev, rotate); ++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) { ++ u16 w, h; ++ /* the display dimensions may have changed, so set a new ++ * update region */ ++ dssdev->get_resolution(dssdev, &w, &h); ++ dsi_set_update_region(dssdev, 0, 0, w, h); ++ } ++ dsi_bus_unlock(); ++ ++ return 0; ++} ++ ++static u8 dsi_display_get_rotate(struct omap_dss_device *dssdev) ++{ ++ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) ++ return 0; ++ ++ return dssdev->driver->get_rotate(dssdev); ++} ++ ++static int dsi_display_set_mirror(struct omap_dss_device *dssdev, bool mirror) ++{ ++ DSSDBGF("%d", mirror); ++ ++ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) ++ return -EINVAL; ++ ++ dsi_bus_lock(); ++ dssdev->driver->set_mirror(dssdev, mirror); ++ dsi_bus_unlock(); ++ ++ return 0; ++} ++ ++static bool dsi_display_get_mirror(struct omap_dss_device *dssdev) ++{ ++ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) ++ return 0; ++ ++ return dssdev->driver->get_mirror(dssdev); ++} ++ ++static int dsi_display_run_test(struct omap_dss_device *dssdev, int test_num) ++{ ++ int r; ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ return -EIO; ++ ++ DSSDBGF("%d", test_num); ++ ++ dsi_bus_lock(); ++ ++ /* run test first in low speed mode */ ++ dsi_vc_enable_hs(0, 0); ++ ++ if (dssdev->driver->run_test) { ++ r = dssdev->driver->run_test(dssdev, test_num); ++ if (r) ++ goto end; ++ } ++ ++ /* then in high speed */ ++ dsi_vc_enable_hs(0, 1); ++ ++ if (dssdev->driver->run_test) { ++ r = dssdev->driver->run_test(dssdev, test_num); ++ if (r) ++ goto end; ++ } ++ ++end: ++ dsi_vc_enable_hs(0, 1); ++ ++ dsi_bus_unlock(); ++ ++ return r; ++} ++ ++static int dsi_display_memory_read(struct omap_dss_device *dssdev, ++ void *buf, size_t size, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ int r; ++ ++ DSSDBGF(""); ++ ++ if (!dssdev->driver->memory_read) ++ return -EINVAL; ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ return -EIO; ++ ++ dsi_bus_lock(); ++ ++ r = dssdev->driver->memory_read(dssdev, buf, size, ++ x, y, w, h); ++ ++ dsi_bus_unlock(); ++ ++ return r; ++} ++ ++void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, ++ u32 fifo_size, enum omap_burst_size *burst_size, ++ u32 *fifo_low, u32 *fifo_high) ++{ ++ unsigned burst_size_bytes; ++ ++ *burst_size = OMAP_DSS_BURST_16x32; ++ burst_size_bytes = 16 * 32 / 8; ++ ++ *fifo_high = fifo_size - burst_size_bytes; ++ *fifo_low = 0; ++} ++ ++int dsi_init_display(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("DSI init\n"); ++ ++ dssdev->enable = dsi_display_enable; ++ dssdev->disable = dsi_display_disable; ++ dssdev->suspend = dsi_display_suspend; ++ dssdev->resume = dsi_display_resume; ++ dssdev->update = dsi_display_update; ++ dssdev->sync = dsi_display_sync; ++ dssdev->set_update_mode = dsi_display_set_update_mode; ++ dssdev->get_update_mode = dsi_display_get_update_mode; ++ dssdev->enable_te = dsi_display_enable_te; ++ dssdev->get_te = dsi_display_get_te; ++ ++ dssdev->get_rotate = dsi_display_get_rotate; ++ dssdev->set_rotate = dsi_display_set_rotate; ++ ++ dssdev->get_mirror = dsi_display_get_mirror; ++ dssdev->set_mirror = dsi_display_set_mirror; ++ ++ dssdev->run_test = dsi_display_run_test; ++ dssdev->memory_read = dsi_display_memory_read; ++ ++ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; ++ ++ dsi.vc[0].dssdev = dssdev; ++ dsi.vc[1].dssdev = dssdev; ++ ++ return 0; ++} ++ ++int dsi_init(struct platform_device *pdev) ++{ ++ u32 rev; ++ struct sched_param param = { ++ .sched_priority = MAX_USER_RT_PRIO-1 ++ }; ++ ++ spin_lock_init(&dsi.errors_lock); ++ dsi.errors = 0; ++ ++ /* XXX fail properly */ ++ ++ init_completion(&dsi.bta_completion); ++ init_completion(&dsi.update_completion); ++ ++ dsi.thread = kthread_create(dsi_update_thread, NULL, "dsi"); ++ if (IS_ERR(dsi.thread)) { ++ DSSERR("cannot create kthread\n"); ++ return PTR_ERR(dsi.thread); ++ } ++ sched_setscheduler(dsi.thread, SCHED_FIFO, ¶m); ++ ++ init_waitqueue_head(&dsi.waitqueue); ++ spin_lock_init(&dsi.update_lock); ++ ++ mutex_init(&dsi.lock); ++ mutex_init(&dsi.bus_lock); ++ ++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED; ++ dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED; ++ ++ dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS); ++ if (!dsi.base) { ++ DSSERR("can't ioremap DSI\n"); ++ return -ENOMEM; ++ } ++ ++ dsi.vdds_dsi_reg = regulator_get(&pdev->dev, "vdds_dsi"); ++ if (IS_ERR(dsi.vdds_dsi_reg)) { ++ iounmap(dsi.base); ++ DSSERR("can't get VDDS_DSI regulator\n"); ++ return PTR_ERR(dsi.vdds_dsi_reg); ++ } ++ ++ enable_clocks(1); ++ ++ rev = dsi_read_reg(DSI_REVISION); ++ printk(KERN_INFO "OMAP DSI rev %d.%d\n", ++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); ++ ++ enable_clocks(0); ++ ++ wake_up_process(dsi.thread); ++ ++ return 0; ++} ++ ++void dsi_exit(void) ++{ ++ kthread_stop(dsi.thread); ++ ++ regulator_put(dsi.vdds_dsi_reg); ++ ++ iounmap(dsi.base); ++ ++ DSSDBG("omap_dsi_exit\n"); ++} ++ +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0015-OMAP-DSS2-omapfb-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0015-OMAP-DSS2-omapfb-driver.patch new file mode 100644 index 0000000000..a3ccb7499c --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0015-OMAP-DSS2-omapfb-driver.patch @@ -0,0 +1,3801 @@ +From 13656d59fba28e21311ae0478b6c222339367e72 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Tue, 4 Aug 2009 16:12:50 +0300 +Subject: [PATCH 15/18] OMAP: DSS2: omapfb driver + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + arch/arm/plat-omap/fb.c | 39 +- + drivers/video/omap/Kconfig | 5 +- + drivers/video/omap2/Kconfig | 1 + + drivers/video/omap2/Makefile | 1 + + drivers/video/omap2/omapfb/Kconfig | 37 + + drivers/video/omap2/omapfb/Makefile | 2 + + drivers/video/omap2/omapfb/omapfb-ioctl.c | 727 ++++++++++ + drivers/video/omap2/omapfb/omapfb-main.c | 2137 +++++++++++++++++++++++++++++ + drivers/video/omap2/omapfb/omapfb-sysfs.c | 507 +++++++ + drivers/video/omap2/omapfb/omapfb.h | 146 ++ + include/linux/omapfb.h | 45 + + 11 files changed, 3644 insertions(+), 3 deletions(-) + create mode 100644 drivers/video/omap2/omapfb/Kconfig + create mode 100644 drivers/video/omap2/omapfb/Makefile + create mode 100644 drivers/video/omap2/omapfb/omapfb-ioctl.c + create mode 100644 drivers/video/omap2/omapfb/omapfb-main.c + create mode 100644 drivers/video/omap2/omapfb/omapfb-sysfs.c + create mode 100644 drivers/video/omap2/omapfb/omapfb.h + +diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c +index 40615a6..70fbeae 100644 +--- a/arch/arm/plat-omap/fb.c ++++ b/arch/arm/plat-omap/fb.c +@@ -327,7 +327,33 @@ static inline int omap_init_fb(void) + + arch_initcall(omap_init_fb); + +-#else ++#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) ++ ++static u64 omap_fb_dma_mask = ~(u32)0; ++static struct omapfb_platform_data omapfb_config; ++ ++static struct platform_device omap_fb_device = { ++ .name = "omapfb", ++ .id = -1, ++ .dev = { ++ .dma_mask = &omap_fb_dma_mask, ++ .coherent_dma_mask = ~(u32)0, ++ .platform_data = &omapfb_config, ++ }, ++ .num_resources = 0, ++}; ++ ++void omapfb_set_platform_data(struct omapfb_platform_data *data) ++{ ++ omapfb_config = *data; ++} ++ ++static inline int omap_init_fb(void) ++{ ++ return platform_device_register(&omap_fb_device); ++} ++ ++arch_initcall(omap_init_fb); + + void omapfb_reserve_sdram(void) {} + unsigned long omapfb_reserve_sram(unsigned long sram_pstart, +@@ -339,5 +365,16 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart, + return 0; + } + ++#else ++ ++void omapfb_reserve_sdram(void) {} ++unsigned long omapfb_reserve_sram(unsigned long sram_pstart, ++ unsigned long sram_vstart, ++ unsigned long sram_size, ++ unsigned long start_avail, ++ unsigned long size_avail) ++{ ++ return 0; ++} + + #endif +diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig +index 4440885..0c8f3a5 100644 +--- a/drivers/video/omap/Kconfig ++++ b/drivers/video/omap/Kconfig +@@ -1,6 +1,7 @@ + config FB_OMAP + tristate "OMAP frame buffer support (EXPERIMENTAL)" +- depends on FB && ARCH_OMAP ++ depends on FB && ARCH_OMAP && (OMAP2_DSS = "n") ++ + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT +@@ -9,7 +10,7 @@ config FB_OMAP + + config FB_OMAP_BOOTLOADER_INIT + bool "Check bootloader initialization" +- depends on FB_OMAP ++ depends on FB_OMAP || FB_OMAP2 + help + Say Y here if you want to enable checking if the bootloader has + already initialized the display controller. In this case the +diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig +index 55b4c42..3e60d7e 100644 +--- a/drivers/video/omap2/Kconfig ++++ b/drivers/video/omap2/Kconfig +@@ -5,3 +5,4 @@ config OMAP2_VRFB + bool + + source "drivers/video/omap2/dss/Kconfig" ++source "drivers/video/omap2/omapfb/Kconfig" +diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile +index ee0644f..3ba6ef5 100644 +--- a/drivers/video/omap2/Makefile ++++ b/drivers/video/omap2/Makefile +@@ -2,3 +2,4 @@ obj-$(CONFIG_OMAP2_VRAM) += vram.o + obj-$(CONFIG_OMAP2_VRFB) += vrfb.o + + obj-y += dss/ ++obj-y += omapfb/ +diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig +new file mode 100644 +index 0000000..bb694cc +--- /dev/null ++++ b/drivers/video/omap2/omapfb/Kconfig +@@ -0,0 +1,37 @@ ++menuconfig FB_OMAP2 ++ tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)" ++ depends on FB && OMAP2_DSS ++ ++ select OMAP2_VRAM ++ select OMAP2_VRFB ++ select FB_CFB_FILLRECT ++ select FB_CFB_COPYAREA ++ select FB_CFB_IMAGEBLIT ++ help ++ Frame buffer driver for OMAP2/3 based boards. ++ ++config FB_OMAP2_DEBUG_SUPPORT ++ bool "Debug support for OMAP2/3 FB" ++ default y ++ depends on FB_OMAP2 ++ help ++ Support for debug output. You have to enable the actual printing ++ with debug module parameter. ++ ++config FB_OMAP2_FORCE_AUTO_UPDATE ++ bool "Force main display to automatic update mode" ++ depends on FB_OMAP2 ++ help ++ Forces main display to automatic update mode (if possible), ++ and also enables tearsync (if possible). By default ++ displays that support manual update are started in manual ++ update mode. ++ ++config FB_OMAP2_NUM_FBS ++ int "Number of framebuffers" ++ range 1 10 ++ default 3 ++ depends on FB_OMAP2 ++ help ++ Select the number of framebuffers created. OMAP2/3 has 3 overlays ++ so normally this would be 3. +diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/omap2/omapfb/Makefile +new file mode 100644 +index 0000000..51c2e00 +--- /dev/null ++++ b/drivers/video/omap2/omapfb/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_FB_OMAP2) += omapfb.o ++omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o +diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c +new file mode 100644 +index 0000000..70fb64e +--- /dev/null ++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c +@@ -0,0 +1,727 @@ ++/* ++ * linux/drivers/video/omap2/omapfb-ioctl.c ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/fb.h> ++#include <linux/device.h> ++#include <linux/uaccess.h> ++#include <linux/platform_device.h> ++#include <linux/mm.h> ++#include <linux/omapfb.h> ++#include <linux/vmalloc.h> ++ ++#include <mach/display.h> ++#include <mach/vrfb.h> ++#include <mach/vram.h> ++ ++#include "omapfb.h" ++ ++static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_dss_device *display = fb2display(fbi); ++ struct omap_overlay *ovl; ++ struct omap_overlay_info info; ++ int r = 0; ++ ++ DBG("omapfb_setup_plane\n"); ++ ++ if (ofbi->num_overlays != 1) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ /* XXX uses only the first overlay */ ++ ovl = ofbi->overlays[0]; ++ ++ if (pi->enabled && !ofbi->region.size) { ++ /* ++ * This plane's memory was freed, can't enable it ++ * until it's reallocated. ++ */ ++ r = -EINVAL; ++ goto out; ++ } ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ info.pos_x = pi->pos_x; ++ info.pos_y = pi->pos_y; ++ info.out_width = pi->out_width; ++ info.out_height = pi->out_height; ++ info.enabled = pi->enabled; ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) ++ goto out; ++ ++ if (ovl->manager) { ++ r = ovl->manager->apply(ovl->manager); ++ if (r) ++ goto out; ++ } ++ ++ if (display) { ++ u16 w, h; ++ ++ if (display->sync) ++ display->sync(display); ++ ++ display->get_resolution(display, &w, &h); ++ ++ if (display->update) ++ display->update(display, 0, 0, w, h); ++ } ++ ++out: ++ if (r) ++ dev_err(fbdev->dev, "setup_plane failed\n"); ++ return r; ++} ++ ++static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ if (ofbi->num_overlays != 1) { ++ memset(pi, 0, sizeof(*pi)); ++ } else { ++ struct omap_overlay_info *ovli; ++ struct omap_overlay *ovl; ++ ++ ovl = ofbi->overlays[0]; ++ ovli = &ovl->info; ++ ++ pi->pos_x = ovli->pos_x; ++ pi->pos_y = ovli->pos_y; ++ pi->enabled = ovli->enabled; ++ pi->channel_out = 0; /* xxx */ ++ pi->mirror = 0; ++ pi->out_width = ovli->out_width; ++ pi->out_height = ovli->out_height; ++ } ++ ++ return 0; ++} ++ ++static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omapfb2_mem_region *rg; ++ int r, i; ++ size_t size; ++ ++ if (mi->type > OMAPFB_MEMTYPE_MAX) ++ return -EINVAL; ++ ++ size = PAGE_ALIGN(mi->size); ++ ++ rg = &ofbi->region; ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ofbi->overlays[i]->info.enabled) ++ return -EBUSY; ++ } ++ ++ if (rg->size != size || rg->type != mi->type) { ++ r = omapfb_realloc_fbmem(fbi, size, mi->type); ++ if (r) { ++ dev_err(fbdev->dev, "realloc fbmem failed\n"); ++ return r; ++ } ++ } ++ ++ return 0; ++} ++ ++static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_mem_region *rg; ++ ++ rg = &ofbi->region; ++ memset(mi, 0, sizeof(*mi)); ++ ++ mi->size = rg->size; ++ mi->type = rg->type; ++ ++ return 0; ++} ++ ++static int omapfb_update_window(struct fb_info *fbi, ++ u32 x, u32 y, u32 w, u32 h) ++{ ++ struct omap_dss_device *display = fb2display(fbi); ++ u16 dw, dh; ++ ++ if (!display) ++ return 0; ++ ++ if (w == 0 || h == 0) ++ return 0; ++ ++ display->get_resolution(display, &dw, &dh); ++ ++ if (x + w > dw || y + h > dh) ++ return -EINVAL; ++ ++ display->update(display, x, y, w, h); ++ ++ return 0; ++} ++ ++static int omapfb_set_update_mode(struct fb_info *fbi, ++ enum omapfb_update_mode mode) ++{ ++ struct omap_dss_device *display = fb2display(fbi); ++ enum omap_dss_update_mode um; ++ int r; ++ ++ if (!display || !display->set_update_mode) ++ return -EINVAL; ++ ++ switch (mode) { ++ case OMAPFB_UPDATE_DISABLED: ++ um = OMAP_DSS_UPDATE_DISABLED; ++ break; ++ ++ case OMAPFB_AUTO_UPDATE: ++ um = OMAP_DSS_UPDATE_AUTO; ++ break; ++ ++ case OMAPFB_MANUAL_UPDATE: ++ um = OMAP_DSS_UPDATE_MANUAL; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ r = display->set_update_mode(display, um); ++ ++ return r; ++} ++ ++static int omapfb_get_update_mode(struct fb_info *fbi, ++ enum omapfb_update_mode *mode) ++{ ++ struct omap_dss_device *display = fb2display(fbi); ++ enum omap_dss_update_mode m; ++ ++ if (!display || !display->get_update_mode) ++ return -EINVAL; ++ ++ m = display->get_update_mode(display); ++ ++ switch (m) { ++ case OMAP_DSS_UPDATE_DISABLED: ++ *mode = OMAPFB_UPDATE_DISABLED; ++ break; ++ case OMAP_DSS_UPDATE_AUTO: ++ *mode = OMAPFB_AUTO_UPDATE; ++ break; ++ case OMAP_DSS_UPDATE_MANUAL: ++ *mode = OMAPFB_MANUAL_UPDATE; ++ break; ++ default: ++ BUG(); ++ } ++ ++ return 0; ++} ++ ++/* XXX this color key handling is a hack... */ ++static struct omapfb_color_key omapfb_color_keys[2]; ++ ++static int _omapfb_set_color_key(struct omap_overlay_manager *mgr, ++ struct omapfb_color_key *ck) ++{ ++ struct omap_overlay_manager_info info; ++ enum omap_dss_trans_key_type kt; ++ int r; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) { ++ info.trans_enabled = false; ++ omapfb_color_keys[mgr->id] = *ck; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ ++ return r; ++ } ++ ++ switch (ck->key_type) { ++ case OMAPFB_COLOR_KEY_GFX_DST: ++ kt = OMAP_DSS_COLOR_KEY_GFX_DST; ++ break; ++ case OMAPFB_COLOR_KEY_VID_SRC: ++ kt = OMAP_DSS_COLOR_KEY_VID_SRC; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ info.default_color = ck->background; ++ info.trans_key = ck->trans_key; ++ info.trans_key_type = kt; ++ info.trans_enabled = true; ++ ++ omapfb_color_keys[mgr->id] = *ck; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ ++ return r; ++} ++ ++static int omapfb_set_color_key(struct fb_info *fbi, ++ struct omapfb_color_key *ck) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ int r; ++ int i; ++ struct omap_overlay_manager *mgr = NULL; ++ ++ omapfb_lock(fbdev); ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ofbi->overlays[i]->manager) { ++ mgr = ofbi->overlays[i]->manager; ++ break; ++ } ++ } ++ ++ if (!mgr) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ r = _omapfb_set_color_key(mgr, ck); ++err: ++ omapfb_unlock(fbdev); ++ ++ return r; ++} ++ ++static int omapfb_get_color_key(struct fb_info *fbi, ++ struct omapfb_color_key *ck) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_overlay_manager *mgr = NULL; ++ int r = 0; ++ int i; ++ ++ omapfb_lock(fbdev); ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ofbi->overlays[i]->manager) { ++ mgr = ofbi->overlays[i]->manager; ++ break; ++ } ++ } ++ ++ if (!mgr) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ *ck = omapfb_color_keys[mgr->id]; ++err: ++ omapfb_unlock(fbdev); ++ ++ return r; ++} ++ ++static int omapfb_memory_read(struct fb_info *fbi, ++ struct omapfb_memory_read *mr) ++{ ++ struct omap_dss_device *display = fb2display(fbi); ++ void *buf; ++ int r; ++ ++ if (!display || !display->memory_read) ++ return -ENOENT; ++ ++ if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size)) ++ return -EFAULT; ++ ++ if (mr->w * mr->h * 3 > mr->buffer_size) ++ return -EINVAL; ++ ++ buf = vmalloc(mr->buffer_size); ++ if (!buf) { ++ DBG("vmalloc failed\n"); ++ return -ENOMEM; ++ } ++ ++ r = display->memory_read(display, buf, mr->buffer_size, ++ mr->x, mr->y, mr->w, mr->h); ++ ++ if (r > 0) { ++ if (copy_to_user(mr->buffer, buf, mr->buffer_size)) ++ r = -EFAULT; ++ } ++ ++ vfree(buf); ++ ++ return r; ++} ++ ++static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev, ++ struct omapfb_ovl_colormode *mode) ++{ ++ int ovl_idx = mode->overlay_idx; ++ int mode_idx = mode->mode_idx; ++ struct omap_overlay *ovl; ++ enum omap_color_mode supported_modes; ++ struct fb_var_screeninfo var; ++ int i; ++ ++ if (ovl_idx >= fbdev->num_overlays) ++ return -ENODEV; ++ ovl = fbdev->overlays[ovl_idx]; ++ supported_modes = ovl->supported_modes; ++ ++ mode_idx = mode->mode_idx; ++ ++ for (i = 0; i < sizeof(supported_modes) * 8; i++) { ++ if (!(supported_modes & (1 << i))) ++ continue; ++ /* ++ * It's possible that the FB doesn't support a mode ++ * that is supported by the overlay, so call the ++ * following here. ++ */ ++ if (dss_mode_to_fb_mode(1 << i, &var) < 0) ++ continue; ++ ++ mode_idx--; ++ if (mode_idx < 0) ++ break; ++ } ++ ++ if (i == sizeof(supported_modes) * 8) ++ return -ENOENT; ++ ++ mode->bits_per_pixel = var.bits_per_pixel; ++ mode->nonstd = var.nonstd; ++ mode->red = var.red; ++ mode->green = var.green; ++ mode->blue = var.blue; ++ mode->transp = var.transp; ++ ++ return 0; ++} ++ ++static int omapfb_wait_for_go(struct fb_info *fbi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ int r = 0; ++ int i; ++ ++ for (i = 0; i < ofbi->num_overlays; ++i) { ++ struct omap_overlay *ovl = ofbi->overlays[i]; ++ r = ovl->wait_for_go(ovl); ++ if (r) ++ break; ++ } ++ ++ return r; ++} ++ ++int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_dss_device *display = fb2display(fbi); ++ ++ union { ++ struct omapfb_update_window_old uwnd_o; ++ struct omapfb_update_window uwnd; ++ struct omapfb_plane_info plane_info; ++ struct omapfb_caps caps; ++ struct omapfb_mem_info mem_info; ++ struct omapfb_color_key color_key; ++ struct omapfb_ovl_colormode ovl_colormode; ++ enum omapfb_update_mode update_mode; ++ int test_num; ++ struct omapfb_memory_read memory_read; ++ struct omapfb_vram_info vram_info; ++ } p; ++ ++ int r = 0; ++ ++ switch (cmd) { ++ case OMAPFB_SYNC_GFX: ++ DBG("ioctl SYNC_GFX\n"); ++ if (!display || !display->sync) { ++ /* DSS1 never returns an error here, so we neither */ ++ /*r = -EINVAL;*/ ++ break; ++ } ++ ++ r = display->sync(display); ++ break; ++ ++ case OMAPFB_UPDATE_WINDOW_OLD: ++ DBG("ioctl UPDATE_WINDOW_OLD\n"); ++ if (!display || !display->update) { ++ r = -EINVAL; ++ break; ++ } ++ ++ if (copy_from_user(&p.uwnd_o, ++ (void __user *)arg, ++ sizeof(p.uwnd_o))) { ++ r = -EFAULT; ++ break; ++ } ++ ++ r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y, ++ p.uwnd_o.width, p.uwnd_o.height); ++ break; ++ ++ case OMAPFB_UPDATE_WINDOW: ++ DBG("ioctl UPDATE_WINDOW\n"); ++ if (!display || !display->update) { ++ r = -EINVAL; ++ break; ++ } ++ ++ if (copy_from_user(&p.uwnd, (void __user *)arg, ++ sizeof(p.uwnd))) { ++ r = -EFAULT; ++ break; ++ } ++ ++ r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y, ++ p.uwnd.width, p.uwnd.height); ++ break; ++ ++ case OMAPFB_SETUP_PLANE: ++ DBG("ioctl SETUP_PLANE\n"); ++ if (copy_from_user(&p.plane_info, (void __user *)arg, ++ sizeof(p.plane_info))) ++ r = -EFAULT; ++ else ++ r = omapfb_setup_plane(fbi, &p.plane_info); ++ break; ++ ++ case OMAPFB_QUERY_PLANE: ++ DBG("ioctl QUERY_PLANE\n"); ++ r = omapfb_query_plane(fbi, &p.plane_info); ++ if (r < 0) ++ break; ++ if (copy_to_user((void __user *)arg, &p.plane_info, ++ sizeof(p.plane_info))) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_SETUP_MEM: ++ DBG("ioctl SETUP_MEM\n"); ++ if (copy_from_user(&p.mem_info, (void __user *)arg, ++ sizeof(p.mem_info))) ++ r = -EFAULT; ++ else ++ r = omapfb_setup_mem(fbi, &p.mem_info); ++ break; ++ ++ case OMAPFB_QUERY_MEM: ++ DBG("ioctl QUERY_MEM\n"); ++ r = omapfb_query_mem(fbi, &p.mem_info); ++ if (r < 0) ++ break; ++ if (copy_to_user((void __user *)arg, &p.mem_info, ++ sizeof(p.mem_info))) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_GET_CAPS: ++ DBG("ioctl GET_CAPS\n"); ++ if (!display) { ++ r = -EINVAL; ++ break; ++ } ++ ++ memset(&p.caps, 0, sizeof(p.caps)); ++ p.caps.ctrl = display->caps; ++ ++ if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps))) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_GET_OVERLAY_COLORMODE: ++ DBG("ioctl GET_OVERLAY_COLORMODE\n"); ++ if (copy_from_user(&p.ovl_colormode, (void __user *)arg, ++ sizeof(p.ovl_colormode))) { ++ r = -EFAULT; ++ break; ++ } ++ r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode); ++ if (r < 0) ++ break; ++ if (copy_to_user((void __user *)arg, &p.ovl_colormode, ++ sizeof(p.ovl_colormode))) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_SET_UPDATE_MODE: ++ DBG("ioctl SET_UPDATE_MODE\n"); ++ if (get_user(p.update_mode, (int __user *)arg)) ++ r = -EFAULT; ++ else ++ r = omapfb_set_update_mode(fbi, p.update_mode); ++ break; ++ ++ case OMAPFB_GET_UPDATE_MODE: ++ DBG("ioctl GET_UPDATE_MODE\n"); ++ r = omapfb_get_update_mode(fbi, &p.update_mode); ++ if (r) ++ break; ++ if (put_user(p.update_mode, ++ (enum omapfb_update_mode __user *)arg)) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_SET_COLOR_KEY: ++ DBG("ioctl SET_COLOR_KEY\n"); ++ if (copy_from_user(&p.color_key, (void __user *)arg, ++ sizeof(p.color_key))) ++ r = -EFAULT; ++ else ++ r = omapfb_set_color_key(fbi, &p.color_key); ++ break; ++ ++ case OMAPFB_GET_COLOR_KEY: ++ DBG("ioctl GET_COLOR_KEY\n"); ++ r = omapfb_get_color_key(fbi, &p.color_key); ++ if (r) ++ break; ++ if (copy_to_user((void __user *)arg, &p.color_key, ++ sizeof(p.color_key))) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_WAITFORVSYNC: ++ DBG("ioctl WAITFORVSYNC\n"); ++ if (!display) { ++ r = -EINVAL; ++ break; ++ } ++ ++ r = display->wait_vsync(display); ++ break; ++ ++ case OMAPFB_WAITFORGO: ++ DBG("ioctl WAITFORGO\n"); ++ if (!display) { ++ r = -EINVAL; ++ break; ++ } ++ ++ r = omapfb_wait_for_go(fbi); ++ break; ++ ++ /* LCD and CTRL tests do the same thing for backward ++ * compatibility */ ++ case OMAPFB_LCD_TEST: ++ DBG("ioctl LCD_TEST\n"); ++ if (get_user(p.test_num, (int __user *)arg)) { ++ r = -EFAULT; ++ break; ++ } ++ if (!display || !display->run_test) { ++ r = -EINVAL; ++ break; ++ } ++ ++ r = display->run_test(display, p.test_num); ++ ++ break; ++ ++ case OMAPFB_CTRL_TEST: ++ DBG("ioctl CTRL_TEST\n"); ++ if (get_user(p.test_num, (int __user *)arg)) { ++ r = -EFAULT; ++ break; ++ } ++ if (!display || !display->run_test) { ++ r = -EINVAL; ++ break; ++ } ++ ++ r = display->run_test(display, p.test_num); ++ ++ break; ++ ++ case OMAPFB_MEMORY_READ: ++ DBG("ioctl MEMORY_READ\n"); ++ ++ if (copy_from_user(&p.memory_read, (void __user *)arg, ++ sizeof(p.memory_read))) { ++ r = -EFAULT; ++ break; ++ } ++ ++ r = omapfb_memory_read(fbi, &p.memory_read); ++ ++ break; ++ ++ case OMAPFB_GET_VRAM_INFO: { ++ unsigned long vram, free, largest; ++ ++ DBG("ioctl GET_VRAM_INFO\n"); ++ ++ omap_vram_get_info(&vram, &free, &largest); ++ p.vram_info.total = vram; ++ p.vram_info.free = free; ++ p.vram_info.largest_free_block = largest; ++ ++ if (copy_to_user((void __user *)arg, &p.vram_info, ++ sizeof(p.vram_info))) ++ r = -EFAULT; ++ break; ++ } ++ ++ default: ++ dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd); ++ r = -EINVAL; ++ } ++ ++ if (r < 0) ++ DBG("ioctl failed: %d\n", r); ++ ++ return r; ++} ++ ++ +diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c +new file mode 100644 +index 0000000..7f5ec3b +--- /dev/null ++++ b/drivers/video/omap2/omapfb/omapfb-main.c +@@ -0,0 +1,2137 @@ ++/* ++ * linux/drivers/video/omap2/omapfb-main.c ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/fb.h> ++#include <linux/dma-mapping.h> ++#include <linux/vmalloc.h> ++#include <linux/device.h> ++#include <linux/platform_device.h> ++#include <linux/omapfb.h> ++ ++#include <mach/display.h> ++#include <mach/vram.h> ++#include <mach/vrfb.h> ++ ++#include "omapfb.h" ++ ++#define MODULE_NAME "omapfb" ++ ++#define OMAPFB_PLANE_XRES_MIN 8 ++#define OMAPFB_PLANE_YRES_MIN 8 ++ ++static char *def_mode; ++static char *def_vram; ++static int def_vrfb; ++static int def_rotate; ++static int def_mirror; ++ ++#ifdef DEBUG ++unsigned int omapfb_debug; ++module_param_named(debug, omapfb_debug, bool, 0644); ++static unsigned int omapfb_test_pattern; ++module_param_named(test, omapfb_test_pattern, bool, 0644); ++#endif ++ ++static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi); ++ ++#ifdef DEBUG ++static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color) ++{ ++ struct fb_var_screeninfo *var = &fbi->var; ++ struct fb_fix_screeninfo *fix = &fbi->fix; ++ void __iomem *addr = fbi->screen_base; ++ const unsigned bytespp = var->bits_per_pixel >> 3; ++ const unsigned line_len = fix->line_length / bytespp; ++ ++ int r = (color >> 16) & 0xff; ++ int g = (color >> 8) & 0xff; ++ int b = (color >> 0) & 0xff; ++ ++ if (var->bits_per_pixel == 16) { ++ u16 __iomem *p = (u16 __iomem *)addr; ++ p += y * line_len + x; ++ ++ r = r * 32 / 256; ++ g = g * 64 / 256; ++ b = b * 32 / 256; ++ ++ __raw_writew((r << 11) | (g << 5) | (b << 0), p); ++ } else if (var->bits_per_pixel == 24) { ++ u8 __iomem *p = (u8 __iomem *)addr; ++ p += (y * line_len + x) * 3; ++ ++ __raw_writeb(b, p + 0); ++ __raw_writeb(g, p + 1); ++ __raw_writeb(r, p + 2); ++ } else if (var->bits_per_pixel == 32) { ++ u32 __iomem *p = (u32 __iomem *)addr; ++ p += y * line_len + x; ++ __raw_writel(color, p); ++ } ++} ++ ++static void fill_fb(struct fb_info *fbi) ++{ ++ struct fb_var_screeninfo *var = &fbi->var; ++ const short w = var->xres_virtual; ++ const short h = var->yres_virtual; ++ void __iomem *addr = fbi->screen_base; ++ int y, x; ++ ++ if (!addr) ++ return; ++ ++ DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length); ++ ++ for (y = 0; y < h; y++) { ++ for (x = 0; x < w; x++) { ++ if (x < 20 && y < 20) ++ draw_pixel(fbi, x, y, 0xffffff); ++ else if (x < 20 && (y > 20 && y < h - 20)) ++ draw_pixel(fbi, x, y, 0xff); ++ else if (y < 20 && (x > 20 && x < w - 20)) ++ draw_pixel(fbi, x, y, 0xff00); ++ else if (x > w - 20 && (y > 20 && y < h - 20)) ++ draw_pixel(fbi, x, y, 0xff0000); ++ else if (y > h - 20 && (x > 20 && x < w - 20)) ++ draw_pixel(fbi, x, y, 0xffff00); ++ else if (x == 20 || x == w - 20 || ++ y == 20 || y == h - 20) ++ draw_pixel(fbi, x, y, 0xffffff); ++ else if (x == y || w - x == h - y) ++ draw_pixel(fbi, x, y, 0xff00ff); ++ else if (w - x == y || x == h - y) ++ draw_pixel(fbi, x, y, 0x00ffff); ++ else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) { ++ int t = x * 3 / w; ++ unsigned r = 0, g = 0, b = 0; ++ unsigned c; ++ if (var->bits_per_pixel == 16) { ++ if (t == 0) ++ b = (y % 32) * 256 / 32; ++ else if (t == 1) ++ g = (y % 64) * 256 / 64; ++ else if (t == 2) ++ r = (y % 32) * 256 / 32; ++ } else { ++ if (t == 0) ++ b = (y % 256); ++ else if (t == 1) ++ g = (y % 256); ++ else if (t == 2) ++ r = (y % 256); ++ } ++ c = (r << 16) | (g << 8) | (b << 0); ++ draw_pixel(fbi, x, y, c); ++ } else { ++ draw_pixel(fbi, x, y, 0); ++ } ++ } ++ } ++} ++#endif ++ ++static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot) ++{ ++ struct vrfb *vrfb = &ofbi->region.vrfb; ++ unsigned offset; ++ ++ switch (rot) { ++ case FB_ROTATE_UR: ++ offset = 0; ++ break; ++ case FB_ROTATE_CW: ++ offset = vrfb->yoffset; ++ break; ++ case FB_ROTATE_UD: ++ offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset; ++ break; ++ case FB_ROTATE_CCW: ++ offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN; ++ break; ++ default: ++ BUG(); ++ } ++ ++ offset *= vrfb->bytespp; ++ ++ return offset; ++} ++ ++static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot) ++{ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ return ofbi->region.vrfb.paddr[rot] ++ + omapfb_get_vrfb_offset(ofbi, rot); ++ } else { ++ return ofbi->region.paddr; ++ } ++} ++ ++static u32 omapfb_get_region_paddr(struct omapfb_info *ofbi) ++{ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) ++ return ofbi->region.vrfb.paddr[0]; ++ else ++ return ofbi->region.paddr; ++} ++ ++static void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi) ++{ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) ++ return ofbi->region.vrfb.vaddr[0]; ++ else ++ return ofbi->region.vaddr; ++} ++ ++static struct omapfb_colormode omapfb_colormodes[] = { ++ { ++ .dssmode = OMAP_DSS_COLOR_UYVY, ++ .bits_per_pixel = 16, ++ .nonstd = OMAPFB_COLOR_YUV422, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_YUV2, ++ .bits_per_pixel = 16, ++ .nonstd = OMAPFB_COLOR_YUY422, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_ARGB16, ++ .bits_per_pixel = 16, ++ .red = { .length = 4, .offset = 8, .msb_right = 0 }, ++ .green = { .length = 4, .offset = 4, .msb_right = 0 }, ++ .blue = { .length = 4, .offset = 0, .msb_right = 0 }, ++ .transp = { .length = 4, .offset = 12, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_RGB16, ++ .bits_per_pixel = 16, ++ .red = { .length = 5, .offset = 11, .msb_right = 0 }, ++ .green = { .length = 6, .offset = 5, .msb_right = 0 }, ++ .blue = { .length = 5, .offset = 0, .msb_right = 0 }, ++ .transp = { .length = 0, .offset = 0, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_RGB24P, ++ .bits_per_pixel = 24, ++ .red = { .length = 8, .offset = 16, .msb_right = 0 }, ++ .green = { .length = 8, .offset = 8, .msb_right = 0 }, ++ .blue = { .length = 8, .offset = 0, .msb_right = 0 }, ++ .transp = { .length = 0, .offset = 0, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_RGB24U, ++ .bits_per_pixel = 32, ++ .red = { .length = 8, .offset = 16, .msb_right = 0 }, ++ .green = { .length = 8, .offset = 8, .msb_right = 0 }, ++ .blue = { .length = 8, .offset = 0, .msb_right = 0 }, ++ .transp = { .length = 0, .offset = 0, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_ARGB32, ++ .bits_per_pixel = 32, ++ .red = { .length = 8, .offset = 16, .msb_right = 0 }, ++ .green = { .length = 8, .offset = 8, .msb_right = 0 }, ++ .blue = { .length = 8, .offset = 0, .msb_right = 0 }, ++ .transp = { .length = 8, .offset = 24, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_RGBA32, ++ .bits_per_pixel = 32, ++ .red = { .length = 8, .offset = 24, .msb_right = 0 }, ++ .green = { .length = 8, .offset = 16, .msb_right = 0 }, ++ .blue = { .length = 8, .offset = 8, .msb_right = 0 }, ++ .transp = { .length = 8, .offset = 0, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_RGBX32, ++ .bits_per_pixel = 32, ++ .red = { .length = 8, .offset = 24, .msb_right = 0 }, ++ .green = { .length = 8, .offset = 16, .msb_right = 0 }, ++ .blue = { .length = 8, .offset = 8, .msb_right = 0 }, ++ .transp = { .length = 0, .offset = 0, .msb_right = 0 }, ++ }, ++}; ++ ++static bool cmp_var_to_colormode(struct fb_var_screeninfo *var, ++ struct omapfb_colormode *color) ++{ ++ bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2) ++ { ++ return f1->length == f2->length && ++ f1->offset == f2->offset && ++ f1->msb_right == f2->msb_right; ++ } ++ ++ if (var->bits_per_pixel == 0 || ++ var->red.length == 0 || ++ var->blue.length == 0 || ++ var->green.length == 0) ++ return 0; ++ ++ return var->bits_per_pixel == color->bits_per_pixel && ++ cmp_component(&var->red, &color->red) && ++ cmp_component(&var->green, &color->green) && ++ cmp_component(&var->blue, &color->blue) && ++ cmp_component(&var->transp, &color->transp); ++} ++ ++static void assign_colormode_to_var(struct fb_var_screeninfo *var, ++ struct omapfb_colormode *color) ++{ ++ var->bits_per_pixel = color->bits_per_pixel; ++ var->nonstd = color->nonstd; ++ var->red = color->red; ++ var->green = color->green; ++ var->blue = color->blue; ++ var->transp = color->transp; ++} ++ ++static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var) ++{ ++ enum omap_color_mode dssmode; ++ int i; ++ ++ /* first match with nonstd field */ ++ if (var->nonstd) { ++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { ++ struct omapfb_colormode *mode = &omapfb_colormodes[i]; ++ if (var->nonstd == mode->nonstd) { ++ assign_colormode_to_var(var, mode); ++ return mode->dssmode; ++ } ++ } ++ ++ return -EINVAL; ++ } ++ ++ /* then try exact match of bpp and colors */ ++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { ++ struct omapfb_colormode *mode = &omapfb_colormodes[i]; ++ if (cmp_var_to_colormode(var, mode)) { ++ assign_colormode_to_var(var, mode); ++ return mode->dssmode; ++ } ++ } ++ ++ /* match with bpp if user has not filled color fields ++ * properly */ ++ switch (var->bits_per_pixel) { ++ case 1: ++ dssmode = OMAP_DSS_COLOR_CLUT1; ++ break; ++ case 2: ++ dssmode = OMAP_DSS_COLOR_CLUT2; ++ break; ++ case 4: ++ dssmode = OMAP_DSS_COLOR_CLUT4; ++ break; ++ case 8: ++ dssmode = OMAP_DSS_COLOR_CLUT8; ++ break; ++ case 12: ++ dssmode = OMAP_DSS_COLOR_RGB12U; ++ break; ++ case 16: ++ dssmode = OMAP_DSS_COLOR_RGB16; ++ break; ++ case 24: ++ dssmode = OMAP_DSS_COLOR_RGB24P; ++ break; ++ case 32: ++ dssmode = OMAP_DSS_COLOR_RGB24U; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { ++ struct omapfb_colormode *mode = &omapfb_colormodes[i]; ++ if (dssmode == mode->dssmode) { ++ assign_colormode_to_var(var, mode); ++ return mode->dssmode; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++int dss_mode_to_fb_mode(enum omap_color_mode dssmode, ++ struct fb_var_screeninfo *var) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { ++ struct omapfb_colormode *mode = &omapfb_colormodes[i]; ++ if (dssmode == mode->dssmode) { ++ assign_colormode_to_var(var, mode); ++ return 0; ++ } ++ } ++ return -ENOENT; ++} ++ ++void set_fb_fix(struct fb_info *fbi) ++{ ++ struct fb_fix_screeninfo *fix = &fbi->fix; ++ struct fb_var_screeninfo *var = &fbi->var; ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_mem_region *rg = &ofbi->region; ++ ++ DBG("set_fb_fix\n"); ++ ++ /* used by open/write in fbmem.c */ ++ fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi); ++ ++ DBG("changing rotation to %d\n", var->rotate); ++ ++ /* used by mmap in fbmem.c */ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ switch (var->nonstd) { ++ case OMAPFB_COLOR_YUV422: ++ case OMAPFB_COLOR_YUY422: ++ fix->line_length = ++ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2; ++ break; ++ default: ++ fix->line_length = ++ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3; ++ break; ++ } ++ } else ++ fix->line_length = ++ (var->xres_virtual * var->bits_per_pixel) >> 3; ++ fix->smem_start = omapfb_get_region_paddr(ofbi); ++ fix->smem_len = rg->size; ++ ++ fix->type = FB_TYPE_PACKED_PIXELS; ++ ++ if (var->nonstd) ++ fix->visual = FB_VISUAL_PSEUDOCOLOR; ++ else { ++ switch (var->bits_per_pixel) { ++ case 32: ++ case 24: ++ case 16: ++ case 12: ++ fix->visual = FB_VISUAL_TRUECOLOR; ++ /* 12bpp is stored in 16 bits */ ++ break; ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ fix->visual = FB_VISUAL_PSEUDOCOLOR; ++ break; ++ } ++ } ++ ++ fix->accel = FB_ACCEL_NONE; ++ ++ fix->xpanstep = 1; ++ fix->ypanstep = 1; ++ ++ if (rg->size && ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ unsigned bytespp; ++ bool yuv_mode; ++ enum omap_color_mode mode; ++ ++ mode = fb_mode_to_dss_mode(var); ++ ++ bytespp = var->bits_per_pixel >> 3; ++ ++ if (mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY) ++ yuv_mode = true; ++ else ++ yuv_mode = false; ++ ++ omap_vrfb_setup(&rg->vrfb, rg->paddr, ++ var->xres_virtual, ++ var->yres_virtual, ++ bytespp, yuv_mode); ++ } ++} ++ ++/* check new var and possibly modify it to be ok */ ++int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omap_dss_device *display = fb2display(fbi); ++ unsigned long max_frame_size; ++ unsigned long line_size; ++ int xres_min, yres_min; ++ int xres_max, yres_max; ++ enum omap_color_mode mode = 0; ++ int i; ++ int bytespp; ++ ++ DBG("check_fb_var %d\n", ofbi->id); ++ ++ if (ofbi->region.size == 0) ++ return 0; ++ ++ mode = fb_mode_to_dss_mode(var); ++ if (mode < 0) { ++ DBG("cannot convert var to omap dss mode\n"); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < ofbi->num_overlays; ++i) { ++ if ((ofbi->overlays[i]->supported_modes & mode) == 0) { ++ DBG("invalid mode\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if (var->rotate < 0 || var->rotate > 3) ++ return -EINVAL; ++ ++ xres_min = OMAPFB_PLANE_XRES_MIN; ++ xres_max = 2048; ++ yres_min = OMAPFB_PLANE_YRES_MIN; ++ yres_max = 2048; ++ ++ bytespp = var->bits_per_pixel >> 3; ++ ++ /* XXX: some applications seem to set virtual res to 0. */ ++ if (var->xres_virtual == 0) ++ var->xres_virtual = var->xres; ++ ++ if (var->yres_virtual == 0) ++ var->yres_virtual = var->yres; ++ ++ if (var->xres_virtual < xres_min || var->yres_virtual < yres_min) ++ return -EINVAL; ++ ++ if (var->xres < xres_min) ++ var->xres = xres_min; ++ if (var->yres < yres_min) ++ var->yres = yres_min; ++ if (var->xres > xres_max) ++ var->xres = xres_max; ++ if (var->yres > yres_max) ++ var->yres = yres_max; ++ ++ if (var->xres > var->xres_virtual) ++ var->xres = var->xres_virtual; ++ if (var->yres > var->yres_virtual) ++ var->yres = var->yres_virtual; ++ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) ++ line_size = OMAP_VRFB_LINE_LEN * bytespp; ++ else ++ line_size = var->xres_virtual * bytespp; ++ ++ max_frame_size = ofbi->region.size; ++ ++ DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size); ++ ++ if (line_size * var->yres_virtual > max_frame_size) { ++ DBG("can't fit FB into memory, reducing y\n"); ++ var->yres_virtual = max_frame_size / line_size; ++ ++ if (var->yres_virtual < yres_min) ++ var->yres_virtual = yres_min; ++ ++ if (var->yres > var->yres_virtual) ++ var->yres = var->yres_virtual; ++ } ++ ++ if (line_size * var->yres_virtual > max_frame_size) { ++ DBG("can't fit FB into memory, reducing x\n"); ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) ++ return -EINVAL; ++ ++ var->xres_virtual = max_frame_size / var->yres_virtual / ++ bytespp; ++ ++ if (var->xres_virtual < xres_min) ++ var->xres_virtual = xres_min; ++ ++ if (var->xres > var->xres_virtual) ++ var->xres = var->xres_virtual; ++ ++ line_size = var->xres_virtual * bytespp; ++ } ++ ++ if (line_size * var->yres_virtual > max_frame_size) { ++ DBG("cannot fit FB to memory\n"); ++ return -EINVAL; ++ } ++ ++ if (var->xres + var->xoffset > var->xres_virtual) ++ var->xoffset = var->xres_virtual - var->xres; ++ if (var->yres + var->yoffset > var->yres_virtual) ++ var->yoffset = var->yres_virtual - var->yres; ++ ++ DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n", ++ var->xres, var->yres, ++ var->xres_virtual, var->yres_virtual); ++ ++ var->height = -1; ++ var->width = -1; ++ var->grayscale = 0; ++ ++ if (display && display->get_timings) { ++ struct omap_video_timings timings; ++ display->get_timings(display, &timings); ++ ++ /* pixclock in ps, the rest in pixclock */ ++ var->pixclock = timings.pixel_clock != 0 ? ++ KHZ2PICOS(timings.pixel_clock) : ++ 0; ++ var->left_margin = timings.hfp; ++ var->right_margin = timings.hbp; ++ var->upper_margin = timings.vfp; ++ var->lower_margin = timings.vbp; ++ var->hsync_len = timings.hsw; ++ var->vsync_len = timings.vsw; ++ } else { ++ var->pixclock = 0; ++ var->left_margin = 0; ++ var->right_margin = 0; ++ var->upper_margin = 0; ++ var->lower_margin = 0; ++ var->hsync_len = 0; ++ var->vsync_len = 0; ++ } ++ ++ /* TODO: get these from panel->config */ ++ var->vmode = FB_VMODE_NONINTERLACED; ++ var->sync = 0; ++ ++ return 0; ++} ++ ++/* ++ * --------------------------------------------------------------------------- ++ * fbdev framework callbacks ++ * --------------------------------------------------------------------------- ++ */ ++static int omapfb_open(struct fb_info *fbi, int user) ++{ ++ return 0; ++} ++ ++static int omapfb_release(struct fb_info *fbi, int user) ++{ ++#if 0 ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_dss_device *display = fb2display(fbi); ++ ++ DBG("Closing fb with plane index %d\n", ofbi->id); ++ ++ omapfb_lock(fbdev); ++ ++ if (display && display->get_update_mode && display->update) { ++ /* XXX this update should be removed, I think. But it's ++ * good for debugging */ ++ if (display->get_update_mode(display) == ++ OMAP_DSS_UPDATE_MANUAL) { ++ u16 w, h; ++ ++ if (display->sync) ++ display->sync(display); ++ ++ display->get_resolution(display, &w, &h); ++ display->update(display, 0, 0, w, h); ++ } ++ } ++ ++ if (display && display->sync) ++ display->sync(display); ++ ++ omapfb_unlock(fbdev); ++#endif ++ return 0; ++} ++ ++/* setup overlay according to the fb */ ++static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, ++ u16 posx, u16 posy, u16 outw, u16 outh) ++{ ++ int r = 0; ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct fb_var_screeninfo *var = &fbi->var; ++ struct fb_fix_screeninfo *fix = &fbi->fix; ++ enum omap_color_mode mode = 0; ++ int offset; ++ u32 data_start_p; ++ void __iomem *data_start_v; ++ struct omap_overlay_info info; ++ int xres, yres; ++ int screen_width; ++ int mirror; ++ int rotation = var->rotate; ++ int i; ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ovl != ofbi->overlays[i]) ++ continue; ++ ++ rotation = (rotation + ofbi->rotation[i]) % 4; ++ break; ++ } ++ ++ DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id, ++ posx, posy, outw, outh); ++ ++ if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) { ++ xres = var->yres; ++ yres = var->xres; ++ } else { ++ xres = var->xres; ++ yres = var->yres; ++ } ++ ++ offset = ((var->yoffset * var->xres_virtual + ++ var->xoffset) * var->bits_per_pixel) >> 3; ++ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); ++ data_start_v = NULL; ++ } else { ++ data_start_p = omapfb_get_region_paddr(ofbi); ++ data_start_v = omapfb_get_region_vaddr(ofbi); ++ } ++ ++ data_start_p += offset; ++ data_start_v += offset; ++ ++ mode = fb_mode_to_dss_mode(var); ++ ++ if (mode == -EINVAL) { ++ DBG("fb_mode_to_dss_mode failed"); ++ r = -EINVAL; ++ goto err; ++ } ++ ++ switch (var->nonstd) { ++ case OMAPFB_COLOR_YUV422: ++ case OMAPFB_COLOR_YUY422: ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ screen_width = fix->line_length ++ / (var->bits_per_pixel >> 2); ++ break; ++ } ++ default: ++ screen_width = fix->line_length / (var->bits_per_pixel >> 3); ++ break; ++ } ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) ++ mirror = 0; ++ else ++ mirror = ofbi->mirror; ++ ++ info.paddr = data_start_p; ++ info.vaddr = data_start_v; ++ info.screen_width = screen_width; ++ info.width = xres; ++ info.height = yres; ++ info.color_mode = mode; ++ info.rotation_type = ofbi->rotation_type; ++ info.rotation = rotation; ++ info.mirror = mirror; ++ ++ info.pos_x = posx; ++ info.pos_y = posy; ++ info.out_width = outw; ++ info.out_height = outh; ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) { ++ DBG("ovl->setup_overlay_info failed\n"); ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ DBG("setup_overlay failed\n"); ++ return r; ++} ++ ++/* apply var to the overlay */ ++int omapfb_apply_changes(struct fb_info *fbi, int init) ++{ ++ int r = 0; ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct fb_var_screeninfo *var = &fbi->var; ++ struct omap_overlay *ovl; ++ u16 posx, posy; ++ u16 outw, outh; ++ int i; ++ ++#ifdef DEBUG ++ if (omapfb_test_pattern) ++ fill_fb(fbi); ++#endif ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ ovl = ofbi->overlays[i]; ++ ++ DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); ++ ++ if (ofbi->region.size == 0) { ++ /* the fb is not available. disable the overlay */ ++ omapfb_overlay_enable(ovl, 0); ++ if (!init && ovl->manager) ++ ovl->manager->apply(ovl->manager); ++ continue; ++ } ++ ++ if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { ++ int rotation = (var->rotate + ofbi->rotation[i]) % 4; ++ if (rotation == FB_ROTATE_CW || ++ rotation == FB_ROTATE_CCW) { ++ outw = var->yres; ++ outh = var->xres; ++ } else { ++ outw = var->xres; ++ outh = var->yres; ++ } ++ } else { ++ outw = ovl->info.out_width; ++ outh = ovl->info.out_height; ++ } ++ ++ if (init) { ++ posx = 0; ++ posy = 0; ++ } else { ++ posx = ovl->info.pos_x; ++ posy = ovl->info.pos_y; ++ } ++ ++ r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh); ++ if (r) ++ goto err; ++ ++ if (!init && ovl->manager) ++ ovl->manager->apply(ovl->manager); ++ } ++ return 0; ++err: ++ DBG("apply_changes failed\n"); ++ return r; ++} ++ ++/* checks var and eventually tweaks it to something supported, ++ * DO NOT MODIFY PAR */ ++static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) ++{ ++ int r; ++ ++ DBG("check_var(%d)\n", FB2OFB(fbi)->id); ++ ++ r = check_fb_var(fbi, var); ++ ++ return r; ++} ++ ++/* set the video mode according to info->var */ ++static int omapfb_set_par(struct fb_info *fbi) ++{ ++ int r; ++ ++ DBG("set_par(%d)\n", FB2OFB(fbi)->id); ++ ++ set_fb_fix(fbi); ++ r = omapfb_apply_changes(fbi, 0); ++ ++ return r; ++} ++ ++static int omapfb_pan_display(struct fb_var_screeninfo *var, ++ struct fb_info *fbi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ int r = 0; ++ ++ DBG("pan_display(%d)\n", ofbi->id); ++ ++ if (var->xoffset != fbi->var.xoffset || ++ var->yoffset != fbi->var.yoffset) { ++ struct fb_var_screeninfo new_var; ++ ++ new_var = fbi->var; ++ new_var.xoffset = var->xoffset; ++ new_var.yoffset = var->yoffset; ++ ++ r = check_fb_var(fbi, &new_var); ++ ++ if (r == 0) { ++ fbi->var = new_var; ++ set_fb_fix(fbi); ++ r = omapfb_apply_changes(fbi, 0); ++ } ++ } ++ ++ return r; ++} ++ ++static void mmap_user_open(struct vm_area_struct *vma) ++{ ++ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; ++ ++ atomic_inc(&ofbi->map_count); ++} ++ ++static void mmap_user_close(struct vm_area_struct *vma) ++{ ++ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; ++ ++ atomic_dec(&ofbi->map_count); ++} ++ ++static struct vm_operations_struct mmap_user_ops = { ++ .open = mmap_user_open, ++ .close = mmap_user_close, ++}; ++ ++static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct fb_fix_screeninfo *fix = &fbi->fix; ++ unsigned long off; ++ unsigned long start; ++ u32 len; ++ ++ if (vma->vm_end - vma->vm_start == 0) ++ return 0; ++ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) ++ return -EINVAL; ++ off = vma->vm_pgoff << PAGE_SHIFT; ++ ++ start = omapfb_get_region_paddr(ofbi); ++ len = fix->smem_len; ++ if (off >= len) ++ return -EINVAL; ++ if ((vma->vm_end - vma->vm_start + off) > len) ++ return -EINVAL; ++ ++ off += start; ++ ++ DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off); ++ ++ vma->vm_pgoff = off >> PAGE_SHIFT; ++ vma->vm_flags |= VM_IO | VM_RESERVED; ++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); ++ vma->vm_ops = &mmap_user_ops; ++ vma->vm_private_data = ofbi; ++ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, ++ vma->vm_end - vma->vm_start, vma->vm_page_prot)) ++ return -EAGAIN; ++ /* vm_ops.open won't be called for mmap itself. */ ++ atomic_inc(&ofbi->map_count); ++ return 0; ++} ++ ++/* Store a single color palette entry into a pseudo palette or the hardware ++ * palette if one is available. For now we support only 16bpp and thus store ++ * the entry only to the pseudo palette. ++ */ ++static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green, ++ u_int blue, u_int transp, int update_hw_pal) ++{ ++ /*struct omapfb_info *ofbi = FB2OFB(fbi);*/ ++ /*struct omapfb2_device *fbdev = ofbi->fbdev;*/ ++ struct fb_var_screeninfo *var = &fbi->var; ++ int r = 0; ++ ++ enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */ ++ ++ /*switch (plane->color_mode) {*/ ++ switch (mode) { ++ case OMAPFB_COLOR_YUV422: ++ case OMAPFB_COLOR_YUV420: ++ case OMAPFB_COLOR_YUY422: ++ r = -EINVAL; ++ break; ++ case OMAPFB_COLOR_CLUT_8BPP: ++ case OMAPFB_COLOR_CLUT_4BPP: ++ case OMAPFB_COLOR_CLUT_2BPP: ++ case OMAPFB_COLOR_CLUT_1BPP: ++ /* ++ if (fbdev->ctrl->setcolreg) ++ r = fbdev->ctrl->setcolreg(regno, red, green, blue, ++ transp, update_hw_pal); ++ */ ++ /* Fallthrough */ ++ r = -EINVAL; ++ break; ++ case OMAPFB_COLOR_RGB565: ++ case OMAPFB_COLOR_RGB444: ++ case OMAPFB_COLOR_RGB24P: ++ case OMAPFB_COLOR_RGB24U: ++ if (r != 0) ++ break; ++ ++ if (regno < 0) { ++ r = -EINVAL; ++ break; ++ } ++ ++ if (regno < 16) { ++ u16 pal; ++ pal = ((red >> (16 - var->red.length)) << ++ var->red.offset) | ++ ((green >> (16 - var->green.length)) << ++ var->green.offset) | ++ (blue >> (16 - var->blue.length)); ++ ((u32 *)(fbi->pseudo_palette))[regno] = pal; ++ } ++ break; ++ default: ++ BUG(); ++ } ++ return r; ++} ++ ++static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ++ u_int transp, struct fb_info *info) ++{ ++ DBG("setcolreg\n"); ++ ++ return _setcolreg(info, regno, red, green, blue, transp, 1); ++} ++ ++static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) ++{ ++ int count, index, r; ++ u16 *red, *green, *blue, *transp; ++ u16 trans = 0xffff; ++ ++ DBG("setcmap\n"); ++ ++ red = cmap->red; ++ green = cmap->green; ++ blue = cmap->blue; ++ transp = cmap->transp; ++ index = cmap->start; ++ ++ for (count = 0; count < cmap->len; count++) { ++ if (transp) ++ trans = *transp++; ++ r = _setcolreg(info, index++, *red++, *green++, *blue++, trans, ++ count == cmap->len - 1); ++ if (r != 0) ++ return r; ++ } ++ ++ return 0; ++} ++ ++static void omapfb_vrfb_suspend_all(struct omapfb2_device *fbdev) ++{ ++ int i; ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); ++ ++ if (ofbi->region.vrfb.vaddr[0]) ++ omap_vrfb_suspend_ctx(&ofbi->region.vrfb); ++ } ++} ++ ++static void omapfb_vrfb_resume_all(struct omapfb2_device *fbdev) ++{ ++ int i; ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); ++ ++ if (ofbi->region.vrfb.vaddr[0]) ++ omap_vrfb_resume_ctx(&ofbi->region.vrfb); ++ } ++} ++ ++static int omapfb_blank(int blank, struct fb_info *fbi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_dss_device *display = fb2display(fbi); ++ int do_update = 0; ++ int r = 0; ++ ++ omapfb_lock(fbdev); ++ ++ switch (blank) { ++ case FB_BLANK_UNBLANK: ++ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) ++ goto exit; ++ ++ omapfb_vrfb_resume_all(fbdev); ++ ++ if (display->resume) ++ r = display->resume(display); ++ ++ if (r == 0 && display->get_update_mode && ++ display->get_update_mode(display) == ++ OMAP_DSS_UPDATE_MANUAL) ++ do_update = 1; ++ ++ break; ++ ++ case FB_BLANK_NORMAL: ++ /* FB_BLANK_NORMAL could be implemented. ++ * Needs DSS additions. */ ++ case FB_BLANK_VSYNC_SUSPEND: ++ case FB_BLANK_HSYNC_SUSPEND: ++ case FB_BLANK_POWERDOWN: ++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE) ++ goto exit; ++ ++ if (display->suspend) ++ r = display->suspend(display); ++ ++ omapfb_vrfb_suspend_all(fbdev); ++ ++ break; ++ ++ default: ++ r = -EINVAL; ++ } ++ ++exit: ++ omapfb_unlock(fbdev); ++ ++ if (r == 0 && do_update && display->update) { ++ u16 w, h; ++ display->get_resolution(display, &w, &h); ++ ++ r = display->update(display, 0, 0, w, h); ++ } ++ ++ return r; ++} ++ ++#if 0 ++/* XXX fb_read and fb_write are needed for VRFB */ ++ssize_t omapfb_write(struct fb_info *info, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos); ++ /* XXX needed for VRFB */ ++ return count; ++} ++#endif ++ ++static struct fb_ops omapfb_ops = { ++ .owner = THIS_MODULE, ++ .fb_open = omapfb_open, ++ .fb_release = omapfb_release, ++ .fb_fillrect = cfb_fillrect, ++ .fb_copyarea = cfb_copyarea, ++ .fb_imageblit = cfb_imageblit, ++ .fb_blank = omapfb_blank, ++ .fb_ioctl = omapfb_ioctl, ++ .fb_check_var = omapfb_check_var, ++ .fb_set_par = omapfb_set_par, ++ .fb_pan_display = omapfb_pan_display, ++ .fb_mmap = omapfb_mmap, ++ .fb_setcolreg = omapfb_setcolreg, ++ .fb_setcmap = omapfb_setcmap, ++ /*.fb_write = omapfb_write,*/ ++}; ++ ++static void omapfb_free_fbmem(struct fb_info *fbi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omapfb2_mem_region *rg; ++ ++ rg = &ofbi->region; ++ ++ if (rg->paddr) ++ if (omap_vram_free(rg->paddr, rg->size)) ++ dev_err(fbdev->dev, "VRAM FREE failed\n"); ++ ++ if (rg->vaddr) ++ iounmap(rg->vaddr); ++ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ /* unmap the 0 angle rotation */ ++ if (rg->vrfb.vaddr[0]) { ++ iounmap(rg->vrfb.vaddr[0]); ++ omap_vrfb_release_ctx(&rg->vrfb); ++ } ++ } ++ ++ rg->vaddr = NULL; ++ rg->paddr = 0; ++ rg->alloc = 0; ++ rg->size = 0; ++} ++ ++static void clear_fb_info(struct fb_info *fbi) ++{ ++ memset(&fbi->var, 0, sizeof(fbi->var)); ++ memset(&fbi->fix, 0, sizeof(fbi->fix)); ++ strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id)); ++} ++ ++static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev) ++{ ++ int i; ++ ++ DBG("free all fbmem\n"); ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ struct fb_info *fbi = fbdev->fbs[i]; ++ omapfb_free_fbmem(fbi); ++ clear_fb_info(fbi); ++ } ++ ++ return 0; ++} ++ ++static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size, ++ unsigned long paddr) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omapfb2_mem_region *rg; ++ void __iomem *vaddr; ++ int r; ++ ++ rg = &ofbi->region; ++ memset(rg, 0, sizeof(*rg)); ++ ++ size = PAGE_ALIGN(size); ++ ++ if (!paddr) { ++ DBG("allocating %lu bytes for fb %d\n", size, ofbi->id); ++ r = omap_vram_alloc(OMAP_VRAM_MEMTYPE_SDRAM, size, &paddr); ++ } else { ++ DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr, ++ ofbi->id); ++ r = omap_vram_reserve(paddr, size); ++ } ++ ++ if (r) { ++ dev_err(fbdev->dev, "failed to allocate framebuffer\n"); ++ return -ENOMEM; ++ } ++ ++ if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) { ++ vaddr = ioremap_wc(paddr, size); ++ ++ if (!vaddr) { ++ dev_err(fbdev->dev, "failed to ioremap framebuffer\n"); ++ omap_vram_free(paddr, size); ++ return -ENOMEM; ++ } ++ ++ DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr); ++ } else { ++ void __iomem *va; ++ ++ r = omap_vrfb_request_ctx(&rg->vrfb); ++ if (r) { ++ dev_err(fbdev->dev, "vrfb create ctx failed\n"); ++ return r; ++ } ++ ++ /* only ioremap the 0 angle view */ ++ va = ioremap_wc(rg->vrfb.paddr[0], size); ++ ++ if (!va) { ++ printk(KERN_ERR "vrfb: ioremap failed\n"); ++ omap_vrfb_release_ctx(&rg->vrfb); ++ return -ENOMEM; ++ } ++ ++ DBG("ioremapped vrfb area 0 to %p\n", va); ++ ++ rg->vrfb.vaddr[0] = va; ++ ++ vaddr = NULL; ++ } ++ ++ rg->paddr = paddr; ++ rg->vaddr = vaddr; ++ rg->size = size; ++ rg->alloc = 1; ++ ++ return 0; ++} ++ ++/* allocate fbmem using display resolution as reference */ ++static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size, ++ unsigned long paddr) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omap_dss_device *display; ++ int bytespp; ++ ++ display = fb2display(fbi); ++ ++ if (!display) ++ return 0; ++ ++ switch (display->get_recommended_bpp(display)) { ++ case 16: ++ bytespp = 2; ++ break; ++ case 24: ++ bytespp = 4; ++ break; ++ default: ++ bytespp = 4; ++ break; ++ } ++ ++ if (!size) { ++ u16 w, h; ++ ++ display->get_resolution(display, &w, &h); ++ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++#ifdef DEBUG ++ int oldw = w, oldh = h; ++#endif ++ ++ omap_vrfb_adjust_size(&w, &h, bytespp); ++ ++ /* Because we change the resolution of the 0 degree ++ * view, we need to alloc max(w, h) for height */ ++ h = max(w, h); ++ w = OMAP_VRFB_LINE_LEN; ++ ++ DBG("adjusting fb mem size for VRFB, %dx%d -> %dx%d\n", ++ oldw, oldh, w, h); ++ } ++ ++ size = w * h * bytespp; ++ } ++ ++ if (!size) ++ return 0; ++ ++ return omapfb_alloc_fbmem(fbi, size, paddr); ++} ++ ++static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt) ++{ ++ enum omap_color_mode mode; ++ ++ switch (fmt) { ++ case OMAPFB_COLOR_RGB565: ++ mode = OMAP_DSS_COLOR_RGB16; ++ break; ++ case OMAPFB_COLOR_YUV422: ++ mode = OMAP_DSS_COLOR_YUV2; ++ break; ++ case OMAPFB_COLOR_CLUT_8BPP: ++ mode = OMAP_DSS_COLOR_CLUT8; ++ break; ++ case OMAPFB_COLOR_CLUT_4BPP: ++ mode = OMAP_DSS_COLOR_CLUT4; ++ break; ++ case OMAPFB_COLOR_CLUT_2BPP: ++ mode = OMAP_DSS_COLOR_CLUT2; ++ break; ++ case OMAPFB_COLOR_CLUT_1BPP: ++ mode = OMAP_DSS_COLOR_CLUT1; ++ break; ++ case OMAPFB_COLOR_RGB444: ++ mode = OMAP_DSS_COLOR_RGB12U; ++ break; ++ case OMAPFB_COLOR_YUY422: ++ mode = OMAP_DSS_COLOR_UYVY; ++ break; ++ case OMAPFB_COLOR_ARGB16: ++ mode = OMAP_DSS_COLOR_ARGB16; ++ break; ++ case OMAPFB_COLOR_RGB24U: ++ mode = OMAP_DSS_COLOR_RGB24U; ++ break; ++ case OMAPFB_COLOR_RGB24P: ++ mode = OMAP_DSS_COLOR_RGB24P; ++ break; ++ case OMAPFB_COLOR_ARGB32: ++ mode = OMAP_DSS_COLOR_ARGB32; ++ break; ++ case OMAPFB_COLOR_RGBA32: ++ mode = OMAP_DSS_COLOR_RGBA32; ++ break; ++ case OMAPFB_COLOR_RGBX32: ++ mode = OMAP_DSS_COLOR_RGBX32; ++ break; ++ default: ++ mode = -EINVAL; ++ } ++ ++ return mode; ++} ++ ++static int omapfb_parse_vram_param(const char *param, int max_entries, ++ unsigned long *sizes, unsigned long *paddrs) ++{ ++ int fbnum; ++ unsigned long size; ++ unsigned long paddr = 0; ++ char *p, *start; ++ ++ start = (char *)param; ++ ++ while (1) { ++ p = start; ++ ++ fbnum = simple_strtoul(p, &p, 10); ++ ++ if (p == param) ++ return -EINVAL; ++ ++ if (*p != ':') ++ return -EINVAL; ++ ++ if (fbnum >= max_entries) ++ return -EINVAL; ++ ++ size = memparse(p + 1, &p); ++ ++ if (!size) ++ return -EINVAL; ++ ++ paddr = 0; ++ ++ if (*p == '@') { ++ paddr = simple_strtoul(p + 1, &p, 16); ++ ++ if (!paddr) ++ return -EINVAL; ++ ++ } ++ ++ paddrs[fbnum] = paddr; ++ sizes[fbnum] = size; ++ ++ if (*p == 0) ++ break; ++ ++ if (*p != ',') ++ return -EINVAL; ++ ++ ++p; ++ ++ start = p; ++ } ++ ++ return 0; ++} ++ ++static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev) ++{ ++ int i, r; ++ unsigned long vram_sizes[10]; ++ unsigned long vram_paddrs[10]; ++ ++ memset(&vram_sizes, 0, sizeof(vram_sizes)); ++ memset(&vram_paddrs, 0, sizeof(vram_paddrs)); ++ ++ if (def_vram && omapfb_parse_vram_param(def_vram, 10, ++ vram_sizes, vram_paddrs)) { ++ dev_err(fbdev->dev, "failed to parse vram parameter\n"); ++ ++ memset(&vram_sizes, 0, sizeof(vram_sizes)); ++ memset(&vram_paddrs, 0, sizeof(vram_paddrs)); ++ } ++ ++ if (fbdev->dev->platform_data) { ++ struct omapfb_platform_data *opd; ++ opd = fbdev->dev->platform_data; ++ for (i = 0; i < opd->mem_desc.region_cnt; ++i) { ++ if (!vram_sizes[i]) { ++ unsigned long size; ++ unsigned long paddr; ++ ++ size = opd->mem_desc.region[i].size; ++ paddr = opd->mem_desc.region[i].paddr; ++ ++ vram_sizes[i] = size; ++ vram_paddrs[i] = paddr; ++ } ++ } ++ } ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ /* allocate memory automatically only for fb0, or if ++ * excplicitly defined with vram or plat data option */ ++ if (i == 0 || vram_sizes[i] != 0) { ++ r = omapfb_alloc_fbmem_display(fbdev->fbs[i], ++ vram_sizes[i], vram_paddrs[i]); ++ ++ if (r) ++ return r; ++ } ++ } ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); ++ struct omapfb2_mem_region *rg; ++ rg = &ofbi->region; ++ ++ DBG("region%d phys %08x virt %p size=%lu\n", ++ i, ++ rg->paddr, ++ rg->vaddr, ++ rg->size); ++ } ++ ++ return 0; ++} ++ ++int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_dss_device *display = fb2display(fbi); ++ struct omapfb2_mem_region *rg = &ofbi->region; ++ unsigned long old_size = rg->size; ++ unsigned long old_paddr = rg->paddr; ++ int old_type = rg->type; ++ int r; ++ ++ if (type > OMAPFB_MEMTYPE_MAX) ++ return -EINVAL; ++ ++ size = PAGE_ALIGN(size); ++ ++ if (old_size == size && old_type == type) ++ return 0; ++ ++ if (display && display->sync) ++ display->sync(display); ++ ++ omapfb_free_fbmem(fbi); ++ ++ if (size == 0) { ++ clear_fb_info(fbi); ++ return 0; ++ } ++ ++ r = omapfb_alloc_fbmem(fbi, size, 0); ++ ++ if (r) { ++ if (old_size) ++ omapfb_alloc_fbmem(fbi, old_size, old_paddr); ++ ++ if (rg->size == 0) ++ clear_fb_info(fbi); ++ ++ return r; ++ } ++ ++ if (old_size == size) ++ return 0; ++ ++ if (old_size == 0) { ++ DBG("initializing fb %d\n", ofbi->id); ++ r = omapfb_fb_init(fbdev, fbi); ++ if (r) { ++ DBG("omapfb_fb_init failed\n"); ++ goto err; ++ } ++ r = omapfb_apply_changes(fbi, 1); ++ if (r) { ++ DBG("omapfb_apply_changes failed\n"); ++ goto err; ++ } ++ } else { ++ struct fb_var_screeninfo new_var; ++ memcpy(&new_var, &fbi->var, sizeof(new_var)); ++ r = check_fb_var(fbi, &new_var); ++ if (r) ++ goto err; ++ memcpy(&fbi->var, &new_var, sizeof(fbi->var)); ++ set_fb_fix(fbi); ++ } ++ ++ return 0; ++err: ++ omapfb_free_fbmem(fbi); ++ clear_fb_info(fbi); ++ return r; ++} ++ ++/* initialize fb_info, var, fix to something sane based on the display */ ++static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi) ++{ ++ struct fb_var_screeninfo *var = &fbi->var; ++ struct omap_dss_device *display = fb2display(fbi); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ int r = 0; ++ ++ fbi->fbops = &omapfb_ops; ++ fbi->flags = FBINFO_FLAG_DEFAULT; ++ fbi->pseudo_palette = fbdev->pseudo_palette; ++ ++ if (ofbi->region.size == 0) { ++ clear_fb_info(fbi); ++ return 0; ++ } ++ ++ var->nonstd = 0; ++ var->bits_per_pixel = 0; ++ ++ var->rotate = def_rotate; ++ ++ /* ++ * Check if there is a default color format set in the board file, ++ * and use this format instead the default deducted from the ++ * display bpp. ++ */ ++ if (fbdev->dev->platform_data) { ++ struct omapfb_platform_data *opd; ++ int id = ofbi->id; ++ ++ opd = fbdev->dev->platform_data; ++ if (opd->mem_desc.region[id].format_used) { ++ enum omap_color_mode mode; ++ enum omapfb_color_format format; ++ ++ format = opd->mem_desc.region[id].format; ++ mode = fb_format_to_dss_mode(format); ++ if (mode < 0) { ++ r = mode; ++ goto err; ++ } ++ r = dss_mode_to_fb_mode(mode, var); ++ if (r < 0) ++ goto err; ++ } ++ } ++ ++ if (display) { ++ u16 w, h; ++ int rotation = (var->rotate + ofbi->rotation[0]) % 4; ++ ++ display->get_resolution(display, &w, &h); ++ ++ if (rotation == FB_ROTATE_CW || ++ rotation == FB_ROTATE_CCW) { ++ var->xres = h; ++ var->yres = w; ++ } else { ++ var->xres = w; ++ var->yres = h; ++ } ++ ++ var->xres_virtual = var->xres; ++ var->yres_virtual = var->yres; ++ ++ if (!var->bits_per_pixel) { ++ switch (display->get_recommended_bpp(display)) { ++ case 16: ++ var->bits_per_pixel = 16; ++ break; ++ case 24: ++ var->bits_per_pixel = 32; ++ break; ++ default: ++ dev_err(fbdev->dev, "illegal display " ++ "bpp\n"); ++ return -EINVAL; ++ } ++ } ++ } else { ++ /* if there's no display, let's just guess some basic values */ ++ var->xres = 320; ++ var->yres = 240; ++ var->xres_virtual = var->xres; ++ var->yres_virtual = var->yres; ++ if (!var->bits_per_pixel) ++ var->bits_per_pixel = 16; ++ } ++ ++ r = check_fb_var(fbi, var); ++ if (r) ++ goto err; ++ ++ set_fb_fix(fbi); ++ ++ r = fb_alloc_cmap(&fbi->cmap, 256, 0); ++ if (r) ++ dev_err(fbdev->dev, "unable to allocate color map memory\n"); ++ ++err: ++ return r; ++} ++ ++static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi) ++{ ++ fb_dealloc_cmap(&fbi->cmap); ++} ++ ++ ++static void omapfb_free_resources(struct omapfb2_device *fbdev) ++{ ++ int i; ++ ++ DBG("free_resources\n"); ++ ++ if (fbdev == NULL) ++ return; ++ ++ for (i = 0; i < fbdev->num_fbs; i++) ++ unregister_framebuffer(fbdev->fbs[i]); ++ ++ /* free the reserved fbmem */ ++ omapfb_free_all_fbmem(fbdev); ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ fbinfo_cleanup(fbdev, fbdev->fbs[i]); ++ framebuffer_release(fbdev->fbs[i]); ++ } ++ ++ for (i = 0; i < fbdev->num_displays; i++) { ++ if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED) ++ fbdev->displays[i]->disable(fbdev->displays[i]); ++ ++ omap_dss_put_device(fbdev->displays[i]); ++ } ++ ++ dev_set_drvdata(fbdev->dev, NULL); ++ kfree(fbdev); ++} ++ ++static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) ++{ ++ int r, i; ++ ++ fbdev->num_fbs = 0; ++ ++ DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS); ++ ++ /* allocate fb_infos */ ++ for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) { ++ struct fb_info *fbi; ++ struct omapfb_info *ofbi; ++ ++ fbi = framebuffer_alloc(sizeof(struct omapfb_info), ++ fbdev->dev); ++ ++ if (fbi == NULL) { ++ dev_err(fbdev->dev, ++ "unable to allocate memory for plane info\n"); ++ return -ENOMEM; ++ } ++ ++ clear_fb_info(fbi); ++ ++ fbdev->fbs[i] = fbi; ++ ++ ofbi = FB2OFB(fbi); ++ ofbi->fbdev = fbdev; ++ ofbi->id = i; ++ ++ /* assign these early, so that fb alloc can use them */ ++ ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : ++ OMAP_DSS_ROT_DMA; ++ ofbi->mirror = def_mirror; ++ ++ fbdev->num_fbs++; ++ } ++ ++ DBG("fb_infos allocated\n"); ++ ++ /* assign overlays for the fbs */ ++ for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); ++ ++ ofbi->overlays[0] = fbdev->overlays[i]; ++ ofbi->num_overlays = 1; ++ } ++ ++ /* allocate fb memories */ ++ r = omapfb_allocate_all_fbs(fbdev); ++ if (r) { ++ dev_err(fbdev->dev, "failed to allocate fbmem\n"); ++ return r; ++ } ++ ++ DBG("fbmems allocated\n"); ++ ++ /* setup fb_infos */ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ r = omapfb_fb_init(fbdev, fbdev->fbs[i]); ++ if (r) { ++ dev_err(fbdev->dev, "failed to setup fb_info\n"); ++ return r; ++ } ++ } ++ ++ DBG("fb_infos initialized\n"); ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ r = register_framebuffer(fbdev->fbs[i]); ++ if (r != 0) { ++ dev_err(fbdev->dev, ++ "registering framebuffer %d failed\n", i); ++ return r; ++ } ++ } ++ ++ DBG("framebuffers registered\n"); ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ r = omapfb_apply_changes(fbdev->fbs[i], 1); ++ if (r) { ++ dev_err(fbdev->dev, "failed to change mode\n"); ++ return r; ++ } ++ } ++ ++ DBG("create sysfs for fbs\n"); ++ r = omapfb_create_sysfs(fbdev); ++ if (r) { ++ dev_err(fbdev->dev, "failed to create sysfs entries\n"); ++ return r; ++ } ++ ++ /* Enable fb0 */ ++ if (fbdev->num_fbs > 0) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); ++ ++ if (ofbi->num_overlays > 0) { ++ struct omap_overlay *ovl = ofbi->overlays[0]; ++ ++ r = omapfb_overlay_enable(ovl, 1); ++ ++ if (r) { ++ dev_err(fbdev->dev, ++ "failed to enable overlay\n"); ++ return r; ++ } ++ } ++ } ++ ++ DBG("create_framebuffers done\n"); ++ ++ return 0; ++} ++ ++static int omapfb_mode_to_timings(const char *mode_str, ++ struct omap_video_timings *timings, u8 *bpp) ++{ ++ struct fb_info fbi; ++ struct fb_var_screeninfo var; ++ struct fb_ops fbops; ++ int r; ++ ++#ifdef CONFIG_OMAP2_DSS_VENC ++ if (strcmp(mode_str, "pal") == 0) { ++ *timings = omap_dss_pal_timings; ++ *bpp = 0; ++ return 0; ++ } else if (strcmp(mode_str, "ntsc") == 0) { ++ *timings = omap_dss_ntsc_timings; ++ *bpp = 0; ++ return 0; ++ } ++#endif ++ ++ /* this is quite a hack, but I wanted to use the modedb and for ++ * that we need fb_info and var, so we create dummy ones */ ++ ++ memset(&fbi, 0, sizeof(fbi)); ++ memset(&var, 0, sizeof(var)); ++ memset(&fbops, 0, sizeof(fbops)); ++ fbi.fbops = &fbops; ++ ++ r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24); ++ ++ if (r != 0) { ++ timings->pixel_clock = PICOS2KHZ(var.pixclock); ++ timings->hfp = var.left_margin; ++ timings->hbp = var.right_margin; ++ timings->vfp = var.upper_margin; ++ timings->vbp = var.lower_margin; ++ timings->hsw = var.hsync_len; ++ timings->vsw = var.vsync_len; ++ timings->x_res = var.xres; ++ timings->y_res = var.yres; ++ ++ switch (var.bits_per_pixel) { ++ case 16: ++ *bpp = 16; ++ break; ++ case 24: ++ case 32: ++ default: ++ *bpp = 24; ++ break; ++ } ++ ++ return 0; ++ } else { ++ return -EINVAL; ++ } ++} ++ ++static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str) ++{ ++ int r; ++ u8 bpp; ++ struct omap_video_timings timings; ++ ++ r = omapfb_mode_to_timings(mode_str, &timings, &bpp); ++ if (r) ++ return r; ++ ++ display->panel.recommended_bpp = bpp; ++ ++ if (!display->check_timings || !display->set_timings) ++ return -EINVAL; ++ ++ r = display->check_timings(display, &timings); ++ if (r) ++ return r; ++ ++ display->set_timings(display, &timings); ++ ++ return 0; ++} ++ ++static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) ++{ ++ char *str, *options, *this_opt; ++ int r = 0; ++ ++ str = kmalloc(strlen(def_mode) + 1, GFP_KERNEL); ++ strcpy(str, def_mode); ++ options = str; ++ ++ while (!r && (this_opt = strsep(&options, ",")) != NULL) { ++ char *p, *display_str, *mode_str; ++ struct omap_dss_device *display; ++ int i; ++ ++ p = strchr(this_opt, ':'); ++ if (!p) { ++ r = -EINVAL; ++ break; ++ } ++ ++ *p = 0; ++ display_str = this_opt; ++ mode_str = p + 1; ++ ++ display = NULL; ++ for (i = 0; i < fbdev->num_displays; ++i) { ++ if (strcmp(fbdev->displays[i]->name, ++ display_str) == 0) { ++ display = fbdev->displays[i]; ++ break; ++ } ++ } ++ ++ if (!display) { ++ r = -EINVAL; ++ break; ++ } ++ ++ r = omapfb_set_def_mode(display, mode_str); ++ if (r) ++ break; ++ } ++ ++ kfree(str); ++ ++ return r; ++} ++ ++static int omapfb_probe(struct platform_device *pdev) ++{ ++ struct omapfb2_device *fbdev = NULL; ++ int r = 0; ++ int i; ++ struct omap_overlay *ovl; ++ struct omap_dss_device *def_display; ++ struct omap_dss_device *dssdev; ++ ++ DBG("omapfb_probe\n"); ++ ++ if (pdev->num_resources != 0) { ++ dev_err(&pdev->dev, "probed for an unknown device\n"); ++ r = -ENODEV; ++ goto err0; ++ } ++ ++ fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL); ++ if (fbdev == NULL) { ++ r = -ENOMEM; ++ goto err0; ++ } ++ ++ mutex_init(&fbdev->mtx); ++ ++ fbdev->dev = &pdev->dev; ++ platform_set_drvdata(pdev, fbdev); ++ ++ fbdev->num_displays = 0; ++ dssdev = NULL; ++ for_each_dss_dev(dssdev) { ++ omap_dss_get_device(dssdev); ++ fbdev->displays[fbdev->num_displays++] = dssdev; ++ } ++ ++ if (fbdev->num_displays == 0) { ++ dev_err(&pdev->dev, "no displays\n"); ++ r = -EINVAL; ++ goto cleanup; ++ } ++ ++ fbdev->num_overlays = omap_dss_get_num_overlays(); ++ for (i = 0; i < fbdev->num_overlays; i++) ++ fbdev->overlays[i] = omap_dss_get_overlay(i); ++ ++ fbdev->num_managers = omap_dss_get_num_overlay_managers(); ++ for (i = 0; i < fbdev->num_managers; i++) ++ fbdev->managers[i] = omap_dss_get_overlay_manager(i); ++ ++ if (def_mode && strlen(def_mode) > 0) { ++ if (omapfb_parse_def_modes(fbdev)) ++ dev_warn(&pdev->dev, "cannot parse default modes\n"); ++ } ++ ++ r = omapfb_create_framebuffers(fbdev); ++ if (r) ++ goto cleanup; ++ ++ for (i = 0; i < fbdev->num_managers; i++) { ++ struct omap_overlay_manager *mgr; ++ mgr = fbdev->managers[i]; ++ r = mgr->apply(mgr); ++ if (r) ++ dev_warn(fbdev->dev, "failed to apply dispc config\n"); ++ } ++ ++ DBG("mgr->apply'ed\n"); ++ ++ /* gfx overlay should be the default one. find a display ++ * connected to that, and use it as default display */ ++ ovl = omap_dss_get_overlay(0); ++ if (ovl->manager && ovl->manager->device) { ++ def_display = ovl->manager->device; ++ } else { ++ dev_warn(&pdev->dev, "cannot find default display\n"); ++ def_display = NULL; ++ } ++ ++ if (def_display) { ++ u16 w, h; ++ r = def_display->enable(def_display); ++ if (r) ++ dev_warn(fbdev->dev, "Failed to enable display '%s'\n", ++ def_display->name); ++ ++ /* set the update mode */ ++ if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { ++#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE ++ if (def_display->enable_te) ++ def_display->enable_te(def_display, 1); ++ if (def_display->set_update_mode) ++ def_display->set_update_mode(def_display, ++ OMAP_DSS_UPDATE_AUTO); ++#else /* MANUAL_UPDATE */ ++ if (def_display->enable_te) ++ def_display->enable_te(def_display, 0); ++ if (def_display->set_update_mode) ++ def_display->set_update_mode(def_display, ++ OMAP_DSS_UPDATE_MANUAL); ++ ++ def_display->get_resolution(def_display, &w, &h); ++ def_display->update(def_display, 0, 0, w, h); ++#endif ++ } else { ++ if (def_display->set_update_mode) ++ def_display->set_update_mode(def_display, ++ OMAP_DSS_UPDATE_AUTO); ++ } ++ } ++ ++ return 0; ++ ++cleanup: ++ omapfb_free_resources(fbdev); ++err0: ++ dev_err(&pdev->dev, "failed to setup omapfb\n"); ++ return r; ++} ++ ++static int omapfb_remove(struct platform_device *pdev) ++{ ++ struct omapfb2_device *fbdev = platform_get_drvdata(pdev); ++ ++ /* FIXME: wait till completion of pending events */ ++ ++ omapfb_remove_sysfs(fbdev); ++ ++ omapfb_free_resources(fbdev); ++ ++ return 0; ++} ++ ++static struct platform_driver omapfb_driver = { ++ .probe = omapfb_probe, ++ .remove = omapfb_remove, ++ .driver = { ++ .name = "omapfb", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init omapfb_init(void) ++{ ++ DBG("omapfb_init\n"); ++ ++ if (platform_driver_register(&omapfb_driver)) { ++ printk(KERN_ERR "failed to register omapfb driver\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static void __exit omapfb_exit(void) ++{ ++ DBG("omapfb_exit\n"); ++ platform_driver_unregister(&omapfb_driver); ++} ++ ++module_param_named(mode, def_mode, charp, 0); ++module_param_named(vram, def_vram, charp, 0); ++module_param_named(rotate, def_rotate, int, 0); ++module_param_named(vrfb, def_vrfb, bool, 0); ++module_param_named(mirror, def_mirror, bool, 0); ++ ++/* late_initcall to let panel/ctrl drivers loaded first. ++ * I guess better option would be a more dynamic approach, ++ * so that omapfb reacts to new panels when they are loaded */ ++late_initcall(omapfb_init); ++/*module_init(omapfb_init);*/ ++module_exit(omapfb_exit); ++ ++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); ++MODULE_DESCRIPTION("OMAP2/3 Framebuffer"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c +new file mode 100644 +index 0000000..ef30e0e +--- /dev/null ++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c +@@ -0,0 +1,507 @@ ++/* ++ * linux/drivers/video/omap2/omapfb-sysfs.c ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/fb.h> ++#include <linux/sysfs.h> ++#include <linux/device.h> ++#include <linux/uaccess.h> ++#include <linux/platform_device.h> ++#include <linux/kernel.h> ++#include <linux/mm.h> ++#include <linux/omapfb.h> ++ ++#include <mach/display.h> ++#include <mach/vrfb.h> ++ ++#include "omapfb.h" ++ ++static ssize_t show_rotate_type(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type); ++} ++ ++static ssize_t store_rotate_type(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ enum omap_dss_rotation_type rot_type; ++ int r; ++ ++ rot_type = simple_strtoul(buf, NULL, 0); ++ ++ if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) ++ return -EINVAL; ++ ++ lock_fb_info(fbi); ++ ++ r = 0; ++ if (rot_type == ofbi->rotation_type) ++ goto out; ++ ++ if (ofbi->region.size) { ++ r = -EBUSY; ++ goto out; ++ } ++ ++ ofbi->rotation_type = rot_type; ++ ++ /* ++ * Since the VRAM for this FB is not allocated at the moment we don't ++ * need to do any further parameter checking at this point. ++ */ ++out: ++ unlock_fb_info(fbi); ++ ++ return r ? r : count; ++} ++ ++ ++static ssize_t show_mirror(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror); ++} ++ ++static ssize_t store_mirror(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ bool mirror; ++ int r; ++ struct fb_var_screeninfo new_var; ++ ++ mirror = simple_strtoul(buf, NULL, 0); ++ ++ if (mirror != 0 && mirror != 1) ++ return -EINVAL; ++ ++ lock_fb_info(fbi); ++ ++ ofbi->mirror = mirror; ++ ++ memcpy(&new_var, &fbi->var, sizeof(new_var)); ++ r = check_fb_var(fbi, &new_var); ++ if (r) ++ goto out; ++ memcpy(&fbi->var, &new_var, sizeof(fbi->var)); ++ ++ set_fb_fix(fbi); ++ ++ r = omapfb_apply_changes(fbi, 0); ++ if (r) ++ goto out; ++ ++ r = count; ++out: ++ unlock_fb_info(fbi); ++ ++ return r; ++} ++ ++static ssize_t show_overlays(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ ssize_t l = 0; ++ int t; ++ ++ omapfb_lock(fbdev); ++ lock_fb_info(fbi); ++ ++ for (t = 0; t < ofbi->num_overlays; t++) { ++ struct omap_overlay *ovl = ofbi->overlays[t]; ++ int ovlnum; ++ ++ for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum) ++ if (ovl == fbdev->overlays[ovlnum]) ++ break; ++ ++ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", ++ t == 0 ? "" : ",", ovlnum); ++ } ++ ++ l += snprintf(buf + l, PAGE_SIZE - l, "\n"); ++ ++ unlock_fb_info(fbi); ++ omapfb_unlock(fbdev); ++ ++ return l; ++} ++ ++static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev, ++ struct omap_overlay *ovl) ++{ ++ int i, t; ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); ++ ++ for (t = 0; t < ofbi->num_overlays; t++) { ++ if (ofbi->overlays[t] == ovl) ++ return ofbi; ++ } ++ } ++ ++ return NULL; ++} ++ ++static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB]; ++ struct omap_overlay *ovl; ++ int num_ovls, r, i; ++ int len; ++ bool added = false; ++ ++ num_ovls = 0; ++ ++ len = strlen(buf); ++ if (buf[len - 1] == '\n') ++ len = len - 1; ++ ++ omapfb_lock(fbdev); ++ lock_fb_info(fbi); ++ ++ if (len > 0) { ++ char *p = (char *)buf; ++ int ovlnum; ++ ++ while (p < buf + len) { ++ int found; ++ if (num_ovls == OMAPFB_MAX_OVL_PER_FB) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ ovlnum = simple_strtoul(p, &p, 0); ++ if (ovlnum > fbdev->num_overlays) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ found = 0; ++ for (i = 0; i < num_ovls; ++i) { ++ if (ovls[i] == fbdev->overlays[ovlnum]) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (!found) ++ ovls[num_ovls++] = fbdev->overlays[ovlnum]; ++ ++ p++; ++ } ++ } ++ ++ for (i = 0; i < num_ovls; ++i) { ++ struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]); ++ if (ofbi2 && ofbi2 != ofbi) { ++ dev_err(fbdev->dev, "overlay already in use\n"); ++ r = -EINVAL; ++ goto out; ++ } ++ } ++ ++ /* detach unused overlays */ ++ for (i = 0; i < ofbi->num_overlays; ++i) { ++ int t, found; ++ ++ ovl = ofbi->overlays[i]; ++ ++ found = 0; ++ ++ for (t = 0; t < num_ovls; ++t) { ++ if (ovl == ovls[t]) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (found) ++ continue; ++ ++ DBG("detaching %d\n", ofbi->overlays[i]->id); ++ ++ omapfb_overlay_enable(ovl, 0); ++ ++ if (ovl->manager) ++ ovl->manager->apply(ovl->manager); ++ ++ for (t = i + 1; t < ofbi->num_overlays; t++) { ++ ofbi->rotation[t-1] = ofbi->rotation[t]; ++ ofbi->overlays[t-1] = ofbi->overlays[t]; ++ } ++ ++ ofbi->num_overlays--; ++ i--; ++ } ++ ++ for (i = 0; i < num_ovls; ++i) { ++ int t, found; ++ ++ ovl = ovls[i]; ++ ++ found = 0; ++ ++ for (t = 0; t < ofbi->num_overlays; ++t) { ++ if (ovl == ofbi->overlays[t]) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (found) ++ continue; ++ ofbi->rotation[ofbi->num_overlays] = 0; ++ ofbi->overlays[ofbi->num_overlays++] = ovl; ++ ++ added = true; ++ } ++ ++ if (added) { ++ r = omapfb_apply_changes(fbi, 0); ++ if (r) ++ goto out; ++ } ++ ++ r = count; ++out: ++ unlock_fb_info(fbi); ++ omapfb_unlock(fbdev); ++ ++ return r; ++} ++ ++static ssize_t show_overlays_rotate(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ssize_t l = 0; ++ int t; ++ ++ lock_fb_info(fbi); ++ ++ for (t = 0; t < ofbi->num_overlays; t++) { ++ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", ++ t == 0 ? "" : ",", ofbi->rotation[t]); ++ } ++ ++ l += snprintf(buf + l, PAGE_SIZE - l, "\n"); ++ ++ unlock_fb_info(fbi); ++ ++ return l; ++} ++ ++static ssize_t store_overlays_rotate(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ int num_ovls = 0, r, i; ++ int len; ++ bool changed = false; ++ u8 rotation[OMAPFB_MAX_OVL_PER_FB]; ++ ++ len = strlen(buf); ++ if (buf[len - 1] == '\n') ++ len = len - 1; ++ ++ lock_fb_info(fbi); ++ ++ if (len > 0) { ++ char *p = (char *)buf; ++ ++ while (p < buf + len) { ++ int rot; ++ ++ if (num_ovls == ofbi->num_overlays) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ rot = simple_strtoul(p, &p, 0); ++ if (rot < 0 || rot > 3) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ if (ofbi->rotation[num_ovls] != rot) ++ changed = true; ++ ++ rotation[num_ovls++] = rot; ++ ++ p++; ++ } ++ } ++ ++ if (num_ovls != ofbi->num_overlays) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ if (changed) { ++ for (i = 0; i < num_ovls; ++i) ++ ofbi->rotation[i] = rotation[i]; ++ ++ r = omapfb_apply_changes(fbi, 0); ++ if (r) ++ goto out; ++ ++ /* FIXME error handling? */ ++ } ++ ++ r = count; ++out: ++ unlock_fb_info(fbi); ++ ++ return r; ++} ++ ++static ssize_t show_size(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size); ++} ++ ++static ssize_t store_size(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ unsigned long size; ++ int r; ++ int i; ++ ++ size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0)); ++ ++ lock_fb_info(fbi); ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ofbi->overlays[i]->info.enabled) { ++ r = -EBUSY; ++ goto out; ++ } ++ } ++ ++ if (size != ofbi->region.size) { ++ r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type); ++ if (r) { ++ dev_err(dev, "realloc fbmem failed\n"); ++ goto out; ++ } ++ } ++ ++ r = count; ++out: ++ unlock_fb_info(fbi); ++ ++ return r; ++} ++ ++static ssize_t show_phys(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr); ++} ++ ++static ssize_t show_virt(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr); ++} ++ ++static struct device_attribute omapfb_attrs[] = { ++ __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type, ++ store_rotate_type), ++ __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror), ++ __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size), ++ __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays), ++ __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate, ++ store_overlays_rotate), ++ __ATTR(phys_addr, S_IRUGO, show_phys, NULL), ++ __ATTR(virt_addr, S_IRUGO, show_virt, NULL), ++}; ++ ++int omapfb_create_sysfs(struct omapfb2_device *fbdev) ++{ ++ int i; ++ int r; ++ ++ DBG("create sysfs for fbs\n"); ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ int t; ++ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) { ++ r = device_create_file(fbdev->fbs[i]->dev, ++ &omapfb_attrs[t]); ++ ++ if (r) { ++ dev_err(fbdev->dev, "failed to create sysfs " ++ "file\n"); ++ return r; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++void omapfb_remove_sysfs(struct omapfb2_device *fbdev) ++{ ++ int i, t; ++ ++ DBG("remove sysfs for fbs\n"); ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) ++ device_remove_file(fbdev->fbs[i]->dev, ++ &omapfb_attrs[t]); ++ } ++} ++ +diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h +new file mode 100644 +index 0000000..d9ee986 +--- /dev/null ++++ b/drivers/video/omap2/omapfb/omapfb.h +@@ -0,0 +1,146 @@ ++/* ++ * linux/drivers/video/omap2/omapfb.h ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__ ++#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__ ++ ++#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT ++#define DEBUG ++#endif ++ ++#include <mach/display.h> ++ ++#ifdef DEBUG ++extern unsigned int omapfb_debug; ++#define DBG(format, ...) \ ++ if (omapfb_debug) \ ++ printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__) ++#else ++#define DBG(format, ...) ++#endif ++ ++#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par)) ++ ++/* max number of overlays to which a framebuffer data can be direct */ ++#define OMAPFB_MAX_OVL_PER_FB 3 ++ ++struct omapfb2_mem_region { ++ u32 paddr; ++ void __iomem *vaddr; ++ struct vrfb vrfb; ++ unsigned long size; ++ u8 type; /* OMAPFB_PLANE_MEM_* */ ++ bool alloc; /* allocated by the driver */ ++ bool map; /* kernel mapped by the driver */ ++}; ++ ++/* appended to fb_info */ ++struct omapfb_info { ++ int id; ++ struct omapfb2_mem_region region; ++ atomic_t map_count; ++ int num_overlays; ++ struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB]; ++ struct omapfb2_device *fbdev; ++ enum omap_dss_rotation_type rotation_type; ++ u8 rotation[OMAPFB_MAX_OVL_PER_FB]; ++ bool mirror; ++}; ++ ++struct omapfb2_device { ++ struct device *dev; ++ struct mutex mtx; ++ ++ u32 pseudo_palette[17]; ++ ++ int state; ++ ++ unsigned num_fbs; ++ struct fb_info *fbs[10]; ++ ++ unsigned num_displays; ++ struct omap_dss_device *displays[10]; ++ unsigned num_overlays; ++ struct omap_overlay *overlays[10]; ++ unsigned num_managers; ++ struct omap_overlay_manager *managers[10]; ++}; ++ ++struct omapfb_colormode { ++ enum omap_color_mode dssmode; ++ u32 bits_per_pixel; ++ u32 nonstd; ++ struct fb_bitfield red; ++ struct fb_bitfield green; ++ struct fb_bitfield blue; ++ struct fb_bitfield transp; ++}; ++ ++void set_fb_fix(struct fb_info *fbi); ++int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var); ++int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type); ++int omapfb_apply_changes(struct fb_info *fbi, int init); ++ ++int omapfb_create_sysfs(struct omapfb2_device *fbdev); ++void omapfb_remove_sysfs(struct omapfb2_device *fbdev); ++ ++int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg); ++ ++int dss_mode_to_fb_mode(enum omap_color_mode dssmode, ++ struct fb_var_screeninfo *var); ++ ++/* find the display connected to this fb, if any */ ++static inline struct omap_dss_device *fb2display(struct fb_info *fbi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ int i; ++ ++ /* XXX: returns the display connected to first attached overlay */ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ofbi->overlays[i]->manager) ++ return ofbi->overlays[i]->manager->device; ++ } ++ ++ return NULL; ++} ++ ++static inline void omapfb_lock(struct omapfb2_device *fbdev) ++{ ++ mutex_lock(&fbdev->mtx); ++} ++ ++static inline void omapfb_unlock(struct omapfb2_device *fbdev) ++{ ++ mutex_unlock(&fbdev->mtx); ++} ++ ++static inline int omapfb_overlay_enable(struct omap_overlay *ovl, ++ int enable) ++{ ++ struct omap_overlay_info info; ++ ++ ovl->get_overlay_info(ovl, &info); ++ info.enabled = enable; ++ return ovl->set_overlay_info(ovl, &info); ++} ++ ++#endif +diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h +index a3611d3..52e0987 100644 +--- a/include/linux/omapfb.h ++++ b/include/linux/omapfb.h +@@ -24,6 +24,7 @@ + #ifndef __LINUX_OMAPFB_H__ + #define __LINUX_OMAPFB_H__ + ++#include <linux/fb.h> + #include <linux/ioctl.h> + #include <linux/types.h> + +@@ -50,6 +51,11 @@ + #define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window) + #define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info) + #define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info) ++#define OMAPFB_WAITFORVSYNC OMAP_IO(57) ++#define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read) ++#define OMAPFB_GET_OVERLAY_COLORMODE OMAP_IOR(59, struct omapfb_ovl_colormode) ++#define OMAPFB_WAITFORGO OMAP_IO(60) ++#define OMAPFB_GET_VRAM_INFO OMAP_IOR(61, struct omapfb_vram_info) + + #define OMAPFB_CAPS_GENERIC_MASK 0x00000fff + #define OMAPFB_CAPS_LCDC_MASK 0x00fff000 +@@ -87,6 +93,13 @@ enum omapfb_color_format { + OMAPFB_COLOR_CLUT_1BPP, + OMAPFB_COLOR_RGB444, + OMAPFB_COLOR_YUY422, ++ ++ OMAPFB_COLOR_ARGB16, ++ OMAPFB_COLOR_RGB24U, /* RGB24, 32-bit container */ ++ OMAPFB_COLOR_RGB24P, /* RGB24, 24-bit container */ ++ OMAPFB_COLOR_ARGB32, ++ OMAPFB_COLOR_RGBA32, ++ OMAPFB_COLOR_RGBX32, + }; + + struct omapfb_update_window { +@@ -158,6 +171,33 @@ enum omapfb_update_mode { + OMAPFB_MANUAL_UPDATE + }; + ++struct omapfb_memory_read { ++ __u16 x; ++ __u16 y; ++ __u16 w; ++ __u16 h; ++ size_t buffer_size; ++ void __user *buffer; ++}; ++ ++struct omapfb_ovl_colormode { ++ __u8 overlay_idx; ++ __u8 mode_idx; ++ __u32 bits_per_pixel; ++ __u32 nonstd; ++ struct fb_bitfield red; ++ struct fb_bitfield green; ++ struct fb_bitfield blue; ++ struct fb_bitfield transp; ++}; ++ ++struct omapfb_vram_info { ++ __u32 total; ++ __u32 free; ++ __u32 largest_free_block; ++ __u32 reserved[5]; ++}; ++ + #ifdef __KERNEL__ + + #include <mach/board.h> +@@ -173,6 +213,11 @@ struct omapfb_mem_region { + void __iomem *vaddr; + unsigned long size; + u8 type; /* OMAPFB_PLANE_MEM_* */ ++ enum omapfb_color_format format;/* OMAPFB_COLOR_* */ ++ unsigned format_used:1; /* Must be set when format is set. ++ * Needed b/c of the badly chosen 0 ++ * base for OMAPFB_COLOR_* values ++ */ + unsigned alloc:1; /* allocated by the driver */ + unsigned map:1; /* kernel mapped by the driver */ + }; +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0016-OMAP-DSS2-Add-DPI-panel-drivers.patch b/recipes/linux/linux-omap-2.6.31/dss2/0016-OMAP-DSS2-Add-DPI-panel-drivers.patch new file mode 100644 index 0000000000..fd9db5ae27 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0016-OMAP-DSS2-Add-DPI-panel-drivers.patch @@ -0,0 +1,471 @@ +From e2ddc67b0d9a3450382110edfaca18ecd44804bc Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Tue, 4 Aug 2009 16:41:45 +0300 +Subject: [PATCH 16/18] OMAP: DSS2: Add DPI panel drivers + +- Generic panel +- Samsung LTE430WQ-F0C LCD Panel +- Sharp LS037V7DW01 LCD Panel + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + drivers/video/omap2/Kconfig | 1 + + drivers/video/omap2/Makefile | 1 + + drivers/video/omap2/displays/Kconfig | 22 +++ + drivers/video/omap2/displays/Makefile | 3 + + drivers/video/omap2/displays/panel-generic.c | 104 +++++++++++++ + .../omap2/displays/panel-samsung-lte430wq-f0c.c | 113 +++++++++++++++ + .../video/omap2/displays/panel-sharp-ls037v7dw01.c | 153 ++++++++++++++++++++ + 7 files changed, 397 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/displays/Kconfig + create mode 100644 drivers/video/omap2/displays/Makefile + create mode 100644 drivers/video/omap2/displays/panel-generic.c + create mode 100644 drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c + create mode 100644 drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c + +diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig +index 3e60d7e..d877c36 100644 +--- a/drivers/video/omap2/Kconfig ++++ b/drivers/video/omap2/Kconfig +@@ -6,3 +6,4 @@ config OMAP2_VRFB + + source "drivers/video/omap2/dss/Kconfig" + source "drivers/video/omap2/omapfb/Kconfig" ++source "drivers/video/omap2/displays/Kconfig" +diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile +index 3ba6ef5..d853d05 100644 +--- a/drivers/video/omap2/Makefile ++++ b/drivers/video/omap2/Makefile +@@ -3,3 +3,4 @@ obj-$(CONFIG_OMAP2_VRFB) += vrfb.o + + obj-y += dss/ + obj-y += omapfb/ ++obj-y += displays/ +diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig +new file mode 100644 +index 0000000..396905d +--- /dev/null ++++ b/drivers/video/omap2/displays/Kconfig +@@ -0,0 +1,22 @@ ++menu "OMAP2/3 Display Device Drivers" ++ depends on OMAP2_DSS ++ ++config PANEL_GENERIC ++ tristate "Generic Panel" ++ help ++ Generic panel driver. ++ Used for DVI output for Beagle and OMAP3 SDP. ++ ++config PANEL_SAMSUNG_LTE430WQ_F0C ++ tristate "Samsung LTE430WQ-F0C LCD Panel" ++ depends on OMAP2_DSS ++ help ++ LCD Panel used on Overo Palo43 ++ ++config PANEL_SHARP_LS037V7DW01 ++ tristate "Sharp LS037V7DW01 LCD Panel" ++ depends on OMAP2_DSS ++ help ++ LCD Panel used in TI's SDP3430 and EVM boards ++ ++endmenu +diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile +new file mode 100644 +index 0000000..a26bbd2 +--- /dev/null ++++ b/drivers/video/omap2/displays/Makefile +@@ -0,0 +1,3 @@ ++obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o ++obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o ++obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o +diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c +new file mode 100644 +index 0000000..738147e +--- /dev/null ++++ b/drivers/video/omap2/displays/panel-generic.c +@@ -0,0 +1,104 @@ ++/* ++ * Generic panel support ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/module.h> ++#include <linux/delay.h> ++ ++#include <mach/display.h> ++ ++static struct omap_video_timings generic_panel_timings = { ++ /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ ++ .x_res = 640, ++ .y_res = 480, ++ .pixel_clock = 23500, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 4, ++ .vbp = 7, ++}; ++ ++static int generic_panel_probe(struct omap_dss_device *dssdev) ++{ ++ dssdev->panel.config = OMAP_DSS_LCD_TFT; ++ dssdev->panel.timings = generic_panel_timings; ++ ++ return 0; ++} ++ ++static void generic_panel_remove(struct omap_dss_device *dssdev) ++{ ++} ++ ++static int generic_panel_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ if (dssdev->platform_enable) ++ r = dssdev->platform_enable(dssdev); ++ ++ return r; ++} ++ ++static void generic_panel_disable(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++} ++ ++static int generic_panel_suspend(struct omap_dss_device *dssdev) ++{ ++ generic_panel_disable(dssdev); ++ return 0; ++} ++ ++static int generic_panel_resume(struct omap_dss_device *dssdev) ++{ ++ return generic_panel_enable(dssdev); ++} ++ ++static struct omap_dss_driver generic_driver = { ++ .probe = generic_panel_probe, ++ .remove = generic_panel_remove, ++ ++ .enable = generic_panel_enable, ++ .disable = generic_panel_disable, ++ .suspend = generic_panel_suspend, ++ .resume = generic_panel_resume, ++ ++ .driver = { ++ .name = "generic_panel", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init generic_panel_drv_init(void) ++{ ++ return omap_dss_register_driver(&generic_driver); ++} ++ ++static void __exit generic_panel_drv_exit(void) ++{ ++ omap_dss_unregister_driver(&generic_driver); ++} ++ ++module_init(generic_panel_drv_init); ++module_exit(generic_panel_drv_exit); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c +new file mode 100644 +index 0000000..eafe581 +--- /dev/null ++++ b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c +@@ -0,0 +1,113 @@ ++/* ++ * LCD panel driver for Samsung LTE430WQ-F0C ++ * ++ * Author: Steve Sakoman <steve@sakoman.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/module.h> ++#include <linux/delay.h> ++ ++#include <mach/display.h> ++ ++static struct omap_video_timings samsung_lte_timings = { ++ .x_res = 480, ++ .y_res = 272, ++ ++ .pixel_clock = 9200, ++ ++ .hsw = 41, ++ .hfp = 8, ++ .hbp = 45-41, ++ ++ .vsw = 10, ++ .vfp = 4, ++ .vbp = 12-10, ++}; ++ ++static int samsung_lte_panel_probe(struct omap_dss_device *dssdev) ++{ ++ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | ++ OMAP_DSS_LCD_IHS; ++ dssdev->panel.timings = samsung_lte_timings; ++ ++ return 0; ++} ++ ++static void samsung_lte_panel_remove(struct omap_dss_device *dssdev) ++{ ++} ++ ++static int samsung_lte_panel_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ /* wait couple of vsyncs until enabling the LCD */ ++ msleep(50); ++ ++ if (dssdev->platform_enable) ++ r = dssdev->platform_enable(dssdev); ++ ++ return r; ++} ++ ++static void samsung_lte_panel_disable(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++ ++ /* wait at least 5 vsyncs after disabling the LCD */ ++ ++ msleep(100); ++} ++ ++static int samsung_lte_panel_suspend(struct omap_dss_device *dssdev) ++{ ++ samsung_lte_panel_disable(dssdev); ++ return 0; ++} ++ ++static int samsung_lte_panel_resume(struct omap_dss_device *dssdev) ++{ ++ return samsung_lte_panel_enable(dssdev); ++} ++ ++static struct omap_dss_driver samsung_lte_driver = { ++ .probe = samsung_lte_panel_probe, ++ .remove = samsung_lte_panel_remove, ++ ++ .enable = samsung_lte_panel_enable, ++ .disable = samsung_lte_panel_disable, ++ .suspend = samsung_lte_panel_suspend, ++ .resume = samsung_lte_panel_resume, ++ ++ .driver = { ++ .name = "samsung_lte_panel", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init samsung_lte_panel_drv_init(void) ++{ ++ return omap_dss_register_driver(&samsung_lte_driver); ++} ++ ++static void __exit samsung_lte_panel_drv_exit(void) ++{ ++ omap_dss_unregister_driver(&samsung_lte_driver); ++} ++ ++module_init(samsung_lte_panel_drv_init); ++module_exit(samsung_lte_panel_drv_exit); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c +new file mode 100644 +index 0000000..2f8f0df +--- /dev/null ++++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c +@@ -0,0 +1,153 @@ ++/* ++ * LCD panel driver for Sharp LS037V7DW01 ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/device.h> ++#include <linux/regulator/consumer.h> ++#include <linux/err.h> ++ ++#include <mach/display.h> ++ ++struct sharp_data { ++ /* XXX This regulator should actually be in SDP board file, not here, ++ * as it doesn't actually power the LCD, but something else that ++ * affects the output to LCD (I think. Somebody clarify). It doesn't do ++ * harm here, as SDP is the only board using this currently */ ++ struct regulator *vdvi_reg; ++}; ++ ++static struct omap_video_timings sharp_ls_timings = { ++ .x_res = 480, ++ .y_res = 640, ++ ++ .pixel_clock = 19200, ++ ++ .hsw = 2, ++ .hfp = 1, ++ .hbp = 28, ++ ++ .vsw = 1, ++ .vfp = 1, ++ .vbp = 1, ++}; ++ ++static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) ++{ ++ struct sharp_data *sd; ++ ++ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | ++ OMAP_DSS_LCD_IHS; ++ dssdev->panel.acb = 0x28; ++ dssdev->panel.timings = sharp_ls_timings; ++ ++ sd = kzalloc(sizeof(*sd), GFP_KERNEL); ++ if (!sd) ++ return -ENOMEM; ++ ++ dev_set_drvdata(&dssdev->dev, sd); ++ ++ sd->vdvi_reg = regulator_get(&dssdev->dev, "vdvi"); ++ if (IS_ERR(sd->vdvi_reg)) { ++ kfree(sd); ++ pr_err("failed to get VDVI regulator\n"); ++ return PTR_ERR(sd->vdvi_reg); ++ } ++ ++ return 0; ++} ++ ++static void sharp_ls_panel_remove(struct omap_dss_device *dssdev) ++{ ++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); ++ ++ regulator_put(sd->vdvi_reg); ++ ++ kfree(sd); ++} ++ ++static int sharp_ls_panel_enable(struct omap_dss_device *dssdev) ++{ ++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); ++ int r = 0; ++ ++ /* wait couple of vsyncs until enabling the LCD */ ++ msleep(50); ++ ++ regulator_enable(sd->vdvi_reg); ++ ++ if (dssdev->platform_enable) ++ r = dssdev->platform_enable(dssdev); ++ ++ return r; ++} ++ ++static void sharp_ls_panel_disable(struct omap_dss_device *dssdev) ++{ ++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); ++ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++ ++ regulator_disable(sd->vdvi_reg); ++ ++ /* wait at least 5 vsyncs after disabling the LCD */ ++ ++ msleep(100); ++} ++ ++static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev) ++{ ++ sharp_ls_panel_disable(dssdev); ++ return 0; ++} ++ ++static int sharp_ls_panel_resume(struct omap_dss_device *dssdev) ++{ ++ return sharp_ls_panel_enable(dssdev); ++} ++ ++static struct omap_dss_driver sharp_ls_driver = { ++ .probe = sharp_ls_panel_probe, ++ .remove = sharp_ls_panel_remove, ++ ++ .enable = sharp_ls_panel_enable, ++ .disable = sharp_ls_panel_disable, ++ .suspend = sharp_ls_panel_suspend, ++ .resume = sharp_ls_panel_resume, ++ ++ .driver = { ++ .name = "sharp_ls_panel", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init sharp_ls_panel_drv_init(void) ++{ ++ return omap_dss_register_driver(&sharp_ls_driver); ++} ++ ++static void __exit sharp_ls_panel_drv_exit(void) ++{ ++ omap_dss_unregister_driver(&sharp_ls_driver); ++} ++ ++module_init(sharp_ls_panel_drv_init); ++module_exit(sharp_ls_panel_drv_exit); ++MODULE_LICENSE("GPL"); +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0017-OMAP-DSS2-Taal-DSI-command-mode-panel-driver.patch b/recipes/linux/linux-omap-2.6.31/dss2/0017-OMAP-DSS2-Taal-DSI-command-mode-panel-driver.patch new file mode 100644 index 0000000000..c58ce9d36b --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0017-OMAP-DSS2-Taal-DSI-command-mode-panel-driver.patch @@ -0,0 +1,947 @@ +From fc8cd50c04b519f3839e9dc505532e725c7af080 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Fri, 7 Aug 2009 14:45:05 +0300 +Subject: [PATCH 17/18] OMAP: DSS2: Taal DSI command mode panel driver + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +--- + drivers/video/omap2/displays/Kconfig | 6 + + drivers/video/omap2/displays/Makefile | 2 + + drivers/video/omap2/displays/panel-taal.c | 900 +++++++++++++++++++++++++++++ + 3 files changed, 908 insertions(+), 0 deletions(-) + create mode 100644 drivers/video/omap2/displays/panel-taal.c + +diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig +index 396905d..79d2861 100644 +--- a/drivers/video/omap2/displays/Kconfig ++++ b/drivers/video/omap2/displays/Kconfig +@@ -19,4 +19,10 @@ config PANEL_SHARP_LS037V7DW01 + help + LCD Panel used in TI's SDP3430 and EVM boards + ++config PANEL_TAAL ++ tristate "Taal DSI Panel" ++ depends on OMAP2_DSS_DSI ++ help ++ Taal DSI command mode panel from TPO. ++ + endmenu +diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile +index a26bbd2..d44e765 100644 +--- a/drivers/video/omap2/displays/Makefile ++++ b/drivers/video/omap2/displays/Makefile +@@ -1,3 +1,5 @@ + obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o + obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o + obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o ++ ++obj-$(CONFIG_PANEL_TAAL) += panel-taal.o +diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c +new file mode 100644 +index 0000000..84f0d47 +--- /dev/null ++++ b/drivers/video/omap2/displays/panel-taal.c +@@ -0,0 +1,900 @@ ++/* ++ * Taal DSI command mode panel ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++/*#define DEBUG*/ ++ ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/err.h> ++#include <linux/jiffies.h> ++#include <linux/sched.h> ++#include <linux/backlight.h> ++#include <linux/fb.h> ++#include <linux/interrupt.h> ++#include <linux/gpio.h> ++#include <linux/completion.h> ++ ++#include <mach/display.h> ++ ++/* DSI Virtual channel. Hardcoded for now. */ ++#define TCH 0 ++ ++#define DCS_READ_NUM_ERRORS 0x05 ++#define DCS_READ_POWER_MODE 0x0a ++#define DCS_READ_MADCTL 0x0b ++#define DCS_READ_PIXEL_FORMAT 0x0c ++#define DCS_SLEEP_IN 0x10 ++#define DCS_SLEEP_OUT 0x11 ++#define DCS_DISPLAY_OFF 0x28 ++#define DCS_DISPLAY_ON 0x29 ++#define DCS_COLUMN_ADDR 0x2a ++#define DCS_PAGE_ADDR 0x2b ++#define DCS_MEMORY_WRITE 0x2c ++#define DCS_TEAR_OFF 0x34 ++#define DCS_TEAR_ON 0x35 ++#define DCS_MEM_ACC_CTRL 0x36 ++#define DCS_PIXEL_FORMAT 0x3a ++#define DCS_BRIGHTNESS 0x51 ++#define DCS_CTRL_DISPLAY 0x53 ++#define DCS_WRITE_CABC 0x55 ++#define DCS_READ_CABC 0x56 ++#define DCS_GET_ID1 0xda ++#define DCS_GET_ID2 0xdb ++#define DCS_GET_ID3 0xdc ++ ++struct taal_data { ++ struct backlight_device *bldev; ++ ++ unsigned long hw_guard_end; /* next value of jiffies when we can ++ * issue the next sleep in/out command ++ */ ++ unsigned long hw_guard_wait; /* max guard time in jiffies */ ++ ++ struct omap_dss_device *dssdev; ++ ++ bool enabled; ++ u8 rotate; ++ bool mirror; ++ ++ bool te_enabled; ++ bool use_ext_te; ++ struct completion te_completion; ++ ++ bool use_dsi_bl; ++ ++ bool cabc_broken; ++ unsigned cabc_mode; ++ ++ bool intro_printed; ++}; ++ ++static void hw_guard_start(struct taal_data *td, int guard_msec) ++{ ++ td->hw_guard_wait = msecs_to_jiffies(guard_msec); ++ td->hw_guard_end = jiffies + td->hw_guard_wait; ++} ++ ++static void hw_guard_wait(struct taal_data *td) ++{ ++ unsigned long wait = td->hw_guard_end - jiffies; ++ ++ if ((long)wait > 0 && wait <= td->hw_guard_wait) { ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_timeout(wait); ++ } ++} ++ ++static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) ++{ ++ int r; ++ u8 buf[1]; ++ ++ r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1); ++ ++ if (r < 0) ++ return r; ++ ++ *data = buf[0]; ++ ++ return 0; ++} ++ ++static int taal_dcs_write_0(u8 dcs_cmd) ++{ ++ return dsi_vc_dcs_write(TCH, &dcs_cmd, 1); ++} ++ ++static int taal_dcs_write_1(u8 dcs_cmd, u8 param) ++{ ++ u8 buf[2]; ++ buf[0] = dcs_cmd; ++ buf[1] = param; ++ return dsi_vc_dcs_write(TCH, buf, 2); ++} ++ ++static int taal_sleep_in(struct taal_data *td) ++ ++{ ++ u8 cmd; ++ int r; ++ ++ hw_guard_wait(td); ++ ++ cmd = DCS_SLEEP_IN; ++ r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1); ++ if (r) ++ return r; ++ ++ hw_guard_start(td, 120); ++ ++ msleep(5); ++ ++ return 0; ++} ++ ++static int taal_sleep_out(struct taal_data *td) ++{ ++ int r; ++ ++ hw_guard_wait(td); ++ ++ r = taal_dcs_write_0(DCS_SLEEP_OUT); ++ if (r) ++ return r; ++ ++ hw_guard_start(td, 120); ++ ++ msleep(5); ++ ++ return 0; ++} ++ ++static int taal_get_id(u8 *id1, u8 *id2, u8 *id3) ++{ ++ int r; ++ ++ r = taal_dcs_read_1(DCS_GET_ID1, id1); ++ if (r) ++ return r; ++ r = taal_dcs_read_1(DCS_GET_ID2, id2); ++ if (r) ++ return r; ++ r = taal_dcs_read_1(DCS_GET_ID3, id3); ++ if (r) ++ return r; ++ ++ return 0; ++} ++ ++static int taal_set_addr_mode(u8 rotate, bool mirror) ++{ ++ int r; ++ u8 mode; ++ int b5, b6, b7; ++ ++ r = taal_dcs_read_1(DCS_READ_MADCTL, &mode); ++ if (r) ++ return r; ++ ++ switch (rotate) { ++ default: ++ case 0: ++ b7 = 0; ++ b6 = 0; ++ b5 = 0; ++ break; ++ case 1: ++ b7 = 0; ++ b6 = 1; ++ b5 = 1; ++ break; ++ case 2: ++ b7 = 1; ++ b6 = 1; ++ b5 = 0; ++ break; ++ case 3: ++ b7 = 1; ++ b6 = 0; ++ b5 = 1; ++ break; ++ } ++ ++ if (mirror) ++ b6 = !b6; ++ ++ mode &= ~((1<<7) | (1<<6) | (1<<5)); ++ mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); ++ ++ return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode); ++} ++ ++static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) ++{ ++ int r; ++ u16 x1 = x; ++ u16 x2 = x + w - 1; ++ u16 y1 = y; ++ u16 y2 = y + h - 1; ++ ++ u8 buf[5]; ++ buf[0] = DCS_COLUMN_ADDR; ++ buf[1] = (x1 >> 8) & 0xff; ++ buf[2] = (x1 >> 0) & 0xff; ++ buf[3] = (x2 >> 8) & 0xff; ++ buf[4] = (x2 >> 0) & 0xff; ++ ++ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); ++ if (r) ++ return r; ++ ++ buf[0] = DCS_PAGE_ADDR; ++ buf[1] = (y1 >> 8) & 0xff; ++ buf[2] = (y1 >> 0) & 0xff; ++ buf[3] = (y2 >> 8) & 0xff; ++ buf[4] = (y2 >> 0) & 0xff; ++ ++ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); ++ if (r) ++ return r; ++ ++ dsi_vc_send_bta_sync(TCH); ++ ++ return r; ++} ++ ++static int taal_bl_update_status(struct backlight_device *dev) ++{ ++ struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ int r; ++ int level; ++ ++ if (dev->props.fb_blank == FB_BLANK_UNBLANK && ++ dev->props.power == FB_BLANK_UNBLANK) ++ level = dev->props.brightness; ++ else ++ level = 0; ++ ++ dev_dbg(&dssdev->dev, "update brightness to %d\n", level); ++ ++ if (td->use_dsi_bl) { ++ if (td->enabled) { ++ dsi_bus_lock(); ++ r = taal_dcs_write_1(DCS_BRIGHTNESS, level); ++ dsi_bus_unlock(); ++ if (r) ++ return r; ++ } ++ } else { ++ if (!dssdev->set_backlight) ++ return -EINVAL; ++ ++ r = dssdev->set_backlight(dssdev, level); ++ if (r) ++ return r; ++ } ++ ++ return 0; ++} ++ ++static int taal_bl_get_intensity(struct backlight_device *dev) ++{ ++ if (dev->props.fb_blank == FB_BLANK_UNBLANK && ++ dev->props.power == FB_BLANK_UNBLANK) ++ return dev->props.brightness; ++ ++ return 0; ++} ++ ++static struct backlight_ops taal_bl_ops = { ++ .get_brightness = taal_bl_get_intensity, ++ .update_status = taal_bl_update_status, ++}; ++ ++static void taal_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ *timings = dssdev->panel.timings; ++} ++ ++static void taal_get_resolution(struct omap_dss_device *dssdev, ++ u16 *xres, u16 *yres) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ ++ if (td->rotate == 0 || td->rotate == 2) { ++ *xres = dssdev->panel.timings.x_res; ++ *yres = dssdev->panel.timings.y_res; ++ } else { ++ *yres = dssdev->panel.timings.x_res; ++ *xres = dssdev->panel.timings.y_res; ++ } ++} ++ ++static irqreturn_t taal_te_isr(int irq, void *data) ++{ ++ struct omap_dss_device *dssdev = data; ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ ++ complete_all(&td->te_completion); ++ ++ return IRQ_HANDLED; ++} ++ ++static ssize_t taal_num_errors_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ u8 errors; ++ int r; ++ ++ if (td->enabled) { ++ dsi_bus_lock(); ++ r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); ++ dsi_bus_unlock(); ++ } else { ++ r = -ENODEV; ++ } ++ ++ if (r) ++ return r; ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", errors); ++} ++ ++static ssize_t taal_hw_revision_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ u8 id1, id2, id3; ++ int r; ++ ++ if (td->enabled) { ++ dsi_bus_lock(); ++ r = taal_get_id(&id1, &id2, &id3); ++ dsi_bus_unlock(); ++ } else { ++ r = -ENODEV; ++ } ++ ++ if (r) ++ return r; ++ ++ return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3); ++} ++ ++static const char *cabc_modes[] = { ++ "off", /* used also always when CABC is not supported */ ++ "ui", ++ "still-image", ++ "moving-image", ++}; ++ ++static ssize_t show_cabc_mode(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ const char *mode_str; ++ int mode; ++ int len; ++ ++ mode = td->cabc_mode; ++ ++ mode_str = "unknown"; ++ if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes)) ++ mode_str = cabc_modes[mode]; ++ len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str); ++ ++ return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1; ++} ++ ++static ssize_t store_cabc_mode(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { ++ if (sysfs_streq(cabc_modes[i], buf)) ++ break; ++ } ++ ++ if (i == ARRAY_SIZE(cabc_modes)) ++ return -EINVAL; ++ ++ if (td->enabled) { ++ dsi_bus_lock(); ++ if (!td->cabc_broken) ++ taal_dcs_write_1(DCS_WRITE_CABC, i); ++ dsi_bus_unlock(); ++ } ++ ++ td->cabc_mode = i; ++ ++ return count; ++} ++ ++static ssize_t show_cabc_available_modes(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ int len; ++ int i; ++ ++ for (i = 0, len = 0; ++ len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++) ++ len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s", ++ i ? " " : "", cabc_modes[i], ++ i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : ""); ++ ++ return len < PAGE_SIZE ? len : PAGE_SIZE - 1; ++} ++ ++static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL); ++static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL); ++static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, ++ show_cabc_mode, store_cabc_mode); ++static DEVICE_ATTR(cabc_available_modes, S_IRUGO, ++ show_cabc_available_modes, NULL); ++ ++static struct attribute *taal_attrs[] = { ++ &dev_attr_num_dsi_errors.attr, ++ &dev_attr_hw_revision.attr, ++ &dev_attr_cabc_mode.attr, ++ &dev_attr_cabc_available_modes.attr, ++ NULL, ++}; ++ ++static struct attribute_group taal_attr_group = { ++ .attrs = taal_attrs, ++}; ++ ++static int taal_probe(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td; ++ struct backlight_device *bldev; ++ int r; ++ ++ const struct omap_video_timings taal_panel_timings = { ++ .x_res = 864, ++ .y_res = 480, ++ }; ++ ++ dev_dbg(&dssdev->dev, "probe\n"); ++ ++ dssdev->panel.config = OMAP_DSS_LCD_TFT; ++ dssdev->panel.timings = taal_panel_timings; ++ dssdev->ctrl.pixel_size = 24; ++ ++ td = kzalloc(sizeof(*td), GFP_KERNEL); ++ if (!td) { ++ r = -ENOMEM; ++ goto err0; ++ } ++ ++ dev_set_drvdata(&dssdev->dev, td); ++ ++ dssdev->get_timings = taal_get_timings; ++ dssdev->get_resolution = taal_get_resolution; ++ ++ /* if no platform set_backlight() defined, presume DSI backlight ++ * control */ ++ if (!dssdev->set_backlight) ++ td->use_dsi_bl = true; ++ ++ bldev = backlight_device_register("taal", &dssdev->dev, dssdev, ++ &taal_bl_ops); ++ if (IS_ERR(bldev)) { ++ r = PTR_ERR(bldev); ++ goto err1; ++ } ++ ++ td->bldev = bldev; ++ ++ bldev->props.fb_blank = FB_BLANK_UNBLANK; ++ bldev->props.power = FB_BLANK_UNBLANK; ++ if (td->use_dsi_bl) { ++ bldev->props.max_brightness = 255; ++ bldev->props.brightness = 255; ++ } else { ++ bldev->props.max_brightness = 127; ++ bldev->props.brightness = 127; ++ } ++ ++ taal_bl_update_status(bldev); ++ ++ if (dssdev->phy.dsi.ext_te) { ++ int gpio = dssdev->phy.dsi.ext_te_gpio; ++ ++ r = gpio_request(gpio, "taal irq"); ++ if (r) { ++ dev_err(&dssdev->dev, "GPIO request failed\n"); ++ goto err2; ++ } ++ ++ gpio_direction_input(gpio); ++ ++ r = request_irq(gpio_to_irq(gpio), taal_te_isr, ++ IRQF_DISABLED | IRQF_TRIGGER_RISING, ++ "taal vsync", dssdev); ++ ++ if (r) { ++ dev_err(&dssdev->dev, "IRQ request failed\n"); ++ gpio_free(gpio); ++ goto err2; ++ } ++ ++ init_completion(&td->te_completion); ++ ++ td->use_ext_te = true; ++ } ++ ++ r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); ++ if (r) { ++ dev_err(&dssdev->dev, "failed to create sysfs files\n"); ++ goto err3; ++ } ++ ++ return 0; ++err3: ++ if (td->use_ext_te) { ++ int gpio = dssdev->phy.dsi.ext_te_gpio; ++ free_irq(gpio_to_irq(gpio), dssdev); ++ gpio_free(gpio); ++ } ++err2: ++ backlight_device_unregister(bldev); ++err1: ++ kfree(td); ++err0: ++ return r; ++} ++ ++static void taal_remove(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ struct backlight_device *bldev; ++ ++ dev_dbg(&dssdev->dev, "remove\n"); ++ ++ sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); ++ ++ if (td->use_ext_te) { ++ int gpio = dssdev->phy.dsi.ext_te_gpio; ++ free_irq(gpio_to_irq(gpio), dssdev); ++ gpio_free(gpio); ++ } ++ ++ bldev = td->bldev; ++ bldev->props.power = FB_BLANK_POWERDOWN; ++ taal_bl_update_status(bldev); ++ backlight_device_unregister(bldev); ++ ++ kfree(td); ++} ++ ++static int taal_enable(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ u8 id1, id2, id3; ++ int r; ++ ++ dev_dbg(&dssdev->dev, "enable\n"); ++ ++ if (dssdev->platform_enable) { ++ r = dssdev->platform_enable(dssdev); ++ if (r) ++ return r; ++ } ++ ++ /* it seems we have to wait a bit until taal is ready */ ++ msleep(5); ++ ++ r = taal_sleep_out(td); ++ if (r) ++ return r; ++ ++ r = taal_get_id(&id1, &id2, &id3); ++ if (r) ++ return r; ++ ++ /* on early revisions CABC is broken */ ++ if (id2 == 0x00 || id2 == 0xff || id2 == 0x81) ++ td->cabc_broken = true; ++ ++ taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); ++ taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */ ++ ++ taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ ++ ++ taal_set_addr_mode(td->rotate, td->mirror); ++ if (!td->cabc_broken) ++ taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); ++ ++ taal_dcs_write_0(DCS_DISPLAY_ON); ++ ++ td->enabled = 1; ++ ++ if (!td->intro_printed) { ++ dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n", ++ id1, id2, id3); ++ if (td->cabc_broken) ++ dev_info(&dssdev->dev, ++ "old Taal version, CABC disabled\n"); ++ td->intro_printed = true; ++ } ++ ++ return 0; ++} ++ ++static void taal_disable(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ ++ dev_dbg(&dssdev->dev, "disable\n"); ++ ++ taal_dcs_write_0(DCS_DISPLAY_OFF); ++ taal_sleep_in(td); ++ ++ /* wait a bit so that the message goes through */ ++ msleep(10); ++ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++ ++ td->enabled = 0; ++} ++ ++static int taal_suspend(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ struct backlight_device *bldev = td->bldev; ++ ++ bldev->props.power = FB_BLANK_POWERDOWN; ++ taal_bl_update_status(bldev); ++ ++ return 0; ++} ++ ++static int taal_resume(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ struct backlight_device *bldev = td->bldev; ++ ++ bldev->props.power = FB_BLANK_UNBLANK; ++ taal_bl_update_status(bldev); ++ ++ return 0; ++} ++ ++static void taal_setup_update(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ taal_set_update_window(x, y, w, h); ++} ++ ++static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ int r; ++ ++ td->te_enabled = enable; ++ ++ if (enable) ++ r = taal_dcs_write_1(DCS_TEAR_ON, 0); ++ else ++ r = taal_dcs_write_0(DCS_TEAR_OFF); ++ ++ return r; ++} ++ ++static int taal_wait_te(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ long wait = msecs_to_jiffies(500); ++ ++ if (!td->use_ext_te || !td->te_enabled) ++ return 0; ++ ++ INIT_COMPLETION(td->te_completion); ++ wait = wait_for_completion_timeout(&td->te_completion, wait); ++ if (wait == 0) { ++ dev_err(&dssdev->dev, "timeout waiting TE\n"); ++ return -ETIME; ++ } ++ ++ return 0; ++} ++ ++static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ int r; ++ ++ dev_dbg(&dssdev->dev, "rotate %d\n", rotate); ++ ++ if (td->enabled) { ++ r = taal_set_addr_mode(rotate, td->mirror); ++ ++ if (r) ++ return r; ++ } ++ ++ td->rotate = rotate; ++ ++ return 0; ++} ++ ++static u8 taal_get_rotate(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ return td->rotate; ++} ++ ++static int taal_mirror(struct omap_dss_device *dssdev, bool enable) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ int r; ++ ++ dev_dbg(&dssdev->dev, "mirror %d\n", enable); ++ ++ if (td->enabled) { ++ r = taal_set_addr_mode(td->rotate, enable); ++ ++ if (r) ++ return r; ++ } ++ ++ td->mirror = enable; ++ ++ return 0; ++} ++ ++static bool taal_get_mirror(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ return td->mirror; ++} ++ ++static int taal_run_test(struct omap_dss_device *dssdev, int test_num) ++{ ++ u8 id1, id2, id3; ++ int r; ++ ++ r = taal_dcs_read_1(DCS_GET_ID1, &id1); ++ if (r) ++ return r; ++ r = taal_dcs_read_1(DCS_GET_ID2, &id2); ++ if (r) ++ return r; ++ r = taal_dcs_read_1(DCS_GET_ID3, &id3); ++ if (r) ++ return r; ++ ++ return 0; ++} ++ ++static int taal_memory_read(struct omap_dss_device *dssdev, ++ void *buf, size_t size, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ int r; ++ int first = 1; ++ int plen; ++ unsigned buf_used = 0; ++ ++ if (size < w * h * 3) ++ return -ENOMEM; ++ ++ size = min(w * h * 3, ++ dssdev->panel.timings.x_res * ++ dssdev->panel.timings.y_res * 3); ++ ++ /* plen 1 or 2 goes into short packet. until checksum error is fixed, ++ * use short packets. plen 32 works, but bigger packets seem to cause ++ * an error. */ ++ if (size % 2) ++ plen = 1; ++ else ++ plen = 2; ++ ++ taal_setup_update(dssdev, x, y, w, h); ++ ++ r = dsi_vc_set_max_rx_packet_size(TCH, plen); ++ if (r) ++ return r; ++ ++ while (buf_used < size) { ++ u8 dcs_cmd = first ? 0x2e : 0x3e; ++ first = 0; ++ ++ r = dsi_vc_dcs_read(TCH, dcs_cmd, ++ buf + buf_used, size - buf_used); ++ ++ if (r < 0) { ++ dev_err(&dssdev->dev, "read error\n"); ++ goto err; ++ } ++ ++ buf_used += r; ++ ++ if (r < plen) { ++ dev_err(&dssdev->dev, "short read\n"); ++ break; ++ } ++ } ++ ++ r = buf_used; ++ ++err: ++ dsi_vc_set_max_rx_packet_size(TCH, 1); ++ ++ return r; ++} ++ ++static struct omap_dss_driver taal_driver = { ++ .probe = taal_probe, ++ .remove = taal_remove, ++ ++ .enable = taal_enable, ++ .disable = taal_disable, ++ .suspend = taal_suspend, ++ .resume = taal_resume, ++ ++ .setup_update = taal_setup_update, ++ .enable_te = taal_enable_te, ++ .wait_for_te = taal_wait_te, ++ .set_rotate = taal_rotate, ++ .get_rotate = taal_get_rotate, ++ .set_mirror = taal_mirror, ++ .get_mirror = taal_get_mirror, ++ .run_test = taal_run_test, ++ .memory_read = taal_memory_read, ++ ++ .driver = { ++ .name = "taal", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init taal_init(void) ++{ ++ omap_dss_register_driver(&taal_driver); ++ ++ return 0; ++} ++ ++static void __exit taal_exit(void) ++{ ++ omap_dss_unregister_driver(&taal_driver); ++} ++ ++module_init(taal_init); ++module_exit(taal_exit); ++ ++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); ++MODULE_DESCRIPTION("Taal Driver"); ++MODULE_LICENSE("GPL"); +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/dss2/0018-OMAP-SDP-Enable-DSS2-for-OMAP3-SDP-board.patch b/recipes/linux/linux-omap-2.6.31/dss2/0018-OMAP-SDP-Enable-DSS2-for-OMAP3-SDP-board.patch new file mode 100644 index 0000000000..98cd5adb79 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/dss2/0018-OMAP-SDP-Enable-DSS2-for-OMAP3-SDP-board.patch @@ -0,0 +1,327 @@ +From 8319bb7f267e0434e2d26f30b6f50ff2b0701bd1 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Date: Wed, 5 Aug 2009 16:07:26 +0300 +Subject: [PATCH 18/18] OMAP: SDP: Enable DSS2 for OMAP3 SDP board + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com> +Acked-by: Tony Lindgren <tony@atomide.com> +--- + arch/arm/configs/omap_3430sdp_defconfig | 61 +++++++++++- + arch/arm/mach-omap2/board-3430sdp.c | 172 +++++++++++++++++++++++++++--- + 2 files changed, 214 insertions(+), 19 deletions(-) + +diff --git a/arch/arm/configs/omap_3430sdp_defconfig b/arch/arm/configs/omap_3430sdp_defconfig +index 8fb918d..de063f9 100644 +--- a/arch/arm/configs/omap_3430sdp_defconfig ++++ b/arch/arm/configs/omap_3430sdp_defconfig +@@ -1314,7 +1314,56 @@ CONFIG_DVB_ISL6421=m + # + # CONFIG_VGASTATE is not set + # CONFIG_VIDEO_OUTPUT_CONTROL is not set +-# CONFIG_FB is not set ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++CONFIG_FB_CFB_FILLRECT=y ++CONFIG_FB_CFB_COPYAREA=y ++CONFIG_FB_CFB_IMAGEBLIT=y ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set ++CONFIG_OMAP2_VRAM=y ++CONFIG_OMAP2_VRFB=y ++CONFIG_OMAP2_DSS=y ++CONFIG_OMAP2_VRAM_SIZE=0 ++CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y ++# CONFIG_OMAP2_DSS_RFBI is not set ++CONFIG_OMAP2_DSS_VENC=y ++# CONFIG_OMAP2_DSS_SDI is not set ++# CONFIG_OMAP2_DSS_DSI is not set ++# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set ++CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 ++CONFIG_FB_OMAP2=y ++CONFIG_FB_OMAP2_DEBUG_SUPPORT=y ++# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set ++CONFIG_FB_OMAP2_NUM_FBS=3 ++ ++# ++# OMAP2/3 Display Device Drivers ++# ++CONFIG_PANEL_GENERIC=y ++# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set ++CONFIG_PANEL_SHARP_LS037V7DW01=y + # CONFIG_BACKLIGHT_LCD_SUPPORT is not set + + # +@@ -1331,6 +1380,16 @@ CONFIG_DISPLAY_SUPPORT=y + # + # CONFIG_VGA_CONSOLE is not set + CONFIG_DUMMY_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set ++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++CONFIG_LOGO=y ++CONFIG_LOGO_LINUX_MONO=y ++CONFIG_LOGO_LINUX_VGA16=y ++CONFIG_LOGO_LINUX_CLUT224=y + CONFIG_SOUND=y + CONFIG_SOUND_OSS_CORE=y + CONFIG_SND=y +diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c +index ac262cd..a1ebc3f 100644 +--- a/arch/arm/mach-omap2/board-3430sdp.c ++++ b/arch/arm/mach-omap2/board-3430sdp.c +@@ -36,6 +36,7 @@ + #include <mach/common.h> + #include <mach/dma.h> + #include <mach/gpmc.h> ++#include <mach/display.h> + + #include <mach/control.h> + #include <mach/keypad.h> +@@ -148,23 +149,149 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = { + }, + }; + +-static struct platform_device sdp3430_lcd_device = { +- .name = "sdp2430_lcd", +- .id = -1, ++ ++#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8 ++#define SDP3430_LCD_PANEL_ENABLE_GPIO 5 ++ ++static unsigned backlight_gpio; ++static unsigned enable_gpio; ++static int lcd_enabled; ++static int dvi_enabled; ++ ++static void __init sdp3430_display_init(void) ++{ ++ int r; ++ ++ enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO; ++ backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO; ++ ++ r = gpio_request(enable_gpio, "LCD reset"); ++ if (r) { ++ printk(KERN_ERR "failed to get LCD reset GPIO\n"); ++ goto err0; ++ } ++ ++ r = gpio_request(backlight_gpio, "LCD Backlight"); ++ if (r) { ++ printk(KERN_ERR "failed to get LCD backlight GPIO\n"); ++ goto err1; ++ } ++ ++ gpio_direction_output(enable_gpio, 0); ++ gpio_direction_output(backlight_gpio, 0); ++ ++ return; ++err1: ++ gpio_free(enable_gpio); ++err0: ++ return; ++} ++ ++static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev) ++{ ++ if (dvi_enabled) { ++ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); ++ return -EINVAL; ++ } ++ ++ gpio_direction_output(enable_gpio, 1); ++ gpio_direction_output(backlight_gpio, 1); ++ ++ lcd_enabled = 1; ++ ++ return 0; ++} ++ ++static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev) ++{ ++ lcd_enabled = 0; ++ ++ gpio_direction_output(enable_gpio, 0); ++ gpio_direction_output(backlight_gpio, 0); ++} ++ ++static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev) ++{ ++ if (lcd_enabled) { ++ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n"); ++ return -EINVAL; ++ } ++ ++ dvi_enabled = 1; ++ ++ return 0; ++} ++ ++static void sdp3430_panel_disable_dvi(struct omap_dss_device *dssdev) ++{ ++ dvi_enabled = 0; ++} ++ ++static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev) ++{ ++ return 0; ++} ++ ++static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev) ++{ ++} ++ ++ ++static struct omap_dss_device sdp3430_lcd_device = { ++ .name = "lcd", ++ .driver_name = "sharp_ls_panel", ++ .type = OMAP_DISPLAY_TYPE_DPI, ++ .phy.dpi.data_lines = 16, ++ .platform_enable = sdp3430_panel_enable_lcd, ++ .platform_disable = sdp3430_panel_disable_lcd, + }; + +-static struct regulator_consumer_supply sdp3430_vdac_supply = { +- .supply = "vdac", +- .dev = &sdp3430_lcd_device.dev, ++static struct omap_dss_device sdp3430_dvi_device = { ++ .name = "dvi", ++ .driver_name = "generic_panel", ++ .type = OMAP_DISPLAY_TYPE_DPI, ++ .phy.dpi.data_lines = 24, ++ .platform_enable = sdp3430_panel_enable_dvi, ++ .platform_disable = sdp3430_panel_disable_dvi, + }; + +-static struct regulator_consumer_supply sdp3430_vdvi_supply = { +- .supply = "vdvi", +- .dev = &sdp3430_lcd_device.dev, ++static struct omap_dss_device sdp3430_tv_device = { ++ .name = "tv", ++ .driver_name = "venc", ++ .type = OMAP_DISPLAY_TYPE_VENC, ++ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, ++ .platform_enable = sdp3430_panel_enable_tv, ++ .platform_disable = sdp3430_panel_disable_tv, + }; + +-static struct platform_device *sdp3430_devices[] __initdata = { ++ ++static struct omap_dss_device *sdp3430_dss_devices[] = { + &sdp3430_lcd_device, ++ &sdp3430_dvi_device, ++ &sdp3430_tv_device, ++}; ++ ++static struct omap_dss_board_info sdp3430_dss_data = { ++ .num_devices = ARRAY_SIZE(sdp3430_dss_devices), ++ .devices = sdp3430_dss_devices, ++ .default_device = &sdp3430_lcd_device, ++}; ++ ++static struct platform_device sdp3430_dss_device = { ++ .name = "omapdss", ++ .id = -1, ++ .dev = { ++ .platform_data = &sdp3430_dss_data, ++ }, ++}; ++ ++static struct regulator_consumer_supply sdp3430_vdda_dac_supply = { ++ .supply = "vdda_dac", ++ .dev = &sdp3430_dss_device.dev, ++}; ++ ++static struct platform_device *sdp3430_devices[] __initdata = { ++ &sdp3430_dss_device, + }; + + static void __init omap_3430sdp_init_irq(void) +@@ -178,13 +305,8 @@ static struct omap_uart_config sdp3430_uart_config __initdata = { + .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), + }; + +-static struct omap_lcd_config sdp3430_lcd_config __initdata = { +- .ctrl_name = "internal", +-}; +- + static struct omap_board_config_kernel sdp3430_config[] __initdata = { + { OMAP_TAG_UART, &sdp3430_uart_config }, +- { OMAP_TAG_LCD, &sdp3430_lcd_config }, + }; + + static int sdp3430_batt_table[] = { +@@ -391,22 +513,34 @@ static struct regulator_init_data sdp3430_vdac = { + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, +- .consumer_supplies = &sdp3430_vdac_supply, ++ .consumer_supplies = &sdp3430_vdda_dac_supply, + }; + + /* VPLL2 for digital video outputs */ ++static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = { ++ { ++ .supply = "vdvi", ++ .dev = &sdp3430_lcd_device.dev, ++ }, ++ { ++ .supply = "vdds_dsi", ++ .dev = &sdp3430_dss_device.dev, ++ } ++}; ++ + static struct regulator_init_data sdp3430_vpll2 = { + .constraints = { + .name = "VDVI", + .min_uV = 1800000, + .max_uV = 1800000, ++ .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +- .num_consumer_supplies = 1, +- .consumer_supplies = &sdp3430_vdvi_supply, ++ .num_consumer_supplies = ARRAY_SIZE(sdp3430_vpll2_supplies), ++ .consumer_supplies = sdp3430_vpll2_supplies, + }; + + static struct twl4030_platform_data sdp3430_twldata = { +@@ -495,6 +629,8 @@ static void __init omap_3430sdp_init(void) + omap_serial_init(); + usb_musb_init(); + board_smc91x_init(); ++ ++ sdp3430_display_init(); + } + + static void __init omap_3430sdp_map_io(void) +-- +1.6.2.4 + diff --git a/recipes/linux/linux-omap-2.6.31/echi.patch b/recipes/linux/linux-omap-2.6.31/echi.patch new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/echi.patch diff --git a/recipes/linux/linux-omap-2.6.31/ehci-phy-reset.patch b/recipes/linux/linux-omap-2.6.31/ehci-phy-reset.patch new file mode 100644 index 0000000000..4041c21306 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/ehci-phy-reset.patch @@ -0,0 +1,34 @@ +phy_reset is not getting updated from platform_data. + +Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com> +--- + drivers/usb/host/ehci-omap.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c +index 0058f03..55e5259 100644 +--- a/drivers/usb/host/ehci-omap.c ++++ b/drivers/usb/host/ehci-omap.c +@@ -33,7 +33,6 @@ + * - add suspend/resume + * - move workarounds to board-files + * - differentiate between ES2.x and ES3.x +- * - make it enumerate devices + */ + + #include <linux/platform_device.h> +@@ -590,6 +589,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, omap); + omap->dev = &pdev->dev; ++ omap->phy_reset = pdata->phy_reset; + omap->reset_gpio_port1 = pdata->reset_gpio_port1; + omap->reset_gpio_port2 = pdata->reset_gpio_port2; + omap->phy_mode = pdata->phy_mode; +-- +1.6.2.4 + +-- +To unsubscribe from this list: send the line "unsubscribe linux-omap" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/recipes/linux/linux-omap-2.6.31/expansion-boards/tincantools-zippy.patch b/recipes/linux/linux-omap-2.6.31/expansion-boards/tincantools-zippy.patch new file mode 100644 index 0000000000..71d96bcc86 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/expansion-boards/tincantools-zippy.patch @@ -0,0 +1,122 @@ +diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c +index 55db61e..1172887 100644 +--- a/arch/arm/mach-omap2/board-omap3beagle.c ++++ b/arch/arm/mach-omap2/board-omap3beagle.c +@@ -21,6 +21,7 @@ + #include <linux/io.h> + #include <linux/leds.h> + #include <linux/gpio.h> ++#include <linux/irq.h> + #include <linux/input.h> + #include <linux/gpio_keys.h> + +@@ -56,6 +57,49 @@ + + #define NAND_BLOCK_SIZE SZ_128K + ++#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE) ++ ++#include <mach/mcspi.h> ++#include <linux/spi/spi.h> ++ ++#define OMAP3BEAGLE_GPIO_ENC28J60_IRQ 157 ++ ++static struct omap2_mcspi_device_config enc28j60_spi_chip_info = { ++ .turbo_mode = 0, ++ .single_channel = 1, /* 0: slave, 1: master */ ++}; ++ ++static struct spi_board_info omap3beagle_spi_board_info[] __initdata = { ++ { ++ .modalias = "enc28j60", ++ .bus_num = 4, ++ .chip_select = 0, ++ .max_speed_hz = 20000000, ++ .controller_data = &enc28j60_spi_chip_info, ++ }, ++}; ++ ++static void __init omap3beagle_enc28j60_init(void) ++{ ++ if ((gpio_request(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, "ENC28J60_IRQ") == 0) && ++ (gpio_direction_input(OMAP3BEAGLE_GPIO_ENC28J60_IRQ) == 0)) { ++ gpio_export(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, 0); ++ omap3beagle_spi_board_info[0].irq = OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_ENC28J60_IRQ); ++ set_irq_type(omap3beagle_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING); ++ } else { ++ printk(KERN_ERR "could not obtain gpio for ENC28J60_IRQ\n"); ++ return; ++ } ++ ++ spi_register_board_info(omap3beagle_spi_board_info, ++ ARRAY_SIZE(omap3beagle_spi_board_info)); ++} ++ ++#else ++static inline void __init omap3beagle_enc28j60_init(void) { return; } ++#endif ++ ++ + static struct mtd_partition omap3beagle_nand_partitions[] = { + /* All the partition sizes are listed in terms of NAND block size */ + { +@@ -126,6 +170,14 @@ static struct twl4030_hsmmc_info mmc[] = { + .wires = 8, + .gpio_wp = 29, + }, ++ { ++ .mmc = 2, ++ .wires = 4, ++ .gpio_wp = 141, ++ .gpio_cd = 162, ++ .transceiver = true, ++ .ocr_mask = 0x00100000, /* 3.3V */ ++ }, + {} /* Terminator */ + }; + +@@ -289,7 +341,7 @@ static struct twl4030_platform_data beagle_twldata = { + .vpll2 = &beagle_vpll2, + }; + +-static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = { ++static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, +@@ -298,10 +350,24 @@ static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = { + }, + }; + ++#if defined(CONFIG_RTC_DRV_DS1307) || \ ++ defined(CONFIG_RTC_DRV_DS1307_MODULE) ++ ++static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = { ++ { ++ I2C_BOARD_INFO("ds1307", 0x68), ++ }, ++}; ++#else ++static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {}; ++#endif ++ + static int __init omap3_beagle_i2c_init(void) + { +- omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo, +- ARRAY_SIZE(beagle_i2c_boardinfo)); ++ omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo, ++ ARRAY_SIZE(beagle_i2c1_boardinfo)); ++ omap_register_i2c_bus(2, 400, beagle_i2c2_boardinfo, ++ ARRAY_SIZE(beagle_i2c2_boardinfo)); + /* Bus 3 is attached to the DVI port where devices like the pico DLP + * projector don't work reliably with 400kHz */ + omap_register_i2c_bus(3, 100, NULL, 0); +@@ -512,6 +578,8 @@ static void __init omap3_beagle_init(void) + + omap_cfg_reg(J25_34XX_GPIO170); + ++ omap3beagle_enc28j60_init(); ++ + usb_musb_init(); + usb_ehci_init(); + omap3beagle_flash_init(); diff --git a/recipes/linux/linux-omap-2.6.31/madc/madc-driver.patch b/recipes/linux/linux-omap-2.6.31/madc/madc-driver.patch new file mode 100644 index 0000000000..63f742e3f9 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/madc/madc-driver.patch @@ -0,0 +1,708 @@ +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 491ac0f..3605b5d 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -108,6 +108,27 @@ config TWL4030_CORE + high speed USB OTG transceiver, an audio codec (on most + versions) and many other features. + ++config TWL4030_MADC ++ tristate "TWL4030 MADC Driver" ++ depends on TWL4030_CORE ++ help ++ The TWL4030 Monitoring ADC driver enables the host ++ processor to monitor analog signals using analog-to-digital ++ conversions on the input source. TWL4030 MADC provides the ++ following features: ++ - Single 10-bit ADC with successive approximation register (SAR) conversion; ++ - Analog multiplexer for 16 inputs; ++ - Seven (of the 16) inputs are freely available; ++ - Battery voltage monitoring; ++ - Concurrent conversion request management; ++ - Interrupt signal to Primary Interrupt Handler; ++ - Averaging feature; ++ - Selective enable/disable of the averaging feature. ++ ++ Say 'y' here to statically link this module into the kernel or 'm' ++ to build it as a dinamically loadable module. The module will be ++ called twl4030-madc.ko ++ + config MFD_TMIO + bool + default n +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 6f8a9a1..e8d0ee6 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -23,6 +23,7 @@ obj-$(CONFIG_TPS65010) += tps65010.o + obj-$(CONFIG_MENELAUS) += menelaus.o + + obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o ++obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o + + obj-$(CONFIG_MFD_CORE) += mfd-core.o + +diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c +new file mode 100644 +index 0000000..551c932 +--- /dev/null ++++ b/drivers/mfd/twl4030-madc.c +@@ -0,0 +1,526 @@ ++/* ++ * TWL4030 MADC module driver ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Mikko Ylinen <mikko.k.ylinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/kernel.h> ++#include <linux/types.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/fs.h> ++#include <linux/platform_device.h> ++#include <linux/miscdevice.h> ++#include <linux/i2c/twl4030.h> ++#include <linux/i2c/twl4030-madc.h> ++ ++#include <asm/uaccess.h> ++ ++#define TWL4030_MADC_PFX "twl4030-madc: " ++ ++struct twl4030_madc_data { ++ struct device *dev; ++ struct mutex lock; ++ struct work_struct ws; ++ struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS]; ++ int imr; ++ int isr; ++}; ++ ++static struct twl4030_madc_data *the_madc; ++ ++static ++const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = { ++ [TWL4030_MADC_RT] = { ++ .sel = TWL4030_MADC_RTSELECT_LSB, ++ .avg = TWL4030_MADC_RTAVERAGE_LSB, ++ .rbase = TWL4030_MADC_RTCH0_LSB, ++ }, ++ [TWL4030_MADC_SW1] = { ++ .sel = TWL4030_MADC_SW1SELECT_LSB, ++ .avg = TWL4030_MADC_SW1AVERAGE_LSB, ++ .rbase = TWL4030_MADC_GPCH0_LSB, ++ .ctrl = TWL4030_MADC_CTRL_SW1, ++ }, ++ [TWL4030_MADC_SW2] = { ++ .sel = TWL4030_MADC_SW2SELECT_LSB, ++ .avg = TWL4030_MADC_SW2AVERAGE_LSB, ++ .rbase = TWL4030_MADC_GPCH0_LSB, ++ .ctrl = TWL4030_MADC_CTRL_SW2, ++ }, ++}; ++ ++static int twl4030_madc_read(struct twl4030_madc_data *madc, u8 reg) ++{ ++ int ret; ++ u8 val; ++ ++ ret = twl4030_i2c_read_u8(TWL4030_MODULE_MADC, &val, reg); ++ if (ret) { ++ dev_dbg(madc->dev, "unable to read register 0x%X\n", reg); ++ return ret; ++ } ++ ++ return val; ++} ++ ++static void twl4030_madc_write(struct twl4030_madc_data *madc, u8 reg, u8 val) ++{ ++ int ret; ++ ++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, val, reg); ++ if (ret) ++ dev_err(madc->dev, "unable to write register 0x%X\n", reg); ++} ++ ++static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg) ++{ ++ u8 msb, lsb; ++ ++ /* For each ADC channel, we have MSB and LSB register pair. MSB address ++ * is always LSB address+1. reg parameter is the addr of LSB register */ ++ msb = twl4030_madc_read(madc, reg + 1); ++ lsb = twl4030_madc_read(madc, reg); ++ ++ return (int)(((msb << 8) | lsb) >> 6); ++} ++ ++static int twl4030_madc_read_channels(struct twl4030_madc_data *madc, ++ u8 reg_base, u16 channels, int *buf) ++{ ++ int count = 0; ++ u8 reg, i; ++ ++ if (unlikely(!buf)) ++ return 0; ++ ++ for (i = 0; i < TWL4030_MADC_MAX_CHANNELS; i++) { ++ if (channels & (1<<i)) { ++ reg = reg_base + 2*i; ++ buf[i] = twl4030_madc_channel_raw_read(madc, reg); ++ count++; ++ } ++ } ++ return count; ++} ++ ++static void twl4030_madc_enable_irq(struct twl4030_madc_data *madc, int id) ++{ ++ u8 val; ++ ++ val = twl4030_madc_read(madc, madc->imr); ++ val &= ~(1 << id); ++ twl4030_madc_write(madc, madc->imr, val); ++} ++ ++static void twl4030_madc_disable_irq(struct twl4030_madc_data *madc, int id) ++{ ++ u8 val; ++ ++ val = twl4030_madc_read(madc, madc->imr); ++ val |= (1 << id); ++ twl4030_madc_write(madc, madc->imr, val); ++} ++ ++static irqreturn_t twl4030_madc_irq_handler(int irq, void *_madc) ++{ ++ struct twl4030_madc_data *madc = _madc; ++ u8 isr_val, imr_val; ++ int i; ++ ++#ifdef CONFIG_LOCKDEP ++ /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which ++ * we don't want and can't tolerate. Although it might be ++ * friendlier not to borrow this thread context... ++ */ ++ local_irq_enable(); ++#endif ++ ++ /* Use COR to ack interrupts since we have no shared IRQs in ISRx */ ++ isr_val = twl4030_madc_read(madc, madc->isr); ++ imr_val = twl4030_madc_read(madc, madc->imr); ++ ++ isr_val &= ~imr_val; ++ ++ for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) { ++ ++ if (!(isr_val & (1<<i))) ++ continue; ++ ++ twl4030_madc_disable_irq(madc, i); ++ madc->requests[i].result_pending = 1; ++ } ++ ++ schedule_work(&madc->ws); ++ ++ return IRQ_HANDLED; ++} ++ ++static void twl4030_madc_work(struct work_struct *ws) ++{ ++ const struct twl4030_madc_conversion_method *method; ++ struct twl4030_madc_data *madc; ++ struct twl4030_madc_request *r; ++ int len, i; ++ ++ madc = container_of(ws, struct twl4030_madc_data, ws); ++ mutex_lock(&madc->lock); ++ ++ for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) { ++ ++ r = &madc->requests[i]; ++ ++ /* No pending results for this method, move to next one */ ++ if (!r->result_pending) ++ continue; ++ ++ method = &twl4030_conversion_methods[r->method]; ++ ++ /* Read results */ ++ len = twl4030_madc_read_channels(madc, method->rbase, ++ r->channels, r->rbuf); ++ ++ /* Return results to caller */ ++ if (r->func_cb != NULL) { ++ r->func_cb(len, r->channels, r->rbuf); ++ r->func_cb = NULL; ++ } ++ ++ /* Free request */ ++ r->result_pending = 0; ++ r->active = 0; ++ } ++ ++ mutex_unlock(&madc->lock); ++} ++ ++static int twl4030_madc_set_irq(struct twl4030_madc_data *madc, ++ struct twl4030_madc_request *req) ++{ ++ struct twl4030_madc_request *p; ++ ++ p = &madc->requests[req->method]; ++ ++ memcpy(p, req, sizeof *req); ++ ++ twl4030_madc_enable_irq(madc, req->method); ++ ++ return 0; ++} ++ ++static inline void twl4030_madc_start_conversion(struct twl4030_madc_data *madc, ++ int conv_method) ++{ ++ const struct twl4030_madc_conversion_method *method; ++ ++ method = &twl4030_conversion_methods[conv_method]; ++ ++ switch (conv_method) { ++ case TWL4030_MADC_SW1: ++ case TWL4030_MADC_SW2: ++ twl4030_madc_write(madc, method->ctrl, TWL4030_MADC_SW_START); ++ break; ++ case TWL4030_MADC_RT: ++ default: ++ break; ++ } ++} ++ ++static int twl4030_madc_wait_conversion_ready( ++ struct twl4030_madc_data *madc, ++ unsigned int timeout_ms, u8 status_reg) ++{ ++ unsigned long timeout; ++ ++ timeout = jiffies + msecs_to_jiffies(timeout_ms); ++ do { ++ u8 reg; ++ ++ reg = twl4030_madc_read(madc, status_reg); ++ if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW)) ++ return 0; ++ } while (!time_after(jiffies, timeout)); ++ ++ return -EAGAIN; ++} ++ ++int twl4030_madc_conversion(struct twl4030_madc_request *req) ++{ ++ const struct twl4030_madc_conversion_method *method; ++ u8 ch_msb, ch_lsb; ++ int ret; ++ ++ if (unlikely(!req)) ++ return -EINVAL; ++ ++ mutex_lock(&the_madc->lock); ++ ++ /* Do we have a conversion request ongoing */ ++ if (the_madc->requests[req->method].active) { ++ ret = -EBUSY; ++ goto out; ++ } ++ ++ ch_msb = (req->channels >> 8) & 0xff; ++ ch_lsb = req->channels & 0xff; ++ ++ method = &twl4030_conversion_methods[req->method]; ++ ++ /* Select channels to be converted */ ++ twl4030_madc_write(the_madc, method->sel + 1, ch_msb); ++ twl4030_madc_write(the_madc, method->sel, ch_lsb); ++ ++ /* Select averaging for all channels if do_avg is set */ ++ if (req->do_avg) { ++ twl4030_madc_write(the_madc, method->avg + 1, ch_msb); ++ twl4030_madc_write(the_madc, method->avg, ch_lsb); ++ } ++ ++ if ((req->type == TWL4030_MADC_IRQ_ONESHOT) && (req->func_cb != NULL)) { ++ twl4030_madc_set_irq(the_madc, req); ++ twl4030_madc_start_conversion(the_madc, req->method); ++ the_madc->requests[req->method].active = 1; ++ ret = 0; ++ goto out; ++ } ++ ++ /* With RT method we should not be here anymore */ ++ if (req->method == TWL4030_MADC_RT) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ twl4030_madc_start_conversion(the_madc, req->method); ++ the_madc->requests[req->method].active = 1; ++ ++ /* Wait until conversion is ready (ctrl register returns EOC) */ ++ ret = twl4030_madc_wait_conversion_ready(the_madc, 5, method->ctrl); ++ if (ret) { ++ dev_dbg(the_madc->dev, "conversion timeout!\n"); ++ the_madc->requests[req->method].active = 0; ++ goto out; ++ } ++ ++ ret = twl4030_madc_read_channels(the_madc, method->rbase, req->channels, ++ req->rbuf); ++ ++ the_madc->requests[req->method].active = 0; ++ ++out: ++ mutex_unlock(&the_madc->lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(twl4030_madc_conversion); ++ ++static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc, ++ int chan, int on) ++{ ++ int ret; ++ u8 regval; ++ ++ /* Current generator is only available for ADCIN0 and ADCIN1. NB: ++ * ADCIN1 current generator only works when AC or VBUS is present */ ++ if (chan > 1) ++ return EINVAL; ++ ++ ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, ++ ®val, TWL4030_BCI_BCICTL1); ++ if (on) ++ regval |= (chan) ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN; ++ else ++ regval &= (chan) ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN; ++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, ++ regval, TWL4030_BCI_BCICTL1); ++ ++ return ret; ++} ++ ++static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on) ++{ ++ u8 regval; ++ ++ regval = twl4030_madc_read(madc, TWL4030_MADC_CTRL1); ++ if (on) ++ regval |= TWL4030_MADC_MADCON; ++ else ++ regval &= ~TWL4030_MADC_MADCON; ++ twl4030_madc_write(madc, TWL4030_MADC_CTRL1, regval); ++ ++ return 0; ++} ++ ++static long twl4030_madc_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct twl4030_madc_user_parms par; ++ int val, ret; ++ ++ ret = copy_from_user(&par, (void __user *) arg, sizeof(par)); ++ if (ret) { ++ dev_dbg(the_madc->dev, "copy_from_user: %d\n", ret); ++ return -EACCES; ++ } ++ ++ switch (cmd) { ++ case TWL4030_MADC_IOCX_ADC_RAW_READ: { ++ struct twl4030_madc_request req; ++ if (par.channel >= TWL4030_MADC_MAX_CHANNELS) ++ return -EINVAL; ++ ++ req.channels = (1 << par.channel); ++ req.do_avg = par.average; ++ req.method = TWL4030_MADC_SW1; ++ req.func_cb = NULL; ++ ++ val = twl4030_madc_conversion(&req); ++ if (val <= 0) { ++ par.status = -1; ++ } else { ++ par.status = 0; ++ par.result = (u16)req.rbuf[par.channel]; ++ } ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ ++ ret = copy_to_user((void __user *) arg, &par, sizeof(par)); ++ if (ret) { ++ dev_dbg(the_madc->dev, "copy_to_user: %d\n", ret); ++ return -EACCES; ++ } ++ ++ return 0; ++} ++ ++static struct file_operations twl4030_madc_fileops = { ++ .owner = THIS_MODULE, ++ .unlocked_ioctl = twl4030_madc_ioctl ++}; ++ ++static struct miscdevice twl4030_madc_device = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "twl4030-madc", ++ .fops = &twl4030_madc_fileops ++}; ++ ++static int __init twl4030_madc_probe(struct platform_device *pdev) ++{ ++ struct twl4030_madc_data *madc; ++ struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data; ++ int ret; ++ u8 regval; ++ ++ madc = kzalloc(sizeof *madc, GFP_KERNEL); ++ if (!madc) ++ return -ENOMEM; ++ ++ if (!pdata) { ++ dev_dbg(&pdev->dev, "platform_data not available\n"); ++ ret = -EINVAL; ++ goto err_pdata; ++ } ++ ++ madc->imr = (pdata->irq_line == 1) ? TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2; ++ madc->isr = (pdata->irq_line == 1) ? TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2; ++ ++ ret = misc_register(&twl4030_madc_device); ++ if (ret) { ++ dev_dbg(&pdev->dev, "could not register misc_device\n"); ++ goto err_misc; ++ } ++ twl4030_madc_set_power(madc, 1); ++ twl4030_madc_set_current_generator(madc, 0, 1); ++ ++ ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, ++ ®val, TWL4030_BCI_BCICTL1); ++ ++ regval |= TWL4030_BCI_MESBAT; ++ ++ ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, ++ regval, TWL4030_BCI_BCICTL1); ++ ++ ret = request_irq(platform_get_irq(pdev, 0), twl4030_madc_irq_handler, ++ 0, "twl4030_madc", madc); ++ if (ret) { ++ dev_dbg(&pdev->dev, "could not request irq\n"); ++ goto err_irq; ++ } ++ ++ platform_set_drvdata(pdev, madc); ++ mutex_init(&madc->lock); ++ INIT_WORK(&madc->ws, twl4030_madc_work); ++ ++ the_madc = madc; ++ ++ return 0; ++ ++err_irq: ++ misc_deregister(&twl4030_madc_device); ++ ++err_misc: ++err_pdata: ++ kfree(madc); ++ ++ return ret; ++} ++ ++static int __exit twl4030_madc_remove(struct platform_device *pdev) ++{ ++ struct twl4030_madc_data *madc = platform_get_drvdata(pdev); ++ ++ twl4030_madc_set_power(madc, 0); ++ twl4030_madc_set_current_generator(madc, 0, 0); ++ free_irq(platform_get_irq(pdev, 0), madc); ++ cancel_work_sync(&madc->ws); ++ misc_deregister(&twl4030_madc_device); ++ ++ return 0; ++} ++ ++static struct platform_driver twl4030_madc_driver = { ++ .probe = twl4030_madc_probe, ++ .remove = __exit_p(twl4030_madc_remove), ++ .driver = { ++ .name = "twl4030_madc", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init twl4030_madc_init(void) ++{ ++ return platform_driver_register(&twl4030_madc_driver); ++} ++module_init(twl4030_madc_init); ++ ++static void __exit twl4030_madc_exit(void) ++{ ++ platform_driver_unregister(&twl4030_madc_driver); ++} ++module_exit(twl4030_madc_exit); ++ ++MODULE_ALIAS("platform:twl4030-madc"); ++MODULE_AUTHOR("Nokia Corporation"); ++MODULE_DESCRIPTION("twl4030 ADC driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/include/linux/i2c/twl4030-madc.h b/include/linux/i2c/twl4030-madc.h +new file mode 100644 +index 0000000..24523b5 +--- /dev/null ++++ b/include/linux/i2c/twl4030-madc.h +@@ -0,0 +1,126 @@ ++/* ++ * include/linux/i2c/twl4030-madc.h ++ * ++ * TWL4030 MADC module driver header ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Mikko Ylinen <mikko.k.ylinen@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ */ ++ ++#ifndef _TWL4030_MADC_H ++#define _TWL4030_MADC_H ++ ++struct twl4030_madc_conversion_method { ++ u8 sel; ++ u8 avg; ++ u8 rbase; ++ u8 ctrl; ++}; ++ ++#define TWL4030_MADC_MAX_CHANNELS 16 ++ ++struct twl4030_madc_request { ++ u16 channels; ++ u16 do_avg; ++ u16 method; ++ u16 type; ++ int active; ++ int result_pending; ++ int rbuf[TWL4030_MADC_MAX_CHANNELS]; ++ void (*func_cb)(int len, int channels, int *buf); ++}; ++ ++enum conversion_methods { ++ TWL4030_MADC_RT, ++ TWL4030_MADC_SW1, ++ TWL4030_MADC_SW2, ++ TWL4030_MADC_NUM_METHODS ++}; ++ ++enum sample_type { ++ TWL4030_MADC_WAIT, ++ TWL4030_MADC_IRQ_ONESHOT, ++ TWL4030_MADC_IRQ_REARM ++}; ++ ++#define TWL4030_MADC_CTRL1 0x00 ++#define TWL4030_MADC_CTRL2 0x01 ++ ++#define TWL4030_MADC_RTSELECT_LSB 0x02 ++#define TWL4030_MADC_SW1SELECT_LSB 0x06 ++#define TWL4030_MADC_SW2SELECT_LSB 0x0A ++ ++#define TWL4030_MADC_RTAVERAGE_LSB 0x04 ++#define TWL4030_MADC_SW1AVERAGE_LSB 0x08 ++#define TWL4030_MADC_SW2AVERAGE_LSB 0x0C ++ ++#define TWL4030_MADC_CTRL_SW1 0x12 ++#define TWL4030_MADC_CTRL_SW2 0x13 ++ ++#define TWL4030_MADC_RTCH0_LSB 0x17 ++#define TWL4030_MADC_GPCH0_LSB 0x37 ++ ++#define TWL4030_MADC_MADCON (1<<0) /* MADC power on */ ++#define TWL4030_MADC_BUSY (1<<0) /* MADC busy */ ++#define TWL4030_MADC_EOC_SW (1<<1) /* MADC conversion completion */ ++#define TWL4030_MADC_SW_START (1<<5) /* MADC SWx start conversion */ ++ ++#define TWL4030_MADC_ADCIN0 (1<<0) ++#define TWL4030_MADC_ADCIN1 (1<<1) ++#define TWL4030_MADC_ADCIN2 (1<<2) ++#define TWL4030_MADC_ADCIN3 (1<<3) ++#define TWL4030_MADC_ADCIN4 (1<<4) ++#define TWL4030_MADC_ADCIN5 (1<<5) ++#define TWL4030_MADC_ADCIN6 (1<<6) ++#define TWL4030_MADC_ADCIN7 (1<<7) ++#define TWL4030_MADC_ADCIN8 (1<<8) ++#define TWL4030_MADC_ADCIN9 (1<<9) ++#define TWL4030_MADC_ADCIN10 (1<<10) ++#define TWL4030_MADC_ADCIN11 (1<<11) ++#define TWL4030_MADC_ADCIN12 (1<<12) ++#define TWL4030_MADC_ADCIN13 (1<<13) ++#define TWL4030_MADC_ADCIN14 (1<<14) ++#define TWL4030_MADC_ADCIN15 (1<<15) ++ ++/* Fixed channels */ ++#define TWL4030_MADC_BTEMP TWL4030_MADC_ADCIN1 ++#define TWL4030_MADC_VBUS TWL4030_MADC_ADCIN8 ++#define TWL4030_MADC_VBKB TWL4030_MADC_ADCIN9 ++#define TWL4030_MADC_ICHG TWL4030_MADC_ADCIN10 ++#define TWL4030_MADC_VCHG TWL4030_MADC_ADCIN11 ++#define TWL4030_MADC_VBAT TWL4030_MADC_ADCIN12 ++ ++/* BCI related - XXX To be moved elsewhere */ ++#define TWL4030_BCI_BCICTL1 0x23 ++#define TWL4030_BCI_MESBAT (1<<1) ++#define TWL4030_BCI_TYPEN (1<<4) ++#define TWL4030_BCI_ITHEN (1<<3) ++ ++#define TWL4030_MADC_IOC_MAGIC '`' ++#define TWL4030_MADC_IOCX_ADC_RAW_READ _IO(TWL4030_MADC_IOC_MAGIC, 0) ++ ++struct twl4030_madc_user_parms { ++ int channel; ++ int average; ++ int status; ++ u16 result; ++}; ++ ++int twl4030_madc_conversion(struct twl4030_madc_request *conv); ++ ++#endif diff --git a/recipes/linux/linux-omap-2.6.31/madc/madc.patch b/recipes/linux/linux-omap-2.6.31/madc/madc.patch new file mode 100644 index 0000000000..dbbd50f662 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/madc/madc.patch @@ -0,0 +1,56 @@ +diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c +index 48f9932..ce84ee7 100644 +--- a/arch/arm/mach-omap2/board-overo.c ++++ b/arch/arm/mach-omap2/board-overo.c +@@ -340,10 +340,15 @@ static struct regulator_init_data overo_vmmc1 = { + + /* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */ + ++static struct twl4030_madc_platform_data overo_madc_data = { ++ .irq_line = 1, ++}; ++ + static struct twl4030_platform_data overo_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + .gpio = &overo_gpio_data, ++ .madc = &overo_madc_data, + .usb = &overo_usb_data, + .power = GENERIC3430_T2SCRIPTS_DATA, + .vmmc1 = &overo_vmmc1, +diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c +index 769b34b..c5ca36d 100644 +--- a/drivers/mfd/twl4030-core.c ++++ b/drivers/mfd/twl4030-core.c +@@ -159,6 +159,7 @@ + + /* Few power values */ + #define R_CFG_BOOT 0x05 ++#define R_GPBR1 0x0C + #define R_PROTECT_KEY 0x0E + + /* access control values for R_PROTECT_KEY */ +@@ -166,6 +167,10 @@ + #define KEY_UNLOCK2 0xec + #define KEY_LOCK 0x00 + ++/* MADC clock values for R_GPBR1 */ ++#define MADC_HFCLK_EN 0x80 ++#define DEFAULT_MADC_CLK_EN 0x10 ++ + /* some fields in R_CFG_BOOT */ + #define HFCLK_FREQ_19p2_MHZ (1 << 0) + #define HFCLK_FREQ_26_MHZ (2 << 0) +@@ -717,6 +722,11 @@ static void __init clocks_init(struct device *dev) + ctrl |= HIGH_PERF_SQ; + e |= unprotect_pm_master(); + /* effect->MADC+USB ck en */ ++ ++ if (twl_has_madc()) ++ e |= twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, ++ MADC_HFCLK_EN | DEFAULT_MADC_CLK_EN, R_GPBR1); ++ + e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT); + e |= protect_pm_master(); + + diff --git a/recipes/linux/linux-omap-2.6.31/overo/ehci.patch b/recipes/linux/linux-omap-2.6.31/overo/ehci.patch new file mode 100644 index 0000000000..2fec9d3cc8 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.31/overo/ehci.patch @@ -0,0 +1,47 @@ +From 01984da4f7009c118c18fa251b703de74f26ced2 Mon Sep 17 00:00:00 2001 +From: Steve Sakoman <steve@sakoman.com> +Date: Sun, 16 Aug 2009 14:19:55 -0700 +Subject: [PATCH] ARM: OMAP3: Fix EHCI initialization for Overo + +Overo uses port 2, not port 1. Use OVERO_GPIO_USBH_NRESET rather than hard coded value + +Note: this alone will not give functional EHCI. Also required is: + +[PATCH 4/9] ehci: fix phy_reset init in ehci probe +from Ajay Kumar Gupta +--- + arch/arm/mach-omap2/board-overo.c | 11 ++--------- + 1 files changed, 2 insertions(+), 9 deletions(-) + +diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c +index a9d7c2e..a220a54 100644 +--- a/arch/arm/mach-omap2/board-overo.c ++++ b/arch/arm/mach-omap2/board-overo.c +@@ -394,7 +394,8 @@ static void __init overo_init(void) + omap_serial_init(&overo_uart_config); + overo_flash_init(); + usb_musb_init(); +- usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, false, true, 183, -EINVAL); ++ usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, false, true, ++ -EINVAL, OVERO_GPIO_USBH_NRESET); + overo_ads7846_init(); + overo_init_smsc911x(); + +@@ -437,14 +438,6 @@ static void __init overo_init(void) + else + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_USBH_CPEN\n"); +- +- if ((gpio_request(OVERO_GPIO_USBH_NRESET, +- "OVERO_GPIO_USBH_NRESET") == 0) && +- (gpio_direction_output(OVERO_GPIO_USBH_NRESET, 1) == 0)) +- gpio_export(OVERO_GPIO_USBH_NRESET, 0); +- else +- printk(KERN_ERR "could not obtain gpio for " +- "OVERO_GPIO_USBH_NRESET\n"); + } + + static void __init overo_map_io(void) +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch b/recipes/linux/linux-omap-pm-2.6.29/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch deleted file mode 100644 index 7852f0afdb..0000000000 --- a/recipes/linux/linux-omap-pm-2.6.29/0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch +++ /dev/null @@ -1,287 +0,0 @@ -From 8a7643b09856f4f661403dcedbe0455b3cbeeea9 Mon Sep 17 00:00:00 2001 -From: Steven Newbury <s_j_newbury@yahoo.co.uk> -Date: Fri, 22 May 2009 14:25:40 +0200 -Subject: [PATCH] implement TIF_RESTORE_SIGMASK support and enable the related - syscalls: - -pselect6 -ppoll -epoll_pwait - -Based on http://www.spinics.net/lists/arm-kernel/msg38114.html ---- - arch/arm/include/asm/thread_info.h | 2 + - arch/arm/include/asm/unistd.h | 7 ++- - arch/arm/kernel/calls.S | 6 +- - arch/arm/kernel/signal.c | 90 +++++++++++++++--------------------- - 4 files changed, 46 insertions(+), 59 deletions(-) - -diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h -index 4f88482..2cf0917 100644 ---- a/arch/arm/include/asm/thread_info.h -+++ b/arch/arm/include/asm/thread_info.h -@@ -136,6 +136,7 @@ extern void vfp_sync_state(struct thread_info *thread); - #define TIF_SIGPENDING 0 - #define TIF_NEED_RESCHED 1 - #define TIF_SYSCALL_TRACE 8 -+#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal */ - #define TIF_POLLING_NRFLAG 16 - #define TIF_USING_IWMMXT 17 - #define TIF_MEMDIE 18 -@@ -144,6 +145,7 @@ extern void vfp_sync_state(struct thread_info *thread); - #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) - #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) - #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) -+#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) - #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) - #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) - #define _TIF_FREEZE (1 << TIF_FREEZE) -diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h -index 94cc58e..cd1eaa0 100644 ---- a/arch/arm/include/asm/unistd.h -+++ b/arch/arm/include/asm/unistd.h -@@ -360,8 +360,8 @@ - #define __NR_readlinkat (__NR_SYSCALL_BASE+332) - #define __NR_fchmodat (__NR_SYSCALL_BASE+333) - #define __NR_faccessat (__NR_SYSCALL_BASE+334) -- /* 335 for pselect6 */ -- /* 336 for ppoll */ -+#define __NR_pselect6 (__NR_SYSCALL_BASE+335) -+#define __NR_ppoll (__NR_SYSCALL_BASE+336) - #define __NR_unshare (__NR_SYSCALL_BASE+337) - #define __NR_set_robust_list (__NR_SYSCALL_BASE+338) - #define __NR_get_robust_list (__NR_SYSCALL_BASE+339) -@@ -372,7 +372,7 @@ - #define __NR_vmsplice (__NR_SYSCALL_BASE+343) - #define __NR_move_pages (__NR_SYSCALL_BASE+344) - #define __NR_getcpu (__NR_SYSCALL_BASE+345) -- /* 346 for epoll_pwait */ -+#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346) - #define __NR_kexec_load (__NR_SYSCALL_BASE+347) - #define __NR_utimensat (__NR_SYSCALL_BASE+348) - #define __NR_signalfd (__NR_SYSCALL_BASE+349) -@@ -430,6 +430,7 @@ - #define __ARCH_WANT_SYS_SIGPENDING - #define __ARCH_WANT_SYS_SIGPROCMASK - #define __ARCH_WANT_SYS_RT_SIGACTION -+#define __ARCH_WANT_SYS_RT_SIGSUSPEND - - #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) - #define __ARCH_WANT_SYS_TIME -diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S -index 1680e9e..534000d 100644 ---- a/arch/arm/kernel/calls.S -+++ b/arch/arm/kernel/calls.S -@@ -344,8 +344,8 @@ - CALL(sys_readlinkat) - CALL(sys_fchmodat) - CALL(sys_faccessat) --/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */ -- CALL(sys_ni_syscall) /* eventually ppoll */ -+/* 335 */ CALL(sys_pselect6) -+ CALL(sys_ppoll) - CALL(sys_unshare) - CALL(sys_set_robust_list) - CALL(sys_get_robust_list) -@@ -355,7 +355,7 @@ - CALL(sys_vmsplice) - CALL(sys_move_pages) - /* 345 */ CALL(sys_getcpu) -- CALL(sys_ni_syscall) /* eventually epoll_pwait */ -+ CALL(sys_epoll_pwait) - CALL(sys_kexec_load) - CALL(sys_utimensat) - CALL(sys_signalfd) -diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c -index 80b8b5c..7645048 100644 ---- a/arch/arm/kernel/signal.c -+++ b/arch/arm/kernel/signal.c -@@ -47,57 +47,23 @@ const unsigned long sigreturn_codes[7] = { - MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, - }; - --static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall); -+static void do_signal(struct pt_regs * regs, int syscall); - - /* - * atomically swap in the new signal mask, and wait for a signal. - */ --asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs) -+asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) - { -- sigset_t saveset; -- - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); -- saveset = current->blocked; -+ current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); -- regs->ARM_r0 = -EINTR; -- -- while (1) { -- current->state = TASK_INTERRUPTIBLE; -- schedule(); -- if (do_signal(&saveset, regs, 0)) -- return regs->ARM_r0; -- } --} -- --asmlinkage int --sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs) --{ -- sigset_t saveset, newset; -- -- /* XXX: Don't preclude handling different sized sigset_t's. */ -- if (sigsetsize != sizeof(sigset_t)) -- return -EINVAL; -- -- if (copy_from_user(&newset, unewset, sizeof(newset))) -- return -EFAULT; -- sigdelsetmask(&newset, ~_BLOCKABLE); -- -- spin_lock_irq(¤t->sighand->siglock); -- saveset = current->blocked; -- current->blocked = newset; -- recalc_sigpending(); -- spin_unlock_irq(¤t->sighand->siglock); -- regs->ARM_r0 = -EINTR; -- -- while (1) { -- current->state = TASK_INTERRUPTIBLE; -- schedule(); -- if (do_signal(&saveset, regs, 0)) -- return regs->ARM_r0; -- } -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ set_thread_flag(TIF_RESTORE_SIGMASK); -+ return -ERESTARTNOHAND; - } - - asmlinkage int -@@ -290,7 +256,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) - - badframe: - force_sig(SIGSEGV, current); -- return 0; -+ return -EFAULT; - } - - asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) -@@ -325,7 +291,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) - - badframe: - force_sig(SIGSEGV, current); -- return 0; -+ return -EFAULT; - } - - static int -@@ -541,7 +507,7 @@ static inline void restart_syscall(struct pt_regs *regs) - /* - * OK, we're invoking a handler - */ --static void -+static int - handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs, int syscall) -@@ -592,7 +558,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, - - if (ret != 0) { - force_sigsegv(sig, tsk); -- return; -+ return ret; - } - - /* -@@ -606,6 +572,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, - recalc_sigpending(); - spin_unlock_irq(&tsk->sighand->siglock); - -+ return ret; - } - - /* -@@ -617,11 +584,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, - * the kernel can handle, and then we build all the user-level signal handling - * stack-frames in one go after that. - */ --static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) -+static void do_signal(struct pt_regs *regs, int syscall) - { - struct k_sigaction ka; - siginfo_t info; - int signr; -+ sigset_t *oldset; - - /* - * We want the common case to go fast, which -@@ -630,18 +598,29 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) - * if so. - */ - if (!user_mode(regs)) -- return 0; -+ return; - - if (try_to_freeze()) - goto no_signal; - - single_step_clear(current); - -+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) -+ oldset = ¤t->saved_sigmask; -+ else -+ oldset = ¤t->blocked; -+ - signr = get_signal_to_deliver(&info, &ka, regs, NULL); - if (signr > 0) { -- handle_signal(signr, &ka, &info, oldset, regs, syscall); -+ if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { -+ /* a signal was successfully delivered; the saved -+ * sigmask will have been stored in the signal frame, -+ * and will be restored by sigreturn, so we can simply -+ * clear the TIF_RESTORE_SIGMASK flag */ -+ clear_thread_flag(TIF_RESTORE_SIGMASK); -+ } - single_step_set(current); -- return 1; -+ return; - } - - no_signal: -@@ -665,7 +644,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) - usp = (u32 __user *)regs->ARM_sp; - - /* -- * Either we supports OABI only, or we have -+ * Either we support OABI only, or we have - * EABI with the OABI compat layer enabled. - * In the later case we don't know if user - * space is EABI or not, and if not we must -@@ -695,12 +674,17 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) - } - } - single_step_set(current); -- return 0; -+ /* if there's no signal to deliver, we just put the saved sigmask -+ back. */ -+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { -+ clear_thread_flag(TIF_RESTORE_SIGMASK); -+ sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); -+ } - } - - asmlinkage void - do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall) - { -- if (thread_flags & _TIF_SIGPENDING) -- do_signal(¤t->blocked, regs, syscall); -+ if (thread_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK)) -+ do_signal(regs, syscall); - } --- -1.6.2.4 - diff --git a/recipes/linux/linux-omap-pm-2.6.29/beagleboard/defconfig b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/defconfig index ca5adf229e..9cb8ab5bc9 100644 --- a/recipes/linux/linux-omap-pm-2.6.29/beagleboard/defconfig +++ b/recipes/linux/linux-omap-pm-2.6.29/beagleboard/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.29-omap1 -# Mon Aug 17 17:49:14 2009 +# Wed Sep 2 21:59:02 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -199,7 +199,7 @@ CONFIG_OMAP_BOOT_REASON=y # CONFIG_OMAP_MUX is not set CONFIG_OMAP_MCBSP=y # CONFIG_OMAP_MBOX_FWK is not set -# CONFIG_OMAP_IOMMU is not set +CONFIG_OMAP_IOMMU=m # CONFIG_OMAP_MPU_TIMER is not set CONFIG_OMAP_32K_TIMER=y # CONFIG_OMAP3_DEBOBS is not set @@ -253,6 +253,7 @@ CONFIG_ARM_THUMBEE=y # CONFIG_CPU_BPREDICT_DISABLE is not set CONFIG_HAS_TLS_REG=y # CONFIG_OUTER_CACHE is not set +CONFIG_ARM_L1_CACHE_SHIFT=6 # # Bus support @@ -1514,6 +1515,7 @@ CONFIG_MEDIA_TUNER_MXL5005S=m CONFIG_VIDEO_V4L2=m CONFIG_VIDEO_V4L1=m CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_DMA_SG=m CONFIG_VIDEOBUF_VMALLOC=m CONFIG_VIDEOBUF_DVB=m CONFIG_VIDEO_IR=m @@ -1537,8 +1539,8 @@ CONFIG_VIDEO_VIVI=m # CONFIG_VIDEO_SAA5246A is not set # CONFIG_VIDEO_SAA5249 is not set # CONFIG_VIDEO_AU0828 is not set -# CONFIG_VIDEO_OMAP3 is not set -# CONFIG_VIDEO_OMAP34XX_ISP_RESIZER is not set +CONFIG_VIDEO_OMAP3=m +CONFIG_VIDEO_OMAP34XX_ISP_RESIZER=m # CONFIG_SOC_CAMERA is not set CONFIG_V4L_USB_DRIVERS=y CONFIG_USB_VIDEO_CLASS=m @@ -2136,6 +2138,7 @@ CONFIG_USB_OTG_UTILS=y CONFIG_USB_GPIO_VBUS=y # CONFIG_ISP1301_OMAP is not set CONFIG_TWL4030_USB=y +# CONFIG_NOP_USB_XCEIV is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set CONFIG_MMC_UNSAFE_RESUME=y diff --git a/recipes/linux/linux-omap-pm-2.6.29/cache/copy-page-tweak.patch b/recipes/linux/linux-omap-pm-2.6.29/cache/copy-page-tweak.patch new file mode 100644 index 0000000000..9da374041c --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/cache/copy-page-tweak.patch @@ -0,0 +1,169 @@ +Path: news.gmane.org!not-for-mail +From: "Kirill A. Shutemov" <kirill@shutemov.name> +Newsgroups: gmane.linux.ports.arm.kernel +Subject: [PATCH] ARM: copy_page.S: take into account the size of the cache line +Date: Wed, 2 Sep 2009 20:19:58 +0300 +Lines: 92 +Approved: news@gmane.org +Message-ID: <1251911998-3112-1-git-send-email-kirill__11898.5180197798$1251901300$gmane$org@shutemov.name> +References: <20090902132423.GA12595@n2100.arm.linux.org.uk> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +X-Trace: ger.gmane.org 1251901300 3930 80.91.229.12 (2 Sep 2009 14:21:40 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 2 Sep 2009 14:21:40 +0000 (UTC) +Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>, + "Kirill A. Shutemov" <kirill@shutemov.name>, + Siarhei Siamashka <siarhei.siamashka@nokia.com>, + Moiseichuk Leonid <leonid.moiseichuk@nokia.com>, + Koskinen Aaro <aaro.koskinen@nokia.com> +To: linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org +Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 16:21:32 2009 +Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org> +Envelope-to: linux-arm-kernel@m.gmane.org +Original-Received: from bombadil.infradead.org ([18.85.46.34]) + by lo.gmane.org with esmtp (Exim 4.50) + id 1MiqiI-0003K3-An + for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 16:21:30 +0200 +Original-Received: from localhost ([::1] helo=bombadil.infradead.org) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1MiqhG-0005iZ-OK; Wed, 02 Sep 2009 14:20:26 +0000 +Original-Received: from mail-bw0-f222.google.com ([209.85.218.222]) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1Miqh8-0005LP-ED for linux-arm-kernel@lists.infradead.org; + Wed, 02 Sep 2009 14:20:23 +0000 +Original-Received: by bwz22 with SMTP id 22so788877bwz.18 + for <linux-arm-kernel@lists.infradead.org>; + Wed, 02 Sep 2009 07:20:06 -0700 (PDT) +Original-Received: by 10.204.162.143 with SMTP id v15mr6724283bkx.50.1251901206540; + Wed, 02 Sep 2009 07:20:06 -0700 (PDT) +Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14]) + by mx.google.com with ESMTPS id d13sm11540576fka.2.2009.09.02.07.20.05 + (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 07:20:05 -0700 (PDT) +X-Mailer: git-send-email 1.6.4.2 +In-Reply-To: <20090902132423.GA12595@n2100.arm.linux.org.uk> +X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) ) + MR-646709E3 +X-CRM114-CacheID: sfid-20090902_102018_607316_8AE98A04 +X-CRM114-Status: UNSURE ( 9.59 ) +X-CRM114-Notice: Please train this message. +X-Spam-Score: -4.2 (----) +X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary: + Content analysis details: (-4.2 points) + pts rule name description + ---- ---------------------- + -------------------------------------------------- + -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1% + [score: 0.0000] + -1.6 AWL AWL: From: address is in the auto white-list +X-BeenThere: linux-arm-kernel@lists.infradead.org +X-Mailman-Version: 2.1.12 +Precedence: list +List-Id: <linux-arm-kernel.lists.infradead.org> +List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe> +List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/> +List-Post: <mailto:linux-arm-kernel@lists.infradead.org> +List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help> +List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe> +Original-Sender: linux-arm-kernel-bounces@lists.infradead.org +Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org +Xref: news.gmane.org gmane.linux.ports.arm.kernel:65025 +Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65025> + +Optimized version of copy_page() was written with assumption that cache +line size is 32 bytes. On Cortex-A8 cache line size is 64 bytes. + +This patch tries to generalize copy_page() to work with any cache line +size if cache line size is multiple of 16 and page size is multiple of +two cache line size. + +After this optimization we've got ~25% speedup on OMAP3(tested in +userspace). + +There is test for kernelspace which trigger copy-on-write after fork(): + + #include <stdlib.h> + #include <string.h> + #include <unistd.h> + + #define BUF_SIZE (10000*4096) + #define NFORK 200 + + int main(int argc, char **argv) + { + char *buf = malloc(BUF_SIZE); + int i; + + memset(buf, 0, BUF_SIZE); + + for(i = 0; i < NFORK; i++) { + if (fork()) { + wait(NULL); + } else { + int j; + + for(j = 0; j < BUF_SIZE; j+= 4096) + buf[j] = (j & 0xFF) + 1; + break; + } + } + + free(buf); + return 0; + } + +Before optimization this test takes ~66 seconds, after optimization +takes ~56 seconds. + +Signed-off-by: Siarhei Siamashka <siarhei.siamashka@nokia.com> +Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> +--- + arch/arm/lib/copy_page.S | 16 ++++++++-------- + 1 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S +index 6ae04db..6ee2f67 100644 +--- a/arch/arm/lib/copy_page.S ++++ b/arch/arm/lib/copy_page.S +@@ -12,8 +12,9 @@ + #include <linux/linkage.h> + #include <asm/assembler.h> + #include <asm/asm-offsets.h> ++#include <asm/cache.h> + +-#define COPY_COUNT (PAGE_SZ/64 PLD( -1 )) ++#define COPY_COUNT (PAGE_SZ / (2 * L1_CACHE_BYTES) PLD( -1 )) + + .text + .align 5 +@@ -26,17 +27,16 @@ + ENTRY(copy_page) + stmfd sp!, {r4, lr} @ 2 + PLD( pld [r1, #0] ) +- PLD( pld [r1, #32] ) ++ PLD( pld [r1, #L1_CACHE_BYTES] ) + mov r2, #COPY_COUNT @ 1 + ldmia r1!, {r3, r4, ip, lr} @ 4+1 +-1: PLD( pld [r1, #64] ) +- PLD( pld [r1, #96] ) +-2: stmia r0!, {r3, r4, ip, lr} @ 4 +- ldmia r1!, {r3, r4, ip, lr} @ 4+1 +- stmia r0!, {r3, r4, ip, lr} @ 4 +- ldmia r1!, {r3, r4, ip, lr} @ 4+1 ++1: PLD( pld [r1, #2 * L1_CACHE_BYTES]) ++ PLD( pld [r1, #3 * L1_CACHE_BYTES]) ++2: ++ .rept (2 * L1_CACHE_BYTES / 16 - 1) + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmia r1!, {r3, r4, ip, lr} @ 4 ++ .endr + subs r2, r2, #1 @ 1 + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmgtia r1!, {r3, r4, ip, lr} @ 4 +-- +1.6.4.2 diff --git a/recipes/linux/linux-omap-pm-2.6.29/cache/l1cache-shift.patch b/recipes/linux/linux-omap-pm-2.6.29/cache/l1cache-shift.patch new file mode 100644 index 0000000000..e58d49c7a3 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/cache/l1cache-shift.patch @@ -0,0 +1,115 @@ +Path: news.gmane.org!not-for-mail +From: "Kirill A. Shutemov" <kirill@shutemov.name> +Newsgroups: gmane.linux.ports.arm.kernel +Subject: [PATCH 1/2] ARM: Introduce ARM_L1_CACHE_SHIFT to define cache line + size +Date: Wed, 2 Sep 2009 19:11:52 +0300 +Lines: 39 +Approved: news@gmane.org +Message-ID: <1251907913-16261-1-git-send-email-kirill__21953.4654439942$1251897245$gmane$org@shutemov.name> +NNTP-Posting-Host: lo.gmane.org +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +X-Trace: ger.gmane.org 1251897245 21910 80.91.229.12 (2 Sep 2009 13:14:05 GMT) +X-Complaints-To: usenet@ger.gmane.org +NNTP-Posting-Date: Wed, 2 Sep 2009 13:14:05 +0000 (UTC) +Cc: Bityutskiy Artem <Artem.Bityutskiy@nokia.com>, + "Kirill A. Shutemov" <kirill@shutemov.name>, + Siarhei Siamashka <siarhei.siamashka@nokia.com>, + Moiseichuk Leonid <leonid.moiseichuk@nokia.com>, + Koskinen Aaro <aaro.koskinen@nokia.com> +To: linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org +Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org Wed Sep 02 15:13:57 2009 +Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org> +Envelope-to: linux-arm-kernel@m.gmane.org +Original-Received: from bombadil.infradead.org ([18.85.46.34]) + by lo.gmane.org with esmtp (Exim 4.50) + id 1Mipeu-0000ZH-G2 + for linux-arm-kernel@m.gmane.org; Wed, 02 Sep 2009 15:13:56 +0200 +Original-Received: from localhost ([::1] helo=bombadil.infradead.org) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1MipdW-00035E-AP; Wed, 02 Sep 2009 13:12:30 +0000 +Original-Received: from mail-bw0-f222.google.com ([209.85.218.222]) + by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) + id 1Mipd1-00031v-Ga for linux-arm-kernel@lists.infradead.org; + Wed, 02 Sep 2009 13:12:04 +0000 +Original-Received: by bwz22 with SMTP id 22so735896bwz.18 + for <linux-arm-kernel@lists.infradead.org>; + Wed, 02 Sep 2009 06:11:56 -0700 (PDT) +Original-Received: by 10.204.34.199 with SMTP id m7mr6687295bkd.48.1251897116013; + Wed, 02 Sep 2009 06:11:56 -0700 (PDT) +Original-Received: from localhost.localdomain (viktor.cosmicparrot.net [217.152.255.14]) + by mx.google.com with ESMTPS id c28sm2027077fka.19.2009.09.02.06.11.54 + (version=SSLv3 cipher=RC4-MD5); Wed, 02 Sep 2009 06:11:55 -0700 (PDT) +X-Mailer: git-send-email 1.6.3.4 +X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) ) + MR-646709E3 +X-CRM114-CacheID: sfid-20090902_091159_726883_CEFBECD2 +X-CRM114-Status: UNSURE ( 8.83 ) +X-CRM114-Notice: Please train this message. +X-Spam-Score: -4.6 (----) +X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary: + Content analysis details: (-4.6 points) + pts rule name description + ---- ---------------------- + -------------------------------------------------- + -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1% + [score: 0.0000] + -2.0 AWL AWL: From: address is in the auto white-list +X-BeenThere: linux-arm-kernel@lists.infradead.org +X-Mailman-Version: 2.1.12 +Precedence: list +List-Id: <linux-arm-kernel.lists.infradead.org> +List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe> +List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/> +List-Post: <mailto:linux-arm-kernel@lists.infradead.org> +List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help> +List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>, + <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe> +Original-Sender: linux-arm-kernel-bounces@lists.infradead.org +Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org +Xref: news.gmane.org gmane.linux.ports.arm.kernel:65017 +Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/65017> + +Currently kernel believes that all ARM CPUs have L1_CACHE_SHIFT == 5. +It's not true at least for CPUs based on Cortex-A8. + +List of CPUs with cache line size != 32 should be expanded later. + +Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> +--- + arch/arm/include/asm/cache.h | 2 +- + arch/arm/mm/Kconfig | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h +index feaa75f..2ee7743 100644 +--- a/arch/arm/include/asm/cache.h ++++ b/arch/arm/include/asm/cache.h +@@ -4,7 +4,7 @@ + #ifndef __ASMARM_CACHE_H + #define __ASMARM_CACHE_H + +-#define L1_CACHE_SHIFT 5 ++#define L1_CACHE_SHIFT (CONFIG_ARM_L1_CACHE_SHIFT) + #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) + + /* +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index 83c025e..3c37d4c 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -771,3 +771,8 @@ config CACHE_XSC3L2 + select OUTER_CACHE + help + This option enables the L2 cache on XScale3. ++ ++config ARM_L1_CACHE_SHIFT ++ int ++ default 6 if ARCH_OMAP3 ++ default 5 +-- +1.6.3.4 diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch new file mode 100644 index 0000000000..a7898d1440 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch @@ -0,0 +1,43 @@ +From a9199e8ab6d6fb105aa251d6bf2192e7eafac8ee Mon Sep 17 00:00:00 2001 +From: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> +Date: Tue, 24 Mar 2009 17:22:53 -0700 +Subject: [PATCH] USB: musb: only turn off vbus in OTG hosts + +Except on DaVinci, VBUS is now switched off as part of idling the +USB link (after a_wait_bcon) whenever a device is disconnected +from host. This is correct for OTG hosts, where either SRP or +an ID interrupt could turn VBUS on again. + +However, for non-OTG hosts there's no way to turn VBUS on again, +so the host becomes unusable. And the procfs entry which once +allowed a manual workaround for this is now gone. + +This patch adds an is_otg_enabled() check before scheduling the +switch-off timer in disconnect path, supporting a "classic host" +mode where SRP is unavailable. + +[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: tweak patch description ] + +Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> +--- + drivers/usb/musb/musb_core.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index af77e46..338cd16 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -769,7 +769,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, + case OTG_STATE_A_SUSPEND: + usb_hcd_resume_root_hub(musb_to_hcd(musb)); + musb_root_disconnect(musb); +- if (musb->a_wait_bcon != 0) ++ if (musb->a_wait_bcon != 0 && is_otg_enabled(musb)) + musb_platform_try_idle(musb, jiffies + + msecs_to_jiffies(musb->a_wait_bcon)); + break; +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0002-USB-composite-avoid-inconsistent-lock-state.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0002-USB-composite-avoid-inconsistent-lock-state.patch new file mode 100644 index 0000000000..5cb7bcb065 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0002-USB-composite-avoid-inconsistent-lock-state.patch @@ -0,0 +1,76 @@ +From 83eb44b1c84f99d9a5c67612bd94b4ed7c43f64c Mon Sep 17 00:00:00 2001 +From: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> +Date: Tue, 24 Mar 2009 17:22:49 -0700 +Subject: [PATCH] USB: composite: avoid inconsistent lock state + +Avoid the following INFO from lock debugging: + +[ 369.126112] ================================= +[ 369.132063] [ INFO: inconsistent lock state ] +[ 369.136457] 2.6.28-maemo1 #1 +[ 369.139387] --------------------------------- +[ 369.143782] inconsistent {hardirq-on-W} -> {in-hardirq-W} usage. +[ 369.149855] swapper/0 [HC1[1]:SC0[0]:HE0:SE1] takes: +[ 369.154890] (&cdev->lock){+-..}, at: [<bf1979f0>] composite_disconnect+0x1c/0] +[ 369.163404] {hardirq-on-W} state was registered at: +[ 369.168348] [<c00788a8>] __lock_acquire+0x5d0/0x7d8 +[ 369.173506] [<c0078b14>] lock_acquire+0x64/0x78 +[ 369.178266] [<c0263a34>] _spin_lock+0x4c/0x80 +[ 369.182905] [<bf19597c>] usb_function_deactivate+0x20/0x70 [g_nokia] +[ 369.189527] [<bf1a0a88>] 0xbf1a0a88 +[ 369.193281] [<bf19f450>] 0xbf19f450 +[ 369.197004] [<bf19fa3c>] 0xbf19fa3c +[ 369.200758] [<bf1a03a0>] 0xbf1a03a0 +[ 369.204481] [<bf19f254>] 0xbf19f254 +[ 369.208204] [<bf1a0158>] 0xbf1a0158 +[ 369.211927] [<bf1a130c>] 0xbf1a130c +[ 369.215650] [<c01c21f0>] usb_gadget_register_driver+0x12c/0x28c +[ 369.221846] [<bf1a06bc>] 0xbf1a06bc +[ 369.225569] [<bf1a06e8>] 0xbf1a06e8 +[ 369.229322] [<c002c2dc>] __exception_text_end+0x64/0x19c +[ 369.234877] [<c0081628>] sys_init_module+0x9c/0x194 +[ 369.240004] [<c002c8e0>] ret_fast_syscall+0x0/0x2c +[ 369.245039] [<ffffffff>] 0xffffffff +[ 369.248793] irq event stamp: 218356 +[ 369.252302] hardirqs last enabled at (218355): [<c003a77c>] omap3_enter_idle+8 +[ 369.260420] hardirqs last disabled at (218356): [<c0264774>] __irq_svc+0x34/0x0 +[ 369.267927] softirqs last enabled at (218348): [<c00585a4>] __do_softirq+0x134 +[ 369.275892] softirqs last disabled at (218335): [<c005899c>] irq_exit+0x60/0xb0 +[ 369.283308] +[ 369.283308] other info that might help us debug this: +[ 369.289930] no locks held by swapper/0. + +Cc: David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> +Signed-off-by: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> +Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> +--- + drivers/usb/gadget/composite.c | 5 +++-- + 1 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +index 5d11c29..40f1da7 100644 +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -149,16 +149,17 @@ done: + int usb_function_deactivate(struct usb_function *function) + { + struct usb_composite_dev *cdev = function->config->cdev; ++ unsigned long flags; + int status = 0; + +- spin_lock(&cdev->lock); ++ spin_lock_irqsave(&cdev->lock, flags); + + if (cdev->deactivations == 0) + status = usb_gadget_disconnect(cdev->gadget); + if (status == 0) + cdev->deactivations++; + +- spin_unlock(&cdev->lock); ++ spin_unlock_irqrestore(&cdev->lock, flags); + return status; + } + +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch new file mode 100644 index 0000000000..fadad9e44a --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch @@ -0,0 +1,218 @@ +From ba7b26e69f4bb41f10be444c5fded853330f82b5 Mon Sep 17 00:00:00 2001 +From: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> +Date: Tue, 24 Mar 2009 17:22:51 -0700 +Subject: [PATCH] USB: musb: NAK timeout scheme on bulk RX endpoint + +Fixes endpoint starvation issue when more than one bulk QH is +multiplexed on the reserved bulk RX endpoint, which is normal +for cases like serial and ethernet adapters. + +This patch sets the NAK timeout interval for such QHs, and when +a timeout triggers the next QH will be scheduled. (This resembles +the bulk scheduling done in hardware by EHCI, OHCI, and UHCI.) + +This scheme doesn't work for devices which are connected to a +high to full speed tree (transaction translator) as there is +no NAK timeout interrupt from the musb controller from such +devices. + +Tested with PIO, Inventra DMA, CPPI DMA. + +[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: fold in start_urb() update; + clarify only for bulk RX; don't accidentally clear WZC bits ] + +Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> +Cc: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> +--- + drivers/usb/musb/musb_host.c | 112 ++++++++++++++++++++++++++++++++---------- + 1 files changed, 85 insertions(+), 27 deletions(-) + +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index 6dbbd07..bd1d5ae 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -64,11 +64,8 @@ + * + * - DMA (Mentor/OMAP) ...has at least toggle update problems + * +- * - Still no traffic scheduling code to make NAKing for bulk or control +- * transfers unable to starve other requests; or to make efficient use +- * of hardware with periodic transfers. (Note that network drivers +- * commonly post bulk reads that stay pending for a long time; these +- * would make very visible trouble.) ++ * - [23-feb-2009] minimal traffic scheduling to avoid bulk RX packet ++ * starvation ... nothing yet for TX, interrupt, or bulk. + * + * - Not tested with HNP, but some SRP paths seem to behave. + * +@@ -88,11 +85,8 @@ + * + * CONTROL transfers all go through ep0. BULK ones go through dedicated IN + * and OUT endpoints ... hardware is dedicated for those "async" queue(s). +- * + * (Yes, bulk _could_ use more of the endpoints than that, and would even +- * benefit from it ... one remote device may easily be NAKing while others +- * need to perform transfers in that same direction. The same thing could +- * be done in software though, assuming dma cooperates.) ++ * benefit from it.) + * + * INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints. + * So far that scheduling is both dumb and optimistic: the endpoint will be +@@ -201,8 +195,9 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) + len = urb->iso_frame_desc[0].length; + break; + default: /* bulk, interrupt */ +- buf = urb->transfer_buffer; +- len = urb->transfer_buffer_length; ++ /* actual_length may be nonzero on retry paths */ ++ buf = urb->transfer_buffer + urb->actual_length; ++ len = urb->transfer_buffer_length - urb->actual_length; + } + + DBG(4, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n", +@@ -1045,7 +1040,8 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb) + + /* NOTE: this code path would be a good place to PAUSE a + * control transfer, if another one is queued, so that +- * ep0 is more likely to stay busy. ++ * ep0 is more likely to stay busy. That's already done ++ * for bulk RX transfers. + * + * if (qh->ring.next != &musb->control), then + * we have a candidate... NAKing is *NOT* an error +@@ -1197,6 +1193,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) + /* NOTE: this code path would be a good place to PAUSE a + * transfer, if there's some other (nonperiodic) tx urb + * that could use this fifo. (dma complicates it...) ++ * That's already done for bulk RX transfers. + * + * if (bulk && qh->ring.next != &musb->out_bulk), then + * we have a candidate... NAKing is *NOT* an error +@@ -1358,6 +1355,50 @@ finish: + + #endif + ++/* Schedule next QH from musb->in_bulk and move the current qh to ++ * the end; avoids starvation for other endpoints. ++ */ ++static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep) ++{ ++ struct dma_channel *dma; ++ struct urb *urb; ++ void __iomem *mbase = musb->mregs; ++ void __iomem *epio = ep->regs; ++ struct musb_qh *cur_qh, *next_qh; ++ u16 rx_csr; ++ ++ musb_ep_select(mbase, ep->epnum); ++ dma = is_dma_capable() ? ep->rx_channel : NULL; ++ ++ /* clear nak timeout bit */ ++ rx_csr = musb_readw(epio, MUSB_RXCSR); ++ rx_csr |= MUSB_RXCSR_H_WZC_BITS; ++ rx_csr &= ~MUSB_RXCSR_DATAERROR; ++ musb_writew(epio, MUSB_RXCSR, rx_csr); ++ ++ cur_qh = first_qh(&musb->in_bulk); ++ if (cur_qh) { ++ urb = next_urb(cur_qh); ++ if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { ++ dma->status = MUSB_DMA_STATUS_CORE_ABORT; ++ musb->dma_controller->channel_abort(dma); ++ urb->actual_length += dma->actual_len; ++ dma->actual_len = 0L; ++ } ++ musb_save_toggle(ep, 1, urb); ++ ++ /* move cur_qh to end of queue */ ++ list_move_tail(&cur_qh->ring, &musb->in_bulk); ++ ++ /* get the next qh from musb->in_bulk */ ++ next_qh = first_qh(&musb->in_bulk); ++ ++ /* set rx_reinit and schedule the next qh */ ++ ep->rx_reinit = 1; ++ musb_start_urb(musb, 1, next_qh); ++ } ++} ++ + /* + * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso, + * and high-bandwidth IN transfer cases. +@@ -1421,18 +1462,26 @@ void musb_host_rx(struct musb *musb, u8 epnum) + } else if (rx_csr & MUSB_RXCSR_DATAERROR) { + + if (USB_ENDPOINT_XFER_ISOC != qh->type) { +- /* NOTE this code path would be a good place to PAUSE a +- * transfer, if there's some other (nonperiodic) rx urb +- * that could use this fifo. (dma complicates it...) ++ DBG(6, "RX end %d NAK timeout\n", epnum); ++ ++ /* NOTE: NAKing is *NOT* an error, so we want to ++ * continue. Except ... if there's a request for ++ * another QH, use that instead of starving it. + * +- * if (bulk && qh->ring.next != &musb->in_bulk), then +- * we have a candidate... NAKing is *NOT* an error ++ * Devices like Ethernet and serial adapters keep ++ * reads posted at all times, which will starve ++ * other devices without this logic. + */ +- DBG(6, "RX end %d NAK timeout\n", epnum); ++ if (usb_pipebulk(urb->pipe) ++ && qh->mux == 1 ++ && !list_is_singular(&musb->in_bulk)) { ++ musb_bulk_rx_nak_timeout(musb, hw_ep); ++ return; ++ } + musb_ep_select(mbase, epnum); +- musb_writew(epio, MUSB_RXCSR, +- MUSB_RXCSR_H_WZC_BITS +- | MUSB_RXCSR_H_REQPKT); ++ rx_csr |= MUSB_RXCSR_H_WZC_BITS; ++ rx_csr &= ~MUSB_RXCSR_DATAERROR; ++ musb_writew(epio, MUSB_RXCSR, rx_csr); + + goto finish; + } else { +@@ -1756,6 +1805,17 @@ static int musb_schedule( + head = &musb->in_bulk; + else + head = &musb->out_bulk; ++ ++ /* Enable bulk RX NAK timeout scheme when bulk requests are ++ * multiplexed. This scheme doen't work in high speed to full ++ * speed scenario as NAK interrupts are not coming from a ++ * full speed device connected to a high speed device. ++ * NAK timeout interval is 8 (128 uframe or 16ms) for HS and ++ * 4 (8 frame or 8ms) for FS device. ++ */ ++ if (is_in && qh->dev) ++ qh->intv_reg = ++ (USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4; + goto success; + } else if (best_end < 0) { + return -ENOSPC; +@@ -1888,13 +1948,11 @@ static int musb_urb_enqueue( + * + * The downside of disabling this is that transfer scheduling + * gets VERY unfair for nonperiodic transfers; a misbehaving +- * peripheral could make that hurt. Or for reads, one that's +- * perfectly normal: network and other drivers keep reads +- * posted at all times, having one pending for a week should +- * be perfectly safe. ++ * peripheral could make that hurt. That's perfectly normal ++ * for reads from network or serial adapters ... so we have ++ * partial NAKlimit support for bulk RX. + * +- * The upside of disabling it is avoidng transfer scheduling +- * code to put this aside for while. ++ * The upside of disabling it is simpler transfer scheduling. + */ + interval = 0; + } +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch new file mode 100644 index 0000000000..438f11cf7a --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch @@ -0,0 +1,106 @@ +From 9ebf351bcd28a89a0b1ba8d0496fffbc72421611 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Date: Tue, 24 Mar 2009 17:22:50 -0700 +Subject: [PATCH] USB: musb: rewrite host periodic endpoint allocation + +The current MUSB host code doesn't make use of all the available +FIFOs in for periodic transfers since it wrongly assumes the RX +and TX sides of any given hw_ep always share one FIFO. + +Change: use 'in_qh' and 'out_qh' fields of the 'struct musb_hw_ep' +to check the endpoint's business; get rid of the now-unused 'periodic' +array in the 'struct musb'. Also optimize a loop induction variable +in the endpoint lookup code. + +(Based on a previous patch from Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>) + +[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: clarify description and origin + of this fix; whitespace ] + +Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Cc: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> +Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> +--- + drivers/usb/musb/musb_core.h | 1 - + drivers/usb/musb/musb_host.c | 28 +++++++++++----------------- + 2 files changed, 11 insertions(+), 18 deletions(-) + +diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h +index 630946a..adf1806 100644 +--- a/drivers/usb/musb/musb_core.h ++++ b/drivers/usb/musb/musb_core.h +@@ -331,7 +331,6 @@ struct musb { + struct list_head control; /* of musb_qh */ + struct list_head in_bulk; /* of musb_qh */ + struct list_head out_bulk; /* of musb_qh */ +- struct musb_qh *periodic[32]; /* tree of interrupt+iso */ + #endif + + /* called with IRQs blocked; ON/nonzero implies starting a session, +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index bd1d5ae..499c431 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -390,7 +390,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) + * de-allocated if it's tracked and allocated; + * and where we'd update the schedule tree... + */ +- musb->periodic[ep->epnum] = NULL; + kfree(qh); + qh = NULL; + break; +@@ -1760,31 +1759,27 @@ static int musb_schedule( + + /* else, periodic transfers get muxed to other endpoints */ + +- /* FIXME this doesn't consider direction, so it can only +- * work for one half of the endpoint hardware, and assumes +- * the previous cases handled all non-shared endpoints... +- */ +- +- /* we know this qh hasn't been scheduled, so all we need to do ++ /* ++ * We know this qh hasn't been scheduled, so all we need to do + * is choose which hardware endpoint to put it on ... + * + * REVISIT what we really want here is a regular schedule tree +- * like e.g. OHCI uses, but for now musb->periodic is just an +- * array of the _single_ logical endpoint associated with a +- * given physical one (identity mapping logical->physical). +- * +- * that simplistic approach makes TT scheduling a lot simpler; +- * there is none, and thus none of its complexity... ++ * like e.g. OHCI uses. + */ + best_diff = 4096; + best_end = -1; + +- for (epnum = 1; epnum < musb->nr_endpoints; epnum++) { ++ for (epnum = 1, hw_ep = musb->endpoints + 1; ++ epnum < musb->nr_endpoints; ++ epnum++, hw_ep++) { + int diff; + +- if (musb->periodic[epnum]) ++ if (is_in || hw_ep->is_shared_fifo) { ++ if (hw_ep->in_qh != NULL) ++ continue; ++ } else if (hw_ep->out_qh != NULL) + continue; +- hw_ep = &musb->endpoints[epnum]; ++ + if (hw_ep == musb->bulk_ep) + continue; + +@@ -1824,7 +1819,6 @@ static int musb_schedule( + idle = 1; + qh->mux = 0; + hw_ep = musb->endpoints + best_end; +- musb->periodic[best_end] = qh; + DBG(4, "qh %p periodic slot %d\n", qh, best_end); + success: + if (head) { +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch new file mode 100644 index 0000000000..db3481b87b --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch @@ -0,0 +1,181 @@ +From 60e7ce93befe795357db05001fe4caab522a421d Mon Sep 17 00:00:00 2001 +From: Jouni Hogander <jouni.hogander-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> +Date: Tue, 24 Mar 2009 17:22:57 -0700 +Subject: [PATCH] USB: TWL: disable VUSB regulators when cable unplugged + +This patch disables USB regulators VUSB1V5, VUSB1V8, and VUSB3V1 +when the USB cable is unplugged to reduce power consumption. +Added a depencency from twl4030 usb driver to TWL_REGULATOR. + +Signed-off-by: Jouni Hogander <jouni.hogander-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> +Signed-off-by: Kalle Jokiniemi <kalle.jokiniemi-sMOQStClEysAvxtiuMwx3w@public.gmane.org> +Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> +--- + drivers/usb/otg/Kconfig | 2 +- + drivers/usb/otg/twl4030-usb.c | 73 ++++++++++++++++++++++++++++++++++++----- + 2 files changed, 65 insertions(+), 10 deletions(-) + +diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig +index ee55b44..5790a5b 100644 +--- a/drivers/usb/otg/Kconfig ++++ b/drivers/usb/otg/Kconfig +@@ -43,7 +43,7 @@ config ISP1301_OMAP + + config TWL4030_USB + tristate "TWL4030 USB Transceiver Driver" +- depends on TWL4030_CORE ++ depends on TWL4030_CORE && REGULATOR_TWL4030 + select USB_OTG_UTILS + help + Enable this to support the USB OTG transceiver on TWL4030 +diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c +index 416e441..d9478d0 100644 +--- a/drivers/usb/otg/twl4030-usb.c ++++ b/drivers/usb/otg/twl4030-usb.c +@@ -34,6 +34,8 @@ + #include <linux/delay.h> + #include <linux/usb/otg.h> + #include <linux/i2c/twl4030.h> ++#include <linux/regulator/consumer.h> ++#include <linux/err.h> + + + /* Register defines */ +@@ -246,6 +248,11 @@ struct twl4030_usb { + struct otg_transceiver otg; + struct device *dev; + ++ /* TWL4030 internal USB regulator supplies */ ++ struct regulator *usb1v5; ++ struct regulator *usb1v8; ++ struct regulator *usb3v1; ++ + /* for vbus reporting with irqs disabled */ + spinlock_t lock; + +@@ -434,6 +441,18 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) + + pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); + if (on) { ++ regulator_enable(twl->usb3v1); ++ regulator_enable(twl->usb1v8); ++ /* ++ * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP ++ * in twl4030) resets the VUSB_DEDICATED2 register. This reset ++ * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to ++ * SLEEP. We work around this by clearing the bit after usv3v1 ++ * is re-activated. This ensures that VUSB3V1 is really active. ++ */ ++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, ++ VUSB_DEDICATED2); ++ regulator_enable(twl->usb1v5); + pwr &= ~PHY_PWR_PHYPWD; + WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); + twl4030_usb_write(twl, PHY_CLK_CTRL, +@@ -443,6 +462,9 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) + } else { + pwr |= PHY_PWR_PHYPWD; + WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); ++ regulator_disable(twl->usb1v5); ++ regulator_disable(twl->usb1v8); ++ regulator_disable(twl->usb3v1); + } + } + +@@ -468,7 +490,7 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) + twl->asleep = 0; + } + +-static void twl4030_usb_ldo_init(struct twl4030_usb *twl) ++static int twl4030_usb_ldo_init(struct twl4030_usb *twl) + { + /* Enable writing to power configuration registers */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); +@@ -480,20 +502,45 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl) + /* input to VUSB3V1 LDO is from VBAT, not VBUS */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); + +- /* turn on 3.1V regulator */ +- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP); ++ /* Initialize 3.1V regulator */ ++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); ++ ++ twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); ++ if (IS_ERR(twl->usb3v1)) ++ return -ENODEV; ++ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); + +- /* turn on 1.5V regulator */ +- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP); ++ /* Initialize 1.5V regulator */ ++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); ++ ++ twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); ++ if (IS_ERR(twl->usb1v5)) ++ goto fail1; ++ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); + +- /* turn on 1.8V regulator */ +- twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP); ++ /* Initialize 1.8V regulator */ ++ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); ++ ++ twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); ++ if (IS_ERR(twl->usb1v8)) ++ goto fail2; ++ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); + + /* disable access to power configuration registers */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); ++ ++ return 0; ++ ++fail2: ++ regulator_put(twl->usb1v5); ++ twl->usb1v5 = NULL; ++fail1: ++ regulator_put(twl->usb3v1); ++ twl->usb3v1 = NULL; ++ return -ENODEV; + } + + static ssize_t twl4030_usb_vbus_show(struct device *dev, +@@ -598,7 +645,7 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) + { + struct twl4030_usb_data *pdata = pdev->dev.platform_data; + struct twl4030_usb *twl; +- int status; ++ int status, err; + + if (!pdata) { + dev_dbg(&pdev->dev, "platform_data not available\n"); +@@ -622,7 +669,12 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) + /* init spinlock for workqueue */ + spin_lock_init(&twl->lock); + +- twl4030_usb_ldo_init(twl); ++ err = twl4030_usb_ldo_init(twl); ++ if (err) { ++ dev_err(&pdev->dev, "ldo init failed\n"); ++ kfree(twl); ++ return err; ++ } + otg_set_transceiver(&twl->otg); + + platform_set_drvdata(pdev, twl); +@@ -688,6 +740,9 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) + twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); + + twl4030_phy_power(twl, 0); ++ regulator_put(twl->usb1v5); ++ regulator_put(twl->usb1v8); ++ regulator_put(twl->usb3v1); + + kfree(twl); + +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch new file mode 100644 index 0000000000..3f49a4d636 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch @@ -0,0 +1,84 @@ +From 7eef82d231578140c6000d04846a48bdaf341a65 Mon Sep 17 00:00:00 2001 +From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Date: Tue, 24 Mar 2009 17:23:19 -0700 +Subject: [PATCH] USB: gadget: composite device-level suspend/resume hooks + +Address one open question in the composite gadget framework: +Yes, we should have device-level suspend/resume callbacks +in addition to the function-level ones. We have at least one +scenario (with gadget zero in OTG test mode) that's awkward +to handle without it. + +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Cc: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> +Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> +--- + drivers/usb/gadget/composite.c | 8 ++++++-- + include/linux/usb/composite.h | 8 ++++++++ + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +index 40f1da7..59e8523 100644 +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -1014,7 +1014,7 @@ composite_suspend(struct usb_gadget *gadget) + struct usb_composite_dev *cdev = get_gadget_data(gadget); + struct usb_function *f; + +- /* REVISIT: should we have config and device level ++ /* REVISIT: should we have config level + * suspend/resume callbacks? + */ + DBG(cdev, "suspend\n"); +@@ -1024,6 +1024,8 @@ composite_suspend(struct usb_gadget *gadget) + f->suspend(f); + } + } ++ if (composite->suspend) ++ composite->suspend(cdev); + } + + static void +@@ -1032,10 +1034,12 @@ composite_resume(struct usb_gadget *gadget) + struct usb_composite_dev *cdev = get_gadget_data(gadget); + struct usb_function *f; + +- /* REVISIT: should we have config and device level ++ /* REVISIT: should we have config level + * suspend/resume callbacks? + */ + DBG(cdev, "resume\n"); ++ if (composite->resume) ++ composite->resume(cdev); + if (cdev->config) { + list_for_each_entry(f, &cdev->config->functions, list) { + if (f->resume) +diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h +index 935c380..acd7b0f 100644 +--- a/include/linux/usb/composite.h ++++ b/include/linux/usb/composite.h +@@ -244,6 +244,10 @@ int usb_add_config(struct usb_composite_dev *, + * value; it should return zero on successful initialization. + * @unbind: Reverses @bind(); called as a side effect of unregistering + * this driver. ++ * @suspend: Notifies when the host stops sending USB traffic, ++ * after function notifications ++ * @resume: Notifies configuration when the host restarts USB traffic, ++ * before function notifications + * + * Devices default to reporting self powered operation. Devices which rely + * on bus powered operation should report this in their @bind() method. +@@ -268,6 +272,10 @@ struct usb_composite_driver { + + int (*bind)(struct usb_composite_dev *); + int (*unbind)(struct usb_composite_dev *); ++ ++ /* global suspend hooks */ ++ void (*suspend)(struct usb_composite_dev *); ++ void (*resume)(struct usb_composite_dev *); + }; + + extern int usb_composite_register(struct usb_composite_driver *); +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch new file mode 100644 index 0000000000..a89bc2ff5c --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch @@ -0,0 +1,47 @@ +From 00c4bd07a64061ec9ab9c35f5bf01ec6187138f4 Mon Sep 17 00:00:00 2001 +From: Jonathan McDowell <noodles-4QvXXjU8Dv4@public.gmane.org> +Date: Thu, 26 Mar 2009 00:45:27 -0700 +Subject: [PATCH] usb gadget: fix ethernet link reports to ethtool + +The g_ether USB gadget driver currently decides whether or not there's a +link to report back for eth_get_link based on if the USB link speed is +set. The USB gadget speed is however often set even before the device is +enumerated. It seems more sensible to only report a "link" if we're +actually connected to a host that wants to talk to us. The patch below +does this for me - tested with the PXA27x UDC driver. + +Signed-Off-By: Jonathan McDowell <noodles-4QvXXjU8Dv4@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/gadget/u_ether.c | 8 +------- + 1 files changed, 1 insertions(+), 7 deletions(-) + +diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c +index 96d65ca..4007770 100644 +--- a/drivers/usb/gadget/u_ether.c ++++ b/drivers/usb/gadget/u_ether.c +@@ -175,12 +175,6 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) + strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info); + } + +-static u32 eth_get_link(struct net_device *net) +-{ +- struct eth_dev *dev = netdev_priv(net); +- return dev->gadget->speed != USB_SPEED_UNKNOWN; +-} +- + /* REVISIT can also support: + * - WOL (by tracking suspends and issuing remote wakeup) + * - msglevel (implies updated messaging) +@@ -189,7 +183,7 @@ static u32 eth_get_link(struct net_device *net) + + static struct ethtool_ops ops = { + .get_drvinfo = eth_get_drvinfo, +- .get_link = eth_get_link ++ .get_link = ethtool_op_get_link, + }; + + static void defer_kevent(struct eth_dev *dev, int flag) +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch new file mode 100644 index 0000000000..8627825b5a --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch @@ -0,0 +1,60 @@ +From c3b527a21104b6bb61558fba6c65aa80f63e0772 Mon Sep 17 00:00:00 2001 +From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Date: Thu, 26 Mar 2009 17:36:57 -0700 +Subject: [PATCH] usb: musb_host, minor enqueue locking fix (v2) + +Someone noted that the enqueue path used an unlocked access +for usb_host_endpoint->hcpriv ... fix that, by being safe +and always accessing it under spinlock protection. + +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_host.c | 17 ++++++++--------- + 1 files changed, 8 insertions(+), 9 deletions(-) + +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index 499c431..ff09595 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -1841,7 +1841,7 @@ static int musb_urb_enqueue( + unsigned long flags; + struct musb *musb = hcd_to_musb(hcd); + struct usb_host_endpoint *hep = urb->ep; +- struct musb_qh *qh = hep->hcpriv; ++ struct musb_qh *qh; + struct usb_endpoint_descriptor *epd = &hep->desc; + int ret; + unsigned type_reg; +@@ -1853,22 +1853,21 @@ static int musb_urb_enqueue( + + spin_lock_irqsave(&musb->lock, flags); + ret = usb_hcd_link_urb_to_ep(hcd, urb); ++ qh = ret ? NULL : hep->hcpriv; ++ if (qh) ++ urb->hcpriv = qh; + spin_unlock_irqrestore(&musb->lock, flags); +- if (ret) +- return ret; + + /* DMA mapping was already done, if needed, and this urb is on +- * hep->urb_list ... so there's little to do unless hep wasn't +- * yet scheduled onto a live qh. ++ * hep->urb_list now ... so we're done, unless hep wasn't yet ++ * scheduled onto a live qh. + * + * REVISIT best to keep hep->hcpriv valid until the endpoint gets + * disabled, testing for empty qh->ring and avoiding qh setup costs + * except for the first urb queued after a config change. + */ +- if (qh) { +- urb->hcpriv = qh; +- return 0; +- } ++ if (qh || ret) ++ return ret; + + /* Allocate and initialize qh, minimizing the work done each time + * hw_ep gets reprogrammed, or with irqs blocked. Then schedule it. +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch new file mode 100644 index 0000000000..09fc0a17d0 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch @@ -0,0 +1,93 @@ +From 48ce47b15bfd420982ee275c595a9139eb6fabf7 Mon Sep 17 00:00:00 2001 +From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Date: Thu, 26 Mar 2009 17:38:30 -0700 +Subject: [PATCH] usb: musb_host, fix ep0 fifo flushing + +The MUSB host side can't share generic TX FIFO flush logic +with EP0; the EP0 TX status register bits are different +from those for other entpoints. + +Resolve this issue by providing a new EP0-specific routine +to flush and reset the FIFO, which pays careful attention to +restrictions listed in the latest programmer's guide. This +gets rid of an open issue whereby the usbtest control write +test (#14) failed. + +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_host.c | 38 +++++++++++++++++++++++++------------- + 1 files changed, 25 insertions(+), 13 deletions(-) + +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index ff09595..a5d75aa 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -125,6 +125,29 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) + } + } + ++static void musb_h_ep0_flush_fifo(struct musb_hw_ep *ep) ++{ ++ void __iomem *epio = ep->regs; ++ u16 csr; ++ int retries = 5; ++ ++ /* scrub any data left in the fifo */ ++ do { ++ csr = musb_readw(epio, MUSB_TXCSR); ++ if (!(csr & (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_RXPKTRDY))) ++ break; ++ musb_writew(epio, MUSB_TXCSR, MUSB_CSR0_FLUSHFIFO); ++ csr = musb_readw(epio, MUSB_TXCSR); ++ udelay(10); ++ } while (--retries); ++ ++ WARN(!retries, "Could not flush host TX%d fifo: csr: %04x\n", ++ ep->epnum, csr); ++ ++ /* and reset for the next transfer */ ++ musb_writew(epio, MUSB_TXCSR, 0); ++} ++ + /* + * Start transmit. Caller is responsible for locking shared resources. + * musb must be locked. +@@ -693,11 +716,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, + musb_writew(epio, MUSB_TXCSR, csr); + csr = musb_readw(epio, MUSB_TXCSR); + } else { +- /* endpoint 0: just flush */ +- musb_writew(epio, MUSB_CSR0, +- csr | MUSB_CSR0_FLUSHFIFO); +- musb_writew(epio, MUSB_CSR0, +- csr | MUSB_CSR0_FLUSHFIFO); ++ musb_h_ep0_flush_fifo(hw_ep); + } + + /* target addr and (for multipoint) hub addr/port */ +@@ -1063,11 +1082,7 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb) + csr &= ~MUSB_CSR0_H_NAKTIMEOUT; + musb_writew(epio, MUSB_CSR0, csr); + } else { +- csr |= MUSB_CSR0_FLUSHFIFO; +- musb_writew(epio, MUSB_CSR0, csr); +- musb_writew(epio, MUSB_CSR0, csr); +- csr &= ~MUSB_CSR0_H_NAKTIMEOUT; +- musb_writew(epio, MUSB_CSR0, csr); ++ musb_h_ep0_flush_fifo(hw_ep); + } + + musb_writeb(epio, MUSB_NAKLIMIT0, 0); +@@ -1081,9 +1096,6 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb) + * SHOULD NEVER HAPPEN! */ + ERR("no URB for end 0\n"); + +- musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO); +- musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO); +- musb_writew(epio, MUSB_CSR0, 0); + + goto done; + } +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch new file mode 100644 index 0000000000..bcbe3bbe39 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch @@ -0,0 +1,361 @@ +From c99f4a68268801a2e2ffbef9766c3ac89e4fb22c Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Date: Thu, 26 Mar 2009 18:27:47 -0700 +Subject: [PATCH] musb: sanitize clearing TXCSR DMA bits (take 2) + +The MUSB code clears TXCSR_DMAMODE incorrectly in several +places, either asserting that TXCSR_DMAENAB is clear (when +sometimes it isn't) or clearing both bits together. Recent +versions of the programmer's guide require DMAENAB to be +cleared first, although some older ones didn't. + +Fix this and while at it: + + - In musb_gadget::txstate(), stop clearing the AUTOSET + and DMAMODE bits for the CPPI case since they never + get set anyway (the former bit is reserved on DaVinci); + but do clear the DMAENAB bit on the DMA error path. + + - In musb_host::musb_ep_program(), remove the duplicate + DMA controller specific code code clearing the TXCSR + previous state, add the code to clear TXCSR DMA bits + on the Inventra DMA error path, to replace such code + (executed late) on the PIO path. + + - In musbhsdma::dma_channel_abort()/dma_controller_irq(), + add/use the 'offset' variable to avoid MUSB_EP_OFFSET() + invocations on every RXCSR/TXCSR access. + +[dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: don't introduce CamelCase, +shrink diff] + +Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_gadget.c | 33 +++++++++++------ + drivers/usb/musb/musb_host.c | 79 ++++++++++++++++------------------------ + drivers/usb/musb/musbhsdma.c | 59 ++++++++++++++++++------------ + 3 files changed, 90 insertions(+), 81 deletions(-) + +diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c +index c7ebd08..f79440c 100644 +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -165,9 +165,15 @@ static void nuke(struct musb_ep *ep, const int status) + if (is_dma_capable() && ep->dma) { + struct dma_controller *c = ep->musb->dma_controller; + int value; ++ + if (ep->is_in) { ++ /* ++ * The programming guide says that we must not clear ++ * the DMAMODE bit before DMAENAB, so we only ++ * clear it in the second write... ++ */ + musb_writew(epio, MUSB_TXCSR, +- 0 | MUSB_TXCSR_FLUSHFIFO); ++ MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO); + musb_writew(epio, MUSB_TXCSR, + 0 | MUSB_TXCSR_FLUSHFIFO); + } else { +@@ -230,7 +236,7 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep) + | IN token(s) are recd from Host. + | -> DMA interrupt on completion + | calls TxAvail. +- | -> stop DMA, ~DmaEenab, ++ | -> stop DMA, ~DMAENAB, + | -> set TxPktRdy for last short pkt or zlp + | -> Complete Request + | -> Continue next request (call txstate) +@@ -315,9 +321,17 @@ static void txstate(struct musb *musb, struct musb_request *req) + request->dma, request_size); + if (use_dma) { + if (musb_ep->dma->desired_mode == 0) { +- /* ASSERT: DMAENAB is clear */ +- csr &= ~(MUSB_TXCSR_AUTOSET | +- MUSB_TXCSR_DMAMODE); ++ /* ++ * We must not clear the DMAMODE bit ++ * before the DMAENAB bit -- and the ++ * latter doesn't always get cleared ++ * before we get here... ++ */ ++ csr &= ~(MUSB_TXCSR_AUTOSET ++ | MUSB_TXCSR_DMAENAB); ++ musb_writew(epio, MUSB_TXCSR, csr ++ | MUSB_TXCSR_P_WZC_BITS); ++ csr &= ~MUSB_TXCSR_DMAMODE; + csr |= (MUSB_TXCSR_DMAENAB | + MUSB_TXCSR_MODE); + /* against programming guide */ +@@ -334,10 +348,7 @@ static void txstate(struct musb *musb, struct musb_request *req) + + #elif defined(CONFIG_USB_TI_CPPI_DMA) + /* program endpoint CSR first, then setup DMA */ +- csr &= ~(MUSB_TXCSR_AUTOSET +- | MUSB_TXCSR_DMAMODE +- | MUSB_TXCSR_P_UNDERRUN +- | MUSB_TXCSR_TXPKTRDY); ++ csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY); + csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB; + musb_writew(epio, MUSB_TXCSR, + (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) +@@ -364,8 +375,8 @@ static void txstate(struct musb *musb, struct musb_request *req) + if (!use_dma) { + c->channel_release(musb_ep->dma); + musb_ep->dma = NULL; +- /* ASSERT: DMAENAB clear */ +- csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE); ++ csr &= ~MUSB_TXCSR_DMAENAB; ++ musb_writew(epio, MUSB_TXCSR, csr); + /* invariant: prequest->buf is non-null */ + } + #elif defined(CONFIG_USB_TUSB_OMAP_DMA) +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index a5d75aa..6591282 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -590,10 +590,17 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) + csr = musb_readw(ep->regs, MUSB_TXCSR); + if (csr & MUSB_TXCSR_MODE) { + musb_h_tx_flush_fifo(ep); ++ csr = musb_readw(ep->regs, MUSB_TXCSR); + musb_writew(ep->regs, MUSB_TXCSR, +- MUSB_TXCSR_FRCDATATOG); ++ csr | MUSB_TXCSR_FRCDATATOG); + } +- /* clear mode (and everything else) to enable Rx */ ++ ++ /* ++ * Clear the MODE bit (and everything else) to enable Rx. ++ * NOTE: we mustn't clear the DMAMODE bit before DMAENAB. ++ */ ++ if (csr & MUSB_TXCSR_DMAMODE) ++ musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE); + musb_writew(ep->regs, MUSB_TXCSR, 0); + + /* scrub all previous state, clearing toggle */ +@@ -690,12 +697,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum, + + /* general endpoint setup */ + if (epnum) { +- /* ASSERT: TXCSR_DMAENAB was already cleared */ +- + /* flush all old state, set default */ + musb_h_tx_flush_fifo(hw_ep); ++ ++ /* ++ * We must not clear the DMAMODE bit before or in ++ * the same cycle with the DMAENAB bit, so we clear ++ * the latter first... ++ */ + csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT +- | MUSB_TXCSR_DMAMODE ++ | MUSB_TXCSR_AUTOSET ++ | MUSB_TXCSR_DMAENAB + | MUSB_TXCSR_FRCDATATOG + | MUSB_TXCSR_H_RXSTALL + | MUSB_TXCSR_H_ERROR +@@ -703,16 +715,15 @@ static void musb_ep_program(struct musb *musb, u8 epnum, + ); + csr |= MUSB_TXCSR_MODE; + +- if (usb_gettoggle(urb->dev, +- qh->epnum, 1)) ++ if (usb_gettoggle(urb->dev, qh->epnum, 1)) + csr |= MUSB_TXCSR_H_WR_DATATOGGLE + | MUSB_TXCSR_H_DATATOGGLE; + else + csr |= MUSB_TXCSR_CLRDATATOG; + +- /* twice in case of double packet buffering */ + musb_writew(epio, MUSB_TXCSR, csr); + /* REVISIT may need to clear FLUSHFIFO ... */ ++ csr &= ~MUSB_TXCSR_DMAMODE; + musb_writew(epio, MUSB_TXCSR, csr); + csr = musb_readw(epio, MUSB_TXCSR); + } else { +@@ -755,34 +766,19 @@ static void musb_ep_program(struct musb *musb, u8 epnum, + + #ifdef CONFIG_USB_INVENTRA_DMA + if (dma_channel) { +- +- /* clear previous state */ +- csr = musb_readw(epio, MUSB_TXCSR); +- csr &= ~(MUSB_TXCSR_AUTOSET +- | MUSB_TXCSR_DMAMODE +- | MUSB_TXCSR_DMAENAB); +- csr |= MUSB_TXCSR_MODE; +- musb_writew(epio, MUSB_TXCSR, +- csr | MUSB_TXCSR_MODE); +- + qh->segsize = min(len, dma_channel->max_len); +- + if (qh->segsize <= packet_sz) + dma_channel->desired_mode = 0; + else + dma_channel->desired_mode = 1; + +- + if (dma_channel->desired_mode == 0) { +- csr &= ~(MUSB_TXCSR_AUTOSET +- | MUSB_TXCSR_DMAMODE); ++ /* Against the programming guide */ + csr |= (MUSB_TXCSR_DMAENAB); +- /* against programming guide */ + } else + csr |= (MUSB_TXCSR_AUTOSET + | MUSB_TXCSR_DMAENAB + | MUSB_TXCSR_DMAMODE); +- + musb_writew(epio, MUSB_TXCSR, csr); + + dma_ok = dma_controller->channel_program( +@@ -799,6 +795,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum, + else + hw_ep->rx_channel = NULL; + dma_channel = NULL; ++ ++ /* ++ * The programming guide says that we must ++ * clear the DMAENAB bit before DMAMODE... ++ */ ++ csr = musb_readw(epio, MUSB_TXCSR); ++ csr &= ~(MUSB_TXCSR_DMAENAB ++ | MUSB_TXCSR_AUTOSET); ++ musb_writew(epio, MUSB_TXCSR, csr); ++ csr &= ~MUSB_TXCSR_DMAMODE; ++ musb_writew(epio, MUSB_TXCSR, csr); + } + } + #endif +@@ -806,18 +813,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, + /* candidate for DMA */ + if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) { + +- /* program endpoint CSRs first, then setup DMA. +- * assume CPPI setup succeeds. +- * defer enabling dma. +- */ +- csr = musb_readw(epio, MUSB_TXCSR); +- csr &= ~(MUSB_TXCSR_AUTOSET +- | MUSB_TXCSR_DMAMODE +- | MUSB_TXCSR_DMAENAB); +- csr |= MUSB_TXCSR_MODE; +- musb_writew(epio, MUSB_TXCSR, +- csr | MUSB_TXCSR_MODE); +- ++ /* Defer enabling DMA */ + dma_channel->actual_len = 0L; + qh->segsize = len; + +@@ -846,20 +842,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum, + } + + if (load_count) { +- /* ASSERT: TXCSR_DMAENAB was already cleared */ +- + /* PIO to load FIFO */ + qh->segsize = load_count; + musb_write_fifo(hw_ep, load_count, buf); +- csr = musb_readw(epio, MUSB_TXCSR); +- csr &= ~(MUSB_TXCSR_DMAENAB +- | MUSB_TXCSR_DMAMODE +- | MUSB_TXCSR_AUTOSET); +- /* write CSR */ +- csr |= MUSB_TXCSR_MODE; +- +- if (epnum) +- musb_writew(epio, MUSB_TXCSR, csr); + } + + /* re-enable interrupt */ +diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c +index 8662e9e..40709c3 100644 +--- a/drivers/usb/musb/musbhsdma.c ++++ b/drivers/usb/musb/musbhsdma.c +@@ -195,30 +195,32 @@ static int dma_channel_abort(struct dma_channel *channel) + void __iomem *mbase = musb_channel->controller->base; + + u8 bchannel = musb_channel->idx; ++ int offset; + u16 csr; + + if (channel->status == MUSB_DMA_STATUS_BUSY) { + if (musb_channel->transmit) { +- +- csr = musb_readw(mbase, +- MUSB_EP_OFFSET(musb_channel->epnum, +- MUSB_TXCSR)); +- csr &= ~(MUSB_TXCSR_AUTOSET | +- MUSB_TXCSR_DMAENAB | +- MUSB_TXCSR_DMAMODE); +- musb_writew(mbase, +- MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR), +- csr); ++ offset = MUSB_EP_OFFSET(musb_channel->epnum, ++ MUSB_TXCSR); ++ ++ /* ++ * The programming guide says that we must clear ++ * the DMAENAB bit before the DMAMODE bit... ++ */ ++ csr = musb_readw(mbase, offset); ++ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB); ++ musb_writew(mbase, offset, csr); ++ csr &= ~MUSB_TXCSR_DMAMODE; ++ musb_writew(mbase, offset, csr); + } else { +- csr = musb_readw(mbase, +- MUSB_EP_OFFSET(musb_channel->epnum, +- MUSB_RXCSR)); ++ offset = MUSB_EP_OFFSET(musb_channel->epnum, ++ MUSB_RXCSR); ++ ++ csr = musb_readw(mbase, offset); + csr &= ~(MUSB_RXCSR_AUTOCLEAR | + MUSB_RXCSR_DMAENAB | + MUSB_RXCSR_DMAMODE); +- musb_writew(mbase, +- MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR), +- csr); ++ musb_writew(mbase, offset, csr); + } + + musb_writew(mbase, +@@ -296,14 +298,25 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) + && ((channel->desired_mode == 0) + || (channel->actual_len & + (musb_channel->max_packet_sz - 1))) +- ) { ++ ) { ++ u8 epnum = musb_channel->epnum; ++ int offset = MUSB_EP_OFFSET(epnum, ++ MUSB_TXCSR); ++ u16 txcsr; ++ ++ /* ++ * The programming guide says that we ++ * must clear DMAENAB before DMAMODE. ++ */ ++ musb_ep_select(mbase, epnum); ++ txcsr = musb_readw(mbase, offset); ++ txcsr &= ~(MUSB_TXCSR_DMAENAB ++ | MUSB_TXCSR_AUTOSET); ++ musb_writew(mbase, offset, txcsr); + /* Send out the packet */ +- musb_ep_select(mbase, +- musb_channel->epnum); +- musb_writew(mbase, MUSB_EP_OFFSET( +- musb_channel->epnum, +- MUSB_TXCSR), +- MUSB_TXCSR_TXPKTRDY); ++ txcsr &= ~MUSB_TXCSR_DMAMODE; ++ txcsr |= MUSB_TXCSR_TXPKTRDY; ++ musb_writew(mbase, offset, txcsr); + } else { + musb_dma_completion( + musb, +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch new file mode 100644 index 0000000000..7d546e10b0 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch @@ -0,0 +1,417 @@ +From 035cd4a26e9b1638b4b0419b98409026176563ca Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Date: Thu, 26 Mar 2009 18:29:19 -0700 +Subject: [PATCH] musb: fix isochronous TXDMA (take 2) + +Multi-frame isochronous TX URBs transfers in DMA mode never +complete with CPPI DMA because musb_host_tx() doesn't restart +DMA on the second frame, only emitting a debug message. +With Inventra DMA they complete, but in PIO mode. To fix: + + - Factor out programming of the DMA transfer from + musb_ep_program() into musb_tx_dma_program(); + + - Reorder the code at the end of musb_host_tx() to + facilitate the fallback to PIO iff DMA fails; + + - Handle the buffer offset consistently for both + PIO and DMA modes; + + - Add an argument to musb_ep_program() for the same + reason (it only worked correctly with non-zero + offset of the first frame in PIO mode); + + - Set the completed isochronous frame descriptor's + 'actual_length' and 'status' fields correctly in + DMA mode. + +Also, since CPPI reportedly doesn't like sending isochronous +packets in the RNDIS mode, change the criterion for this +mode to be used only for multi-packet transfers. (There's +no need for that mode in the single-packet case anyway.) + +[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: split comment paragraph +into bullet list, shrink patch delta, style tweaks ] + +Signed-off-by: Pavel Kiryukhin <pkiryukhin-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/cppi_dma.c | 1 + + drivers/usb/musb/musb_host.c | 227 +++++++++++++++++++----------------------- + 2 files changed, 105 insertions(+), 123 deletions(-) + +diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c +index 569ef0f..ac7227c 100644 +--- a/drivers/usb/musb/cppi_dma.c ++++ b/drivers/usb/musb/cppi_dma.c +@@ -579,6 +579,7 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx) + * trigger the "send a ZLP?" confusion. + */ + rndis = (maxpacket & 0x3f) == 0 ++ && length > maxpacket + && length < 0xffff + && (length % maxpacket) != 0; + +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index 6591282..f6e84a0 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -96,8 +96,8 @@ + + + static void musb_ep_program(struct musb *musb, u8 epnum, +- struct urb *urb, unsigned int nOut, +- u8 *buf, u32 len); ++ struct urb *urb, int is_out, ++ u8 *buf, u32 offset, u32 len); + + /* + * Clear TX fifo. Needed to avoid BABBLE errors. +@@ -189,9 +189,10 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) + { + u16 frame; + u32 len; +- void *buf; + void __iomem *mbase = musb->mregs; + struct urb *urb = next_urb(qh); ++ void *buf = urb->transfer_buffer; ++ u32 offset = 0; + struct musb_hw_ep *hw_ep = qh->hw_ep; + unsigned pipe = urb->pipe; + u8 address = usb_pipedevice(pipe); +@@ -214,7 +215,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) + case USB_ENDPOINT_XFER_ISOC: + qh->iso_idx = 0; + qh->frame = 0; +- buf = urb->transfer_buffer + urb->iso_frame_desc[0].offset; ++ offset = urb->iso_frame_desc[0].offset; + len = urb->iso_frame_desc[0].length; + break; + default: /* bulk, interrupt */ +@@ -232,14 +233,14 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) + case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break; + default: s = "-intr"; break; + }; s; }), +- epnum, buf, len); ++ epnum, buf + offset, len); + + /* Configure endpoint */ + if (is_in || hw_ep->is_shared_fifo) + hw_ep->in_qh = qh; + else + hw_ep->out_qh = qh; +- musb_ep_program(musb, epnum, urb, !is_in, buf, len); ++ musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len); + + /* transmit may have more work: start it when it is time */ + if (is_in) +@@ -250,7 +251,6 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) + case USB_ENDPOINT_XFER_ISOC: + case USB_ENDPOINT_XFER_INT: + DBG(3, "check whether there's still time for periodic Tx\n"); +- qh->iso_idx = 0; + frame = musb_readw(mbase, MUSB_FRAME); + /* FIXME this doesn't implement that scheduling policy ... + * or handle framecounter wrapping +@@ -631,14 +631,68 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) + ep->rx_reinit = 0; + } + ++static bool musb_tx_dma_program(struct dma_controller *dma, ++ struct musb_hw_ep *hw_ep, struct musb_qh *qh, ++ struct urb *urb, u32 offset, u32 length) ++{ ++ struct dma_channel *channel = hw_ep->tx_channel; ++ void __iomem *epio = hw_ep->regs; ++ u16 pkt_size = qh->maxpacket; ++ u16 csr; ++ u8 mode; ++ ++#ifdef CONFIG_USB_INVENTRA_DMA ++ if (length > channel->max_len) ++ length = channel->max_len; ++ ++ csr = musb_readw(epio, MUSB_TXCSR); ++ if (length > pkt_size) { ++ mode = 1; ++ csr |= MUSB_TXCSR_AUTOSET ++ | MUSB_TXCSR_DMAMODE ++ | MUSB_TXCSR_DMAENAB; ++ } else { ++ mode = 0; ++ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE); ++ csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */ ++ } ++ channel->desired_mode = mode; ++ musb_writew(epio, MUSB_TXCSR, csr); ++#else ++ if (!is_cppi_enabled() && !tusb_dma_omap()) ++ return false; ++ ++ channel->actual_len = 0; ++ ++ /* ++ * TX uses "RNDIS" mode automatically but needs help ++ * to identify the zero-length-final-packet case. ++ */ ++ mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0; ++#endif ++ ++ qh->segsize = length; ++ ++ if (!dma->channel_program(channel, pkt_size, mode, ++ urb->transfer_dma + offset, length)) { ++ dma->channel_release(channel); ++ hw_ep->tx_channel = NULL; ++ ++ csr = musb_readw(epio, MUSB_TXCSR); ++ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB); ++ musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_H_WZC_BITS); ++ return false; ++ } ++ return true; ++} + + /* + * Program an HDRC endpoint as per the given URB + * Context: irqs blocked, controller lock held + */ + static void musb_ep_program(struct musb *musb, u8 epnum, +- struct urb *urb, unsigned int is_out, +- u8 *buf, u32 len) ++ struct urb *urb, int is_out, ++ u8 *buf, u32 offset, u32 len) + { + struct dma_controller *dma_controller; + struct dma_channel *dma_channel; +@@ -764,82 +818,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum, + else + load_count = min((u32) packet_sz, len); + +-#ifdef CONFIG_USB_INVENTRA_DMA +- if (dma_channel) { +- qh->segsize = min(len, dma_channel->max_len); +- if (qh->segsize <= packet_sz) +- dma_channel->desired_mode = 0; +- else +- dma_channel->desired_mode = 1; +- +- if (dma_channel->desired_mode == 0) { +- /* Against the programming guide */ +- csr |= (MUSB_TXCSR_DMAENAB); +- } else +- csr |= (MUSB_TXCSR_AUTOSET +- | MUSB_TXCSR_DMAENAB +- | MUSB_TXCSR_DMAMODE); +- musb_writew(epio, MUSB_TXCSR, csr); +- +- dma_ok = dma_controller->channel_program( +- dma_channel, packet_sz, +- dma_channel->desired_mode, +- urb->transfer_dma, +- qh->segsize); +- if (dma_ok) { +- load_count = 0; +- } else { +- dma_controller->channel_release(dma_channel); +- if (is_out) +- hw_ep->tx_channel = NULL; +- else +- hw_ep->rx_channel = NULL; +- dma_channel = NULL; +- +- /* +- * The programming guide says that we must +- * clear the DMAENAB bit before DMAMODE... +- */ +- csr = musb_readw(epio, MUSB_TXCSR); +- csr &= ~(MUSB_TXCSR_DMAENAB +- | MUSB_TXCSR_AUTOSET); +- musb_writew(epio, MUSB_TXCSR, csr); +- csr &= ~MUSB_TXCSR_DMAMODE; +- musb_writew(epio, MUSB_TXCSR, csr); +- } +- } +-#endif +- +- /* candidate for DMA */ +- if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) { +- +- /* Defer enabling DMA */ +- dma_channel->actual_len = 0L; +- qh->segsize = len; +- +- /* TX uses "rndis" mode automatically, but needs help +- * to identify the zero-length-final-packet case. +- */ +- dma_ok = dma_controller->channel_program( +- dma_channel, packet_sz, +- (urb->transfer_flags +- & URB_ZERO_PACKET) +- == URB_ZERO_PACKET, +- urb->transfer_dma, +- qh->segsize); +- if (dma_ok) { +- load_count = 0; +- } else { +- dma_controller->channel_release(dma_channel); +- hw_ep->tx_channel = NULL; +- dma_channel = NULL; +- +- /* REVISIT there's an error path here that +- * needs handling: can't do dma, but +- * there's no pio buffer address... +- */ +- } +- } ++ if (dma_channel && musb_tx_dma_program(dma_controller, ++ hw_ep, qh, urb, offset, len)) ++ load_count = 0; + + if (load_count) { + /* PIO to load FIFO */ +@@ -899,7 +880,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, + dma_channel, packet_sz, + !(urb->transfer_flags + & URB_SHORT_NOT_OK), +- urb->transfer_dma, ++ urb->transfer_dma + offset, + qh->segsize); + if (!dma_ok) { + dma_controller->channel_release( +@@ -1142,8 +1123,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) + int pipe; + bool done = false; + u16 tx_csr; +- size_t wLength = 0; +- u8 *buf = NULL; ++ size_t length = 0; ++ size_t offset = 0; + struct urb *urb; + struct musb_hw_ep *hw_ep = musb->endpoints + epnum; + void __iomem *epio = hw_ep->regs; +@@ -1161,7 +1142,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) + /* with CPPI, DMA sometimes triggers "extra" irqs */ + if (!urb) { + DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr); +- goto finish; ++ return; + } + + pipe = urb->pipe; +@@ -1198,7 +1179,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) + musb_writew(epio, MUSB_TXCSR, + MUSB_TXCSR_H_WZC_BITS + | MUSB_TXCSR_TXPKTRDY); +- goto finish; ++ return; + } + + if (status) { +@@ -1230,29 +1211,28 @@ void musb_host_tx(struct musb *musb, u8 epnum) + /* second cppi case */ + if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { + DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr); +- goto finish; +- ++ return; + } + +- /* REVISIT this looks wrong... */ + if (!status || dma || usb_pipeisoc(pipe)) { + if (dma) +- wLength = dma->actual_len; ++ length = dma->actual_len; + else +- wLength = qh->segsize; +- qh->offset += wLength; ++ length = qh->segsize; ++ qh->offset += length; + + if (usb_pipeisoc(pipe)) { + struct usb_iso_packet_descriptor *d; + + d = urb->iso_frame_desc + qh->iso_idx; +- d->actual_length = qh->segsize; ++ d->actual_length = length; ++ d->status = status; + if (++qh->iso_idx >= urb->number_of_packets) { + done = true; + } else { + d++; +- buf = urb->transfer_buffer + d->offset; +- wLength = d->length; ++ offset = d->offset; ++ length = d->length; + } + } else if (dma) { + done = true; +@@ -1265,10 +1245,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) + & URB_ZERO_PACKET)) + done = true; + if (!done) { +- buf = urb->transfer_buffer +- + qh->offset; +- wLength = urb->transfer_buffer_length +- - qh->offset; ++ offset = qh->offset; ++ length = urb->transfer_buffer_length - offset; + } + } + } +@@ -1287,28 +1265,31 @@ void musb_host_tx(struct musb *musb, u8 epnum) + urb->status = status; + urb->actual_length = qh->offset; + musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT); ++ return; ++ } else if (usb_pipeisoc(pipe) && dma) { ++ if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb, ++ offset, length)) ++ return; ++ } else if (tx_csr & MUSB_TXCSR_DMAENAB) { ++ DBG(1, "not complete, but DMA enabled?\n"); ++ return; ++ } + +- } else if (!(tx_csr & MUSB_TXCSR_DMAENAB)) { +- /* WARN_ON(!buf); */ +- +- /* REVISIT: some docs say that when hw_ep->tx_double_buffered, +- * (and presumably, fifo is not half-full) we should write TWO +- * packets before updating TXCSR ... other docs disagree ... +- */ +- /* PIO: start next packet in this URB */ +- if (wLength > qh->maxpacket) +- wLength = qh->maxpacket; +- musb_write_fifo(hw_ep, wLength, buf); +- qh->segsize = wLength; +- +- musb_ep_select(mbase, epnum); +- musb_writew(epio, MUSB_TXCSR, +- MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY); +- } else +- DBG(1, "not complete, but dma enabled?\n"); ++ /* ++ * PIO: start next packet in this URB. ++ * ++ * REVISIT: some docs say that when hw_ep->tx_double_buffered, ++ * (and presumably, FIFO is not half-full) we should write *two* ++ * packets before updating TXCSR; other docs disagree... ++ */ ++ if (length > qh->maxpacket) ++ length = qh->maxpacket; ++ musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset); ++ qh->segsize = length; + +-finish: +- return; ++ musb_ep_select(mbase, epnum); ++ musb_writew(epio, MUSB_TXCSR, ++ MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY); + } + + +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0012-musb-fix-possible-panic-while-resuming.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0012-musb-fix-possible-panic-while-resuming.patch new file mode 100644 index 0000000000..2bbde84c16 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0012-musb-fix-possible-panic-while-resuming.patch @@ -0,0 +1,56 @@ +From b9a61b80ea89d9d6d78a23d96a28df94fd612298 Mon Sep 17 00:00:00 2001 +From: Kim Kyuwon <q1.kim-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> +Date: Thu, 26 Mar 2009 18:56:51 -0700 +Subject: [PATCH] musb: fix possible panic while resuming + +During driver resume processing, musb could cause a kernel panic. +Fix by enabling the clock earlier, with the resume_early method. + +Signed-off-by: Kim Kyuwon <q1.kim-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_core.c | 8 ++------ + 1 files changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index 338cd16..3019725 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -2170,16 +2170,13 @@ static int musb_suspend(struct platform_device *pdev, pm_message_t message) + return 0; + } + +-static int musb_resume(struct platform_device *pdev) ++static int musb_resume_early(struct platform_device *pdev) + { +- unsigned long flags; + struct musb *musb = dev_to_musb(&pdev->dev); + + if (!musb->clock) + return 0; + +- spin_lock_irqsave(&musb->lock, flags); +- + if (musb->set_clock) + musb->set_clock(musb->clock, 1); + else +@@ -2189,7 +2186,6 @@ static int musb_resume(struct platform_device *pdev) + * unless for some reason the whole soc powered down and we're + * not treating that as a whole-system restart (e.g. swsusp) + */ +- spin_unlock_irqrestore(&musb->lock, flags); + return 0; + } + +@@ -2207,7 +2203,7 @@ static struct platform_driver musb_driver = { + .remove = __devexit_p(musb_remove), + .shutdown = musb_shutdown, + .suspend = musb_suspend, +- .resume = musb_resume, ++ .resume_early = musb_resume_early, + }; + + /*-------------------------------------------------------------------------*/ +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch new file mode 100644 index 0000000000..0202871d41 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch @@ -0,0 +1,91 @@ +From 2658f7c9029967501cd4d749364f2e02d02eebd5 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Date: Fri, 27 Mar 2009 12:54:21 -0700 +Subject: [PATCH] musb_host: refactor musb_save_toggle() (take 2) + +Refactor musb_save_toggle() as follows: + + - replace 'struct musb_hw_ep *ep' parameter by 'struct + musb_qh *qh' to avoid re-calculating this value + + - move usb_settogle() call out of the *if* operator. + +This is a net minor shrink of source and object code. + +Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_host.c | 35 ++++++++++++----------------------- + 1 files changed, 12 insertions(+), 23 deletions(-) + +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index f6e84a0..dc32ce4 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -318,35 +318,24 @@ __acquires(musb->lock) + spin_lock(&musb->lock); + } + +-/* for bulk/interrupt endpoints only */ +-static inline void +-musb_save_toggle(struct musb_hw_ep *ep, int is_in, struct urb *urb) ++/* For bulk/interrupt endpoints only */ ++static inline void musb_save_toggle(struct musb_qh *qh, int is_in, ++ struct urb *urb) + { +- struct usb_device *udev = urb->dev; ++ void __iomem *epio = qh->hw_ep->regs; + u16 csr; +- void __iomem *epio = ep->regs; +- struct musb_qh *qh; + +- /* FIXME: the current Mentor DMA code seems to have ++ /* ++ * FIXME: the current Mentor DMA code seems to have + * problems getting toggle correct. + */ + +- if (is_in || ep->is_shared_fifo) +- qh = ep->in_qh; ++ if (is_in) ++ csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE; + else +- qh = ep->out_qh; ++ csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE; + +- if (!is_in) { +- csr = musb_readw(epio, MUSB_TXCSR); +- usb_settoggle(udev, qh->epnum, 1, +- (csr & MUSB_TXCSR_H_DATATOGGLE) +- ? 1 : 0); +- } else { +- csr = musb_readw(epio, MUSB_RXCSR); +- usb_settoggle(udev, qh->epnum, 0, +- (csr & MUSB_RXCSR_H_DATATOGGLE) +- ? 1 : 0); +- } ++ usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0); + } + + /* caller owns controller lock, irqs are blocked */ +@@ -362,7 +351,7 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) + switch (qh->type) { + case USB_ENDPOINT_XFER_BULK: + case USB_ENDPOINT_XFER_INT: +- musb_save_toggle(ep, is_in, urb); ++ musb_save_toggle(qh, is_in, urb); + break; + case USB_ENDPOINT_XFER_ISOC: + if (status == 0 && urb->error_count) +@@ -1362,7 +1351,7 @@ static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep) + urb->actual_length += dma->actual_len; + dma->actual_len = 0L; + } +- musb_save_toggle(ep, 1, urb); ++ musb_save_toggle(cur_qh, 1, urb); + + /* move cur_qh to end of queue */ + list_move_tail(&cur_qh->ring, &musb->in_bulk); +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch new file mode 100644 index 0000000000..08e08a8538 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch @@ -0,0 +1,32 @@ +From 7766f2ea909b73f56d21746485069e02839b75f1 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Date: Fri, 27 Mar 2009 12:53:32 -0700 +Subject: [PATCH] musb_gadget: suppress "parasitic" TX interrupts with CPPI + +Suppress "parasitic" endpoint interrupts in the DMA mode +when using CPPI DMA driver; they're caused by the MUSB gadget +driver using the DMA request mode 0 instead of the mode 1. + +Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_gadget.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c +index f79440c..bc197b2 100644 +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -349,7 +349,8 @@ static void txstate(struct musb *musb, struct musb_request *req) + #elif defined(CONFIG_USB_TI_CPPI_DMA) + /* program endpoint CSR first, then setup DMA */ + csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY); +- csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB; ++ csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE | ++ MUSB_TXCSR_MODE; + musb_writew(epio, MUSB_TXCSR, + (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) + | csr); +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch new file mode 100644 index 0000000000..7115b152d9 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch @@ -0,0 +1,202 @@ +From 5424305125492a2417bde7c6d23ee4b84e25f6be Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Date: Fri, 27 Mar 2009 12:52:43 -0700 +Subject: [PATCH] musb_gadget: fix unhandled endpoint 0 IRQs + +The gadget EP0 code routinely ignores an interrupt at end of +the data phase because of musb_g_ep0_giveback() resetting the +state machine to "idle, waiting for SETUP" phase prematurely. + +The driver also prematurely leaves the status phase on +receiving the SetupEnd interrupt. + +As there were still unhandled endpoint 0 interrupts happening +from time to time after fixing these issues, there turned to +be yet another culprit: two distinct gadget states collapsed +into one. + +The (missing) state that comes after STATUS IN/OUT states was +typically indiscernible from them since the corresponding +interrupts tend to happen within too little period of time +(due to only a zero-length status packet in between) and so +they got coalesced; yet this state is not the same as the next +one which is associated with the reception of a SETUP packet. + +Adding this extra state seems to have fixed the rest of the +unhandled interrupts that generic_interrupt() and +davinci_interrupt() hid by faking their result and only +emitting a debug message -- so, stop doing that. + +Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/davinci.c | 7 +---- + drivers/usb/musb/musb_core.c | 8 +----- + drivers/usb/musb/musb_core.h | 3 +- + drivers/usb/musb/musb_gadget_ep0.c | 45 +++++++++++++++++++++++++++++++---- + 4 files changed, 43 insertions(+), 20 deletions(-) + +diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c +index 2dc7606..399c435 100644 +--- a/drivers/usb/musb/davinci.c ++++ b/drivers/usb/musb/davinci.c +@@ -357,12 +357,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) + + spin_unlock_irqrestore(&musb->lock, flags); + +- /* REVISIT we sometimes get unhandled IRQs +- * (e.g. ep0). not clear why... +- */ +- if (retval != IRQ_HANDLED) +- DBG(5, "unhandled? %08x\n", tmp); +- return IRQ_HANDLED; ++ return retval; + } + + int musb_platform_set_mode(struct musb *musb, u8 mode) +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index 3019725..a1de43b 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -1481,13 +1481,7 @@ static irqreturn_t generic_interrupt(int irq, void *__hci) + + spin_unlock_irqrestore(&musb->lock, flags); + +- /* REVISIT we sometimes get spurious IRQs on g_ep0 +- * not clear why... +- */ +- if (retval != IRQ_HANDLED) +- DBG(5, "spurious?\n"); +- +- return IRQ_HANDLED; ++ return retval; + } + + #else +diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h +index adf1806..f56a56c 100644 +--- a/drivers/usb/musb/musb_core.h ++++ b/drivers/usb/musb/musb_core.h +@@ -171,7 +171,8 @@ enum musb_h_ep0_state { + + /* peripheral side ep0 states */ + enum musb_g_ep0_state { +- MUSB_EP0_STAGE_SETUP, /* idle, waiting for setup */ ++ MUSB_EP0_STAGE_IDLE, /* idle, waiting for SETUP */ ++ MUSB_EP0_STAGE_SETUP, /* received SETUP */ + MUSB_EP0_STAGE_TX, /* IN data */ + MUSB_EP0_STAGE_RX, /* OUT data */ + MUSB_EP0_STAGE_STATUSIN, /* (after OUT data) */ +diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c +index 3f5e30d..ec0e899 100644 +--- a/drivers/usb/musb/musb_gadget_ep0.c ++++ b/drivers/usb/musb/musb_gadget_ep0.c +@@ -4,6 +4,7 @@ + * Copyright 2005 Mentor Graphics Corporation + * Copyright (C) 2005-2006 by Texas Instruments + * Copyright (C) 2006-2007 Nokia Corporation ++ * Copyright (C) 2008-2009 MontaVista Software, Inc. <source-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License +@@ -58,7 +59,8 @@ + static char *decode_ep0stage(u8 stage) + { + switch (stage) { +- case MUSB_EP0_STAGE_SETUP: return "idle"; ++ case MUSB_EP0_STAGE_IDLE: return "idle"; ++ case MUSB_EP0_STAGE_SETUP: return "setup"; + case MUSB_EP0_STAGE_TX: return "in"; + case MUSB_EP0_STAGE_RX: return "out"; + case MUSB_EP0_STAGE_ACKWAIT: return "wait"; +@@ -628,7 +630,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) + musb_writew(regs, MUSB_CSR0, + csr & ~MUSB_CSR0_P_SENTSTALL); + retval = IRQ_HANDLED; +- musb->ep0_state = MUSB_EP0_STAGE_SETUP; ++ musb->ep0_state = MUSB_EP0_STAGE_IDLE; + csr = musb_readw(regs, MUSB_CSR0); + } + +@@ -636,7 +638,18 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) + if (csr & MUSB_CSR0_P_SETUPEND) { + musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDSETUPEND); + retval = IRQ_HANDLED; +- musb->ep0_state = MUSB_EP0_STAGE_SETUP; ++ /* Transition into the early status phase */ ++ switch (musb->ep0_state) { ++ case MUSB_EP0_STAGE_TX: ++ musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT; ++ break; ++ case MUSB_EP0_STAGE_RX: ++ musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; ++ break; ++ default: ++ ERR("SetupEnd came in a wrong ep0stage %s", ++ decode_ep0stage(musb->ep0_state)); ++ } + csr = musb_readw(regs, MUSB_CSR0); + /* NOTE: request may need completion */ + } +@@ -697,11 +710,31 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) + if (req) + musb_g_ep0_giveback(musb, req); + } ++ ++ /* ++ * In case when several interrupts can get coalesced, ++ * check to see if we've already received a SETUP packet... ++ */ ++ if (csr & MUSB_CSR0_RXPKTRDY) ++ goto setup; ++ ++ retval = IRQ_HANDLED; ++ musb->ep0_state = MUSB_EP0_STAGE_IDLE; ++ break; ++ ++ case MUSB_EP0_STAGE_IDLE: ++ /* ++ * This state is typically (but not always) indiscernible ++ * from the status states since the corresponding interrupts ++ * tend to happen within too little period of time (with only ++ * a zero-length packet in between) and so get coalesced... ++ */ + retval = IRQ_HANDLED; + musb->ep0_state = MUSB_EP0_STAGE_SETUP; + /* FALLTHROUGH */ + + case MUSB_EP0_STAGE_SETUP: ++setup: + if (csr & MUSB_CSR0_RXPKTRDY) { + struct usb_ctrlrequest setup; + int handled = 0; +@@ -783,7 +816,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) + stall: + DBG(3, "stall (%d)\n", handled); + musb->ackpend |= MUSB_CSR0_P_SENDSTALL; +- musb->ep0_state = MUSB_EP0_STAGE_SETUP; ++ musb->ep0_state = MUSB_EP0_STAGE_IDLE; + finish: + musb_writew(regs, MUSB_CSR0, + musb->ackpend); +@@ -803,7 +836,7 @@ finish: + /* "can't happen" */ + WARN_ON(1); + musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SENDSTALL); +- musb->ep0_state = MUSB_EP0_STAGE_SETUP; ++ musb->ep0_state = MUSB_EP0_STAGE_IDLE; + break; + } + +@@ -959,7 +992,7 @@ static int musb_g_ep0_halt(struct usb_ep *e, int value) + + csr |= MUSB_CSR0_P_SENDSTALL; + musb_writew(regs, MUSB_CSR0, csr); +- musb->ep0_state = MUSB_EP0_STAGE_SETUP; ++ musb->ep0_state = MUSB_EP0_STAGE_IDLE; + musb->ackpend = 0; + break; + default: +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch new file mode 100644 index 0000000000..a2f54ff47b --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch @@ -0,0 +1,146 @@ +From f9ca8154cf395ec00129f12016697ef610a826ff Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Date: Fri, 27 Mar 2009 12:55:16 -0700 +Subject: [PATCH] musb_host: factor out musb_ep_{get|set}_qh() + +Factor out the often used code to get/set the active 'qh' +pointer for the hardware endpoint. Change the way the case +of a shared FIFO is handled by setting *both* 'in_qh' and +'out_qh' fields of 'struct musb_hw_ep'. That seems more +consistent and makes getting to the current 'qh' easy when +the code knows the direction beforehand. + +While at it, turn some assignments into intializers and +fix declaration style in the vicinity. + +Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_host.c | 56 ++++++++++++++++------------------------- + 1 files changed, 22 insertions(+), 34 deletions(-) + +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index dc32ce4..bc89079 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -178,6 +178,19 @@ static inline void cppi_host_txdma_start(struct musb_hw_ep *ep) + musb_writew(ep->regs, MUSB_TXCSR, txcsr); + } + ++static void musb_ep_set_qh(struct musb_hw_ep *ep, int is_in, struct musb_qh *qh) ++{ ++ if (is_in != 0 || ep->is_shared_fifo) ++ ep->in_qh = qh; ++ if (is_in == 0 || ep->is_shared_fifo) ++ ep->out_qh = qh; ++} ++ ++static struct musb_qh *musb_ep_get_qh(struct musb_hw_ep *ep, int is_in) ++{ ++ return is_in ? ep->in_qh : ep->out_qh; ++} ++ + /* + * Start the URB at the front of an endpoint's queue + * end must be claimed from the caller. +@@ -207,7 +220,6 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) + case USB_ENDPOINT_XFER_CONTROL: + /* control transfers always start with SETUP */ + is_in = 0; +- hw_ep->out_qh = qh; + musb->ep0_stage = MUSB_EP0_START; + buf = urb->setup_packet; + len = 8; +@@ -236,10 +248,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) + epnum, buf + offset, len); + + /* Configure endpoint */ +- if (is_in || hw_ep->is_shared_fifo) +- hw_ep->in_qh = qh; +- else +- hw_ep->out_qh = qh; ++ musb_ep_set_qh(hw_ep, is_in, qh); + musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len); + + /* transmit may have more work: start it when it is time */ +@@ -374,11 +383,8 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) + else + ep->tx_reinit = 1; + +- /* clobber old pointers to this qh */ +- if (is_in || ep->is_shared_fifo) +- ep->in_qh = NULL; +- else +- ep->out_qh = NULL; ++ /* Clobber old pointers to this qh */ ++ musb_ep_set_qh(ep, is_in, NULL); + qh->hep->hcpriv = NULL; + + switch (qh->type) { +@@ -421,12 +427,7 @@ static void + musb_advance_schedule(struct musb *musb, struct urb *urb, + struct musb_hw_ep *hw_ep, int is_in) + { +- struct musb_qh *qh; +- +- if (is_in || hw_ep->is_shared_fifo) +- qh = hw_ep->in_qh; +- else +- qh = hw_ep->out_qh; ++ struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in); + + if (urb->status == -EINPROGRESS) + qh = musb_giveback(qh, urb, 0); +@@ -689,15 +690,8 @@ static void musb_ep_program(struct musb *musb, u8 epnum, + void __iomem *mbase = musb->mregs; + struct musb_hw_ep *hw_ep = musb->endpoints + epnum; + void __iomem *epio = hw_ep->regs; +- struct musb_qh *qh; +- u16 packet_sz; +- +- if (!is_out || hw_ep->is_shared_fifo) +- qh = hw_ep->in_qh; +- else +- qh = hw_ep->out_qh; +- +- packet_sz = qh->maxpacket; ++ struct musb_qh *qh = musb_ep_get_qh(hw_ep, !is_out); ++ u16 packet_sz = qh->maxpacket; + + DBG(3, "%s hw%d urb %p spd%d dev%d ep%d%s " + "h_addr%02x h_port%02x bytes %d\n", +@@ -1114,17 +1108,14 @@ void musb_host_tx(struct musb *musb, u8 epnum) + u16 tx_csr; + size_t length = 0; + size_t offset = 0; +- struct urb *urb; + struct musb_hw_ep *hw_ep = musb->endpoints + epnum; + void __iomem *epio = hw_ep->regs; +- struct musb_qh *qh = hw_ep->is_shared_fifo ? hw_ep->in_qh +- : hw_ep->out_qh; ++ struct musb_qh *qh = hw_ep->out_qh; ++ struct urb *urb = next_urb(qh); + u32 status = 0; + void __iomem *mbase = musb->mregs; + struct dma_channel *dma; + +- urb = next_urb(qh); +- + musb_ep_select(mbase, epnum); + tx_csr = musb_readw(epio, MUSB_TXCSR); + +@@ -1741,10 +1732,7 @@ static int musb_schedule( + epnum++, hw_ep++) { + int diff; + +- if (is_in || hw_ep->is_shared_fifo) { +- if (hw_ep->in_qh != NULL) +- continue; +- } else if (hw_ep->out_qh != NULL) ++ if (musb_ep_get_qh(hw_ep, is_in) != NULL) + continue; + + if (hw_ep == musb->bulk_ep) +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0017-musb_host-refactor-URB-giveback.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0017-musb_host-refactor-URB-giveback.patch new file mode 100644 index 0000000000..4a520dff87 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0017-musb_host-refactor-URB-giveback.patch @@ -0,0 +1,132 @@ +From 013056a09afd324e729d64b9a0e66a004604e1d6 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Date: Fri, 27 Mar 2009 12:58:31 -0700 +Subject: [PATCH] musb_host: refactor URB giveback + +As musb_advance_schedule() is now the only remaning +caller of musb_giveback() (and the only valid context +of such call), just fold the latter into the former +and then rename __musb_giveback() into musb_giveback(). + +This is a net minor shrink. + +Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_host.c | 54 +++++++++++++++-------------------------- + 1 files changed, 20 insertions(+), 34 deletions(-) + +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index bc89079..e833959 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -292,9 +292,8 @@ start: + } + } + +-/* caller owns controller lock, irqs are blocked */ +-static void +-__musb_giveback(struct musb *musb, struct urb *urb, int status) ++/* Context: caller owns controller lock, IRQs are blocked */ ++static void musb_giveback(struct musb *musb, struct urb *urb, int status) + __releases(musb->lock) + __acquires(musb->lock) + { +@@ -347,14 +346,22 @@ static inline void musb_save_toggle(struct musb_qh *qh, int is_in, + usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0); + } + +-/* caller owns controller lock, irqs are blocked */ +-static struct musb_qh * +-musb_giveback(struct musb_qh *qh, struct urb *urb, int status) ++/* ++ * Advance this hardware endpoint's queue, completing the specified URB and ++ * advancing to either the next URB queued to that qh, or else invalidating ++ * that qh and advancing to the next qh scheduled after the current one. ++ * ++ * Context: caller owns controller lock, IRQs are blocked ++ */ ++static void musb_advance_schedule(struct musb *musb, struct urb *urb, ++ struct musb_hw_ep *hw_ep, int is_in) + { ++ struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in); + struct musb_hw_ep *ep = qh->hw_ep; +- struct musb *musb = ep->musb; +- int is_in = usb_pipein(urb->pipe); + int ready = qh->is_ready; ++ int status; ++ ++ status = (urb->status == -EINPROGRESS) ? 0 : urb->status; + + /* save toggle eagerly, for paranoia */ + switch (qh->type) { +@@ -363,13 +370,13 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) + musb_save_toggle(qh, is_in, urb); + break; + case USB_ENDPOINT_XFER_ISOC: +- if (status == 0 && urb->error_count) ++ if (urb->error_count) + status = -EXDEV; + break; + } + + qh->is_ready = 0; +- __musb_giveback(musb, urb, status); ++ musb_giveback(musb, urb, status); + qh->is_ready = ready; + + /* reclaim resources (and bandwidth) ASAP; deschedule it, and +@@ -413,31 +420,10 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) + break; + } + } +- return qh; +-} +- +-/* +- * Advance this hardware endpoint's queue, completing the specified urb and +- * advancing to either the next urb queued to that qh, or else invalidating +- * that qh and advancing to the next qh scheduled after the current one. +- * +- * Context: caller owns controller lock, irqs are blocked +- */ +-static void +-musb_advance_schedule(struct musb *musb, struct urb *urb, +- struct musb_hw_ep *hw_ep, int is_in) +-{ +- struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in); +- +- if (urb->status == -EINPROGRESS) +- qh = musb_giveback(qh, urb, 0); +- else +- qh = musb_giveback(qh, urb, urb->status); + + if (qh != NULL && qh->is_ready) { + DBG(4, "... next ep%d %cX urb %p\n", +- hw_ep->epnum, is_in ? 'R' : 'T', +- next_urb(qh)); ++ hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh)); + musb_start_urb(musb, is_in, qh); + } + } +@@ -2080,7 +2066,7 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + + ret = 0; + qh->is_ready = 0; +- __musb_giveback(musb, urb, 0); ++ musb_giveback(musb, urb, 0); + qh->is_ready = ready; + + /* If nothing else (usually musb_giveback) is using it +@@ -2164,7 +2150,7 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) + * will activate any of these as it advances. + */ + while (!list_empty(&hep->urb_list)) +- __musb_giveback(musb, next_urb(qh), -ESHUTDOWN); ++ musb_giveback(musb, next_urb(qh), -ESHUTDOWN); + + hep->hcpriv = NULL; + list_del(&qh->ring); +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0018-musb-split-out-CPPI-interrupt-handler.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0018-musb-split-out-CPPI-interrupt-handler.patch new file mode 100644 index 0000000000..bf3d6e7021 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0018-musb-split-out-CPPI-interrupt-handler.patch @@ -0,0 +1,167 @@ +From b91b067c531c9322f3719951b07303e790b13475 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Date: Fri, 27 Mar 2009 12:59:46 -0700 +Subject: [PATCH] musb: split out CPPI interrupt handler + +As DaVinci DM646x has a dedicated CPPI DMA interrupt, replace +cppi_completion() (which has always been kind of layering +violation) by a complete CPPI interrupt handler. + +[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: only cppi_dma.c needs platform +device header, not cppi_dma.h ] + +Signed-off-by: Dmitry Krivoschekov <dkrivoschekov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/cppi_dma.c | 34 +++++++++++++++++++++++++++++++--- + drivers/usb/musb/cppi_dma.h | 6 ++++-- + drivers/usb/musb/davinci.c | 14 ++++---------- + 3 files changed, 39 insertions(+), 15 deletions(-) + +diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c +index ac7227c..6ff3c67 100644 +--- a/drivers/usb/musb/cppi_dma.c ++++ b/drivers/usb/musb/cppi_dma.c +@@ -6,6 +6,7 @@ + * The TUSB6020, using VLYNQ, has CPPI that looks much like DaVinci. + */ + ++#include <linux/platform_device.h> + #include <linux/usb.h> + + #include "musb_core.h" +@@ -1145,17 +1146,27 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch) + return completed; + } + +-void cppi_completion(struct musb *musb, u32 rx, u32 tx) ++irqreturn_t cppi_interrupt(int irq, void *dev_id) + { +- void __iomem *tibase; +- int i, index; ++ struct musb *musb = dev_id; + struct cppi *cppi; ++ void __iomem *tibase; + struct musb_hw_ep *hw_ep = NULL; ++ u32 rx, tx; ++ int i, index; + + cppi = container_of(musb->dma_controller, struct cppi, controller); + + tibase = musb->ctrl_base; + ++ tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG); ++ rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG); ++ ++ if (!tx && !rx) ++ return IRQ_NONE; ++ ++ DBG(4, "CPPI IRQ Tx%x Rx%x\n", tx, rx); ++ + /* process TX channels */ + for (index = 0; tx; tx = tx >> 1, index++) { + struct cppi_channel *tx_ch; +@@ -1293,6 +1304,8 @@ void cppi_completion(struct musb *musb, u32 rx, u32 tx) + + /* write to CPPI EOI register to re-enable interrupts */ + musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0); ++ ++ return IRQ_HANDLED; + } + + /* Instantiate a software object representing a DMA controller. */ +@@ -1300,6 +1313,9 @@ struct dma_controller *__init + dma_controller_create(struct musb *musb, void __iomem *mregs) + { + struct cppi *controller; ++ struct device *dev = musb->controller; ++ struct platform_device *pdev = to_platform_device(dev); ++ int irq = platform_get_irq(pdev, 1); + + controller = kzalloc(sizeof *controller, GFP_KERNEL); + if (!controller) +@@ -1330,6 +1346,15 @@ dma_controller_create(struct musb *musb, void __iomem *mregs) + return NULL; + } + ++ if (irq > 0) { ++ if (request_irq(irq, cppi_interrupt, 0, "cppi-dma", musb)) { ++ dev_err(dev, "request_irq %d failed!\n", irq); ++ dma_controller_destroy(&controller->controller); ++ return NULL; ++ } ++ controller->irq = irq; ++ } ++ + return &controller->controller; + } + +@@ -1342,6 +1367,9 @@ void dma_controller_destroy(struct dma_controller *c) + + cppi = container_of(c, struct cppi, controller); + ++ if (cppi->irq) ++ free_irq(cppi->irq, cppi->musb); ++ + /* assert: caller stopped the controller first */ + dma_pool_destroy(cppi->pool); + +diff --git a/drivers/usb/musb/cppi_dma.h b/drivers/usb/musb/cppi_dma.h +index 729b407..8a39de3 100644 +--- a/drivers/usb/musb/cppi_dma.h ++++ b/drivers/usb/musb/cppi_dma.h +@@ -119,6 +119,8 @@ struct cppi { + void __iomem *mregs; /* Mentor regs */ + void __iomem *tibase; /* TI/CPPI regs */ + ++ int irq; ++ + struct cppi_channel tx[4]; + struct cppi_channel rx[4]; + +@@ -127,7 +129,7 @@ struct cppi { + struct list_head tx_complete; + }; + +-/* irq handling hook */ +-extern void cppi_completion(struct musb *, u32 rx, u32 tx); ++/* CPPI IRQ handler */ ++extern irqreturn_t cppi_interrupt(int, void *); + + #endif /* end of ifndef _CPPI_DMA_H_ */ +diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c +index 399c435..9fd74bf 100644 +--- a/drivers/usb/musb/davinci.c ++++ b/drivers/usb/musb/davinci.c +@@ -250,6 +250,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) + irqreturn_t retval = IRQ_NONE; + struct musb *musb = __hci; + void __iomem *tibase = musb->ctrl_base; ++ struct cppi *cppi; + u32 tmp; + + spin_lock_irqsave(&musb->lock, flags); +@@ -266,16 +267,9 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) + /* CPPI interrupts share the same IRQ line, but have their own + * mask, state, "vector", and EOI registers. + */ +- if (is_cppi_enabled()) { +- u32 cppi_tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG); +- u32 cppi_rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG); +- +- if (cppi_tx || cppi_rx) { +- DBG(4, "CPPI IRQ t%x r%x\n", cppi_tx, cppi_rx); +- cppi_completion(musb, cppi_rx, cppi_tx); +- retval = IRQ_HANDLED; +- } +- } ++ cppi = container_of(musb->dma_controller, struct cppi, controller); ++ if (is_cppi_enabled() && musb->dma_controller && !cppi->irq) ++ retval = cppi_interrupt(irq, __hci); + + /* ack and handle non-CPPI interrupts */ + tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG); +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0019-musb_host-simplify-check-for-active-URB.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0019-musb_host-simplify-check-for-active-URB.patch new file mode 100644 index 0000000000..c0e57155c8 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0019-musb_host-simplify-check-for-active-URB.patch @@ -0,0 +1,158 @@ +From 69242ddd26151d45f46011cf7abc581b14699fb2 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Date: Fri, 27 Mar 2009 12:56:26 -0700 +Subject: [PATCH] musb_host: simplify check for active URB + +The existance of the scheduling list shouldn't matter in +determining whether there's currectly an URB executing on a +hardware endpoint. What should actually matter is the 'in_qh' +or 'out_qh' fields of the 'struct musb_hw_ep' -- those are +set in musb_start_urb() and cleared in musb_giveback() when +the endpoint's URB list drains. Hence we should be able to +replace the big *switch* statements in musb_urb_dequeue() +and musb_h_disable() with mere musb_ep_get_qh() calls... + +While at it, do some more changes: + + - add 'is_in' variable to musb_urb_dequeue(); + + - remove the unnecessary 'epnum' variable from musb_h_disable(); + + - fix the comment style in the vicinity. + +This is a minor shrink of source and object code. + +Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_host.c | 72 ++++++++--------------------------------- + 1 files changed, 14 insertions(+), 58 deletions(-) + +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index e833959..e121e0e 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -2008,14 +2008,14 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + { + struct musb *musb = hcd_to_musb(hcd); + struct musb_qh *qh; +- struct list_head *sched; + unsigned long flags; ++ int is_in = usb_pipein(urb->pipe); + int ret; + + DBG(4, "urb=%p, dev%d ep%d%s\n", urb, + usb_pipedevice(urb->pipe), + usb_pipeendpoint(urb->pipe), +- usb_pipein(urb->pipe) ? "in" : "out"); ++ is_in ? "in" : "out"); + + spin_lock_irqsave(&musb->lock, flags); + ret = usb_hcd_check_unlink_urb(hcd, urb, status); +@@ -2026,45 +2026,23 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + if (!qh) + goto done; + +- /* Any URB not actively programmed into endpoint hardware can be ++ /* ++ * Any URB not actively programmed into endpoint hardware can be + * immediately given back; that's any URB not at the head of an + * endpoint queue, unless someday we get real DMA queues. And even + * if it's at the head, it might not be known to the hardware... + * +- * Otherwise abort current transfer, pending dma, etc.; urb->status ++ * Otherwise abort current transfer, pending DMA, etc.; urb->status + * has already been updated. This is a synchronous abort; it'd be + * OK to hold off until after some IRQ, though. ++ * ++ * NOTE: qh is invalid unless !list_empty(&hep->urb_list) + */ +- if (!qh->is_ready || urb->urb_list.prev != &qh->hep->urb_list) +- ret = -EINPROGRESS; +- else { +- switch (qh->type) { +- case USB_ENDPOINT_XFER_CONTROL: +- sched = &musb->control; +- break; +- case USB_ENDPOINT_XFER_BULK: +- if (qh->mux == 1) { +- if (usb_pipein(urb->pipe)) +- sched = &musb->in_bulk; +- else +- sched = &musb->out_bulk; +- break; +- } +- default: +- /* REVISIT when we get a schedule tree, periodic +- * transfers won't always be at the head of a +- * singleton queue... +- */ +- sched = NULL; +- break; +- } +- } +- +- /* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */ +- if (ret < 0 || (sched && qh != first_qh(sched))) { ++ if (!qh->is_ready ++ || urb->urb_list.prev != &qh->hep->urb_list ++ || musb_ep_get_qh(qh->hw_ep, is_in) != qh) { + int ready = qh->is_ready; + +- ret = 0; + qh->is_ready = 0; + musb_giveback(musb, urb, 0); + qh->is_ready = ready; +@@ -2088,13 +2066,11 @@ done: + static void + musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) + { +- u8 epnum = hep->desc.bEndpointAddress; ++ u8 is_in = hep->desc.bEndpointAddress & USB_DIR_IN; + unsigned long flags; + struct musb *musb = hcd_to_musb(hcd); +- u8 is_in = epnum & USB_DIR_IN; + struct musb_qh *qh; + struct urb *urb; +- struct list_head *sched; + + spin_lock_irqsave(&musb->lock, flags); + +@@ -2102,31 +2078,11 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) + if (qh == NULL) + goto exit; + +- switch (qh->type) { +- case USB_ENDPOINT_XFER_CONTROL: +- sched = &musb->control; +- break; +- case USB_ENDPOINT_XFER_BULK: +- if (qh->mux == 1) { +- if (is_in) +- sched = &musb->in_bulk; +- else +- sched = &musb->out_bulk; +- break; +- } +- default: +- /* REVISIT when we get a schedule tree, periodic transfers +- * won't always be at the head of a singleton queue... +- */ +- sched = NULL; +- break; +- } +- +- /* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */ ++ /* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */ + +- /* kick first urb off the hardware, if needed */ ++ /* Kick the first URB off the hardware, if needed */ + qh->is_ready = 0; +- if (!sched || qh == first_qh(sched)) { ++ if (musb_ep_get_qh(qh->hw_ep, is_in) == qh) { + urb = next_urb(qh); + + /* make software (then hardware) stop ASAP */ +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch new file mode 100644 index 0000000000..d89eaadd61 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch @@ -0,0 +1,58 @@ +From d408894fa4263440ed8a9e68566bacea7e6f6bed Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Date: Fri, 27 Mar 2009 12:57:50 -0700 +Subject: [PATCH] musb_host: streamline musb_cleanup_urb() calls + +The argument for the 'is_in' parameter of musb_cleanup_urb() +is always extracted from an URB that's passed to the function. +So that parameter is superfluous; remove it. + +Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_host.c | 9 +++++---- + 1 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index e121e0e..71e835e 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -1950,14 +1950,15 @@ done: + * called with controller locked, irqs blocked + * that hardware queue advances to the next transfer, unless prevented + */ +-static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in) ++static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh) + { + struct musb_hw_ep *ep = qh->hw_ep; + void __iomem *epio = ep->regs; + unsigned hw_end = ep->epnum; + void __iomem *regs = ep->musb->mregs; +- u16 csr; ++ int is_in = usb_pipein(urb->pipe); + int status = 0; ++ u16 csr; + + musb_ep_select(regs, hw_end); + +@@ -2056,7 +2057,7 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + kfree(qh); + } + } else +- ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); ++ ret = musb_cleanup_urb(urb, qh); + done: + spin_unlock_irqrestore(&musb->lock, flags); + return ret; +@@ -2090,7 +2091,7 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) + urb->status = -ESHUTDOWN; + + /* cleanup */ +- musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); ++ musb_cleanup_urb(urb, qh); + + /* Then nuke all the others ... and advance the + * queue on hw_ep (e.g. bulk ring) when we're done. +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch new file mode 100644 index 0000000000..d9733f92b0 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch @@ -0,0 +1,70 @@ +From c4804e5a447275553c55bbb0ab1748954cb8fbfc Mon Sep 17 00:00:00 2001 +From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Date: Tue, 31 Mar 2009 12:26:10 -0700 +Subject: [PATCH] twl4030-usb: fix minor reporting goofage + +Fix a reporting glitch in the twl4030 USB transceiver code. +It wasn't properly distinguishing the two types of active +USB link: ID grounded, vs not. In the current code that +distinction doesn't much matter; in the future this bugfix +should help support better USB controller communications. + +Provide a comment sorting out some of the cryptic bits of +the manual: different sections use different names for +key signals, and the register definitions don't help much +without the explanations and diagrams. + +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/otg/twl4030-usb.c | 26 +++++++++++++++++++------- + 1 files changed, 19 insertions(+), 7 deletions(-) + +diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c +index d9478d0..f740390 100644 +--- a/drivers/usb/otg/twl4030-usb.c ++++ b/drivers/usb/otg/twl4030-usb.c +@@ -217,6 +217,7 @@ + + /* In module TWL4030_MODULE_PM_MASTER */ + #define PROTECT_KEY 0x0E ++#define STS_HW_CONDITIONS 0x0F + + /* In module TWL4030_MODULE_PM_RECEIVER */ + #define VUSB_DEDICATED1 0x7D +@@ -351,15 +352,26 @@ static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl) + int status; + int linkstat = USB_LINK_UNKNOWN; + +- /* STS_HW_CONDITIONS */ +- status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, 0x0f); ++ /* ++ * For ID/VBUS sensing, see manual section 15.4.8 ... ++ * except when using only battery backup power, two ++ * comparators produce VBUS_PRES and ID_PRES signals, ++ * which don't match docs elsewhere. But ... BIT(7) ++ * and BIT(2) of STS_HW_CONDITIONS, respectively, do ++ * seem to match up. If either is true the USB_PRES ++ * signal is active, the OTG module is activated, and ++ * its interrupt may be raised (may wake the system). ++ */ ++ status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, ++ STS_HW_CONDITIONS); + if (status < 0) + dev_err(twl->dev, "USB link status err %d\n", status); +- else if (status & BIT(7)) +- linkstat = USB_LINK_VBUS; +- else if (status & BIT(2)) +- linkstat = USB_LINK_ID; +- else ++ else if (status & (BIT(7) | BIT(2))) { ++ if (status & BIT(2)) ++ linkstat = USB_LINK_ID; ++ else ++ linkstat = USB_LINK_VBUS; ++ } else + linkstat = USB_LINK_NONE; + + dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch new file mode 100644 index 0000000000..16b5b9908b --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch @@ -0,0 +1,38 @@ +From ba59a0812ba0e223bd0af8f4dea6c971b6289696 Mon Sep 17 00:00:00 2001 +From: Anand Gadiyar <gadiyar-l0cyMroinI0@public.gmane.org> +Date: Thu, 2 Apr 2009 12:07:08 -0700 +Subject: [PATCH] musb: use dma mode 1 for TX if transfer size equals maxpacket (v2) + +Currently, with Inventra DMA, we use Mode 0 if transfer size is less +than or equal to the endpoint's maxpacket size. This requires that +we explicitly set TXPKTRDY for that transfer. + +However the musb_g_tx code will not set TXPKTRDY twice if the last +transfer is exactly equal to maxpacket, even if request->zero is set. +Using Mode 1 will solve this; a better fix might be in musb_g_tx(). + +Without this change, musb will not correctly send out a ZLP if the +last transfer is the maxpacket size and request->zero is set. + +Signed-off-by: Anand Gadiyar <gadiyar-l0cyMroinI0@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_gadget.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c +index bc197b2..e8f920c 100644 +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -310,7 +310,7 @@ static void txstate(struct musb *musb, struct musb_request *req) + /* setup DMA, then program endpoint CSR */ + request_size = min(request->length, + musb_ep->dma->max_len); +- if (request_size <= musb_ep->packet_sz) ++ if (request_size < musb_ep->packet_sz) + musb_ep->dma->desired_mode = 0; + else + musb_ep->dma->desired_mode = 1; +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0023-musb-add-high-bandwidth-ISO-support.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0023-musb-add-high-bandwidth-ISO-support.patch new file mode 100644 index 0000000000..3038dd171d --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0023-musb-add-high-bandwidth-ISO-support.patch @@ -0,0 +1,187 @@ +From 2e049a88b729ae2fdc0ecdabad1857810bd62737 Mon Sep 17 00:00:00 2001 +From: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> +Date: Fri, 3 Apr 2009 16:16:17 -0700 +Subject: [PATCH] musb: add high bandwidth ISO support + +Tested on OMAP3 host side with Creative (Live! Cam Optia) USB camera +which uses high bandwidth isochronous IN endpoints. FIFO mode 4 is +updated to provide the needed 4K endpoint buffer without breaking +the g_nokia composite gadget configuration. (This is the only +gadget driver known to use enough endpoints to notice the change.) + +Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_core.c | 19 ++++++++--------- + drivers/usb/musb/musb_core.h | 3 ++ + drivers/usb/musb/musb_host.c | 47 +++++++++++++++++++++++++++++++---------- + drivers/usb/musb/musb_host.h | 1 + + 4 files changed, 48 insertions(+), 22 deletions(-) + +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index a1de43b..d953305 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -1068,14 +1068,13 @@ static struct fifo_cfg __initdata mode_4_cfg[] = { + { .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 512, }, +-{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 512, }, +-{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 512, }, +-{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 512, }, +-{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 512, }, +-{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 512, }, +-{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 512, }, +-{ .hw_ep_num = 13, .style = FIFO_TX, .maxpacket = 512, }, +-{ .hw_ep_num = 13, .style = FIFO_RX, .maxpacket = 512, }, ++{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 256, }, ++{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 64, }, ++{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 256, }, ++{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 64, }, ++{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 256, }, ++{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 64, }, ++{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 4096, }, + { .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, }, + { .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, + }; +@@ -1335,11 +1334,11 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) + } + if (reg & MUSB_CONFIGDATA_HBRXE) { + strcat(aInfo, ", HB-ISO Rx"); +- strcat(aInfo, " (X)"); /* no driver support */ ++ musb->hb_iso_rx = true; + } + if (reg & MUSB_CONFIGDATA_HBTXE) { + strcat(aInfo, ", HB-ISO Tx"); +- strcat(aInfo, " (X)"); /* no driver support */ ++ musb->hb_iso_tx = true; + } + if (reg & MUSB_CONFIGDATA_SOFTCONE) + strcat(aInfo, ", SoftConn"); +diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h +index f56a56c..0ac4faf 100644 +--- a/drivers/usb/musb/musb_core.h ++++ b/drivers/usb/musb/musb_core.h +@@ -387,6 +387,9 @@ struct musb { + unsigned is_multipoint:1; + unsigned ignore_disconnect:1; /* during bus resets */ + ++ unsigned hb_iso_rx:1; /* high bandwidth iso rx? */ ++ unsigned hb_iso_tx:1; /* high bandwidth iso tx? */ ++ + #ifdef C_MP_TX + unsigned bulk_split:1; + #define can_bulk_split(musb,type) \ +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index 71e835e..ece5122 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -602,7 +602,8 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) + musb_writeb(ep->regs, MUSB_RXTYPE, qh->type_reg); + musb_writeb(ep->regs, MUSB_RXINTERVAL, qh->intv_reg); + /* NOTE: bulk combining rewrites high bits of maxpacket */ +- musb_writew(ep->regs, MUSB_RXMAXP, qh->maxpacket); ++ musb_writew(ep->regs, MUSB_RXMAXP, ++ qh->maxpacket | ((qh->hb_mult - 1) << 11)); + + ep->rx_reinit = 0; + } +@@ -624,9 +625,10 @@ static bool musb_tx_dma_program(struct dma_controller *dma, + csr = musb_readw(epio, MUSB_TXCSR); + if (length > pkt_size) { + mode = 1; +- csr |= MUSB_TXCSR_AUTOSET +- | MUSB_TXCSR_DMAMODE +- | MUSB_TXCSR_DMAENAB; ++ csr |= MUSB_TXCSR_DMAMODE | MUSB_TXCSR_DMAENAB; ++ /* autoset shouldn't be set in high bandwidth */ ++ if (qh->hb_mult == 1) ++ csr |= MUSB_TXCSR_AUTOSET; + } else { + mode = 0; + csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE); +@@ -1432,6 +1434,10 @@ void musb_host_rx(struct musb *musb, u8 epnum) + /* packet error reported later */ + iso_err = true; + } ++ } else if (rx_csr & MUSB_RXCSR_INCOMPRX) { ++ DBG(3, "end %d high bandwidth incomplete ISO packet RX\n", ++ epnum); ++ status = -EPROTO; + } + + /* faults abort the transfer */ +@@ -1639,7 +1645,11 @@ void musb_host_rx(struct musb *musb, u8 epnum) + val &= ~MUSB_RXCSR_H_AUTOREQ; + else + val |= MUSB_RXCSR_H_AUTOREQ; +- val |= MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB; ++ val |= MUSB_RXCSR_DMAENAB; ++ ++ /* autoclear shouldn't be set in high bandwidth */ ++ if (qh->hb_mult == 1) ++ val |= MUSB_RXCSR_AUTOCLEAR; + + musb_writew(epio, MUSB_RXCSR, + MUSB_RXCSR_H_WZC_BITS | val); +@@ -1725,9 +1735,10 @@ static int musb_schedule( + continue; + + if (is_in) +- diff = hw_ep->max_packet_sz_rx - qh->maxpacket; ++ diff = hw_ep->max_packet_sz_rx; + else +- diff = hw_ep->max_packet_sz_tx - qh->maxpacket; ++ diff = hw_ep->max_packet_sz_tx; ++ diff -= (qh->maxpacket * qh->hb_mult); + + if (diff >= 0 && best_diff > diff) { + best_diff = diff; +@@ -1830,15 +1841,27 @@ static int musb_urb_enqueue( + qh->is_ready = 1; + + qh->maxpacket = le16_to_cpu(epd->wMaxPacketSize); ++ qh->type = usb_endpoint_type(epd); + +- /* no high bandwidth support yet */ +- if (qh->maxpacket & ~0x7ff) { +- ret = -EMSGSIZE; +- goto done; ++ /* Bits 11 & 12 of wMaxPacketSize encode high bandwidth multiplier. ++ * Some musb cores don't support high bandwidth ISO transfers; and ++ * we don't (yet!) support high bandwidth interrupt transfers. ++ */ ++ qh->hb_mult = 1 + ((qh->maxpacket >> 11) & 0x03); ++ if (qh->hb_mult > 1) { ++ int ok = (qh->type == USB_ENDPOINT_XFER_ISOC); ++ ++ if (ok) ++ ok = (usb_pipein(urb->pipe) && musb->hb_iso_rx) ++ || (usb_pipeout(urb->pipe) && musb->hb_iso_tx); ++ if (!ok) { ++ ret = -EMSGSIZE; ++ goto done; ++ } ++ qh->maxpacket &= 0x7ff; + } + + qh->epnum = usb_endpoint_num(epd); +- qh->type = usb_endpoint_type(epd); + + /* NOTE: urb->dev->devnum is wrong during SET_ADDRESS */ + qh->addr_reg = (u8) usb_pipedevice(urb->pipe); +diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h +index 0b7fbcd..14b0077 100644 +--- a/drivers/usb/musb/musb_host.h ++++ b/drivers/usb/musb/musb_host.h +@@ -67,6 +67,7 @@ struct musb_qh { + u8 is_ready; /* safe to modify hw_ep */ + u8 type; /* XFERTYPE_* */ + u8 epnum; ++ u8 hb_mult; /* high bandwidth pkts per uf */ + u16 maxpacket; + u16 frame; /* for periodic schedule */ + unsigned iso_idx; /* in urb->iso_frame_desc[] */ +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0024-USB-otg-adding-nop-usb-transceiver.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0024-USB-otg-adding-nop-usb-transceiver.patch new file mode 100644 index 0000000000..67004d7ec6 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0024-USB-otg-adding-nop-usb-transceiver.patch @@ -0,0 +1,259 @@ +From de835357b3597af5304742cbd89771d70533292a Mon Sep 17 00:00:00 2001 +From: Ajay Kumar Gupta <ajay.gupta@ti.com> +Date: Fri, 6 Feb 2009 17:32:35 +0530 +Subject: [PATCH] USB: otg: adding nop usb transceiver + +NOP transceiver is used by all the usb transceiver which are mostly +autonomous and doesn't require any programming or which are built +into the usb ip itself.NOP transceiver only allocates the memory +for struct xceiv and calls otg_set_transceiver() so function call +to otg_get_transceiver() will return a valid transceiver. + +NOP transceiver device should be registered by calling +usb_nop_xceiv_register() from platform files. + +Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com> +Cc: Felipe Balbi <felipe.balbi@nokia.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/otg/Kconfig | 8 ++ + drivers/usb/otg/Makefile | 1 + + drivers/usb/otg/nop-usb-xceiv.c | 180 +++++++++++++++++++++++++++++++++++++++ + include/linux/usb/otg.h | 4 + + 4 files changed, 193 insertions(+), 0 deletions(-) + create mode 100644 drivers/usb/otg/nop-usb-xceiv.c + +diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig +index 5790a5b..aa884d0 100644 +--- a/drivers/usb/otg/Kconfig ++++ b/drivers/usb/otg/Kconfig +@@ -51,4 +51,12 @@ config TWL4030_USB + This transceiver supports high and full speed devices plus, + in host mode, low speed. + ++config NOP_USB_XCEIV ++ tristate "NOP USB Transceiver Driver" ++ select USB_OTG_UTILS ++ help ++ this driver is to be used by all the usb transceiver which are either ++ built-in with usb ip or which are autonomous and doesn't require any ++ phy programming such as ISP1x04 etc. ++ + endif # USB || OTG +diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile +index d73c7cf..2081678 100644 +--- a/drivers/usb/otg/Makefile ++++ b/drivers/usb/otg/Makefile +@@ -9,6 +9,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o + obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o + obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o + obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o ++obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o + + ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG + ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG +diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c +new file mode 100644 +index 0000000..4b933f6 +--- /dev/null ++++ b/drivers/usb/otg/nop-usb-xceiv.c +@@ -0,0 +1,180 @@ ++/* ++ * drivers/usb/otg/nop-usb-xceiv.c ++ * ++ * NOP USB transceiver for all USB transceiver which are either built-in ++ * into USB IP or which are mostly autonomous. ++ * ++ * Copyright (C) 2009 Texas Instruments Inc ++ * Author: Ajay Kumar Gupta <ajay.gupta@ti.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * Current status: ++ * this is to add "nop" transceiver for all those phy which is ++ * autonomous such as isp1504 etc. ++ */ ++ ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/dma-mapping.h> ++#include <linux/usb/otg.h> ++ ++struct nop_usb_xceiv { ++ struct otg_transceiver otg; ++ struct device *dev; ++}; ++ ++static u64 nop_xceiv_dmamask = DMA_32BIT_MASK; ++ ++static struct platform_device nop_xceiv_device = { ++ .name = "nop_usb_xceiv", ++ .id = -1, ++ .dev = { ++ .dma_mask = &nop_xceiv_dmamask, ++ .coherent_dma_mask = DMA_32BIT_MASK, ++ .platform_data = NULL, ++ }, ++}; ++ ++void usb_nop_xceiv_register(void) ++{ ++ if (platform_device_register(&nop_xceiv_device) < 0) { ++ printk(KERN_ERR "Unable to register usb nop transceiver\n"); ++ return; ++ } ++} ++ ++void usb_nop_xceiv_unregister(void) ++{ ++ platform_device_unregister(&nop_xceiv_device); ++} ++ ++static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x) ++{ ++ return container_of(x, struct nop_usb_xceiv, otg); ++} ++ ++static int nop_set_suspend(struct otg_transceiver *x, int suspend) ++{ ++ return 0; ++} ++ ++static int nop_set_peripheral(struct otg_transceiver *x, ++ struct usb_gadget *gadget) ++{ ++ struct nop_usb_xceiv *nop; ++ ++ if (!x) ++ return -ENODEV; ++ ++ nop = xceiv_to_nop(x); ++ ++ if (!gadget) { ++ nop->otg.gadget = NULL; ++ return -ENODEV; ++ } ++ ++ nop->otg.gadget = gadget; ++ nop->otg.state = OTG_STATE_B_IDLE; ++ return 0; ++} ++ ++static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host) ++{ ++ struct nop_usb_xceiv *nop; ++ ++ if (!x) ++ return -ENODEV; ++ ++ nop = xceiv_to_nop(x); ++ ++ if (!host) { ++ nop->otg.host = NULL; ++ return -ENODEV; ++ } ++ ++ nop->otg.host = host; ++ return 0; ++} ++ ++static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) ++{ ++ struct nop_usb_xceiv *nop; ++ int err; ++ ++ nop = kzalloc(sizeof *nop, GFP_KERNEL); ++ if (!nop) ++ return -ENOMEM; ++ ++ nop->dev = &pdev->dev; ++ nop->otg.dev = nop->dev; ++ nop->otg.label = "nop-xceiv"; ++ nop->otg.state = OTG_STATE_UNDEFINED; ++ nop->otg.set_host = nop_set_host; ++ nop->otg.set_peripheral = nop_set_peripheral; ++ nop->otg.set_suspend = nop_set_suspend; ++ ++ err = otg_set_transceiver(&nop->otg); ++ if (err) { ++ dev_err(&pdev->dev, "can't register transceiver, err: %d\n", ++ err); ++ goto exit; ++ } ++ ++ platform_set_drvdata(pdev, nop); ++ ++ return 0; ++exit: ++ kfree(nop); ++ return err; ++} ++ ++static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) ++{ ++ struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); ++ ++ otg_set_transceiver(NULL); ++ ++ platform_set_drvdata(pdev, NULL); ++ kfree(nop); ++ ++ return 0; ++} ++ ++static struct platform_driver nop_usb_xceiv_driver = { ++ .probe = nop_usb_xceiv_probe, ++ .remove = __devexit_p(nop_usb_xceiv_remove), ++ .driver = { ++ .name = "nop_usb_xceiv", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init nop_usb_xceiv_init(void) ++{ ++ return platform_driver_register(&nop_usb_xceiv_driver); ++} ++subsys_initcall(nop_usb_xceiv_init); ++ ++static void __exit nop_usb_xceiv_exit(void) ++{ ++ platform_driver_unregister(&nop_usb_xceiv_driver); ++} ++module_exit(nop_usb_xceiv_exit); ++ ++MODULE_ALIAS("platform:nop_usb_xceiv"); ++MODULE_AUTHOR("Texas Instruments Inc"); ++MODULE_DESCRIPTION("NOP USB Transceiver driver"); ++MODULE_LICENSE("GPL"); +diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h +index 94df4fe..54f2424 100644 +--- a/include/linux/usb/otg.h ++++ b/include/linux/usb/otg.h +@@ -80,6 +80,10 @@ struct otg_transceiver { + + /* for board-specific init logic */ + extern int otg_set_transceiver(struct otg_transceiver *); ++#ifdef CONFIG_NOP_USB_XCEIV ++extern void usb_nop_xceiv_register(void); ++extern void usb_nop_xceiv_unregister(void); ++#endif + + + /* for usb host and peripheral controller drivers */ +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch new file mode 100644 index 0000000000..21fe7bea17 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch @@ -0,0 +1,90 @@ +From ae4f027580168814f734cf3c41a662a7f10c744c Mon Sep 17 00:00:00 2001 +From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Date: Tue, 31 Mar 2009 12:28:31 -0700 +Subject: [PATCH] nop-usb-xceiv: behave when linked as a module + +The NOP OTG transceiver driver needs to be usable from modules. +Make sure its symbols are always accessible at both compile and +link time, and make sure the device instance is allocated from +the heap so that device lifetime rules are obeyed. + +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/otg/nop-usb-xceiv.c | 25 ++++++++++--------------- + include/linux/usb/otg.h | 4 ++-- + 2 files changed, 12 insertions(+), 17 deletions(-) + +diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c +index 4b933f6..9ed5ea5 100644 +--- a/drivers/usb/otg/nop-usb-xceiv.c ++++ b/drivers/usb/otg/nop-usb-xceiv.c +@@ -22,8 +22,8 @@ + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Current status: +- * this is to add "nop" transceiver for all those phy which is +- * autonomous such as isp1504 etc. ++ * This provides a "nop" transceiver for PHYs which are ++ * autonomous such as isp1504, isp1707, etc. + */ + + #include <linux/module.h> +@@ -36,30 +36,25 @@ struct nop_usb_xceiv { + struct device *dev; + }; + +-static u64 nop_xceiv_dmamask = DMA_32BIT_MASK; +- +-static struct platform_device nop_xceiv_device = { +- .name = "nop_usb_xceiv", +- .id = -1, +- .dev = { +- .dma_mask = &nop_xceiv_dmamask, +- .coherent_dma_mask = DMA_32BIT_MASK, +- .platform_data = NULL, +- }, +-}; ++static struct platform_device *pd; + + void usb_nop_xceiv_register(void) + { +- if (platform_device_register(&nop_xceiv_device) < 0) { ++ if (pd) ++ return; ++ pd = platform_device_register_simple("nop_usb_xceiv", -1, NULL, 0); ++ if (!pd) { + printk(KERN_ERR "Unable to register usb nop transceiver\n"); + return; + } + } ++EXPORT_SYMBOL(usb_nop_xceiv_register); + + void usb_nop_xceiv_unregister(void) + { +- platform_device_unregister(&nop_xceiv_device); ++ platform_device_unregister(pd); + } ++EXPORT_SYMBOL(usb_nop_xceiv_unregister); + + static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x) + { +diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h +index 54f2424..7df8bae 100644 +--- a/include/linux/usb/otg.h ++++ b/include/linux/usb/otg.h +@@ -80,10 +80,10 @@ struct otg_transceiver { + + /* for board-specific init logic */ + extern int otg_set_transceiver(struct otg_transceiver *); +-#ifdef CONFIG_NOP_USB_XCEIV ++ ++/* sometimes transceivers are accessed only through e.g. ULPI */ + extern void usb_nop_xceiv_register(void); + extern void usb_nop_xceiv_unregister(void); +-#endif + + + /* for usb host and peripheral controller drivers */ +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0026-musb-proper-hookup-to-transceiver-drivers.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0026-musb-proper-hookup-to-transceiver-drivers.patch new file mode 100644 index 0000000000..035a6c7676 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0026-musb-proper-hookup-to-transceiver-drivers.patch @@ -0,0 +1,1109 @@ +From 43ee46723ffa9dd43d611362064d235440aa04e7 Mon Sep 17 00:00:00 2001 +From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Date: Tue, 31 Mar 2009 12:30:04 -0700 +Subject: [PATCH] musb: proper hookup to transceiver drivers + +Let the otg_transceiver in MUSB be managed by an external driver; +don't assume it's integrated. OMAP3 chips need it to be external, +and there may be ways to interact with the transceiver which add +functionality to the system. + +Platform init code is responsible for setting up the transeciver, +probably using the NOP transceiver for integrated transceivers. +External ones will use whatever the board init code provided, +such as twl4030 or something more hands-off. + +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/Kconfig | 2 + + drivers/usb/musb/blackfin.c | 11 +++- + drivers/usb/musb/davinci.c | 33 +++++++++----- + drivers/usb/musb/musb_core.c | 96 +++++++++++++++++++++------------------ + drivers/usb/musb/musb_core.h | 2 +- + drivers/usb/musb/musb_gadget.c | 38 +++++++-------- + drivers/usb/musb/musb_host.c | 2 +- + drivers/usb/musb/musb_virthub.c | 20 ++++---- + drivers/usb/musb/omap2430.c | 62 +++++++++---------------- + drivers/usb/musb/tusb6010.c | 70 ++++++++++++++++++----------- + 10 files changed, 181 insertions(+), 155 deletions(-) + +diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig +index 9985db0..9eea991 100644 +--- a/drivers/usb/musb/Kconfig ++++ b/drivers/usb/musb/Kconfig +@@ -10,6 +10,7 @@ comment "Enable Host or Gadget support to see Inventra options" + config USB_MUSB_HDRC + depends on (USB || USB_GADGET) && HAVE_CLK + depends on !SUPERH ++ select NOP_USB_XCEIV if ARCH_DAVINCI + select TWL4030_USB if MACH_OMAP_3430SDP + select USB_OTG_UTILS + tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' +@@ -55,6 +56,7 @@ comment "Blackfin high speed USB Support" + config USB_TUSB6010 + boolean "TUSB 6010 support" + depends on USB_MUSB_HDRC && !USB_MUSB_SOC ++ select NOP_USB_XCEIV + default y + help + The TUSB 6010 chip, from Texas Instruments, connects a discrete +diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c +index 7861348..f2f66eb 100644 +--- a/drivers/usb/musb/blackfin.c ++++ b/drivers/usb/musb/blackfin.c +@@ -143,7 +143,7 @@ static void musb_conn_timer_handler(unsigned long _musb) + u16 val; + + spin_lock_irqsave(&musb->lock, flags); +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_IDLE: + case OTG_STATE_A_WAIT_BCON: + /* Start a new session */ +@@ -154,7 +154,7 @@ static void musb_conn_timer_handler(unsigned long _musb) + val = musb_readw(musb->mregs, MUSB_DEVCTL); + if (!(val & MUSB_DEVCTL_BDEVICE)) { + gpio_set_value(musb->config->gpio_vrsel, 1); +- musb->xceiv.state = OTG_STATE_A_WAIT_BCON; ++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON; + } else { + gpio_set_value(musb->config->gpio_vrsel, 0); + +@@ -247,6 +247,11 @@ int __init musb_platform_init(struct musb *musb) + } + gpio_direction_output(musb->config->gpio_vrsel, 0); + ++ usb_nop_xceiv_register(); ++ musb->xceiv = otg_get_transceiver(); ++ if (!musb->xceiv) ++ return -ENODEV; ++ + if (ANOMALY_05000346) { + bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); + SSYNC(); +@@ -291,7 +296,7 @@ int __init musb_platform_init(struct musb *musb) + musb_conn_timer_handler, (unsigned long) musb); + } + if (is_peripheral_enabled(musb)) +- musb->xceiv.set_power = bfin_set_power; ++ musb->xceiv->set_power = bfin_set_power; + + musb->isr = blackfin_interrupt; + +diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c +index 9fd74bf..81de742 100644 +--- a/drivers/usb/musb/davinci.c ++++ b/drivers/usb/musb/davinci.c +@@ -200,7 +200,7 @@ static void otg_timer(unsigned long _musb) + DBG(7, "poll devctl %02x (%s)\n", devctl, otg_state_string(musb)); + + spin_lock_irqsave(&musb->lock, flags); +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_WAIT_VFALL: + /* Wait till VBUS falls below SessionEnd (~0.2V); the 1.3 RTL + * seems to mis-handle session "start" otherwise (or in our +@@ -211,7 +211,7 @@ static void otg_timer(unsigned long _musb) + mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); + break; + } +- musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; ++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; + musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG, + MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT); + break; +@@ -236,7 +236,7 @@ static void otg_timer(unsigned long _musb) + if (devctl & MUSB_DEVCTL_BDEVICE) + mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); + else +- musb->xceiv.state = OTG_STATE_A_IDLE; ++ musb->xceiv->state = OTG_STATE_A_IDLE; + break; + default: + break; +@@ -310,21 +310,21 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) + * to stop registering in devctl. + */ + musb->int_usb &= ~MUSB_INTR_VBUSERROR; +- musb->xceiv.state = OTG_STATE_A_WAIT_VFALL; ++ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; + mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); + WARNING("VBUS error workaround (delay coming)\n"); + } else if (is_host_enabled(musb) && drvvbus) { + musb->is_active = 1; + MUSB_HST_MODE(musb); +- musb->xceiv.default_a = 1; +- musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; ++ musb->xceiv->default_a = 1; ++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; + portstate(musb->port1_status |= USB_PORT_STAT_POWER); + del_timer(&otg_workaround); + } else { + musb->is_active = 0; + MUSB_DEV_MODE(musb); +- musb->xceiv.default_a = 0; +- musb->xceiv.state = OTG_STATE_B_IDLE; ++ musb->xceiv->default_a = 0; ++ musb->xceiv->state = OTG_STATE_B_IDLE; + portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); + } + +@@ -346,7 +346,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) + + /* poll for ID change */ + if (is_otg_enabled(musb) +- && musb->xceiv.state == OTG_STATE_B_IDLE) ++ && musb->xceiv->state == OTG_STATE_B_IDLE) + mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); + + spin_unlock_irqrestore(&musb->lock, flags); +@@ -365,6 +365,11 @@ int __init musb_platform_init(struct musb *musb) + void __iomem *tibase = musb->ctrl_base; + u32 revision; + ++ usb_nop_xceiv_register(); ++ musb->xceiv = otg_get_transceiver(); ++ if (!musb->xceiv) ++ return -ENODEV; ++ + musb->mregs += DAVINCI_BASE_OFFSET; + + clk_enable(musb->clock); +@@ -372,7 +377,7 @@ int __init musb_platform_init(struct musb *musb) + /* returns zero if e.g. not clocked */ + revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); + if (revision == 0) +- return -ENODEV; ++ goto fail; + + if (is_host_enabled(musb)) + setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); +@@ -396,6 +401,10 @@ int __init musb_platform_init(struct musb *musb) + + musb->isr = davinci_interrupt; + return 0; ++ ++fail: ++ usb_nop_xceiv_unregister(); ++ return -ENODEV; + } + + int musb_platform_exit(struct musb *musb) +@@ -406,7 +415,7 @@ int musb_platform_exit(struct musb *musb) + davinci_source_power(musb, 0 /*off*/, 1); + + /* delay, to avoid problems with module reload */ +- if (is_host_enabled(musb) && musb->xceiv.default_a) { ++ if (is_host_enabled(musb) && musb->xceiv->default_a) { + int maxdelay = 30; + u8 devctl, warn = 0; + +@@ -435,5 +444,7 @@ int musb_platform_exit(struct musb *musb) + + clk_disable(musb->clock); + ++ usb_nop_xceiv_unregister(); ++ + return 0; + } +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index d953305..ac150af 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -267,7 +267,7 @@ void musb_load_testpacket(struct musb *musb) + + const char *otg_state_string(struct musb *musb) + { +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_IDLE: return "a_idle"; + case OTG_STATE_A_WAIT_VRISE: return "a_wait_vrise"; + case OTG_STATE_A_WAIT_BCON: return "a_wait_bcon"; +@@ -302,11 +302,11 @@ void musb_otg_timer_func(unsigned long data) + unsigned long flags; + + spin_lock_irqsave(&musb->lock, flags); +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_B_WAIT_ACON: + DBG(1, "HNP: b_wait_acon timeout; back to b_peripheral\n"); + musb_g_disconnect(musb); +- musb->xceiv.state = OTG_STATE_B_PERIPHERAL; ++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL; + musb->is_active = 0; + break; + case OTG_STATE_A_WAIT_BCON: +@@ -331,20 +331,20 @@ void musb_hnp_stop(struct musb *musb) + void __iomem *mbase = musb->mregs; + u8 reg; + +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_PERIPHERAL: + case OTG_STATE_A_WAIT_VFALL: + case OTG_STATE_A_WAIT_BCON: + DBG(1, "HNP: Switching back to A-host\n"); + musb_g_disconnect(musb); +- musb->xceiv.state = OTG_STATE_A_IDLE; ++ musb->xceiv->state = OTG_STATE_A_IDLE; + MUSB_HST_MODE(musb); + musb->is_active = 0; + break; + case OTG_STATE_B_HOST: + DBG(1, "HNP: Disabling HR\n"); + hcd->self.is_b_host = 0; +- musb->xceiv.state = OTG_STATE_B_PERIPHERAL; ++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL; + MUSB_DEV_MODE(musb); + reg = musb_readb(mbase, MUSB_POWER); + reg |= MUSB_POWER_SUSPENDM; +@@ -402,7 +402,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + + if (devctl & MUSB_DEVCTL_HM) { + #ifdef CONFIG_USB_MUSB_HDRC_HCD +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_SUSPEND: + /* remote wakeup? later, GetPortStatus + * will stop RESUME signaling +@@ -425,12 +425,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + musb->rh_timer = jiffies + + msecs_to_jiffies(20); + +- musb->xceiv.state = OTG_STATE_A_HOST; ++ musb->xceiv->state = OTG_STATE_A_HOST; + musb->is_active = 1; + usb_hcd_resume_root_hub(musb_to_hcd(musb)); + break; + case OTG_STATE_B_WAIT_ACON: +- musb->xceiv.state = OTG_STATE_B_PERIPHERAL; ++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL; + musb->is_active = 1; + MUSB_DEV_MODE(musb); + break; +@@ -441,11 +441,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + } + #endif + } else { +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + #ifdef CONFIG_USB_MUSB_HDRC_HCD + case OTG_STATE_A_SUSPEND: + /* possibly DISCONNECT is upcoming */ +- musb->xceiv.state = OTG_STATE_A_HOST; ++ musb->xceiv->state = OTG_STATE_A_HOST; + usb_hcd_resume_root_hub(musb_to_hcd(musb)); + break; + #endif +@@ -490,7 +490,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + */ + musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); + musb->ep0_stage = MUSB_EP0_START; +- musb->xceiv.state = OTG_STATE_A_IDLE; ++ musb->xceiv->state = OTG_STATE_A_IDLE; + MUSB_HST_MODE(musb); + musb_set_vbus(musb, 1); + +@@ -516,7 +516,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + * REVISIT: do delays from lots of DEBUG_KERNEL checks + * make trouble here, keeping VBUS < 4.4V ? + */ +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_HOST: + /* recovery is dicey once we've gotten past the + * initial stages of enumeration, but if VBUS +@@ -602,11 +602,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + MUSB_HST_MODE(musb); + + /* indicate new connection to OTG machine */ +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_B_PERIPHERAL: + if (int_usb & MUSB_INTR_SUSPEND) { + DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n"); +- musb->xceiv.state = OTG_STATE_B_HOST; ++ musb->xceiv->state = OTG_STATE_B_HOST; + hcd->self.is_b_host = 1; + int_usb &= ~MUSB_INTR_SUSPEND; + } else +@@ -614,13 +614,13 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + break; + case OTG_STATE_B_WAIT_ACON: + DBG(1, "HNP: Waiting to switch to b_host state\n"); +- musb->xceiv.state = OTG_STATE_B_HOST; ++ musb->xceiv->state = OTG_STATE_B_HOST; + hcd->self.is_b_host = 1; + break; + default: + if ((devctl & MUSB_DEVCTL_VBUS) + == (3 << MUSB_DEVCTL_VBUS_SHIFT)) { +- musb->xceiv.state = OTG_STATE_A_HOST; ++ musb->xceiv->state = OTG_STATE_A_HOST; + hcd->self.is_b_host = 0; + } + break; +@@ -650,7 +650,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + } + } else if (is_peripheral_capable()) { + DBG(1, "BUS RESET as %s\n", otg_state_string(musb)); +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + #ifdef CONFIG_USB_OTG + case OTG_STATE_A_SUSPEND: + /* We need to ignore disconnect on suspend +@@ -673,12 +673,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + case OTG_STATE_B_WAIT_ACON: + DBG(1, "HNP: RESET (%s), to b_peripheral\n", + otg_state_string(musb)); +- musb->xceiv.state = OTG_STATE_B_PERIPHERAL; ++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL; + musb_g_reset(musb); + break; + #endif + case OTG_STATE_B_IDLE: +- musb->xceiv.state = OTG_STATE_B_PERIPHERAL; ++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL; + /* FALLTHROUGH */ + case OTG_STATE_B_PERIPHERAL: + musb_g_reset(musb); +@@ -763,7 +763,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, + MUSB_MODE(musb), devctl); + handled = IRQ_HANDLED; + +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + #ifdef CONFIG_USB_MUSB_HDRC_HCD + case OTG_STATE_A_HOST: + case OTG_STATE_A_SUSPEND: +@@ -805,7 +805,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, + otg_state_string(musb), devctl, power); + handled = IRQ_HANDLED; + +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + #ifdef CONFIG_USB_MUSB_OTG + case OTG_STATE_A_PERIPHERAL: + /* +@@ -817,10 +817,10 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, + case OTG_STATE_B_PERIPHERAL: + musb_g_suspend(musb); + musb->is_active = is_otg_enabled(musb) +- && musb->xceiv.gadget->b_hnp_enable; ++ && musb->xceiv->gadget->b_hnp_enable; + if (musb->is_active) { + #ifdef CONFIG_USB_MUSB_OTG +- musb->xceiv.state = OTG_STATE_B_WAIT_ACON; ++ musb->xceiv->state = OTG_STATE_B_WAIT_ACON; + DBG(1, "HNP: Setting timer for b_ase0_brst\n"); + musb_otg_timer.data = (unsigned long)musb; + mod_timer(&musb_otg_timer, jiffies +@@ -834,9 +834,9 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, + + msecs_to_jiffies(musb->a_wait_bcon)); + break; + case OTG_STATE_A_HOST: +- musb->xceiv.state = OTG_STATE_A_SUSPEND; ++ musb->xceiv->state = OTG_STATE_A_SUSPEND; + musb->is_active = is_otg_enabled(musb) +- && musb->xceiv.host->b_hnp_enable; ++ && musb->xceiv->host->b_hnp_enable; + break; + case OTG_STATE_B_HOST: + /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ +@@ -1681,7 +1681,7 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr, + + spin_lock_irqsave(&musb->lock, flags); + musb->a_wait_bcon = val; +- if (musb->xceiv.state == OTG_STATE_A_WAIT_BCON) ++ if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON) + musb->is_active = 0; + musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val)); + spin_unlock_irqrestore(&musb->lock, flags); +@@ -1742,8 +1742,8 @@ static void musb_irq_work(struct work_struct *data) + struct musb *musb = container_of(data, struct musb, irq_work); + static int old_state; + +- if (musb->xceiv.state != old_state) { +- old_state = musb->xceiv.state; ++ if (musb->xceiv->state != old_state) { ++ old_state = musb->xceiv->state; + sysfs_notify(&musb->controller->kobj, NULL, "mode"); + } + } +@@ -1840,7 +1840,7 @@ static void musb_free(struct musb *musb) + } + + #ifdef CONFIG_USB_MUSB_OTG +- put_device(musb->xceiv.dev); ++ put_device(musb->xceiv->dev); + #endif + + #ifdef CONFIG_USB_MUSB_HDRC_HCD +@@ -1921,10 +1921,18 @@ bad_config: + } + } + +- /* assume vbus is off */ +- +- /* platform adjusts musb->mregs and musb->isr if needed, +- * and activates clocks ++ /* The musb_platform_init() call: ++ * - adjusts musb->mregs and musb->isr if needed, ++ * - may initialize an integrated tranceiver ++ * - initializes musb->xceiv, usually by otg_get_transceiver() ++ * - activates clocks. ++ * - stops powering VBUS ++ * - assigns musb->board_set_vbus if host mode is enabled ++ * ++ * There are various transciever configurations. Blackfin, ++ * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses ++ * external/discrete ones in various flavors (twl4030 family, ++ * isp1504, non-OTG, etc) mostly hooking up through ULPI. + */ + musb->isr = generic_interrupt; + status = musb_platform_init(musb); +@@ -1992,17 +2000,17 @@ bad_config: + ? "DMA" : "PIO", + musb->nIrq); + +-#ifdef CONFIG_USB_MUSB_HDRC_HCD +- /* host side needs more setup, except for no-host modes */ +- if (musb->board_mode != MUSB_PERIPHERAL) { ++ /* host side needs more setup */ ++ if (is_host_enabled(musb)) { + struct usb_hcd *hcd = musb_to_hcd(musb); + +- if (musb->board_mode == MUSB_OTG) ++ otg_set_host(musb->xceiv, &hcd->self); ++ ++ if (is_otg_enabled(musb)) + hcd->self.otg_port = 1; +- musb->xceiv.host = &hcd->self; ++ musb->xceiv->host = &hcd->self; + hcd->power_budget = 2 * (plat->power ? : 250); + } +-#endif /* CONFIG_USB_MUSB_HDRC_HCD */ + + /* For the host-only role, we can activate right away. + * (We expect the ID pin to be forcibly grounded!!) +@@ -2010,8 +2018,8 @@ bad_config: + */ + if (!is_otg_enabled(musb) && is_host_enabled(musb)) { + MUSB_HST_MODE(musb); +- musb->xceiv.default_a = 1; +- musb->xceiv.state = OTG_STATE_A_IDLE; ++ musb->xceiv->default_a = 1; ++ musb->xceiv->state = OTG_STATE_A_IDLE; + + status = usb_add_hcd(musb_to_hcd(musb), -1, 0); + if (status) +@@ -2026,8 +2034,8 @@ bad_config: + + } else /* peripheral is enabled */ { + MUSB_DEV_MODE(musb); +- musb->xceiv.default_a = 0; +- musb->xceiv.state = OTG_STATE_B_IDLE; ++ musb->xceiv->default_a = 0; ++ musb->xceiv->state = OTG_STATE_B_IDLE; + + status = musb_gadget_setup(musb); + if (status) +diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h +index 0ac4faf..c3ee348 100644 +--- a/drivers/usb/musb/musb_core.h ++++ b/drivers/usb/musb/musb_core.h +@@ -356,7 +356,7 @@ struct musb { + u16 int_rx; + u16 int_tx; + +- struct otg_transceiver xceiv; ++ struct otg_transceiver *xceiv; + + int nIrq; + unsigned irq_wake:1; +diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c +index e8f920c..2fbfba5 100644 +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -1406,7 +1406,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget) + + spin_lock_irqsave(&musb->lock, flags); + +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_B_PERIPHERAL: + /* NOTE: OTG state machine doesn't include B_SUSPENDED; + * that's part of the standard usb 1.1 state machine, and +@@ -1508,9 +1508,9 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) + { + struct musb *musb = gadget_to_musb(gadget); + +- if (!musb->xceiv.set_power) ++ if (!musb->xceiv->set_power) + return -EOPNOTSUPP; +- return otg_set_power(&musb->xceiv, mA); ++ return otg_set_power(musb->xceiv, mA); + } + + static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on) +@@ -1733,11 +1733,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) + + spin_lock_irqsave(&musb->lock, flags); + +- /* REVISIT always use otg_set_peripheral(), handling +- * issues including the root hub one below ... +- */ +- musb->xceiv.gadget = &musb->g; +- musb->xceiv.state = OTG_STATE_B_IDLE; ++ otg_set_peripheral(musb->xceiv, &musb->g); + musb->is_active = 1; + + /* FIXME this ignores the softconnect flag. Drivers are +@@ -1749,6 +1745,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) + if (!is_otg_enabled(musb)) + musb_start(musb); + ++ otg_set_peripheral(musb->xceiv, &musb->g); ++ + spin_unlock_irqrestore(&musb->lock, flags); + + if (is_otg_enabled(musb)) { +@@ -1762,8 +1760,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) + if (retval < 0) { + DBG(1, "add_hcd failed, %d\n", retval); + spin_lock_irqsave(&musb->lock, flags); +- musb->xceiv.gadget = NULL; +- musb->xceiv.state = OTG_STATE_UNDEFINED; ++ otg_set_peripheral(musb->xceiv, NULL); + musb->gadget_driver = NULL; + musb->g.dev.driver = NULL; + spin_unlock_irqrestore(&musb->lock, flags); +@@ -1846,8 +1843,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) + + (void) musb_gadget_vbus_draw(&musb->g, 0); + +- musb->xceiv.state = OTG_STATE_UNDEFINED; ++ musb->xceiv->state = OTG_STATE_UNDEFINED; + stop_activity(musb, driver); ++ otg_set_peripheral(musb->xceiv, NULL); + + DBG(3, "unregistering driver %s\n", driver->function); + spin_unlock_irqrestore(&musb->lock, flags); +@@ -1883,7 +1881,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver); + void musb_g_resume(struct musb *musb) + { + musb->is_suspended = 0; +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_B_IDLE: + break; + case OTG_STATE_B_WAIT_ACON: +@@ -1909,10 +1907,10 @@ void musb_g_suspend(struct musb *musb) + devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + DBG(3, "devctl %02x\n", devctl); + +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_B_IDLE: + if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) +- musb->xceiv.state = OTG_STATE_B_PERIPHERAL; ++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL; + break; + case OTG_STATE_B_PERIPHERAL: + musb->is_suspended = 1; +@@ -1958,22 +1956,22 @@ void musb_g_disconnect(struct musb *musb) + spin_lock(&musb->lock); + } + +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + default: + #ifdef CONFIG_USB_MUSB_OTG + DBG(2, "Unhandled disconnect %s, setting a_idle\n", + otg_state_string(musb)); +- musb->xceiv.state = OTG_STATE_A_IDLE; ++ musb->xceiv->state = OTG_STATE_A_IDLE; + break; + case OTG_STATE_A_PERIPHERAL: +- musb->xceiv.state = OTG_STATE_A_WAIT_VFALL; ++ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; + break; + case OTG_STATE_B_WAIT_ACON: + case OTG_STATE_B_HOST: + #endif + case OTG_STATE_B_PERIPHERAL: + case OTG_STATE_B_IDLE: +- musb->xceiv.state = OTG_STATE_B_IDLE; ++ musb->xceiv->state = OTG_STATE_B_IDLE; + break; + case OTG_STATE_B_SRP_INIT: + break; +@@ -2029,10 +2027,10 @@ __acquires(musb->lock) + * or else after HNP, as A-Device + */ + if (devctl & MUSB_DEVCTL_BDEVICE) { +- musb->xceiv.state = OTG_STATE_B_PERIPHERAL; ++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL; + musb->g.is_a_peripheral = 0; + } else if (is_otg_enabled(musb)) { +- musb->xceiv.state = OTG_STATE_A_PERIPHERAL; ++ musb->xceiv->state = OTG_STATE_A_PERIPHERAL; + musb->g.is_a_peripheral = 1; + } else + WARN_ON(1); +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index ece5122..795dabe 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -2169,7 +2169,7 @@ static int musb_bus_suspend(struct usb_hcd *hcd) + { + struct musb *musb = hcd_to_musb(hcd); + +- if (musb->xceiv.state == OTG_STATE_A_SUSPEND) ++ if (musb->xceiv->state == OTG_STATE_A_SUSPEND) + return 0; + + if (is_host_active(musb) && musb->is_active) { +diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c +index e0e9ce5..7e7900f 100644 +--- a/drivers/usb/musb/musb_virthub.c ++++ b/drivers/usb/musb/musb_virthub.c +@@ -78,18 +78,18 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) + DBG(3, "Root port suspended, power %02x\n", power); + + musb->port1_status |= USB_PORT_STAT_SUSPEND; +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_HOST: +- musb->xceiv.state = OTG_STATE_A_SUSPEND; ++ musb->xceiv->state = OTG_STATE_A_SUSPEND; + musb->is_active = is_otg_enabled(musb) +- && musb->xceiv.host->b_hnp_enable; ++ && musb->xceiv->host->b_hnp_enable; + musb_platform_try_idle(musb, 0); + break; + #ifdef CONFIG_USB_MUSB_OTG + case OTG_STATE_B_HOST: +- musb->xceiv.state = OTG_STATE_B_WAIT_ACON; ++ musb->xceiv->state = OTG_STATE_B_WAIT_ACON; + musb->is_active = is_otg_enabled(musb) +- && musb->xceiv.host->b_hnp_enable; ++ && musb->xceiv->host->b_hnp_enable; + musb_platform_try_idle(musb, 0); + break; + #endif +@@ -116,7 +116,7 @@ static void musb_port_reset(struct musb *musb, bool do_reset) + void __iomem *mbase = musb->mregs; + + #ifdef CONFIG_USB_MUSB_OTG +- if (musb->xceiv.state == OTG_STATE_B_IDLE) { ++ if (musb->xceiv->state == OTG_STATE_B_IDLE) { + DBG(2, "HNP: Returning from HNP; no hub reset from b_idle\n"); + musb->port1_status &= ~USB_PORT_STAT_RESET; + return; +@@ -186,14 +186,14 @@ void musb_root_disconnect(struct musb *musb) + usb_hcd_poll_rh_status(musb_to_hcd(musb)); + musb->is_active = 0; + +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_HOST: + case OTG_STATE_A_SUSPEND: +- musb->xceiv.state = OTG_STATE_A_WAIT_BCON; ++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON; + musb->is_active = 0; + break; + case OTG_STATE_A_WAIT_VFALL: +- musb->xceiv.state = OTG_STATE_B_IDLE; ++ musb->xceiv->state = OTG_STATE_B_IDLE; + break; + default: + DBG(1, "host disconnect (%s)\n", otg_state_string(musb)); +@@ -332,7 +332,7 @@ int musb_hub_control( + musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; + usb_hcd_poll_rh_status(musb_to_hcd(musb)); + /* NOTE: it might really be A_WAIT_BCON ... */ +- musb->xceiv.state = OTG_STATE_A_HOST; ++ musb->xceiv->state = OTG_STATE_A_HOST; + } + + put_unaligned(cpu_to_le32(musb->port1_status +diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c +index 901dffd..5f67b03 100644 +--- a/drivers/usb/musb/omap2430.c ++++ b/drivers/usb/musb/omap2430.c +@@ -62,17 +62,17 @@ static void musb_do_idle(unsigned long _musb) + + devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_WAIT_BCON: + devctl &= ~MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + + devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + if (devctl & MUSB_DEVCTL_BDEVICE) { +- musb->xceiv.state = OTG_STATE_B_IDLE; ++ musb->xceiv->state = OTG_STATE_B_IDLE; + MUSB_DEV_MODE(musb); + } else { +- musb->xceiv.state = OTG_STATE_A_IDLE; ++ musb->xceiv->state = OTG_STATE_A_IDLE; + MUSB_HST_MODE(musb); + } + break; +@@ -90,7 +90,7 @@ static void musb_do_idle(unsigned long _musb) + musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; + usb_hcd_poll_rh_status(musb_to_hcd(musb)); + /* NOTE: it might really be A_WAIT_BCON ... */ +- musb->xceiv.state = OTG_STATE_A_HOST; ++ musb->xceiv->state = OTG_STATE_A_HOST; + } + break; + #endif +@@ -98,9 +98,9 @@ static void musb_do_idle(unsigned long _musb) + case OTG_STATE_A_HOST: + devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + if (devctl & MUSB_DEVCTL_BDEVICE) +- musb->xceiv.state = OTG_STATE_B_IDLE; ++ musb->xceiv->state = OTG_STATE_B_IDLE; + else +- musb->xceiv.state = OTG_STATE_A_WAIT_BCON; ++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON; + #endif + default: + break; +@@ -119,7 +119,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) + + /* Never idle if active, or when VBUS timeout is not set as host */ + if (musb->is_active || ((musb->a_wait_bcon == 0) +- && (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) { ++ && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { + DBG(4, "%s active, deleting timer\n", otg_state_string(musb)); + del_timer(&musb_idle_timer); + last_timer = jiffies; +@@ -164,8 +164,8 @@ static void omap_set_vbus(struct musb *musb, int is_on) + + if (is_on) { + musb->is_active = 1; +- musb->xceiv.default_a = 1; +- musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; ++ musb->xceiv->default_a = 1; ++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; + devctl |= MUSB_DEVCTL_SESSION; + + MUSB_HST_MODE(musb); +@@ -176,8 +176,8 @@ static void omap_set_vbus(struct musb *musb, int is_on) + * jumping right to B_IDLE... + */ + +- musb->xceiv.default_a = 0; +- musb->xceiv.state = OTG_STATE_B_IDLE; ++ musb->xceiv->default_a = 0; ++ musb->xceiv->state = OTG_STATE_B_IDLE; + devctl &= ~MUSB_DEVCTL_SESSION; + + MUSB_DEV_MODE(musb); +@@ -189,10 +189,6 @@ static void omap_set_vbus(struct musb *musb, int is_on) + otg_state_string(musb), + musb_readb(musb->mregs, MUSB_DEVCTL)); + } +-static int omap_set_power(struct otg_transceiver *x, unsigned mA) +-{ +- return 0; +-} + + static int musb_platform_resume(struct musb *musb); + +@@ -203,24 +199,6 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode) + devctl |= MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + +- switch (musb_mode) { +-#ifdef CONFIG_USB_MUSB_HDRC_HCD +- case MUSB_HOST: +- otg_set_host(&musb->xceiv, musb->xceiv.host); +- break; +-#endif +-#ifdef CONFIG_USB_GADGET_MUSB_HDRC +- case MUSB_PERIPHERAL: +- otg_set_peripheral(&musb->xceiv, musb->xceiv.gadget); +- break; +-#endif +-#ifdef CONFIG_USB_MUSB_OTG +- case MUSB_OTG: +- break; +-#endif +- default: +- return -EINVAL; +- } + return 0; + } + +@@ -232,6 +210,16 @@ int __init musb_platform_init(struct musb *musb) + omap_cfg_reg(AE5_2430_USB0HS_STP); + #endif + ++ /* We require some kind of external transceiver, hooked ++ * up through ULPI. TWL4030-family PMICs include one, ++ * which needs a driver, drivers aren't always needed. ++ */ ++ musb->xceiv = otg_get_transceiver(); ++ if (!musb->xceiv) { ++ pr_err("HS USB OTG: no transceiver configured\n"); ++ return -ENODEV; ++ } ++ + musb_platform_resume(musb); + + l = omap_readl(OTG_SYSCONFIG); +@@ -258,8 +246,6 @@ int __init musb_platform_init(struct musb *musb) + + if (is_host_enabled(musb)) + musb->board_set_vbus = omap_set_vbus; +- if (is_peripheral_enabled(musb)) +- musb->xceiv.set_power = omap_set_power; + musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON; + + setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); +@@ -283,8 +269,7 @@ int musb_platform_suspend(struct musb *musb) + l |= ENABLEWAKEUP; /* enable wakeup */ + omap_writel(l, OTG_SYSCONFIG); + +- if (musb->xceiv.set_suspend) +- musb->xceiv.set_suspend(&musb->xceiv, 1); ++ otg_set_suspend(musb->xceiv, 1); + + if (musb->set_clock) + musb->set_clock(musb->clock, 0); +@@ -301,8 +286,7 @@ static int musb_platform_resume(struct musb *musb) + if (!musb->clock) + return 0; + +- if (musb->xceiv.set_suspend) +- musb->xceiv.set_suspend(&musb->xceiv, 0); ++ otg_set_suspend(musb->xceiv, 0); + + if (musb->set_clock) + musb->set_clock(musb->clock, 1); +diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c +index 9e20fd0..c473dec 100644 +--- a/drivers/usb/musb/tusb6010.c ++++ b/drivers/usb/musb/tusb6010.c +@@ -260,6 +260,8 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf) + tusb_fifo_read_unaligned(fifo, buf, len); + } + ++static struct musb *the_musb; ++ + #ifdef CONFIG_USB_GADGET_MUSB_HDRC + + /* This is used by gadget drivers, and OTG transceiver logic, allowing +@@ -270,7 +272,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf) + */ + static int tusb_draw_power(struct otg_transceiver *x, unsigned mA) + { +- struct musb *musb = container_of(x, struct musb, xceiv); ++ struct musb *musb = the_musb; + void __iomem *tbase = musb->ctrl_base; + u32 reg; + +@@ -420,7 +422,7 @@ static void musb_do_idle(unsigned long _musb) + + spin_lock_irqsave(&musb->lock, flags); + +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_WAIT_BCON: + if ((musb->a_wait_bcon != 0) + && (musb->idle_timeout == 0 +@@ -484,7 +486,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) + + /* Never idle if active, or when VBUS timeout is not set as host */ + if (musb->is_active || ((musb->a_wait_bcon == 0) +- && (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) { ++ && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { + DBG(4, "%s active, deleting timer\n", otg_state_string(musb)); + del_timer(&musb_idle_timer); + last_timer = jiffies; +@@ -533,8 +535,8 @@ static void tusb_source_power(struct musb *musb, int is_on) + if (musb->set_clock) + musb->set_clock(musb->clock, 1); + timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE); +- musb->xceiv.default_a = 1; +- musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; ++ musb->xceiv->default_a = 1; ++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; + devctl |= MUSB_DEVCTL_SESSION; + + conf |= TUSB_DEV_CONF_USB_HOST_MODE; +@@ -547,24 +549,24 @@ static void tusb_source_power(struct musb *musb, int is_on) + /* If ID pin is grounded, we want to be a_idle */ + otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); + if (!(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) { +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_WAIT_VRISE: + case OTG_STATE_A_WAIT_BCON: +- musb->xceiv.state = OTG_STATE_A_WAIT_VFALL; ++ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; + break; + case OTG_STATE_A_WAIT_VFALL: +- musb->xceiv.state = OTG_STATE_A_IDLE; ++ musb->xceiv->state = OTG_STATE_A_IDLE; + break; + default: +- musb->xceiv.state = OTG_STATE_A_IDLE; ++ musb->xceiv->state = OTG_STATE_A_IDLE; + } + musb->is_active = 0; +- musb->xceiv.default_a = 1; ++ musb->xceiv->default_a = 1; + MUSB_HST_MODE(musb); + } else { + musb->is_active = 0; +- musb->xceiv.default_a = 0; +- musb->xceiv.state = OTG_STATE_B_IDLE; ++ musb->xceiv->default_a = 0; ++ musb->xceiv->state = OTG_STATE_B_IDLE; + MUSB_DEV_MODE(musb); + } + +@@ -675,7 +677,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) + else + default_a = is_host_enabled(musb); + DBG(2, "Default-%c\n", default_a ? 'A' : 'B'); +- musb->xceiv.default_a = default_a; ++ musb->xceiv->default_a = default_a; + tusb_source_power(musb, default_a); + + /* Don't allow idling immediately */ +@@ -687,7 +689,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) + if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) { + + /* B-dev state machine: no vbus ~= disconnect */ +- if ((is_otg_enabled(musb) && !musb->xceiv.default_a) ++ if ((is_otg_enabled(musb) && !musb->xceiv->default_a) + || !is_host_enabled(musb)) { + #ifdef CONFIG_USB_MUSB_HDRC_HCD + /* ? musb_root_disconnect(musb); */ +@@ -702,9 +704,9 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) + + if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) { + DBG(1, "Forcing disconnect (no interrupt)\n"); +- if (musb->xceiv.state != OTG_STATE_B_IDLE) { ++ if (musb->xceiv->state != OTG_STATE_B_IDLE) { + /* INTR_DISCONNECT can hide... */ +- musb->xceiv.state = OTG_STATE_B_IDLE; ++ musb->xceiv->state = OTG_STATE_B_IDLE; + musb->int_usb |= MUSB_INTR_DISCONNECT; + } + musb->is_active = 0; +@@ -718,7 +720,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) + DBG(2, "vbus change, %s, otg %03x\n", + otg_state_string(musb), otg_stat); + +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_IDLE: + DBG(2, "Got SRP, turning on VBUS\n"); + musb_set_vbus(musb, 1); +@@ -766,7 +768,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) + + DBG(4, "%s timer, %03x\n", otg_state_string(musb), otg_stat); + +- switch (musb->xceiv.state) { ++ switch (musb->xceiv->state) { + case OTG_STATE_A_WAIT_VRISE: + /* VBUS has probably been valid for a while now, + * but may well have bounced out of range a bit +@@ -778,7 +780,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) + DBG(2, "devctl %02x\n", devctl); + break; + } +- musb->xceiv.state = OTG_STATE_A_WAIT_BCON; ++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON; + musb->is_active = 0; + idle_timeout = jiffies + + msecs_to_jiffies(musb->a_wait_bcon); +@@ -1094,9 +1096,14 @@ int __init musb_platform_init(struct musb *musb) + { + struct platform_device *pdev; + struct resource *mem; +- void __iomem *sync; ++ void __iomem *sync = NULL; + int ret; + ++ usb_nop_xceiv_register(); ++ musb->xceiv = otg_get_transceiver(); ++ if (!musb->xceiv) ++ return -ENODEV; ++ + pdev = to_platform_device(musb->controller); + + /* dma address for async dma */ +@@ -1107,14 +1114,16 @@ int __init musb_platform_init(struct musb *musb) + mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!mem) { + pr_debug("no sync dma resource?\n"); +- return -ENODEV; ++ ret = -ENODEV; ++ goto done; + } + musb->sync = mem->start; + + sync = ioremap(mem->start, mem->end - mem->start + 1); + if (!sync) { + pr_debug("ioremap for sync failed\n"); +- return -ENOMEM; ++ ret = -ENOMEM; ++ goto done; + } + musb->sync_va = sync; + +@@ -1127,28 +1136,37 @@ int __init musb_platform_init(struct musb *musb) + if (ret) { + printk(KERN_ERR "Could not start tusb6010 (%d)\n", + ret); +- return -ENODEV; ++ goto done; + } + musb->isr = tusb_interrupt; + + if (is_host_enabled(musb)) + musb->board_set_vbus = tusb_source_power; +- if (is_peripheral_enabled(musb)) +- musb->xceiv.set_power = tusb_draw_power; ++ if (is_peripheral_enabled(musb)) { ++ musb->xceiv->set_power = tusb_draw_power; ++ the_musb = musb; ++ } + + setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); + ++done: ++ if (ret < 0) { ++ if (sync) ++ iounmap(sync); ++ usb_nop_xceiv_unregister(); ++ } + return ret; + } + + int musb_platform_exit(struct musb *musb) + { + del_timer_sync(&musb_idle_timer); ++ the_musb = NULL; + + if (musb->board_set_power) + musb->board_set_power(0); + + iounmap(musb->sync_va); +- ++ usb_nop_xceiv_unregister(); + return 0; + } +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0027-musb-otg-timer-cleanup.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0027-musb-otg-timer-cleanup.patch new file mode 100644 index 0000000000..f41b766cfe --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0027-musb-otg-timer-cleanup.patch @@ -0,0 +1,198 @@ +From b4b8c1e7604784b9877f07400ff2a718118ef05c Mon Sep 17 00:00:00 2001 +From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Date: Tue, 31 Mar 2009 12:32:12 -0700 +Subject: [PATCH] musb: otg timer cleanup + +Minor cleanup of OTG timer handling: + * unify decls for OTG time constants, in the core header + * set up and use that timer in a more normal way + * move to the driver struct, so it's usable outside core + +And tighten use and setup of T(a_wait_bcon) so that if it's used, +it's always valid. (If that timer expires, the A-device will +stop powering VBUS. For non-OTG systems, that will be a surprise.) +No behavioral changes, other than more consistency when applying +that core HNP timeout. + +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_core.c | 41 ++++++++++++++++++++++------------------- + drivers/usb/musb/musb_core.h | 14 +++++++++++--- + drivers/usb/musb/omap2430.c | 2 -- + 3 files changed, 33 insertions(+), 24 deletions(-) + +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index ac150af..05c5dd3 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -112,6 +112,7 @@ + #include "davinci.h" + #endif + ++#define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON) + + + unsigned musb_debug; +@@ -288,12 +289,6 @@ const char *otg_state_string(struct musb *musb) + #ifdef CONFIG_USB_MUSB_OTG + + /* +- * See also USB_OTG_1-3.pdf 6.6.5 Timers +- * REVISIT: Are the other timers done in the hardware? +- */ +-#define TB_ASE0_BRST 100 /* Min 3.125 ms */ +- +-/* + * Handles OTG hnp timeouts, such as b_ase0_brst + */ + void musb_otg_timer_func(unsigned long data) +@@ -320,10 +315,8 @@ void musb_otg_timer_func(unsigned long data) + spin_unlock_irqrestore(&musb->lock, flags); + } + +-static DEFINE_TIMER(musb_otg_timer, musb_otg_timer_func, 0, 0); +- + /* +- * Stops the B-device HNP state. Caller must take care of locking. ++ * Stops the HNP transition. Caller must take care of locking. + */ + void musb_hnp_stop(struct musb *musb) + { +@@ -661,11 +654,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + musb_g_reset(musb); + /* FALLTHROUGH */ + case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ +- DBG(1, "HNP: Setting timer as %s\n", +- otg_state_string(musb)); +- musb_otg_timer.data = (unsigned long)musb; +- mod_timer(&musb_otg_timer, jiffies +- + msecs_to_jiffies(100)); ++ /* never use invalid T(a_wait_bcon) */ ++ DBG(1, "HNP: in %s, %d msec timeout\n", ++ otg_state_string(musb), ++ TA_WAIT_BCON(musb)); ++ mod_timer(&musb->otg_timer, jiffies ++ + msecs_to_jiffies(TA_WAIT_BCON(musb))); + break; + case OTG_STATE_A_PERIPHERAL: + musb_hnp_stop(musb); +@@ -822,9 +816,9 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, + #ifdef CONFIG_USB_MUSB_OTG + musb->xceiv->state = OTG_STATE_B_WAIT_ACON; + DBG(1, "HNP: Setting timer for b_ase0_brst\n"); +- musb_otg_timer.data = (unsigned long)musb; +- mod_timer(&musb_otg_timer, jiffies +- + msecs_to_jiffies(TB_ASE0_BRST)); ++ mod_timer(&musb->otg_timer, jiffies ++ + msecs_to_jiffies( ++ OTG_TIME_B_ASE0_BRST)); + #endif + } + break; +@@ -1680,7 +1674,8 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr, + } + + spin_lock_irqsave(&musb->lock, flags); +- musb->a_wait_bcon = val; ++ /* force T(a_wait_bcon) to be zero/unlimited *OR* valid */ ++ musb->a_wait_bcon = val ? max_t(int, val, OTG_TIME_A_WAIT_BCON) : 0 ; + if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON) + musb->is_active = 0; + musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val)); +@@ -1699,10 +1694,13 @@ musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf) + + spin_lock_irqsave(&musb->lock, flags); + val = musb->a_wait_bcon; ++ /* FIXME get_vbus_status() is normally #defined as false... ++ * and is effectively TUSB-specific. ++ */ + vbus = musb_platform_get_vbus_status(musb); + spin_unlock_irqrestore(&musb->lock, flags); + +- return sprintf(buf, "Vbus %s, timeout %lu\n", ++ return sprintf(buf, "Vbus %s, timeout %lu msec\n", + vbus ? "on" : "off", val); + } + static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store); +@@ -1775,6 +1773,7 @@ allocate_instance(struct device *dev, + hcd->uses_new_polling = 1; + + musb->vbuserr_retry = VBUSERR_RETRY_COUNT; ++ musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON; + #else + musb = kzalloc(sizeof *musb, GFP_KERNEL); + if (!musb) +@@ -1969,6 +1968,10 @@ bad_config: + if (status < 0) + goto fail2; + ++#ifdef CONFIG_USB_OTG ++ setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb); ++#endif ++ + /* Init IRQ workqueue before request_irq */ + INIT_WORK(&musb->irq_work, musb_irq_work); + +diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h +index c3ee348..cf3ccb0 100644 +--- a/drivers/usb/musb/musb_core.h ++++ b/drivers/usb/musb/musb_core.h +@@ -40,6 +40,7 @@ + #include <linux/interrupt.h> + #include <linux/smp_lock.h> + #include <linux/errno.h> ++#include <linux/timer.h> + #include <linux/clk.h> + #include <linux/device.h> + #include <linux/usb/ch9.h> +@@ -180,10 +181,15 @@ enum musb_g_ep0_state { + MUSB_EP0_STAGE_ACKWAIT, /* after zlp, before statusin */ + } __attribute__ ((packed)); + +-/* OTG protocol constants */ ++/* ++ * OTG protocol constants. See USB OTG 1.3 spec, ++ * sections 5.5 "Device Timings" and 6.6.5 "Timers". ++ */ + #define OTG_TIME_A_WAIT_VRISE 100 /* msec (max) */ +-#define OTG_TIME_A_WAIT_BCON 0 /* 0=infinite; min 1000 msec */ +-#define OTG_TIME_A_IDLE_BDIS 200 /* msec (min) */ ++#define OTG_TIME_A_WAIT_BCON 1100 /* min 1 second */ ++#define OTG_TIME_A_AIDL_BDIS 200 /* min 200 msec */ ++#define OTG_TIME_B_ASE0_BRST 100 /* min 3.125 ms */ ++ + + /*************************** REGISTER ACCESS ********************************/ + +@@ -332,6 +338,8 @@ struct musb { + struct list_head control; /* of musb_qh */ + struct list_head in_bulk; /* of musb_qh */ + struct list_head out_bulk; /* of musb_qh */ ++ ++ struct timer_list otg_timer; + #endif + + /* called with IRQs blocked; ON/nonzero implies starting a session, +diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c +index 5f67b03..3fbc807 100644 +--- a/drivers/usb/musb/omap2430.c ++++ b/drivers/usb/musb/omap2430.c +@@ -45,7 +45,6 @@ + #define get_cpu_rev() 2 + #endif + +-#define MUSB_TIMEOUT_A_WAIT_BCON 1100 + + static struct timer_list musb_idle_timer; + +@@ -246,7 +245,6 @@ int __init musb_platform_init(struct musb *musb) + + if (is_host_enabled(musb)) + musb->board_set_vbus = omap_set_vbus; +- musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON; + + setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); + +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch new file mode 100644 index 0000000000..6269016223 --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch @@ -0,0 +1,133 @@ +From a637c5056ef52fbb7c41eb7537a9ec3d150231ad Mon Sep 17 00:00:00 2001 +From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Date: Thu, 2 Apr 2009 10:16:11 -0700 +Subject: [PATCH] musb: make initial HNP roleswitch work (v2) + +Minor HNP bugfixes, so the initial role switch works: + + - A-Device: + * disconnect-during-suspend enters A_PERIPHERAL state + * kill OTG timer after reset as A_PERIPHERAL ... + * ... and also pass that reset to the gadget + * once HNP succeeds, clear the "ignore_disconnect" flag + * from A_PERIPHERAL, disconnect transitions to A_WAIT_BCON + + - B-Device: + * kill OTG timer on entry to B_HOST state (HNP succeeded) + * once HNP succeeds, clear "ignore_disconnect" flag + * kick the root hub only _after_ the state is adjusted + +Other state transitions are left alone. Notably, exit paths from +the "roles have switched" state ... A_PERIPHERAL handling of that +stays seriously broken. + +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_core.c | 27 ++++++++++++++++----------- + drivers/usb/musb/musb_gadget.c | 2 +- + drivers/usb/musb/musb_virthub.c | 11 ++++++++++- + 3 files changed, 27 insertions(+), 13 deletions(-) + +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index 05c5dd3..9dc995a 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -587,28 +587,23 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + if (devctl & MUSB_DEVCTL_LSDEV) + musb->port1_status |= USB_PORT_STAT_LOW_SPEED; + +- if (hcd->status_urb) +- usb_hcd_poll_rh_status(hcd); +- else +- usb_hcd_resume_root_hub(hcd); +- +- MUSB_HST_MODE(musb); +- + /* indicate new connection to OTG machine */ + switch (musb->xceiv->state) { + case OTG_STATE_B_PERIPHERAL: + if (int_usb & MUSB_INTR_SUSPEND) { + DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n"); +- musb->xceiv->state = OTG_STATE_B_HOST; +- hcd->self.is_b_host = 1; + int_usb &= ~MUSB_INTR_SUSPEND; ++ goto b_host; + } else + DBG(1, "CONNECT as b_peripheral???\n"); + break; + case OTG_STATE_B_WAIT_ACON: +- DBG(1, "HNP: Waiting to switch to b_host state\n"); ++ DBG(1, "HNP: CONNECT, now b_host\n"); ++b_host: + musb->xceiv->state = OTG_STATE_B_HOST; + hcd->self.is_b_host = 1; ++ musb->ignore_disconnect = 0; ++ del_timer(&musb->otg_timer); + break; + default: + if ((devctl & MUSB_DEVCTL_VBUS) +@@ -618,6 +613,14 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + } + break; + } ++ ++ /* poke the root hub */ ++ MUSB_HST_MODE(musb); ++ if (hcd->status_urb) ++ usb_hcd_poll_rh_status(hcd); ++ else ++ usb_hcd_resume_root_hub(hcd); ++ + DBG(1, "CONNECT (%s) devctl %02x\n", + otg_state_string(musb), devctl); + } +@@ -662,7 +665,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + + msecs_to_jiffies(TA_WAIT_BCON(musb))); + break; + case OTG_STATE_A_PERIPHERAL: +- musb_hnp_stop(musb); ++ musb->ignore_disconnect = 0; ++ del_timer(&musb->otg_timer); ++ musb_g_reset(musb); + break; + case OTG_STATE_B_WAIT_ACON: + DBG(1, "HNP: RESET (%s), to b_peripheral\n", +diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c +index 2fbfba5..7dd3d59 100644 +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -1964,7 +1964,7 @@ void musb_g_disconnect(struct musb *musb) + musb->xceiv->state = OTG_STATE_A_IDLE; + break; + case OTG_STATE_A_PERIPHERAL: +- musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; ++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON; + break; + case OTG_STATE_B_WAIT_ACON: + case OTG_STATE_B_HOST: +diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c +index 7e7900f..14f7cf3 100644 +--- a/drivers/usb/musb/musb_virthub.c ++++ b/drivers/usb/musb/musb_virthub.c +@@ -187,8 +187,17 @@ void musb_root_disconnect(struct musb *musb) + musb->is_active = 0; + + switch (musb->xceiv->state) { +- case OTG_STATE_A_HOST: + case OTG_STATE_A_SUSPEND: ++#ifdef CONFIG_USB_MUSB_OTG ++ if (is_otg_enabled(musb) ++ && musb->xceiv->host->b_hnp_enable) { ++ musb->xceiv->state = OTG_STATE_A_PERIPHERAL; ++ musb->g.is_a_peripheral = 1; ++ break; ++ } ++#endif ++ /* FALLTHROUGH */ ++ case OTG_STATE_A_HOST: + musb->xceiv->state = OTG_STATE_A_WAIT_BCON; + musb->is_active = 0; + break; +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch b/recipes/linux/linux-omap-pm-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch new file mode 100644 index 0000000000..fc34fb983e --- /dev/null +++ b/recipes/linux/linux-omap-pm-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch @@ -0,0 +1,145 @@ +From 4288b7df4ae6629a4fb14aca2c489da01d4d19c3 Mon Sep 17 00:00:00 2001 +From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Date: Tue, 31 Mar 2009 12:35:09 -0700 +Subject: [PATCH] musb: support disconnect after HNP roleswitch + +Adjust HNP state machines in MUSB driver so that they handle the +case where the cable is disconnected. The A-side machine was +very wrong (unrecoverable); the B-Side was much less so. + + - A_PERIPHERAL ... as usual, the non-observability of the ID + pin through Mentor's registers makes trouble. We can't go + directly to A_WAIT_VFALL to end the session and start the + disconnect processing. We can however sense link suspending, + go to A_WAIT_BCON, and from there use OTG timeouts to finally + trigger that A_WAIT_VFALL transition. (Hoping that nobody + reconnects quickly to that port and notices the wrong state.) + + - B_HOST ... actually clear the Host Request (HR) bit as the + messages say, disconnect the peripheral from the root hub, + and don't detour through a suspend state. (In some cases + this would eventually have cleaned up.) + +Also adjust the A_SUSPEND transition to respect the A_AIDL_BDIS +timeout, so if HNP doesn't trigger quickly enough the A_WAIT_VFALL +transition happens as it should. + +Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_core.c | 41 +++++++++++++++++++++++++++----------- + drivers/usb/musb/musb_gadget.c | 2 + + drivers/usb/musb/musb_virthub.c | 4 +++ + 3 files changed, 35 insertions(+), 12 deletions(-) + +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index 9dc995a..5770ccb 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -304,9 +304,11 @@ void musb_otg_timer_func(unsigned long data) + musb->xceiv->state = OTG_STATE_B_PERIPHERAL; + musb->is_active = 0; + break; ++ case OTG_STATE_A_SUSPEND: + case OTG_STATE_A_WAIT_BCON: +- DBG(1, "HNP: a_wait_bcon timeout; back to a_host\n"); +- musb_hnp_stop(musb); ++ DBG(1, "HNP: %s timeout\n", otg_state_string(musb)); ++ musb_set_vbus(musb, 0); ++ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; + break; + default: + DBG(1, "HNP: Unhandled mode %s\n", otg_state_string(musb)); +@@ -324,15 +326,12 @@ void musb_hnp_stop(struct musb *musb) + void __iomem *mbase = musb->mregs; + u8 reg; + ++ DBG(1, "HNP: stop from %s\n", otg_state_string(musb)); ++ + switch (musb->xceiv->state) { + case OTG_STATE_A_PERIPHERAL: +- case OTG_STATE_A_WAIT_VFALL: +- case OTG_STATE_A_WAIT_BCON: +- DBG(1, "HNP: Switching back to A-host\n"); + musb_g_disconnect(musb); +- musb->xceiv->state = OTG_STATE_A_IDLE; +- MUSB_HST_MODE(musb); +- musb->is_active = 0; ++ DBG(1, "HNP: back to %s\n", otg_state_string(musb)); + break; + case OTG_STATE_B_HOST: + DBG(1, "HNP: Disabling HR\n"); +@@ -775,7 +774,16 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, + #endif /* HOST */ + #ifdef CONFIG_USB_MUSB_OTG + case OTG_STATE_B_HOST: +- musb_hnp_stop(musb); ++ /* REVISIT this behaves for "real disconnect" ++ * cases; make sure the other transitions from ++ * from B_HOST act right too. The B_HOST code ++ * in hnp_stop() is currently not used... ++ */ ++ musb_root_disconnect(musb); ++ musb_to_hcd(musb)->self.is_b_host = 0; ++ musb->xceiv->state = OTG_STATE_B_PERIPHERAL; ++ MUSB_DEV_MODE(musb); ++ musb_g_disconnect(musb); + break; + case OTG_STATE_A_PERIPHERAL: + musb_hnp_stop(musb); +@@ -807,10 +815,19 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, + switch (musb->xceiv->state) { + #ifdef CONFIG_USB_MUSB_OTG + case OTG_STATE_A_PERIPHERAL: +- /* +- * We cannot stop HNP here, devctl BDEVICE might be +- * still set. ++ /* We also come here if the cable is removed, since ++ * this silicon doesn't report ID-no-longer-grounded. ++ * ++ * We depend on T(a_wait_bcon) to shut us down, and ++ * hope users don't do anything dicey during this ++ * undesired detour through A_WAIT_BCON. + */ ++ musb_hnp_stop(musb); ++ usb_hcd_resume_root_hub(musb_to_hcd(musb)); ++ musb_root_disconnect(musb); ++ musb_platform_try_idle(musb, jiffies ++ + msecs_to_jiffies(musb->a_wait_bcon ++ ? : OTG_TIME_A_WAIT_BCON)); + break; + #endif + case OTG_STATE_B_PERIPHERAL: +diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c +index 7dd3d59..8b3c4e2 100644 +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -1962,9 +1962,11 @@ void musb_g_disconnect(struct musb *musb) + DBG(2, "Unhandled disconnect %s, setting a_idle\n", + otg_state_string(musb)); + musb->xceiv->state = OTG_STATE_A_IDLE; ++ MUSB_HST_MODE(musb); + break; + case OTG_STATE_A_PERIPHERAL: + musb->xceiv->state = OTG_STATE_A_WAIT_BCON; ++ MUSB_HST_MODE(musb); + break; + case OTG_STATE_B_WAIT_ACON: + case OTG_STATE_B_HOST: +diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c +index 14f7cf3..e8ef925 100644 +--- a/drivers/usb/musb/musb_virthub.c ++++ b/drivers/usb/musb/musb_virthub.c +@@ -83,6 +83,10 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) + musb->xceiv->state = OTG_STATE_A_SUSPEND; + musb->is_active = is_otg_enabled(musb) + && musb->xceiv->host->b_hnp_enable; ++ if (musb->is_active) ++ mod_timer(&musb->otg_timer, jiffies ++ + msecs_to_jiffies( ++ OTG_TIME_A_AIDL_BDIS)); + musb_platform_try_idle(musb, 0); + break; + #ifdef CONFIG_USB_MUSB_OTG +-- +1.6.0.4 + diff --git a/recipes/linux/linux-omap-pm_2.6.29.bb b/recipes/linux/linux-omap-pm_2.6.29.bb index e06653690f..3a587b2fcb 100644 --- a/recipes/linux/linux-omap-pm_2.6.29.bb +++ b/recipes/linux/linux-omap-pm_2.6.29.bb @@ -126,6 +126,37 @@ SRC_URI_append = " \ file://vfp/04-vfp-threads.patch;patch=1 \ file://vfp/05-vfp-signal-handlers.patch;patch=1 \ file://arch-has-holes.diff;patch=1 \ + file://musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch;patch=1 \ + file://musb/0002-USB-composite-avoid-inconsistent-lock-state.patch;patch=1 \ + file://musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch;patch=1 \ + file://musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch;patch=1 \ + file://musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch;patch=1 \ + file://musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch;patch=1 \ + file://musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch;patch=1 \ + file://musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch;patch=1 \ + file://musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch;patch=1 \ + file://musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch;patch=1 \ + file://musb/0011-musb-fix-isochronous-TXDMA-take-2.patch;patch=1 \ + file://musb/0012-musb-fix-possible-panic-while-resuming.patch;patch=1 \ + file://musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch;patch=1 \ + file://musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch;patch=1 \ + file://musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch;patch=1 \ + file://musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch;patch=1 \ + file://musb/0017-musb_host-refactor-URB-giveback.patch;patch=1 \ + file://musb/0018-musb-split-out-CPPI-interrupt-handler.patch;patch=1 \ + file://musb/0019-musb_host-simplify-check-for-active-URB.patch;patch=1 \ + file://musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch;patch=1 \ + file://musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch;patch=1 \ + file://musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch;patch=1 \ + file://musb/0023-musb-add-high-bandwidth-ISO-support.patch;patch=1 \ + file://musb/0024-USB-otg-adding-nop-usb-transceiver.patch;patch=1 \ + file://musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch;patch=1 \ + file://musb/0026-musb-proper-hookup-to-transceiver-drivers.patch;patch=1 \ + file://musb/0027-musb-otg-timer-cleanup.patch;patch=1 \ + file://musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch;patch=1 \ + file://musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch;patch=1 \ + file://cache/l1cache-shift.patch;patch=1 \ + file://cache/copy-page-tweak.patch;patch=1 \ " diff --git a/recipes/linux/linux-omap_2.6.29.bb b/recipes/linux/linux-omap_2.6.29.bb index 9f390d4f6e..18382b60ef 100644 --- a/recipes/linux/linux-omap_2.6.29.bb +++ b/recipes/linux/linux-omap_2.6.29.bb @@ -163,6 +163,8 @@ SRC_URI_append = " \ file://vfp/04-vfp-threads.patch;patch=1 \ file://vfp/05-vfp-signal-handlers.patch;patch=1 \ file://arch-has-holes.diff;patch=1 \ + file://cache/l1cache-shift.patch;patch=1 \ + file://cache/copy-page-tweak.patch;patch=1 \ " diff --git a/recipes/linux/linux-omap_git.bb b/recipes/linux/linux-omap_git.bb index 731878dc32..f19840d4f4 100644 --- a/recipes/linux/linux-omap_git.bb +++ b/recipes/linux/linux-omap_git.bb @@ -8,18 +8,50 @@ COMPATIBLE_MACHINE = "omap5912osk|omap1710h3|omap2430sdp|omap2420h4|beagleboard| DEFAULT_PREFERENCE = "-1" DEFAULT_PREFERENCE_omapzoom2 = "1" -SRCREV = "fd673394fa970fb82e4bc206e171c58995d0c2ba" +SRCREV = "3777b1e9ffb6e0901be93cbe201ae8e96003179b" FILESPATHPKG_prepend = "linux-omap-2.6.31:" # The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc -PV = "2.6.30+2.6.31-rc5+gitr${SRCREV}" +PV = "2.6.30+2.6.31-rc8+gitr${SRCREV}" PR = "r0" SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git;protocol=git \ file://defconfig" SRC_URI_append = " \ + file://ehci-phy-reset.patch;patch=1 \ + file://ehci.patch;patch=1 \ + file://0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch;patch=1 \ + file://cache/l1cache-shift.patch;patch=1 \ + file://cache/copy-page-tweak.patch;patch=1 \ + file://dss2/0001-OMAP2-Add-funcs-for-writing-SMS_ROT_-registers.patch;patch=1 \ + file://dss2/0002-OMAP-OMAPFB-split-omapfb.h.patch;patch=1 \ + file://dss2/0003-OMAP-OMAPFB-add-omapdss-device.patch;patch=1 \ + file://dss2/0004-OMAP-Add-VRAM-manager.patch;patch=1 \ + file://dss2/0005-OMAP-Add-support-for-VRFB-rotation-engine.patch;patch=1 \ + file://dss2/0006-OMAP-DSS2-Documentation-for-DSS2.patch;patch=1 \ + file://dss2/0007-OMAP-DSS2-Display-Subsystem-Driver-core.patch;patch=1 \ + file://dss2/0008-OMAP-DSS2-Add-more-core-files.patch;patch=1 \ + file://dss2/0009-OMAP-DSS2-DISPC.patch;patch=1 \ + file://dss2/0010-OMAP-DSS2-DPI-driver.patch;patch=1 \ + file://dss2/0011-OMAP-DSS2-Video-encoder-driver.patch;patch=1 \ + file://dss2/0012-OMAP-DSS2-RFBI-driver.patch;patch=1 \ + file://dss2/0013-OMAP-DSS2-SDI-driver.patch;patch=1 \ + file://dss2/0014-OMAP-DSS2-DSI-driver.patch;patch=1 \ + file://dss2/0015-OMAP-DSS2-omapfb-driver.patch;patch=1 \ + file://dss2/0016-OMAP-DSS2-Add-DPI-panel-drivers.patch;patch=1 \ + file://dss2/0017-OMAP-DSS2-Taal-DSI-command-mode-panel-driver.patch;patch=1 \ + file://dss2/0001-OMAP3-Enable-DSS2-for-OMAP3EVM-board.patch;patch=1 \ + file://dss2/0002-V4L2-Added-New-V4L2-CIDs-for-omap-devices-V4L2-IOCT.patch;patch=1 \ + file://dss2/0003-V4L2-Updated-v4l2_common-for-new-V4L2-CIDs.patch;patch=1 \ + file://dss2/0004-OMAP2-3-V4L2-Add-support-for-OMAP2-3-V4L2-driver-on.patch;patch=1 \ + file://expansion-boards/tincantools-zippy.patch;patch=1 \ + file://madc/madc-driver.patch;patch=1 \ + file://madc/madc.patch;patch=1 \ +" + +SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \ " S = "${WORKDIR}/git" diff --git a/recipes/linux/linux-palm-omap1_2.6.22-omap1.bb b/recipes/linux/linux-palm-omap1_2.6.22-omap1.bb index 786e4901c3..16fe38bf5c 100644 --- a/recipes/linux/linux-palm-omap1_2.6.22-omap1.bb +++ b/recipes/linux/linux-palm-omap1_2.6.22-omap1.bb @@ -25,7 +25,7 @@ do_configure() { fi - if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/linux/linux-rp.inc b/recipes/linux/linux-rp.inc index bdeb9f364a..041a095d91 100644 --- a/recipes/linux/linux-rp.inc +++ b/recipes/linux/linux-rp.inc @@ -105,7 +105,7 @@ do_configure() { echo "CONFIG_CMDLINE=\"${CMDLINE}\"" >> ${S}/.config - if [ "${TARGET_OS}" = "linux-gnueabi" -o "${TARGET_OS}" = "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" = "linux-gnueabi" -o "${TARGET_OS}" = "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config if [ "${ARM_KEEP_OABI}" = "1" ] ; then echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config diff --git a/recipes/linux/linux-tornado-omap2_2.6.16.16.bb b/recipes/linux/linux-tornado-omap2_2.6.16.16.bb index a9ebee14cd..9c6e133c28 100644 --- a/recipes/linux/linux-tornado-omap2_2.6.16.16.bb +++ b/recipes/linux/linux-tornado-omap2_2.6.16.16.bb @@ -24,7 +24,7 @@ do_configure() { fi - if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/linux/linux.inc b/recipes/linux/linux.inc index 3dbb1ecb40..044d4130c5 100644 --- a/recipes/linux/linux.inc +++ b/recipes/linux/linux.inc @@ -68,7 +68,7 @@ do_configure_prepend() { # # oabi / eabi support # - if [ "${TARGET_OS}" = "linux-gnueabi" -o "${TARGET_OS}" = "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" = "linux-gnueabi" -o "${TARGET_OS}" = "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config if [ "${ARM_KEEP_OABI}" = "1" ] ; then echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config diff --git a/recipes/linux/linux_2.6.28.bb b/recipes/linux/linux_2.6.28.bb index 37a8646306..98cf19129d 100644 --- a/recipes/linux/linux_2.6.28.bb +++ b/recipes/linux/linux_2.6.28.bb @@ -1,6 +1,6 @@ require linux.inc -PR = "r11" +PR = "r12" # Mark archs/machines that this kernel supports DEFAULT_PREFERENCE = "-1" diff --git a/recipes/linux/mx21ads-kernel_2.6.19rc6.bb b/recipes/linux/mx21ads-kernel_2.6.19rc6.bb index 47f363d7df..bc8e6242a7 100644 --- a/recipes/linux/mx21ads-kernel_2.6.19rc6.bb +++ b/recipes/linux/mx21ads-kernel_2.6.19rc6.bb @@ -26,7 +26,7 @@ RPROVIDES_kernel-image += "hostap-modules" do_configure_prepend() { install -m 0644 ${WORKDIR}/mx21ads_defconfig ${S}/defconfig - if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/linux/netbook-pro-kernel_2.6.17.bb b/recipes/linux/netbook-pro-kernel_2.6.17.bb index 1d24646b3b..37704dcb64 100644 --- a/recipes/linux/netbook-pro-kernel_2.6.17.bb +++ b/recipes/linux/netbook-pro-kernel_2.6.17.bb @@ -27,7 +27,7 @@ do_configure() { fi - if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" == "linux-gnueabi" -o "${TARGET_OS}" == "linux-uclibceabi" ]; then echo "CONFIG_AEABI=y" >> ${S}/.config echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config else diff --git a/recipes/make/make.inc b/recipes/make/make.inc index 8a43f40a24..af21861c2e 100644 --- a/recipes/make/make.inc +++ b/recipes/make/make.inc @@ -11,7 +11,7 @@ SRC_URI = "${GNU_MIRROR}/make/make-${PV}.tar.bz2 \ inherit autotools do_configure_prepend() { - if [ "${TARGET_OS}" = "linux-uclibc" -o "${TARGET_OS}" = "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" = "linux-uclibc" -o "${TARGET_OS}" = "linux-uclibceabi" ]; then export make_cv_sys_gnu_glob="no" export GLOBINC=-I`pwd`/glob export GLOBLIB=glob/libglob.a diff --git a/recipes/mozilla/fennec_hg.bb b/recipes/mozilla/fennec_hg.bb index 94996134fa..ef4cedd70b 100644 --- a/recipes/mozilla/fennec_hg.bb +++ b/recipes/mozilla/fennec_hg.bb @@ -1,12 +1,12 @@ DESCRIPTION = "Mozilla Mobile browser" -PV = "0.9+1.0b2pre" -MOZPV = "1.0b2pre" -PR = "r5" +PV = "0.9+1.0b4pre" +MOZPV = "1.0b4pre" +PR = "r7" PE = "1" -SRC_URI = "hg://hg.mozilla.org/;module=mozilla-central;rev=8c9a6d851018 \ - hg://hg.mozilla.org/;module=mobile-browser;rev=c24b8b4ade53 \ +SRC_URI = "hg://hg.mozilla.org/;module=mozilla-central;rev=37acc871cb55 \ + hg://hg.mozilla.org/;module=mobile-browser;rev=c725e5e30b9d \ file://jsautocfg.h \ file://jsautocfg-dontoverwrite.patch;patch=1 \ file://use-native-bpp.patch;patch=1 \ @@ -20,7 +20,7 @@ require firefox.inc DEPENDS += "libnotify autoconf213-native cairo alsa-lib sqlite3" PARALLEL_MAKE = "" -export HOST_LIBIDL_CONFIG = "${STAGING_BINDIR_NATIVE}/libIDL-config-2" + FULL_OPTIMIZATION = "-fexpensive-optimizations -fomit-frame-pointer -frename-registers -O2" export LIBXUL_DIST="${S}/objdir/xulrunner/dist/" diff --git a/recipes/mozilla/firefox.inc b/recipes/mozilla/firefox.inc index 1be9c4da8f..8526a8d151 100644 --- a/recipes/mozilla/firefox.inc +++ b/recipes/mozilla/firefox.inc @@ -30,6 +30,13 @@ FILES_${PN}-dbg += " ${libdir}/${PN}-*/.debug \ ${bindir}/.debug \ " +export HOST_LIBIDL_CONFIG = "${STAGING_BINDIR_NATIVE}/libIDL-config-2" + +# Due to sysroot we need to sed out references to the target staging when building the native version of xpidl +# Symptons of the failure include "gthread.h:344: error: size of array 'type name' is negative" +export HOST_LIBIDL_CFLAGS = "`${HOST_LIBIDL_CONFIG} --cflags | sed -e s:${STAGING_DIR_TARGET}:${STAGING_DIR_NATIVE}:g`" + + do_install() { oe_runmake DESTDIR="${D}" destdir="${D}" install install -d ${D}${datadir}/applications diff --git a/recipes/openssl/openssl-native_0.9.7g.bb b/recipes/openssl/openssl-native_0.9.7g.bb index dfe3ab5eae..40558f2cdb 100644 --- a/recipes/openssl/openssl-native_0.9.7g.bb +++ b/recipes/openssl/openssl-native_0.9.7g.bb @@ -2,7 +2,7 @@ inherit pkgconfig native require openssl.inc -PR = "r2" +PR = "${INC_PR}.0" SRC_URI += "file://debian.patch;patch=1 \ file://armeb.patch;patch=1;pnum=0 \ diff --git a/recipes/openssl/openssl-native_0.9.7m.bb b/recipes/openssl/openssl-native_0.9.7m.bb index 445b6e9161..ccae43e629 100644 --- a/recipes/openssl/openssl-native_0.9.7m.bb +++ b/recipes/openssl/openssl-native_0.9.7m.bb @@ -6,7 +6,7 @@ require openssl.inc export FULL_OPTIMIZATION = " " export BUILD_OPTIMIZATION = " " -PR = "r2" +PR = "${INC_PR}.0" SRC_URI += "file://debian.patch;patch=1 \ file://armeb.patch;patch=1;pnum=0 \ diff --git a/recipes/openssl/openssl-native_0.9.8g.bb b/recipes/openssl/openssl-native_0.9.8g.bb index 27f0169cf9..d567ae73f9 100644 --- a/recipes/openssl/openssl-native_0.9.8g.bb +++ b/recipes/openssl/openssl-native_0.9.8g.bb @@ -2,7 +2,7 @@ inherit pkgconfig native require openssl.inc -PR = "r1" +PR = "${INC_PR}.0" # This flag can contain target options (e.g -mfpu=neon for armv7-a systems) export FULL_OPTIMIZATION = " " diff --git a/recipes/openssl/openssl-native_0.9.8j.bb b/recipes/openssl/openssl-native_0.9.8j.bb index ffbd5ea8a9..976a4d7835 100644 --- a/recipes/openssl/openssl-native_0.9.8j.bb +++ b/recipes/openssl/openssl-native_0.9.8j.bb @@ -2,7 +2,7 @@ inherit pkgconfig native require openssl.inc -PR = "r1" +PR = "${INC_PR}.0" # This flag can contain target options (e.g -mfpu=neon for armv7-a systems) export FULL_OPTIMIZATION = " " diff --git a/recipes/openssl/openssl.inc b/recipes/openssl/openssl.inc index 3972cd3bd9..9031b7b3bb 100644 --- a/recipes/openssl/openssl.inc +++ b/recipes/openssl/openssl.inc @@ -6,6 +6,8 @@ SECTION = "libs/network" SRC_URI = "http://www.openssl.org/source/openssl-${PV}.tar.gz" S = "${WORKDIR}/openssl-${PV}" +INC_PR = "r10" + AR_append = " r" CFLAG = "${@base_conditional('SITEINFO_ENDIANESS', 'le', '-DL_ENDIAN', '-DB_ENDIAN', d)} \ -DTERMIO ${FULL_OPTIMIZATION} -Wall" @@ -32,6 +34,9 @@ do_configure () { if [ "x$os" = "xlinux-uclibc" ]; then os=linux fi + if [ "x$os" = "xlinux-uclibceabi" ]; then + os=linux + fi target="$os-${HOST_ARCH}" case $target in linux-arm) @@ -94,9 +99,16 @@ do_stage () { } do_install () { - install -m 0755 -d ${D}${libdir}/pkgconfig oe_runmake INSTALL_PREFIX="${D}" install - chmod 644 ${D}${libdir}/pkgconfig/openssl.pc + + # On x86_64, move lib/* to lib64 + if [ "${libdir}" != "${prefix}/lib" ] + then + install -d ${D}${libdir} ${D}${libdir}/pkgconfig + mv ${D}${prefix}/lib/lib* ${D}${libdir} + mv ${D}${prefix}/lib/pkgconfig/*.pc ${D}${libdir}/pkgconfig + fi + oe_libinstall -so libcrypto ${D}${libdir} oe_libinstall -so libssl ${D}${libdir} } diff --git a/recipes/openssl/openssl_0.9.7e.bb b/recipes/openssl/openssl_0.9.7e.bb index cda364a53d..b82107661b 100644 --- a/recipes/openssl/openssl_0.9.7e.bb +++ b/recipes/openssl/openssl_0.9.7e.bb @@ -1,6 +1,6 @@ require openssl.inc -PR = "r6" +PR = "${INC_PR}.0" SRC_URI += "file://debian.patch;patch=1 \ file://armeb.patch;patch=1 \ diff --git a/recipes/openssl/openssl_0.9.7g.bb b/recipes/openssl/openssl_0.9.7g.bb index fbd2af26f9..68a26147c6 100644 --- a/recipes/openssl/openssl_0.9.7g.bb +++ b/recipes/openssl/openssl_0.9.7g.bb @@ -2,7 +2,7 @@ inherit pkgconfig require openssl.inc -PR = "r7" +PR = "${INC_PR}.0" SRC_URI += "file://debian.patch;patch=1 \ file://armeb.patch;patch=1;pnum=0 \ diff --git a/recipes/openssl/openssl_0.9.7m.bb b/recipes/openssl/openssl_0.9.7m.bb index fbd2af26f9..68a26147c6 100644 --- a/recipes/openssl/openssl_0.9.7m.bb +++ b/recipes/openssl/openssl_0.9.7m.bb @@ -2,7 +2,7 @@ inherit pkgconfig require openssl.inc -PR = "r7" +PR = "${INC_PR}.0" SRC_URI += "file://debian.patch;patch=1 \ file://armeb.patch;patch=1;pnum=0 \ diff --git a/recipes/openssl/openssl_0.9.8g.bb b/recipes/openssl/openssl_0.9.8g.bb index 1cb360f967..d76e756c14 100644 --- a/recipes/openssl/openssl_0.9.8g.bb +++ b/recipes/openssl/openssl_0.9.8g.bb @@ -2,7 +2,7 @@ inherit pkgconfig require openssl.inc -PR = "r9" +PR = "${INC_PR}.0" SRC_URI += "file://debian.patch;patch=1 \ file://configure-targets.patch;patch=1 \ diff --git a/recipes/openssl/openssl_0.9.8j.bb b/recipes/openssl/openssl_0.9.8j.bb index 21450d2a24..bb9694f618 100644 --- a/recipes/openssl/openssl_0.9.8j.bb +++ b/recipes/openssl/openssl_0.9.8j.bb @@ -2,7 +2,7 @@ inherit pkgconfig require openssl.inc -PR = "r2" +PR = "${INC_PR}.0" export OE_LDFLAGS="${LDFLAGS}" diff --git a/recipes/opkg/files/opkg_wget_nogpg_02_use_vfork_system.patch b/recipes/opkg/files/opkg_wget_nogpg_02_use_vfork_system.patch index 5eb9517df8..6c108286e5 100644 --- a/recipes/opkg/files/opkg_wget_nogpg_02_use_vfork_system.patch +++ b/recipes/opkg/files/opkg_wget_nogpg_02_use_vfork_system.patch @@ -155,15 +155,6 @@ err = errno; perror (de->d_name); } -@@ -382,7 +384,7 @@ - perror (ctx->statedir); - - sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir); -- err = system (cmd); -+ err = system (cmd); /* FIXME FIXME */ - free (cmd); - - free (ctx->statedir); --- orig/libopkg/opkg_download.c 2008-12-20 15:07:04.000000000 -0600 +++ opkg/libopkg/opkg_download.c 2008-12-21 21:44:30.000000000 -0600 @@ -129,16 +129,21 @@ diff --git a/recipes/ortp/ortp.inc b/recipes/ortp/ortp.inc index c05e9d51cb..a086156c6a 100644 --- a/recipes/ortp/ortp.inc +++ b/recipes/ortp/ortp.inc @@ -1,8 +1,7 @@ DESCRIPTION = "An LGPL implementation of RTP - RFC3550" LICENSE = "LGPL" -DEPENDS = "glibc " -PR = "r1" +INC_PR = "r1" inherit autotools pkgconfig diff --git a/recipes/ortp/ortp_0.13.1.bb b/recipes/ortp/ortp_0.13.1.bb index ae06320421..48f0f184b4 100644 --- a/recipes/ortp/ortp_0.13.1.bb +++ b/recipes/ortp/ortp_0.13.1.bb @@ -1,2 +1,2 @@ require ortp.inc - +PR = "${INC_PR}.0" diff --git a/recipes/ortp/ortp_0.7.1.bb b/recipes/ortp/ortp_0.7.1.bb index 0318301cfd..4700320153 100644 --- a/recipes/ortp/ortp_0.7.1.bb +++ b/recipes/ortp/ortp_0.7.1.bb @@ -1,4 +1,4 @@ require ortp.inc - -PR = "r1" +DEPENDS = "glib-2.0 " +PR = "${INC_PR}.0" diff --git a/recipes/pam/libpam-1.0.2/pam-disable-nis-on-uclibc.patch b/recipes/pam/libpam-1.0.2/pam-disable-nis-on-uclibc.patch new file mode 100644 index 0000000000..258166cc52 --- /dev/null +++ b/recipes/pam/libpam-1.0.2/pam-disable-nis-on-uclibc.patch @@ -0,0 +1,251 @@ +Index: Linux-PAM-1.0.2/Makefile.in +=================================================================== +--- Linux-PAM-1.0.2.orig/Makefile.in 2008-08-29 01:14:12.000000000 -0700 ++++ Linux-PAM-1.0.2/Makefile.in 2009-09-04 01:06:22.571466501 -0700 +@@ -71,8 +71,7 @@ + distclean-recursive maintainer-clean-recursive + ETAGS = etags + CTAGS = ctags +-DIST_SUBDIRS = libpam tests libpamc libpam_misc modules po conf doc \ +- examples xtests ++DIST_SUBDIRS = libpam libpamc libpam_misc modules po conf + DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + distdir = $(PACKAGE)-$(VERSION) + top_distdir = $(distdir) +@@ -244,8 +243,8 @@ + top_builddir = @top_builddir@ + top_srcdir = @top_srcdir@ + AUTOMAKE_OPTIONS = 1.9 gnu dist-bzip2 check-news +-@STATIC_MODULES_FALSE@SUBDIRS = libpam tests libpamc libpam_misc modules po conf doc examples xtests +-@STATIC_MODULES_TRUE@SUBDIRS = modules libpam libpamc libpam_misc tests po conf doc examples xtests ++@STATIC_MODULES_FALSE@SUBDIRS = libpam libpamc libpam_misc modules po conf ++@STATIC_MODULES_TRUE@SUBDIRS = modules libpam libpamc libpam_misc po conf + CLEANFILES = *~ + M4_FILES = m4/codeset.m4 m4/gettext.m4 m4/glibc21.m4 m4/glibc2.m4 \ + m4/iconv.m4 m4/intdiv0.m4 m4/intmax.m4 m4/inttypes_h.m4 \ +Index: Linux-PAM-1.0.2/modules/pam_access/pam_access.c +=================================================================== +--- Linux-PAM-1.0.2.orig/modules/pam_access/pam_access.c 2007-12-07 07:40:01.000000000 -0800 ++++ Linux-PAM-1.0.2/modules/pam_access/pam_access.c 2009-09-04 01:06:22.575455835 -0700 +@@ -41,7 +41,11 @@ + #include <errno.h> + #include <ctype.h> + #include <sys/utsname.h> ++ ++#ifdef NIS + #include <rpcsvc/ypclnt.h> ++#endif ++ + #include <arpa/inet.h> + #include <netdb.h> + #include <sys/socket.h> +@@ -479,8 +483,9 @@ + char *mydomain = NULL; + int retval; + ++#ifdef NIS + yp_get_default_domain(&mydomain); +- ++#endif + + retval = innetgr (netgroup, machine, user, mydomain); + if (debug == YES) +Index: Linux-PAM-1.0.2/modules/pam_unix/Makefile.am +=================================================================== +--- Linux-PAM-1.0.2.orig/modules/pam_unix/Makefile.am 2008-02-29 07:22:03.000000000 -0800 ++++ Linux-PAM-1.0.2/modules/pam_unix/Makefile.am 2009-09-04 01:09:46.519457167 -0700 +@@ -32,7 +32,7 @@ + + securelib_LTLIBRARIES = pam_unix.la + +-noinst_HEADERS = md5.h support.h yppasswd.h bigcrypt.h passverify.h ++noinst_HEADERS = md5.h support.h bigcrypt.h passverify.h + + sbin_PROGRAMS = unix_chkpwd unix_update + +@@ -40,7 +40,7 @@ + + pam_unix_la_SOURCES = bigcrypt.c pam_unix_acct.c \ + pam_unix_auth.c pam_unix_passwd.c pam_unix_sess.c support.c \ +- passverify.c yppasswd_xdr.c md5_good.c md5_broken.c ++ passverify.c md5_good.c md5_broken.c + + bigcrypt_SOURCES = bigcrypt.c bigcrypt_main.c + bigcrypt_CFLAGS = $(AM_CFLAGS) +Index: Linux-PAM-1.0.2/modules/pam_unix/Makefile.in +=================================================================== +--- Linux-PAM-1.0.2.orig/modules/pam_unix/Makefile.in 2008-08-29 01:14:10.000000000 -0700 ++++ Linux-PAM-1.0.2/modules/pam_unix/Makefile.in 2009-09-04 01:13:42.939510044 -0700 +@@ -74,7 +74,7 @@ + pam_unix_la_DEPENDENCIES = + am_pam_unix_la_OBJECTS = bigcrypt.lo pam_unix_acct.lo pam_unix_auth.lo \ + pam_unix_passwd.lo pam_unix_sess.lo support.lo passverify.lo \ +- yppasswd_xdr.lo md5_good.lo md5_broken.lo ++ md5_good.lo md5_broken.lo + pam_unix_la_OBJECTS = $(am_pam_unix_la_OBJECTS) + pam_unix_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ +@@ -310,10 +310,10 @@ + @LIBCRYPT@ @LIBSELINUX@ + + securelib_LTLIBRARIES = pam_unix.la +-noinst_HEADERS = md5.h support.h yppasswd.h bigcrypt.h passverify.h ++noinst_HEADERS = md5.h support.h bigcrypt.h passverify.h + pam_unix_la_SOURCES = bigcrypt.c pam_unix_acct.c \ + pam_unix_auth.c pam_unix_passwd.c pam_unix_sess.c support.c \ +- passverify.c yppasswd_xdr.c md5_good.c md5_broken.c ++ passverify.c md5_good.c md5_broken.c + + bigcrypt_SOURCES = bigcrypt.c bigcrypt_main.c + bigcrypt_CFLAGS = $(AM_CFLAGS) +@@ -465,7 +465,6 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-md5_good.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-passverify.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-unix_update.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yppasswd_xdr.Plo@am__quote@ + + .c.o: + @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +Index: Linux-PAM-1.0.2/modules/pam_unix/pam_unix_passwd.c +=================================================================== +--- Linux-PAM-1.0.2.orig/modules/pam_unix/pam_unix_passwd.c 2008-02-29 07:22:03.000000000 -0800 ++++ Linux-PAM-1.0.2/modules/pam_unix/pam_unix_passwd.c 2009-09-04 01:06:22.579455994 -0700 +@@ -55,8 +55,11 @@ + #include <sys/time.h> + #include <sys/stat.h> + #include <rpc/rpc.h> ++ ++#ifdef NIS + #include <rpcsvc/yp_prot.h> + #include <rpcsvc/ypclnt.h> ++#endif + + #include <signal.h> + #include <errno.h> +@@ -77,7 +80,10 @@ + #include <security/pam_ext.h> + #include <security/pam_modutil.h> + ++#ifdef NIS + #include "yppasswd.h" ++#endif ++ + #include "md5.h" + #include "support.h" + #include "passverify.h" +@@ -105,6 +111,7 @@ + + static char *getNISserver(pam_handle_t *pamh) + { ++#ifdef NIS + char *master; + char *domainname; + int port, err; +@@ -131,6 +138,9 @@ + return NULL; + } + return master; ++#else ++ return NULL; ++#endif + } + + #ifdef WITH_SELINUX +@@ -301,6 +311,7 @@ + + if (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, forwho, 0, 1)) { + if ((master=getNISserver(pamh)) != NULL) { ++#ifdef NIS + struct timeval timeout; + struct yppasswd yppwd; + CLIENT *clnt; +@@ -362,6 +373,7 @@ + #ifdef DEBUG + sleep(5); + #endif ++#endif + } else { + retval = PAM_TRY_AGAIN; + } +Index: Linux-PAM-1.0.2/modules/pam_unix/support.c +=================================================================== +--- Linux-PAM-1.0.2.orig/modules/pam_unix/support.c 2008-01-23 07:35:13.000000000 -0800 ++++ Linux-PAM-1.0.2/modules/pam_unix/support.c 2009-09-04 01:06:22.579455994 -0700 +@@ -19,7 +19,10 @@ + #include <ctype.h> + #include <syslog.h> + #include <sys/resource.h> ++ ++#ifdef NIS + #include <rpcsvc/ypclnt.h> ++#endif + + #include <security/_pam_macros.h> + #include <security/pam_modules.h> +@@ -266,6 +269,7 @@ + if (!matched && nis) { + char *userinfo = NULL, *domain = NULL; + int len = 0, i; ++#ifdef NIS + len = yp_get_default_domain(&domain); + if (len == YPERR_SUCCESS) { + len = yp_bind(domain); +@@ -280,6 +284,7 @@ + matched = 1; + } + } ++#endif + } + + if (matched && (ret != NULL)) { +Index: Linux-PAM-1.0.2/modules/pam_unix/yppasswd.h +=================================================================== +--- Linux-PAM-1.0.2.orig/modules/pam_unix/yppasswd.h 2000-06-20 15:12:08.000000000 -0700 ++++ Linux-PAM-1.0.2/modules/pam_unix/yppasswd.h 2009-09-04 01:06:22.579455994 -0700 +@@ -13,6 +13,8 @@ + #ifndef _YPPASSWD_H_ + #define _YPPASSWD_H_ + ++#ifdef NIS ++ + #define YPPASSWDPROG ((u_long)100009) + #define YPPASSWDVERS ((u_long)1) + #define YPPASSWDPROC_UPDATE ((u_long)1) +@@ -48,4 +50,6 @@ + bool_t xdr_xpasswd(XDR * xdrs, xpasswd * objp); + bool_t xdr_yppasswd(XDR * xdrs, yppasswd * objp); + ++#endif ++ + #endif /* _YPPASSWD_H_ */ +Index: Linux-PAM-1.0.2/modules/pam_unix/yppasswd_xdr.c +=================================================================== +--- Linux-PAM-1.0.2.orig/modules/pam_unix/yppasswd_xdr.c 2005-07-20 02:46:19.000000000 -0700 ++++ Linux-PAM-1.0.2/modules/pam_unix/yppasswd_xdr.c 2009-09-04 01:06:22.579455994 -0700 +@@ -10,6 +10,8 @@ + * editied manually. + */ + ++#ifdef NIS ++ + #include "config.h" + + #include <rpc/rpc.h> +@@ -36,3 +38,5 @@ + return xdr_string(xdrs, &objp->oldpass, ~0) + && xdr_xpasswd(xdrs, &objp->newpw); + } ++ ++#endif +Index: Linux-PAM-1.0.2/po/POTFILES.in +=================================================================== +--- Linux-PAM-1.0.2.orig/po/POTFILES.in 2008-02-13 06:39:41.000000000 -0800 ++++ Linux-PAM-1.0.2/po/POTFILES.in 2009-09-04 01:06:22.579455994 -0700 +@@ -85,7 +85,6 @@ + ./modules/pam_unix/passverify.c + ./modules/pam_unix/support.c + ./modules/pam_unix/unix_chkpwd.c +-./modules/pam_unix/yppasswd_xdr.c + ./modules/pam_userdb/pam_userdb.c + ./modules/pam_warn/pam_warn.c + ./modules/pam_wheel/pam_wheel.c diff --git a/recipes/pam/libpam_1.0.2.bb b/recipes/pam/libpam_1.0.2.bb index 2acbe0ac6f..17d8f3028f 100644 --- a/recipes/pam/libpam_1.0.2.bb +++ b/recipes/pam/libpam_1.0.2.bb @@ -12,7 +12,7 @@ LICENSE = "GPLv2" DEPENDS = "flex flex-native" -PR = "r2" +PR = "r3" # The project is actually called Linux-PAM but that gives # a bad OE package name because of the upper case characters @@ -23,6 +23,10 @@ S = "${WORKDIR}/${p}" SRC_URI = "${KERNELORG_MIRROR}/pub/linux/libs/pam/library/${p}.tar.bz2 \ file://pam-nodocs.patch;patch=1 " +SRC_URI_append_linux-uclibc = "file://pam-disable-nis-on-uclibc.patch;patch=1" +SRC_URI_append_linux-uclibceabi = "file://pam-disable-nis-on-uclibc.patch;patch=1" +SRC_URI_append_linux-uclibcspe = "file://pam-disable-nis-on-uclibc.patch;patch=1" + inherit autotools LEAD_SONAME = "libpam.so.*" diff --git a/recipes/perl/perl_5.8.8.bb b/recipes/perl/perl_5.8.8.bb index 521cdf65e5..8a6d8392b2 100644 --- a/recipes/perl/perl_5.8.8.bb +++ b/recipes/perl/perl_5.8.8.bb @@ -5,7 +5,7 @@ LICENSE = "Artistic|GPL" PRIORITY = "optional" # We need gnugrep (for -I) DEPENDS = "virtual/db perl-native grep-native" -PR = "r27" +PR = "r28" # Major part of version PVM = "5.8" @@ -63,7 +63,7 @@ do_configure() { done # Fixups for uclibc - if [ "${TARGET_OS}" = "linux-uclibc" -o "${TARGET_OS}" = "linux-uclibcgnueabi" ]; then + if [ "${TARGET_OS}" = "linux-uclibc" -o "${TARGET_OS}" = "linux-uclibceabi" ]; then sed -i -e "s,\(d_crypt_r=\)'define',\1'undef',g" \ -e "s,\(crypt_r_proto=\)'\w+',\1'0',g" \ -e "s,\(d_getnetbyname_r=\)'define',\1'undef',g" \ @@ -81,6 +81,7 @@ do_configure() { sed -i -e 's,@DESTDIR@,${D},g' \ -e 's,@ARCH@,${TARGET_ARCH}-${TARGET_OS},g' \ -e "s%/usr/include/%${STAGING_INCDIR}/%g" \ + -e 's,/usr/,${exec_prefix}/,g' \ config.sh-${TARGET_ARCH}-${TARGET_OS} if test "${MACHINE}" != "native"; then @@ -103,10 +104,9 @@ do_compile() { oe_runmake perl LD="${TARGET_SYS}-gcc" } do_install() { - oe_runmake install - + oe_runmake install # Add perl pointing at current version - ln -sf perl${PV} ${D}/usr/bin/perl + ln -sf perl${PV} ${D}${bindir}/perl # Fix up versioned directories mv ${D}/${libdir}/perl/${PVM} ${D}/${libdir}/perl/${PV} diff --git a/recipes/powervr-drivers/libgles-omap3.inc b/recipes/powervr-drivers/libgles-omap3.inc index d7f655dc1d..c66309e827 100644 --- a/recipes/powervr-drivers/libgles-omap3.inc +++ b/recipes/powervr-drivers/libgles-omap3.inc @@ -1,6 +1,8 @@ DESCRIPTION = "libGLES for the omap3" LICENCE = "proprietary-binary" +RDEPENDS_${PN} += "devmem2" + #HACK! These are binaries, so we can't guarantee that LDFLAGS match :( INSANE_SKIP_${PN} = True INSANE_SKIP_${PN}-tests = True @@ -25,6 +27,7 @@ PROVIDES += "virtual/egl" # voila! SRC_URI = "file://OMAP35x_Graphics_SDK_setuplinux_${SGXPV}.bin \ + file://cputype \ file://rc.pvr \ file://chameleonman.desktop \ file://evilskull.desktop \ @@ -83,6 +86,8 @@ do_install () { cp -pP ${BINLOCATION}/*.so* ${D}${libdir} install -d ${D}${bindir}/ + install -m 0755 ${WORKDIR}/cputype ${D}${bindir}/ + cp -pP ${BINLOCATION}/*_test ${D}${bindir}/ cp -pP ${BINLOCATION}/gl2info ${D}${bindir}/ cp -pP ${BINLOCATION}/gles1test1 ${D}${bindir}/ diff --git a/recipes/powervr-drivers/libgles-omap3/cputype b/recipes/powervr-drivers/libgles-omap3/cputype new file mode 100755 index 0000000000..31fc89b8e1 --- /dev/null +++ b/recipes/powervr-drivers/libgles-omap3/cputype @@ -0,0 +1,5 @@ +#!/bin/sh +devmem2 0x4800244c | \ +grep 'Value at address' | \ +sed -e 's/.*): //' | \ +sed -e 's/0x5C00/OMAP3503/' -e 's/0x1C00/OMAP3515/' -e 's/0x4C00/OMAP3525/' -e 's/0x0C00/OMAP3530/' diff --git a/recipes/powervr-drivers/libgles-omap3/rc.pvr b/recipes/powervr-drivers/libgles-omap3/rc.pvr index 244f480f2c..20b5167b4c 100755 --- a/recipes/powervr-drivers/libgles-omap3/rc.pvr +++ b/recipes/powervr-drivers/libgles-omap3/rc.pvr @@ -1,24 +1,30 @@ #!/bin/sh -#rmmod bc_example -rmmod omaplfb -rmmod pvrsrvkm +CPUTYPE="$(cputype)" -insmod $(busybox find /lib/modules/$(uname -r) -name "pvrsrvkm.ko") -#modprobe bc_example -modprobe omaplfb +if ( $CPUTYPE == "OMAP3530"); then -pvr_maj=`grep "pvrsrvkm$" /proc/devices | cut -b1,2,3` + rmmod omaplfb + rmmod pvrsrvkm -if [ -e /dev/pvrsrvkm ] ; then - rm -f /dev/pvrsrvkm -fi + insmod $(busybox find /lib/modules/$(uname -r) -name "pvrsrvkm.ko") + + modprobe omaplfb + + pvr_maj=`grep "pvrsrvkm$" /proc/devices | cut -b1,2,3` -mknod /dev/pvrsrvkm c $pvr_maj 0 -chmod 666 /dev/pvrsrvkm + if [ -e /dev/pvrsrvkm ] ; then + rm -f /dev/pvrsrvkm + fi -/usr/bin/pvrsrvinit + mknod /dev/pvrsrvkm c $pvr_maj 0 + chmod 666 /dev/pvrsrvkm -# Set SGX to full speed -devmem2 0x48004b40 w 0 + /usr/bin/pvrsrvinit + + # Set SGX to full speed + devmem2 0x48004b40 w 0 +else + echo No SGX hardware, not starting pvrsinit +fi diff --git a/recipes/procps/procps_3.2.7.bb b/recipes/procps/procps_3.2.7.bb index 6da975adc7..b31b683708 100644 --- a/recipes/procps/procps_3.2.7.bb +++ b/recipes/procps/procps_3.2.7.bb @@ -1,6 +1,6 @@ require procps.inc -PR = "r8" +PR = "r9" inherit update-rc.d @@ -23,6 +23,9 @@ CONFFILES_${PN} = "${sysconfdir}/sysctl.conf" EXTRA_OEMAKE = "CFLAGS=-I${STAGING_INCDIR} \ CPPFLAGS=-I${STAGING_INCDIR} \ + usr/bin=${D}${bindir}/ \ + bin=${D}${base_bindir}/ \ + usr/proc/bin=${D}${bindir}/ \ LDFLAGS="${LDFLAGS}" \ CURSES=-lncurses \ install='install -D' \ diff --git a/recipes/qmake/qmake-native_1.07a.bb b/recipes/qmake/qmake-native_1.07a.bb index a80bb1bb92..bb3e79bca2 100644 --- a/recipes/qmake/qmake-native_1.07a.bb +++ b/recipes/qmake/qmake-native_1.07a.bb @@ -18,7 +18,7 @@ EXTRA_OEMAKE = "-e" do_configure() { # Install the OE build templates - for template in linux-oe-g++ linux-uclibc-oe-g++ linux-gnueabi-oe-g++ linux-uclibcgnueabi-oe-g++ + for template in linux-oe-g++ linux-uclibc-oe-g++ linux-gnueabi-oe-g++ linux-uclibceabi-oe-g++ do install -d ${S}/mkspecs/$template install -m 0644 ${WORKDIR}/linux-oe-qmake.conf ${S}/mkspecs/$template/qmake.conf diff --git a/recipes/qmake/qmake2-native.inc b/recipes/qmake/qmake2-native.inc index f84da2ad52..990820066a 100644 --- a/recipes/qmake/qmake2-native.inc +++ b/recipes/qmake/qmake2-native.inc @@ -26,7 +26,7 @@ do_configure() { # Make sure we regenerate all Makefiles find ${S} -name "Makefile" | xargs rm # Install the OE build templates - for template in linux-oe-g++ linux-uclibc-oe-g++ linux-gnueabi-oe-g++ linux-uclibcgnueabi-oe-g++ + for template in linux-oe-g++ linux-uclibc-oe-g++ linux-gnueabi-oe-g++ linux-uclibceabi-oe-g++ do install -d ${S}/mkspecs/$template install -m 0644 ${WORKDIR}/linux-oe-qmake.conf ${S}/mkspecs/$template/qmake.conf diff --git a/recipes/qte/qte-common_2.3.10.inc b/recipes/qte/qte-common_2.3.10.inc index 6f0b1344b3..f24a265bf0 100644 --- a/recipes/qte/qte-common_2.3.10.inc +++ b/recipes/qte/qte-common_2.3.10.inc @@ -116,8 +116,8 @@ do_configure() { > `dirname $f`/`basename $f | sed -e 's,linux-,linux-uclibc-,'` sed -e 's,-linux-,-linux-gnueabi-,g' < $f \ > `dirname $f`/`basename $f | sed -e 's,linux-,linux-gnueabi-,'` - sed -e 's,-linux-,-linux-uclibcgnueabi-,g' < $f \ - > `dirname $f`/`basename $f | sed -e 's,linux-,linux-uclibcgnueabi-,'` + sed -e 's,-linux-,-linux-uclibceabi-,g' < $f \ + > `dirname $f`/`basename $f | sed -e 's,linux-,linux-uclibceabi-,'` done echo yes | ./configure ${EXTRA_OECONF} || die "Configuring qte failed. EXTRA_OECONF was ${EXTRA_OECONF}" } diff --git a/recipes/samba/samba_3.0.34.bb b/recipes/samba/samba_3.0.34.bb index d43c50dcdb..5ef9da5bb0 100644 --- a/recipes/samba/samba_3.0.34.bb +++ b/recipes/samba/samba_3.0.34.bb @@ -4,7 +4,7 @@ require samba-basic.inc SRC_URI += "file://configure.patch;patch=1 \ " SRC_URI_append_linux-uclibc = "file://uclibc-strlcpy-strlcat.patch;patch=1" -SRC_URI_append_linux-uclibcgnueabi = "file://uclibc-strlcpy-strlcat.patch;patch=1" +SRC_URI_append_linux-uclibceabi = "file://uclibc-strlcpy-strlcat.patch;patch=1" PR = "r5" diff --git a/recipes/swfdec/swfdec-gnome_2.26.0.bb b/recipes/swfdec/swfdec-gnome_2.26.0.bb new file mode 100644 index 0000000000..2686dda7e9 --- /dev/null +++ b/recipes/swfdec/swfdec-gnome_2.26.0.bb @@ -0,0 +1,12 @@ +DESCRIPTION = "flash plugin" +LICENSE = "GPL" + +DEPENDS = "gtk+ gconf swfdec" + +inherit gnome pkgconfig + +do_configure_prepend() { + sed -i -e 's/swfdec-$SWFDEC_MAJORMINOR/swfdec/g' configure.ac + sed -i -e 's/swfdec-gtk-$SWFDEC_MAJORMINOR/swfdec-gtk/g' configure.ac +} + diff --git a/recipes/tasks/task-cli-tools-python.bb b/recipes/tasks/task-cli-tools-python.bb new file mode 100644 index 0000000000..7c75084dd0 --- /dev/null +++ b/recipes/tasks/task-cli-tools-python.bb @@ -0,0 +1,12 @@ +DESCRIPTION = "A set of python-based command line tools" +SECTION = "console" +LICENSE = "MIT" +PV = "1.0" +PR = "r8" + +inherit task + +RDEPENDS_${PN} = "\ + mickeydbus \ + mickeyterm \ +" diff --git a/recipes/tasks/task-cli-tools.bb b/recipes/tasks/task-cli-tools.bb index e05fa398b7..0110a8d9b0 100644 --- a/recipes/tasks/task-cli-tools.bb +++ b/recipes/tasks/task-cli-tools.bb @@ -1,12 +1,12 @@ -DESCRIPTION = "A set of command line tools, python tools-based tools, debug tools" +DESCRIPTION = "A set of command line tools useful for debugging" SECTION = "console" LICENSE = "MIT" PV = "1.0" -PR = "r7" +PR = "r8" inherit task -PACKAGES += "${PN}-debug ${PN}-python" +PACKAGES += "${PN}-debug" RDEPENDS_${PN} = "\ dosfstools \ @@ -34,8 +34,3 @@ RDEPENDS_${PN}-debug = "\ s3c64xx-gpio \ strace \ " - -RDEPENDS_${PN}-python = "\ - mickeydbus \ - mickeyterm \ -" diff --git a/recipes/tasks/task-sdk-bare.bb b/recipes/tasks/task-sdk-bare.bb index 85d362612f..9c78cfa45d 100644 --- a/recipes/tasks/task-sdk-bare.bb +++ b/recipes/tasks/task-sdk-bare.bb @@ -23,7 +23,7 @@ GLIBC_PKGS = "\ LIBC_PKGS_linux = "${GLIBC_PKGS}" LIBC_PKGS_linux-gnueabi = "${GLIBC_PKGS}" LIBC_PKGS_linux-uclibc = "uclibc uclibc-dev uclibc-thread-db" -LIBC_PKGS_linux-uclibcgnueabi = "uclibc uclibc-dev uclibc-thread-db" +LIBC_PKGS_linux-uclibceabi = "uclibc uclibc-dev uclibc-thread-db" RDEPENDS_${PN} = "\ ${LIBC_PKGS} \ diff --git a/recipes/ti/files/gstreamer-ti-tracker-824.patch b/recipes/ti/files/gstreamer-ti-tracker-824.patch index 852e60adbc..634fa4aaf6 100644 --- a/recipes/ti/files/gstreamer-ti-tracker-824.patch +++ b/recipes/ti/files/gstreamer-ti-tracker-824.patch @@ -1,6 +1,15 @@ -diff -uNr ticodecplugin/src/gstticodecplugin_omap3530.cfg ticodecplugin.new/src/gstticodecplugin_omap3530.cfg ---- ticodecplugin/src/gstticodecplugin_omap3530.cfg 2009-06-10 17:29:59.000000000 -0500 -+++ ticodecplugin.new/src/gstticodecplugin_omap3530.cfg 2009-08-07 16:17:24.000000000 -0500 +--- ticodecplugin/ChangeLog ++++ ticodecplugin.new/ChangeLog +@@ -1,3 +1,7 @@ ++2009-08-14 Don Darling, Texas Instruments, Inc. ++ * src/{gstticodecplugin_omap3530.cfg,gstticodecs_omap3530.c}: ++ Update OMAP3530 Support to use DVSDK 3.00.00.40. ++ + 2009-07-28 Brijesh Singh, Texas Instruments, Inc. + * src/{gstticircbuffer.c}: + Fix potential memory leak in circular buffer when accel framecopy flag is +--- ticodecplugin/src/gstticodecplugin_omap3530.cfg ++++ ticodecplugin.new/src/gstticodecplugin_omap3530.cfg @@ -12,8 +12,6 @@ * */ @@ -10,7 +19,7 @@ diff -uNr ticodecplugin/src/gstticodecplugin_omap3530.cfg ticodecplugin.new/src/ /* Load the Codec Engine 'Operating System Abstraction Layer' */ var osalGlobal = xdc.useModule('ti.sdo.ce.osal.Global'); -@@ -27,21 +25,15 @@ +@@ -27,31 +25,20 @@ ipc.commType = ipc.COMM_DSPLINK; /* * ======== Engine Configuration ======== */ @@ -31,6 +40,19 @@ diff -uNr ticodecplugin/src/gstticodecplugin_omap3530.cfg ticodecplugin.new/src/ + "ti.sdo.server.cs" ); +-var encpath = "" + java.lang.System.getenv("ENCODE_COMBO"); +-if (encpath != "" && encpath != "null") { +- encEngine.server = java.lang.System.getenv("ENCODE_COMBO"); +-} +- +-var decpath = "" + java.lang.System.getenv("DECODE_COMBO"); +-if (decpath != "" && decpath != "null") { +- decEngine.server = java.lang.System.getenv("DECODE_COMBO"); ++var combopath = "" + java.lang.System.getenv("CODEC_SERVER"); ++if (combopath != "" && combopath != "null") { ++ demoEngine.server = java.lang.System.getenv("CODEC_SERVER"); + } + /* Load support for the DMAI module */ var DMAI = xdc.loadPackage('ti.sdo.dmai'); @@ -39,9 +61,8 @@ diff -uNr ticodecplugin/src/gstticodecplugin_omap3530.cfg ticodecplugin.new/src/ -var SDMA = xdc.useModule("ti.sdo.linuxutils.sdma.SDMA"); +var SCPY = xdc.useModule('ti.sdo.fc.scpy.SCPY'); +var SDMA = xdc.useModule('ti.sdo.linuxutils.sdma.SDMA'); -diff -uNr ticodecplugin/src/gstticodecs_omap3530.c ticodecplugin.new/src/gstticodecs_omap3530.c ---- ticodecplugin/src/gstticodecs_omap3530.c 2009-06-10 17:29:59.000000000 -0500 -+++ ticodecplugin.new/src/gstticodecs_omap3530.c 2009-08-07 16:17:24.000000000 -0500 +--- ticodecplugin/src/gstticodecs_omap3530.c ++++ ticodecplugin.new/src/gstticodecs_omap3530.c @@ -22,8 +22,7 @@ #include "gstticodecs.h" @@ -52,7 +73,7 @@ diff -uNr ticodecplugin/src/gstticodecs_omap3530.c ticodecplugin.new/src/gsttico /* NULL terminated list of speech decoders in the engine to use in the demo */ GstTICodec gst_ticodec_codecs[] = { -@@ -32,59 +31,55 @@ +@@ -32,59 +31,55 @@ GstTICodec gst_ticodec_codecs[] = { { "AAC Audio Decoder", /* String name of codec used by plugin */ "aachedec", /* String name of codec used by CE */ @@ -123,3 +144,4 @@ diff -uNr ticodecplugin/src/gstticodecs_omap3530.c ticodecplugin.new/src/gsttico }, { NULL } + diff --git a/recipes/ti/gstreamer-ti_svn.bb b/recipes/ti/gstreamer-ti_svn.bb index 7d13c7186a..59f7046bac 100644 --- a/recipes/ti/gstreamer-ti_svn.bb +++ b/recipes/ti/gstreamer-ti_svn.bb @@ -7,13 +7,13 @@ inherit autotools DEPENDS = "ti-dmai gstreamer gst-plugins-base gst-plugins-good gst-plugins-ugly" # Fetch source from svn repo -SRCREV = "285" +SRCREV = "331" SRC_URI = "svn://gforge.ti.com/svn/gstreamer_ti/trunk;module=gstreamer_ti;proto=https;user=anonymous;pswd='' \ file://gstreamer-ti-tracker-824.patch;patch=1 \ " # Again, no '.' in PWD allowed :( -PR = "r28" +PR = "r32" PV = "svnr${SRCREV}" S = "${WORKDIR}/gstreamer_ti/ti_build/ticodecplugin" @@ -36,6 +36,12 @@ CPPFLAGS_append = " -DPlatform_${PLATFORM}" PACKAGE_ARCH = "${MACHINE_ARCH}" +# export codec combo (or server) locations +export HMJCP_COMBO = "${installdir}/codec-combo/hmjcp.accel" +export CODEC_SERVER = "${installdir}/codec-combo/cs.x64P" +export ENCODE_COMBO = "${installdir}/codec-combo/encodeCombo.x64P" +export DECODE_COMBO = "${installdir}/codec-combo/decodeCombo.x64P" + do_install_prepend () { # install gstreamer demo scripts install -d ${D}/${installdir}/gst diff --git a/recipes/uclibc/uclibc.inc b/recipes/uclibc/uclibc.inc index 2ed7d82378..88f62fa557 100644 --- a/recipes/uclibc/uclibc.inc +++ b/recipes/uclibc/uclibc.inc @@ -146,12 +146,13 @@ do_configure() { sed -i -e '/CONFIG_ARM_EABI/d' ${S}/.config - if [ "${TARGET_OS}" = "linux-gnueabi" -o "${TARGET_OS}" = "linux-uclibcgnueabi" ]; then - echo "CONFIG_ARM_EABI=y" >> ${S}/.config - else - echo "# CONFIG_ARM_EABI is not set" >> ${S}/.config + if [ `echo ${TARGET_ARCH} | grep -e '^arm'` ]; then + if [ `echo ${TARGET_OS} | grep -e 'eabi$'` ]; then + echo "CONFIG_ARM_EABI=y" >> ${S}/.config + else + echo "# CONFIG_ARM_EABI is not set" >> ${S}/.config + fi fi - yes '' | oe_runmake oldconfig } diff --git a/recipes/util-linux-ng/util-linux-ng_2.14.bb b/recipes/util-linux-ng/util-linux-ng_2.14.bb index d7eafd3602..7385324fdb 100644 --- a/recipes/util-linux-ng/util-linux-ng_2.14.bb +++ b/recipes/util-linux-ng/util-linux-ng_2.14.bb @@ -6,6 +6,6 @@ SRC_URI += "file://util-linux-ng-uclibc-versionsort.patch;patch=1 \ file://util-linux-ng-replace-siginterrupt.patch;patch=1 \ " LDFLAGS_append_linux-uclibc = " -lintl" -LDFLAGS_append_linux-uclibcgnueabi = " -lintl " +LDFLAGS_append_linux-uclibceabi = " -lintl " LDFLAGS_append_uclinux-uclibc = " -lintl" diff --git a/recipes/wpa-supplicant/wpa-supplicant-0.6.7/action_wpa.sh b/recipes/wpa-supplicant/wpa-supplicant-0.6.7/action_wpa.sh new file mode 100755 index 0000000000..205ca65542 --- /dev/null +++ b/recipes/wpa-supplicant/wpa-supplicant-0.6.7/action_wpa.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +# Action script to enable/disable wpa-roam interfaces in reaction to +# pm-action or ifplugd events. +# +# Copyright: Copyright (c) 2008, Kel Modderman <kel@otaku42.de> +# License: GPL-2 +# + +PATH=/sbin:/usr/sbin:/bin:/usr/bin + +if [ ! -x /sbin/wpa_action ]; then + exit 0 +fi + +SELF=action_wpa +COMMAND= +IFPLUGD_IFACE= + +# pm-action(8) - <action> <suspend method> +# +# On suspend|hibernate, disconnect any wpa-roam managed interfaces, +# reconnect it on resume. + +case "${1}" in + suspend|hibernate) + COMMAND=disconnect + ;; + resume|thaw) + COMMAND=reconnect + ;; +esac + +if [ -z "$COMMAND" ]; then + # ifplugd(8) - <iface> <action> + # + # If an ifplugd managed interface is brought up, disconnect any + # wpa-roam managed interfaces so that only one "roaming" interface + # remains active on the system. + + IFPLUGD_IFACE="${1}" + + case "${2}" in + up) + COMMAND=disconnect + ;; + down) + COMMAND=reconnect + ;; + *) + echo "${SELF}: unknown $0 arguments: ${@}" >&2 + exit 1 + ;; + esac +fi + +if [ -z "$COMMAND" ]; then + echo "${SELF}: unknown arguments: ${@}" >&2 + exit 1 +fi + +for CTRL in /var/run/wpa_supplicant/*; do + [ -S "${CTRL}" ] || continue + + IFACE="${CTRL#/var/run/wpa_supplicant/}" + + wpa_action "${IFACE}" check || continue + + if [ "${IFPLUGD_IFACE}" ] && [ "${IFPLUGD_IFACE}" = "${IFACE}" ]; then + # if ifplugd is managing this interface (not likely but..) + # do nothing + continue + fi + + wpa_cli -i "${IFACE}" "${COMMAND}" +done diff --git a/recipes/wpa-supplicant/wpa-supplicant-0.6.7/functions.sh b/recipes/wpa-supplicant/wpa-supplicant-0.6.7/functions.sh new file mode 100755 index 0000000000..0baa101925 --- /dev/null +++ b/recipes/wpa-supplicant/wpa-supplicant-0.6.7/functions.sh @@ -0,0 +1,1080 @@ +#!/bin/sh + +##################################################################### +## Purpose +# This file contains common shell functions used by scripts of the +# wpasupplicant package to allow ifupdown to manage wpa_supplicant. +# It also contains some functions used by wpa_action(8) that allow +# ifupdown to be managed by wpa_cli(8) action events. +# +# This file is provided by the wpasupplicant package. + +##################################################################### +# Copyright (C) 2006 - 2008 Debian/Ubuntu wpasupplicant Maintainers +# <pkg-wpa-devel@lists.alioth.debian.org> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# On Debian GNU/Linux systems, the text of the GPL license can be +# found in /usr/share/common-licenses/GPL. + +##################################################################### +## global variables +# wpa_supplicant variables +WPA_SUP_BIN="/sbin/wpa_supplicant" +WPA_SUP_PNAME="wpa_supplicant" +WPA_SUP_PIDFILE="/var/run/wpa_supplicant.${WPA_IFACE}.pid" +#WPA_SUP_LOGFILE="/var/log/wpa_supplicant.${WPA_IFACE}.log" +WPA_SUP_LOGFILE="syslog" + +# wpa_cli variables +WPA_CLI_BIN="/sbin/wpa_cli" +WPA_CLI_PNAME="wpa_cli" +WPA_CLI_PIDFILE="/var/run/wpa_action.${WPA_IFACE}.pid" +WPA_CLI_LOGFILE="/var/log/wpa_action.${WPA_IFACE}.log" +WPA_CLI_TIMESTAMP="/var/run/wpa_action.${WPA_IFACE}.timestamp" +WPA_CLI_IFUPDOWN="/var/run/wpa_action.${WPA_IFACE}.ifupdown" + +# sendsigs omission interface, present in initscripts (>= 2.86.ds1-48) +if [ -d /lib/init/rw/sendsigs.omit.d/ ]; then + # Debian + WPA_SUP_OMIT_PIDFILE="/lib/init/rw/sendsigs.omit.d/wpasupplicant.wpa_supplicant.${WPA_IFACE}.pid" + WPA_CLI_OMIT_PIDFILE="/lib/init/rw/sendsigs.omit.d/wpasupplicant.wpa_action.${WPA_IFACE}.pid" +elif [ -d /var/run/sendsigs.omit.d/ ]; then + # Ubuntu, see https://launchpad.net/bugs/181541 for status + WPA_SUP_OMIT_PIDFILE="/var/run/sendsigs.omit.d/wpasupplicant.wpa_supplicant.${WPA_IFACE}.pid" + WPA_CLI_OMIT_PIDFILE="/var/run/sendsigs.omit.d/wpasupplicant.wpa_action.${WPA_IFACE}.pid" +else + WPA_SUP_OMIT_PIDFILE= + WPA_CLI_OMIT_PIDFILE= +fi + +# default ctrl_interface socket directory +if [ -z "$WPA_CTRL_DIR" ]; then + WPA_CTRL_DIR="/var/run/wpa_supplicant" +fi + +# verbosity variables +if [ -n "$IF_WPA_VERBOSITY" ] || [ "$VERBOSITY" = "1" ]; then + TO_NULL="/dev/stdout" + DAEMON_VERBOSITY="--verbose" +else + TO_NULL="/dev/null" + DAEMON_VERBOSITY="--quiet" +fi + +##################################################################### +## wpa_cli wrapper +# Path to common ctrl_interface socket and iface supplied. +# NB: WPA_CTRL_DIR cannot be used for interactive commands, it is +# set only in the environment that wpa_cli provides when processing +# action events. +# +wpa_cli () { + "$WPA_CLI_BIN" -p "$WPA_CTRL_DIR" -i "$WPA_IFACE" "$@" + + return "$?" +} + +##################################################################### +## verbose and stderr message wrapper +# Ensures a standard and easily identifiable message is printed by +# scripts using this function library. +# +# verbose To stdout when IF_WPA_VERBOSITY or VERBOSITY is true +# +# action Same as verbose but without newline +# Useful for allowing wpa_cli commands to echo result +# value of 'OK' or 'FAILED' +# +# stderr Echo warning or error messages to stderr +# +# NB: when called by wpa_action, there is no redirection (verbose) +# +wpa_msg () { + if [ -n "$WPA_ACTION" ]; then + shift + echo "wpa_action: $@" + return + fi + + case "$1" in + "verbose") + shift + echo "$WPA_SUP_PNAME: $@" >$TO_NULL + ;; + "action") + shift + echo -n "$WPA_SUP_PNAME: $@ -- " >$TO_NULL + ;; + "stderr") + shift + echo "$WPA_SUP_PNAME: $@" >/dev/stderr + ;; + *) + ;; + esac +} + +##################################################################### +## validate daemon pid files +# Test daemon process ID files via start-stop-daemon with a signal 0 +# given the exec binary and pidfile location. +# +# $1 daemon +# $2 pidfile +# +# Returns true when pidfile exists, the process ID exists _and_ was +# created by the exec binary. +# +# If the test fails, but the pidfile exists, it is stale +# +test_daemon_pidfile () { + local DAEMON + local PIDFILE + + if [ -n "$1" ]; then + DAEMON="$1" + fi + + if [ -f "$2" ]; then + PIDFILE="$2" + fi + + if [ -n "$DAEMON" ] && [ -f "$PIDFILE" ]; then + if start-stop-daemon --stop --quiet --signal 0 \ + --exec "$DAEMON" --pidfile "$PIDFILE"; then + return 0 + else + rm -f "$PIDFILE" + return 1 + fi + else + return 1 + fi +} + +# validate wpa_supplicant pidfile +test_wpa_supplicant () { + test_daemon_pidfile "$WPA_SUP_BIN" "$WPA_SUP_PIDFILE" +} + +# validate wpa_cli pidfile +test_wpa_cli () { + test_daemon_pidfile "$WPA_CLI_BIN" "$WPA_CLI_PIDFILE" +} + +##################################################################### +## daemonize wpa_supplicant +# Start wpa_supplicant via start-stop-dameon with all required +# options. Will start if environment variable WPA_SUP_CONF is present +# +# Required options: +# -B dameonize/background process +# -D driver backend ('wext' if none given) +# -P process ID file +# -C path to ctrl_interface socket directory +# +# Optional options: +# -c configuration file +# -W wait for wpa_cli to attach to ctrl_interface socket +# -b bridge interface name +# -f path to log file +# +init_wpa_supplicant () { + [ -n "$WPA_SUP_CONF" ] || return 0 + + local WPA_SUP_OPTIONS + + if [ -n "$WPA_ACTION_SCRIPT" ]; then + if [ -x "$WPA_ACTION_SCRIPT" ]; then + WPA_SUP_OPTIONS="-W -B -P $WPA_SUP_PIDFILE -i $WPA_IFACE" + wpa_msg verbose "wait for wpa_cli to attach" + else + wpa_msg stderr "action script \"$WPA_ACTION_SCRIPT\" not executable" + return 1 + fi + else + WPA_SUP_OPTIONS="-B -P $WPA_SUP_PIDFILE -i $WPA_IFACE" + fi + + if [ -n "$IF_WPA_BRIDGE" ]; then + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -b $IF_WPA_BRIDGE" + wpa_msg verbose "wpa-bridge $IF_WPA_BRIDGE" + fi + + if [ -n "$IF_WPA_DRIVER" ]; then + wpa_msg verbose "wpa-driver $IF_WPA_DRIVER" + case "$IF_WPA_DRIVER" in + hostap|ipw|madwifi|ndiswrapper) + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -D wext" + wpa_msg stderr "\"$IF_WPA_DRIVER\" wpa-driver is unsupported" + wpa_msg stderr "using \"wext\" wpa-driver instead ..." + ;; + *) + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -D $IF_WPA_DRIVER" + ;; + esac + else + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -D wext" + wpa_msg verbose "using default driver type: wpa-driver wext" + fi + + if [ -n "$IF_WPA_DEBUG_LEVEL" ]; then + case "$IF_WPA_DEBUG_LEVEL" in + 3) + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -t -ddd" + ;; + 2) + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -t -dd" + ;; + 1) + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -t -d" + ;; + 0) + # wpa_supplicant default verbosity + ;; + -1) + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -q" + ;; + -2) + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -qq" + ;; + esac + wpa_msg verbose "using debug level: $IF_WPA_DEBUG_LEVEL" + else + # log warnings only by default + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -q" + fi + + if [ -n "$IF_WPA_LOGFILE" ]; then + # custom log file + WPA_SUP_LOGFILE="$IF_WPA_LOGFILE" + wpa_msg verbose "logging to $IF_WPA_LOGFILE" + fi + + if [ "$WPA_SUP_LOGFILE" = syslog ]; then + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -s" + elif [ -d "${WPA_SUP_LOGFILE%/*}" ]; then + WPA_SUP_OPTIONS="$WPA_SUP_OPTIONS -f $WPA_SUP_LOGFILE" + else + wpa_msg stderr "unable to log output to $WPA_SUP_LOGFILE" + fi + + wpa_msg verbose "$WPA_SUP_BIN $WPA_SUP_OPTIONS $WPA_SUP_CONF" + + start-stop-daemon --start --oknodo $DAEMON_VERBOSITY \ + --name $WPA_SUP_PNAME --startas $WPA_SUP_BIN --pidfile $WPA_SUP_PIDFILE \ + -- $WPA_SUP_OPTIONS $WPA_SUP_CONF + + if [ "$?" -ne 0 ]; then + wpa_msg stderr "$WPA_SUP_BIN daemon failed to start" + return 1 + fi + + if [ -n "$WPA_SUP_OMIT_PIDFILE" ]; then + local WPA_PIDFILE_WAIT + local MAX_WPA_PIDFILE_WAIT + WPA_PIDFILE_WAIT="0" + MAX_WPA_PIDFILE_WAIT="5" + until [ -s "$WPA_SUP_PIDFILE" ]; do + if [ "$WPA_PIDFILE_WAIT" -ge "$MAX_WPA_PIDFILE_WAIT" ]; then + wpa_msg stderr "timed out waiting for creation of $WPA_SUP_PIDFILE" + return 1 + else + wpa_msg verbose "waiting for \"$WPA_SUP_PIDFILE\": " \ + "$WPA_PIDFILE_WAIT (max. $MAX_WPA_PIDFILE_WAIT)" + fi + + WPA_PIDFILE_WAIT=$(($WPA_PIDFILE_WAIT + 1)) + sleep 1 + done + wpa_msg verbose "creating sendsigs omission pidfile: $WPA_SUP_OMIT_PIDFILE" + cat "$WPA_SUP_PIDFILE" > "$WPA_SUP_OMIT_PIDFILE" + else + wpa_msg verbose "sendsigs omission pidfile not created" + fi + + local WPA_SOCKET_WAIT + local MAX_WPA_SOCKET_WAIT + WPA_SOCKET_WAIT="0" + MAX_WPA_SOCKET_WAIT="5" + until [ -S "$WPA_CTRL_DIR/$WPA_IFACE" ]; do + if [ "$WPA_SOCKET_WAIT" -ge "$MAX_WPA_SOCKET_WAIT" ]; then + wpa_msg stderr "ctrl_interface socket not found at $WPA_CTRL_DIR/$WPA_IFACE" + return 1 + else + wpa_msg verbose "waiting for \"$WPA_CTRL_DIR/$WPA_IFACE\": " \ + "$WPA_SOCKET_WAIT (max. $MAX_WPA_SOCKET_WAIT)" + fi + + WPA_SOCKET_WAIT=$(($WPA_SOCKET_WAIT + 1)) + sleep 1 + done + + wpa_msg verbose "ctrl_interface socket located at $WPA_CTRL_DIR/$WPA_IFACE" +} + +##################################################################### +## stop wpa_supplicant process +# Kill wpa_supplicant via start-stop-daemon, given the location of +# the pidfile or ctrl_interface socket path and interface name +# +kill_wpa_supplicant () { + test_wpa_supplicant || return 0 + + wpa_msg verbose "terminating $WPA_SUP_PNAME daemon via pidfile $WPA_SUP_PIDFILE" + + start-stop-daemon --stop --oknodo $DAEMON_VERBOSITY \ + --exec $WPA_SUP_BIN --pidfile $WPA_SUP_PIDFILE + + if [ -f "$WPA_SUP_PIDFILE" ]; then + rm -f "$WPA_SUP_PIDFILE" + fi + + if [ -f "$WPA_SUP_OMIT_PIDFILE" ]; then + wpa_msg verbose "removing $WPA_SUP_OMIT_PIDFILE" + rm -f "$WPA_SUP_OMIT_PIDFILE" + fi +} + +##################################################################### +## reload wpa_supplicant process +# Sending a HUP signal causes wpa_supplicant to reparse its +# configuration file +# +reload_wpa_supplicant () { + if test_wpa_supplicant; then + wpa_msg verbose "reloading wpa_supplicant configuration file via HUP signal" + start-stop-daemon --stop --signal HUP \ + --name "$WPA_SUP_PNAME" --pidfile "$WPA_SUP_PIDFILE" + else + wpa_msg verbose "cannot $WPA_ACTION, $WPA_SUP_PIDFILE does not exist" + fi +} + +##################################################################### +## daemonize wpa_cli and action script +# If environment variable WPA_ACTION_SCRIPT is present, wpa_cli will +# be spawned via start-stop-daemon +# +# Required options: +# -a action script => wpa_action +# -P process ID file +# -B background process +# +init_wpa_cli () { + [ -n "$WPA_ACTION_SCRIPT" ] || return 0 + + local WPA_CLI_OPTIONS + WPA_CLI_OPTIONS="-B -P $WPA_CLI_PIDFILE -i $WPA_IFACE" + + wpa_msg verbose "$WPA_CLI_BIN $WPA_CLI_OPTIONS -p $WPA_CTRL_DIR -a $WPA_ACTION_SCRIPT" + + start-stop-daemon --start --oknodo $DAEMON_VERBOSITY \ + --name $WPA_CLI_PNAME --startas $WPA_CLI_BIN --pidfile $WPA_CLI_PIDFILE \ + -- $WPA_CLI_OPTIONS -p $WPA_CTRL_DIR -a $WPA_ACTION_SCRIPT + + if [ "$?" -ne 0 ]; then + wpa_msg stderr "$WPA_CLI_BIN daemon failed to start" + return 1 + fi + + if [ -n "$WPA_CLI_OMIT_PIDFILE" ]; then + local WPA_PIDFILE_WAIT + local MAX_WPA_PIDFILE_WAIT + WPA_PIDFILE_WAIT="0" + MAX_WPA_PIDFILE_WAIT="5" + until [ -s "$WPA_CLI_PIDFILE" ]; do + if [ "$WPA_PIDFILE_WAIT" -ge "$MAX_WPA_PIDFILE_WAIT" ]; then + wpa_msg stderr "timed out waiting for creation of $WPA_CLI_PIDFILE" + return 1 + else + wpa_msg verbose "waiting for \"$WPA_CLI_PIDFILE\": " \ + "$WPA_PIDFILE_WAIT (max. $MAX_WPA_PIDFILE_WAIT)" + fi + + WPA_PIDFILE_WAIT=$(($WPA_PIDFILE_WAIT + 1)) + sleep 1 + done + wpa_msg verbose "creating sendsigs omission pidfile: $WPA_CLI_OMIT_PIDFILE" + cat "$WPA_CLI_PIDFILE" > "$WPA_CLI_OMIT_PIDFILE" + else + wpa_msg verbose "sendsigs omission pidfile not created" + fi +} + +##################################################################### +## stop wpa_cli process +# Kill wpa_cli via start-stop-daemon, given the location of the +# pidfile +# +kill_wpa_cli () { + test_wpa_cli || return 0 + + wpa_msg verbose "terminating $WPA_CLI_PNAME daemon via pidfile $WPA_CLI_PIDFILE" + + start-stop-daemon --stop --oknodo $DAEMON_VERBOSITY \ + --exec $WPA_CLI_BIN --pidfile $WPA_CLI_PIDFILE + + if [ -f "$WPA_CLI_PIDFILE" ]; then + rm -f "$WPA_CLI_PIDFILE" + fi + + if [ -f "$WPA_CLI_OMIT_PIDFILE" ]; then + rm -f "$WPA_CLI_OMIT_PIDFILE" + fi + + if [ -f "$WPA_CLI_TIMESTAMP" ]; then + rm -f "$WPA_CLI_TIMESTAMP" + fi + + if [ -L "$WPA_CLI_IFUPDOWN" ]; then + rm -f "$WPA_CLI_IFUPDOWN" + fi +} + +##################################################################### +## higher level wpa_cli wrapper for variable and set_network commands +# wpa_cli_do <value> <type> <variable> [set_network variable] <desc> +# +# $1 envorinment variable +# $2 data type of variable {raw|ascii} +# $3 wpa_cli variable, if $3 is set_network, shift and take +# set_network subvariable +# $4 wpa-* string as it would appear in interfaces file, enhances +# verbose messages +# +wpa_cli_do () { + if [ -z "$1" ]; then + return 0 + fi + + local WPACLISET_VALUE + local WPACLISET_VARIABLE + local WPACLISET_DESC + + case "$2" in + ascii) + # Double quote + WPACLISET_VALUE="\"$1\"" + ;; + raw|*) + # Provide raw value + WPACLISET_VALUE="$1" + ;; + esac + + case "$3" in + set_network) + if [ -z "$WPA_ID" ]; then + return 1 + fi + shift + WPACLISET_VARIABLE="set_network $WPA_ID $3" + ;; + *) + WPACLISET_VARIABLE="$3" + ;; + esac + + case "$4" in + *-psk|*-passphrase|*-passwd*|*-wep-key*) + WPACLISET_DESC="$4 *****" + ;; + *) + WPACLISET_DESC="$4 $WPACLISET_VALUE" + ;; + esac + + wpa_msg action "$WPACLISET_DESC" + + wpa_cli $WPACLISET_VARIABLE "$WPACLISET_VALUE" >$TO_NULL + + if [ "$?" -ne 0 ]; then + wpa_msg stderr "$WPACLISET_DESC failed!" + fi +} + +##################################################################### +## check value data type in plaintext or hex +# returns 0 if input consists of hexadecimal digits only, 1 otherwise +# +ishex () { + if [ -z "$1" ]; then + return 0 + fi + + case "$1" in + *[!0-9a-fA-F]*) + # plaintext + return 1 + ;; + *) + # hexadecimal + return 0 + ;; + esac +} + +##################################################################### +## sanity check and set psk|passphrase +# Warn about strange psk|passphrase values +# +# $1 psk or passphrase value +# +# If psk is surrounded by quotes strip them. +# +# If psk contains all hexadecimal characters and string length is 64: +# is 256bit hexadecimal +# else: +# is plaintext +# +# plaintext passphrases must be 8 - 63 characters in length +# 256-bit hexadecimal key must be 64 characters in length +# +wpa_key_check_and_set () { + if [ "$#" -ne 3 ]; then + return 0 + fi + + local KEY + local KEY_LEN + local KEY_TYPE + local ENC_TYPE + + case "$1" in + '"'*'"') + # Strip surrounding quotation marks + KEY=$(echo -n "$1" | sed 's/^"//;s/"$//') + ;; + *) + KEY="$1" + ;; + esac + + KEY_LEN="${#KEY}" + + case "$2" in + wep_key*) + ENC_TYPE="WEP" + ;; + psk) + ENC_TYPE="WPA" + ;; + *) + return 0 + ;; + esac + + if [ "$ENC_TYPE" = "WEP" ]; then + if ishex "$KEY"; then + case "$KEY_LEN" in + 10|26|32|58) + # 64/128/152/256-bit WEP + KEY_TYPE="raw" + ;; + *) + KEY_TYPE="ascii" + ;; + esac + else + KEY_TYPE="ascii" + fi + + if [ "$KEY_TYPE" = "ascii" ]; then + if [ "$KEY_LEN" -lt "5" ]; then + wpa_msg stderr "WARNING: plaintext or ascii WEP key has $KEY_LEN characters," + wpa_msg stderr "it must have at least 5 to be valid." + fi + fi + elif [ "$ENC_TYPE" = "WPA" ]; then + if ishex "$KEY"; then + case "$KEY_LEN" in + 64) + # 256-bit WPA + KEY_TYPE="raw" + ;; + *) + KEY_TYPE="ascii" + ;; + esac + else + KEY_TYPE="ascii" + fi + + if [ "$KEY_TYPE" = "ascii" ]; then + if [ "$KEY_LEN" -lt "8" ] || [ "$KEY_LEN" -gt "63" ]; then + wpa_msg stderr "WARNING: plaintext or ascii WPA key has $KEY_LEN characters," + wpa_msg stderr "it must have between 8 and 63 to be valid." + wpa_msg stderr "If the WPA key is a 256-bit hexadecimal key, it must have" + wpa_msg stderr "exactly 64 characters." + fi + fi + fi + + wpa_cli_do "$KEY" "$KEY_TYPE" set_network "$2" "$3" +} + +##################################################################### +## formulate a usable configuration from interfaces(5) wpa- lines +# A series of wpa_cli commands corresponding to environment variables +# created as a result of wpa- lines in an interfaces stanza. +# +# NB: no-act when roaming daemon is used (to avoid prematurely +# attaching to ctrl_interface socket) +# +conf_wpa_supplicant () { + if [ -n "$WPA_ACTION_SCRIPT" ]; then + return 0 + fi + + if [ "$IF_WPA_DRIVER" = "wired" ]; then + IF_WPA_AP_SCAN="0" + wpa_msg verbose "forcing ap_scan=0 (required for wired IEEE8021X auth)" + fi + + if [ -n "$IF_WPA_ESSID" ]; then + # #403316, be similar to wireless tools + IF_WPA_SSID="$IF_WPA_ESSID" + fi + + wpa_cli_do "$IF_WPA_AP_SCAN" raw \ + ap_scan wpa-ap-scan + + wpa_cli_do "$IF_WPA_PREAUTHENTICATE" raw \ + preauthenticate wpa-preauthenticate + + if [ -n "$IF_WPA_SSID" ] || [ "$IF_WPA_DRIVER" = "wired" ] || \ + [ -n "$IF_WPA_KEY_MGMT" ]; then + + case "$IF_WPA_SSID" in + '"'*'"') + IF_WPA_SSID=$(echo -n "$IF_WPA_SSID" | sed 's/^"//;s/"$//') + ;; + *) + ;; + esac + + WPA_ID=$(wpa_cli add_network) + + wpa_msg verbose "configuring network block -- $WPA_ID" + + wpa_cli_do "$IF_WPA_SSID" ascii \ + set_network ssid wpa-ssid + + wpa_cli_do "$IF_WPA_PRIORITY" raw \ + set_network priority wpa-priority + + wpa_cli_do "$IF_WPA_BSSID" raw \ + set_network bssid wpa-bssid + + if [ -s "$IF_WPA_PSK_FILE" ]; then + IF_WPA_PSK=$(cat "$IF_WPA_PSK_FILE") + fi + + # remain compat with wpa-passphrase-file + if [ -s "$IF_WPA_PASSPHRASE_FILE" ]; then + IF_WPA_PSK=$(cat "$IF_WPA_PASSPHRASE_FILE") + fi + + # remain compat with wpa-passphrase + if [ -n "$IF_WPA_PASSPHRASE" ]; then + IF_WPA_PSK="$IF_WPA_PASSPHRASE" + fi + + if [ -n "$IF_WPA_PSK" ]; then + wpa_key_check_and_set "$IF_WPA_PSK" \ + psk wpa-psk + fi + + wpa_cli_do "$IF_WPA_PAIRWISE" raw \ + set_network pairwise wpa-pairwise + + wpa_cli_do "$IF_WPA_GROUP" raw \ + set_network group wpa-group + + wpa_cli_do "$IF_WPA_MODE" raw \ + set_network mode wpa-mode + + wpa_cli_do "$IF_WPA_FREQUENCY" raw \ + set_network frequency wpa-frequency + + wpa_cli_do "$IF_WPA_KEY_MGMT" raw \ + set_network key_mgmt wpa-key-mgmt + + wpa_cli_do "$IF_WPA_PROTO" raw \ + set_network proto wpa-proto + + wpa_cli_do "$IF_WPA_AUTH_ALG" raw \ + set_network auth_alg wpa-auth-alg + + wpa_cli_do "$IF_WPA_SCAN_SSID" raw \ + set_network scan_ssid wpa-scan-ssid + + wpa_cli_do "$IF_WPA_IDENTITY" ascii \ + set_network identity wpa-identity + + wpa_cli_do "$IF_WPA_ANONYMOUS_IDENTITY" ascii \ + set_network anonymous_identity wpa-anonymous-identity + + wpa_cli_do "$IF_WPA_EAP" raw \ + set_network eap wpa-eap + + wpa_cli_do "$IF_WPA_EAPPSK" raw \ + set_network eappsk wpa-eappsk + + wpa_cli_do "$IF_WPA_NAI" ascii \ + set_network nai wpa-nai + + wpa_cli_do "$IF_WPA_PASSWORD" ascii \ + set_network password wpa-password + + wpa_cli_do "$IF_WPA_CA_CERT" ascii \ + set_network ca_cert wpa-ca-cert + + wpa_cli_do "$IF_WPA_CA_PATH" ascii \ + set_network ca_path wpa-ca-path + + wpa_cli_do "$IF_WPA_CLIENT_CERT" ascii \ + set_network client_cert wpa-client-cert + + wpa_cli_do "$IF_WPA_PRIVATE_KEY" ascii \ + set_network private_key wpa-private-key + + wpa_cli_do "$IF_WPA_PRIVATE_KEY_PASSWD" ascii \ + set_network private_key_passwd wpa-private-key-passwd + + wpa_cli_do "$IF_WPA_DH_FILE" ascii \ + set_network dh_file wpa-dh-file + + wpa_cli_do "$IF_WPA_SUBJECT_MATCH" ascii \ + set_network subject_match wpa-subject-match + + wpa_cli_do "$IF_WPA_ALTSUBJECT_MATCH" ascii \ + set_network altsubject_match wpa-altsubject-match + + wpa_cli_do "$IF_WPA_CA_CERT2" ascii \ + set_network ca_cert2 wpa-ca-cert2 + + wpa_cli_do "$IF_WPA_CA_PATH2" ascii \ + set_network ca_path2 wpa-ca-path2 + + wpa_cli_do "$IF_WPA_CLIENT_CERT2" ascii \ + set_network client_cert2 wpa-client-cert2 + + wpa_cli_do "$IF_WPA_PRIVATE_KEY2" ascii \ + set_network private_key2 wpa-private-key2 + + wpa_cli_do "$IF_WPA_PRIVATE_KEY_PASSWD2" ascii \ + set_network private_key_passwd2 wpa-private-key-passwd2 + + wpa_cli_do "$IF_WPA_DH_FILE2" ascii \ + set_network dh_file2 wpa-dh-file2 + + wpa_cli_do "$IF_WPA_SUBJECT_MATCH2" ascii \ + set_network subject_match2 wpa-subject-match2 + + wpa_cli_do "$IF_WPA_ALTSUBJECT_MATCH2" ascii \ + set_network altsubject_match2 wpa-altsubject-match2 + + wpa_cli_do "$IF_WPA_EAP_METHODS" raw \ + set_network eap_methods wpa-eap-methods + + wpa_cli_do "$IF_WPA_PHASE1" ascii \ + set_network phase1 wpa-phase1 + + wpa_cli_do "$IF_WPA_PHASE2" ascii \ + set_network phase2 wpa-phase2 + + wpa_cli_do "$IF_WPA_PCSC" raw \ + set_network pcsc wpa-pcsc + + wpa_cli_do "$IF_WPA_PIN" ascii \ + set_network pin wpa-pin + + wpa_cli_do "$IF_WPA_ENGINE" raw \ + set_network engine wpa-engine + + wpa_cli_do "$IF_WPA_ENGINE_ID" ascii \ + set_network engine_id wpa-engine-id + + wpa_cli_do "$IF_WPA_KEY_ID" ascii \ + set_network key_id wpa-key-id + + wpa_cli_do "$IF_WPA_EAPOL_FLAGS" raw \ + set_network eapol_flags wpa-eapol-flags + + if [ -n "$IF_WPA_WEP_KEY0" ]; then + wpa_key_check_and_set "$IF_WPA_WEP_KEY0" \ + wep_key0 wpa-wep-key0 + fi + + if [ -n "$IF_WPA_WEP_KEY1" ]; then + wpa_key_check_and_set "$IF_WPA_WEP_KEY1" \ + wep_key1 wpa-wep-key1 + fi + + if [ -n "$IF_WPA_WEP_KEY2" ]; then + wpa_key_check_and_set "$IF_WPA_WEP_KEY2" \ + wep_key2 wpa-wep-key2 + fi + + if [ -n "$IF_WPA_WEP_KEY3" ]; then + wpa_key_check_and_set "$IF_WPA_WEP_KEY3" \ + wep_key3 wpa-wep-key3 + fi + + wpa_cli_do "$IF_WPA_WEP_TX_KEYIDX" raw \ + set_network wep_tx_keyidx wpa-wep-tx-keyidx + + wpa_cli_do "$IF_WPA_PROACTIVE_KEY_CACHING" raw \ + set_network proactive_key_caching wpa-proactive-key-caching + + wpa_cli_do "$IF_WPA_PAC_FILE" ascii \ + set_network pac_file wpa-pac-file + + wpa_cli_do "$IF_WPA_MODE" raw \ + set_network mode wpa-mode + + wpa_cli_do "$IF_WPA_PEERKEY" raw \ + set_network peerkey wpa-peerkey + + wpa_cli_do "$IF_FRAGMENT_SIZE" raw \ + set_network fragment_size wpa-fragment-size + + wpa_cli_do "$IF_WPA_ID_STR" ascii \ + set_network id_str wpa-id-str + + wpa_cli_do "$WPA_ID" raw \ + enable_network "enabling network block" + fi +} + +##################################################################### +## wpa_action basic logging +# Log actions to file +# +wpa_log_init () { + [ -w "$WPA_CLI_LOGFILE" ] || return 0 + + exec >> "$WPA_CLI_LOGFILE" 2>&1 +} + +# log timestamp and wpa_action arguments +wpa_log_action () { + [ -w "$WPA_CLI_LOGFILE" ] || return 0 + + local DATE + + DATE=$(date +"%H:%M:%S %Y-%m-%d") + echo "########## $DATE ##########" + echo "IFACE=$WPA_IFACE ACTION=$WPA_ACTION" +} + +# log wpa_cli environment variables +wpa_log_environment () { + [ -w "$WPA_CLI_LOGFILE" ] || return 0 + + echo "WPA_ID=$WPA_ID WPA_ID_STR=$WPA_ID_STR" + echo "WPA_CTRL_DIR=$WPA_CTRL_DIR" +} + +##################################################################### +## hysteresis checking +# Networking tools such as dhcp clients used with ifupdown can +# synthesize artificial ACTION events, particuarly just after a +# DISCONNECTED/CONNECTED events are experienced in quick succession. +# This can lead to infinite event loops, and in extreme cases has the +# potential to cause system instability. +# +wpa_hysteresis_event () { + local TIME + + TIME=$(date +%s) + echo "$TIME" > "$WPA_CLI_TIMESTAMP" +} + +wpa_hysteresis_check () { + if [ -f "$WPA_CLI_TIMESTAMP" ]; then + local TIME + local TIMESTAMP + local TIMEWAIT + TIME=$(date +%s) + # current time minus 4 second event buffer + TIMEWAIT=$(($TIME-4)) + # get time of last event + TIMESTAMP=$(cat $WPA_CLI_TIMESTAMP) + # compare values, allowing new action to be processed + # only if last action was more than 4 seconds ago + if [ "$TIMEWAIT" -le "$TIMESTAMP" ]; then + echo "Ignoring $WPA_ACTION event, too soon after previous event" + return 1 + fi + fi + + return 0 +} + +##################################################################### +## identify ifupdown files +# Identify ifupdown core files, so that state of the interface can be +# checked. This is the weakest part of the wpa_action roaming scheme, +# it would be _much_ better if stateless ifupdown capabilities were +# a reality. +# +ifupdown_check () { + if [ -e /etc/network/interfaces ]; then + INTERFACES_FILE="/etc/network/interfaces" + else + echo "Cannot locate ifupdown's \"interfaces\" file, $WPA_IFACE will not be configured" + return 1 + fi + + if [ -e /etc/network/run/ifstate ]; then + # debian's ifupdown + IFSTATE_FILE="/etc/network/run/ifstate" + elif [ -e /var/run/network/ifstate ]; then + # ubuntu's + IFSTATE_FILE="/var/run/network/ifstate" + else + echo "Cannot locate ifupdown's \"ifstate\" file, $WPA_IFACE will not be configured" + return 1 + fi + + return 0 +} + +ifupdown_status () { + if grep -s -q "^${WPA_IFACE}=${WPA_LOGICAL_IFACE}" "$IFSTATE_FILE"; then + return 0 + fi + + echo "Interface \"$WPA_IFACE\" failed to establish a connection." + echo "Attempting reassociation..." + return 1 +} + +ifupdown_lock () { + ln -s lock "$WPA_CLI_IFUPDOWN" +} + +ifupdown_locked () { + [ -L "$WPA_CLI_IFUPDOWN" ] && return 0 + + return 1 +} + +ifupdown_unlock () { + rm -f "$WPA_CLI_IFUPDOWN" +} + +##################################################################### +## apply mapping logic and ifup logical interface +# Apply mapping logic via id_str or external mapping script, check +# state of IFACE with respect to ifupdown and ifup logical interaface +# +ifup () { + local WPA_LOGICAL_IFACE + + if [ -z "$IF_WPA_MAPPING_SCRIPT_PRIORITY" ] && [ -n "$WPA_ID_STR" ]; then + WPA_LOGICAL_IFACE="$WPA_ID_STR" + echo "Mapping logical interface via id_str: $WPA_LOGICAL_IFACE" + fi + + if [ -z "$WPA_LOGICAL_IFACE" ] && [ -n "$IF_WPA_MAPPING_SCRIPT" ]; then + echo "Mapping logical interface via wpa-mapping-script: $IF_WPA_MAPPING_SCRIPT" + + local WPA_MAP_STDIN + + WPA_MAP_STDIN=$(set | sed -n 's/^\(IF_WPA_MAP[0-9]*\)=.*/echo \$\1/p') + + if [ -n "$WPA_MAP_STDIN" ]; then + WPA_LOGICAL_IFACE=$(eval "$WPA_MAP_STDIN" | "$IF_WPA_MAPPING_SCRIPT" "$WPA_IFACE") + else + WPA_LOGICAL_IFACE=$("$IF_WPA_MAPPING_SCRIPT" "$WPA_IFACE") + fi + + if [ -n "$WPA_LOGICAL_IFACE" ]; then + echo "Mapping script result: $WPA_LOGICAL_IFACE" + else + echo "Mapping script failed." + fi + fi + + if [ -z "$WPA_LOGICAL_IFACE" ]; then + if [ -n "$IF_WPA_ROAM_DEFAULT_IFACE" ]; then + WPA_LOGICAL_IFACE="$IF_WPA_ROAM_DEFAULT_IFACE" + echo "Using wpa-roam-default-iface: $WPA_LOGICAL_IFACE" + else + WPA_LOGICAL_IFACE="default" + echo "Using fallback logical interface: $WPA_LOGICAL_IFACE" + fi + fi + + if [ -n "$WPA_LOGICAL_IFACE" ]; then + if egrep -q "^iface[[:space:]]+${WPA_LOGICAL_IFACE}[[:space:]]+inet" "$INTERFACES_FILE"; then + : # logical network is defined + else + echo "No network defined for \"$WPA_LOGICAL_IFACE\" in \"$INTERFACES_FILE\"" + echo "Trying to configure the \"default\" network instead ..." + WPA_LOGICAL_IFACE="default" + fi + + echo "ifup $WPA_IFACE=$WPA_LOGICAL_IFACE" + + ifupdown_lock + + if grep -q "^$WPA_IFACE=$WPA_IFACE" "$IFSTATE_FILE"; then + # Force settings over the unconfigured "master" IFACE + /sbin/ifup -v --force "$WPA_IFACE=$WPA_LOGICAL_IFACE" + else + /sbin/ifup -v "$WPA_IFACE=$WPA_LOGICAL_IFACE" + fi + + ifupdown_unlock + else + echo "No suitable logical interface mapping for ifupdown to configure" + fi +} + +##################################################################### +## ifdown IFACE +# Check IFACE state and ifdown as requested. +# +ifdown () { + if grep -q "^$WPA_IFACE" "$IFSTATE_FILE"; then + ifupdown_lock + + echo "ifdown $WPA_IFACE" + /sbin/ifdown -v "$WPA_IFACE" + + ifupdown_unlock + else + echo "Ignoring request to take \"$WPA_IFACE\" down, it is not up" + fi +} + +##################################################################### +## keep IFACE scanning +# After ifdown, the IFACE may be left "down", and inhibits +# wpa_supplicant's ability to continue roaming. +# +# NB: use iproute if present, flushing the IFACE first +# +if_post_down_up () { + if type ip >/dev/null; then + ip addr flush dev "$WPA_IFACE" 2>/dev/null + ip link set "$WPA_IFACE" up + else + ifconfig "$WPA_IFACE" up + fi +} diff --git a/recipes/wpa-supplicant/wpa-supplicant-0.6.7/ifupdown.sh b/recipes/wpa-supplicant/wpa-supplicant-0.6.7/ifupdown.sh new file mode 100755 index 0000000000..3e38fa036c --- /dev/null +++ b/recipes/wpa-supplicant/wpa-supplicant-0.6.7/ifupdown.sh @@ -0,0 +1,172 @@ +#!/bin/sh + +##################################################################### +## Purpose +# This file is executed by ifupdown in pre-up, post-up, pre-down and +# post-down phases of network interface configuration. It allows +# ifup(8), and ifdown(8) to manage wpa_supplicant(8) and wpa_cli(8) +# processes running in daemon mode. +# +# /etc/wpa_supplicant/functions.sh is sourced by this file. +# +# This file is provided by the wpasupplicant package. + +##################################################################### +# Copyright (C) 2006 - 2008 Debian/Ubuntu wpasupplicant Maintainers +# <pkg-wpa-devel@lists.alioth.debian.org> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# On Debian GNU/Linux systems, the text of the GPL license can be +# found in /usr/share/common-licenses/GPL. + +if [ -n "$IF_WPA_MAINT_DEBUG" ]; then + set -x +fi + +# quit if we're called for the loopback +if [ "$IFACE" = lo ]; then + exit 0 +fi + +# allow wpa_supplicant interface to be specified via wpa-iface +# useful for starting wpa_supplicant on one interface of a bridge +if [ -n "$IF_WPA_IFACE" ]; then + WPA_IFACE="$IF_WPA_IFACE" +else + WPA_IFACE="$IFACE" +fi + +# source functions +if [ -f /etc/wpa_supplicant/functions.sh ]; then + . /etc/wpa_supplicant/functions.sh +else + exit 0 +fi + +# quit if executables are not installed +if [ ! -x "$WPA_SUP_BIN" ] || [ ! -x "$WPA_CLI_BIN" ]; then + exit 0 +fi + +do_start () { + if test_wpa_cli; then + # if wpa_action is active for this IFACE, do nothing + ifupdown_locked && exit 0 + + # if the administrator is calling ifup, say something useful + if [ "$PHASE" = "pre-up" ]; then + wpa_msg stderr "wpa_action is managing ifup/ifdown state of $WPA_IFACE" + wpa_msg stderr "execute \`ifdown --force $WPA_IFACE' to stop wpa_action" + fi + exit 1 + elif ! set | grep -q "^IF_WPA"; then + # no wpa- option defined for IFACE, do nothing + exit 0 + fi + + # ensure stale ifupdown_lock marker is purged + ifupdown_unlock + + # preliminary sanity checks for roaming daemon + if [ -n "$IF_WPA_ROAM" ]; then + if [ "$METHOD" != "manual" ]; then + wpa_msg stderr "wpa-roam can only be used with the \"manual\" inet METHOD" + exit 1 + fi + if [ -n "$IF_WPA_MAPPING_SCRIPT" ]; then + if ! type "$IF_WPA_MAPPING_SCRIPT" >/dev/null; then + wpa_msg stderr "wpa-mapping-script \"$IF_WPA_MAPPING_SCRIPT\" is not valid" + exit 1 + fi + fi + if [ -n "$IF_WPA_MAPPING_SCRIPT_PRIORITY" ] && [ -z "$IF_WPA_MAPPING_SCRIPT" ]; then + wpa_msg stderr "\"wpa-mapping-script-priority 1\" is invalid without a wpa-mapping-script" + exit 1 + fi + IF_WPA_CONF="$IF_WPA_ROAM" + WPA_ACTION_SCRIPT="/sbin/wpa_action" + fi + + # master function; determines if ifupdown.sh should do something or not + if [ -n "$IF_WPA_CONF" ] && [ "$IF_WPA_CONF" != "managed" ]; then + if [ ! -s "$IF_WPA_CONF" ]; then + wpa_msg stderr "cannot read contents of $IF_WPA_CONF" + exit 1 + fi + WPA_SUP_CONF_CTRL_DIR=$(sed -n -e 's/[[:space:]]*#.*//g' -e 's/[[:space:]]\+.*$//g' \ + -e 's/^ctrl_interface=\(DIR=\)\?\(.*\)/\2/p' "$IF_WPA_CONF") + if [ -n "$WPA_SUP_CONF_CTRL_DIR" ]; then + WPA_CTRL_DIR="$WPA_SUP_CONF_CTRL_DIR" + WPA_SUP_CONF="-c $IF_WPA_CONF" + else + # specify the default ctrl_interface since none was defined in + # the given IF_WPA_CONF + WPA_SUP_CONF="-c $IF_WPA_CONF -C $WPA_CTRL_DIR" + fi + else + # specify the default ctrl_interface + WPA_SUP_CONF="-C $WPA_CTRL_DIR" + fi +} + +do_stop () { + if test_wpa_cli; then + # if wpa_action is active for this IFACE and calling ifdown, + # do nothing + ifupdown_locked && exit 0 + elif test_wpa_supplicant; then + # wpa_supplicant process exists for this IFACE, but wpa_cli + # process does not. Allow stop mode to kill this process. + : + else + exit 0 + fi +} + +case "$MODE" in + start) + do_start + case "$PHASE" in + pre-up) + kill_wpa_supplicant + init_wpa_supplicant || exit 1 + conf_wpa_supplicant || { kill_wpa_supplicant; exit 1; } + ;; + post-up) + init_wpa_cli || { kill_wpa_supplicant; exit 1; } + ;; + esac + ;; + + stop) + do_stop + case "$PHASE" in + pre-down) + kill_wpa_cli + ;; + post-down) + kill_wpa_supplicant + ;; + *) + wpa_msg stderr "unknown phase: \"$PHASE\"" + exit 1 + ;; + esac + ;; + + *) + wpa_msg stderr "unknown mode: \"$MODE\"" + exit 1 + ;; +esac + +exit 0 diff --git a/recipes/wpa-supplicant/wpa-supplicant-0.6.inc b/recipes/wpa-supplicant/wpa-supplicant-0.6.inc index 05d439f8e2..e3ab3976a9 100644 --- a/recipes/wpa-supplicant/wpa-supplicant-0.6.inc +++ b/recipes/wpa-supplicant/wpa-supplicant-0.6.inc @@ -12,6 +12,7 @@ DEFAULT_PREFERENCE = "-2" SRC_URI = "http://hostap.epitest.fi/releases/wpa_supplicant-${PV}.tar.gz \ file://defconfig-0.6.0-gnutls \ + file://action_wpa.sh \ file://ifupdown.sh \ file://functions.sh" @@ -57,6 +58,7 @@ do_install () { install -d ${D}${sysconfdir}/network/if-down.d/ install -d ${D}${sysconfdir}/wpa_supplicant + install -m 755 ${WORKDIR}/action_wpa.sh ${D}${sysconfdir}/wpa_supplicant/ install -m 755 ${WORKDIR}/ifupdown.sh ${D}${sysconfdir}/wpa_supplicant/ install -m 755 ${WORKDIR}/functions.sh ${D}${sysconfdir}/wpa_supplicant diff --git a/recipes/wpa-supplicant/wpa-supplicant_0.6.7.bb b/recipes/wpa-supplicant/wpa-supplicant_0.6.7.bb index 4712d9ec26..9d9ac6852d 100644 --- a/recipes/wpa-supplicant/wpa-supplicant_0.6.7.bb +++ b/recipes/wpa-supplicant/wpa-supplicant_0.6.7.bb @@ -1,3 +1,3 @@ require wpa-supplicant-0.6.inc -PR = "r4" +PR = "r5" diff --git a/recipes/xorg-app/xinput_1.4.2.bb b/recipes/xorg-app/xinput_1.4.2.bb new file mode 100644 index 0000000000..a95753c1f9 --- /dev/null +++ b/recipes/xorg-app/xinput_1.4.2.bb @@ -0,0 +1,4 @@ +require xorg-app-common.inc + +DESCRIPTION = "a utility to configure and test XInput devices" +DEPENDS += " libxi" diff --git a/recipes/xorg-driver/xf86-input-evdev_2.2.2.bb b/recipes/xorg-driver/xf86-input-evdev_2.2.5.bb index 792909621a..792909621a 100644 --- a/recipes/xorg-driver/xf86-input-evdev_2.2.2.bb +++ b/recipes/xorg-driver/xf86-input-evdev_2.2.5.bb diff --git a/recipes/xorg-driver/xf86-video-fbdev_0.4.1.bb b/recipes/xorg-driver/xf86-video-fbdev_0.4.1.bb new file mode 100644 index 0000000000..ee2ec96eb5 --- /dev/null +++ b/recipes/xorg-driver/xf86-video-fbdev_0.4.1.bb @@ -0,0 +1,6 @@ +require xorg-driver-video.inc +PE = "1" + +DESCRIPTION = "X.Org X server -- fbdev display driver" + +#DEPENDS += " " diff --git a/recipes/xorg-lib/libx11-native_1.2.bb b/recipes/xorg-lib/libx11-native_1.2.bb new file mode 100644 index 0000000000..e7931dcdfd --- /dev/null +++ b/recipes/xorg-lib/libx11-native_1.2.bb @@ -0,0 +1,11 @@ +require libx11_${PV}.bb + +FILESDIR = "${@os.path.dirname(bb.data.getVar('FILE',d,1))}/libx11" + +DEPENDS = "xproto-native xextproto-native libxau-native xtrans-native libxdmcp-native xcmiscproto-native xf86bigfontproto-native kbproto-native inputproto-native bigreqsproto-native util-macros-native" +PROVIDES = "" + +inherit native + +#fake it here for the libtool mess +TARGET_PREFIX = "${TARGET_SYS}-" diff --git a/recipes/xorg-lib/libxext-native_1.0.5.bb b/recipes/xorg-lib/libxext-native_1.0.5.bb new file mode 100644 index 0000000000..25320d9dda --- /dev/null +++ b/recipes/xorg-lib/libxext-native_1.0.5.bb @@ -0,0 +1,8 @@ +require libxext_${PV}.bb + +PROVIDES = "" + +DEPENDS = "libx11-native libxau-native xextproto-native" +PE = "1" + +inherit native diff --git a/recipes/xorg-lib/pixman/nearest-neighbour.patch b/recipes/xorg-lib/pixman/nearest-neighbour.patch new file mode 100644 index 0000000000..29b140faf9 --- /dev/null +++ b/recipes/xorg-lib/pixman/nearest-neighbour.patch @@ -0,0 +1,1040 @@ +From: Siarhei Siamashka <siarhei.siamashka@nokia.com> +Date: Fri, 17 Jul 2009 10:22:23 +0000 (+0300) +Subject: Fastpath for nearest neighbour scaled compositing operations. +X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=pixman.git;a=commitdiff_plain;h=247531c6978725a88fd3706129b9d3e339026f54 + +Fastpath for nearest neighbour scaled compositing operations. + +OVER 8888x8888, OVER 8888x0565, SRC 8888x8888, SRC 8888x0565 +and SRC 0565x0565 cases are supported. +--- + +diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c +index 7f80578..7f3a6ad 100644 +--- a/pixman/pixman-fast-path.c ++++ b/pixman/pixman-fast-path.c +@@ -1261,6 +1261,993 @@ fast_composite_src_scale_nearest (pixman_implementation_t *imp, + } + } + ++/* ++ * Functions, which implement the core inner loops for the nearest neighbour ++ * scaled fastpath compositing operations. The do not need to do clipping ++ * checks, also the loops are unrolled to process two pixels per iteration ++ * for better performance on most CPU architectures (superscalar processors ++ * can issue several operations simultaneously, other processors can hide ++ * instructions latencies by pipelining operations). Unrolling more ++ * does not make much sense because the compiler will start running out ++ * of spare registers soon. ++ */ ++ ++#undef READ ++#undef WRITE ++#define READ(img,x) (*(x)) ++#define WRITE(img,ptr,v) ((*(ptr)) = (v)) ++ ++#define UN8x4_MUL_UN8_ADD_UN8x4_store_r5g6b5(x, a, y) do { \ ++ UN8x4_MUL_UN8_ADD_UN8x4(x, a, y); \ ++ x = CONVERT_8888_TO_0565(x); \ ++ } while (0) ++ ++static void fbCompositeTransformNearestNonrotatedAffineTrivialclipOver_8888x0565 ( ++ pixman_image_t *pSrc, pixman_image_t *pDst, int xSrc, int ySrc, int xDst, int yDst, ++ int width, int height, int32_t vx, int32_t vy, int32_t unit_x, int32_t unit_y) ++{ ++ uint16_t *dstLine; ++ uint32_t *srcFirstLine; ++ uint32_t d; ++ uint32_t s1, s2; ++ uint8_t a1, a2; ++ int w; ++ int x1, x2, y; ++ int32_t orig_vx = vx; ++ ++ uint32_t *src; ++ uint16_t *dst; ++ int srcStride, dstStride; ++ PIXMAN_IMAGE_GET_LINE (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); ++ /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be ++ * transformed from destination space to source space */ ++ PIXMAN_IMAGE_GET_LINE (pSrc, 0, 0, uint32_t, srcStride, srcFirstLine, 1); ++ ++ while (--height >= 0) ++ { ++ dst = dstLine; ++ dstLine += dstStride; ++ ++ y = vy >> 16; ++ vy += unit_y; ++ ++ if ((y < 0) || (y >= pSrc->bits.height)) { ++ continue; ++ } ++ ++ src = srcFirstLine + srcStride * y; ++ ++ w = width; ++ vx = orig_vx; ++ while ((w -= 2) >= 0) ++ { ++ x1 = vx >> 16; ++ vx += unit_x; ++ s1 = READ(pSrc, src + x1); ++ ++ x2 = vx >> 16; ++ vx += unit_x; ++ s2 = READ(pSrc, src + x2); ++ ++ a1 = s1 >> 24; ++ a2 = s2 >> 24; ++ ++ if (a1 == 0xff) ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s1)); ++ else if (s1) { ++ d = CONVERT_0565_TO_0888(READ(pDst, dst)); ++ a1 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4_store_r5g6b5(d, a1, s1); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ ++ if (a2 == 0xff) ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s2)); ++ else if (s2) { ++ d = CONVERT_0565_TO_0888(READ(pDst, dst)); ++ a2 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4_store_r5g6b5(d, a2, s2); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ } ++ if (w & 1) { ++ x1 = vx >> 16; ++ vx += unit_x; ++ s1 = READ(pSrc, src + x1); ++ ++ a1 = s1 >> 24; ++ if (a1 == 0xff) ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s1)); ++ else if (s1) { ++ d = CONVERT_0565_TO_0888(READ(pDst, dst)); ++ a1 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4_store_r5g6b5(d, a1, s1); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ } ++ } ++} ++ ++static void fbCompositeTransformNearestNonrotatedAffineTrivialclipRepeatOver_8888x0565 ( ++ pixman_image_t *pSrc, pixman_image_t *pDst, int xSrc, int ySrc, int xDst, int yDst, ++ int width, int height, int32_t vx, int32_t vy, int32_t unit_x, int32_t unit_y) ++{ ++ uint16_t *dstLine; ++ uint32_t *srcFirstLine; ++ uint32_t d; ++ uint32_t s1, s2; ++ uint8_t a1, a2; ++ int w; ++ int x1, x2, y; ++ int32_t orig_vx = vx; ++ int32_t max_vx, max_vy; ++ ++ uint32_t *src; ++ uint16_t *dst; ++ int srcStride, dstStride; ++ PIXMAN_IMAGE_GET_LINE (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); ++ /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be ++ * transformed from destination space to source space */ ++ PIXMAN_IMAGE_GET_LINE (pSrc, 0, 0, uint32_t, srcStride, srcFirstLine, 1); ++ ++ max_vx = pSrc->bits.width << 16; ++ max_vy = pSrc->bits.height << 16; ++ ++ while (orig_vx < 0) orig_vx += max_vx; ++ while (vy < 0) vy += max_vy; ++ while (orig_vx >= max_vx) orig_vx -= max_vx; ++ while (vy >= max_vy) vy -= max_vy; ++ ++ while (--height >= 0) ++ { ++ dst = dstLine; ++ dstLine += dstStride; ++ ++ y = vy >> 16; ++ vy += unit_y; ++ while (vy >= max_vy) vy -= max_vy; ++ ++ src = srcFirstLine + srcStride * y; ++ ++ w = width; ++ vx = orig_vx; ++ while ((w -= 2) >= 0) ++ { ++ x1 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s1 = READ(pSrc, src + x1); ++ ++ x2 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s2 = READ(pSrc, src + x2); ++ ++ a1 = s1 >> 24; ++ a2 = s2 >> 24; ++ ++ if (a1 == 0xff) ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s1)); ++ else if (s1) { ++ d = CONVERT_0565_TO_0888(READ(pDst, dst)); ++ a1 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4_store_r5g6b5(d, a1, s1); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ ++ if (a2 == 0xff) ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s2)); ++ else if (s2) { ++ d = CONVERT_0565_TO_0888(READ(pDst, dst)); ++ a2 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4_store_r5g6b5(d, a2, s2); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ } ++ if (w & 1) { ++ x1 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s1 = READ(pSrc, src + x1); ++ ++ a1 = s1 >> 24; ++ if (a1 == 0xff) ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s1)); ++ else if (s1) { ++ d = CONVERT_0565_TO_0888(READ(pDst, dst)); ++ a1 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4_store_r5g6b5(d, a1, s1); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ } ++ } ++} ++ ++static void fbCompositeTransformNearestNonrotatedAffineTrivialclipOver_8888x8888 ( ++ pixman_image_t *pSrc, pixman_image_t *pDst, int xSrc, int ySrc, int xDst, int yDst, ++ int width, int height, int32_t vx, int32_t vy, int32_t unit_x, int32_t unit_y) ++{ ++ uint32_t *dstLine; ++ uint32_t *srcFirstLine; ++ uint32_t d; ++ uint32_t s1, s2; ++ uint8_t a1, a2; ++ int w; ++ int x1, x2, y; ++ int32_t orig_vx = vx; ++ ++ uint32_t *src, *dst; ++ int srcStride, dstStride; ++ PIXMAN_IMAGE_GET_LINE (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); ++ /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be ++ * transformed from destination space to source space */ ++ PIXMAN_IMAGE_GET_LINE (pSrc, 0, 0, uint32_t, srcStride, srcFirstLine, 1); ++ ++ while (--height >= 0) ++ { ++ dst = dstLine; ++ dstLine += dstStride; ++ ++ y = vy >> 16; ++ vy += unit_y; ++ ++ if ((y < 0) || (y >= pSrc->bits.height)) { ++ continue; ++ } ++ ++ src = srcFirstLine + srcStride * y; ++ ++ w = width; ++ vx = orig_vx; ++ while ((w -= 2) >= 0) ++ { ++ x1 = vx >> 16; ++ vx += unit_x; ++ s1 = READ(pSrc, src + x1); ++ ++ x2 = vx >> 16; ++ vx += unit_x; ++ s2 = READ(pSrc, src + x2); ++ ++ a1 = s1 >> 24; ++ a2 = s2 >> 24; ++ ++ if (a1 == 0xff) ++ WRITE(pDst, dst, s1); ++ else if (s1) { ++ d = READ(pDst, dst); ++ a1 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4(d, a1, s1); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ ++ if (a2 == 0xff) ++ WRITE(pDst, dst, s2); ++ else if (s2) { ++ d = READ(pDst, dst); ++ a2 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4(d, a2, s2); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ } ++ if (w & 1) { ++ x1 = vx >> 16; ++ vx += unit_x; ++ s1 = READ(pSrc, src + x1); ++ ++ a1 = s1 >> 24; ++ if (a1 == 0xff) ++ WRITE(pDst, dst, s1); ++ else if (s1) { ++ d = READ(pDst, dst); ++ a1 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4(d, a1, s1); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ } ++ } ++} ++ ++static void fbCompositeTransformNearestNonrotatedAffineTrivialclipRepeatOver_8888x8888 ( ++ pixman_image_t *pSrc, pixman_image_t *pDst, int xSrc, int ySrc, int xDst, int yDst, ++ int width, int height, int32_t vx, int32_t vy, int32_t unit_x, int32_t unit_y) ++{ ++ uint32_t *dstLine; ++ uint32_t *srcFirstLine; ++ uint32_t d; ++ uint32_t s1, s2; ++ uint8_t a1, a2; ++ int w; ++ int x1, x2, y; ++ int32_t orig_vx = vx; ++ int32_t max_vx, max_vy; ++ ++ uint32_t *src, *dst; ++ int srcStride, dstStride; ++ PIXMAN_IMAGE_GET_LINE (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); ++ /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be ++ * transformed from destination space to source space */ ++ PIXMAN_IMAGE_GET_LINE (pSrc, 0, 0, uint32_t, srcStride, srcFirstLine, 1); ++ ++ max_vx = pSrc->bits.width << 16; ++ max_vy = pSrc->bits.height << 16; ++ ++ while (orig_vx < 0) orig_vx += max_vx; ++ while (vy < 0) vy += max_vy; ++ while (orig_vx >= max_vx) orig_vx -= max_vx; ++ while (vy >= max_vy) vy -= max_vy; ++ ++ while (--height >= 0) ++ { ++ dst = dstLine; ++ dstLine += dstStride; ++ ++ y = vy >> 16; ++ vy += unit_y; ++ while (vy >= max_vy) vy -= max_vy; ++ ++ src = srcFirstLine + srcStride * y; ++ ++ w = width; ++ vx = orig_vx; ++ while ((w -= 2) >= 0) ++ { ++ x1 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s1 = READ(pSrc, src + x1); ++ ++ x2 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s2 = READ(pSrc, src + x2); ++ ++ a1 = s1 >> 24; ++ a2 = s2 >> 24; ++ ++ if (a1 == 0xff) ++ WRITE(pDst, dst, s1); ++ else if (s1) { ++ d = READ(pDst, dst); ++ a1 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4(d, a1, s1); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ ++ if (a2 == 0xff) ++ WRITE(pDst, dst, s2); ++ else if (s2) { ++ d = READ(pDst, dst); ++ a2 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4(d, a2, s2); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ } ++ if (w & 1) { ++ x1 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s1 = READ(pSrc, src + x1); ++ ++ a1 = s1 >> 24; ++ if (a1 == 0xff) ++ WRITE(pDst, dst, s1); ++ else if (s1) { ++ d = READ(pDst, dst); ++ a1 ^= 0xff; ++ UN8x4_MUL_UN8_ADD_UN8x4(d, a1, s1); ++ WRITE(pDst, dst, d); ++ } ++ dst++; ++ } ++ } ++} ++ ++static void fbCompositeTransformNearestNonrotatedAffineTrivialclipSrc_8888x8888 ( ++ pixman_image_t *pSrc, pixman_image_t *pDst, int xSrc, int ySrc, int xDst, int yDst, ++ int width, int height, int32_t vx, int32_t vy, int32_t unit_x, int32_t unit_y) ++{ ++ uint32_t *dstLine; ++ uint32_t *srcFirstLine; ++ uint32_t s1, s2; ++ int w; ++ int x1, x2, y; ++ int32_t orig_vx = vx; ++ ++ uint32_t *src, *dst; ++ int srcStride, dstStride; ++ PIXMAN_IMAGE_GET_LINE (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); ++ /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be ++ * transformed from destination space to source space */ ++ PIXMAN_IMAGE_GET_LINE (pSrc, 0, 0, uint32_t, srcStride, srcFirstLine, 1); ++ ++ while (--height >= 0) ++ { ++ dst = dstLine; ++ dstLine += dstStride; ++ ++ y = vy >> 16; ++ vy += unit_y; ++ ++ if ((y < 0) || (y >= pSrc->bits.height)) { ++ memset(dst, 0, width * sizeof(*dst)); ++ continue; ++ } ++ ++ src = srcFirstLine + srcStride * y; ++ ++ w = width; ++ vx = orig_vx; ++ while ((w -= 2) >= 0) ++ { ++ x1 = vx >> 16; ++ vx += unit_x; ++ s1 = READ(pSrc, src + x1); ++ ++ x2 = vx >> 16; ++ vx += unit_x; ++ s2 = READ(pSrc, src + x2); ++ ++ WRITE(pDst, dst, s1); ++ dst++; ++ WRITE(pDst, dst, s2); ++ dst++; ++ } ++ if (w & 1) { ++ x1 = vx >> 16; ++ vx += unit_x; ++ s1 = READ(pSrc, src + x1); ++ WRITE(pDst, dst, s1); ++ dst++; ++ } ++ } ++} ++ ++static void fbCompositeTransformNearestNonrotatedAffineTrivialclipRepeatSrc_8888x8888 ( ++ pixman_image_t *pSrc, pixman_image_t *pDst, int xSrc, int ySrc, int xDst, int yDst, ++ int width, int height, int32_t vx, int32_t vy, int32_t unit_x, int32_t unit_y) ++{ ++ uint32_t *dstLine; ++ uint32_t *srcFirstLine; ++ uint32_t s1, s2; ++ int w; ++ int x1, x2, y; ++ int32_t orig_vx = vx; ++ int32_t max_vx, max_vy; ++ ++ uint32_t *src, *dst; ++ int srcStride, dstStride; ++ PIXMAN_IMAGE_GET_LINE (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1); ++ /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be ++ * transformed from destination space to source space */ ++ PIXMAN_IMAGE_GET_LINE (pSrc, 0, 0, uint32_t, srcStride, srcFirstLine, 1); ++ ++ max_vx = pSrc->bits.width << 16; ++ max_vy = pSrc->bits.height << 16; ++ ++ while (orig_vx < 0) orig_vx += max_vx; ++ while (vy < 0) vy += max_vy; ++ while (orig_vx >= max_vx) orig_vx -= max_vx; ++ while (vy >= max_vy) vy -= max_vy; ++ ++ while (--height >= 0) ++ { ++ dst = dstLine; ++ dstLine += dstStride; ++ ++ y = vy >> 16; ++ vy += unit_y; ++ while (vy >= max_vy) vy -= max_vy; ++ ++ src = srcFirstLine + srcStride * y; ++ ++ w = width; ++ vx = orig_vx; ++ while ((w -= 2) >= 0) ++ { ++ x1 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s1 = READ(pSrc, src + x1); ++ ++ x2 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s2 = READ(pSrc, src + x2); ++ ++ WRITE(pDst, dst, s1); ++ dst++; ++ WRITE(pDst, dst, s2); ++ dst++; ++ } ++ if (w & 1) { ++ x1 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s1 = READ(pSrc, src + x1); ++ ++ WRITE(pDst, dst, s1); ++ dst++; ++ } ++ } ++} ++ ++static void fbCompositeTransformNearestNonrotatedAffineTrivialclipSrc_0565x0565 ( ++ pixman_image_t *pSrc, pixman_image_t *pDst, int xSrc, int ySrc, int xDst, int yDst, ++ int width, int height, int32_t vx, int32_t vy, int32_t unit_x, int32_t unit_y) ++{ ++ uint16_t *dstLine; ++ uint16_t *srcFirstLine; ++ uint16_t s1, s2; ++ int w; ++ int x1, x2, y; ++ int32_t orig_vx = vx; ++ ++ uint16_t *src, *dst; ++ int srcStride, dstStride; ++ PIXMAN_IMAGE_GET_LINE (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); ++ /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be ++ * transformed from destination space to source space */ ++ PIXMAN_IMAGE_GET_LINE (pSrc, 0, 0, uint16_t, srcStride, srcFirstLine, 1); ++ ++ while (--height >= 0) ++ { ++ dst = dstLine; ++ dstLine += dstStride; ++ ++ y = vy >> 16; ++ vy += unit_y; ++ ++ if ((y < 0) || (y >= pSrc->bits.height)) { ++ memset(dst, 0, width * sizeof(*dst)); ++ continue; ++ } ++ ++ src = srcFirstLine + srcStride * y; ++ ++ w = width; ++ vx = orig_vx; ++ while ((w -= 2) >= 0) ++ { ++ x1 = vx >> 16; ++ vx += unit_x; ++ s1 = READ(pSrc, src + x1); ++ ++ x2 = vx >> 16; ++ vx += unit_x; ++ s2 = READ(pSrc, src + x2); ++ ++ WRITE(pDst, dst, s1); ++ dst++; ++ WRITE(pDst, dst, s2); ++ dst++; ++ } ++ if (w & 1) { ++ x1 = vx >> 16; ++ vx += unit_x; ++ s1 = READ(pSrc, src + x1); ++ WRITE(pDst, dst, s1); ++ dst++; ++ } ++ } ++} ++ ++static void fbCompositeTransformNearestNonrotatedAffineTrivialclipRepeatSrc_0565x0565 ( ++ pixman_image_t *pSrc, pixman_image_t *pDst, int xSrc, int ySrc, int xDst, int yDst, ++ int width, int height, int32_t vx, int32_t vy, int32_t unit_x, int32_t unit_y) ++{ ++ uint16_t *dstLine; ++ uint16_t *srcFirstLine; ++ uint16_t s1, s2; ++ int w; ++ int x1, x2, y; ++ int32_t orig_vx = vx; ++ int32_t max_vx, max_vy; ++ ++ uint16_t *src, *dst; ++ int srcStride, dstStride; ++ PIXMAN_IMAGE_GET_LINE (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); ++ /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be ++ * transformed from destination space to source space */ ++ PIXMAN_IMAGE_GET_LINE (pSrc, 0, 0, uint16_t, srcStride, srcFirstLine, 1); ++ ++ max_vx = pSrc->bits.width << 16; ++ max_vy = pSrc->bits.height << 16; ++ ++ while (orig_vx < 0) orig_vx += max_vx; ++ while (vy < 0) vy += max_vy; ++ while (orig_vx >= max_vx) orig_vx -= max_vx; ++ while (vy >= max_vy) vy -= max_vy; ++ ++ while (--height >= 0) ++ { ++ dst = dstLine; ++ dstLine += dstStride; ++ ++ y = vy >> 16; ++ vy += unit_y; ++ while (vy >= max_vy) vy -= max_vy; ++ ++ src = srcFirstLine + srcStride * y; ++ ++ w = width; ++ vx = orig_vx; ++ while ((w -= 2) >= 0) ++ { ++ x1 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s1 = READ(pSrc, src + x1); ++ ++ x2 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s2 = READ(pSrc, src + x2); ++ ++ WRITE(pDst, dst, s1); ++ dst++; ++ WRITE(pDst, dst, s2); ++ dst++; ++ } ++ if (w & 1) { ++ x1 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s1 = READ(pSrc, src + x1); ++ ++ WRITE(pDst, dst, s1); ++ dst++; ++ } ++ } ++} ++ ++static void fbCompositeTransformNearestNonrotatedAffineTrivialclipSrc_8888x0565 ( ++ pixman_image_t *pSrc, pixman_image_t *pDst, int xSrc, int ySrc, int xDst, int yDst, ++ int width, int height, int32_t vx, int32_t vy, int32_t unit_x, int32_t unit_y) ++{ ++ uint16_t *dstLine; ++ uint32_t *srcFirstLine; ++ uint32_t s1, s2; ++ int w; ++ int x1, x2, y; ++ int32_t orig_vx = vx; ++ ++ uint32_t *src; ++ uint16_t *dst; ++ int srcStride, dstStride; ++ PIXMAN_IMAGE_GET_LINE (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); ++ /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be ++ * transformed from destination space to source space */ ++ PIXMAN_IMAGE_GET_LINE (pSrc, 0, 0, uint32_t, srcStride, srcFirstLine, 1); ++ ++ while (--height >= 0) ++ { ++ dst = dstLine; ++ dstLine += dstStride; ++ ++ y = vy >> 16; ++ vy += unit_y; ++ ++ if ((y < 0) || (y >= pSrc->bits.height)) { ++ memset(dst, 0, width * sizeof(*dst)); ++ continue; ++ } ++ ++ src = srcFirstLine + srcStride * y; ++ ++ w = width; ++ vx = orig_vx; ++ while ((w -= 2) >= 0) ++ { ++ x1 = vx >> 16; ++ vx += unit_x; ++ s1 = READ(pSrc, src + x1); ++ ++ x2 = vx >> 16; ++ vx += unit_x; ++ s2 = READ(pSrc, src + x2); ++ ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s1)); ++ dst++; ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s2)); ++ dst++; ++ } ++ if (w & 1) { ++ x1 = vx >> 16; ++ vx += unit_x; ++ s1 = READ(pSrc, src + x1); ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s1)); ++ dst++; ++ } ++ } ++} ++ ++static void fbCompositeTransformNearestNonrotatedAffineTrivialclipRepeatSrc_8888x0565 ( ++ pixman_image_t *pSrc, pixman_image_t *pDst, int xSrc, int ySrc, int xDst, int yDst, ++ int width, int height, int32_t vx, int32_t vy, int32_t unit_x, int32_t unit_y) ++{ ++ uint16_t *dstLine; ++ uint32_t *srcFirstLine; ++ uint32_t s1, s2; ++ int w; ++ int x1, x2, y; ++ int32_t orig_vx = vx; ++ int32_t max_vx, max_vy; ++ ++ uint32_t *src; ++ uint16_t *dst; ++ int srcStride, dstStride; ++ PIXMAN_IMAGE_GET_LINE (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1); ++ /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be ++ * transformed from destination space to source space */ ++ PIXMAN_IMAGE_GET_LINE (pSrc, 0, 0, uint32_t, srcStride, srcFirstLine, 1); ++ ++ max_vx = pSrc->bits.width << 16; ++ max_vy = pSrc->bits.height << 16; ++ ++ while (orig_vx < 0) orig_vx += max_vx; ++ while (vy < 0) vy += max_vy; ++ while (orig_vx >= max_vx) orig_vx -= max_vx; ++ while (vy >= max_vy) vy -= max_vy; ++ ++ while (--height >= 0) ++ { ++ dst = dstLine; ++ dstLine += dstStride; ++ ++ y = vy >> 16; ++ vy += unit_y; ++ while (vy >= max_vy) vy -= max_vy; ++ ++ src = srcFirstLine + srcStride * y; ++ ++ w = width; ++ vx = orig_vx; ++ while ((w -= 2) >= 0) ++ { ++ x1 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s1 = READ(pSrc, src + x1); ++ ++ x2 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s2 = READ(pSrc, src + x2); ++ ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s1)); ++ dst++; ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s2)); ++ dst++; ++ } ++ if (w & 1) { ++ x1 = vx >> 16; ++ vx += unit_x; ++ while (vx >= max_vx) vx -= max_vx; ++ s1 = READ(pSrc, src + x1); ++ ++ WRITE(pDst, dst, CONVERT_8888_TO_0565(s1)); ++ dst++; ++ } ++ } ++} ++ ++/* ++ * Check if the clipping boundary is crossed on horizontal scaling ++ */ ++static inline pixman_bool_t ++fbTransformVerifyHorizontalClipping(pixman_image_t *pict, int width, int32_t vx, int32_t unit_x) ++{ ++ while (--width >= 0) { ++ int x = vx >> 16; ++ if ((x < 0) || (x >= pict->bits.width)) return 1; ++ vx += unit_x; ++ } ++ return 0; ++} ++ ++/* ++ * Check if the clipping boundary is crossed on vertical scaling ++ */ ++static inline pixman_bool_t ++fbTransformVerifyVerticalClipping(pixman_image_t *pict, int height, int32_t vy, int32_t unit_y) ++{ ++ while (--height >= 0) { ++ int y = vy >> 16; ++ if ((y < 0) || (y >= pict->bits.height)) return 1; ++ vy += unit_y; ++ } ++ return 0; ++} ++ ++/* ++ * Easy case of transform without rotation or complex clipping ++ * Returns 1 in the case if it was able to handle this operation and 0 otherwise ++ */ ++static pixman_bool_t ++fbCompositeTransformNonrotatedAffineTrivialclip ( ++ pixman_op_t op, ++ pixman_image_t *pSrc, ++ pixman_image_t *pMask, ++ pixman_image_t *pDst, ++ int16_t xSrc, ++ int16_t ySrc, ++ int16_t xMask, ++ int16_t yMask, ++ int16_t xDst, ++ int16_t yDst, ++ uint16_t width, ++ uint16_t height) ++{ ++ pixman_vector_t v, unit; ++ int skipdst_x = 0, skipdst_y = 0; ++ ++ /* Handle destination clipping */ ++ if (xDst < pDst->common.clip_region.extents.x1) { ++ skipdst_x = pDst->common.clip_region.extents.x1 - xDst; ++ if (skipdst_x >= (int)width) ++ return 1; ++ xDst = pDst->common.clip_region.extents.x1; ++ width -= skipdst_x; ++ } ++ ++ if (yDst < pDst->common.clip_region.extents.y1) { ++ skipdst_y = pDst->common.clip_region.extents.y1 - yDst; ++ if (skipdst_y >= (int)height) ++ return 1; ++ yDst = pDst->common.clip_region.extents.y1; ++ height -= skipdst_y; ++ } ++ ++ if (xDst >= pDst->common.clip_region.extents.x2 || ++ yDst >= pDst->common.clip_region.extents.y2) ++ { ++ return 1; ++ } ++ ++ if (xDst + width > pDst->common.clip_region.extents.x2) ++ width = pDst->common.clip_region.extents.x2 - xDst; ++ if (yDst + height > pDst->common.clip_region.extents.y2) ++ height = pDst->common.clip_region.extents.y2 - yDst; ++ ++ /* reference point is the center of the pixel */ ++ v.vector[0] = pixman_int_to_fixed(xSrc) + pixman_fixed_1 / 2; ++ v.vector[1] = pixman_int_to_fixed(ySrc) + pixman_fixed_1 / 2; ++ v.vector[2] = pixman_fixed_1; ++ ++ if (!pixman_transform_point_3d (pSrc->common.transform, &v)) ++ return 0; ++ ++ /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */ ++ v.vector[0] -= pixman_fixed_e; ++ v.vector[1] -= pixman_fixed_e; ++ ++ unit.vector[0] = pSrc->common.transform->matrix[0][0]; ++ unit.vector[1] = pSrc->common.transform->matrix[1][1]; ++ ++ v.vector[0] += unit.vector[0] * skipdst_x; ++ v.vector[1] += unit.vector[1] * skipdst_y; ++ ++ /* Check for possible fixed point arithmetics problems/overflows */ ++ if (unit.vector[0] <= 0 || unit.vector[1] <= 0) ++ return 0; ++ if (width == 0 || height == 0) ++ return 0; ++ if ((uint32_t)width + (unit.vector[0] >> 16) >= 0x7FFF) ++ return 0; ++ if ((uint32_t)height + (unit.vector[1] >> 16) >= 0x7FFF) ++ return 0; ++ ++ /* Horizontal source clipping is only supported for NORMAL repeat */ ++ if (pSrc->common.repeat != PIXMAN_REPEAT_NORMAL ++ && fbTransformVerifyHorizontalClipping(pSrc, width, v.vector[0], unit.vector[0])) { ++ return 0; ++ } ++ ++ /* Vertical source clipping is only supported for NONE and NORMAL repeat */ ++ if (pSrc->common.repeat != PIXMAN_REPEAT_NONE && pSrc->common.repeat != PIXMAN_REPEAT_NORMAL ++ && fbTransformVerifyVerticalClipping(pSrc, height, v.vector[1], unit.vector[1])) { ++ return 0; ++ } ++ ++ if (op == PIXMAN_OP_OVER && pSrc->bits.format == PIXMAN_a8r8g8b8 ++ && (pDst->bits.format == PIXMAN_x8r8g8b8 || pDst->bits.format == PIXMAN_a8r8g8b8)) ++ { ++ if (pSrc->common.filter == PIXMAN_FILTER_NEAREST && pSrc->common.repeat != PIXMAN_REPEAT_NORMAL) { ++ fbCompositeTransformNearestNonrotatedAffineTrivialclipOver_8888x8888( ++ pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height, ++ v.vector[0], v.vector[1], unit.vector[0], unit.vector[1]); ++ return 1; ++ } ++ if (pSrc->common.filter == PIXMAN_FILTER_NEAREST && pSrc->common.repeat == PIXMAN_REPEAT_NORMAL) { ++ fbCompositeTransformNearestNonrotatedAffineTrivialclipRepeatOver_8888x8888( ++ pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height, ++ v.vector[0], v.vector[1], unit.vector[0], unit.vector[1]); ++ return 1; ++ } ++ } ++ ++ if (op == PIXMAN_OP_SRC && (pSrc->bits.format == PIXMAN_x8r8g8b8 || pSrc->bits.format == PIXMAN_a8r8g8b8) ++ && (pDst->bits.format == PIXMAN_x8r8g8b8 || pDst->bits.format == pSrc->bits.format)) ++ { ++ if (pSrc->common.filter == PIXMAN_FILTER_NEAREST && pSrc->common.repeat != PIXMAN_REPEAT_NORMAL) { ++ fbCompositeTransformNearestNonrotatedAffineTrivialclipSrc_8888x8888( ++ pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height, ++ v.vector[0], v.vector[1], unit.vector[0], unit.vector[1]); ++ return 1; ++ } ++ if (pSrc->common.filter == PIXMAN_FILTER_NEAREST && pSrc->common.repeat == PIXMAN_REPEAT_NORMAL) { ++ fbCompositeTransformNearestNonrotatedAffineTrivialclipRepeatSrc_8888x8888( ++ pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height, ++ v.vector[0], v.vector[1], unit.vector[0], unit.vector[1]); ++ return 1; ++ } ++ } ++ ++ if (op == PIXMAN_OP_OVER && pSrc->bits.format == PIXMAN_a8r8g8b8 && pDst->bits.format == PIXMAN_r5g6b5) ++ { ++ if (pSrc->common.filter == PIXMAN_FILTER_NEAREST && pSrc->common.repeat != PIXMAN_REPEAT_NORMAL) { ++ fbCompositeTransformNearestNonrotatedAffineTrivialclipOver_8888x0565( ++ pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height, ++ v.vector[0], v.vector[1], unit.vector[0], unit.vector[1]); ++ return 1; ++ } ++ if (pSrc->common.filter == PIXMAN_FILTER_NEAREST && pSrc->common.repeat == PIXMAN_REPEAT_NORMAL) { ++ fbCompositeTransformNearestNonrotatedAffineTrivialclipRepeatOver_8888x0565( ++ pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height, ++ v.vector[0], v.vector[1], unit.vector[0], unit.vector[1]); ++ return 1; ++ } ++ } ++ ++ if (op == PIXMAN_OP_SRC && pSrc->bits.format == PIXMAN_r5g6b5 && pDst->bits.format == PIXMAN_r5g6b5) ++ { ++ if (pSrc->common.filter == PIXMAN_FILTER_NEAREST && pSrc->common.repeat != PIXMAN_REPEAT_NORMAL) { ++ fbCompositeTransformNearestNonrotatedAffineTrivialclipSrc_0565x0565( ++ pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height, ++ v.vector[0], v.vector[1], unit.vector[0], unit.vector[1]); ++ return 1; ++ } ++ if (pSrc->common.filter == PIXMAN_FILTER_NEAREST && pSrc->common.repeat == PIXMAN_REPEAT_NORMAL) { ++ fbCompositeTransformNearestNonrotatedAffineTrivialclipRepeatSrc_0565x0565( ++ pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height, ++ v.vector[0], v.vector[1], unit.vector[0], unit.vector[1]); ++ return 1; ++ } ++ } ++ ++ if (op == PIXMAN_OP_SRC && (pSrc->bits.format == PIXMAN_x8r8g8b8 || pSrc->bits.format == PIXMAN_a8r8g8b8) ++ && pDst->bits.format == PIXMAN_r5g6b5) ++ { ++ if (pSrc->common.filter == PIXMAN_FILTER_NEAREST && pSrc->common.repeat != PIXMAN_REPEAT_NORMAL) { ++ fbCompositeTransformNearestNonrotatedAffineTrivialclipSrc_8888x0565( ++ pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height, ++ v.vector[0], v.vector[1], unit.vector[0], unit.vector[1]); ++ return 1; ++ } ++ if (pSrc->common.filter == PIXMAN_FILTER_NEAREST && pSrc->common.repeat == PIXMAN_REPEAT_NORMAL) { ++ fbCompositeTransformNearestNonrotatedAffineTrivialclipRepeatSrc_8888x0565( ++ pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height, ++ v.vector[0], v.vector[1], unit.vector[0], unit.vector[1]); ++ return 1; ++ } ++ } ++ ++ /* No fastpath scaling implemented for this case */ ++ return 0; ++} ++ + static void + fast_path_composite (pixman_implementation_t *imp, + pixman_op_t op, +@@ -1279,6 +2266,30 @@ fast_path_composite (pixman_implementation_t *imp, + if (src->type == BITS + && src->common.transform + && !mask ++ && !src->common.alpha_map && !dest->common.alpha_map ++ && (src->common.filter == PIXMAN_FILTER_NEAREST) ++ && !src->bits.read_func && !src->bits.write_func ++ && !dest->bits.read_func && !dest->bits.write_func) ++ { ++ /* ensure that the transform matrix only has a scale */ ++ if (src->common.transform->matrix[0][1] == 0 && ++ src->common.transform->matrix[1][0] == 0 && ++ src->common.transform->matrix[2][0] == 0 && ++ src->common.transform->matrix[2][1] == 0 && ++ src->common.transform->matrix[2][2] == pixman_fixed_1 && ++ dest->common.clip_region.data == NULL) ++ { ++ if (fbCompositeTransformNonrotatedAffineTrivialclip (op, src, mask, dest, ++ src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height)) ++ { ++ return; ++ } ++ } ++ } ++ ++ if (src->type == BITS ++ && src->common.transform ++ && !mask + && op == PIXMAN_OP_SRC + && !src->common.alpha_map && !dest->common.alpha_map + && (src->common.filter == PIXMAN_FILTER_NEAREST) diff --git a/recipes/xorg-lib/pixman/over-8888-0565.patch b/recipes/xorg-lib/pixman/over-8888-0565.patch new file mode 100644 index 0000000000..3e27094022 --- /dev/null +++ b/recipes/xorg-lib/pixman/over-8888-0565.patch @@ -0,0 +1,296 @@ +From: Siarhei Siamashka <siarhei.siamashka@nokia.com> +Date: Mon, 27 Jul 2009 04:48:04 +0000 (+0300) +Subject: ARM: NEON optimized version of composite_over_8888_0565 +X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=pixman.git;a=commitdiff_plain;h=17d8ab82858511f212dfb30c347255393eb12b0c + +ARM: NEON optimized version of composite_over_8888_0565 +--- + +diff --git a/pixman/pixman-arm-neon.c b/pixman/pixman-arm-neon.c +index 9404c70..f1dcf1f 100644 +--- a/pixman/pixman-arm-neon.c ++++ b/pixman/pixman-arm-neon.c +@@ -1447,6 +1447,274 @@ neon_composite_src_16_16 (pixman_implementation_t * impl, + } + } + ++static inline void ++neon_composite_over_8888_0565_internal (uint32_t *src, ++ uint16_t *dst, ++ int32_t w, ++ int32_t h, ++ int32_t src_stride, ++ int32_t dst_stride) ++{ ++ int32_t dst_newline_delta = (dst_stride - w) * 2; ++ int32_t src_newline_delta = (src_stride - w) * 4; ++ asm volatile ( ++ ++ ".macro process_pixblock_head size\n" ++ /* load pixel data from memory */ ++ " .if \\size == 8\n" ++ " vld1.32 {d0, d1, d2, d3}, [%[src]]!\n" ++ " vld1.16 {d4, d5}, [%[dst_r]]!\n" ++ " .elseif \\size == 4\n" ++ " vld1.32 {d0, d1}, [%[src]]!\n" ++ " vld1.16 {d4}, [%[dst_r]]!\n" ++ " .elseif \\size == 2\n" ++ " vld1.32 {d0}, [%[src]]!\n" ++ " vld1.16 {d4[0]}, [%[dst_r]]!\n" ++ " vld1.16 {d4[1]}, [%[dst_r]]!\n" ++ " .elseif \\size == 1\n" ++ " vld1.32 {d0[0]}, [%[src]]!\n" ++ " vld1.16 {d4[0]}, [%[dst_r]]!\n" ++ " .endif\n" ++ /* deinterleave and convert both source and destination ++ to "planar" 8-bit format */ ++ " vshrn.u16 d16, q2, #8\n" ++ " vuzp.8 d0, d1\n" ++ " vshrn.u16 d17, q2, #3\n" ++ " vuzp.8 d2, d3\n" ++ " vsli.u16 q2, q2, #5\n" ++ " vuzp.8 d1, d3\n" ++ " vsri.u8 d16, d16, #5\n" ++ " vuzp.8 d0, d2\n" ++ " vmvn.8 d3, d3\n" ++ " vsri.u8 d17, d17, #6\n" ++ " vshrn.u16 d18, q2, #2\n" ++ /* source: d0 - blue, d1 - green, d2 - red, d3 - alpha */ ++ /* destination: d16 - red, d17 - green, d18 - blue */ ++ /* now do alpha blending */ ++ " vmull.u8 q10, d3, d16\n" ++ "pld [%[src], #128]\n" ++ " vmull.u8 q11, d3, d17\n" ++ "pld [%[dst_r], #64]\n" ++ " vmull.u8 q12, d3, d18\n" ++ " vrshr.u16 q13, q10, #8\n" ++ " vrshr.u16 q8, q11, #8\n" ++ " vrshr.u16 q9, q12, #8\n" ++ " vraddhn.u16 d20, q10, q13\n" ++ " vraddhn.u16 d21, q11, q8\n" ++ " vraddhn.u16 d22, q12, q9\n" ++ ".endm\n" ++ ++ ".macro process_pixblock_tail size\n" ++ /* result is ready in d28, d29, d30 (R, G, B) */ ++ " vqadd.u8 d28, d2, d20\n" ++ " vqadd.u8 d29, d1, d21\n" ++ " vqadd.u8 d30, d0, d22\n" ++ /* convert it to r5g6b5 */ ++ " vshll.u8 q3, d28, #8\n" ++ " vshll.u8 q14, d29, #8\n" ++ " vshll.u8 q15, d30, #8\n" ++ " vsri.u16 q3, q14, #5\n" ++ " vsri.u16 q3, q15, #11\n" ++ /* store pixel data to memory */ ++ " .if \\size == 8\n" ++ " vst1.16 {d6, d7}, [%[dst_w], :128]!\n" ++ " .elseif \\size == 4\n" ++ " vst1.16 {d6}, [%[dst_w]]!\n" ++ " .elseif \\size == 2\n" ++ " vst1.16 {d6[0]}, [%[dst_w]]!\n" ++ " vst1.16 {d6[1]}, [%[dst_w]]!\n" ++ " .elseif \\size == 1\n" ++ " vst1.16 {d6[0]}, [%[dst_w]]!\n" ++ " .endif\n" ++ ".endm\n" ++ ++ /* "tail" of the previous block and "head" of the next block ++ are merged and interleaved for better instructions scheduling */ ++ ".macro process_pixblock_tail_head_8\n" ++ " vqadd.u8 d28, d2, d20\n" ++ " vld1.16 {d4, d5}, [%[dst_r], :128]!\n" ++ " vqadd.u8 d29, d1, d21\n" /* TODO: try to join these into a */ ++ " vqadd.u8 d30, d0, d22\n" /* single 128-bit operation */ ++ " vshrn.u16 d16, q2, #8\n" ++ " vld1.32 {d0, d1, d2, d3}, [%[src]]!\n" /* TODO: maybe split */ ++ " vshrn.u16 d17, q2, #3\n" ++ " vsli.u16 q2, q2, #5\n" ++ " vuzp.8 d0, d1\n" ++ " vshll.u8 q3, d28, #8\n" ++ " vuzp.8 d2, d3\n" ++ " vshll.u8 q14, d29, #8\n" ++ " vuzp.8 d1, d3\n" ++ " vsri.u8 d16, d16, #5\n" ++ " vuzp.8 d0, d2\n" ++ " vmvn.8 d3, d3\n" ++ " vsri.u8 d17, d17, #6\n" ++ " vshrn.u16 d18, q2, #2\n" ++ " vmull.u8 q10, d3, d16\n" ++ "pld [%[src], #128]\n" ++ " vmull.u8 q11, d3, d17\n" ++ "pld [%[dst_r], #64]\n" ++ " vmull.u8 q12, d3, d18\n" ++ " vsri.u16 d6, d28, #5\n" ++ " vsri.u16 d7, d29, #5\n" ++ " vshll.u8 q15, d30, #8\n" ++ " vrshr.u16 q13, q10, #8\n" ++ " vrshr.u16 q8, q11, #8\n" ++ " vrshr.u16 q9, q12, #8\n" ++ " vsri.u16 d6, d30, #11\n" ++ " vsri.u16 d7, d31, #11\n" ++ " vraddhn.u16 d20, q10, q13\n" ++ " vraddhn.u16 d21, q11, q8\n" ++ " vraddhn.u16 d22, q12, q9\n" ++ " vst1.16 {d6, d7}, [%[dst_w], :128]!\n" ++ ".endm\n" ++ ++ "subs %[h], %[h], #1\n" ++ "blt 9f\n" ++ "0:\n" ++ "cmp %[w], #8\n" ++ "blt 8f\n" ++ ++ /* ensure 16 byte alignment of the destination buffer */ ++ "tst %[dst_r], #0xF\n" ++ "beq 2f\n" ++ "tst %[dst_r], #2\n" ++ "beq 1f\n" ++ "vld1.32 {d3[0]}, [%[src]]!\n" ++ "vld1.16 {d5[2]}, [%[dst_r]]!\n" ++ "sub %[w], %[w], #1\n" ++ "1:\n" ++ "tst %[dst_r], #4\n" ++ "beq 1f\n" ++ "vld1.32 {d2}, [%[src]]!\n" ++ "vld1.16 {d5[0]}, [%[dst_r]]!\n" ++ "vld1.16 {d5[1]}, [%[dst_r]]!\n" ++ "sub %[w], %[w], #2\n" ++ "1:\n" ++ "tst %[dst_r], #8\n" ++ "beq 1f\n" ++ "vld1.32 {d0, d1}, [%[src]]!\n" ++ "vld1.16 {d4}, [%[dst_r]]!\n" ++ "sub %[w], %[w], #4\n" ++ "1:\n" ++ "process_pixblock_head -1\n" ++ "process_pixblock_tail -1\n" ++ "tst %[dst_w], #2\n" ++ "beq 1f\n" ++ "vst1.16 {d7[2]}, [%[dst_w]]!\n" ++ "1:\n" ++ "tst %[dst_w], #4\n" ++ "beq 1f\n" ++ "vst1.16 {d7[0]}, [%[dst_w]]!\n" ++ "vst1.16 {d7[1]}, [%[dst_w]]!\n" ++ "1:\n" ++ "tst %[dst_w], #8\n" ++ "beq 2f\n" ++ "vst1.16 {d6}, [%[dst_w]]!\n" ++ "2:\n" ++ ++ "subs %[w], %[w], #8\n" ++ "blt 8f\n" ++ "process_pixblock_head 8\n" ++ "subs %[w], %[w], #8\n" ++ "blt 2f\n" ++ "1:\n" /* innermost pipelined loop */ ++ "process_pixblock_tail_head_8\n" ++ "subs %[w], %[w], #8\n" ++ "bge 1b\n" ++ "2:\n" ++ "process_pixblock_tail 8\n" ++ ++ "8:\n" ++ /* process up to 7 remaining pixels */ ++ "tst %[w], #7\n" ++ "beq 2f\n" ++ "tst %[w], #4\n" ++ "beq 1f\n" ++ "vld1.32 {d0, d1}, [%[src]]!\n" ++ "vld1.16 {d4}, [%[dst_r]]!\n" ++ "1:\n" ++ "tst %[w], #2\n" ++ "beq 1f\n" ++ "vld1.32 {d2}, [%[src]]!\n" ++ "vld1.16 {d5[0]}, [%[dst_r]]!\n" ++ "vld1.16 {d5[1]}, [%[dst_r]]!\n" ++ "1:\n" ++ "tst %[w], #1\n" ++ "beq 1f\n" ++ "vld1.32 {d3[0]}, [%[src]]!\n" ++ "vld1.16 {d5[2]}, [%[dst_r]]!\n" ++ "1:\n" ++ ++ "process_pixblock_head -1\n" ++ "process_pixblock_tail -1\n" ++ ++ "tst %[w], #4\n" ++ "beq 1f\n" ++ "vst1.16 {d6}, [%[dst_w]]!\n" ++ "1:\n" ++ "tst %[w], #2\n" ++ "beq 1f\n" ++ "vst1.16 {d7[0]}, [%[dst_w]]!\n" ++ "vst1.16 {d7[1]}, [%[dst_w]]!\n" ++ "1:\n" ++ "tst %[w], #1\n" ++ "beq 2f\n" ++ "vst1.16 {d7[2]}, [%[dst_w]]!\n" ++ "2:\n" ++ ++ "add %[src], %[src], %[src_newline_delta]\n" ++ "add %[dst_r], %[dst_r], %[dst_newline_delta]\n" ++ "add %[dst_w], %[dst_w], %[dst_newline_delta]\n" ++ "mov %[w], %[orig_w]\n" ++ "subs %[h], %[h], #1\n" ++ "bge 0b\n" ++ "9:\n" ++ ".purgem process_pixblock_head\n" ++ ".purgem process_pixblock_tail\n" ++ ".purgem process_pixblock_tail_head_8\n" ++ ++ : [src] "+&r" (src), [dst_r] "+&r" (dst), [dst_w] "+&r" (dst), ++ [w] "+&r" (w), [h] "+&r" (h) ++ : [dst_newline_delta] "r" (dst_newline_delta), ++ [src_newline_delta] "r" (src_newline_delta), [orig_w] "r" (w) ++ : "cc", "memory", ++ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ++ /* "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", */ ++ "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", ++ "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31" ++ ); ++} ++ ++static void ++neon_composite_over_8888_0565 (pixman_implementation_t *imp, ++ pixman_op_t op, ++ pixman_image_t * src_image, ++ pixman_image_t * mask_image, ++ pixman_image_t * dst_image, ++ int32_t src_x, ++ int32_t src_y, ++ int32_t mask_x, ++ int32_t mask_y, ++ int32_t dest_x, ++ int32_t dest_y, ++ int32_t width, ++ int32_t height) ++{ ++ uint16_t *dst_line; ++ uint32_t *src_line; ++ int32_t dst_stride, src_stride; ++ ++ PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); ++ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); ++ ++ neon_composite_over_8888_0565_internal (src_line, ++ dst_line, ++ width, ++ height, ++ src_stride, ++ dst_stride); ++} ++ + #endif /* USE_GCC_INLINE_ASM */ + + static void +@@ -1908,6 +2176,8 @@ static const pixman_fast_path_t arm_neon_fast_path_array[] = + #ifdef USE_GCC_INLINE_ASM + { PIXMAN_OP_SRC, PIXMAN_r5g6b5, PIXMAN_null, PIXMAN_r5g6b5, neon_composite_src_16_16, 0 }, + { PIXMAN_OP_SRC, PIXMAN_b5g6r5, PIXMAN_null, PIXMAN_b5g6r5, neon_composite_src_16_16, 0 }, ++ { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, neon_composite_over_8888_0565, 0 }, ++ { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, neon_composite_over_8888_0565, 0 }, + #endif + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, neon_composite_over_8888_8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, neon_composite_over_8888_8888, 0 }, diff --git a/recipes/xorg-lib/pixman/pixman-28986.patch b/recipes/xorg-lib/pixman/pixman-28986.patch new file mode 100644 index 0000000000..f5ba4c302e --- /dev/null +++ b/recipes/xorg-lib/pixman/pixman-28986.patch @@ -0,0 +1,32 @@ +From 7b7860d61fb1526acdf010dd8fd644bbf1396b9e Mon Sep 17 00:00:00 2001 +From: Siarhei Siamashka <siarhei.siamashka@nokia.com> +Date: Fri, 28 Aug 2009 22:34:21 +0300 +Subject: [PATCH] ARM: workaround for gcc bug in vshll_n_u8 intrinsic + +Some versions of gcc (cs2009q1, 4.4.1) incorrectly reject +shift operand having value >= 8, claiming that it is out of +range. So inline assembly is used as a workaround. +--- + pixman/pixman-arm-neon.c | 6 ++++++ + 1 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/pixman/pixman-arm-neon.c b/pixman/pixman-arm-neon.c +index 4125d1b..3e7f566 100644 +--- a/pixman/pixman-arm-neon.c ++++ b/pixman/pixman-arm-neon.c +@@ -64,6 +64,12 @@ unpack0565 (uint16x8_t rgb) + return res; + } + ++#ifdef USE_GCC_INLINE_ASM ++/* Some versions of gcc have problems with vshll_n_u8 intrinsic (Bug 23576) */ ++#define vshll_n_u8(a, n) ({ uint16x8_t r; \ ++ asm ("vshll.u8 %q0, %P1, %2\n" : "=w" (r) : "w" (a), "i" (n)); r; }) ++#endif ++ + static force_inline uint16x8_t + pack0565 (uint8x8x4_t s) + { +-- +1.5.4.3 + diff --git a/recipes/xorg-lib/pixman/remove-broken.patch b/recipes/xorg-lib/pixman/remove-broken.patch new file mode 100644 index 0000000000..fd025b4bbd --- /dev/null +++ b/recipes/xorg-lib/pixman/remove-broken.patch @@ -0,0 +1,826 @@ +From: Siarhei Siamashka <siarhei.siamashka@nokia.com> +Date: Sun, 26 Jul 2009 22:21:26 +0000 (+0300) +Subject: ARM: Removal of unused/broken NEON code +X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=pixman.git;a=commitdiff_plain;h=7ef2322eefcccc28a2d45c0da22c0fee88b8f464 + +ARM: Removal of unused/broken NEON code +--- + +diff --git a/pixman/pixman-arm-neon.c b/pixman/pixman-arm-neon.c +index 4125d1b..9404c70 100644 +--- a/pixman/pixman-arm-neon.c ++++ b/pixman/pixman-arm-neon.c +@@ -1895,710 +1895,6 @@ pixman_fill_neon (uint32_t *bits, + #endif + } + +-/* TODO: is there a more generic way of doing this being introduced? */ +-#define NEON_SCANLINE_BUFFER_PIXELS (1024) +- +-static inline void +-neon_quadword_copy (void * dst, +- void * src, +- uint32_t count, /* of quadwords */ +- uint32_t trailer_count /* of bytes */) +-{ +- uint8_t *t_dst = dst, *t_src = src; +- +- /* Uses aligned multi-register loads to maximise read bandwidth +- * on uncached memory such as framebuffers +- * The accesses do not have the aligned qualifiers, so that the copy +- * may convert between aligned-uncached and unaligned-cached memory. +- * It is assumed that the CPU can infer alignedness from the address. +- */ +- +-#ifdef USE_GCC_INLINE_ASM +- +- asm volatile ( +- " cmp %[count], #8 \n" +- " blt 1f @ skip oversized fragments \n" +- "0: @ start with eight quadwords at a time \n" +- " sub %[count], %[count], #8 \n" +- " vld1.8 {d16, d17, d18, d19}, [%[src]]! \n" +- " vld1.8 {d20, d21, d22, d23}, [%[src]]! \n" +- " vld1.8 {d24, d25, d26, d27}, [%[src]]! \n" +- " vld1.8 {d28, d29, d30, d31}, [%[src]]! \n" +- " cmp %[count], #8 \n" +- " vst1.8 {d16, d17, d18, d19}, [%[dst]]! \n" +- " vst1.8 {d20, d21, d22, d23}, [%[dst]]! \n" +- " vst1.8 {d24, d25, d26, d27}, [%[dst]]! \n" +- " vst1.8 {d28, d29, d30, d31}, [%[dst]]! \n" +- " bge 0b \n" +- "1: @ four quadwords \n" +- " tst %[count], #4 \n" +- " beq 2f @ skip oversized fragment \n" +- " vld1.8 {d16, d17, d18, d19}, [%[src]]! \n" +- " vld1.8 {d20, d21, d22, d23}, [%[src]]! \n" +- " vst1.8 {d16, d17, d18, d19}, [%[dst]]! \n" +- " vst1.8 {d20, d21, d22, d23}, [%[dst]]! \n" +- "2: @ two quadwords \n" +- " tst %[count], #2 \n" +- " beq 3f @ skip oversized fragment \n" +- " vld1.8 {d16, d17, d18, d19}, [%[src]]! \n" +- " vst1.8 {d16, d17, d18, d19}, [%[dst]]! \n" +- "3: @ one quadword \n" +- " tst %[count], #1 \n" +- " beq 4f @ skip oversized fragment \n" +- " vld1.8 {d16, d17}, [%[src]]! \n" +- " vst1.8 {d16, d17}, [%[dst]]! \n" +- "4: @ end \n" +- +- /* Clobbered input registers marked as input/outputs */ +- : [dst] "+r" (t_dst), [src] "+r" (t_src), [count] "+r" (count) +- +- /* No unclobbered inputs */ +- : +- +- /* Clobbered vector registers */ +- : "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", +- "d26", "d27", "d28", "d29", "d30", "d31", "cc", "memory"); +- +-#else +- +- while (count >= 8) +- { +- uint8x16x4_t t1 = vld4q_u8 (t_src); +- uint8x16x4_t t2 = vld4q_u8 (t_src + sizeof(uint8x16x4_t)); +- +- t_src += sizeof(uint8x16x4_t) * 2; +- vst4q_u8 (t_dst, t1); +- vst4q_u8 (t_dst + sizeof(uint8x16x4_t), t2); +- t_dst += sizeof(uint8x16x4_t) * 2; +- count -= 8; +- } +- +- if (count & 4) +- { +- uint8x16x4_t t1 = vld4q_u8 (t_src); +- +- t_src += sizeof(uint8x16x4_t); +- vst4q_u8 (t_dst, t1); +- t_dst += sizeof(uint8x16x4_t); +- } +- +- if (count & 2) +- { +- uint8x8x4_t t1 = vld4_u8 (t_src); +- +- t_src += sizeof(uint8x8x4_t); +- vst4_u8 (t_dst, t1); +- t_dst += sizeof(uint8x8x4_t); +- } +- +- if (count & 1) +- { +- uint8x16_t t1 = vld1q_u8 (t_src); +- +- t_src += sizeof(uint8x16_t); +- vst1q_u8 (t_dst, t1); +- t_dst += sizeof(uint8x16_t); +- } +- +-#endif /* !USE_GCC_INLINE_ASM */ +- +- if (trailer_count) +- { +- if (trailer_count & 8) +- { +- uint8x8_t t1 = vld1_u8 (t_src); +- +- t_src += sizeof(uint8x8_t); +- vst1_u8 (t_dst, t1); +- t_dst += sizeof(uint8x8_t); +- } +- +- if (trailer_count & 4) +- { +- *((uint32_t*) t_dst) = *((uint32_t*) t_src); +- +- t_dst += 4; +- t_src += 4; +- } +- +- if (trailer_count & 2) +- { +- *((uint16_t*) t_dst) = *((uint16_t*) t_src); +- +- t_dst += 2; +- t_src += 2; +- } +- +- if (trailer_count & 1) +- { +- *t_dst++ = *t_src++; +- } +- } +-} +- +-static inline void +-solid_over_565_8_pix_neon (uint32_t glyph_colour, +- uint16_t *dest, +- uint8_t * in_mask, +- uint32_t dest_stride, /* bytes, not elements */ +- uint32_t mask_stride, +- uint32_t count /* 8-pixel groups */) +-{ +- /* Inner loop of glyph blitter (solid colour, alpha mask) */ +- +-#ifdef USE_GCC_INLINE_ASM +- +- asm volatile ( +- " vld4.8 {d20[], d21[], d22[], d23[]}, [%[glyph_colour]] @ splat solid colour components \n" +- "0: @ loop \n" +- " vld1.16 {d0, d1}, [%[dest]] @ load first pixels from framebuffer \n" +- " vld1.8 {d17}, [%[in_mask]] @ load alpha mask of glyph \n" +- " vmull.u8 q9, d17, d23 @ apply glyph colour alpha to mask \n" +- " vshrn.u16 d17, q9, #8 @ reformat it to match original mask \n" +- " vmvn d18, d17 @ we need the inverse mask for the background \n" +- " vsli.u16 q3, q0, #5 @ duplicate framebuffer blue bits \n" +- " vshrn.u16 d2, q0, #8 @ unpack red from framebuffer pixels \n" +- " vshrn.u16 d4, q0, #3 @ unpack green \n" +- " vsri.u8 d2, d2, #5 @ duplicate red bits (extend 5 to 8) \n" +- " vshrn.u16 d6, q3, #2 @ unpack extended blue (truncate 10 to 8) \n" +- " vsri.u8 d4, d4, #6 @ duplicate green bits (extend 6 to 8) \n" +- " vmull.u8 q1, d2, d18 @ apply inverse mask to background red... \n" +- " vmull.u8 q2, d4, d18 @ ...green... \n" +- " vmull.u8 q3, d6, d18 @ ...blue \n" +- " subs %[count], %[count], #1 @ decrement/test loop counter \n" +- " vmlal.u8 q1, d17, d22 @ add masked foreground red... \n" +- " vmlal.u8 q2, d17, d21 @ ...green... \n" +- " vmlal.u8 q3, d17, d20 @ ...blue \n" +- " add %[in_mask], %[in_mask], %[mask_stride] @ advance mask pointer, while we wait \n" +- " vsri.16 q1, q2, #5 @ pack green behind red \n" +- " vsri.16 q1, q3, #11 @ pack blue into pixels \n" +- " vst1.16 {d2, d3}, [%[dest]] @ store composited pixels \n" +- " add %[dest], %[dest], %[dest_stride] @ advance framebuffer pointer \n" +- " bne 0b @ next please \n" +- +- /* Clobbered registers marked as input/outputs */ +- : [dest] "+r" (dest), [in_mask] "+r" (in_mask), [count] "+r" (count) +- +- /* Inputs */ +- : [dest_stride] "r" (dest_stride), [mask_stride] "r" (mask_stride), [glyph_colour] "r" (&glyph_colour) +- +- /* Clobbers, including the inputs we modify, and potentially lots of memory */ +- : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d17", "d18", "d19", +- "d20", "d21", "d22", "d23", "d24", "d25", "cc", "memory" +- ); +- +-#else +- +- uint8x8x4_t solid_colour = vld4_dup_u8 ((uint8_t*) &glyph_colour); +- +- while (count--) +- { +- uint16x8_t pixels = vld1q_u16 (dest); +- uint8x8_t mask = vshrn_n_u16 (vmull_u8 (solid_colour.val[3], vld1_u8 (in_mask)), 8); +- uint8x8_t mask_image = vmvn_u8 (mask); +- +- uint8x8_t t_red = vshrn_n_u16 (pixels, 8); +- uint8x8_t t_green = vshrn_n_u16 (pixels, 3); +- uint8x8_t t_blue = vshrn_n_u16 (vsli_n_u8 (pixels, pixels, 5), 2); +- +- uint16x8_t s_red = vmull_u8 (vsri_n_u8 (t_red, t_red, 5), mask_image); +- uint16x8_t s_green = vmull_u8 (vsri_n_u8 (t_green, t_green, 6), mask_image); +- uint16x8_t s_blue = vmull_u8 (t_blue, mask_image); +- +- s_red = vmlal (s_red, mask, solid_colour.val[2]); +- s_green = vmlal (s_green, mask, solid_colour.val[1]); +- s_blue = vmlal (s_blue, mask, solid_colour.val[0]); +- +- pixels = vsri_n_u16 (s_red, s_green, 5); +- pixels = vsri_n_u16 (pixels, s_blue, 11); +- vst1q_u16 (dest, pixels); +- +- dest += dest_stride; +- mask += mask_stride; +- } +- +-#endif +-} +- +-#if 0 /* this is broken currently */ +-static void +-neon_composite_over_n_8_0565 (pixman_implementation_t * impl, +- pixman_op_t op, +- pixman_image_t * src_image, +- pixman_image_t * mask_image, +- pixman_image_t * dst_image, +- int32_t src_x, +- int32_t src_y, +- int32_t mask_x, +- int32_t mask_y, +- int32_t dest_x, +- int32_t dest_y, +- int32_t width, +- int32_t height) +-{ +- uint32_t src, srca; +- uint16_t *dst_line, *aligned_line; +- uint8_t *mask_line; +- uint32_t dst_stride, mask_stride; +- uint32_t kernel_count, copy_count, copy_tail; +- uint8_t kernel_offset, copy_offset; +- +- src = _pixman_image_get_solid (src_image, dst_image->bits.format); +- +- /* bail out if fully transparent or degenerate */ +- srca = src >> 24; +- if (src == 0) +- return; +- +- if (width == 0 || height == 0) +- return; +- +- if (width > NEON_SCANLINE_BUFFER_PIXELS) +- { +- /* split the blit, so we can use a fixed-size scanline buffer +- * TODO: there must be a more elegant way of doing this. +- */ +- int x; +- for (x = 0; x < width; x += NEON_SCANLINE_BUFFER_PIXELS) +- { +- neon_composite_over_n_8_0565 ( +- impl, op, +- src_image, mask_image, dst_image, +- src_x + x, src_y, mask_x + x, mask_y, dest_x + x, dest_y, +- (x + NEON_SCANLINE_BUFFER_PIXELS > width) ? width - x : NEON_SCANLINE_BUFFER_PIXELS, height); +- } +- +- return; +- } +- +- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); +- PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1); +- +- /* keep within minimum number of aligned quadwords on width +- * while also keeping the minimum number of columns to process +- */ +- { +- unsigned long aligned_left = (unsigned long)(dst_line) & ~0xF; +- unsigned long aligned_right = (((unsigned long)(dst_line + width)) + 0xF) & ~0xF; +- unsigned long ceiling_length = (((unsigned long) width) * sizeof(*dst_line) + 0xF) & ~0xF; +- +- /* the fast copy should be quadword aligned */ +- copy_offset = dst_line - ((uint16_t*) aligned_left); +- aligned_line = dst_line - copy_offset; +- copy_count = (uint32_t) ((aligned_right - aligned_left) >> 4); +- copy_tail = 0; +- +- if (aligned_right - aligned_left > ceiling_length) +- { +- /* unaligned routine is tightest */ +- kernel_count = (uint32_t) (ceiling_length >> 4); +- kernel_offset = copy_offset; +- } +- else +- { +- /* aligned routine is equally tight, so it is safer to align */ +- kernel_count = copy_count; +- kernel_offset = 0; +- } +- +- /* We should avoid reading beyond scanline ends for safety */ +- if (aligned_line < (dst_line - dest_x) || +- (aligned_line + (copy_count * 16 / sizeof(*dst_line))) > ((dst_line - dest_x) + dst_image->bits.width)) +- { +- /* switch to precise read */ +- copy_offset = kernel_offset = 0; +- aligned_line = dst_line; +- kernel_count = (uint32_t) (ceiling_length >> 4); +- copy_count = (width * sizeof(*dst_line)) >> 4; +- copy_tail = (width * sizeof(*dst_line)) & 0xF; +- } +- } +- +- { +- uint16_t scan_line[NEON_SCANLINE_BUFFER_PIXELS + 8]; /* deliberately not initialised */ +- uint8_t glyph_line[NEON_SCANLINE_BUFFER_PIXELS + 8]; +- int y = height; +- +- /* row-major order */ +- /* left edge, middle block, right edge */ +- for ( ; y--; mask_line += mask_stride, aligned_line += dst_stride, dst_line += dst_stride) +- { +- /* We don't want to overrun the edges of the glyph, +- * so realign the edge data into known buffers +- */ +- neon_quadword_copy (glyph_line + copy_offset, mask_line, width >> 4, width & 0xF); +- +- /* Uncached framebuffer access is really, really slow +- * if we do it piecemeal. It should be much faster if we +- * grab it all at once. One scanline should easily fit in +- * L1 cache, so this should not waste RAM bandwidth. +- */ +- neon_quadword_copy (scan_line, aligned_line, copy_count, copy_tail); +- +- /* Apply the actual filter */ +- solid_over_565_8_pix_neon ( +- src, scan_line + kernel_offset, +- glyph_line + kernel_offset, 8 * sizeof(*dst_line), +- 8, kernel_count); +- +- /* Copy the modified scanline back */ +- neon_quadword_copy (dst_line, scan_line + copy_offset, +- width >> 3, (width & 7) * 2); +- } +- } +-} +-#endif +- +-#ifdef USE_GCC_INLINE_ASM +- +-static inline void +-plain_over_565_8_pix_neon (uint32_t colour, +- uint16_t *dest, +- uint32_t dest_stride, /* bytes, not elements */ +- uint32_t count /* 8-pixel groups */) +-{ +- /* Inner loop for plain translucent rects +- * (solid colour without alpha mask) +- */ +- asm volatile ( +- " vld4.8 {d20[], d21[], d22[], d23[]}, [%[colour]] @ solid colour load/splat \n" +- " vmull.u8 q12, d23, d22 @ premultiply alpha red \n" +- " vmull.u8 q13, d23, d21 @ premultiply alpha green \n" +- " vmull.u8 q14, d23, d20 @ premultiply alpha blue \n" +- " vmvn d18, d23 @ inverse alpha for background \n" +- "0: @ loop\n" +- " vld1.16 {d0, d1}, [%[dest]] @ load first pixels from framebuffer \n" +- " vshrn.u16 d2, q0, #8 @ unpack red from framebuffer pixels \n" +- " vshrn.u16 d4, q0, #3 @ unpack green \n" +- " vsli.u16 q3, q0, #5 @ duplicate framebuffer blue bits \n" +- " vsri.u8 d2, d2, #5 @ duplicate red bits (extend 5 to 8) \n" +- " vsri.u8 d4, d4, #6 @ duplicate green bits (extend 6 to 8) \n" +- " vshrn.u16 d6, q3, #2 @ unpack extended blue (truncate 10 to 8) \n" +- " vmov q0, q12 @ retrieve foreground red \n" +- " vmlal.u8 q0, d2, d18 @ blend red - my kingdom for a four-operand MLA \n" +- " vmov q1, q13 @ retrieve foreground green \n" +- " vmlal.u8 q1, d4, d18 @ blend green \n" +- " vmov q2, q14 @ retrieve foreground blue \n" +- " vmlal.u8 q2, d6, d18 @ blend blue \n" +- " subs %[count], %[count], #1 @ decrement/test loop counter \n" +- " vsri.16 q0, q1, #5 @ pack green behind red \n" +- " vsri.16 q0, q2, #11 @ pack blue into pixels \n" +- " vst1.16 {d0, d1}, [%[dest]] @ store composited pixels \n" +- " add %[dest], %[dest], %[dest_stride] @ advance framebuffer pointer \n" +- " bne 0b @ next please \n" +- +- /* Clobbered registers marked as input/outputs */ +- : [dest] "+r" (dest), [count] "+r" (count) +- +- /* Inputs */ +- : [dest_stride] "r" (dest_stride), [colour] "r" (&colour) +- +- /* Clobbers, including the inputs we modify, and +- * potentially lots of memory +- */ +- : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d18", "d19", +- "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", +- "cc", "memory" +- ); +-} +- +-static void +-neon_composite_over_n_0565 (pixman_implementation_t * impl, +- pixman_op_t op, +- pixman_image_t * src_image, +- pixman_image_t * mask_image, +- pixman_image_t * dst_image, +- int32_t src_x, +- int32_t src_y, +- int32_t mask_x, +- int32_t mask_y, +- int32_t dest_x, +- int32_t dest_y, +- int32_t width, +- int32_t height) +-{ +- uint32_t src, srca; +- uint16_t *dst_line, *aligned_line; +- uint32_t dst_stride; +- uint32_t kernel_count, copy_count, copy_tail; +- uint8_t kernel_offset, copy_offset; +- +- src = _pixman_image_get_solid (src_image, dst_image->bits.format); +- +- /* bail out if fully transparent */ +- srca = src >> 24; +- if (src == 0) +- return; +- +- if (width == 0 || height == 0) +- return; +- +- if (width > NEON_SCANLINE_BUFFER_PIXELS) +- { +- /* split the blit, so we can use a fixed-size scanline buffer * +- * TODO: there must be a more elegant way of doing this. +- */ +- int x; +- +- for (x = 0; x < width; x += NEON_SCANLINE_BUFFER_PIXELS) +- { +- neon_composite_over_n_0565 ( +- impl, op, +- src_image, mask_image, dst_image, +- src_x + x, src_y, mask_x + x, mask_y, dest_x + x, dest_y, +- (x + NEON_SCANLINE_BUFFER_PIXELS > width) ? width - x : NEON_SCANLINE_BUFFER_PIXELS, height); +- } +- return; +- } +- +- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); +- +- /* keep within minimum number of aligned quadwords on width +- * while also keeping the minimum number of columns to process +- */ +- { +- unsigned long aligned_left = (unsigned long)(dst_line) & ~0xF; +- unsigned long aligned_right = (((unsigned long)(dst_line + width)) + 0xF) & ~0xF; +- unsigned long ceiling_length = (((unsigned long) width) * sizeof(*dst_line) + 0xF) & ~0xF; +- +- /* the fast copy should be quadword aligned */ +- copy_offset = dst_line - ((uint16_t*) aligned_left); +- aligned_line = dst_line - copy_offset; +- copy_count = (uint32_t) ((aligned_right - aligned_left) >> 4); +- copy_tail = 0; +- +- if (aligned_right - aligned_left > ceiling_length) +- { +- /* unaligned routine is tightest */ +- kernel_count = (uint32_t) (ceiling_length >> 4); +- kernel_offset = copy_offset; +- } +- else +- { +- /* aligned routine is equally tight, so it is safer to align */ +- kernel_count = copy_count; +- kernel_offset = 0; +- } +- +- /* We should avoid reading beyond scanline ends for safety */ +- if (aligned_line < (dst_line - dest_x) || +- (aligned_line + (copy_count * 16 / sizeof(*dst_line))) > ((dst_line - dest_x) + dst_image->bits.width)) +- { +- /* switch to precise read */ +- copy_offset = kernel_offset = 0; +- aligned_line = dst_line; +- kernel_count = (uint32_t) (ceiling_length >> 4); +- copy_count = (width * sizeof(*dst_line)) >> 4; +- copy_tail = (width * sizeof(*dst_line)) & 0xF; +- } +- } +- +- { +- uint16_t scan_line[NEON_SCANLINE_BUFFER_PIXELS + 8]; /* deliberately not initialised */ +- +- /* row-major order */ +- /* left edge, middle block, right edge */ +- for ( ; height--; aligned_line += dst_stride, dst_line += dst_stride) +- { +- /* Uncached framebuffer access is really, really slow if we do it piecemeal. +- * It should be much faster if we grab it all at once. +- * One scanline should easily fit in L1 cache, so this should +- * not waste RAM bandwidth. +- */ +- neon_quadword_copy (scan_line, aligned_line, copy_count, copy_tail); +- +- /* Apply the actual filter */ +- plain_over_565_8_pix_neon ( +- src, scan_line + kernel_offset, 8 * sizeof(*dst_line), kernel_count); +- +- /* Copy the modified scanline back */ +- neon_quadword_copy ( +- dst_line, scan_line + copy_offset, width >> 3, (width & 7) * 2); +- } +- } +-} +- +-static inline void +-ARGB8_over_565_8_pix_neon (uint32_t *src, +- uint16_t *dest, +- uint32_t src_stride, /* bytes, not elements */ +- uint32_t count /* 8-pixel groups */) +-{ +- asm volatile ( +- "0: @ loop\n" +- " pld [%[src], %[src_stride]] @ preload from next scanline \n" +- " vld1.16 {d0, d1}, [%[dest]] @ load pixels from framebuffer \n" +- " vld4.8 {d20, d21, d22, d23},[%[src]]! @ load source image pixels \n" +- " vsli.u16 q3, q0, #5 @ duplicate framebuffer blue bits \n" +- " vshrn.u16 d2, q0, #8 @ unpack red from framebuffer pixels \n" +- " vshrn.u16 d4, q0, #3 @ unpack green \n" +- " vmvn d18, d23 @ we need the inverse alpha for the background \n" +- " vsri.u8 d2, d2, #5 @ duplicate red bits (extend 5 to 8) \n" +- " vshrn.u16 d6, q3, #2 @ unpack extended blue (truncate 10 to 8) \n" +- " vsri.u8 d4, d4, #6 @ duplicate green bits (extend 6 to 8) \n" +- " vmull.u8 q1, d2, d18 @ apply inverse alpha to background red... \n" +- " vmull.u8 q2, d4, d18 @ ...green... \n" +- " vmull.u8 q3, d6, d18 @ ...blue \n" +- " subs %[count], %[count], #1 @ decrement/test loop counter \n" +- " vmlal.u8 q1, d23, d22 @ add blended foreground red... \n" +- " vmlal.u8 q2, d23, d21 @ ...green... \n" +- " vmlal.u8 q3, d23, d20 @ ...blue \n" +- " vsri.16 q1, q2, #5 @ pack green behind red \n" +- " vsri.16 q1, q3, #11 @ pack blue into pixels \n" +- " vst1.16 {d2, d3}, [%[dest]]! @ store composited pixels \n" +- " bne 0b @ next please \n" +- +- /* Clobbered registers marked as input/outputs */ +- : [dest] "+r" (dest), [src] "+r" (src), [count] "+r" (count) +- +- /* Inputs */ +- : [src_stride] "r" (src_stride) +- +- /* Clobbers, including the inputs we modify, and potentially lots of memory */ +- : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d17", "d18", "d20", +- "d21", "d22", "d23", "cc", "memory" +- ); +-} +- +-static void +-neon_composite_over_8888_0565 (pixman_implementation_t * impl, +- pixman_op_t op, +- pixman_image_t * src_image, +- pixman_image_t * mask_image, +- pixman_image_t * dst_image, +- int32_t src_x, +- int32_t src_y, +- int32_t mask_x, +- int32_t mask_y, +- int32_t dest_x, +- int32_t dest_y, +- int32_t width, +- int32_t height) +-{ +- uint32_t *src_line; +- uint16_t *dst_line, *aligned_line; +- uint32_t dst_stride, src_stride; +- uint32_t kernel_count, copy_count, copy_tail; +- uint8_t kernel_offset, copy_offset; +- +- /* we assume mask is opaque +- * so the only alpha to deal with is embedded in src +- */ +- if (width > NEON_SCANLINE_BUFFER_PIXELS) +- { +- /* split the blit, so we can use a fixed-size scanline buffer */ +- int x; +- for (x = 0; x < width; x += NEON_SCANLINE_BUFFER_PIXELS) +- { +- neon_composite_over_8888_0565 ( +- impl, op, +- src_image, mask_image, dst_image, +- src_x + x, src_y, mask_x + x, mask_y, dest_x + x, dest_y, +- (x + NEON_SCANLINE_BUFFER_PIXELS > width) ? width - x : NEON_SCANLINE_BUFFER_PIXELS, height); +- } +- return; +- } +- +- PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); +- PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); +- +- /* keep within minimum number of aligned quadwords on width +- * while also keeping the minimum number of columns to process +- */ +- { +- unsigned long aligned_left = (unsigned long)(dst_line) & ~0xF; +- unsigned long aligned_right = (((unsigned long)(dst_line + width)) + 0xF) & ~0xF; +- unsigned long ceiling_length = (((unsigned long) width) * sizeof(*dst_line) + 0xF) & ~0xF; +- +- /* the fast copy should be quadword aligned */ +- copy_offset = dst_line - ((uint16_t*) aligned_left); +- aligned_line = dst_line - copy_offset; +- copy_count = (uint32_t) ((aligned_right - aligned_left) >> 4); +- copy_tail = 0; +- +- if (aligned_right - aligned_left > ceiling_length) +- { +- /* unaligned routine is tightest */ +- kernel_count = (uint32_t) (ceiling_length >> 4); +- kernel_offset = copy_offset; +- } +- else +- { +- /* aligned routine is equally tight, so it is safer to align */ +- kernel_count = copy_count; +- kernel_offset = 0; +- } +- +- /* We should avoid reading beyond scanline ends for safety */ +- if (aligned_line < (dst_line - dest_x) || +- (aligned_line + (copy_count * 16 / sizeof(*dst_line))) > ((dst_line - dest_x) + dst_image->bits.width)) +- { +- /* switch to precise read */ +- copy_offset = kernel_offset = 0; +- aligned_line = dst_line; +- kernel_count = (uint32_t) (ceiling_length >> 4); +- copy_count = (width * sizeof(*dst_line)) >> 4; +- copy_tail = (width * sizeof(*dst_line)) & 0xF; +- } +- } +- +- /* Preload the first input scanline */ +- { +- uint8_t *src_ptr = (uint8_t*) src_line; +- uint32_t count = (width + 15) / 16; +- +-#ifdef USE_GCC_INLINE_ASM +- asm volatile ( +- "0: @ loop \n" +- " subs %[count], %[count], #1 \n" +- " pld [%[src]] \n" +- " add %[src], %[src], #64 \n" +- " bgt 0b \n" +- +- /* Clobbered input registers marked as input/outputs */ +- : [src] "+r" (src_ptr), [count] "+r" (count) +- : /* no unclobbered inputs */ +- : "cc" +- ); +-#else +- do +- { +- __pld (src_ptr); +- src_ptr += 64; +- } +- while (--count); +-#endif +- } +- +- { +- uint16_t scan_line[NEON_SCANLINE_BUFFER_PIXELS + 8]; /* deliberately not initialised */ +- +- /* row-major order */ +- /* left edge, middle block, right edge */ +- for ( ; height--; src_line += src_stride, aligned_line += dst_stride) +- { +- /* Uncached framebuffer access is really, really slow if we do +- * it piecemeal. It should be much faster if we grab it all at +- * once. One scanline should easily fit in L1 cache, so this +- * should not waste RAM bandwidth. +- */ +- neon_quadword_copy (scan_line, aligned_line, copy_count, copy_tail); +- +- /* Apply the actual filter */ +- ARGB8_over_565_8_pix_neon ( +- src_line, scan_line + kernel_offset, +- src_stride * sizeof(*src_line), kernel_count); +- +- /* Copy the modified scanline back */ +- neon_quadword_copy (dst_line, +- scan_line + copy_offset, +- width >> 3, (width & 7) * 2); +- } +- } +-} +- +-#endif /* USE_GCC_INLINE_ASM */ +- + static const pixman_fast_path_t arm_neon_fast_path_array[] = + { + { PIXMAN_OP_ADD, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, neon_composite_add_8888_8_8, 0 }, +@@ -2612,12 +1908,6 @@ static const pixman_fast_path_t arm_neon_fast_path_array[] = + #ifdef USE_GCC_INLINE_ASM + { PIXMAN_OP_SRC, PIXMAN_r5g6b5, PIXMAN_null, PIXMAN_r5g6b5, neon_composite_src_16_16, 0 }, + { PIXMAN_OP_SRC, PIXMAN_b5g6r5, PIXMAN_null, PIXMAN_b5g6r5, neon_composite_src_16_16, 0 }, +-#if 0 /* this code has some bugs */ +- { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_r5g6b5, neon_composite_over_n_0565, 0 }, +- { PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_b5g6r5, neon_composite_over_n_0565, 0 }, +- { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, neon_composite_over_8888_0565, 0 }, +- { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, neon_composite_over_8888_0565, 0 }, +-#endif + #endif + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, neon_composite_over_8888_8888, 0 }, + { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, neon_composite_over_8888_8888, 0 }, +@@ -2668,79 +1958,6 @@ arm_neon_composite (pixman_implementation_t *imp, + } + + static pixman_bool_t +-pixman_blt_neon (void *src_bits, +- void *dst_bits, +- int src_stride, +- int dst_stride, +- int src_bpp, +- int dst_bpp, +- int src_x, +- int src_y, +- int dst_x, +- int dst_y, +- int width, +- int height) +-{ +- if (!width || !height) +- return TRUE; +- +- /* accelerate only straight copies involving complete bytes */ +- if (src_bpp != dst_bpp || (src_bpp & 7)) +- return FALSE; +- +- { +- uint32_t bytes_per_pixel = src_bpp >> 3; +- uint32_t byte_width = width * bytes_per_pixel; +- /* parameter is in words for some reason */ +- int32_t src_stride_bytes = src_stride * 4; +- int32_t dst_stride_bytes = dst_stride * 4; +- uint8_t *src_bytes = ((uint8_t*) src_bits) + +- src_y * src_stride_bytes + src_x * bytes_per_pixel; +- uint8_t *dst_bytes = ((uint8_t*) dst_bits) + +- dst_y * dst_stride_bytes + dst_x * bytes_per_pixel; +- uint32_t quadword_count = byte_width / 16; +- uint32_t offset = byte_width % 16; +- +- while (height--) +- { +- neon_quadword_copy (dst_bytes, src_bytes, quadword_count, offset); +- src_bytes += src_stride_bytes; +- dst_bytes += dst_stride_bytes; +- } +- } +- +- return TRUE; +-} +- +-static pixman_bool_t +-arm_neon_blt (pixman_implementation_t *imp, +- uint32_t * src_bits, +- uint32_t * dst_bits, +- int src_stride, +- int dst_stride, +- int src_bpp, +- int dst_bpp, +- int src_x, +- int src_y, +- int dst_x, +- int dst_y, +- int width, +- int height) +-{ +- if (pixman_blt_neon ( +- src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, +- src_x, src_y, dst_x, dst_y, width, height)) +- { +- return TRUE; +- } +- +- return _pixman_implementation_blt ( +- imp->delegate, +- src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, +- src_x, src_y, dst_x, dst_y, width, height); +-} +- +-static pixman_bool_t + arm_neon_fill (pixman_implementation_t *imp, + uint32_t * bits, + int stride, +@@ -2765,9 +1982,6 @@ _pixman_implementation_create_arm_neon (void) + pixman_implementation_t *imp = _pixman_implementation_create (simd); + + imp->composite = arm_neon_composite; +-#if 0 /* this code has some bugs */ +- imp->blt = arm_neon_blt; +-#endif + imp->fill = arm_neon_fill; + + return imp; diff --git a/recipes/xorg-lib/pixman_git.bb b/recipes/xorg-lib/pixman_git.bb index 2ba06af67e..b8aa2a43c6 100644 --- a/recipes/xorg-lib/pixman_git.bb +++ b/recipes/xorg-lib/pixman_git.bb @@ -3,16 +3,20 @@ PRIORITY = "optional" DESCRIPTION = "Low-level pixel manipulation library." LICENSE = "X11" -PV = "0.15.16" -PR = "r1" +PV = "0.17.1" +PR = "r2" PR_append = "+gitr${SRCREV}" -SRCREV = "f9660ce29ed072c6cbaec711c5d18b9f0ba113ae" +SRCREV = "7af985a69a9147e54dd5946a8062dbc2e534b735" DEFAULT_PREFERENCE = "-1" DEFAULT_PREFERENCE_angstrom = "1" SRC_URI = "git://anongit.freedesktop.org/pixman;protocol=git \ + file://pixman-28986.patch;patch=1 \ + file://nearest-neighbour.patch;patch=1 \ + file://remove-broken.patch;patch=1 \ + file://over-8888-0565.patch;patch=1 \ " S = "${WORKDIR}/git" diff --git a/recipes/xscreensaver/xscreensaver.inc b/recipes/xscreensaver/xscreensaver.inc index a4925ac108..5f8cdc0074 100644 --- a/recipes/xscreensaver/xscreensaver.inc +++ b/recipes/xscreensaver/xscreensaver.inc @@ -10,6 +10,7 @@ DEPENDS = "intltool mesa freeglut virtual/libx11 gtk+ libxml2 libglade" # xscreensaver-demo is a glade app LDFLAGS_append = " -Wl,--export-dynamic" +TARGET_CC_ARCH += "${LDFLAGS}" inherit autotools @@ -30,7 +31,7 @@ EXTRA_OECONF=" --with-xml \ PACKAGES =+ " xscreensaver-demo xscreensaver-extra" -FILES_${PN}= "${bindir}/xscreensaver ${bindir}/xscreensaver-command ${datadir}/applications \ +FILES_${PN}= "${bindir}/xscreensaver ${bindir}/xscreensaver-text ${bindir}/xscreensaver-command ${datadir}/applications \ ${libdir}/X11/" FILES_${PN}-dbg += "${libexecdir}/xscreensaver/.debug" diff --git a/recipes/xscreensaver/xscreensaver_5.07.bb b/recipes/xscreensaver/xscreensaver_5.07.bb index 8932b6fd3c..cfe5cccdaa 100644 --- a/recipes/xscreensaver/xscreensaver_5.07.bb +++ b/recipes/xscreensaver/xscreensaver_5.07.bb @@ -1,5 +1,5 @@ require xscreensaver.inc -PR = "r2" +PR = "r3" SRC_URI = "http://www.jwz.org/xscreensaver/xscreensaver-${PV}.tar.gz \ file://configure.in.patch;patch=1 \ |
