From b31c446ecd85a506af75d9ca609d99f03796e081 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Sun, 1 Sep 2013 19:22:36 +0200 Subject: smdk4412: add opensource camera hal Change-Id: Icb555cc6158247c32a6feb5d846bcf4d727749af --- camera/Android.mk | 54 + camera/MODULE_LICENSE_GPL | 0 camera/NOTICE | 674 ++++ camera/exynos_camera.c | 4318 ++++++++++++++++++++++++ camera/exynos_camera.h | 679 ++++ camera/exynos_exif.c | 873 +++++ camera/exynos_ion.c | 159 + camera/exynos_jpeg.c | 404 +++ camera/exynos_param.c | 492 +++ camera/exynos_utils.c | 158 + camera/exynos_v4l2.c | 739 ++++ camera/exynos_v4l2_output.c | 387 +++ camera/include/linux/fimc.h | 381 +++ camera/include/linux/ion.h | 449 +++ camera/include/linux/s5c73m3.h | 371 ++ camera/include/linux/videodev2.h | 2364 +++++++++++++ camera/include/linux/videodev2_exynos_camera.h | 1363 ++++++++ camera/include/linux/videodev2_exynos_media.h | 225 ++ 18 files changed, 14090 insertions(+) create mode 100644 camera/Android.mk create mode 100644 camera/MODULE_LICENSE_GPL create mode 100644 camera/NOTICE create mode 100644 camera/exynos_camera.c create mode 100644 camera/exynos_camera.h create mode 100644 camera/exynos_exif.c create mode 100644 camera/exynos_ion.c create mode 100644 camera/exynos_jpeg.c create mode 100644 camera/exynos_param.c create mode 100644 camera/exynos_utils.c create mode 100644 camera/exynos_v4l2.c create mode 100644 camera/exynos_v4l2_output.c create mode 100644 camera/include/linux/fimc.h create mode 100644 camera/include/linux/ion.h create mode 100644 camera/include/linux/s5c73m3.h create mode 100644 camera/include/linux/videodev2.h create mode 100644 camera/include/linux/videodev2_exynos_camera.h create mode 100644 camera/include/linux/videodev2_exynos_media.h (limited to 'camera') diff --git a/camera/Android.mk b/camera/Android.mk new file mode 100644 index 0000000..dc48ea1 --- /dev/null +++ b/camera/Android.mk @@ -0,0 +1,54 @@ +# +# Copyright (C) 2013 Paul Kocialkowski +# +# 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 3 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, see . +# + +ifneq ($(filter i9300 i9305 n7100 t0lte t0lteatt t0ltetmo i605 l900 r950 i925,$(TARGET_DEVICE)),) + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + exynos_camera.c \ + exynos_exif.c \ + exynos_jpeg.c \ + exynos_param.c \ + exynos_utils.c \ + exynos_v4l2.c \ + exynos_v4l2_output.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + hardware/samsung/exynos4/hal/include + +LOCAL_SHARED_LIBRARIES := libutils libcutils liblog libcamera_client libhardware +LOCAL_PRELINK_MODULE := false + +ifeq ($(TARGET_SOC),exynos4x12) + LOCAL_SHARED_LIBRARIES += libhwjpeg + LOCAL_CFLAGS += -DEXYNOS_JPEG_HW + + LOCAL_SRC_FILES += exynos_ion.c + LOCAL_CFLAGS += -DEXYNOS_ION +endif + +LOCAL_MODULE := camera.$(TARGET_BOOTLOADER_BOARD_NAME) +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) + +endif diff --git a/camera/MODULE_LICENSE_GPL b/camera/MODULE_LICENSE_GPL new file mode 100644 index 0000000..e69de29 diff --git a/camera/NOTICE b/camera/NOTICE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/camera/NOTICE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c new file mode 100644 index 0000000..e002231 --- /dev/null +++ b/camera/exynos_camera.c @@ -0,0 +1,4318 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski + * + * Based on crespo libcamera and exynos4 hal libcamera: + * Copyright 2008, The Android Open Source Project + * Copyright 2010, Samsung Electronics Co. LTD + * + * 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 3 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define LOG_TAG "exynos_camera" +#include +#include + +#include "exynos_camera.h" + +#define BIG2LITTLE_ENDIAN(big) ((big & 0xff) << 24 | (big & 0xff00) << 8 | (big & 0xff0000) >> 8 | (big & 0xff000000) >> 24) + +/* + * Devices configurations + */ + +struct exynos_camera_mbus_resolution exynos_camera_mbus_resolutions_s5k6a3_smdk4x12[] = { + // 16:9 ratio + { 1280, 720, 1344, 756 }, + // 4:3 ratio + { 1280, 960, 1392, 1044 }, + { 960, 720, 1392, 1044 }, + { 640, 480, 1392, 1044 }, + { 320, 240, 1392, 1044 }, + // 1:1 ratio + { 1392, 1392, 1392, 1392 }, + { 704, 704, 1392, 1392 }, + { 320, 320, 1392, 1392 }, +}; + +struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { + { + .name = "S5C73M3", + .facing = CAMERA_FACING_BACK, + .orientation = 90, + .rotation = 0, + .hflip = 0, + .vflip = 0, + .capture_format = V4L2_PIX_FMT_INTERLEAVED, + .picture_format = 0, + .fimc_is = 0, + .focal_length = 3.7f, + .horizontal_view_angle = 63.0f, + .vertical_view_angle = 49.3f, + .metering = METERING_CENTER, + .params = { + .preview_size_values = "960x720,1280x720,1184x666,960x640,704x576,640x480,352x288,320x240", + .preview_size = "960x720", + .preview_format_values = "yuv420sp,yuv420p,rgb565", + .preview_format = "yuv420sp", + .preview_frame_rate_values = "30,20,15", + .preview_frame_rate = 30, + .preview_fps_range_values = "(15000,15000),(15000,30000),(30000,30000)", + .preview_fps_range = "15000,30000", + + .picture_size_values = "640x480,1024x768,1280x720,1600x1200,2560x1920,3264x2448,2048x1536,3264x1836,2048x1152,3264x2176", + .picture_size = "3264x2448", + .picture_format_values = "jpeg", + .picture_format = "jpeg", + .jpeg_thumbnail_size_values = "160x120,160x90,144x96", + .jpeg_thumbnail_width = 160, + .jpeg_thumbnail_height = 160, + .jpeg_thumbnail_quality = 100, + .jpeg_quality = 90, + + .video_snapshot_supported = 0, + .full_video_snap_supported = 0, + + .recording_size = "1280x720", + .recording_size_values = "1280x720,1920x1080,720x480,640x480,352x288,320x240,176x144", + .recording_format = "yuv420sp", + + .focus_mode = "continuous-picture", + .focus_mode_values = "auto,infinity,macro,fixed,continuous-picture,continuous-video", + .focus_distances = "0.15,1.20,Infinity", + .focus_areas = NULL, + .max_num_focus_areas = 1, + + .zoom_supported = 1, + .smooth_zoom_supported = 0, + .zoom_ratios = "100,102,104,109,111,113,119,121,124,131,134,138,146,150,155,159,165,170,182,189,200,213,222,232,243,255,283,300,319,364,400", + .zoom = 0, + .max_zoom = 30, + + .flash_mode = "off", + .flash_mode_values = "off,auto,on,torch", + + .exposure_compensation = 0, + .exposure_compensation_step = 0.5, + .min_exposure_compensation = -4, + .max_exposure_compensation = 4, + + .whitebalance = "auto", + .whitebalance_values = "auto,incandescent,fluorescent,daylight,cloudy-daylight", + + .antibanding = "50hz", + .antibanding_values = "50hz,off", + + .scene_mode = "auto", + .scene_mode_values = "auto,portrait,landscape,night,beach,snow,sunset,fireworks,sports,party,candlelight,dusk-dawn,fall-color,text,back-light", + + .effect = "none", + .effect_values = "none,mono,negative,sepia,solarize,posterize,washed,vintage-warm,vintage-cold,point-blue,point-red-yellow,point-green", + + .iso = "auto", + .iso_values = "auto,ISO100,ISO200,ISO400,ISO800", + }, + .mbus_resolutions = NULL, + .mbus_resolutions_count = 0, + }, + { + .name = "S5K6A3", + .facing = CAMERA_FACING_FRONT, + .orientation = 270, + .rotation = 0, + .hflip = 0, + .vflip = 0, + .capture_format = 0, + .picture_format = V4L2_PIX_FMT_YUYV, + .fimc_is = 1, + .focal_length = 2.73f, + .horizontal_view_angle = 52.58f, + .vertical_view_angle = 52.58f, + .metering = METERING_CENTER, + .params = { + .preview_size_values = "1280x720,960x720,640x480,320x240,704x704,320x320", + .preview_size = "960x720", + .preview_format_values = "yuv420sp,yuv420p,rgb565", + .preview_format = "yuv420sp", + .preview_frame_rate_values = "30,20,15,8", + .preview_frame_rate = 30, + .preview_fps_range_values = "(8000,8000),(15000,15000),(15000,30000),(30000,30000)", + .preview_fps_range = "15000,30000", + + .picture_size_values = "1344x756,1280x720,1392x1044,1280x960,960x720,640x480,1392x1392", + .picture_size = "1280x960", + .picture_format_values = "jpeg", + .picture_format = "jpeg", + .jpeg_thumbnail_size_values = "160x120,160x160,160x90,144x96", + .jpeg_thumbnail_width = 160, + .jpeg_thumbnail_height = 120, + .jpeg_thumbnail_quality = 100, + .jpeg_quality = 90, + + .video_snapshot_supported = 0, + .full_video_snap_supported = 0, + + .recording_size = "1280x720", + .recording_size_values = "1280x720,720x480,640x480,352x288,320x320,320x240,176x144", + .recording_format = "yuv420sp", + + .focus_mode = "fixed", + .focus_mode_values = "infinity,fixed", + .focus_distances = "0.20,0.25,Infinity", + .focus_areas = NULL, + .max_num_focus_areas = 0, + + .zoom_supported = 0, + + .flash_mode = NULL, + .flash_mode_values = NULL, + + .exposure_compensation = 0, + .exposure_compensation_step = 0.5, + .min_exposure_compensation = -4, + .max_exposure_compensation = 4, + + .whitebalance = "auto", + .whitebalance_values = "auto,incandescent,fluorescent,daylight,cloudy-daylight", + + .antibanding = NULL, + .antibanding_values = NULL, + + .scene_mode = NULL, + .scene_mode_values = NULL, + + .effect = "none", + .effect_values = "none,mono,negative,sepia,solarize,posterize,washed,vintage-warm,vintage-cold,point-blue,point-red-yellow,point-green", + + .iso = "auto", + .iso_values = "auto", + }, + .mbus_resolutions = (struct exynos_camera_mbus_resolution *) &exynos_camera_mbus_resolutions_s5k6a3_smdk4x12, + .mbus_resolutions_count = 8, + }, +}; + +struct exynos_v4l2_node exynos_v4l2_nodes_smdk4x12[] = { + { // FIMC0 is used for capture + .id = 0, + .node = "/dev/video0", + }, + { // FIMC1 is used for preview output + .id = 1, + .node = "/dev/video1", + }, + { // FIMC2 is used for picture output + .id = 2, + .node = "/dev/video2", + }, + { // FIMC3 is used for recording output + .id = 3, + .node = "/dev/video3", + }, +}; + +struct exynox_camera_config exynos_camera_config_smdk4x12 = { + .presets = (struct exynos_camera_preset *) &exynos_camera_presets_smdk4x12, + .presets_count = 2, + .v4l2_nodes = (struct exynos_v4l2_node *) &exynos_v4l2_nodes_smdk4x12, + .v4l2_nodes_count = 4, +}; + +/* + * Exynos Camera + */ + +struct exynox_camera_config *exynos_camera_config = + &exynos_camera_config_smdk4x12; + +int exynos_camera_start(struct exynos_camera *exynos_camera, int id) +{ + int rc; + + if (exynos_camera == NULL || id >= exynos_camera->config->presets_count) + return -EINVAL; + + // ION + +#ifdef EXYNOS_ION + rc = exynos_ion_init(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to init ION", __func__); + goto error; + } + + rc = exynos_ion_open(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to open ION", __func__); + goto error; + } +#endif + + // V4L2 + + rc = exynos_v4l2_init(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to init v4l2", __func__); + goto error; + } + + // FIMC0 + + rc = exynos_v4l2_open(exynos_camera, 0); + if (rc < 0) { + ALOGE("%s: Unable to open v4l2 device", __func__); + goto error; + } + + rc = exynos_v4l2_querycap_cap(exynos_camera, 0); + if (rc < 0) { + ALOGE("%s: Unable to query capabilities", __func__); + goto error; + } + + rc = exynos_v4l2_enum_input(exynos_camera, 0, id); + if (rc < 0) { + ALOGE("%s: Unable to enumerate input", __func__); + goto error; + } + + rc = exynos_v4l2_s_input(exynos_camera, 0, id); + if (rc < 0) { + ALOGE("%s: Unable to set inputs", __func__); + goto error; + } + + // Recording + + exynos_camera->recording_metadata = 1; + + // Params + + rc = exynos_camera_params_init(exynos_camera, id); + if (rc < 0) { + ALOGE("%s: Unable to init params", __func__); + goto error; + } + + // Gralloc + + rc = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const struct hw_module_t **) &exynos_camera->gralloc); + if (rc) + ALOGE("%s: Unable to get gralloc module", __func__); + + rc = 0; + goto complete; + +error: + exynos_v4l2_close(exynos_camera, 0); + +#ifdef EXYNOS_ION + exynos_ion_close(exynos_camera); +#endif + + rc = -1; + +complete: + return rc; +} + +void exynos_camera_stop(struct exynos_camera *exynos_camera) +{ + int i; + int id; + + if (exynos_camera == NULL || exynos_camera->config == NULL) + return; + + exynos_v4l2_close(exynos_camera, 0); + +#ifdef EXYNOS_ION + exynos_ion_close(exynos_camera); +#endif +} + +// Params + +int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id) +{ + int rc; + + if (exynos_camera == NULL || id >= exynos_camera->config->presets_count) + return -EINVAL; + + // Camera params + + exynos_camera->camera_rotation = exynos_camera->config->presets[id].rotation; + exynos_camera->camera_hflip = exynos_camera->config->presets[id].hflip; + exynos_camera->camera_vflip = exynos_camera->config->presets[id].vflip; + exynos_camera->camera_capture_format = exynos_camera->config->presets[id].capture_format; + exynos_camera->camera_picture_format = exynos_camera->config->presets[id].picture_format; + exynos_camera->camera_fimc_is = exynos_camera->config->presets[id].fimc_is; + exynos_camera->camera_focal_length = (int) (exynos_camera->config->presets[id].focal_length * 100); + exynos_camera->camera_metering = exynos_camera->config->presets[id].metering; + + exynos_camera->camera_mbus_resolutions = exynos_camera->config->presets[id].mbus_resolutions; + exynos_camera->camera_mbus_resolutions_count = exynos_camera->config->presets[id].mbus_resolutions_count; + + // Recording preview + + exynos_param_string_set(exynos_camera, "preferred-preview-size-for-video", + exynos_camera->config->presets[id].params.preview_size); + + // Preview + + exynos_param_string_set(exynos_camera, "preview-size-values", + exynos_camera->config->presets[id].params.preview_size_values); + exynos_param_string_set(exynos_camera, "preview-size", + exynos_camera->config->presets[id].params.preview_size); + exynos_param_string_set(exynos_camera, "preview-format-values", + exynos_camera->config->presets[id].params.preview_format_values); + exynos_param_string_set(exynos_camera, "preview-format", + exynos_camera->config->presets[id].params.preview_format); + exynos_param_string_set(exynos_camera, "preview-frame-rate-values", + exynos_camera->config->presets[id].params.preview_frame_rate_values); + exynos_param_int_set(exynos_camera, "preview-frame-rate", + exynos_camera->config->presets[id].params.preview_frame_rate); + exynos_param_string_set(exynos_camera, "preview-fps-range-values", + exynos_camera->config->presets[id].params.preview_fps_range_values); + exynos_param_string_set(exynos_camera, "preview-fps-range", + exynos_camera->config->presets[id].params.preview_fps_range); + + // Picture + + exynos_param_string_set(exynos_camera, "picture-size-values", + exynos_camera->config->presets[id].params.picture_size_values); + exynos_param_string_set(exynos_camera, "picture-size", + exynos_camera->config->presets[id].params.picture_size); + exynos_param_string_set(exynos_camera, "picture-format-values", + exynos_camera->config->presets[id].params.picture_format_values); + exynos_param_string_set(exynos_camera, "picture-format", + exynos_camera->config->presets[id].params.picture_format); + exynos_param_string_set(exynos_camera, "jpeg-thumbnail-size-values", + exynos_camera->config->presets[id].params.jpeg_thumbnail_size_values); + exynos_param_int_set(exynos_camera, "jpeg-thumbnail-width", + exynos_camera->config->presets[id].params.jpeg_thumbnail_width); + exynos_param_int_set(exynos_camera, "jpeg-thumbnail-height", + exynos_camera->config->presets[id].params.jpeg_thumbnail_height); + exynos_param_int_set(exynos_camera, "jpeg-thumbnail-quality", + exynos_camera->config->presets[id].params.jpeg_thumbnail_quality); + exynos_param_int_set(exynos_camera, "jpeg-quality", + exynos_camera->config->presets[id].params.jpeg_quality); + + if (exynos_camera->config->presets[id].params.video_snapshot_supported == 1) + exynos_param_string_set(exynos_camera, "video-snapshot-supported", "true"); + if (exynos_camera->config->presets[id].params.full_video_snap_supported == 1) + exynos_param_string_set(exynos_camera, "full-video-snap-supported", "true"); + + // Recording + + exynos_param_string_set(exynos_camera, "video-size", + exynos_camera->config->presets[id].params.recording_size); + exynos_param_string_set(exynos_camera, "video-size-values", + exynos_camera->config->presets[id].params.recording_size_values); + exynos_param_string_set(exynos_camera, "video-frame-format", + exynos_camera->config->presets[id].params.recording_format); + + // Focus + + exynos_param_string_set(exynos_camera, "focus-mode", + exynos_camera->config->presets[id].params.focus_mode); + exynos_param_string_set(exynos_camera, "focus-mode-values", + exynos_camera->config->presets[id].params.focus_mode_values); + exynos_param_string_set(exynos_camera, "focus-distances", + exynos_camera->config->presets[id].params.focus_distances); + if (exynos_camera->config->presets[id].params.max_num_focus_areas > 0) { + exynos_param_string_set(exynos_camera, "focus-areas", + exynos_camera->config->presets[id].params.focus_areas); + exynos_param_int_set(exynos_camera, "max-num-focus-areas", + exynos_camera->config->presets[id].params.max_num_focus_areas); + } + + // Zoom + + if (exynos_camera->config->presets[id].params.zoom_supported == 1) { + exynos_param_string_set(exynos_camera, "zoom-supported", "true"); + + if (exynos_camera->config->presets[id].params.smooth_zoom_supported == 1) + exynos_param_string_set(exynos_camera, "smooth-zoom-supported", "true"); + + if (exynos_camera->config->presets[id].params.zoom_ratios != NULL) + exynos_param_string_set(exynos_camera, "zoom-ratios", exynos_camera->config->presets[id].params.zoom_ratios); + + exynos_param_int_set(exynos_camera, "zoom", exynos_camera->config->presets[id].params.zoom); + exynos_param_int_set(exynos_camera, "max-zoom", exynos_camera->config->presets[id].params.max_zoom); + + } else { + exynos_param_string_set(exynos_camera, "zoom-supported", "false"); + } + + // Flash + + exynos_param_string_set(exynos_camera, "flash-mode", + exynos_camera->config->presets[id].params.flash_mode); + exynos_param_string_set(exynos_camera, "flash-mode-values", + exynos_camera->config->presets[id].params.flash_mode_values); + + // Exposure + + exynos_param_int_set(exynos_camera, "exposure-compensation", + exynos_camera->config->presets[id].params.exposure_compensation); + exynos_param_float_set(exynos_camera, "exposure-compensation-step", + exynos_camera->config->presets[id].params.exposure_compensation_step); + exynos_param_int_set(exynos_camera, "min-exposure-compensation", + exynos_camera->config->presets[id].params.min_exposure_compensation); + exynos_param_int_set(exynos_camera, "max-exposure-compensation", + exynos_camera->config->presets[id].params.max_exposure_compensation); + + // Antibanding + + exynos_param_string_set(exynos_camera, "antibanding", + exynos_camera->config->presets[id].params.antibanding); + exynos_param_string_set(exynos_camera, "antibanding-values", + exynos_camera->config->presets[id].params.antibanding_values); + + // WB + + exynos_param_string_set(exynos_camera, "whitebalance", + exynos_camera->config->presets[id].params.whitebalance); + exynos_param_string_set(exynos_camera, "whitebalance-values", + exynos_camera->config->presets[id].params.whitebalance_values); + + // Scene mode + + exynos_param_string_set(exynos_camera, "scene-mode", + exynos_camera->config->presets[id].params.scene_mode); + exynos_param_string_set(exynos_camera, "scene-mode-values", + exynos_camera->config->presets[id].params.scene_mode_values); + + // Effect + + exynos_param_string_set(exynos_camera, "effect", + exynos_camera->config->presets[id].params.effect); + exynos_param_string_set(exynos_camera, "effect-values", + exynos_camera->config->presets[id].params.effect_values); + + // ISO + + exynos_param_string_set(exynos_camera, "iso", + exynos_camera->config->presets[id].params.iso); + exynos_param_string_set(exynos_camera, "iso-values", + exynos_camera->config->presets[id].params.iso_values); + + // Camera + + exynos_param_float_set(exynos_camera, "focal-length", + exynos_camera->config->presets[id].focal_length); + exynos_param_float_set(exynos_camera, "horizontal-view-angle", + exynos_camera->config->presets[id].horizontal_view_angle); + exynos_param_float_set(exynos_camera, "vertical-view-angle", + exynos_camera->config->presets[id].vertical_view_angle); + + rc = exynos_camera_params_apply(exynos_camera, 1); + if (rc < 0) { + ALOGE("%s: Unable to apply params", __func__); + return -1; + } + + return 0; +} + +int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) +{ + char *recording_hint_string; + char *recording_preview_size_string; + + char *preview_size_string; + int preview_width = 0; + int preview_height = 0; + char *preview_format_string; + int preview_format; + int preview_fps; + + char *picture_size_string; + int picture_width = 0; + int picture_height = 0; + char *picture_format_string; + int picture_format; + + int jpeg_thumbnail_width; + int jpeg_thumbnail_height; + int jpeg_thumbnail_quality; + int jpeg_quality; + + char *video_size_string; + int recording_width = 0; + int recording_height = 0; + char *video_frame_format_string; + int recording_format; + int camera_sensor_mode; + int fimc_is_mode = 0; + + char *focus_mode_string; + int focus_mode = 0; + char *focus_areas_string; + int focus_left, focus_top, focus_right, focus_bottom, focus_weigth; + int focus_x; + int focus_y; + + char *zoom_supported_string; + int zoom, max_zoom; + + char *flash_mode_string; + int flash_mode; + + int exposure_compensation; + int min_exposure_compensation; + int max_exposure_compensation; + + char *antibanding_string; + int antibanding; + + char *whitebalance_string; + int whitebalance; + + char *scene_mode_string; + int scene_mode; + + char *effect_string; + int effect; + + char *iso_string; + int iso; + + int w, h; + char *k; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + // Preview + + preview_size_string = exynos_param_string_get(exynos_camera, "preview-size"); + if (preview_size_string != NULL) { + sscanf(preview_size_string, "%dx%d", &preview_width, &preview_height); + + if (preview_width != 0 && preview_width != exynos_camera->preview_width) + exynos_camera->preview_width = preview_width; + if (preview_height != 0 && preview_height != exynos_camera->preview_height) + exynos_camera->preview_height = preview_height; + } + + preview_format_string = exynos_param_string_get(exynos_camera, "preview-format"); + if (preview_format_string != NULL) { + if (strcmp(preview_format_string, "yuv420sp") == 0) { + preview_format = V4L2_PIX_FMT_NV21; + } else if (strcmp(preview_format_string, "yuv420p") == 0) { + preview_format = V4L2_PIX_FMT_YUV420; + } else if (strcmp(preview_format_string, "rgb565") == 0) { + preview_format = V4L2_PIX_FMT_RGB565; + } else if (strcmp(preview_format_string, "rgb8888") == 0) { + preview_format = V4L2_PIX_FMT_RGB32; + } else { + ALOGE("%s: Unsupported preview format: %s", __func__, preview_format_string); + preview_format = V4L2_PIX_FMT_NV21; + } + + if (preview_format != exynos_camera->preview_format) + exynos_camera->preview_format = preview_format; + } + + preview_fps = exynos_param_int_get(exynos_camera, "preview-frame-rate"); + if (preview_fps > 0) + exynos_camera->preview_fps = preview_fps; + else + exynos_camera->preview_fps = 0; + + // Picture + + picture_size_string = exynos_param_string_get(exynos_camera, "picture-size"); + if (picture_size_string != NULL) { + sscanf(picture_size_string, "%dx%d", &picture_width, &picture_height); + + if (picture_width != 0 && picture_height != 0 && (picture_width != exynos_camera->picture_width || picture_height != exynos_camera->picture_height)) { + exynos_camera->picture_width = picture_width; + exynos_camera->picture_height = picture_height; + + if (exynos_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_JPEG_RESOLUTION, (picture_width & 0xffff) << 16 | (picture_height & 0xffff)); + if (rc < 0) + ALOGE("%s: Unablet to set jpeg resolution", __func__); + } + } + } + + picture_format_string = exynos_param_string_get(exynos_camera, "picture-format"); + if (picture_format_string != NULL) { + if (strcmp(picture_format_string, "jpeg") == 0) { + picture_format = V4L2_PIX_FMT_JPEG; + } else { + ALOGE("%s: Unsupported picture format: %s", __func__, picture_format_string); + picture_format = V4L2_PIX_FMT_JPEG; + } + + if (picture_format != exynos_camera->picture_format) + exynos_camera->picture_format = picture_format; + } + + jpeg_thumbnail_width = exynos_param_int_get(exynos_camera, "jpeg-thumbnail-width"); + if (jpeg_thumbnail_width > 0) + exynos_camera->jpeg_thumbnail_width = jpeg_thumbnail_width; + + jpeg_thumbnail_height = exynos_param_int_get(exynos_camera, "jpeg-thumbnail-height"); + if (jpeg_thumbnail_height > 0) + exynos_camera->jpeg_thumbnail_height = jpeg_thumbnail_height; + + jpeg_thumbnail_quality = exynos_param_int_get(exynos_camera, "jpeg-thumbnail-quality"); + if (jpeg_thumbnail_quality > 0) + exynos_camera->jpeg_thumbnail_quality = jpeg_thumbnail_quality; + + jpeg_quality = exynos_param_int_get(exynos_camera, "jpeg-quality"); + if (jpeg_quality <= 100 && jpeg_quality >= 0 && (jpeg_quality != exynos_camera->jpeg_quality || force)) { + exynos_camera->jpeg_quality = jpeg_quality; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_QUALITY, jpeg_quality); + if (rc < 0) + ALOGE("%s: Unable to set jpeg quality", __func__); + } + + // Recording + + video_size_string = exynos_param_string_get(exynos_camera, "video-size"); + if (video_size_string == NULL) + video_size_string = exynos_param_string_get(exynos_camera, "preview-size"); + + if (video_size_string != NULL) { + sscanf(video_size_string, "%dx%d", &recording_width, &recording_height); + + if (recording_width != 0 && recording_width != exynos_camera->recording_width) + exynos_camera->recording_width = recording_width; + if (recording_height != 0 && recording_height != exynos_camera->recording_height) + exynos_camera->recording_height = recording_height; + } + + video_frame_format_string = exynos_param_string_get(exynos_camera, "video-frame-format"); + if (video_frame_format_string != NULL) { + if (strcmp(video_frame_format_string, "yuv420sp") == 0) { + recording_format = V4L2_PIX_FMT_NV12; + } else if (strcmp(video_frame_format_string, "yuv420p") == 0) { + recording_format = V4L2_PIX_FMT_YUV420; + } else if (strcmp(video_frame_format_string, "rgb565") == 0) { + recording_format = V4L2_PIX_FMT_RGB565; + } else if (strcmp(video_frame_format_string, "rgb8888") == 0) { + recording_format = V4L2_PIX_FMT_RGB32; + } else { + ALOGE("%s: Unsupported recording format: %s", __func__, video_frame_format_string); + recording_format = V4L2_PIX_FMT_NV12; + } + + if (recording_format != exynos_camera->recording_format) + exynos_camera->recording_format = recording_format; + } + + recording_hint_string = exynos_param_string_get(exynos_camera, "recording-hint"); + if (recording_hint_string != NULL && strcmp(recording_hint_string, "true") == 0) { + camera_sensor_mode = SENSOR_MOVIE; + + k = exynos_param_string_get(exynos_camera, "preview-size-values"); + while (recording_width != 0 && recording_height != 0) { + if (k == NULL) + break; + + sscanf(k, "%dx%d", &w, &h); + + // Look for same aspect ratio + if ((recording_width * h) / recording_height == w) { + preview_width = w; + preview_height = h; + break; + } + + k = strchr(k, ','); + if (k == NULL) + break; + + k++; + } + + if (preview_width != 0 && preview_width != exynos_camera->preview_width) + exynos_camera->preview_width = preview_width; + if (preview_height != 0 && preview_height != exynos_camera->preview_height) + exynos_camera->preview_height = preview_height; + + if (exynos_camera->camera_fimc_is) + fimc_is_mode = IS_MODE_PREVIEW_VIDEO; + } else { + camera_sensor_mode = SENSOR_CAMERA; + + if (exynos_camera->camera_fimc_is) + fimc_is_mode = IS_MODE_PREVIEW_STILL; + } + + // Switching modes + + if (camera_sensor_mode != exynos_camera->camera_sensor_mode) { + exynos_camera->camera_sensor_mode = camera_sensor_mode; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SENSOR_MODE, camera_sensor_mode); + if (rc < 0) + ALOGE("%s: Unable to set sensor mode", __func__); + } + + if (exynos_camera->camera_fimc_is && fimc_is_mode != exynos_camera->fimc_is_mode) { + exynos_camera->fimc_is_mode = fimc_is_mode; + + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_IS_S_FORMAT_SCENARIO, exynos_camera->fimc_is_mode); + if (rc < 0) + ALOGE("%s: Unable to set FIMC-IS scenario", __func__); + } + + // Focus + + focus_areas_string = exynos_param_string_get(exynos_camera, "focus-areas"); + if (focus_areas_string != NULL) { + focus_left = focus_top = focus_right = focus_bottom = focus_weigth = 0; + + rc = sscanf(focus_areas_string, "(%d,%d,%d,%d,%d)", + &focus_left, &focus_top, &focus_right, &focus_bottom, &focus_weigth); + if (rc != 5) { + ALOGE("%s: Unable to scan focus areas", __func__); + } else if (focus_left != 0 && focus_top != 0 && focus_right != 0 && focus_bottom != 0) { + focus_x = (((focus_left + focus_right) / 2) + 1000) * preview_width / 2000; + focus_y = (((focus_top + focus_bottom) / 2) + 1000) * preview_height / 2000; + + if (focus_x != exynos_camera->focus_x || force) { + exynos_camera->focus_x = focus_x; + + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_OBJECT_POSITION_X, focus_x); + if (rc < 0) + ALOGE("%s: Unable to set object x position", __func__); + } + + if (focus_y != exynos_camera->focus_y || force) { + exynos_camera->focus_y = focus_y; + + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_OBJECT_POSITION_Y, focus_y); + if (rc < 0) + ALOGE("%s: Unable to set object y position", __func__); + } + + focus_mode = FOCUS_MODE_TOUCH; + } + } + + focus_mode_string = exynos_param_string_get(exynos_camera, "focus-mode"); + if (focus_mode_string != NULL) { + if (focus_mode == 0) { + if (strcmp(focus_mode_string, "auto") == 0) + focus_mode = FOCUS_MODE_AUTO; + else if (strcmp(focus_mode_string, "infinity") == 0) + focus_mode = FOCUS_MODE_INFINITY; + else if (strcmp(focus_mode_string, "macro") == 0) + focus_mode = FOCUS_MODE_MACRO; + else if (strcmp(focus_mode_string, "fixed") == 0) + focus_mode = FOCUS_MODE_FIXED; + else if (strcmp(focus_mode_string, "facedetect") == 0) + focus_mode = FOCUS_MODE_FACEDETECT; + else if (strcmp(focus_mode_string, "continuous-video") == 0) + focus_mode = FOCUS_MODE_CONTINOUS_VIDEO; + else if (strcmp(focus_mode_string, "continuous-picture") == 0) + focus_mode = FOCUS_MODE_CONTINOUS_PICTURE; + else + focus_mode = FOCUS_MODE_AUTO; + } + + if (focus_mode != exynos_camera->focus_mode || force) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode); + if (rc < 0) + ALOGE("%s: Unable to set focus mode", __func__); + } + + exynos_camera->focus_mode = focus_mode; + } + + // Zoom + + zoom_supported_string = exynos_param_string_get(exynos_camera, "zoom-supported"); + if (zoom_supported_string != NULL && strcmp(zoom_supported_string, "true") == 0) { + zoom = exynos_param_int_get(exynos_camera, "zoom"); + max_zoom = exynos_param_int_get(exynos_camera, "max-zoom"); + if (zoom <= max_zoom && zoom >= 0 && (zoom != exynos_camera->zoom || force)) { + exynos_camera->zoom = zoom; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_ZOOM, zoom); + if (rc < 0) + ALOGE("%s: Unable to set camera zoom", __func__); + } + + } + + // Flash + + flash_mode_string = exynos_param_string_get(exynos_camera, "flash-mode"); + if (flash_mode_string != NULL) { + if (strcmp(flash_mode_string, "off") == 0) + flash_mode = FLASH_MODE_OFF; + else if (strcmp(flash_mode_string, "auto") == 0) + flash_mode = FLASH_MODE_AUTO; + else if (strcmp(flash_mode_string, "on") == 0) + flash_mode = FLASH_MODE_ON; + else if (strcmp(flash_mode_string, "torch") == 0) + flash_mode = FLASH_MODE_TORCH; + else + flash_mode = FLASH_MODE_AUTO; + + if (flash_mode != exynos_camera->flash_mode || force) { + exynos_camera->flash_mode = flash_mode; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_FLASH_MODE, flash_mode); + if (rc < 0) + ALOGE("%s:Unable to set flash mode", __func__); + } + } + + // Exposure + + exposure_compensation = exynos_param_int_get(exynos_camera, "exposure-compensation"); + min_exposure_compensation = exynos_param_int_get(exynos_camera, "min-exposure-compensation"); + max_exposure_compensation = exynos_param_int_get(exynos_camera, "max-exposure-compensation"); + + if (exposure_compensation <= max_exposure_compensation && exposure_compensation >= min_exposure_compensation && + (exposure_compensation != exynos_camera->exposure_compensation || force)) { + exynos_camera->exposure_compensation = exposure_compensation; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_BRIGHTNESS, exposure_compensation); + if (rc < 0) + ALOGE("%s: Unable to set exposure", __func__); + } + + // Antibanding + + antibanding_string = exynos_param_string_get(exynos_camera, "antibanding"); + if (antibanding_string != NULL) { + if (strcmp(antibanding_string, "auto") == 0) + antibanding = ANTI_BANDING_AUTO; + else if (strcmp(antibanding_string, "50hz") == 0) + antibanding = ANTI_BANDING_50HZ; + else if (strcmp(antibanding_string, "60hz") == 0) + antibanding = ANTI_BANDING_60HZ; + else if (strcmp(antibanding_string, "off") == 0) + antibanding = ANTI_BANDING_OFF; + else + antibanding = ANTI_BANDING_AUTO; + + if (antibanding != exynos_camera->antibanding || force) { + exynos_camera->antibanding = antibanding; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_ANTI_BANDING, antibanding); + if (rc < 0) + ALOGE("%s: Unable to set antibanding", __func__); + } + } + + // WB + + whitebalance_string = exynos_param_string_get(exynos_camera, "whitebalance"); + if (whitebalance_string != NULL) { + if (strcmp(whitebalance_string, "auto") == 0) + whitebalance = WHITE_BALANCE_AUTO; + else if (strcmp(whitebalance_string, "incandescent") == 0) + whitebalance = WHITE_BALANCE_TUNGSTEN; + else if (strcmp(whitebalance_string, "fluorescent") == 0) + whitebalance = WHITE_BALANCE_FLUORESCENT; + else if (strcmp(whitebalance_string, "daylight") == 0) + whitebalance = WHITE_BALANCE_SUNNY; + else if (strcmp(whitebalance_string, "cloudy-daylight") == 0) + whitebalance = WHITE_BALANCE_CLOUDY; + else + whitebalance = WHITE_BALANCE_AUTO; + + if (whitebalance != exynos_camera->whitebalance || force) { + exynos_camera->whitebalance = whitebalance; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_WHITE_BALANCE, whitebalance); + if (rc < 0) + ALOGE("%s: Unable to set whitebalance", __func__); + } + } + + // Scene mode + + scene_mode_string = exynos_param_string_get(exynos_camera, "scene-mode"); + if (scene_mode_string != NULL) { + if (strcmp(scene_mode_string, "auto") == 0) + scene_mode = SCENE_MODE_NONE; + else if (strcmp(scene_mode_string, "portrait") == 0) + scene_mode = SCENE_MODE_PORTRAIT; + else if (strcmp(scene_mode_string, "landscape") == 0) + scene_mode = SCENE_MODE_LANDSCAPE; + else if (strcmp(scene_mode_string, "night") == 0) + scene_mode = SCENE_MODE_NIGHTSHOT; + else if (strcmp(scene_mode_string, "beach") == 0) + scene_mode = SCENE_MODE_BEACH_SNOW; + else if (strcmp(scene_mode_string, "snow") == 0) + scene_mode = SCENE_MODE_BEACH_SNOW; + else if (strcmp(scene_mode_string, "sunset") == 0) + scene_mode = SCENE_MODE_SUNSET; + else if (strcmp(scene_mode_string, "fireworks") == 0) + scene_mode = SCENE_MODE_FIREWORKS; + else if (strcmp(scene_mode_string, "sports") == 0) + scene_mode = SCENE_MODE_SPORTS; + else if (strcmp(scene_mode_string, "party") == 0) + scene_mode = SCENE_MODE_PARTY_INDOOR; + else if (strcmp(scene_mode_string, "candlelight") == 0) + scene_mode = SCENE_MODE_CANDLE_LIGHT; + else if (strcmp(scene_mode_string, "dusk-dawn") == 0) + scene_mode = SCENE_MODE_DUSK_DAWN; + else if (strcmp(scene_mode_string, "fall-color") == 0) + scene_mode = SCENE_MODE_FALL_COLOR; + else if (strcmp(scene_mode_string, "back-light") == 0) + scene_mode = SCENE_MODE_BACK_LIGHT; + else if (strcmp(scene_mode_string, "text") == 0) + scene_mode = SCENE_MODE_TEXT; + else + scene_mode = SCENE_MODE_NONE; + + if (scene_mode != exynos_camera->scene_mode || force) { + exynos_camera->scene_mode = scene_mode; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SCENE_MODE, scene_mode); + if (rc < 0) + ALOGE("%s: Unable to set scene mode", __func__); + } + } + + // Effect + + effect_string = exynos_param_string_get(exynos_camera, "effect"); + if (effect_string != NULL) { + if (strcmp(effect_string, "auto") == 0) + effect = IMAGE_EFFECT_NONE; + if (strcmp(effect_string, "none") == 0) + effect = IMAGE_EFFECT_NONE; + else if (strcmp(effect_string, "mono") == 0) + effect = IMAGE_EFFECT_BNW; + else if (strcmp(effect_string, "negative") == 0) + effect = IMAGE_EFFECT_NEGATIVE; + else if (strcmp(effect_string, "sepia") == 0) + effect = IMAGE_EFFECT_SEPIA; + else if (strcmp(effect_string, "aqua") == 0) + effect = IMAGE_EFFECT_AQUA; + else if (strcmp(effect_string, "solarize") == 0) + effect = IMAGE_EFFECT_SOLARIZE; + else if (strcmp(effect_string, "posterize") == 0) + effect = IMAGE_EFFECT_POSTERIZE; + else if (strcmp(effect_string, "washed") == 0) + effect = IMAGE_EFFECT_WASHED; + else if (strcmp(effect_string, "sketch") == 0) + effect = IMAGE_EFFECT_SKETCH; + else if (strcmp(effect_string, "vintage-warm") == 0) + effect = IMAGE_EFFECT_VINTAGE_WARM; + else if (strcmp(effect_string, "vintage-cold") == 0) + effect = IMAGE_EFFECT_VINTAGE_COLD; + else if (strcmp(effect_string, "point-blue") == 0) + effect = IMAGE_EFFECT_POINT_BLUE; + else if (strcmp(effect_string, "point-red-yellow") == 0) + effect = IMAGE_EFFECT_POINT_RED_YELLOW; + else if (strcmp(effect_string, "point-green") == 0) + effect = IMAGE_EFFECT_POINT_GREEN; + else + effect = IMAGE_EFFECT_NONE; + + if (effect != exynos_camera->effect || force) { + exynos_camera->effect = effect; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EFFECT, effect); + if (rc < 0) + ALOGE("%s: Unable to set effect", __func__); + } + } + + // ISO + + iso_string = exynos_param_string_get(exynos_camera, "iso"); + if (iso_string != NULL) { + if (strcmp(iso_string, "auto") == 0) + iso = ISO_AUTO; + else if (strcmp(iso_string, "ISO50") == 0) + iso = ISO_50; + else if (strcmp(iso_string, "ISO100") == 0) + iso = ISO_100; + else if (strcmp(iso_string, "ISO200") == 0) + iso = ISO_200; + else if (strcmp(iso_string, "ISO400") == 0) + iso = ISO_400; + else if (strcmp(iso_string, "ISO800") == 0) + iso = ISO_800; + else + iso = ISO_AUTO; + + if (iso != exynos_camera->iso || force) { + exynos_camera->iso = iso; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_ISO, iso); + if (rc < 0) + ALOGE("%s: Unable to set iso", __func__); + } + } + + ALOGD("%s: Preview size: %dx%d, picture size: %dx%d, recording size: %dx%d", __func__, preview_width, preview_height, picture_width, picture_height, recording_width, recording_height); + + return 0; +} + +// Capture + +int s5c73m3_interleaved_decode(void *data, int size, + void *yuv_data, int *yuv_size, int yuv_width, int yuv_height, + void *jpeg_data, int *jpeg_size, int *decoded, int *auto_focus_result) +{ + int yuv_length; + int jpeg_length; + unsigned char *yuv_p; + unsigned char *jpeg_p; + unsigned char *data_p; + unsigned int *offset_p; + unsigned int pointers_array_offset; + unsigned int pointers_array_size; + unsigned int interleaved_size; + unsigned char s5c73m3_auto_focus_result; + unsigned int yuv_offset_last; + unsigned int yuv_offset; + unsigned int yuv_line_size; + unsigned short *jpeg_start_p; + int gap; + unsigned int i; + + if (data == NULL || size <= 0 || yuv_data == NULL || yuv_size == NULL || yuv_width <= 0 || yuv_height <= 0 || jpeg_data == NULL || jpeg_size == NULL || decoded == NULL || auto_focus_result == NULL) + return -EINVAL; + + yuv_length = 0; + jpeg_length = 0; + + data_p = (unsigned char *) data; + data_p += size - 0x1000; // End of the first plane (interleaved buffer) + data_p += 4046; // Experimental offset for decoded + + *decoded = (int) *data_p; + + data_p = (unsigned char *) data; + data_p += size - 0x1000; // End of the first plane (interleaved buffer) + data_p += 50; // Experimental offset for auto-focus result + + s5c73m3_auto_focus_result = *data_p; + + switch (s5c73m3_auto_focus_result) { + case S5C73M3_CAF_STATUS_FOCUSING: + case S5C73M3_CAF_STATUS_FIND_SEARCHING_DIR: + case S5C73M3_AF_STATUS_INVALID: + *auto_focus_result = CAMERA_AF_STATUS_IN_PROGRESS; + break; + case S5C73M3_AF_STATUS_FOCUSED: + case S5C73M3_CAF_STATUS_FOCUSED: + *auto_focus_result = CAMERA_AF_STATUS_SUCCESS; + break; + + case S5C73M3_CAF_STATUS_UNFOCUSED: + case S5C73M3_AF_STATUS_UNFOCUSED: + default: + *auto_focus_result = CAMERA_AF_STATUS_FAIL; + break; + } + + data_p = (unsigned char *) data; + data_p += size - 0x1000; // End of the first plane (interleaved buffer) + data_p += 4084; // Experimental offset for interleaved size + + // Read the pointers array offset + offset_p = (unsigned int *) data_p; + pointers_array_offset = BIG2LITTLE_ENDIAN(*offset_p); + interleaved_size = pointers_array_offset; + + // Read the pointers array size, it should be 4 * yuv_height + data_p += sizeof(pointers_array_offset); + offset_p = (unsigned int *) data_p; + pointers_array_size = BIG2LITTLE_ENDIAN(*offset_p); + + if (!*decoded) + return 0; + + ALOGD("%s: Interleaved pointers array is at offset 0x%x, 0x%x bytes long\n", __func__, pointers_array_offset, pointers_array_size); + + if ((int) pointers_array_offset > size || (int) pointers_array_size > size || (int) pointers_array_size < yuv_height * (int) sizeof(unsigned int)) { + ALOGE("%s: Invalid informations", __func__); + return -1; + } + + data_p = (unsigned char *) data; + data_p += pointers_array_offset; + yuv_p = (unsigned char *) yuv_data; + jpeg_p = (unsigned char *) jpeg_data; + jpeg_start_p = NULL; + + yuv_line_size = yuv_width * 2; + yuv_offset_last = 0; + yuv_offset = 0; + i = 0; + + while (i < pointers_array_size) { + offset_p = (unsigned int *) data_p; + yuv_offset = BIG2LITTLE_ENDIAN(*offset_p); + + if (yuv_offset > size - yuv_line_size) + return -1; + + gap = yuv_offset - yuv_offset_last - yuv_line_size; + + if (gap > 0) { + data_p = (unsigned char *) data + yuv_offset_last + yuv_line_size; + + if (jpeg_start_p == NULL) { + jpeg_start_p = (unsigned short *) data_p; + if (*jpeg_start_p != 0xd8ff) { + ALOGE("%s: Invalid jpeg start", __func__); + return -1; + } + } + + memcpy(jpeg_p, data_p, gap); + jpeg_p += gap; + jpeg_length += gap; + } + + yuv_offset_last = yuv_offset; + + data_p = (unsigned char *) data + yuv_offset; + memcpy(yuv_p, data_p, yuv_line_size); + yuv_p += yuv_line_size; + yuv_length += yuv_line_size; + + data_p = (unsigned char *) offset_p; + data_p += sizeof(yuv_offset); + i += sizeof(yuv_offset); + } + + gap = interleaved_size - yuv_offset_last - yuv_line_size; + + if (gap > 0) { + data_p = (unsigned char *) data + yuv_offset_last + yuv_line_size; + + memcpy(jpeg_p, data_p, gap); + jpeg_p += gap; + jpeg_length += gap; + } + + *yuv_size = yuv_length; + *jpeg_size = jpeg_length; + + return 0; +} + +int exynos_camera_capture(struct exynos_camera *exynos_camera) +{ + struct exynos_camera_capture_listener *listener; + struct exynos_camera_buffer *buffers = NULL; + struct exynos_camera_buffer *buffer; + struct list_head *list; + int width, height, format; + int yuv_length, jpeg_length; + int jpeg_offset, jpeg_size; + int jpeg_thumbnail_offset, jpeg_thumbnail_size; + int buffers_count; + int buffer_length; + int auto_focus_result; + int decoded; + int busy; + void *pointer; + int address; + int offset; + int index; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + width = exynos_camera->capture_width; + height = exynos_camera->capture_height; + format = exynos_camera->capture_format; + + buffers_count = exynos_camera->capture_buffers_count; + buffer_length = exynos_camera->capture_buffer_length; + + // V4L2 + + index = exynos_v4l2_dqbuf_cap(exynos_camera, 0); + if (index < 0 || index >= buffers_count) { + rc = exynos_v4l2_poll(exynos_camera, 0); + if (rc < 0) { + ALOGE("%s Unable to poll", __func__); + goto error; + } else if (rc == 0) { + // Timeout + rc = 0; + goto complete; + } + + index = exynos_v4l2_dqbuf_cap(exynos_camera, 0); + if (index < 0 || index >= buffers_count) { + ALOGE("%s: Unable to dequeue buffer", __func__); + goto error; + } + } + + exynos_camera->capture_memory_index = index; + + address = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_PADDR_Y, index); + if (address == 0 || address == (int) 0xffffffff) { + ALOGE("%s: Unable to get address", __func__); + goto error; + } + + offset = address - exynos_camera->capture_memory_address; + if (offset != index * buffer_length) + ALOGE("%s: Inconsistent memory offset (0x%x/0x%x)", __func__, offset, index * buffer_length); + + pointer = (void *) ((unsigned char *) exynos_camera->capture_memory->data + offset); + + // Buffers + + switch (format) { + case V4L2_PIX_FMT_INTERLEAVED: + yuv_length = jpeg_length = 0; + auto_focus_result = decoded = 0; + + rc = s5c73m3_interleaved_decode(pointer, buffer_length, exynos_camera->capture_yuv_buffer, &yuv_length, width, height, exynos_camera->capture_jpeg_buffer, &jpeg_length, &decoded, &auto_focus_result); + if (rc < 0) { + ALOGE("%s: Unable to decode S5C73M3 interleaved", __func__); + goto error; + } + + if (auto_focus_result != exynos_camera->capture_auto_focus_result) { + exynos_camera->capture_auto_focus_result = auto_focus_result; + + if (!exynos_camera->auto_focus_thread_enabled) { + rc = exynos_camera_auto_focus(exynos_camera, auto_focus_result); + if (rc < 0) { + ALOGE("%s: Unable to auto focus", __func__); + goto error; + } + } + } + + if (!decoded) { + buffers_count = 1; + buffers = (struct exynos_camera_buffer *) calloc(buffers_count, sizeof(struct exynos_camera_buffer)); + + buffer = buffers; + + buffer->pointer = pointer; + buffer->address = address; + buffer->length = exynos_camera_buffer_length(width, height, V4L2_PIX_FMT_UYVY); + buffer->width = width; + buffer->height = height; + buffer->format = V4L2_PIX_FMT_UYVY; + } else { + buffers_count = 2; + buffers = (struct exynos_camera_buffer *) calloc(buffers_count, sizeof(struct exynos_camera_buffer)); + + buffer = buffers; + + memcpy(pointer, exynos_camera->capture_yuv_buffer, yuv_length); + + buffer->pointer = pointer; + buffer->address = address; + buffer->length = yuv_length; + buffer->width = width; + buffer->height = height; + buffer->format = V4L2_PIX_FMT_UYVY; + + pointer = (void *) ((unsigned char *) pointer + yuv_length); + address += yuv_length; + buffer = (struct exynos_camera_buffer *) ((unsigned char *) buffer + sizeof(struct exynos_camera_buffer)); + + memcpy(pointer, exynos_camera->capture_jpeg_buffer, jpeg_length); + + buffer->pointer = pointer; + buffer->address = address; + buffer->length = jpeg_length; + buffer->width = exynos_camera->picture_width; + buffer->height = exynos_camera->picture_height; + buffer->format = V4L2_PIX_FMT_JPEG; + + exynos_camera->capture_hybrid = 0; + } + break; + case V4L2_PIX_FMT_JPEG: + jpeg_size = jpeg_offset = 0; + jpeg_thumbnail_size = jpeg_thumbnail_offset = 0; + + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_MAIN_SIZE, &jpeg_size); + if (rc < 0 || jpeg_size <= 0) { + ALOGE("%s: Unable to get jpeg size", __func__); + goto error; + } + + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_MAIN_OFFSET, &jpeg_offset); + if (rc < 0) { + ALOGE("%s: Unable to get jpeg offset", __func__); + goto error; + } + + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_THUMB_SIZE, &jpeg_thumbnail_size); + if (rc < 0 || jpeg_thumbnail_size <= 0) { + ALOGE("%s: Unable to get jpeg thumbnail size", __func__); + goto error; + } + + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_THUMB_OFFSET, &jpeg_thumbnail_offset); + if (rc < 0) { + ALOGE("%s: Unable to get jpeg thumbnail offset", __func__); + goto error; + } + + buffers_count = 2; + buffers = (struct exynos_camera_buffer *) calloc(buffers_count, sizeof(struct exynos_camera_buffer)); + + buffer = buffers; + + buffer->pointer = (void *) ((unsigned char *) pointer + jpeg_offset); + buffer->address = address + jpeg_offset; + buffer->length = jpeg_size; + buffer->width = exynos_camera->picture_width; + buffer->height = exynos_camera->picture_height; + buffer->format = V4L2_PIX_FMT_JPEG; + + buffer = (struct exynos_camera_buffer *) ((unsigned char *) buffer + sizeof(struct exynos_camera_buffer)); + + buffer->pointer = (void *) ((unsigned char *) pointer + jpeg_thumbnail_offset); + buffer->address = address + jpeg_thumbnail_offset; + buffer->length = jpeg_thumbnail_size; + buffer->width = exynos_camera->jpeg_thumbnail_width; + buffer->height = exynos_camera->jpeg_thumbnail_height; + buffer->format = V4L2_PIX_FMT_JPEG; + break; + default: + buffers_count = 1; + buffers = (struct exynos_camera_buffer *) calloc(buffers_count, sizeof(struct exynos_camera_buffer)); + + buffer = buffers; + + buffer->pointer = pointer; + buffer->address = address; + buffer->length = buffer_length; + buffer->width = width; + buffer->height = height; + buffer->format = format; + break; + } + + // Listeners + + list = (struct list_head *) exynos_camera->capture_listeners; + while (list != NULL) { + listener = (struct exynos_camera_capture_listener *) list; + + if (listener->callback == NULL) + goto list_continue_callback; + + /* + * Callback must never call a capture-locked function or it will + * block. Hence, do not unregister the listener in callback. + */ + + listener->callback(exynos_camera, buffers, buffers_count); + +list_continue_callback: + list = list->next; + } + + do { + busy = 0; + + list = (struct list_head *) exynos_camera->capture_listeners; + while (list != NULL) { + listener = (struct exynos_camera_capture_listener *) list; + + if (listener->callback == NULL) + goto list_continue_busy; + + busy |= listener->busy; + +list_continue_busy: + list = list->next; + } + + if (busy) + usleep(1000); + } while (busy); + + rc = exynos_v4l2_qbuf_cap(exynos_camera, 0, index); + if (rc < 0) { + ALOGE("%s: Unable to queue buffer", __func__); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffers != NULL) + free(buffers); + + return rc; +} + +void *exynos_camera_capture_thread(void *data) +{ + struct exynos_camera *exynos_camera; + int rc; + + if (data == NULL) + return NULL; + + exynos_camera = (struct exynos_camera *) data; + + ALOGE("%s: Starting thread", __func__); + exynos_camera->capture_thread_running = 1; + + while (exynos_camera->capture_thread_enabled) { + pthread_mutex_lock(&exynos_camera->capture_lock_mutex); + + while (exynos_camera->capture_enabled) { + pthread_mutex_lock(&exynos_camera->capture_mutex); + + if (!exynos_camera->capture_enabled) { + pthread_mutex_unlock(&exynos_camera->capture_mutex); + break; + } + + rc = exynos_camera_capture(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to capture", __func__); + pthread_mutex_unlock(&exynos_camera->capture_mutex); + break; + } + + pthread_mutex_unlock(&exynos_camera->capture_mutex); + + // Wait a bit to let others lock the mutex if they need to + usleep(10); + } + } + + exynos_camera->capture_thread_running = 0; + ALOGE("%s: Exiting thread", __func__); + + return NULL; +} + +int exynos_camera_capture_thread_start(struct exynos_camera *exynos_camera) +{ + pthread_attr_t thread_attr; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exynos_camera->capture_thread_enabled) { + ALOGE("Capture thread was already started!"); + return -1; + } + + pthread_mutex_init(&exynos_camera->capture_mutex, NULL); + pthread_mutex_init(&exynos_camera->capture_lock_mutex, NULL); + + // Initial lock + pthread_mutex_lock(&exynos_camera->capture_lock_mutex); + + pthread_attr_init(&thread_attr); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + + exynos_camera->capture_thread_enabled = 1; + + rc = pthread_create(&exynos_camera->capture_thread, &thread_attr, exynos_camera_capture_thread, (void *) exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to create thread", __func__); + goto error; + } + + rc = 0; + goto complete; + +error: + pthread_mutex_destroy(&exynos_camera->capture_mutex); + pthread_mutex_destroy(&exynos_camera->capture_lock_mutex); + + rc = -1; + +complete: + return rc; +} + +void exynos_camera_capture_thread_stop(struct exynos_camera *exynos_camera) +{ + int i; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exynos_camera->capture_thread_enabled) { + ALOGE("Capture thread was already stopped!"); + return; + } + + exynos_camera->capture_enabled = 0; + exynos_camera->capture_thread_enabled = 0; + + pthread_mutex_unlock(&exynos_camera->capture_lock_mutex); + + // Wait for the thread to end + i = 0; + while (exynos_camera->capture_thread_running) { + if (i++ > 10000) { + ALOGE("Capture thread is taking too long to end, something is going wrong"); + break; + } + usleep(100); + } + + if (exynos_camera->capture_enabled) { + pthread_mutex_lock(&exynos_camera->capture_mutex); + exynos_camera_capture_stop(exynos_camera); + pthread_mutex_unlock(&exynos_camera->capture_mutex); + } + + pthread_mutex_destroy(&exynos_camera->capture_mutex); + pthread_mutex_destroy(&exynos_camera->capture_lock_mutex); +} + +int exynos_camera_capture_start(struct exynos_camera *exynos_camera) +{ + struct v4l2_streamparm fps_param; + int width, height, format; + int mbus_width, mbus_height; + int buffers_count, buffer_length; + camera_memory_t *memory = NULL; + int value; + int fd; + int rc; + int i; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exynos_camera->capture_enabled) { + ALOGE("Capture was already started!"); + return -1; + } + + width = exynos_camera->capture_width; + height = exynos_camera->capture_height; + format = exynos_camera->capture_format; + + // V4L2 + + if (format == V4L2_PIX_FMT_INTERLEAVED) { + ALOGD("Enabling hybrid capture"); + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_HYBRID, 1); + if (rc < 0) { + ALOGE("%s: Unable to set hybrid", __func__); + goto error; + } + } + + if (exynos_camera->camera_fimc_is) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_IS_S_FORMAT_SCENARIO, exynos_camera->fimc_is_mode); + if (rc < 0) { + ALOGE("%s: Unable to set FIMC-IS scenario", __func__); + goto error; + } + } + + rc = exynos_v4l2_enum_fmt_cap(exynos_camera, 0, format); + if (rc < 0) { + ALOGE("%s: Unable to enumerate formats", __func__); + goto error; + } + + mbus_width = width; + mbus_height = height; + + if (exynos_camera->camera_mbus_resolutions != NULL) { + for (i = 0; i < exynos_camera->camera_mbus_resolutions_count; i++) { + if (exynos_camera->camera_mbus_resolutions[i].width == width && exynos_camera->camera_mbus_resolutions[i].height == height) { + mbus_width = exynos_camera->camera_mbus_resolutions[i].mbus_width; + mbus_height = exynos_camera->camera_mbus_resolutions[i].mbus_height; + break; + } + } + } + + if (exynos_camera->camera_fimc_is) { + // Set MBUS width/height/format + rc = exynos_v4l2_s_fmt_pix(exynos_camera, 0, V4L2_BUF_TYPE_PRIVATE, mbus_width, mbus_height, format, exynos_camera->fimc_is_mode, V4L2_PIX_FMT_MODE_PREVIEW); + if (rc < 0) { + ALOGE("%s: Unable to set MBUS capture pixel format", __func__); + goto error; + } + } + + rc = exynos_v4l2_s_fmt_pix_cap(exynos_camera, 0, width, height, format, V4L2_PIX_FMT_MODE_PREVIEW); + if (rc < 0) { + ALOGE("%s: Unable to set capture pixel format", __func__); + goto error; + } + + if (!exynos_camera->camera_fimc_is) { + // Set MBUS width/height/format + rc = exynos_v4l2_s_fmt_pix(exynos_camera, 0, V4L2_BUF_TYPE_PRIVATE, mbus_width, mbus_height, format, V4L2_FIELD_NONE, V4L2_PIX_FMT_MODE_PREVIEW); + if (rc < 0) { + ALOGE("%s: Unable to set MBUS capture pixel format", __func__); + goto error; + } + } + + if (format == V4L2_PIX_FMT_INTERLEAVED) + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CACHEABLE, 0); + else + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CACHEABLE, 1); + if (rc < 0) { + ALOGE("%s: Unable to set cacheable", __func__); + goto error; + } + + if (exynos_camera->camera_fimc_is) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_IS_S_SCENARIO_MODE, exynos_camera->fimc_is_mode); + if (rc < 0) { + ALOGE("%s: Unable to set FIMC-IS scenario mode", __func__); + goto error; + } + } + + if (format == V4L2_PIX_FMT_INTERLEAVED) { + // This must be set to 1 for interleaved data decoding + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_EMBEDDEDDATA_ENABLE, 1); + if (rc < 0) { + ALOGE("%s: Unable to set embdedded data enable", __func__); + goto error; + } + } + + // Let's assume FIMC0 has memory available through mmap + + for (i = EXYNOS_CAMERA_CAPTURE_BUFFERS_COUNT; i > 0; i--) { + rc = exynos_v4l2_reqbufs_cap(exynos_camera, 0, i); + if (rc >= 0) + break; + } + + if (rc < 0) { + ALOGE("%s: Unable to request buffers", __func__); + goto error; + } + + buffers_count = rc; + ALOGD("Found %d buffers available for capture!", buffers_count); + + memset(&fps_param, 0, sizeof(fps_param)); + fps_param.parm.capture.timeperframe.numerator = 1; + fps_param.parm.capture.timeperframe.denominator = exynos_camera->preview_fps; + + rc = exynos_v4l2_s_parm_cap(exynos_camera, 0, &fps_param); + if (rc < 0) { + ALOGE("%s: Unable to set fps", __func__); + goto error; + } + + for (i = 0; i < buffers_count; i++) { + rc = exynos_v4l2_querybuf_cap(exynos_camera, 0, i); + if (rc < 0) { + ALOGE("%s: Unable to query buffers", __func__); + goto error; + } + } + + buffer_length = rc; + + value = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_PADDR_Y, 0); + if (value == 0 || value == (int) 0xffffffff) { + ALOGE("%s: Unable to get address", __func__); + goto error; + } + + exynos_camera->capture_memory_address = value; + + if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { + fd = exynos_v4l2_fd(exynos_camera, 0); + if (fd < 0) { + ALOGE("%s: Unable to get v4l2 fd for id %d", __func__, 0); + goto error; + } + + exynos_camera->capture_memory = NULL; + + memory = exynos_camera->callbacks.request_memory(fd, buffer_length, buffers_count, exynos_camera->callbacks.user); + if (memory == NULL || memory->data == NULL || memory->data == MAP_FAILED) { + ALOGE("%s: Unable to request memory", __func__); + goto error; + } + + exynos_camera->capture_memory = memory; + } else { + ALOGE("%s: No memory request function!", __func__); + goto error; + } + + if (format == V4L2_PIX_FMT_INTERLEAVED) { + exynos_camera->capture_yuv_buffer = malloc(buffer_length); + exynos_camera->capture_jpeg_buffer = malloc(buffer_length); + } + + for (i = 0; i < buffers_count; i++) { + rc = exynos_v4l2_qbuf_cap(exynos_camera, 0, i); + if (rc < 0) { + ALOGE("%s: Unable to queue buffer", __func__); + goto error; + } + } + + exynos_camera->capture_buffers_count = buffers_count; + exynos_camera->capture_buffer_length = buffer_length; + + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_ROTATION, + exynos_camera->camera_rotation); + if (rc < 0) { + ALOGE("%s: Unable to set rotation", __func__); + goto error; + } + + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_HFLIP, + exynos_camera->camera_hflip); + if (rc < 0) { + ALOGE("%s: Unable to set hflip", __func__); + goto error; + } + + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_VFLIP, + exynos_camera->camera_vflip); + if (rc < 0) { + ALOGE("%s: Unable to set vflip", __func__); + goto error; + } + + rc = exynos_v4l2_streamon_cap(exynos_camera, 0); + if (rc < 0) { + ALOGE("%s: Unable to start stream", __func__); + goto error; + } + + exynos_camera->capture_enabled = 1; + pthread_mutex_unlock(&exynos_camera->capture_lock_mutex); + + rc = 0; + goto complete; + +error: + if (exynos_camera->capture_memory != NULL && exynos_camera->capture_memory->release != NULL) { + exynos_camera->capture_memory->release(exynos_camera->capture_memory); + exynos_camera->capture_memory = NULL; + } + + rc = -1; + +complete: + return rc; +} + +void exynos_camera_capture_stop(struct exynos_camera *exynos_camera) +{ + int rc; + int i; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exynos_camera->capture_enabled) { + ALOGE("Capture was already stopped!"); + return; + } + + if (exynos_camera->capture_format == V4L2_PIX_FMT_INTERLEAVED) { + ALOGD("Disabling hybrid capture"); + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_HYBRID, 0); + if (rc < 0) + ALOGE("%s: Unable to set hybrid", __func__); + } + + rc = exynos_v4l2_streamoff_cap(exynos_camera, 0); + if (rc < 0) { + ALOGE("%s: Unable to stop stream", __func__); + } + + if (exynos_camera->capture_memory != NULL && exynos_camera->capture_memory->release != NULL) { + exynos_camera->capture_memory->release(exynos_camera->capture_memory); + exynos_camera->capture_memory = NULL; + } + + if (exynos_camera->capture_yuv_buffer != NULL) { + free(exynos_camera->capture_yuv_buffer); + exynos_camera->capture_yuv_buffer = NULL; + } + + if (exynos_camera->capture_jpeg_buffer != NULL) { + free(exynos_camera->capture_jpeg_buffer); + exynos_camera->capture_jpeg_buffer = NULL; + } + + exynos_camera->capture_enabled = 0; +} + +int exynos_camera_capture_setup(struct exynos_camera *exynos_camera) +{ + struct exynos_camera_capture_listener *listener; + struct list_head *list; + int width, height, format; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + // No listener left + if (exynos_camera->capture_listeners == NULL && exynos_camera->capture_enabled) { + exynos_camera_capture_stop(exynos_camera); + return 0; + } + + width = height = format = 0; + + list = (struct list_head *) exynos_camera->capture_listeners; + while (list != NULL) { + listener = (struct exynos_camera_capture_listener *) list; + + // Interleaved format already has the correct width and height for picture set through ioctl + if (exynos_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED) + if (listener->format == V4L2_PIX_FMT_JPEG || listener->format == V4L2_PIX_FMT_INTERLEAVED) + goto list_continue; + + if (listener->width >= width && listener->height >= height) { + width = listener->width; + height = listener->height; + format = listener->format; + } + +list_continue: + list = list->next; + } + + // Override the capture format + if (exynos_camera->camera_capture_format) + format = exynos_camera->camera_capture_format; + + // Only picture is listening, but we need some preview size anyway + if (format == V4L2_PIX_FMT_INTERLEAVED && (width == 0 || height == 0)) { + width = exynos_camera->preview_width; + height = exynos_camera->preview_height; + } + + ALOGD("%s: Selected width: %d, height: %d, format: 0x%x", __func__, width, height, format); + + if (!exynos_camera->capture_enabled) { + exynos_camera->capture_width = width; + exynos_camera->capture_height = height; + exynos_camera->capture_format = format; + + rc = exynos_camera_capture_start(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to start capture", __func__); + return -1; + } + } else if (exynos_camera->capture_width != width || exynos_camera->capture_height != height || exynos_camera->capture_format != format) { + exynos_camera_capture_stop(exynos_camera); + + exynos_camera->capture_width = width; + exynos_camera->capture_height = height; + exynos_camera->capture_format = format; + + rc = exynos_camera_capture_start(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to start capture", __func__); + return -1; + } + } + + return 0; +} + +struct exynos_camera_capture_listener *exynos_camera_capture_listener_register( + struct exynos_camera *exynos_camera, int width, int height, int format, + int (*callback)(struct exynos_camera *exynos_camera, struct exynos_camera_buffer *buffers, int buffers_count)) +{ + struct exynos_camera_capture_listener *listener = NULL; + struct list_head *list_end; + struct list_head *list; + int rc; + + if (exynos_camera == NULL || callback == NULL) + return NULL; + + pthread_mutex_lock(&exynos_camera->capture_mutex); + + listener = calloc(1, sizeof(struct exynos_camera_capture_listener)); + if (listener == NULL) + goto error; + + listener->width = width; + listener->height = height; + listener->format = format; + listener->callback = callback; + listener->busy = 0; + + list_end = (struct list_head *) exynos_camera->capture_listeners; + while (list_end != NULL && list_end->next != NULL) + list_end = list_end->next; + + list = (struct list_head *) listener; + list_head_insert(list, list_end, NULL); + + if (exynos_camera->capture_listeners == NULL) + exynos_camera->capture_listeners = listener; + + rc = exynos_camera_capture_setup(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to setup capture", __func__); + goto error; + } + + rc = 0; + goto complete; + +error: + listener = NULL; + +complete: + pthread_mutex_unlock(&exynos_camera->capture_mutex); + + return listener; +} + +void exynos_camera_capture_listener_unregister( + struct exynos_camera *exynos_camera, + struct exynos_camera_capture_listener *listener) +{ + struct list_head *list; + int rc; + + if (exynos_camera == NULL || listener == NULL) + return; + + pthread_mutex_lock(&exynos_camera->capture_mutex); + + list = (struct list_head *) exynos_camera->capture_listeners; + while (list != NULL) { + if ((void *) list == (void *) listener) { + list_head_remove(list); + + if ((void *) list == (void *) exynos_camera->capture_listeners) + exynos_camera->capture_listeners = (struct exynos_camera_capture_listener *) list->next; + + memset(listener, 0, sizeof(struct exynos_camera_capture_listener)); + free(listener); + + break; + } +list_continue: + list = list->next; + } + + rc = exynos_camera_capture_setup(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to setup capture", __func__); + goto complete; + } + +complete: + pthread_mutex_unlock(&exynos_camera->capture_mutex); +} + +// Preview + +int exynos_camera_preview_output_start(struct exynos_camera *exynos_camera) +{ + struct exynos_v4l2_output *output; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exynos_camera->preview_output_enabled) { + ALOGE("Preview was already started!"); + return -1; + } + + output = &exynos_camera->preview_output; + + memset(output, 0, sizeof(struct exynos_v4l2_output)); + output->v4l2_id = 1; + output->width = exynos_camera->preview_width; + output->height = exynos_camera->preview_height; + output->format = exynos_camera->preview_format; + output->buffer_width = exynos_camera->preview_buffer.width; + output->buffer_height = exynos_camera->preview_buffer.height; + output->buffer_format = exynos_camera->preview_buffer.format; + output->buffers_count = EXYNOS_CAMERA_PREVIEW_BUFFERS_COUNT; + + rc = exynos_v4l2_output_start(exynos_camera, output); + if (rc < 0) { + ALOGE("%s: Unable to start preview output", __func__); + goto error; + } + + exynos_camera->preview_output_enabled = 1; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +void exynos_camera_preview_output_stop(struct exynos_camera *exynos_camera) +{ + struct exynos_v4l2_output *output; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exynos_camera->preview_output_enabled) { + ALOGE("Preview was already stopped!"); + return; + } + + output = &exynos_camera->preview_output; + + exynos_v4l2_output_stop(exynos_camera, output); + + exynos_camera->preview_output_enabled = 0; +} + +int exynos_camera_preview_callback(struct exynos_camera *exynos_camera, + struct exynos_camera_buffer *buffers, int buffers_count) +{ + struct exynos_camera_buffer *buffer = NULL; + int width, height, format; + int buffer_width, buffer_height, buffer_format; + int rc; + int i; + + if (exynos_camera == NULL || buffers == NULL || buffers_count <= 0) + return -EINVAL; + +// ALOGD("%s()", __func__); + + if (exynos_camera->preview_listener == NULL) + return -1; + + if (exynos_camera->preview_listener->busy) { + ALOGE("%s: Dropping buffer", __func__); + return 0; + } + + exynos_camera->preview_listener->busy = 1; + + width = exynos_camera->preview_width; + height = exynos_camera->preview_height; + format = exynos_camera->preview_format; + + for (i = 0; i < buffers_count; i++) { + if (buffers->format == V4L2_PIX_FMT_JPEG) + goto buffers_continue; + + if (buffers->format == V4L2_PIX_FMT_INTERLEAVED) + goto buffers_continue; + + // Optimal buffer + if (buffers->width == width && buffers->height == height) { + buffer = buffers; + break; + } + + // Might-work buffer, but not optimal + buffer = buffers; + +buffers_continue: + buffers = (struct exynos_camera_buffer *) ((unsigned char *) buffers + sizeof(struct exynos_camera_buffer)); + } + + if (buffer == NULL) { + ALOGE("%s: Unable to find an appropriate buffer for preview", __func__); + exynos_camera->preview_listener->busy = 0; + return 0; + } + + buffer_width = buffer->width; + buffer_height = buffer->height; + buffer_format = buffer->format; + + pthread_mutex_lock(&exynos_camera->preview_mutex); + + if (buffer_width != width || buffer_height != height || buffer_format != format) { + if (!exynos_camera->preview_output_enabled) { + memcpy(&exynos_camera->preview_buffer, buffer, sizeof(struct exynos_camera_buffer)); + + rc = exynos_camera_preview_output_start(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to start preview", __func__); + goto error; + } + } else if (exynos_camera->preview_buffer.width != buffer_width || exynos_camera->preview_buffer.height != buffer_height || exynos_camera->preview_buffer.format != buffer_format) { + exynos_camera_preview_output_stop(exynos_camera); + + memcpy(&exynos_camera->preview_buffer, buffer, sizeof(struct exynos_camera_buffer)); + + rc = exynos_camera_preview_output_start(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to start preview", __func__); + goto error; + } + } else { + memcpy(&exynos_camera->preview_buffer, buffer, sizeof(struct exynos_camera_buffer)); + } + } else { + // The buffer format exactly matches our expectations + + if (exynos_camera->preview_output_enabled) + exynos_camera_preview_output_stop(exynos_camera); + + memcpy(&exynos_camera->preview_buffer, buffer, sizeof(struct exynos_camera_buffer)); + } + + pthread_mutex_unlock(&exynos_camera->preview_lock_mutex); + + pthread_mutex_unlock(&exynos_camera->preview_mutex); + + rc = 0; + goto complete; + +error: + pthread_mutex_unlock(&exynos_camera->preview_mutex); + + exynos_camera->preview_listener->busy = 0; + + rc = -1; + +complete: + return rc; +} + +int exynos_camera_preview(struct exynos_camera *exynos_camera) +{ + struct exynos_v4l2_output *output; + int width, height, format; + buffer_handle_t *window_buffer; + void *window_data; + int window_stride; + camera_memory_t *memory; + void *memory_pointer; + int memory_index; + int memory_size; + int rc; + + if (exynos_camera == NULL) + goto error; + +// ALOGD("%s()", __func__); + + width = exynos_camera->preview_width; + height = exynos_camera->preview_height; + format = exynos_camera->preview_format; + + output = &exynos_camera->preview_output; + + if (exynos_camera->preview_output_enabled) { + rc = exynos_v4l2_output(exynos_camera, output, exynos_camera->preview_buffer.address); + if (rc < 0) { + ALOGE("%s: Unable to output preview", __func__); + goto error; + } + + memory = output->memory; + memory_index = output->memory_index; + memory_pointer = (void *) ((unsigned char *) memory->data + output->buffer_length * memory_index); + memory_size = output->buffer_length; + } else { + // In that case, we can directly use the capture memory + memory = exynos_camera->capture_memory; + memory_index = exynos_camera->capture_memory_index; + memory_pointer = exynos_camera->preview_buffer.pointer; + memory_size = exynos_camera->preview_buffer.length; + } + + if (exynos_camera->preview_window != NULL && exynos_camera->gralloc != NULL) { + exynos_camera->preview_window->dequeue_buffer(exynos_camera->preview_window, &window_buffer, &window_stride); + exynos_camera->gralloc->lock(exynos_camera->gralloc, *window_buffer, GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0, width, height, &window_data); + + if (window_data == NULL) { + ALOGE("%s: Unable to lock gralloc", __func__); + goto error; + } + + memcpy(window_data, memory_pointer, memory_size); + + exynos_camera->gralloc->unlock(exynos_camera->gralloc, *window_buffer); + exynos_camera->preview_window->enqueue_buffer(exynos_camera->preview_window, window_buffer); + } + + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_PREVIEW_FRAME) && EXYNOS_CAMERA_CALLBACK_DEFINED(data) && !exynos_camera->callback_lock) { + exynos_camera->callbacks.data(CAMERA_MSG_PREVIEW_FRAME, memory, memory_index, NULL, exynos_camera->callbacks.user); + } + + if (exynos_camera->preview_output_enabled) { + rc = exynos_v4l2_output_release(exynos_camera, output); + if (rc < 0) { + ALOGE("%s: Unable to release preview output", __func__); + goto error; + } + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + exynos_camera->preview_listener->busy = 0; + + return rc; +} + +void *exynos_camera_preview_thread(void *data) +{ + struct exynos_camera *exynos_camera; + int rc; + + if (data == NULL) + return NULL; + + exynos_camera = (struct exynos_camera *) data; + + ALOGE("%s: Starting thread", __func__); + exynos_camera->preview_thread_running = 1; + + while (exynos_camera->preview_thread_enabled) { + pthread_mutex_lock(&exynos_camera->preview_lock_mutex); + + pthread_mutex_lock(&exynos_camera->preview_mutex); + + if (exynos_camera->preview_listener == NULL) { + pthread_mutex_unlock(&exynos_camera->preview_mutex); + break; + } + + if (exynos_camera->preview_listener->busy) { + rc = exynos_camera_preview(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to preview", __func__); + pthread_mutex_unlock(&exynos_camera->preview_mutex); + break; + } + } + + pthread_mutex_unlock(&exynos_camera->preview_mutex); + } + + exynos_camera->preview_thread_running = 0; + ALOGE("%s: Exiting thread", __func__); + + return NULL; +} + +int exynos_camera_preview_thread_start(struct exynos_camera *exynos_camera) +{ + struct exynos_camera_capture_listener *listener; + pthread_attr_t thread_attr; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exynos_camera->preview_thread_enabled) { + ALOGE("Preview thread was already started!"); + return -1; + } + + pthread_mutex_init(&exynos_camera->preview_mutex, NULL); + pthread_mutex_init(&exynos_camera->preview_lock_mutex, NULL); + + // Initial lock + pthread_mutex_lock(&exynos_camera->preview_lock_mutex); + + pthread_attr_init(&thread_attr); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + + exynos_camera->preview_thread_enabled = 1; + + rc = pthread_create(&exynos_camera->preview_thread, &thread_attr, exynos_camera_preview_thread, (void *) exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to create thread", __func__); + goto error; + } + + listener = exynos_camera_capture_listener_register(exynos_camera, exynos_camera->preview_width, exynos_camera->preview_height, exynos_camera->preview_format, exynos_camera_preview_callback); + if (listener == NULL) { + ALOGE("%s: Unable to register preview capture listener", __func__); + goto error; + } + + exynos_camera->preview_listener = listener; + + rc = 0; + goto complete; + +error: + pthread_mutex_destroy(&exynos_camera->preview_mutex); + pthread_mutex_destroy(&exynos_camera->preview_lock_mutex); + + rc = -1; + +complete: + return rc; +} + +void exynos_camera_preview_thread_stop(struct exynos_camera *exynos_camera) +{ + int i; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exynos_camera->preview_thread_enabled) { + ALOGE("Preview thread was already stopped!"); + return; + } + + if (exynos_camera->preview_listener != NULL) { + exynos_camera_capture_listener_unregister(exynos_camera, exynos_camera->preview_listener); + exynos_camera->preview_listener = NULL; + } + + exynos_camera->preview_thread_enabled = 0; + + pthread_mutex_unlock(&exynos_camera->preview_lock_mutex); + + // Wait for the thread to end + i = 0; + while (exynos_camera->preview_thread_running) { + if (i++ > 10000) { + ALOGE("Preview thread is taking too long to end, something is going wrong"); + break; + } + usleep(100); + } + + if (exynos_camera->preview_output_enabled) { + pthread_mutex_lock(&exynos_camera->preview_mutex); + exynos_camera_preview_output_stop(exynos_camera); + pthread_mutex_unlock(&exynos_camera->preview_mutex); + } + + pthread_mutex_destroy(&exynos_camera->preview_mutex); + pthread_mutex_destroy(&exynos_camera->preview_lock_mutex); + + // Invalidate the preview window + exynos_camera->preview_window = NULL; +} + +// Picture + +int exynos_camera_picture_callback(struct exynos_camera *exynos_camera, + struct exynos_camera_buffer *buffers, int buffers_count) +{ + struct exynos_camera_buffer *jpeg_buffer = NULL; + struct exynos_camera_buffer *jpeg_thumbnail_buffer = NULL; + struct exynos_camera_buffer *yuv_buffer = NULL; + struct exynos_camera_buffer *yuv_thumbnail_buffer = NULL; + int width, height; + int thumbnail_width, thumbnail_height; + int rc; + int i; + + if (exynos_camera == NULL || buffers == NULL || buffers_count <= 0) + return -EINVAL; + +// ALOGD("%s()", __func__); + + width = exynos_camera->picture_width; + height = exynos_camera->picture_height; + thumbnail_width = exynos_camera->jpeg_thumbnail_width; + thumbnail_height = exynos_camera->jpeg_thumbnail_height; + + if (exynos_camera->picture_completed) + return -1; + + if (exynos_camera->picture_listener == NULL) + return -1; + + if (exynos_camera->picture_listener->busy) { + ALOGE("%s: Dropping buffer", __func__); + return 0; + } + + pthread_mutex_lock(&exynos_camera->picture_mutex); + + if (!exynos_camera->picture_enabled && !exynos_camera->camera_fimc_is) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_CAPTURE, 0); + if (rc < 0) { + ALOGE("%s: Unable to set capture", __func__); + goto error; + } + + if (exynos_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED && !exynos_camera->capture_hybrid) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_HYBRID_CAPTURE, 1); + if (rc < 0) { + ALOGE("%s: Unable to set hybrid capture", __func__); + goto error; + } + + exynos_camera->capture_hybrid = 1; + } + + exynos_camera->picture_enabled = 1; + + pthread_mutex_unlock(&exynos_camera->picture_mutex); + return 0; + } + + pthread_mutex_unlock(&exynos_camera->picture_mutex); + + exynos_camera->picture_listener->busy = 1; + + // Let's assume the picture format is JPEG + + for (i = 0; i < buffers_count; i++) { + if (buffers->format == V4L2_PIX_FMT_JPEG) { + if (buffers->width == width && buffers->height == height) + jpeg_buffer = buffers; + else if (buffers->width == thumbnail_width && buffers->height == thumbnail_height) + jpeg_thumbnail_buffer = buffers; + } else { + if (buffers->width >= width && buffers->height >= height) + yuv_buffer = buffers; + if (buffers->width >= thumbnail_width && buffers->height >= thumbnail_height) + yuv_thumbnail_buffer = buffers; + } + +buffers_continue: + buffers = (struct exynos_camera_buffer *) ((unsigned char *) buffers + sizeof(struct exynos_camera_buffer)); + } + + if (jpeg_buffer == NULL && yuv_buffer == NULL) { +// ALOGE("%s: Unable to find an appropriate buffer for picture", __func__); + exynos_camera->picture_listener->busy = 0; + return 0; + } + + // Interleaved must not use a preview frame as picture + if (exynos_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED && jpeg_buffer == NULL) { + exynos_camera->picture_listener->busy = 0; + return 0; + } + + pthread_mutex_lock(&exynos_camera->picture_mutex); + + if (jpeg_buffer == NULL) + memset(&exynos_camera->picture_jpeg_buffer, 0, sizeof(exynos_camera->picture_jpeg_buffer)); + else + memcpy(&exynos_camera->picture_jpeg_buffer, jpeg_buffer, sizeof(struct exynos_camera_buffer)); + + if (jpeg_thumbnail_buffer == NULL) + memset(&exynos_camera->picture_jpeg_thumbnail_buffer, 0, sizeof(exynos_camera->picture_jpeg_thumbnail_buffer)); + else + memcpy(&exynos_camera->picture_jpeg_thumbnail_buffer, jpeg_thumbnail_buffer, sizeof(struct exynos_camera_buffer)); + + if (yuv_buffer == NULL) + memset(&exynos_camera->picture_yuv_buffer, 0, sizeof(exynos_camera->picture_yuv_buffer)); + else + memcpy(&exynos_camera->picture_yuv_buffer, yuv_buffer, sizeof(struct exynos_camera_buffer)); + + if (yuv_thumbnail_buffer == NULL) + memset(&exynos_camera->picture_yuv_thumbnail_buffer, 0, sizeof(exynos_camera->picture_yuv_thumbnail_buffer)); + else + memcpy(&exynos_camera->picture_yuv_thumbnail_buffer, yuv_thumbnail_buffer, sizeof(struct exynos_camera_buffer)); + + pthread_mutex_unlock(&exynos_camera->picture_lock_mutex); + + pthread_mutex_unlock(&exynos_camera->picture_mutex); + + rc = 0; + goto complete; + +error: + pthread_mutex_unlock(&exynos_camera->picture_mutex); + + exynos_camera->picture_listener->busy = 0; + + rc = -1; + +complete: + return rc; +} + +int exynos_camera_picture(struct exynos_camera *exynos_camera) +{ + struct exynos_camera_buffer *jpeg_buffer; + struct exynos_camera_buffer *jpeg_thumbnail_buffer; + struct exynos_camera_buffer *yuv_buffer; + struct exynos_camera_buffer *yuv_thumbnail_buffer; + struct exynos_v4l2_output output; + struct exynos_jpeg jpeg; + struct exynos_exif exif; + int output_enabled = 0; + int width, height, format; + int buffer_width, buffer_height, buffer_format, buffer_address; + camera_memory_t *memory = NULL; + int memory_size; + unsigned char *p; + camera_memory_t *jpeg_memory = NULL; + void *jpeg_data = NULL; + int jpeg_size = 0; + camera_memory_t *jpeg_thumbnail_memory = NULL; + void *jpeg_thumbnail_data = NULL; + int jpeg_thumbnail_size = 0; + void *yuv_data = NULL; + int yuv_address; + int yuv_size = 0; + void *yuv_thumbnail_data = NULL; + int yuv_thumbnail_address; + int yuv_thumbnail_size = 0; + int rc; + + if (exynos_camera == NULL) + goto error; + +// ALOGD("%s()", __func__); + + jpeg_buffer = &exynos_camera->picture_jpeg_buffer; + jpeg_thumbnail_buffer = &exynos_camera->picture_jpeg_thumbnail_buffer; + yuv_buffer = &exynos_camera->picture_yuv_buffer; + yuv_thumbnail_buffer = &exynos_camera->picture_yuv_thumbnail_buffer; + + if (jpeg_buffer->pointer != NULL && jpeg_buffer->length > 0) { + jpeg_data = jpeg_buffer->pointer; + jpeg_size = jpeg_buffer->length; + } + + if (jpeg_thumbnail_buffer->pointer != NULL && jpeg_thumbnail_buffer->length > 0) { + jpeg_thumbnail_data = jpeg_thumbnail_buffer->pointer; + jpeg_thumbnail_size = jpeg_thumbnail_buffer->length; + } + + if (yuv_buffer->pointer != NULL && yuv_buffer->length > 0) { + yuv_data = yuv_buffer->pointer; + yuv_address = yuv_buffer->address; + yuv_size = yuv_buffer->length; + } + + if (yuv_thumbnail_buffer->pointer != NULL && yuv_thumbnail_buffer->length > 0) { + yuv_thumbnail_data = yuv_thumbnail_buffer->pointer; + yuv_thumbnail_address = yuv_thumbnail_buffer->address; + yuv_thumbnail_size = yuv_thumbnail_buffer->length; + } + + // JPEG + + if (jpeg_data == NULL) { + if (yuv_data == NULL || yuv_size <= 0) { + ALOGE("%s: Unable to create jpeg without an YUV buffer", __func__); + goto error; + } + + width = exynos_camera->picture_width; + height = exynos_camera->picture_height; + format = yuv_buffer->format; + + buffer_width = yuv_buffer->width; + buffer_height = yuv_buffer->height; + buffer_format = yuv_buffer->format; + buffer_address = yuv_buffer->address; + + if (width != buffer_width && height != buffer_height) { + format = EXYNOS_CAMERA_PICTURE_OUTPUT_FORMAT; + + memset(&output, 0, sizeof(output)); + output.v4l2_id = 2; + output.width = width; + output.height = height; + output.format = format; + output.buffer_width = buffer_width; + output.buffer_height = buffer_height; + output.buffer_format = buffer_format; + output.buffers_count = 1; + + rc = exynos_v4l2_output_start(exynos_camera, &output); + if (rc < 0) { + ALOGE("%s: Unable to start picture output", __func__); + goto error; + } + + rc = exynos_v4l2_output(exynos_camera, &output, buffer_address); + if (rc < 0) { + ALOGE("%s: Unable to output picture", __func__); + goto error; + } + + output_enabled = 1; + + yuv_data = output.memory->data; + yuv_address = output.memory_address; + yuv_size = output.buffer_length; + } + + memset(&jpeg, 0, sizeof(jpeg)); + jpeg.width = width; + jpeg.height = height; + jpeg.format = format; + jpeg.quality = exynos_camera->jpeg_quality; + + rc = exynos_jpeg_start(exynos_camera, &jpeg); + if (rc < 0) { + ALOGE("%s: Unable to start jpeg", __func__); + goto error; + } + + if (jpeg.memory_in_pointer == NULL) { + ALOGE("%s: Invalid memory input pointer", __func__); + goto error; + } + + memcpy(jpeg.memory_in_pointer, yuv_data, yuv_size); + + rc = exynos_jpeg(exynos_camera, &jpeg); + if (rc < 0) { + ALOGE("%s: Unable to jpeg", __func__); + goto error; + } + + jpeg_size = jpeg.memory_out_size; + if (jpeg_size <= 0) { + ALOGE("%s: Invalid jpeg size", __func__); + goto error; + } + + if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { + jpeg_memory = exynos_camera->callbacks.request_memory(-1, jpeg_size, 1, exynos_camera->callbacks.user); + if (jpeg_memory == NULL || jpeg_memory->data == NULL || jpeg_memory->data == MAP_FAILED) { + ALOGE("%s: Unable to request memory", __func__); + goto error; + } + } else { + ALOGE("%s: No memory request function!", __func__); + goto error; + } + + jpeg_data = jpeg_memory->data; + + memcpy(jpeg_data, jpeg.memory_out_pointer, jpeg_size); + + exynos_jpeg_stop(exynos_camera, &jpeg); + + if (output_enabled) { + exynos_v4l2_output_stop(exynos_camera, &output); + output_enabled = 0; + } + } + + // Thumbnail + + if (jpeg_thumbnail_data == NULL) { + if (yuv_thumbnail_data == NULL || yuv_thumbnail_size <= 0) { + ALOGE("%s: Unable to create jpeg thumbnail without an YUV buffer", __func__); + goto error; + } + + width = exynos_camera->jpeg_thumbnail_width; + height = exynos_camera->jpeg_thumbnail_height; + format = yuv_thumbnail_buffer->format; + + buffer_width = yuv_thumbnail_buffer->width; + buffer_height = yuv_thumbnail_buffer->height; + buffer_format = yuv_thumbnail_buffer->format; + buffer_address = yuv_thumbnail_buffer->address; + + if (width != buffer_width && height != buffer_height) { + format = EXYNOS_CAMERA_PICTURE_OUTPUT_FORMAT; + + memset(&output, 0, sizeof(output)); + output.v4l2_id = 2; + output.width = width; + output.height = height; + output.format = format; + output.buffer_width = buffer_width; + output.buffer_height = buffer_height; + output.buffer_format = buffer_format; + output.buffers_count = 1; + + rc = exynos_v4l2_output_start(exynos_camera, &output); + if (rc < 0) { + ALOGE("%s: Unable to start thumbnail picture output", __func__); + goto error; + } + + output_enabled = 1; + + rc = exynos_v4l2_output(exynos_camera, &output, buffer_address); + if (rc < 0) { + ALOGE("%s: Unable to output thumbnail picture", __func__); + goto error; + } + + yuv_thumbnail_data = output.memory->data; + yuv_thumbnail_address = output.memory_address; + yuv_thumbnail_size = output.buffer_length; + } + + memset(&jpeg, 0, sizeof(jpeg)); + jpeg.width = width; + jpeg.height = height; + jpeg.format = format; + jpeg.quality = exynos_camera->jpeg_thumbnail_quality; + + rc = exynos_jpeg_start(exynos_camera, &jpeg); + if (rc < 0) { + ALOGE("%s: Unable to start jpeg", __func__); + goto error; + } + + if (jpeg.memory_in_pointer == NULL) { + ALOGE("%s: Invalid memory input pointer", __func__); + goto error; + } + + memcpy(jpeg.memory_in_pointer, yuv_thumbnail_data, yuv_thumbnail_size); + + rc = exynos_jpeg(exynos_camera, &jpeg); + if (rc < 0) { + ALOGE("%s: Unable to jpeg", __func__); + goto error; + } + + jpeg_thumbnail_size = jpeg.memory_out_size; + if (jpeg_thumbnail_size <= 0) { + ALOGE("%s: Invalid jpeg size", __func__); + goto error; + } + + if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { + jpeg_thumbnail_memory = exynos_camera->callbacks.request_memory(-1, jpeg_thumbnail_size, 1, exynos_camera->callbacks.user); + if (jpeg_thumbnail_memory == NULL || jpeg_thumbnail_memory->data == NULL || jpeg_thumbnail_memory->data == MAP_FAILED) { + ALOGE("%s: Unable to request memory", __func__); + goto error; + } + } else { + ALOGE("%s: No memory request function!", __func__); + goto error; + } + + jpeg_thumbnail_data = jpeg_thumbnail_memory->data; + + memcpy(jpeg_thumbnail_data, jpeg.memory_out_pointer, jpeg_thumbnail_size); + + exynos_jpeg_stop(exynos_camera, &jpeg); + + if (output_enabled) { + exynos_v4l2_output_stop(exynos_camera, &output); + output_enabled = 0; + } + } + + // EXIF + + memset(&exif, 0, sizeof(exif)); + exif.jpeg_thumbnail_data = jpeg_thumbnail_data; + exif.jpeg_thumbnail_size = jpeg_thumbnail_size; + + rc = exynos_exif_start(exynos_camera, &exif); + if (rc < 0) { + ALOGE("%s: Unable to start exif", __func__); + goto error; + } + + rc = exynos_exif(exynos_camera, &exif); + if (rc < 0) { + ALOGE("%s: Unable to exif", __func__); + goto error; + } + + memory_size = exif.memory_size + jpeg_size; + + if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { + memory = exynos_camera->callbacks.request_memory(-1, memory_size, 1, exynos_camera->callbacks.user); + if (memory == NULL || memory->data == NULL || memory->data == MAP_FAILED) { + ALOGE("%s: Unable to request memory", __func__); + goto error; + } + } else { + ALOGE("%s: No memory request function!", __func__); + goto error; + } + + p = (unsigned char *) memory->data; + + // Copy the first two bytes of the JPEG picture + memcpy(p, jpeg_data, 2); + p += 2; + + // Copy the EXIF data + memcpy(p, exif.memory->data, exif.memory_size); + p += exif.memory_size; + + // Copy the JPEG picture + memcpy(p, (void *) ((unsigned char *) jpeg_data + 2), jpeg_size - 2); + + exynos_exif_stop(exynos_camera, &exif); + + exynos_camera->picture_memory = memory; + + rc = 0; + goto complete; + +error: + if (output_enabled) + exynos_v4l2_output_stop(exynos_camera, &output); + + if (memory != NULL && memory->release != NULL) { + memory->release(memory); + exynos_camera->picture_memory = NULL; + } + + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_ERROR) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) + exynos_camera->callbacks.notify(CAMERA_MSG_ERROR, -1, 0, exynos_camera->callbacks.user); + + rc = -1; + +complete: + if (jpeg_memory != NULL && jpeg_memory->release != NULL) + jpeg_memory->release(jpeg_memory); + + if (jpeg_thumbnail_memory != NULL && jpeg_thumbnail_memory->release != NULL) + jpeg_thumbnail_memory->release(jpeg_thumbnail_memory); + + exynos_camera->picture_completed = 1; + exynos_camera->picture_listener->busy = 0; + + return rc; +} + +void *exynos_camera_picture_thread(void *data) +{ + struct exynos_camera *exynos_camera; + int rc; + + if (data == NULL) + return NULL; + + exynos_camera = (struct exynos_camera *) data; + + ALOGE("%s: Starting thread", __func__); + exynos_camera->picture_thread_running = 1; + + while (exynos_camera->picture_thread_enabled) { + pthread_mutex_lock(&exynos_camera->picture_lock_mutex); + + pthread_mutex_lock(&exynos_camera->picture_mutex); + + if (exynos_camera->picture_listener == NULL) { + pthread_mutex_unlock(&exynos_camera->picture_mutex); + break; + } + + if (exynos_camera->picture_listener->busy) { + rc = exynos_camera_picture(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to take picture", __func__); + pthread_mutex_unlock(&exynos_camera->picture_mutex); + break; + } + } + + pthread_mutex_unlock(&exynos_camera->picture_mutex); + + if (exynos_camera->picture_completed) { + exynos_camera->picture_thread_running = 0; + exynos_camera_picture_thread_stop(exynos_camera); + break; + } + } + + exynos_camera->picture_thread_running = 0; + ALOGE("%s: Exiting thread", __func__); + + return NULL; +} + +int exynos_camera_picture_thread_start(struct exynos_camera *exynos_camera) +{ + struct exynos_camera_capture_listener *listener; + pthread_attr_t thread_attr; + int format; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exynos_camera->picture_thread_enabled) { + ALOGE("Picture thread was already started!"); + return -1; + } + + if (exynos_camera->camera_picture_format) + format = exynos_camera->camera_picture_format; + else + format = exynos_camera->picture_format; + + pthread_mutex_init(&exynos_camera->picture_mutex, NULL); + pthread_mutex_init(&exynos_camera->picture_lock_mutex, NULL); + + // Initial lock + pthread_mutex_lock(&exynos_camera->picture_lock_mutex); + + pthread_attr_init(&thread_attr); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + + exynos_camera->picture_thread_enabled = 1; + + rc = pthread_create(&exynos_camera->picture_thread, &thread_attr, exynos_camera_picture_thread, (void *) exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to create thread", __func__); + goto error; + } + + exynos_camera->picture_completed = 0; + + listener = exynos_camera_capture_listener_register(exynos_camera, exynos_camera->picture_width, exynos_camera->picture_height, format, exynos_camera_picture_callback); + if (listener == NULL) { + ALOGE("%s: Unable to register picture capture listener", __func__); + goto error; + } + + exynos_camera->picture_listener = listener; + + rc = 0; + goto complete; + +error: + pthread_mutex_destroy(&exynos_camera->picture_mutex); + pthread_mutex_destroy(&exynos_camera->picture_lock_mutex); + + rc = -1; + +complete: + return rc; +} + +void exynos_camera_picture_thread_stop(struct exynos_camera *exynos_camera) +{ + camera_memory_t *memory; + int i; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exynos_camera->picture_thread_enabled) { + ALOGE("Picture thread was already stopped!"); + return; + } + + memory = exynos_camera->picture_memory; + + if (exynos_camera->picture_listener != NULL) { + exynos_camera_capture_listener_unregister(exynos_camera, exynos_camera->picture_listener); + exynos_camera->picture_listener = NULL; + } + + exynos_camera->picture_thread_enabled = 0; + + pthread_mutex_unlock(&exynos_camera->picture_lock_mutex); + + // Wait for the thread to end + i = 0; + while (exynos_camera->picture_thread_running) { + if (i++ > 10000) { + ALOGE("Picture thread is taking too long to end, something is going wrong"); + break; + } + usleep(100); + } + + if (exynos_camera->picture_enabled) { + pthread_mutex_lock(&exynos_camera->picture_mutex); + exynos_camera->picture_enabled = 0; + pthread_mutex_unlock(&exynos_camera->picture_mutex); + } + + pthread_mutex_destroy(&exynos_camera->picture_mutex); + pthread_mutex_destroy(&exynos_camera->picture_lock_mutex); + + if (exynos_camera->picture_completed && memory != NULL) { + // It is important to return at this point (and not before) for burst + + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_SHUTTER) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) + exynos_camera->callbacks.notify(CAMERA_MSG_SHUTTER, 0, 0, exynos_camera->callbacks.user); + + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_COMPRESSED_IMAGE) && EXYNOS_CAMERA_CALLBACK_DEFINED(data) && !exynos_camera->callback_lock) + exynos_camera->callbacks.data(CAMERA_MSG_COMPRESSED_IMAGE, memory, 0, NULL, exynos_camera->callbacks.user); + + if (memory->release != NULL) { + memory->release(memory); + exynos_camera->picture_memory = NULL; + } + } +} + +// Recording + +int exynos_camera_recording_output_start(struct exynos_camera *exynos_camera) +{ + struct exynos_v4l2_output *output; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exynos_camera->recording_output_enabled) { + ALOGE("Recording was already started!"); + return -1; + } + + output = &exynos_camera->recording_output; + + memset(output, 0, sizeof(struct exynos_v4l2_output)); + output->v4l2_id = 3; + output->width = exynos_camera->recording_width; + output->height = exynos_camera->recording_height; + output->format = exynos_camera->recording_format; + output->buffer_width = exynos_camera->recording_buffer.width; + output->buffer_height = exynos_camera->recording_buffer.height; + output->buffer_format = exynos_camera->recording_buffer.format; + output->buffers_count = EXYNOS_CAMERA_RECORDING_BUFFERS_COUNT; + + rc = exynos_v4l2_output_start(exynos_camera, output); + if (rc < 0) { + ALOGE("%s: Unable to start recording output", __func__); + goto error; + } + + exynos_camera->recording_output_enabled = 1; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +void exynos_camera_recording_output_stop(struct exynos_camera *exynos_camera) +{ + struct exynos_v4l2_output *output; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exynos_camera->recording_output_enabled) { + ALOGE("Recording was already stopped!"); + return; + } + + output = &exynos_camera->recording_output; + + exynos_v4l2_output_stop(exynos_camera, output); + + exynos_camera->recording_output_enabled = 0; +} + +int exynos_camera_recording_callback(struct exynos_camera *exynos_camera, + struct exynos_camera_buffer *buffers, int buffers_count) +{ + struct exynos_camera_buffer *buffer = NULL; + int width, height, format; + int buffer_width, buffer_height, buffer_format; + int rc; + int i; + + if (exynos_camera == NULL || buffers == NULL || buffers_count <= 0) + return -EINVAL; + +// ALOGD("%s()", __func__); + + if (exynos_camera->recording_listener == NULL) + return -1; + + if (exynos_camera->recording_listener->busy) { + ALOGE("%s: Dropping buffer", __func__); + return 0; + } + + exynos_camera->recording_listener->busy = 1; + + width = exynos_camera->recording_width; + height = exynos_camera->recording_height; + format = exynos_camera->recording_format; + + for (i = 0; i < buffers_count; i++) { + if (buffers->format == V4L2_PIX_FMT_JPEG) + goto buffers_continue; + + if (buffers->format == V4L2_PIX_FMT_INTERLEAVED) + goto buffers_continue; + + // Optimal buffer + if (buffers->width == width && buffers->height == height) { + buffer = buffers; + break; + } + + // Might-work buffer, but not optimal + buffer = buffers; + +buffers_continue: + buffers = (struct exynos_camera_buffer *) ((unsigned char *) buffers + sizeof(struct exynos_camera_buffer)); + } + + if (buffer == NULL) { + ALOGE("%s: Unable to find an appropriate buffer for recording", __func__); + exynos_camera->recording_listener->busy = 0; + return 0; + } + + buffer_width = buffer->width; + buffer_height = buffer->height; + buffer_format = buffer->format; + + pthread_mutex_lock(&exynos_camera->recording_mutex); + + if (!exynos_camera->recording_output_enabled) { + memcpy(&exynos_camera->recording_buffer, buffer, sizeof(struct exynos_camera_buffer)); + + rc = exynos_camera_recording_output_start(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to start recording", __func__); + goto error; + } + } else if (exynos_camera->recording_buffer.width != buffer_width || exynos_camera->recording_buffer.height != buffer_height || exynos_camera->recording_buffer.format != buffer_format) { + exynos_camera_recording_output_stop(exynos_camera); + + memcpy(&exynos_camera->recording_buffer, buffer, sizeof(struct exynos_camera_buffer)); + + rc = exynos_camera_recording_output_start(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to start recording", __func__); + goto error; + } + } else { + memcpy(&exynos_camera->recording_buffer, buffer, sizeof(struct exynos_camera_buffer)); + } + + pthread_mutex_unlock(&exynos_camera->recording_lock_mutex); + + pthread_mutex_unlock(&exynos_camera->recording_mutex); + + rc = 0; + goto complete; + +error: + pthread_mutex_unlock(&exynos_camera->recording_mutex); + + exynos_camera->recording_listener->busy = 0; + + rc = -1; + +complete: + return rc; +} + +void exynos_camera_recording_frame_release(struct exynos_camera *exynos_camera) +{ + struct exynos_v4l2_output *output; + int rc; + + if (exynos_camera == NULL) + return; + +// ALOGD("%s()", __func__); + + output = &exynos_camera->recording_output; + + if (!exynos_camera->recording_output_enabled) { + ALOGE("%s: Recording output should always be enabled", __func__); + return; + } + + rc = exynos_v4l2_output_release(exynos_camera, output); + if (rc < 0) { + ALOGE("%s: Unable to release recording output", __func__); + return; + } +} + +int exynos_camera_recording(struct exynos_camera *exynos_camera) +{ + struct exynos_v4l2_output *output; + struct exynos_camera_addrs *addrs; + int width, height, format; + camera_memory_t *memory; + int memory_address; + int memory_index; + int buffer_length; + int buffers_count; + nsecs_t timestamp; + int rc; + + if (exynos_camera == NULL) + goto error; + +// ALOGD("%s()", __func__); + + width = exynos_camera->recording_width; + height = exynos_camera->recording_height; + format = exynos_camera->recording_format; + + output = &exynos_camera->recording_output; + + buffer_length = exynos_camera->recording_buffer_length; + buffers_count = exynos_camera->recording_buffers_count; + + timestamp = systemTime(1); + + if (!exynos_camera->recording_output_enabled) { + ALOGE("%s: Recording output should always be enabled", __func__); + goto error; + } + + rc = exynos_v4l2_output(exynos_camera, output, exynos_camera->recording_buffer.address); + if (rc < 0) { + ALOGE("%s: Unable to output recording", __func__); + goto error; + } + + if (exynos_camera->recording_metadata) { + memory = exynos_camera->recording_memory; + memory_index = exynos_camera->recording_memory_index; + memory_address = output->memory_address + output->buffer_length * output->memory_index; + + addrs = (struct exynos_camera_addrs *) ((unsigned char *) memory->data + buffer_length * memory_index); + memset(addrs, 0, sizeof(struct exynos_camera_addrs)); + addrs->type = 0; // kMetadataBufferTypeCameraSource + addrs->index = memory_index; + + exynos_camera_yuv_planes(width, height, format, memory_address, (int *) &addrs->y, (int *) &addrs->cbcr, NULL); + } else { + memory = output->memory; + memory_index = output->memory_index; + } + + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_VIDEO_FRAME) && EXYNOS_CAMERA_CALLBACK_DEFINED(data_timestamp) && !exynos_camera->callback_lock) + exynos_camera->callbacks.data_timestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, memory, memory_index, exynos_camera->callbacks.user); + else + exynos_camera_recording_frame_release(exynos_camera); + + if (exynos_camera->recording_metadata) { + memory_index++; + exynos_camera->recording_memory_index = memory_index % buffers_count; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + exynos_camera->recording_listener->busy = 0; + + return rc; +} + +void *exynos_camera_recording_thread(void *data) +{ + struct exynos_camera *exynos_camera; + int rc; + + if (data == NULL) + return NULL; + + exynos_camera = (struct exynos_camera *) data; + + ALOGE("%s: Starting thread", __func__); + exynos_camera->recording_thread_running = 1; + + while (exynos_camera->recording_thread_enabled) { + pthread_mutex_lock(&exynos_camera->recording_lock_mutex); + + pthread_mutex_lock(&exynos_camera->recording_mutex); + + if (exynos_camera->recording_listener == NULL) { + pthread_mutex_unlock(&exynos_camera->recording_mutex); + break; + } + + if (exynos_camera->recording_listener->busy) { + rc = exynos_camera_recording(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to record", __func__); + pthread_mutex_unlock(&exynos_camera->recording_mutex); + break; + } + } + + pthread_mutex_unlock(&exynos_camera->recording_mutex); + } + + exynos_camera->recording_thread_running = 0; + ALOGE("%s: Exiting thread", __func__); + + return NULL; +} + +int exynos_camera_recording_thread_start(struct exynos_camera *exynos_camera) +{ + struct exynos_camera_capture_listener *listener; + pthread_attr_t thread_attr; + camera_memory_t *memory = NULL; + int buffer_length; + int buffers_count; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exynos_camera->recording_thread_enabled) { + ALOGE("Recording thread was already started!"); + return -1; + } + + pthread_mutex_init(&exynos_camera->recording_mutex, NULL); + pthread_mutex_init(&exynos_camera->recording_lock_mutex, NULL); + + // Initial lock + pthread_mutex_lock(&exynos_camera->recording_lock_mutex); + + pthread_attr_init(&thread_attr); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + + exynos_camera->recording_thread_enabled = 1; + + rc = pthread_create(&exynos_camera->recording_thread, &thread_attr, exynos_camera_recording_thread, (void *) exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to create thread", __func__); + goto error; + } + + if (exynos_camera->recording_metadata) { + buffer_length = sizeof(struct exynos_camera_addrs); + buffers_count = EXYNOS_CAMERA_RECORDING_BUFFERS_COUNT; + + if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { + memory = exynos_camera->callbacks.request_memory(-1, buffer_length, buffers_count, exynos_camera->callbacks.user); + if (memory == NULL || memory->data == NULL || memory->data == MAP_FAILED) { + ALOGE("%s: Unable to request memory", __func__); + goto error; + } + } else { + ALOGE("%s: No memory request function!", __func__); + goto error; + } + + exynos_camera->recording_memory = memory; + exynos_camera->recording_buffer_length = buffer_length; + exynos_camera->recording_buffers_count = buffers_count; + } + + listener = exynos_camera_capture_listener_register(exynos_camera, exynos_camera->recording_width, exynos_camera->recording_height, exynos_camera->recording_format, exynos_camera_recording_callback); + if (listener == NULL) { + ALOGE("%s: Unable to register recording capture listener", __func__); + goto error; + } + + exynos_camera->recording_listener = listener; + + rc = 0; + goto complete; + +error: + if (memory != NULL && memory->release != NULL) { + memory->release(memory); + exynos_camera->recording_memory = NULL; + } + + pthread_mutex_destroy(&exynos_camera->recording_mutex); + pthread_mutex_destroy(&exynos_camera->recording_lock_mutex); + + rc = -1; + +complete: + return rc; +} + +void exynos_camera_recording_thread_stop(struct exynos_camera *exynos_camera) +{ + int i; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exynos_camera->recording_thread_enabled) { + ALOGE("Recording thread was already stopped!"); + return; + } + + if (exynos_camera->recording_listener != NULL) { + exynos_camera_capture_listener_unregister(exynos_camera, exynos_camera->recording_listener); + exynos_camera->recording_listener = NULL; + } + + exynos_camera->recording_thread_enabled = 0; + + pthread_mutex_unlock(&exynos_camera->recording_lock_mutex); + + // Wait for the thread to end + i = 0; + while (exynos_camera->recording_thread_running) { + if (i++ > 10000) { + ALOGE("Recording thread is taking too long to end, something is going wrong"); + break; + } + usleep(100); + } + + if (exynos_camera->recording_output_enabled) { + pthread_mutex_lock(&exynos_camera->recording_mutex); + exynos_camera_recording_output_stop(exynos_camera); + pthread_mutex_unlock(&exynos_camera->recording_mutex); + } + + pthread_mutex_destroy(&exynos_camera->recording_mutex); + pthread_mutex_destroy(&exynos_camera->recording_lock_mutex); +} + +// Auto-focus + +int exynos_camera_auto_focus(struct exynos_camera *exynos_camera, int auto_focus_status) +{ + if (exynos_camera == NULL) + return -EINVAL; + +// ALOGD("%s()", __func__); + + switch (auto_focus_status) { + case CAMERA_AF_STATUS_IN_PROGRESS: +/* + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS_MOVE) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) + exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS_MOVE, 1, 0, exynos_camera->callbacks.user); +*/ + break; + case CAMERA_AF_STATUS_SUCCESS: + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) + exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS, 1, 0, exynos_camera->callbacks.user); + break; + case CAMERA_AF_STATUS_FAIL: + default: + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) + exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS, 0, 0, exynos_camera->callbacks.user); + break; + } + + return 0; +} + +void *exynos_camera_auto_focus_thread(void *data) +{ + struct exynos_camera *exynos_camera; + int auto_focus_status = CAMERA_AF_STATUS_FAIL; + int auto_focus_completed = 0; + int rc; + + if (data == NULL) + return NULL; + + exynos_camera = (struct exynos_camera *) data; + + ALOGE("%s: Starting thread", __func__); + exynos_camera->auto_focus_thread_running = 1; + + while (exynos_camera->auto_focus_thread_enabled) { + pthread_mutex_lock(&exynos_camera->auto_focus_mutex); + + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT, &auto_focus_status); + if (rc < 0) { + ALOGE("%s: Unable to get auto-focus result", __func__); + auto_focus_status = CAMERA_AF_STATUS_FAIL; + } + + rc = exynos_camera_auto_focus(exynos_camera, auto_focus_status); + if (rc < 0) { + ALOGE("%s: Unable to auto-focus", __func__); + auto_focus_status = CAMERA_AF_STATUS_FAIL; + } + + if (auto_focus_status == CAMERA_AF_STATUS_IN_PROGRESS) + usleep(10000); + else + auto_focus_completed = 1; + + pthread_mutex_unlock(&exynos_camera->auto_focus_mutex); + + if (auto_focus_completed) { + exynos_camera->auto_focus_thread_running = 0; + exynos_camera_auto_focus_thread_stop(exynos_camera); + } + } + + exynos_camera->auto_focus_thread_running = 0; + ALOGE("%s: Exiting thread", __func__); + + return NULL; +} + +int exynos_camera_auto_focus_thread_start(struct exynos_camera *exynos_camera) +{ + pthread_attr_t thread_attr; + int auto_focus; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exynos_camera->auto_focus_thread_enabled) { + ALOGE("Auto-focus thread was already started!"); + return -1; + } + + pthread_mutex_init(&exynos_camera->auto_focus_mutex, NULL); + + auto_focus = AUTO_FOCUS_ON | (exynos_camera->preview_width & 0xfff) << 20 | (exynos_camera->preview_height & 0xfff) << 8; + + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SET_AUTO_FOCUS, auto_focus); + if (rc < 0) { + ALOGE("%s: Unable to set auto-focus on", __func__); + goto error; + } + + pthread_attr_init(&thread_attr); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + + exynos_camera->auto_focus_thread_enabled = 1; + + rc = pthread_create(&exynos_camera->auto_focus_thread, &thread_attr, exynos_camera_auto_focus_thread, (void *) exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to create thread", __func__); + goto error; + } + + rc = 0; + goto complete; + +error: + pthread_mutex_destroy(&exynos_camera->auto_focus_mutex); + + rc = -1; + +complete: + return rc; +} + +void exynos_camera_auto_focus_thread_stop(struct exynos_camera *exynos_camera) +{ + int rc; + int i; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exynos_camera->auto_focus_thread_enabled) { + ALOGE("Auto-focus thread was already stopped!"); + return; + } + + exynos_camera->auto_focus_thread_enabled = 0; + + // Wait for the thread to end + i = 0; + while (exynos_camera->auto_focus_thread_running) { + if (i++ > 10000) { + ALOGE("Auto-focus thread is taking too long to end, something is going wrong"); + break; + } + usleep(100); + } + + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF); + if (rc < 0) + ALOGE("%s: Unable to set auto-focus off", __func__); + + pthread_mutex_destroy(&exynos_camera->auto_focus_mutex); +} + +/* + * Exynos Camera OPS + */ + +int exynos_camera_set_preview_window(struct camera_device *dev, + struct preview_stream_ops *w) +{ + struct exynos_camera *exynos_camera; + + int width, height, format, gralloc_format; + + buffer_handle_t *buffer; + int stride; + void *addr = NULL; + + int rc; + + ALOGD("%s(%p, %p)", __func__, dev, w); + + if (dev == NULL || dev->priv == NULL) + return -EINVAL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + if (exynos_camera->preview_thread_enabled) + pthread_mutex_lock(&exynos_camera->preview_mutex); + + if (w == NULL) { + exynos_camera->preview_window = NULL; + return 0; + } + + if (w->set_buffer_count == NULL || w->set_usage == NULL || w->set_buffers_geometry == NULL) + goto error; + + rc = w->set_buffer_count(w, EXYNOS_CAMERA_GRALLOC_BUFFERS_COUNT); + if (rc) { + ALOGE("%s: Unable to set buffer count: %d", __func__, EXYNOS_CAMERA_GRALLOC_BUFFERS_COUNT); + goto error; + } + + rc = w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN); + if (rc) { + ALOGE("%s: Unable to set usage", __func__); + goto error; + } + + width = exynos_camera->preview_width; + height = exynos_camera->preview_height; + format = exynos_camera->preview_format; + + switch (format) { + case V4L2_PIX_FMT_NV21: + gralloc_format = HAL_PIXEL_FORMAT_YCrCb_420_SP; + break; + case V4L2_PIX_FMT_YUV420: + gralloc_format = HAL_PIXEL_FORMAT_YV12; + break; + case V4L2_PIX_FMT_RGB565: + gralloc_format = HAL_PIXEL_FORMAT_RGB_565; + break; + case V4L2_PIX_FMT_RGB32: + gralloc_format = HAL_PIXEL_FORMAT_RGBX_8888; + break; + default: + gralloc_format = HAL_PIXEL_FORMAT_YCrCb_420_SP; + break; + } + + rc = w->set_buffers_geometry(w, width, height, gralloc_format); + if (rc) { + ALOGE("%s: Unable to set buffers geometry", __func__); + goto error; + } + + exynos_camera->preview_window = w; + + rc = 0; + goto complete; + +error: + exynos_camera->preview_window = NULL; + rc = -1; + +complete: + if (exynos_camera->preview_thread_enabled) + pthread_mutex_unlock(&exynos_camera->preview_mutex); + + return rc; +} + +void exynos_camera_set_callbacks(struct camera_device *dev, + camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p, %p)", __func__, dev, user); + + if (dev == NULL || dev->priv == NULL) + return; + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera->callbacks.notify = notify_cb; + exynos_camera->callbacks.data = data_cb; + exynos_camera->callbacks.data_timestamp = data_cb_timestamp; + exynos_camera->callbacks.request_memory = get_memory; + exynos_camera->callbacks.user = user; +} + +void exynos_camera_enable_msg_type(struct camera_device *dev, int32_t msg_type) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p, %d)", __func__, dev, msg_type); + + if (dev == NULL || dev->priv == NULL) + return; + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera->messages_enabled |= msg_type; +} + +void exynos_camera_disable_msg_type(struct camera_device *dev, int32_t msg_type) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p, %d)", __func__, dev, msg_type); + + if (dev == NULL || dev->priv == NULL) + return; + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera->messages_enabled &= ~msg_type; +} + +int exynos_camera_msg_type_enabled(struct camera_device *dev, int32_t msg_type) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p, %d)", __func__, dev, msg_type); + + if (dev == NULL || dev->priv == NULL) + return -EINVAL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + return exynos_camera->messages_enabled & msg_type; +} + +int exynos_camera_start_preview(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + int rc; + + ALOGD("%s(%p)", __func__, dev); + + if (dev == NULL || dev->priv == NULL) + return -EINVAL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera->callback_lock = 1; + rc = exynos_camera_preview_thread_start(exynos_camera); + exynos_camera->callback_lock = 0; + + return rc; +} + +void exynos_camera_stop_preview(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p)", __func__, dev); + + if (dev == NULL || dev->priv == NULL) + return; + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera->callback_lock = 1; + exynos_camera_preview_thread_stop(exynos_camera); + exynos_camera->callback_lock = 0; +} + +int exynos_camera_preview_enabled(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p)", __func__, dev); + + if (dev == NULL || dev->priv == NULL) + return -EINVAL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + return exynos_camera->preview_thread_enabled; +} + +int exynos_camera_store_meta_data_in_buffers(struct camera_device *dev, + int enable) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p, %d)", __func__, dev, enable); + + if (dev == NULL || dev->priv == NULL) + return -EINVAL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + if (!exynos_camera->recording_thread_enabled) + exynos_camera->recording_metadata = enable; + else + ALOGE("%s: Recording is running!", __func__); + + return 0; +} + +int exynos_camera_start_recording(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + int rc; + + ALOGD("%s(%p)", __func__, dev); + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera->callback_lock = 1; + rc = exynos_camera_recording_thread_start(exynos_camera); + exynos_camera->callback_lock = 0; + + return rc; +} + +void exynos_camera_stop_recording(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p)", __func__, dev); + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera->callback_lock = 1; + exynos_camera_recording_thread_stop(exynos_camera); + exynos_camera->callback_lock = 0; +} + +int exynos_camera_recording_enabled(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p)", __func__, dev); + + if (dev == NULL || dev->priv == NULL) + return -EINVAL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + return exynos_camera->recording_thread_enabled; +} + +void exynos_camera_release_recording_frame(struct camera_device *dev, + const void *opaque) +{ + struct exynos_camera *exynos_camera; + +// ALOGD("%s(%p, %p)", __func__, dev, opaque); + + if (dev == NULL || dev->priv == NULL) + return; + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera_recording_frame_release(exynos_camera); +} + +int exynos_camera_start_auto_focus(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p)", __func__, dev); + + if (dev == NULL || dev->priv == NULL) + return -EINVAL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + return exynos_camera_auto_focus_thread_start(exynos_camera); +} + +int exynos_camera_cancel_auto_focus(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p)", __func__, dev); + + if (dev == NULL || dev->priv == NULL) + return -EINVAL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera_auto_focus_thread_stop(exynos_camera); + + return 0; +} + +int exynos_camera_take_picture(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + int rc; + + ALOGD("%s(%p)", __func__, dev); + + if (dev == NULL || dev->priv == NULL) + return -EINVAL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera->callback_lock = 1; + rc = exynos_camera_picture_thread_start(exynos_camera); + exynos_camera->callback_lock = 0; + + return rc; +} + +int exynos_camera_cancel_picture(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + int rc; + + ALOGD("%s(%p)", __func__, dev); + + if (dev == NULL || dev->priv == NULL) + return -EINVAL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera->callback_lock = 1; + exynos_camera_picture_thread_stop(exynos_camera); + exynos_camera->callback_lock = 0; + + return 0; +} + +int exynos_camera_set_parameters(struct camera_device *dev, + const char *params) +{ + struct exynos_camera *exynos_camera; + int rc; + + ALOGD("%s(%p, %s)", __func__, dev, params); + + if (dev == NULL || dev->priv == NULL || params == NULL) + return -EINVAL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + rc = exynos_params_string_set(exynos_camera, (char *) params); + if (rc < 0) { + ALOGE("%s: Unable to set params string", __func__); + return -1; + } + + rc = exynos_camera_params_apply(exynos_camera, 0); + if (rc < 0) { + ALOGE("%s: Unable to apply params", __func__); + return -1; + } + + return 0; +} + +char *exynos_camera_get_parameters(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + char *params; + + ALOGD("%s(%p)", __func__, dev); + + if (dev == NULL || dev->priv == NULL) + return NULL; + + exynos_camera = (struct exynos_camera *) dev->priv; + + params = exynos_params_string_get(exynos_camera); + if (params == NULL) { + ALOGE("%s: Couldn't find any param", __func__); + return strdup(""); + } + + return params; +} + +void exynos_camera_put_parameters(struct camera_device *dev, char *params) +{ + ALOGD("%s(%p)", __func__, dev); + + if (params != NULL) + free(params); +} + +int exynos_camera_send_command(struct camera_device *dev, + int32_t cmd, int32_t arg1, int32_t arg2) +{ + ALOGD("%s(%p, %d, %d, %d)", __func__, dev, cmd, arg1, arg2); + + return 0; +} + +void exynos_camera_release(struct camera_device *dev) +{ + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p)", __func__, dev); + + if (dev == NULL || dev->priv == NULL) + return; + + exynos_camera = (struct exynos_camera *) dev->priv; + + exynos_camera_capture_thread_stop(exynos_camera); + + exynos_camera_stop(exynos_camera); +} + +int exynos_camera_dump(struct camera_device *dev, int fd) +{ + ALOGD("%s(%p, %d)", __func__, dev, fd); + + return 0; +} + +/* + * Interface + */ + +struct camera_device_ops exynos_camera_ops = { + .set_preview_window = exynos_camera_set_preview_window, + .set_callbacks = exynos_camera_set_callbacks, + .enable_msg_type = exynos_camera_enable_msg_type, + .disable_msg_type = exynos_camera_disable_msg_type, + .msg_type_enabled = exynos_camera_msg_type_enabled, + .start_preview = exynos_camera_start_preview, + .stop_preview = exynos_camera_stop_preview, + .preview_enabled = exynos_camera_preview_enabled, + .store_meta_data_in_buffers = exynos_camera_store_meta_data_in_buffers, + .start_recording = exynos_camera_start_recording, + .stop_recording = exynos_camera_stop_recording, + .recording_enabled = exynos_camera_recording_enabled, + .release_recording_frame = exynos_camera_release_recording_frame, + .auto_focus = exynos_camera_start_auto_focus, + .cancel_auto_focus = exynos_camera_cancel_auto_focus, + .take_picture = exynos_camera_take_picture, + .cancel_picture = exynos_camera_cancel_picture, + .set_parameters = exynos_camera_set_parameters, + .get_parameters = exynos_camera_get_parameters, + .put_parameters = exynos_camera_put_parameters, + .send_command = exynos_camera_send_command, + .release = exynos_camera_release, + .dump = exynos_camera_dump, +}; + +int exynos_camera_close(hw_device_t *device) +{ + struct camera_device *camera_device; + struct exynos_camera *exynos_camera; + + ALOGD("%s(%p)", __func__, device); + + if (device == NULL) + return -EINVAL; + + camera_device = (struct camera_device *) device; + + if (camera_device->priv != NULL) { + free(camera_device->priv); + } + + free(camera_device); + + return 0; +} + +int exynos_camera_open(const struct hw_module_t* module, const char *camera_id, + struct hw_device_t** device) +{ + struct camera_device *camera_device = NULL; + struct exynos_camera *exynos_camera = NULL; + int id; + int rc; + + ALOGD("%s(%p, %s, %p)", __func__, module, camera_id, device); + + if (module == NULL || camera_id == NULL || device == NULL) + return -EINVAL; + + id = atoi(camera_id); + if (id < 0) + return -EINVAL; + + exynos_camera = calloc(1, sizeof(struct exynos_camera)); + exynos_camera->config = exynos_camera_config; + + if (exynos_camera->config->v4l2_nodes_count > EXYNOS_CAMERA_MAX_V4L2_NODES_COUNT) + goto error_preset; + + if (id >= exynos_camera->config->presets_count) + goto error_preset; + + rc = exynos_camera_start(exynos_camera, id); + if (rc < 0) { + ALOGE("%s: Unable to start camera", __func__); + goto error; + } + + rc = exynos_camera_capture_thread_start(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to start capture thread", __func__); + goto error; + } + + camera_device = calloc(1, sizeof(struct camera_device)); + camera_device->common.tag = HARDWARE_DEVICE_TAG; + camera_device->common.version = 0; + camera_device->common.module = (struct hw_module_t *) module; + camera_device->common.close = exynos_camera_close; + + camera_device->ops = &exynos_camera_ops; + camera_device->priv = exynos_camera; + + *device = (struct hw_device_t *) &(camera_device->common); + + return 0; + +error: + exynos_camera_stop(exynos_camera); + +error_device: + if (camera_device != NULL) + free(camera_device); + +error_preset: + if (exynos_camera != NULL) + free(exynos_camera); + + return -1; +} + +int exynos_camera_get_number_of_cameras(void) +{ + ALOGD("%s()", __func__); + + if (exynos_camera_config == NULL || exynos_camera_config->presets == NULL) { + ALOGE("%s: Unable to find proper camera config", __func__); + return -1; + } + + return exynos_camera_config->presets_count; +} + +int exynos_camera_get_camera_info(int id, struct camera_info *info) +{ + ALOGD("%s(%d, %p)", __func__, id, info); + + if (id < 0 || info == NULL) + return -EINVAL; + + if (exynos_camera_config == NULL || exynos_camera_config->presets == NULL) { + ALOGE("%s: Unable to find proper camera config", __func__); + return -1; + } + + if (id >= exynos_camera_config->presets_count) + return -EINVAL; + + ALOGD("Selected camera: %s", exynos_camera_config->presets[id].name); + + info->facing = exynos_camera_config->presets[id].facing; + info->orientation = exynos_camera_config->presets[id].orientation; + + return 0; +} + +struct hw_module_methods_t exynos_camera_module_methods = { + .open = exynos_camera_open, +}; + +struct camera_module HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .module_api_version = CAMERA_MODULE_API_VERSION_1_0, + .id = CAMERA_HARDWARE_MODULE_ID, + .name = "Exynos Camera", + .author = "Paul Kocialkowski", + .methods = &exynos_camera_module_methods, + }, + .get_number_of_cameras = exynos_camera_get_number_of_cameras, + .get_camera_info = exynos_camera_get_camera_info, +}; diff --git a/camera/exynos_camera.h b/camera/exynos_camera.h new file mode 100644 index 0000000..9db8dfb --- /dev/null +++ b/camera/exynos_camera.h @@ -0,0 +1,679 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski + * + * 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 3 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, see . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#ifdef EXYNOS_JPEG_HW +#include +#endif +#include + +#include +#include + +#ifndef _EXYNOS_CAMERA_H_ +#define _EXYNOS_CAMERA_H_ + +#define EXYNOS_CAMERA_MAX_V4L2_NODES_COUNT 4 + +#define EXYNOS_CAMERA_CAPTURE_BUFFERS_COUNT 6 +#define EXYNOS_CAMERA_PREVIEW_BUFFERS_COUNT 6 +#define EXYNOS_CAMERA_RECORDING_BUFFERS_COUNT 6 +#define EXYNOS_CAMERA_GRALLOC_BUFFERS_COUNT 3 + +#define EXYNOS_CAMERA_PICTURE_OUTPUT_FORMAT V4L2_PIX_FMT_YUYV + +#define EXYNOS_CAMERA_MSG_ENABLED(msg) (exynos_camera->messages_enabled & msg) +#define EXYNOS_CAMERA_CALLBACK_DEFINED(cb) (exynos_camera->callbacks.cb != NULL) + +#define EXYNOS_CAMERA_ALIGN(value) ((value + (0x10000 - 1)) & ~(0x10000 - 1)) + +/* + * Structures + */ + +struct exynos_camera; + +struct list_head { + struct list_head *next; + struct list_head *prev; +}; + +enum exynos_param_type { + EXYNOS_PARAM_INT, + EXYNOS_PARAM_FLOAT, + EXYNOS_PARAM_STRING, +}; + +union exynos_param_data { + int integer; + float floating; + char *string; +}; + +struct exynos_param { + struct list_head list; + + char *key; + union exynos_param_data data; + enum exynos_param_type type; +}; + +struct exynos_camera_buffer { + void *pointer; + int address; + int length; + + int width; + int height; + int format; +}; + +struct exynos_camera_capture_listener { + struct list_head list; + + int width; + int height; + int format; + + int (*callback)(struct exynos_camera *exynos_camera, struct exynos_camera_buffer *buffers, int buffers_count); + int busy; +}; + +struct exynos_camera_mbus_resolution { + int width; + int height; + int mbus_width; + int mbus_height; +}; + +struct exynos_camera_params { + char *preview_size_values; + char *preview_size; + char *preview_format_values; + char *preview_format; + char *preview_frame_rate_values; + int preview_frame_rate; + char *preview_fps_range_values; + char *preview_fps_range; + + char *picture_size_values; + char *picture_size; + char *picture_format_values; + char *picture_format; + char *jpeg_thumbnail_size_values; + int jpeg_thumbnail_width; + int jpeg_thumbnail_height; + int jpeg_thumbnail_quality; + int jpeg_quality; + + int video_snapshot_supported; + int full_video_snap_supported; + + char *recording_size; + char *recording_size_values; + char *recording_format; + + char *focus_mode; + char *focus_mode_values; + char *focus_distances; + char *focus_areas; + int max_num_focus_areas; + + int zoom_supported; + int smooth_zoom_supported; + char *zoom_ratios; + int zoom; + int max_zoom; + + char *flash_mode; + char *flash_mode_values; + + int exposure_compensation; + float exposure_compensation_step; + int min_exposure_compensation; + int max_exposure_compensation; + + char *whitebalance; + char *whitebalance_values; + + char *antibanding; + char *antibanding_values; + + char *scene_mode; + char *scene_mode_values; + + char *effect; + char *effect_values; + + char *iso; + char *iso_values; +}; + +struct exynos_camera_preset { + char *name; + int facing; + int orientation; + + int rotation; + int hflip; + int vflip; + + int capture_format; + int picture_format; + int fimc_is; + + float focal_length; + float horizontal_view_angle; + float vertical_view_angle; + + int metering; + + struct exynos_camera_params params; + struct exynos_camera_mbus_resolution *mbus_resolutions; + int mbus_resolutions_count; +}; + +struct exynos_v4l2_node { + int id; + char *node; +}; + +struct exynos_v4l2_output { + int enabled; + + int v4l2_id; + + int width; + int height; + int format; + + int buffer_width; + int buffer_height; + int buffer_format; + + camera_memory_t *memory; + int memory_address; +#ifdef EXYNOS_ION + int memory_ion_fd; +#endif + int memory_index; + int buffers_count; + int buffer_length; +}; + +struct exynos_exif { + int enabled; + + exif_attribute_t attributes; + void *jpeg_thumbnail_data; + int jpeg_thumbnail_size; + + camera_memory_t *memory; + int memory_size; +}; + +#ifdef EXYNOS_JPEG_HW +struct exynos_jpeg { + int enabled; + + int fd; + struct jpeg_buf buffer_in; + struct jpeg_buf buffer_out; + camera_memory_t *memory_in; + void *memory_in_pointer; +#ifdef EXYNOS_ION + int memory_in_ion_fd; +#endif + camera_memory_t *memory_out; + void *memory_out_pointer; + int memory_out_size; +#ifdef EXYNOS_ION + int memory_out_ion_fd; +#endif + + int width; + int height; + int format; + + int quality; +}; +#endif + +struct exynox_camera_config { + struct exynos_camera_preset *presets; + int presets_count; + + struct exynos_v4l2_node *v4l2_nodes; + int v4l2_nodes_count; +}; + +struct exynos_camera_callbacks { + camera_notify_callback notify; + camera_data_callback data; + camera_data_timestamp_callback data_timestamp; + camera_request_memory request_memory; + void *user; +}; + +struct exynos_camera { + int v4l2_fds[EXYNOS_CAMERA_MAX_V4L2_NODES_COUNT]; + int ion_fd; + + struct exynox_camera_config *config; + struct exynos_param *params; + + struct exynos_camera_callbacks callbacks; + int callback_lock; + int messages_enabled; + + gralloc_module_t *gralloc; + + // Capture + + pthread_t capture_thread; + pthread_mutex_t capture_mutex; + pthread_mutex_t capture_lock_mutex; + int capture_thread_running; + int capture_thread_enabled; + + int capture_enabled; + struct exynos_camera_capture_listener *capture_listeners; + camera_memory_t *capture_memory; + int capture_memory_address; + int capture_memory_index; + void *capture_yuv_buffer; + void *capture_jpeg_buffer; + int capture_auto_focus_result; + int capture_hybrid; + int capture_width; + int capture_height; + int capture_format; + int capture_buffers_count; + int capture_buffer_length; + + // Preview + + pthread_t preview_thread; + pthread_mutex_t preview_mutex; + pthread_mutex_t preview_lock_mutex; + int preview_thread_running; + int preview_thread_enabled; + + int preview_output_enabled; + struct exynos_camera_capture_listener *preview_listener; + struct preview_stream_ops *preview_window; + struct exynos_camera_buffer preview_buffer; + struct exynos_v4l2_output preview_output; + + // Picture + + pthread_t picture_thread; + pthread_mutex_t picture_mutex; + pthread_mutex_t picture_lock_mutex; + int picture_thread_running; + int picture_thread_enabled; + + int picture_enabled; + int picture_completed; + struct exynos_camera_capture_listener *picture_listener; + camera_memory_t *picture_memory; + struct exynos_camera_buffer picture_jpeg_buffer; + struct exynos_camera_buffer picture_jpeg_thumbnail_buffer; + struct exynos_camera_buffer picture_yuv_buffer; + struct exynos_camera_buffer picture_yuv_thumbnail_buffer; + + // Recording + + pthread_t recording_thread; + pthread_mutex_t recording_mutex; + pthread_mutex_t recording_lock_mutex; + int recording_thread_running; + int recording_thread_enabled; + + int recording_output_enabled; + struct exynos_camera_capture_listener *recording_listener; + camera_memory_t *recording_memory; + int recording_memory_index; + struct exynos_camera_buffer recording_buffer; + struct exynos_v4l2_output recording_output; + int recording_buffers_count; + int recording_buffer_length; + int recording_metadata; + + // Auto-focus + + pthread_t auto_focus_thread; + pthread_mutex_t auto_focus_mutex; + int auto_focus_thread_enabled; + int auto_focus_thread_running; + + // Camera params + + int camera_rotation; + int camera_hflip; + int camera_vflip; + int camera_capture_format; + int camera_picture_format; + int camera_fimc_is; + int camera_focal_length; + int camera_metering; + + struct exynos_camera_mbus_resolution *camera_mbus_resolutions; + int camera_mbus_resolutions_count; + + int camera_sensor_mode; + int fimc_is_mode; + + // Params + + int preview_width; + int preview_height; + int preview_format; + int preview_fps; + int picture_width; + int picture_height; + int picture_format; + int jpeg_thumbnail_width; + int jpeg_thumbnail_height; + int jpeg_thumbnail_quality; + int jpeg_quality; + int recording_width; + int recording_height; + int recording_format; + int focus_mode; + int focus_x; + int focus_y; + int zoom; + int flash_mode; + int exposure_compensation; + int whitebalance; + int antibanding; + int scene_mode; + int effect; + int iso; + int metering; +}; + +struct exynos_camera_addrs { + unsigned int type; + unsigned int y; + unsigned int cbcr; + unsigned int index; + unsigned int reserved; +}; + +// This is because the linux header uses anonymous union +struct exynos_v4l2_ext_control { + __u32 id; + __u32 size; + __u32 reserved2[1]; + union { + __s32 value; + __s64 value64; + char *string; + } data; +} __attribute__ ((packed)); + +/* + * Camera + */ + +// Camera +int exynos_camera_start(struct exynos_camera *exynos_camera, int id); +void exynos_camera_stop(struct exynos_camera *exynos_camera); + +// Params +int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id); +int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force); + +// Capture +int exynos_camera_capture(struct exynos_camera *exynos_camera); +int exynos_camera_capture_thread_start(struct exynos_camera *exynos_camera); +void exynos_camera_capture_thread_stop(struct exynos_camera *exynos_camera); +int exynos_camera_capture_start(struct exynos_camera *exynos_camera); +void exynos_camera_capture_stop(struct exynos_camera *exynos_camera); +int exynos_camera_capture_setup(struct exynos_camera *exynos_camera); +struct exynos_camera_capture_listener *exynos_camera_capture_listener_register( + struct exynos_camera *exynos_camera, int width, int height, int format, + int (*callback)(struct exynos_camera *exynos_camera, struct exynos_camera_buffer *buffers, int buffers_count)); +void exynos_camera_capture_listener_unregister( + struct exynos_camera *exynos_camera, + struct exynos_camera_capture_listener *listener); + +// Preview +int exynos_camera_preview_output_start(struct exynos_camera *exynos_camera); +void exynos_camera_preview_output_stop(struct exynos_camera *exynos_camera); +int exynos_camera_preview_callback(struct exynos_camera *exynos_camera, + struct exynos_camera_buffer *buffers, int buffers_count); +int exynos_camera_preview(struct exynos_camera *exynos_camera); +int exynos_camera_preview_thread_start(struct exynos_camera *exynos_camera); +void exynos_camera_preview_thread_stop(struct exynos_camera *exynos_camera); + +// Picture +int exynos_camera_picture_callback(struct exynos_camera *exynos_camera, + struct exynos_camera_buffer *buffers, int buffers_count); +int exynos_camera_picture(struct exynos_camera *exynos_camera); +int exynos_camera_picture_thread_start(struct exynos_camera *exynos_camera); +void exynos_camera_picture_thread_stop(struct exynos_camera *exynos_camera); + +// Recording +int exynos_camera_recording_output_start(struct exynos_camera *exynos_camera); +void exynos_camera_recording_output_stop(struct exynos_camera *exynos_camera); +int exynos_camera_recording_callback(struct exynos_camera *exynos_camera, + struct exynos_camera_buffer *buffers, int buffers_count); +void exynos_camera_recording_frame_release(struct exynos_camera *exynos_camera); +int exynos_camera_recording(struct exynos_camera *exynos_camera); +int exynos_camera_recording_thread_start(struct exynos_camera *exynos_camera); +void exynos_camera_recording_thread_stop(struct exynos_camera *exynos_camera); + +// Auto-focus +int exynos_camera_auto_focus(struct exynos_camera *exynos_camera, int auto_focus_status); +int exynos_camera_auto_focus_thread_start(struct exynos_camera *exynos_camera); +void exynos_camera_auto_focus_thread_stop(struct exynos_camera *exynos_camera); + +/* + * EXIF + */ + +int exynos_exif_start(struct exynos_camera *exynos_camera, struct exynos_exif *exif); +void exynos_exif_stop(struct exynos_camera *exynos_camera, + struct exynos_exif *exif); +int exynos_exif(struct exynos_camera *exynos_camera, struct exynos_exif *exif); + +/* + * ION + */ + +#ifdef EXYNOS_ION +int exynos_ion_init(struct exynos_camera *exynos_camera); +int exynos_ion_open(struct exynos_camera *exynos_camera); +void exynos_ion_close(struct exynos_camera *exynos_camera); +int exynos_ion_alloc(struct exynos_camera *exynos_camera, int size); +int exynos_ion_free(struct exynos_camera *exynos_camera, int fd); +int exynos_ion_phys(struct exynos_camera *exynos_camera, int fd); +int exynos_ion_msync(struct exynos_camera *exynos_camera, int fd, + int offset, int size); +#endif + +/* + * Jpeg + */ + +int exynos_jpeg_start(struct exynos_camera *exynos_camera, + struct exynos_jpeg *jpeg); +void exynos_jpeg_stop(struct exynos_camera *exynos_camera, + struct exynos_jpeg *jpeg); +int exynos_jpeg(struct exynos_camera *exynos_camera, struct exynos_jpeg *jpeg); + +/* + * Param + */ + +int exynos_param_int_get(struct exynos_camera *exynos_camera, + char *key); +float exynos_param_float_get(struct exynos_camera *exynos_camera, + char *key); +char *exynos_param_string_get(struct exynos_camera *exynos_camera, + char *key); +int exynos_param_int_set(struct exynos_camera *exynos_camera, + char *key, int integer); +int exynos_param_float_set(struct exynos_camera *exynos_camera, + char *key, float floating); +int exynos_param_string_set(struct exynos_camera *exynos_camera, + char *key, char *string); +char *exynos_params_string_get(struct exynos_camera *exynos_camera); +int exynos_params_string_set(struct exynos_camera *exynos_camera, char *string); + +/* + * Utils + */ + +int list_head_insert(struct list_head *list, struct list_head *prev, + struct list_head *next); +void list_head_remove(struct list_head *list); + +int exynos_camera_buffer_length(int width, int height, int format); +void exynos_camera_yuv_planes(int width, int height, int format, int address, int *address_y, int *address_cb, int *address_cr); + +/* + * V4L2 + */ + +int exynos_v4l2_init(struct exynos_camera *exynos_camera); +int exynos_v4l2_index(struct exynos_camera *exynos_camera, int exynos_v4l2_id); +int exynos_v4l2_fd(struct exynos_camera *exynos_camera, int exynos_v4l2_id); + +int exynos_v4l2_open(struct exynos_camera *exynos_camera, int exynos_v4l2_id); +void exynos_v4l2_close(struct exynos_camera *exynos_camera, int exynos_v4l2_id); +int exynos_v4l2_ioctl(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int request, void *data); +int exynos_v4l2_poll(struct exynos_camera *exynos_camera, int exynos_v4l2_id); +int exynos_v4l2_qbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int type, int memory, int index, unsigned long userptr); +int exynos_v4l2_qbuf_cap(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int index); +int exynos_v4l2_qbuf_out(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int index, unsigned long userptr); +int exynos_v4l2_dqbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int type, int memory); +int exynos_v4l2_dqbuf_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id); +int exynos_v4l2_dqbuf_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id); +int exynos_v4l2_reqbufs(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type, int memory, int count); +int exynos_v4l2_reqbufs_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int count); +int exynos_v4l2_reqbufs_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int count); +int exynos_v4l2_querybuf(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type, int memory, int index); +int exynos_v4l2_querybuf_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int index); +int exynos_v4l2_querybuf_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int index); +int exynos_v4l2_querycap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int flags); +int exynos_v4l2_querycap_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id); +int exynos_v4l2_querycap_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id); +int exynos_v4l2_streamon(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type); +int exynos_v4l2_streamon_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id); +int exynos_v4l2_streamon_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id); +int exynos_v4l2_streamoff(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type); +int exynos_v4l2_streamoff_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id); +int exynos_v4l2_streamoff_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id); +int exynos_v4l2_g_fmt(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int type, int *width, int *height, int *fmt); +int exynos_v4l2_g_fmt_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int *width, int *height, int *fmt); +int exynos_v4l2_g_fmt_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int *width, int *height, int *fmt); +int exynos_v4l2_s_fmt_pix(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type, int width, int height, int fmt, int field, + int priv); +int exynos_v4l2_s_fmt_pix_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int width, int height, int fmt, int priv); +int exynos_v4l2_s_fmt_pix_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int width, int height, int fmt, int priv); +int exynos_v4l2_s_fmt_win(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int left, int top, int width, int height); +int exynos_v4l2_enum_fmt(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type, int fmt); +int exynos_v4l2_enum_fmt_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int fmt); +int exynos_v4l2_enum_fmt_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int fmt); +int exynos_v4l2_enum_input(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int id); +int exynos_v4l2_s_input(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int id); +int exynos_v4l2_g_ext_ctrls(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, struct v4l2_ext_control *control, int count); +int exynos_v4l2_g_ctrl(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int id, int *value); +int exynos_v4l2_s_ctrl(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int id, int value); +int exynos_v4l2_s_parm(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int type, struct v4l2_streamparm *streamparm); +int exynos_v4l2_s_parm_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, struct v4l2_streamparm *streamparm); +int exynos_v4l2_s_parm_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, struct v4l2_streamparm *streamparm); +int exynos_v4l2_s_crop(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int type, int left, int top, int width, int height); +int exynos_v4l2_s_crop_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int left, int top, int width, int height); +int exynos_v4l2_s_crop_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int left, int top, int width, int height); +int exynos_v4l2_g_fbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + void **base, int *width, int *height, int *fmt); +int exynos_v4l2_s_fbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + void *base, int width, int height, int fmt); + +/* + * V4L2 Output + */ + +int exynos_v4l2_output_start(struct exynos_camera *exynos_camera, + struct exynos_v4l2_output *output); +void exynos_v4l2_output_stop(struct exynos_camera *exynos_camera, + struct exynos_v4l2_output *output); +int exynos_v4l2_output(struct exynos_camera *exynos_camera, + struct exynos_v4l2_output *output, int buffer_address); +int exynos_v4l2_output_release(struct exynos_camera *exynos_camera, + struct exynos_v4l2_output *output); + +#endif diff --git a/camera/exynos_exif.c b/camera/exynos_exif.c new file mode 100644 index 0000000..2ba4ca1 --- /dev/null +++ b/camera/exynos_exif.c @@ -0,0 +1,873 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski + * + * Based on crespo libcamera and exynos4 hal libcamera: + * Copyright 2008, The Android Open Source Project + * Copyright 2010, Samsung Electronics Co. LTD + * + * 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 3 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define LOG_TAG "exynos_camera" +#include +#include + +#include "exynos_camera.h" + +int exynos_exif_attributes_create_static(struct exynos_camera *exynos_camera, + struct exynos_exif *exif) +{ + exif_attribute_t *attributes; + unsigned char gps_version[] = { 0x02, 0x02, 0x00, 0x00 }; + char property[PROPERTY_VALUE_MAX]; + uint32_t av; + + if (exynos_camera == NULL || exif == NULL) + return -EINVAL; + + attributes = &exif->attributes; + + // Device + + property_get("ro.product.brand", property, EXIF_DEF_MAKER); + strncpy((char *) attributes->maker, property, + sizeof(attributes->maker) - 1); + attributes->maker[sizeof(attributes->maker) - 1] = '\0'; + + property_get("ro.product.model", property, EXIF_DEF_MODEL); + strncpy((char *) attributes->model, property, + sizeof(attributes->model) - 1); + attributes->model[sizeof(attributes->model) - 1] = '\0'; + + property_get("ro.build.id", property, EXIF_DEF_SOFTWARE); + strncpy((char *) attributes->software, property, + sizeof(attributes->software) - 1); + attributes->software[sizeof(attributes->software) - 1] = '\0'; + + attributes->ycbcr_positioning = EXIF_DEF_YCBCR_POSITIONING; + + attributes->fnumber.num = EXIF_DEF_FNUMBER_NUM; + attributes->fnumber.den = EXIF_DEF_FNUMBER_DEN; + + attributes->exposure_program = EXIF_DEF_EXPOSURE_PROGRAM; + + memcpy(attributes->exif_version, EXIF_DEF_EXIF_VERSION, + sizeof(attributes->exif_version)); + + av = APEX_FNUM_TO_APERTURE((double) attributes->fnumber.num / + attributes->fnumber.den); + attributes->aperture.num = av; + attributes->aperture.den = EXIF_DEF_APEX_DEN; + attributes->max_aperture.num = av; + attributes->max_aperture.den = EXIF_DEF_APEX_DEN; + + strcpy((char *) attributes->user_comment, EXIF_DEF_USERCOMMENTS); + attributes->color_space = EXIF_DEF_COLOR_SPACE; + attributes->exposure_mode = EXIF_DEF_EXPOSURE_MODE; + + // GPS version + + memcpy(attributes->gps_version_id, gps_version, sizeof(gps_version)); + + attributes->compression_scheme = EXIF_DEF_COMPRESSION; + attributes->x_resolution.num = EXIF_DEF_RESOLUTION_NUM; + attributes->x_resolution.den = EXIF_DEF_RESOLUTION_DEN; + attributes->y_resolution.num = EXIF_DEF_RESOLUTION_NUM; + attributes->y_resolution.den = EXIF_DEF_RESOLUTION_DEN; + attributes->resolution_unit = EXIF_DEF_RESOLUTION_UNIT; + + return 0; +} + +int exynos_exif_attributes_create_gps(struct exynos_camera *exynos_camera, + struct exynos_exif *exif) +{ + exif_attribute_t *attributes; + float gps_latitude_float, gps_longitude_float, gps_altitude_float; + int gps_timestamp_int; + char *gps_processing_method_string; + long gps_latitude, gps_longitude; + long gps_altitude, gps_timestamp; + double gps_latitude_abs, gps_longitude_abs, gps_altitude_abs; + + struct tm time_info; + + if (exynos_camera == NULL || exif == NULL) + return -EINVAL; + + attributes = &exif->attributes; + + gps_latitude_float = exynos_param_float_get(exynos_camera, "gps-latitude"); + gps_longitude_float = exynos_param_float_get(exynos_camera, "gps-longitude"); + gps_altitude_float = exynos_param_float_get(exynos_camera, "gps-altitude"); + if (gps_altitude_float == -1) + gps_altitude_float = (float) exynos_param_int_get(exynos_camera, "gps-altitude"); + gps_timestamp_int = exynos_param_int_get(exynos_camera, "gps-timestamp"); + gps_processing_method_string = exynos_param_string_get(exynos_camera, "gps-processing-method"); + + if (gps_latitude_float == -1 || gps_longitude_float == -1 || + gps_altitude_float == -1 || gps_timestamp_int <= 0 || + gps_processing_method_string == NULL) { + attributes->enableGps = false; + return 0; + } + + gps_latitude = (long) (gps_latitude_float * 10000000) / 1; + gps_longitude = (long) (gps_longitude_float * 10000000) / 1; + gps_altitude = (long) (gps_altitude_float * 100) / 1; + gps_timestamp = (long) gps_timestamp_int; + + if (gps_latitude == 0 || gps_longitude == 0) { + attributes->enableGps = false; + return 0; + } + + if (gps_latitude > 0) + strcpy((char *) attributes->gps_latitude_ref, "N"); + else + strcpy((char *) attributes->gps_latitude_ref, "S"); + + if (gps_longitude > 0) + strcpy((char *) attributes->gps_longitude_ref, "E"); + else + strcpy((char *) attributes->gps_longitude_ref, "W"); + + if (gps_altitude > 0) + attributes->gps_altitude_ref = 0; + else + attributes->gps_altitude_ref = 1; + + + gps_latitude_abs = fabs(gps_latitude); + gps_longitude_abs = fabs(gps_longitude); + gps_altitude_abs = fabs(gps_altitude); + + attributes->gps_latitude[0].num = (uint32_t) gps_latitude_abs; + attributes->gps_latitude[0].den = 10000000; + attributes->gps_latitude[1].num = 0; + attributes->gps_latitude[1].den = 1; + attributes->gps_latitude[2].num = 0; + attributes->gps_latitude[2].den = 1; + + attributes->gps_longitude[0].num = (uint32_t) gps_longitude_abs; + attributes->gps_longitude[0].den = 10000000; + attributes->gps_longitude[1].num = 0; + attributes->gps_longitude[1].den = 1; + attributes->gps_longitude[2].num = 0; + attributes->gps_longitude[2].den = 1; + + attributes->gps_altitude.num = (uint32_t) gps_altitude_abs; + attributes->gps_altitude.den = 100; + + gmtime_r(&gps_timestamp, &time_info); + + attributes->gps_timestamp[0].num = time_info.tm_hour; + attributes->gps_timestamp[0].den = 1; + attributes->gps_timestamp[1].num = time_info.tm_min; + attributes->gps_timestamp[1].den = 1; + attributes->gps_timestamp[2].num = time_info.tm_sec; + attributes->gps_timestamp[2].den = 1; + snprintf((char *) attributes->gps_datestamp, sizeof(attributes->gps_datestamp), + "%04d:%02d:%02d", time_info.tm_year + 1900, time_info.tm_mon + 1, time_info.tm_mday); + + attributes->enableGps = true; + + return 0; +} + +int exynos_exif_attributes_create_params(struct exynos_camera *exynos_camera, + struct exynos_exif *exif) +{ + exif_attribute_t *attributes; + uint32_t av, tv, bv, sv, ev; + time_t time_data; + struct tm *time_info; + int rotation; + int shutter_speed; + int exposure_time; + int iso_speed; + int exposure; + int flash_results; + + int rc; + + if (exynos_camera == NULL || exif == NULL) + return -EINVAL; + + attributes = &exif->attributes; + + // Picture size + + attributes->width = exynos_camera->picture_width; + attributes->height = exynos_camera->picture_height; + + // Thumbnail + + attributes->widthThumb = exynos_camera->jpeg_thumbnail_width; + attributes->heightThumb = exynos_camera->jpeg_thumbnail_height; + attributes->enableThumb = true; + + // Orientation + + rotation = exynos_param_int_get(exynos_camera, "rotation"); + switch (rotation) { + case 90: + attributes->orientation = EXIF_ORIENTATION_90; + break; + case 180: + attributes->orientation = EXIF_ORIENTATION_180; + break; + case 270: + attributes->orientation = EXIF_ORIENTATION_270; + break; + case 0: + default: + attributes->orientation = EXIF_ORIENTATION_UP; + break; + } + + // Time + + time(&time_data); + time_info = localtime(&time_data); + strftime((char *) attributes->date_time, sizeof(attributes->date_time), + "%Y:%m:%d %H:%M:%S", time_info); + + attributes->focal_length.num = exynos_camera->camera_focal_length; + attributes->focal_length.den = EXIF_DEF_FOCAL_LEN_DEN; + + shutter_speed = 100; + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_TV, + &shutter_speed); + if (rc < 0) + ALOGE("%s: Unable to get shutter speed", __func__); + + attributes->shutter_speed.num = shutter_speed; + attributes->shutter_speed.den = 100; + + attributes->exposure_time.num = 1; + attributes->exposure_time.den = APEX_SHUTTER_TO_EXPOSURE(shutter_speed); + + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_ISO, + &iso_speed); + if (rc < 0) + ALOGE("%s: Unable to get iso", __func__); + + attributes->iso_speed_rating = iso_speed; + + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_FLASH, + &flash_results); + if (rc < 0) + ALOGE("%s: Unable to get flash", __func__); + + attributes->flash = flash_results; + + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_BV, + (int *) &bv); + if (rc < 0) { + ALOGE("%s: Unable to get bv", __func__); + goto bv_static; + } + + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_EBV, + (int *) &ev); + if (rc < 0) { + ALOGE("%s: Unable to get ebv", __func__); + goto bv_static; + } + + goto bv_ioctl; + +bv_static: + exposure = exynos_param_int_get(exynos_camera, "exposure-compensation"); + if (exposure < 0) + exposure = EV_DEFAULT; + + av = APEX_FNUM_TO_APERTURE((double) attributes->fnumber.num / + attributes->fnumber.den); + tv = APEX_EXPOSURE_TO_SHUTTER((double) attributes->exposure_time.num / + attributes->exposure_time.den); + sv = APEX_ISO_TO_FILMSENSITIVITY(iso_speed); + bv = av + tv - sv; + ev = exposure - EV_DEFAULT; + +bv_ioctl: + attributes->brightness.num = bv; + attributes->brightness.den = EXIF_DEF_APEX_DEN; + + if (exynos_camera->scene_mode == SCENE_MODE_BEACH_SNOW) { + attributes->exposure_bias.num = EXIF_DEF_APEX_DEN; + attributes->exposure_bias.den = EXIF_DEF_APEX_DEN; + } else { + attributes->exposure_bias.num = ev * EXIF_DEF_APEX_DEN; + attributes->exposure_bias.den = EXIF_DEF_APEX_DEN; + } + + switch (exynos_camera->camera_metering) { + case METERING_CENTER: + attributes->metering_mode = EXIF_METERING_CENTER; + break; + case METERING_MATRIX: + attributes->metering_mode = EXIF_METERING_AVERAGE; + break; + case METERING_SPOT: + attributes->metering_mode = EXIF_METERING_SPOT; + break; + default: + attributes->metering_mode = EXIF_METERING_AVERAGE; + break; + } + + if (exynos_camera->whitebalance == WHITE_BALANCE_AUTO || + exynos_camera->whitebalance == WHITE_BALANCE_BASE) + attributes->white_balance = EXIF_WB_AUTO; + else + attributes->white_balance = EXIF_WB_MANUAL; + + switch (exynos_camera->scene_mode) { + case SCENE_MODE_PORTRAIT: + attributes->scene_capture_type = EXIF_SCENE_PORTRAIT; + break; + case SCENE_MODE_LANDSCAPE: + attributes->scene_capture_type = EXIF_SCENE_LANDSCAPE; + break; + case SCENE_MODE_NIGHTSHOT: + attributes->scene_capture_type = EXIF_SCENE_NIGHT; + break; + default: + attributes->scene_capture_type = EXIF_SCENE_STANDARD; + break; + } + + rc = exynos_exif_attributes_create_gps(exynos_camera, exif); + if (rc < 0) { + ALOGE("%s: Unable to create GPS attributes", __func__); + return -1; + } + + return 0; +} + +int exynos_exif_write_data(void *exif_data, unsigned short tag, + unsigned short type, unsigned int count, unsigned int *offset, void *start, + void *data, int length) +{ + unsigned char *pointer; + int size; + + if (exif_data == NULL || data == NULL || length <= 0) + return -EINVAL; + + pointer = (unsigned char *) exif_data; + + memcpy(pointer, &tag, sizeof(tag)); + pointer += sizeof(tag); + + memcpy(pointer, &type, sizeof(type)); + pointer += sizeof(type); + + memcpy(pointer, &count, sizeof(count)); + pointer += sizeof(count); + + if (offset != NULL && start != NULL) { + memcpy(pointer, offset, sizeof(*offset)); + pointer += sizeof(*offset); + + memcpy((void *) ((int) start + *offset), data, count * length); + *offset += count * length; + } else { + memcpy(pointer, data, count * length); + pointer += 4; + } + + size = (int) pointer - (int) exif_data; + return size; +} + +int exynos_exif_start(struct exynos_camera *exynos_camera, struct exynos_exif *exif) +{ + int rc; + + if (exynos_camera == NULL || exif == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exif->enabled) { + ALOGE("Exif was already started"); + return -1; + } + + rc = exynos_exif_attributes_create_static(exynos_camera, exif); + if (rc < 0) { + ALOGE("%s: Unable to create exif attributes", __func__); + goto error; + } + + rc = exynos_exif_attributes_create_params(exynos_camera, exif); + if (rc < 0) { + ALOGE("%s: Unable to create exif parameters", __func__); + goto error; + } + + exif->enabled = 1; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +void exynos_exif_stop(struct exynos_camera *exynos_camera, + struct exynos_exif *exif) +{ + if (exynos_camera == NULL || exif == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exif->enabled) { + ALOGE("Exif was already stopped"); + return; + } + + if (exif->memory != NULL && exif->memory->release != NULL) { + exif->memory->release(exif->memory); + exif->memory = NULL; + } + + exif->enabled = 0; +} + +int exynos_exif(struct exynos_camera *exynos_camera, struct exynos_exif *exif) +{ + // Markers + unsigned char exif_app1_marker[] = { 0xff, 0xe1 }; + unsigned char exif_app1_size[] = { 0x00, 0x00 }; + unsigned char exif_marker[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; + unsigned char tiff_marker[] = { 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00 }; + + unsigned char user_comment_code[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; + unsigned char exif_ascii_prefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; + + void *jpeg_thumbnail_data; + int jpeg_thumbnail_size; + camera_memory_t *memory = NULL; + int memory_size; + exif_attribute_t *attributes; + void *exif_ifd_data_start = NULL; + void *exif_ifd_start = NULL; + void *exif_ifd_gps = NULL; + void *exif_ifd_thumb = NULL; + unsigned char *pointer; + unsigned int offset; + unsigned int value; + void *data; + int count; + int rc; + + if (exynos_camera == NULL || exif == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (!exif->enabled) { + ALOGE("Exif was not started"); + return -1; + } + + jpeg_thumbnail_data = exif->jpeg_thumbnail_data; + jpeg_thumbnail_size = exif->jpeg_thumbnail_size; + + if (jpeg_thumbnail_data == NULL || jpeg_thumbnail_size <= 0) { + ALOGE("%s: Invalid jpeg thumbnail", __func__); + goto error; + } + + attributes = &exif->attributes; + + memory_size = EXIF_FILE_SIZE + jpeg_thumbnail_size; + + if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { + memory = exynos_camera->callbacks.request_memory(-1, memory_size, 1, exynos_camera->callbacks.user); + if (memory == NULL || memory->data == NULL || memory->data == MAP_FAILED) { + ALOGE("%s: Unable to request memory", __func__); + goto error; + } + } else { + ALOGE("%s: No memory request function!", __func__); + goto error; + } + + memset(memory->data, 0, memory_size); + + pointer = (unsigned char *) memory->data; + exif_ifd_data_start = (void *) pointer; + + // Skip 4 bytes for APP1 marker + pointer += 4; + + // Copy EXIF marker + memcpy(pointer, exif_marker, sizeof(exif_marker)); + pointer += sizeof(exif_marker); + + // Copy TIFF marker + memcpy(pointer, tiff_marker, sizeof(tiff_marker)); + exif_ifd_start = (void *) pointer; + pointer += sizeof(tiff_marker); + + if (attributes->enableGps) + value = NUM_0TH_IFD_TIFF; + else + value = NUM_0TH_IFD_TIFF - 1; + + memcpy(pointer, &value, NUM_SIZE); + pointer += NUM_SIZE; + + offset = 8 + NUM_SIZE + value * IFD_SIZE + OFFSET_SIZE; + + // Write EXIF data + count = exynos_exif_write_data(pointer, EXIF_TAG_IMAGE_WIDTH, + EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->width, sizeof(attributes->width)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_IMAGE_HEIGHT, + EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->height, sizeof(attributes->height)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_MAKE, + EXIF_TYPE_ASCII, strlen((char *) attributes->maker) + 1, &offset, exif_ifd_start, &attributes->maker, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_MODEL, + EXIF_TYPE_ASCII, strlen((char *) attributes->model) + 1, &offset, exif_ifd_start, &attributes->model, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_ORIENTATION, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->orientation, sizeof(attributes->orientation)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_SOFTWARE, + EXIF_TYPE_ASCII, strlen((char *) attributes->software) + 1, &offset, exif_ifd_start, &attributes->software, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_DATE_TIME, + EXIF_TYPE_ASCII, 20, &offset, exif_ifd_start, &attributes->date_time, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_YCBCR_POSITIONING, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->ycbcr_positioning, sizeof(attributes->ycbcr_positioning)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_EXIF_IFD_POINTER, + EXIF_TYPE_LONG, 1, NULL, NULL, &offset, sizeof(offset)); + pointer += count; + + if (attributes->enableGps) { + exif_ifd_gps = (void *) pointer; + pointer += IFD_SIZE; + } + + exif_ifd_thumb = (void *) pointer; + pointer += OFFSET_SIZE; + + pointer = (unsigned char *) exif_ifd_start; + pointer += offset; + + value = NUM_0TH_IFD_EXIF; + memcpy(pointer, &value, NUM_SIZE); + pointer += NUM_SIZE; + + offset += NUM_SIZE + NUM_0TH_IFD_EXIF * IFD_SIZE + OFFSET_SIZE; + + count = exynos_exif_write_data(pointer, EXIF_TAG_EXPOSURE_TIME, + EXIF_TYPE_RATIONAL, 1, &offset, exif_ifd_start, &attributes->exposure_time, sizeof(attributes->exposure_time)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_FNUMBER, + EXIF_TYPE_RATIONAL, 1, &offset, exif_ifd_start, &attributes->fnumber, sizeof(attributes->fnumber)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_EXPOSURE_PROGRAM, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->exposure_program, sizeof(attributes->exposure_program)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_ISO_SPEED_RATING, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->iso_speed_rating, sizeof(attributes->iso_speed_rating)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_EXIF_VERSION, + EXIF_TYPE_UNDEFINED, 4, NULL, NULL, &attributes->exif_version, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_DATE_TIME_ORG, + EXIF_TYPE_ASCII, 20, &offset, exif_ifd_start, &attributes->date_time, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_DATE_TIME_DIGITIZE, + EXIF_TYPE_ASCII, 20, &offset, exif_ifd_start, &attributes->date_time, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_SHUTTER_SPEED, + EXIF_TYPE_SRATIONAL, 1, &offset, exif_ifd_start, &attributes->shutter_speed, sizeof(attributes->shutter_speed)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_APERTURE, + EXIF_TYPE_RATIONAL, 1, &offset, exif_ifd_start, &attributes->aperture, sizeof(attributes->aperture)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_BRIGHTNESS, + EXIF_TYPE_SRATIONAL, 1, &offset, exif_ifd_start, &attributes->brightness, sizeof(attributes->brightness)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_EXPOSURE_BIAS, + EXIF_TYPE_SRATIONAL, 1, &offset, exif_ifd_start, &attributes->exposure_bias, sizeof(attributes->exposure_bias)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_MAX_APERTURE, + EXIF_TYPE_RATIONAL, 1, &offset, exif_ifd_start, &attributes->max_aperture, sizeof(attributes->max_aperture)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_METERING_MODE, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->metering_mode, sizeof(attributes->metering_mode)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_FLASH, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->flash, sizeof(attributes->flash)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_FOCAL_LENGTH, + EXIF_TYPE_RATIONAL, 1, &offset, exif_ifd_start, &attributes->focal_length, sizeof(attributes->focal_length)); + pointer += count; + + value = strlen((char *) attributes->user_comment) + 1; + memmove(attributes->user_comment + sizeof(user_comment_code), attributes->user_comment, value); + memcpy(attributes->user_comment, user_comment_code, sizeof(user_comment_code)); + + count = exynos_exif_write_data(pointer, EXIF_TAG_USER_COMMENT, + EXIF_TYPE_UNDEFINED, value + sizeof(user_comment_code), &offset, exif_ifd_start, &attributes->user_comment, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_COLOR_SPACE, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->color_space, sizeof(attributes->color_space)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_PIXEL_X_DIMENSION, + EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->width, sizeof(attributes->width)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_PIXEL_Y_DIMENSION, + EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->height, sizeof(attributes->height)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_EXPOSURE_MODE, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->exposure_mode, sizeof(attributes->exposure_mode)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_WHITE_BALANCE, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->white_balance, sizeof(attributes->white_balance)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_SCENCE_CAPTURE_TYPE, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->scene_capture_type, sizeof(attributes->scene_capture_type)); + pointer += count; + + value = 0; + memcpy(pointer, &value, OFFSET_SIZE); + pointer += OFFSET_SIZE; + + // GPS + if (attributes->enableGps) { + pointer = (unsigned char *) exif_ifd_gps; + count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_IFD_POINTER, + EXIF_TYPE_LONG, 1, NULL, NULL, &offset, sizeof(offset)); + + pointer = (unsigned char *) exif_ifd_start + offset; + + if (attributes->gps_processing_method[0] == 0) + value = NUM_0TH_IFD_GPS - 1; + else + value = NUM_0TH_IFD_GPS; + + memcpy(pointer, &value, NUM_SIZE); + pointer += NUM_SIZE; + + offset += NUM_SIZE + value * IFD_SIZE + OFFSET_SIZE; + + count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_VERSION_ID, + EXIF_TYPE_BYTE, 4, NULL, NULL, &attributes->gps_version_id, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_LATITUDE_REF, + EXIF_TYPE_ASCII, 2, NULL, NULL, &attributes->gps_latitude_ref, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_LATITUDE, + EXIF_TYPE_RATIONAL, 3, &offset, exif_ifd_start, &attributes->gps_latitude, sizeof(attributes->gps_latitude[0])); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_LONGITUDE_REF, + EXIF_TYPE_ASCII, 2, NULL, NULL, &attributes->gps_longitude_ref, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_LONGITUDE, + EXIF_TYPE_RATIONAL, 3, &offset, exif_ifd_start, &attributes->gps_longitude, sizeof(attributes->gps_longitude[0])); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_ALTITUDE_REF, + EXIF_TYPE_BYTE, 1, NULL, NULL, &attributes->gps_altitude_ref, sizeof(char)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_ALTITUDE, + EXIF_TYPE_RATIONAL, 1, &offset, exif_ifd_start, &attributes->gps_altitude, sizeof(attributes->gps_altitude)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_TIMESTAMP, + EXIF_TYPE_RATIONAL, 3, &offset, exif_ifd_start, &attributes->gps_timestamp, sizeof(attributes->gps_timestamp[0])); + pointer += count; + + value = strlen((char *) attributes->gps_processing_method); + if (value > 0) { + value = value > 100 ? 100 : value; + + data = calloc(1, value + sizeof(exif_ascii_prefix)); + memcpy(data, &exif_ascii_prefix, sizeof(exif_ascii_prefix)); + memcpy((void *) ((int) data + (int) sizeof(exif_ascii_prefix)), attributes->gps_processing_method, value); + + count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_PROCESSING_METHOD, + EXIF_TYPE_UNDEFINED, value + sizeof(exif_ascii_prefix), &offset, exif_ifd_start, data, sizeof(char)); + pointer += count; + + free(data); + } + + count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_DATESTAMP, + EXIF_TYPE_ASCII, 11, &offset, exif_ifd_start, &attributes->gps_datestamp, 1); + pointer += count; + + value = 0; + memcpy(pointer, &value, OFFSET_SIZE); + pointer += OFFSET_SIZE; + } + + if (attributes->enableThumb) { + value = offset; + memcpy(exif_ifd_thumb, &value, OFFSET_SIZE); + + pointer = (unsigned char *) ((int) exif_ifd_start + (int) offset); + + value = NUM_1TH_IFD_TIFF; + memcpy(pointer, &value, NUM_SIZE); + pointer += NUM_SIZE; + + offset += NUM_SIZE + NUM_1TH_IFD_TIFF * IFD_SIZE + OFFSET_SIZE; + + count = exynos_exif_write_data(pointer, EXIF_TAG_IMAGE_WIDTH, + EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->widthThumb, sizeof(attributes->widthThumb)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_IMAGE_HEIGHT, + EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->heightThumb, sizeof(attributes->heightThumb)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_COMPRESSION_SCHEME, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->compression_scheme, sizeof(attributes->compression_scheme)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_ORIENTATION, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->orientation, sizeof(attributes->orientation)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_X_RESOLUTION, + EXIF_TYPE_RATIONAL, 1, &offset, exif_ifd_start, &attributes->x_resolution, sizeof(attributes->x_resolution)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_Y_RESOLUTION, + EXIF_TYPE_RATIONAL, 1, &offset, exif_ifd_start, &attributes->y_resolution, sizeof(attributes->y_resolution)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_RESOLUTION_UNIT, + EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->resolution_unit, sizeof(attributes->resolution_unit)); + pointer += count; + + count = exynos_exif_write_data(pointer, EXIF_TAG_JPEG_INTERCHANGE_FORMAT, + EXIF_TYPE_LONG, 1, NULL, NULL, &offset, sizeof(offset)); + pointer += count; + + value = (unsigned int) jpeg_thumbnail_size; + + count = exynos_exif_write_data(pointer, EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LEN, + EXIF_TYPE_LONG, 1, NULL, NULL, &value, sizeof(value)); + pointer += count; + + value = 0; + memcpy(pointer, &value, OFFSET_SIZE); + + pointer = (unsigned char *) ((int) exif_ifd_start + (int) offset); + + memcpy(pointer, jpeg_thumbnail_data, jpeg_thumbnail_size); + offset += jpeg_thumbnail_size; + } else { + value = 0; + memcpy(exif_ifd_thumb, &value, OFFSET_SIZE); + + } + + pointer = (unsigned char *) exif_ifd_data_start; + + memcpy(pointer, exif_app1_marker, sizeof(exif_app1_marker)); + pointer += sizeof(exif_app1_marker); + + memory_size = offset + 10; + value = memory_size - 2; + exif_app1_size[0] = (value >> 8) & 0xff; + exif_app1_size[1] = value & 0xff; + + memcpy(pointer, exif_app1_size, sizeof(exif_app1_size)); + + exif->memory = memory; + exif->memory_size = memory_size; + + rc = 0; + goto complete; + +error: + if (memory != NULL && memory->release != NULL) { + memory->release(memory); + exif->memory = NULL; + } + + rc = -1; + +complete: + return rc; +} diff --git a/camera/exynos_ion.c b/camera/exynos_ion.c new file mode 100644 index 0000000..6adf7cc --- /dev/null +++ b/camera/exynos_ion.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski + * + * 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 3 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, see . + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define LOG_TAG "exynos_ion" +#include + +#include "exynos_camera.h" + +int exynos_ion_init(struct exynos_camera *exynos_camera) +{ + exynos_camera->ion_fd = -1; + + return 0; +} + +int exynos_ion_open(struct exynos_camera *exynos_camera) +{ + int fd; + + fd = open("/dev/ion", O_RDWR); + if (fd < 0) { + ALOGE("%s: Unable to open ion device", __func__); + return -1; + } + + exynos_camera->ion_fd = fd; + + return 0; +} + +void exynos_ion_close(struct exynos_camera *exynos_camera) +{ + if (exynos_camera->ion_fd >= 0) + close(exynos_camera->ion_fd); + + exynos_camera->ion_fd = -1; +} + +int exynos_ion_alloc(struct exynos_camera *exynos_camera, int size) +{ + struct ion_allocation_data alloc_data; + struct ion_fd_data share_data; + struct ion_handle_data free_data; + int page_size; + int fd; + int rc; + + page_size = getpagesize(); + + fd = exynos_camera->ion_fd; + if (fd < 0) + return -1; + + memset(&alloc_data, 0, sizeof(alloc_data)); + alloc_data.len = size; + alloc_data.align = page_size; + alloc_data.flags = ION_HEAP_EXYNOS_CONTIG_MASK; + + rc = ioctl(fd, ION_IOC_ALLOC, &alloc_data); + if (rc < 0) + return -1; + + memset(&share_data, 0, sizeof(share_data)); + share_data.handle = alloc_data.handle; + + rc = ioctl(fd, ION_IOC_SHARE, &share_data); + if (rc < 0) + return -1; + + memset(&free_data, 0, sizeof(free_data)); + free_data.handle = alloc_data.handle; + + rc = ioctl(fd, ION_IOC_FREE, &free_data); + if (rc < 0) + return -1; + + return share_data.fd; +} + +int exynos_ion_free(struct exynos_camera *exynos_camera, int fd) +{ + close(fd); + return 0; +} + +int exynos_ion_phys(struct exynos_camera *exynos_camera, int fd) +{ + struct ion_custom_data custom_data; + struct ion_phys_data phys_data; + int rc; + + memset(&phys_data, 0, sizeof(phys_data)); + phys_data.fd_buffer = fd; + + memset(&custom_data, 0, sizeof(custom_data)); + custom_data.cmd = ION_EXYNOS_CUSTOM_PHYS; + custom_data.arg = (unsigned long) &phys_data; + + fd = exynos_camera->ion_fd; + if (fd < 0) + return -1; + + rc = ioctl(fd, ION_IOC_CUSTOM, &custom_data); + if (rc < 0) + return -1; + + return (int) phys_data.phys; +} + +int exynos_ion_msync(struct exynos_camera *exynos_camera, int fd, + int offset, int size) +{ + struct ion_custom_data custom_data; + struct ion_msync_data msync_data; + int rc; + + memset(&msync_data, 0, sizeof(msync_data)); + msync_data.dir = IMSYNC_SYNC_FOR_DEV | IMSYNC_DEV_TO_RW; + msync_data.fd_buffer = fd; + msync_data.offset = offset; + msync_data.size = size; + + memset(&custom_data, 0, sizeof(custom_data)); + custom_data.cmd = ION_EXYNOS_CUSTOM_MSYNC; + custom_data.arg = (unsigned long) &msync_data; + + fd = exynos_camera->ion_fd; + if (fd < 0) + return -1; + + rc = ioctl(fd, ION_IOC_CUSTOM, &custom_data); + if (rc < 0) + return -1; + + return 0; +} diff --git a/camera/exynos_jpeg.c b/camera/exynos_jpeg.c new file mode 100644 index 0000000..24e74fc --- /dev/null +++ b/camera/exynos_jpeg.c @@ -0,0 +1,404 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski + * + * 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 3 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define LOG_TAG "exynos_jpeg" +#include + +#include "exynos_camera.h" + +#ifdef EXYNOS_JPEG_HW +int exynos_jpeg_start(struct exynos_camera *exynos_camera, + struct exynos_jpeg *jpeg) +{ + struct jpeg_config config; + struct jpeg_buf *buffer_in; + struct jpeg_buf *buffer_out; + camera_memory_t *memory = NULL; +#ifdef EXYNOS_ION + int memory_ion_fd = -1; +#endif + int address; + int fd = -1; + int rc; + + if (exynos_camera == NULL || jpeg == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (jpeg->enabled) { + ALOGE("Jpeg was already started"); + return -1; + } + + buffer_in = &jpeg->buffer_in; + buffer_out = &jpeg->buffer_out; + +#ifdef EXYNOS_ION + jpeg->memory_in_ion_fd = -1; + jpeg->memory_out_ion_fd = -1; +#endif + + fd = jpeghal_enc_init(); + if (fd < 0) { + ALOGE("%s: Unable to init jpeg encoder", __func__); + goto error; + } + + jpeg->fd = fd; + + memset(&config, 0, sizeof(config)); + config.mode = JPEG_ENCODE; + config.width = jpeg->width; + config.height = jpeg->height; + config.num_planes = 1; + config.pix.enc_fmt.in_fmt = jpeg->format; + config.pix.enc_fmt.out_fmt = V4L2_PIX_FMT_JPEG_420; + + if (jpeg->quality >= 90) + config.enc_qual = QUALITY_LEVEL_1; + else if (jpeg->quality >= 80) + config.enc_qual = QUALITY_LEVEL_2; + else if (jpeg->quality >= 70) + config.enc_qual = QUALITY_LEVEL_3; + else + config.enc_qual = QUALITY_LEVEL_4; + + rc = jpeghal_enc_setconfig(fd, &config); + if (rc < 0) { + ALOGE("%s: Unable to set jpeg config", __func__); + goto error; + } + + rc = jpeghal_s_ctrl(fd, V4L2_CID_CACHEABLE, 1); + if (rc < 0) { + ALOGE("%s: Unable to set cacheable control", __func__); + goto error; + } + + memset(buffer_in, 0, sizeof(struct jpeg_buf)); + buffer_in->memory = V4L2_MEMORY_MMAP; + buffer_in->num_planes = 1; + + memset(buffer_out, 0, sizeof(struct jpeg_buf)); + buffer_out->memory = V4L2_MEMORY_MMAP; + buffer_out->num_planes = 1; + + rc = jpeghal_set_inbuf(fd, buffer_in); + if (rc < 0) { +#ifdef EXYNOS_ION + // Input + + buffer_in->memory = V4L2_MEMORY_USERPTR; + buffer_in->length[0] = exynos_camera_buffer_length(jpeg->width, jpeg->height, jpeg->format); + + memory_ion_fd = exynos_ion_alloc(exynos_camera, buffer_in->length[0]); + if (memory_ion_fd < 0) { + ALOGE("%s: Unable to alloc input ION memory", __func__); + goto error; + } + + address = exynos_ion_phys(exynos_camera, memory_ion_fd); + + if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { + memory = exynos_camera->callbacks.request_memory(memory_ion_fd, buffer_in->length[0], 1, exynos_camera->callbacks.user); + if (memory == NULL || memory->data == NULL || memory->data == MAP_FAILED) { + ALOGE("%s: Unable to request memory", __func__); + goto error; + } + } else { + ALOGE("%s: No memory request function!", __func__); + goto error; + } + + jpeg->memory_in = memory; + jpeg->memory_in_pointer = memory->data; + jpeg->memory_in_ion_fd = memory_ion_fd; + buffer_in->start[0] = (void *) address; + + rc = jpeghal_set_inbuf(fd, buffer_in); + if (rc < 0) { + ALOGE("%s: Unable to set input buffer", __func__); + goto error; + } + + // Output + + buffer_out->memory = V4L2_MEMORY_USERPTR; + buffer_out->length[0] = jpeg->width * jpeg->height * 4; + + memory_ion_fd = exynos_ion_alloc(exynos_camera, buffer_out->length[0]); + if (memory_ion_fd < 0) { + ALOGE("%s: Unable to alloc output ION memory", __func__); + goto error; + } + + address = exynos_ion_phys(exynos_camera, memory_ion_fd); + + if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { + memory = exynos_camera->callbacks.request_memory(memory_ion_fd, buffer_out->length[0], 1, exynos_camera->callbacks.user); + if (memory == NULL || memory->data == NULL || memory->data == MAP_FAILED) { + ALOGE("%s: Unable to request memory", __func__); + goto error; + } + } else { + ALOGE("%s: No memory request function!", __func__); + goto error; + } + + jpeg->memory_out = memory; + jpeg->memory_out_pointer = memory->data; + jpeg->memory_out_ion_fd = memory_ion_fd; + buffer_out->start[0] = (void *) address; +#else + ALOGE("%s: Unable to set input buffer", __func__); + goto error; +#endif + } else { + jpeg->memory_in_pointer = buffer_in->start[0]; + jpeg->memory_out_pointer = buffer_out->start[0]; + } + + rc = jpeghal_set_outbuf(fd, buffer_out); + if (rc < 0) { + ALOGE("%s: Unable to set output buffer", __func__); + goto error; + } + + jpeg->enabled = 1; + + rc = 0; + goto complete; + +error: + if (fd >= 0) { + // Avoid releasing unrequested mmap buffers + + if (buffer_in->memory == 0) + buffer_in->memory = V4L2_MEMORY_USERPTR; + + if (buffer_out->memory == 0) + buffer_out->memory = V4L2_MEMORY_USERPTR; + + jpeghal_deinit(fd, buffer_in, buffer_out); + jpeg->fd = -1; + } + + if (jpeg->memory_in != NULL && jpeg->memory_in->release != NULL) { + jpeg->memory_in->release(jpeg->memory_in); + jpeg->memory_in = NULL; +#ifdef EXYNOS_ION + if (jpeg->memory_in_ion_fd >= 0) { + exynos_ion_free(exynos_camera, jpeg->memory_in_ion_fd); + jpeg->memory_in_ion_fd = -1; + } +#endif + } + + if (jpeg->memory_out != NULL && jpeg->memory_out->release != NULL) { + jpeg->memory_out->release(jpeg->memory_out); + jpeg->memory_out = NULL; + +#ifdef EXYNOS_ION + if (jpeg->memory_out_ion_fd >= 0) { + exynos_ion_free(exynos_camera, jpeg->memory_out_ion_fd); + jpeg->memory_out_ion_fd = -1; + } +#endif + } + + rc = -1; + +complete: + return rc; +} + +void exynos_jpeg_stop(struct exynos_camera *exynos_camera, + struct exynos_jpeg *jpeg) +{ + struct jpeg_buf *buffer_in; + struct jpeg_buf *buffer_out; + int fd = -1; + int rc; + + if (exynos_camera == NULL || jpeg == NULL) + return; + + ALOGD("%s()", __func__); + + if (!jpeg->enabled) { + ALOGE("Jpeg was already stopped"); + return; + } + + buffer_in = &jpeg->buffer_in; + buffer_out = &jpeg->buffer_out; + + fd = jpeg->fd; + + if (fd >= 0) { + jpeghal_deinit(fd, buffer_in, buffer_out); + jpeg->fd = -1; + } + + if (jpeg->memory_in != NULL && jpeg->memory_in->release != NULL) { + jpeg->memory_in->release(jpeg->memory_in); + jpeg->memory_in = NULL; +#ifdef EXYNOS_ION + if (jpeg->memory_in_ion_fd >= 0) { + exynos_ion_free(exynos_camera, jpeg->memory_in_ion_fd); + jpeg->memory_in_ion_fd = -1; + } +#endif + } + + if (jpeg->memory_out != NULL && jpeg->memory_out->release != NULL) { + jpeg->memory_out->release(jpeg->memory_out); + jpeg->memory_out = NULL; + +#ifdef EXYNOS_ION + if (jpeg->memory_out_ion_fd >= 0) { + exynos_ion_free(exynos_camera, jpeg->memory_out_ion_fd); + jpeg->memory_out_ion_fd = -1; + } +#endif + } + + jpeg->enabled = 0; +} + +int exynos_jpeg(struct exynos_camera *exynos_camera, struct exynos_jpeg *jpeg) +{ + struct jpeg_buf *buffer_in; + struct jpeg_buf *buffer_out; + int memory_size; + int fd = -1; + int rc; + + if (exynos_camera == NULL || jpeg == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (!jpeg->enabled) { + ALOGE("Jpeg was not started"); + return -1; + } + + buffer_in = &jpeg->buffer_in; + buffer_out = &jpeg->buffer_out; + + fd = jpeg->fd; + if (fd < 0) { + ALOGE("%s: Invalid jpeg fd", __func__); + goto error; + } + +#ifdef EXYNOS_ION + if (jpeg->memory_in != NULL && jpeg->memory_in_ion_fd >= 0) { + rc = exynos_ion_msync(exynos_camera, jpeg->memory_in_ion_fd, 0, buffer_in->length[0]); + if (rc < 0) { + ALOGE("%s: Unable to sync ION memory", __func__); + goto error; + } + } +#endif + + rc = jpeghal_enc_exe(fd, buffer_in, buffer_out); + if (rc < 0) { + ALOGE("%s: Unable to encode jpeg", __func__); + goto error; + } + + memory_size = jpeghal_g_ctrl(fd, V4L2_CID_CAM_JPEG_ENCODEDSIZE); + if (memory_size <= 0) { + ALOGE("%s: Unable to get jpeg size", __func__); + goto error; + } + + jpeg->memory_out_size = memory_size; + +#ifdef EXYNOS_ION + if (jpeg->memory_out != NULL && jpeg->memory_out_ion_fd >= 0) { + rc = exynos_ion_msync(exynos_camera, jpeg->memory_out_ion_fd, 0, memory_size); + if (rc < 0) { + ALOGE("%s: Unable to sync ION memory", __func__); + goto error; + } + } +#endif + + rc = 0; + goto complete; + +error: + if (fd >= 0) { + // Avoid releasing unrequested mmap buffers + + if (buffer_in->memory == 0) + buffer_in->memory = V4L2_MEMORY_USERPTR; + + if (buffer_out->memory == 0) + buffer_out->memory = V4L2_MEMORY_USERPTR; + + jpeghal_deinit(fd, buffer_in, buffer_out); + jpeg->fd = -1; + } + + if (jpeg->memory_in != NULL && jpeg->memory_in->release != NULL) { + jpeg->memory_in->release(jpeg->memory_in); + jpeg->memory_in = NULL; + +#ifdef EXYNOS_ION + if (jpeg->memory_in_ion_fd >= 0) { + exynos_ion_free(exynos_camera, jpeg->memory_in_ion_fd); + jpeg->memory_in_ion_fd = -1; + } +#endif + } + + if (jpeg->memory_out != NULL && jpeg->memory_out->release != NULL) { + jpeg->memory_out->release(jpeg->memory_out); + jpeg->memory_out = NULL; + +#ifdef EXYNOS_ION + if (jpeg->memory_out_ion_fd >= 0) { + exynos_ion_free(exynos_camera, jpeg->memory_out_ion_fd); + jpeg->memory_out_ion_fd = -1; + } +#endif + } + + rc = -1; + +complete: + return rc; +} +#endif diff --git a/camera/exynos_param.c b/camera/exynos_param.c new file mode 100644 index 0000000..f41f4f6 --- /dev/null +++ b/camera/exynos_param.c @@ -0,0 +1,492 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski + * + * 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 3 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, see . + */ + +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "exynos_param" +#include + +#include "exynos_camera.h" + +int exynos_param_register(struct exynos_camera *exynos_camera, char *key, + union exynos_param_data data, enum exynos_param_type type) +{ + struct list_head *list_end; + struct list_head *list; + struct exynos_param *param; + + if (exynos_camera == NULL || key == NULL) + return -EINVAL; + + param = (struct exynos_param *) calloc(1, sizeof(struct exynos_param)); + if (param == NULL) + return -ENOMEM; + + param->key = strdup(key); + switch (type) { + case EXYNOS_PARAM_INT: + param->data.integer = data.integer; + break; + case EXYNOS_PARAM_FLOAT: + param->data.floating = data.floating; + break; + case EXYNOS_PARAM_STRING: + param->data.string = strdup(data.string); + break; + default: + ALOGE("%s: Invalid type", __func__); + goto error; + } + param->type = type; + + list_end = (struct list_head *) exynos_camera->params; + while (list_end != NULL && list_end->next != NULL) + list_end = list_end->next; + + list = (struct list_head *) param; + list_head_insert(list, list_end, NULL); + + if (exynos_camera->params == NULL) + exynos_camera->params = param; + + return 0; + +error: + if (param != NULL) { + if (param->key != NULL) + free(param->key); + + free(param); + } + + return -1; +} + +void exynos_param_unregister(struct exynos_camera *exynos_camera, + struct exynos_param *param) +{ + struct list_head *list; + + if (exynos_camera == NULL || param == NULL) + return; + + list = (struct list_head *) exynos_camera->params; + while (list != NULL) { + if ((void *) list == (void *) param) { + list_head_remove(list); + + if ((void *) list == (void *) exynos_camera->params) + exynos_camera->params = (struct exynos_param *) list->next; + + if (param->type == EXYNOS_PARAM_STRING && param->data.string != NULL) + free(param->data.string); + + memset(param, 0, sizeof(struct exynos_param)); + free(param); + + break; + } + +list_continue: + list = list->next; + } +} + +struct exynos_param *exynos_param_find_key(struct exynos_camera *exynos_camera, + char *key) +{ + struct exynos_param *param; + struct list_head *list; + + if (exynos_camera == NULL || key == NULL) + return NULL; + + list = (struct list_head *) exynos_camera->params; + while (list != NULL) { + param = (struct exynos_param *) list; + if (param->key == NULL) + goto list_continue; + + if (strcmp(param->key, key) == 0) + return param; + +list_continue: + list = list->next; + } + + return NULL; +} + +int exynos_param_data_set(struct exynos_camera *exynos_camera, char *key, + union exynos_param_data data, enum exynos_param_type type) +{ + struct exynos_param *param; + + if (exynos_camera == NULL || key == NULL) + return -EINVAL; + + if (strchr(key, '=') || strchr(key, ';')) + return -EINVAL; + + if (type == EXYNOS_PARAM_STRING && data.string != NULL && + (strchr(data.string, '=') || strchr(data.string, ';'))) + return -EINVAL; + + param = exynos_param_find_key(exynos_camera, key); + if (param == NULL) { + // The key isn't in the list yet + exynos_param_register(exynos_camera, key, data, type); + return 0; + } + + if (param->type != type) + ALOGE("%s: Mismatching types for key %s", __func__, key); + + if (param->type == EXYNOS_PARAM_STRING && param->data.string != NULL) + free(param->data.string); + + switch (type) { + case EXYNOS_PARAM_INT: + param->data.integer = data.integer; + break; + case EXYNOS_PARAM_FLOAT: + param->data.floating = data.floating; + break; + case EXYNOS_PARAM_STRING: + param->data.string = strdup(data.string); + break; + default: + ALOGE("%s: Invalid type", __func__); + return -1; + } + param->type = type; + + return 0; +} + +int exynos_param_data_get(struct exynos_camera *exynos_camera, char *key, + union exynos_param_data *data, enum exynos_param_type type) +{ + struct exynos_param *param; + + if (exynos_camera == NULL || key == NULL || data == NULL) + return -EINVAL; + + param = exynos_param_find_key(exynos_camera, key); + if (param == NULL || param->type != type) + return -1; + + memcpy(data, ¶m->data, sizeof(param->data)); + + return 0; +} + +int exynos_param_int_get(struct exynos_camera *exynos_camera, + char *key) +{ + union exynos_param_data data; + int rc; + + if (exynos_camera == NULL || key == NULL) + return -EINVAL; + + rc = exynos_param_data_get(exynos_camera, key, &data, EXYNOS_PARAM_INT); + if (rc < 0) { + ALOGE("%s: Unable to get data for key %s", __func__, key); + return -1; + } + + return data.integer; +} + +float exynos_param_float_get(struct exynos_camera *exynos_camera, + char *key) +{ + union exynos_param_data data; + int rc; + + if (exynos_camera == NULL || key == NULL) + return -EINVAL; + + rc = exynos_param_data_get(exynos_camera, key, &data, EXYNOS_PARAM_FLOAT); + if (rc < 0) { + ALOGE("%s: Unable to get data for key %s", __func__, key); + return -1; + } + + return data.floating; +} + +char *exynos_param_string_get(struct exynos_camera *exynos_camera, + char *key) +{ + union exynos_param_data data; + int rc; + + if (exynos_camera == NULL || key == NULL) + return NULL; + + rc = exynos_param_data_get(exynos_camera, key, &data, EXYNOS_PARAM_STRING); + if (rc < 0) { + ALOGE("%s: Unable to get data for key %s", __func__, key); + return NULL; + } + + return data.string; +} + +int exynos_param_int_set(struct exynos_camera *exynos_camera, + char *key, int integer) +{ + union exynos_param_data data; + int rc; + + if (exynos_camera == NULL || key == NULL) + return -EINVAL; + + data.integer = integer; + + rc = exynos_param_data_set(exynos_camera, key, data, EXYNOS_PARAM_INT); + if (rc < 0) { + ALOGE("%s: Unable to set data for key %s", __func__, key); + return -1; + } + + return 0; +} + +int exynos_param_float_set(struct exynos_camera *exynos_camera, + char *key, float floating) +{ + union exynos_param_data data; + int rc; + + if (exynos_camera == NULL || key == NULL) + return -EINVAL; + + data.floating = floating; + + rc = exynos_param_data_set(exynos_camera, key, data, EXYNOS_PARAM_FLOAT); + if (rc < 0) { + ALOGE("%s: Unable to set data for key %s", __func__, key); + return -1; + } + + return 0; +} + +int exynos_param_string_set(struct exynos_camera *exynos_camera, + char *key, char *string) +{ + union exynos_param_data data; + int rc; + + if (exynos_camera == NULL || key == NULL || string == NULL) + return -EINVAL; + + data.string = string; + + rc = exynos_param_data_set(exynos_camera, key, data, EXYNOS_PARAM_STRING); + if (rc < 0) { + ALOGE("%s: Unable to set data for key %s", __func__, key); + return -1; + } + + return 0; +} + +char *exynos_params_string_get(struct exynos_camera *exynos_camera) +{ + struct exynos_param *param; + struct list_head *list; + char *string = NULL; + char *s = NULL; + int length = 0; + int l = 0; + + if (exynos_camera == NULL) + return NULL; + + list = (struct list_head *) exynos_camera->params; + while (list != NULL) { + param = (struct exynos_param *) list; + if (param->key == NULL) + goto list_continue_length; + + length += strlen(param->key); + length++; + + switch (param->type) { + case EXYNOS_PARAM_INT: + case EXYNOS_PARAM_FLOAT: + length += 16; + break; + case EXYNOS_PARAM_STRING: + length += strlen(param->data.string); + break; + default: + ALOGE("%s: Invalid type", __func__); + return NULL; + } + + length++; + +list_continue_length: + list = list->next; + } + + if (length == 0) + return NULL; + + string = calloc(1, length); + s = string; + + list = (struct list_head *) exynos_camera->params; + while (list != NULL) { + param = (struct exynos_param *) list; + if (param->key == NULL) + goto list_continue; + + l = sprintf(s, "%s=", param->key); + s += l; + + switch (param->type) { + case EXYNOS_PARAM_INT: + l = snprintf(s, 16, "%d", param->data.integer); + s += l; + break; + case EXYNOS_PARAM_FLOAT: + l = snprintf(s, 16, "%g", param->data.floating); + s += l; + break; + case EXYNOS_PARAM_STRING: + l = sprintf(s, "%s", param->data.string); + s += l; + break; + default: + ALOGE("%s: Invalid type", __func__); + return NULL; + } + + if (list->next != NULL) { + *s = ';'; + s++; + } else { + *s = '\0'; + break; + } + +list_continue: + list = list->next; + } + + return string; +} + +int exynos_params_string_set(struct exynos_camera *exynos_camera, char *string) +{ + union exynos_param_data data; + enum exynos_param_type type; + + char *d = NULL; + char *s = NULL; + char *k = NULL; + char *v = NULL; + + char *key; + char *value; + + int rc; + int i; + + if (exynos_camera == NULL || string == NULL) + return -1; + + d = strdup(string); + s = d; + + while (1) { + k = strchr(s, '='); + if (k == NULL) + break; + *k = '\0'; + key = s; + + v = strchr(k+1, ';'); + if (v != NULL) + *v = '\0'; + value = k+1; + + k = value; + if (isdigit(k[0]) || k[0] == '-') { + type = EXYNOS_PARAM_INT; + + for (i=1 ; k[i] != '\0' ; i++) { + if (k[i] == '.') { + type = EXYNOS_PARAM_FLOAT; + } else if (!isdigit(k[i])) { + type = EXYNOS_PARAM_STRING; + break; + } + } + } else { + type = EXYNOS_PARAM_STRING; + } + + switch (type) { + case EXYNOS_PARAM_INT: + data.integer = atoi(value); + break; + case EXYNOS_PARAM_FLOAT: + data.floating = atof(value); + break; + case EXYNOS_PARAM_STRING: + data.string = value; + break; + default: + ALOGE("%s: Invalid type", __func__); + goto error; + } + + rc = exynos_param_data_set(exynos_camera, key, data, type); + if (rc < 0) { + ALOGE("%s: Unable to set data for key %s", __func__, key); + goto error; + } + + if (v == NULL) + break; + + s = v+1; + } + + if (d != NULL) + free(d); + + return 0; + +error: + if (d != NULL) + free(d); + + return -1; +} diff --git a/camera/exynos_utils.c b/camera/exynos_utils.c new file mode 100644 index 0000000..c969656 --- /dev/null +++ b/camera/exynos_utils.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski + * + * 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 3 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, see . + */ + +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "exynos_utils" +#include + +#include "exynos_camera.h" + +int list_head_insert(struct list_head *list, struct list_head *prev, + struct list_head *next) +{ + if (list == NULL) + return -EINVAL; + + list->prev = prev; + list->next = next; + + if(prev != NULL) + prev->next = list; + if(next != NULL) + next->prev = list; + + return 0; +} + +void list_head_remove(struct list_head *list) +{ + if(list == NULL) + return; + + if(list->next != NULL) + list->next->prev = list->prev; + if(list->prev != NULL) + list->prev->next = list->next; +} + + +int exynos_camera_buffer_length(int width, int height, int format) +{ + float bpp; + int buffer_length; + + switch (format) { + case V4L2_PIX_FMT_RGB32: + bpp = 4.0f; + buffer_length = (int) ((float) width * (float) height * bpp); + break; + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_YUV422P: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + bpp = 2.0f; + buffer_length = (int) ((float) width * (float) height * bpp); + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + bpp = 1.5f; + buffer_length = EXYNOS_CAMERA_ALIGN(width * height); + buffer_length += EXYNOS_CAMERA_ALIGN(width * height / 2); + break; + case V4L2_PIX_FMT_NV21: + bpp = 1.5f; + buffer_length = (int) ((float) width * (float) height * bpp); + break; + case V4L2_PIX_FMT_JPEG: + case V4L2_PIX_FMT_INTERLEAVED: + default: + buffer_length = -1; + bpp = 0; + break; + } + + return buffer_length; +} + +void exynos_camera_yuv_planes(int width, int height, int format, int address, int *address_y, int *address_cb, int *address_cr) +{ + switch (format) { + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YVYU: + if (address_y != NULL) + *address_y = address; + break; + case V4L2_PIX_FMT_YUV420: + if (address_y != NULL) + *address_y = address; + + address += EXYNOS_CAMERA_ALIGN(width * height); + + if (address_cb != NULL) + *address_cb = address; + + address += EXYNOS_CAMERA_ALIGN(width * height / 4); + + if (address_cr != NULL) + *address_cr = address; + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12T: + if (address_y != NULL) + *address_y = address; + + address += EXYNOS_CAMERA_ALIGN(width * height); + + if (address_cb != NULL) + *address_cb = address; + + if (address_cr != NULL) + *address_cr = address; + break; + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + default: + if (address_y != NULL) + *address_y = address; + + address += width * height; + + if (address_cb != NULL) + *address_cb = address; + + if (address_cr != NULL) + *address_cr = address; + break; + } +} diff --git a/camera/exynos_v4l2.c b/camera/exynos_v4l2.c new file mode 100644 index 0000000..2e7fdaf --- /dev/null +++ b/camera/exynos_v4l2.c @@ -0,0 +1,739 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski + * + * Based on crespo libcamera and exynos4 hal libcamera: + * Copyright 2008, The Android Open Source Project + * Copyright 2010, Samsung Electronics Co. LTD + * + * 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 3 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define LOG_TAG "exynos_v4l2" +#include + +#include "exynos_camera.h" + +int exynos_v4l2_init(struct exynos_camera *exynos_camera) +{ + int i; + + for (i = 0; i < EXYNOS_CAMERA_MAX_V4L2_NODES_COUNT; i++) + exynos_camera->v4l2_fds[i] = -1; + + return 0; +} + +int exynos_v4l2_index(struct exynos_camera *exynos_camera, int exynos_v4l2_id) +{ + int index; + int i; + + if (exynos_camera == NULL || exynos_camera->config == NULL || + exynos_camera->config->v4l2_nodes == NULL) + return -EINVAL; + + if (exynos_v4l2_id > exynos_camera->config->v4l2_nodes_count) + return -1; + + index = -1; + for (i = 0; i < exynos_camera->config->v4l2_nodes_count; i++) { + if (exynos_camera->config->v4l2_nodes[i].id == exynos_v4l2_id && + exynos_camera->config->v4l2_nodes[i].node != NULL) { + index = i; + } + } + + return index; +} + +int exynos_v4l2_fd(struct exynos_camera *exynos_camera, int exynos_v4l2_id) +{ + int index; + + if (exynos_camera == NULL) + return -EINVAL; + + index = exynos_v4l2_index(exynos_camera, exynos_v4l2_id); + if (index < 0) { + ALOGE("%s: Unable to get v4l2 index for id %d", __func__, exynos_v4l2_id); + return -1; + } + + return exynos_camera->v4l2_fds[index]; +} + +int exynos_v4l2_open(struct exynos_camera *exynos_camera, int exynos_v4l2_id) +{ + char *node; + int index; + int fd; + + if (exynos_camera == NULL || exynos_camera->config == NULL || + exynos_camera->config->v4l2_nodes == NULL) + return -EINVAL; + + index = exynos_v4l2_index(exynos_camera, exynos_v4l2_id); + if (index < 0) { + ALOGE("%s: Unable to get v4l2 node for id %d", __func__, exynos_v4l2_id); + return -1; + } + + node = exynos_camera->config->v4l2_nodes[index].node; + fd = open(node, O_RDWR); + if (fd < 0) { + ALOGE("%s: Unable to open v4l2 node for id %d", __func__, exynos_v4l2_id); + return -1; + } + + exynos_camera->v4l2_fds[index] = fd; + + return 0; +} + +void exynos_v4l2_close(struct exynos_camera *exynos_camera, int exynos_v4l2_id) +{ + int index; + + if (exynos_camera == NULL || exynos_camera->config == NULL || + exynos_camera->config->v4l2_nodes == NULL) + return; + + index = exynos_v4l2_index(exynos_camera, exynos_v4l2_id); + if (index < 0) { + ALOGE("%s: Unable to get v4l2 node for id %d", __func__, exynos_v4l2_id); + return; + } + + if (exynos_camera->v4l2_fds[index] >= 0) + close(exynos_camera->v4l2_fds[index]); + + exynos_camera->v4l2_fds[index] = -1; +} + +int exynos_v4l2_ioctl(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int request, void *data) +{ + int fd; + + if (exynos_camera == NULL) + return -EINVAL; + + fd = exynos_v4l2_fd(exynos_camera, exynos_v4l2_id); + if (fd < 0) { + ALOGE("%s: Unable to get v4l2 fd for id %d", __func__, exynos_v4l2_id); + return -1; + } + + return ioctl(fd, request, data); +} + +int exynos_v4l2_poll(struct exynos_camera *exynos_camera, int exynos_v4l2_id) +{ + struct pollfd events; + int fd; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + fd = exynos_v4l2_fd(exynos_camera, exynos_v4l2_id); + if (fd < 0) { + ALOGE("%s: Unable to get v4l2 fd for id %d", __func__, exynos_v4l2_id); + return -1; + } + + memset(&events, 0, sizeof(events)); + events.fd = fd; + events.events = POLLIN | POLLERR; + + rc = poll(&events, 1, 1000); + if (rc < 0 || events.revents & POLLERR) + return -1; + + return rc; +} + +int exynos_v4l2_qbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int type, int memory, int index, unsigned long userptr) +{ + struct v4l2_buffer buffer; + int rc; + + if (exynos_camera == NULL || index < 0) + return -EINVAL; + + memset(&buffer, 0, sizeof(buffer)); + buffer.type = type; + buffer.memory = memory; + buffer.index = index; + + if (userptr) + buffer.m.userptr = userptr; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_QBUF, &buffer); + return rc; +} + +int exynos_v4l2_qbuf_cap(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int index) +{ + return exynos_v4l2_qbuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_MEMORY_MMAP, index, 0); +} + +int exynos_v4l2_qbuf_out(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int index, unsigned long userptr) +{ + return exynos_v4l2_qbuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, + V4L2_MEMORY_USERPTR, index, userptr); +} + +int exynos_v4l2_dqbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int type, int memory) +{ + struct v4l2_buffer buffer; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + memset(&buffer, 0, sizeof(buffer)); + buffer.type = type; + buffer.memory = memory; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_DQBUF, &buffer); + if (rc < 0) + return rc; + + return buffer.index; +} + +int exynos_v4l2_dqbuf_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id) +{ + return exynos_v4l2_dqbuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_MEMORY_MMAP); +} + +int exynos_v4l2_dqbuf_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id) +{ + return exynos_v4l2_dqbuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, + V4L2_MEMORY_USERPTR); +} + +int exynos_v4l2_reqbufs(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type, int memory, int count) +{ + struct v4l2_requestbuffers requestbuffers; + int rc; + + if (exynos_camera == NULL || count < 0) + return -EINVAL; + + requestbuffers.type = type; + requestbuffers.count = count; + requestbuffers.memory = memory; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_REQBUFS, &requestbuffers); + if (rc < 0) + return rc; + + return requestbuffers.count; +} + +int exynos_v4l2_reqbufs_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int count) +{ + return exynos_v4l2_reqbufs(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_MEMORY_MMAP, count); +} + +int exynos_v4l2_reqbufs_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int count) +{ + return exynos_v4l2_reqbufs(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, + V4L2_MEMORY_USERPTR, count); +} + +int exynos_v4l2_querybuf(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type, int memory, int index) +{ + struct v4l2_buffer buffer; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + memset(&buffer, 0, sizeof(buffer)); + buffer.type = type; + buffer.memory = memory; + buffer.index = index; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_QUERYBUF, &buffer); + if (rc < 0) + return rc; + + return buffer.length; +} + +int exynos_v4l2_querybuf_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int index) +{ + return exynos_v4l2_querybuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_MEMORY_MMAP, index); +} + +int exynos_v4l2_querybuf_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int index) +{ + return exynos_v4l2_querybuf(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, + V4L2_MEMORY_USERPTR, index); +} + +int exynos_v4l2_querycap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int flags) +{ + struct v4l2_capability cap; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_QUERYCAP, &cap); + if (rc < 0) + return rc; + + if (!(cap.capabilities & flags)) + return -1; + + return 0; +} + +int exynos_v4l2_querycap_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id) +{ + return exynos_v4l2_querycap(exynos_camera, exynos_v4l2_id, V4L2_CAP_VIDEO_CAPTURE); +} + +int exynos_v4l2_querycap_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id) +{ + return exynos_v4l2_querycap(exynos_camera, exynos_v4l2_id, V4L2_CAP_VIDEO_OUTPUT); +} + +int exynos_v4l2_streamon(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type) +{ + enum v4l2_buf_type buf_type; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + buf_type = type; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_STREAMON, &buf_type); + return rc; +} + +int exynos_v4l2_streamon_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id) +{ + return exynos_v4l2_streamon(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE); +} + +int exynos_v4l2_streamon_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id) +{ + return exynos_v4l2_streamon(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT); +} + +int exynos_v4l2_streamoff(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type) +{ + enum v4l2_buf_type buf_type; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + buf_type = type; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_STREAMOFF, &buf_type); + return rc; +} + +int exynos_v4l2_streamoff_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id) +{ + return exynos_v4l2_streamoff(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE); +} + +int exynos_v4l2_streamoff_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id) +{ + return exynos_v4l2_streamoff(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT); +} + +int exynos_v4l2_g_fmt(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int type, int *width, int *height, int *fmt) +{ + struct v4l2_format format; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + format.type = type; + format.fmt.pix.field = V4L2_FIELD_NONE; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_G_FMT, &format); + if (rc < 0) + return rc; + + if (width != NULL) + *width = format.fmt.pix.width; + if (height != NULL) + *height = format.fmt.pix.height; + if (fmt != NULL) + *fmt = format.fmt.pix.pixelformat; + + return 0; +} + +int exynos_v4l2_g_fmt_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int *width, int *height, int *fmt) +{ + return exynos_v4l2_g_fmt(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, + width, height, fmt); +} + +int exynos_v4l2_g_fmt_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int *width, int *height, int *fmt) +{ + return exynos_v4l2_g_fmt(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, + width, height, fmt); +} + +int exynos_v4l2_s_fmt_pix(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type, int width, int height, int fmt, int field, + int priv) +{ + struct v4l2_format format; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + memset(&format, 0, sizeof(format)); + format.type = type; + format.fmt.pix.width = width; + format.fmt.pix.height = height; + format.fmt.pix.pixelformat = fmt; + format.fmt.pix.field = field; + format.fmt.pix.priv = priv; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_FMT, &format); + return rc; + + return 0; +} + +int exynos_v4l2_s_fmt_pix_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int width, int height, int fmt, int priv) +{ + return exynos_v4l2_s_fmt_pix(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, + width, height, fmt, V4L2_FIELD_NONE, priv); +} + +int exynos_v4l2_s_fmt_pix_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int width, int height, int fmt, int priv) +{ + return exynos_v4l2_s_fmt_pix(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, + width, height, fmt, V4L2_FIELD_NONE, priv); +} + +int exynos_v4l2_s_fmt_win(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int left, int top, int width, int height) +{ + struct v4l2_format format; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + memset(&format, 0, sizeof(format)); + format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + format.fmt.win.w.left = left; + format.fmt.win.w.top = top; + format.fmt.win.w.width = width; + format.fmt.win.w.height = height; + + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_FMT, &format); + return rc; +} + +int exynos_v4l2_enum_fmt(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int type, int fmt) +{ + struct v4l2_fmtdesc fmtdesc; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + fmtdesc.type = type; + fmtdesc.index = 0; + + do { + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_ENUM_FMT, &fmtdesc); + if (rc < 0) + return rc; + + if (fmtdesc.pixelformat == (unsigned int) fmt) + return 0; + + fmtdesc.index++; + } while (rc >= 0); + + return -1; +} + +int exynos_v4l2_enum_fmt_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int fmt) +{ + return exynos_v4l2_enum_fmt(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, + fmt); +} + +int exynos_v4l2_enum_fmt_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int fmt) +{ + return exynos_v4l2_enum_fmt(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, + fmt); +} + +int exynos_v4l2_enum_input(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int id) +{ + struct v4l2_input input; + int rc; + + if (exynos_camera == NULL || id < 0) + return -EINVAL; + + input.index = id; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_ENUMINPUT, &input); + if (rc < 0) + return rc; + + if (input.name[0] == '\0') + return -1; + + return 0; +} + +int exynos_v4l2_s_input(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int id) +{ + struct v4l2_input input; + int rc; + + if (exynos_camera == NULL || id < 0) + return -EINVAL; + + input.index = id; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_INPUT, &input); + return rc; +} + +int exynos_v4l2_g_ext_ctrls(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, struct v4l2_ext_control *control, int count) +{ + struct v4l2_ext_controls controls; + int rc; + + if (exynos_camera == NULL || control == NULL) + return -EINVAL; + + memset(&controls, 0, sizeof(controls)); + controls.ctrl_class = V4L2_CTRL_CLASS_CAMERA; + controls.count = count; + controls.controls = control; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_G_EXT_CTRLS, &controls); + return rc; +} + +int exynos_v4l2_g_ctrl(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int id, int *value) +{ + struct v4l2_control control; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + control.id = id; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_G_CTRL, &control); + if (rc < 0) + return rc; + + if (value != NULL) + *value = control.value; + + return 0; +} + +int exynos_v4l2_s_ctrl(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int id, int value) +{ + struct v4l2_control control; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + control.id = id; + control.value = value; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_CTRL, &control); + if (rc < 0) + return rc; + + return control.value; +} + +int exynos_v4l2_s_parm(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int type, struct v4l2_streamparm *streamparm) +{ + int rc; + + if (exynos_camera == NULL || streamparm == NULL) + return -EINVAL; + + streamparm->type = type; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_PARM, streamparm); + return rc; +} + +int exynos_v4l2_s_parm_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, struct v4l2_streamparm *streamparm) +{ + return exynos_v4l2_s_parm(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, + streamparm); +} + +int exynos_v4l2_s_parm_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, struct v4l2_streamparm *streamparm) +{ + return exynos_v4l2_s_parm(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, + streamparm); +} + +int exynos_v4l2_s_crop(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + int type, int left, int top, int width, int height) +{ + struct v4l2_crop crop; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + crop.type = type; + crop.c.left = left; + crop.c.top = top; + crop.c.width = width; + crop.c.height = height; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_CROP, &crop); + return rc; +} + +int exynos_v4l2_s_crop_cap(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int left, int top, int width, int height) +{ + return exynos_v4l2_s_crop(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, + left, top, width, height); +} + +int exynos_v4l2_s_crop_out(struct exynos_camera *exynos_camera, + int exynos_v4l2_id, int left, int top, int width, int height) +{ + return exynos_v4l2_s_crop(exynos_camera, exynos_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, + left, top, width, height); +} + +int exynos_v4l2_g_fbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + void **base, int *width, int *height, int *fmt) +{ + struct v4l2_framebuffer framebuffer; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_G_FBUF, &framebuffer); + if (rc < 0) + return rc; + + if (base != NULL) + *base = framebuffer.base; + if (width != NULL) + *width = framebuffer.fmt.width; + if (height != NULL) + *height = framebuffer.fmt.height; + if (fmt != NULL) + *fmt = framebuffer.fmt.pixelformat; + + return 0; +} + +int exynos_v4l2_s_fbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, + void *base, int width, int height, int fmt) +{ + struct v4l2_framebuffer framebuffer; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + memset(&framebuffer, 0, sizeof(framebuffer)); + framebuffer.base = base; + framebuffer.fmt.width = width; + framebuffer.fmt.height = height; + framebuffer.fmt.pixelformat = fmt; + + rc = exynos_v4l2_ioctl(exynos_camera, exynos_v4l2_id, VIDIOC_S_FBUF, &framebuffer); + return rc; +} diff --git a/camera/exynos_v4l2_output.c b/camera/exynos_v4l2_output.c new file mode 100644 index 0000000..2a39fd2 --- /dev/null +++ b/camera/exynos_v4l2_output.c @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski + * + * 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 3 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define LOG_TAG "exynos_v4l2_output" +#include + +#include "exynos_camera.h" + +int exynos_v4l2_output_start(struct exynos_camera *exynos_camera, + struct exynos_v4l2_output *output) +{ + int width, height, format; + int buffer_width, buffer_height, buffer_format; + camera_memory_t *memory = NULL; + int memory_address, memory_size; +#ifdef EXYNOS_ION + int memory_ion_fd = -1; +#endif + int buffers_count, buffer_length; + int v4l2_id; + int value; + int fd; + int rc; + int i; + + if (exynos_camera == NULL || output == NULL) + return -EINVAL; + +// ALOGD("%s()", __func__); + + if (output->enabled) { + ALOGE("Output was already started"); + return -1; + } + + width = output->width; + height = output->height; + format = output->format; + + buffer_width = output->buffer_width; + buffer_height = output->buffer_height; + buffer_format = output->buffer_format; + + v4l2_id = output->v4l2_id; + + buffers_count = output->buffers_count; + if (buffers_count <= 0) { + ALOGE("%s: Invalid buffers count: %d", __func__, buffers_count); + goto error; + } + + buffer_length = exynos_camera_buffer_length(width, height, format); + + rc = exynos_v4l2_open(exynos_camera, v4l2_id); + if (rc < 0) { + ALOGE("%s: Unable to open v4l2 device", __func__); + goto error; + } + + rc = exynos_v4l2_querycap_out(exynos_camera, v4l2_id); + if (rc < 0) { + ALOGE("%s: Unable to query capabilities", __func__); + goto error; + } + + rc = exynos_v4l2_g_fmt_out(exynos_camera, v4l2_id, NULL, NULL, NULL); + if (rc < 0) { + ALOGE("%s: Unable to get format", __func__); + goto error; + } + + value = 0; + rc = exynos_v4l2_g_ctrl(exynos_camera, v4l2_id, V4L2_CID_RESERVED_MEM_BASE_ADDR, &value); + if (rc < 0) { + ALOGE("%s: Unable to get address", __func__); + goto error; + } + + memory_address = value; + + value = 0; + rc = exynos_v4l2_g_ctrl(exynos_camera, v4l2_id, V4L2_CID_RESERVED_MEM_SIZE, &value); + if (rc < 0) { + ALOGE("%s: Unable to get size", __func__); + goto error; + } + + memory_size = value * 1024; + + rc = exynos_v4l2_s_ctrl(exynos_camera, v4l2_id, V4L2_CID_OVLY_MODE, FIMC_OVLY_NONE_MULTI_BUF); + if (rc < 0) { + ALOGE("%s: Unable to set overlay mode", __func__); + goto error; + } + + rc = exynos_v4l2_s_fmt_pix_out(exynos_camera, v4l2_id, buffer_width, buffer_height, buffer_format, 0); + if (rc < 0) { + ALOGE("%s: Unable to set output pixel format!", __func__); + goto error; + } + + rc = exynos_v4l2_s_crop_out(exynos_camera, v4l2_id, 0, 0, buffer_width, buffer_height); + if (rc < 0) { + ALOGE("%s: Unable to crop", __func__); + goto error; + } + + rc = exynos_v4l2_reqbufs_out(exynos_camera, v4l2_id, 1); + if (rc < 0) { + ALOGE("%s: Unable to request buffers", __func__); + goto error; + } + + if (memory_address != 0 && memory_address != (int) 0xffffffff && memory_size >= buffer_length) { + for (i = buffers_count; i > 0; i--) { + if (buffer_length * i < memory_size) + break; + } + + // This should never happen + if (i == 0) + goto error; + + buffers_count = i; + ALOGD("Found %d buffers available for output!", buffers_count); + + if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { + fd = exynos_v4l2_fd(exynos_camera, v4l2_id); + if (fd < 0) { + ALOGE("%s: Unable to get v4l2 fd for id %d", __func__, v4l2_id); + goto error; + } + + memory = exynos_camera->callbacks.request_memory(fd, buffer_length, buffers_count, exynos_camera->callbacks.user); + if (memory == NULL || memory->data == NULL || memory->data == MAP_FAILED) { + ALOGE("%s: Unable to request memory", __func__); + goto error; + } + } else { + ALOGE("%s: No memory request function!", __func__); + goto error; + } + } else { +#ifdef EXYNOS_ION + memory_ion_fd = exynos_ion_alloc(exynos_camera, buffers_count * buffer_length); + if (memory_ion_fd < 0) { + ALOGE("%s: Unable to alloc ION memory", __func__); + goto error; + } + + if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { + memory = exynos_camera->callbacks.request_memory(memory_ion_fd, buffer_length, buffers_count, exynos_camera->callbacks.user); + if (memory == NULL || memory->data == NULL || memory->data == MAP_FAILED) { + ALOGE("%s: Unable to request memory", __func__); + goto error; + } + } else { + ALOGE("%s: No memory request function!", __func__); + goto error; + } + + memory_address = exynos_ion_phys(exynos_camera, memory_ion_fd); +#else + ALOGE("%s: Unable to find memory", __func__); + goto error; +#endif + } + + output->memory = memory; + output->memory_address = memory_address; +#ifdef EXYNOS_ION + output->memory_ion_fd = memory_ion_fd; +#endif + output->memory_index = 0; + output->buffers_count = buffers_count; + output->buffer_length = buffer_length; + + output->enabled = 1; + + rc = 0; + goto complete; + +error: + if (memory != NULL && memory->release != NULL) { + memory->release(memory); + output->memory = NULL; + } + +#ifdef EXYNOS_ION + if (memory_ion_fd >= 0) + exynos_ion_free(exynos_camera, memory_ion_fd); +#endif + + exynos_v4l2_close(exynos_camera, v4l2_id); + + rc = -1; + +complete: + return rc; +} + +void exynos_v4l2_output_stop(struct exynos_camera *exynos_camera, + struct exynos_v4l2_output *output) +{ + int v4l2_id; + int rc; + + if (exynos_camera == NULL || output == NULL) + return; + +// ALOGD("%s()", __func__); + + if (!output->enabled) { + ALOGE("Output was already stopped"); + return; + } + + v4l2_id = output->v4l2_id; + + rc = exynos_v4l2_reqbufs_out(exynos_camera, v4l2_id, 0); + if (rc < 0) + ALOGE("%s: Unable to request buffers", __func__); + + if (output->memory != NULL && output->memory->release != NULL) { + output->memory->release(output->memory); + output->memory = NULL; + } + +#ifdef EXYNOS_ION + if (output->memory_ion_fd >= 0) { + exynos_ion_free(exynos_camera, output->memory_ion_fd); + output->memory_ion_fd = -1; + } +#endif + + exynos_v4l2_close(exynos_camera, v4l2_id); + + output->enabled = 0; +} + +int exynos_v4l2_output(struct exynos_camera *exynos_camera, + struct exynos_v4l2_output *output, int buffer_address) +{ + struct fimc_buf fimc_buffer; + void *fb_base; + int width, height, format; + int buffer_width, buffer_height, buffer_format; + int buffer_length; + int address; + int v4l2_id; + int rc; + + if (exynos_camera == NULL || output == NULL) + return -EINVAL; + +// ALOGD("%s()", __func__); + + if (!output->enabled) { + ALOGE("Output was not started"); + return -1; + } + + width = output->width; + height = output->height; + format = output->format; + + buffer_width = output->buffer_width; + buffer_height = output->buffer_height; + buffer_format = output->buffer_format; + + buffer_length = output->buffer_length; + v4l2_id = output->v4l2_id; + + rc = exynos_v4l2_g_fbuf(exynos_camera, v4l2_id, &fb_base, NULL, NULL, NULL); + if (rc < 0) { + ALOGE("%s: Unable to get fbuf", __func__); + goto error; + } + + rc = exynos_v4l2_s_fbuf(exynos_camera, v4l2_id, fb_base, width, height, format); + if (rc < 0) { + ALOGE("%s: Unable to set fbuf", __func__); + goto error; + } + + memset(&fimc_buffer, 0, sizeof(fimc_buffer)); + + address = output->memory_address + buffer_length * output->memory_index; + + exynos_camera_yuv_planes(width, height, format, address, (int *) &fimc_buffer.base[0], (int *) &fimc_buffer.base[1], (int *) &fimc_buffer.base[2]); + + rc = exynos_v4l2_s_ctrl(exynos_camera, v4l2_id, V4L2_CID_DST_INFO, (int) &fimc_buffer); + if (rc < 0) { + ALOGE("%s: Unable to set dst info", __func__); + goto error; + } + + rc = exynos_v4l2_s_fmt_win(exynos_camera, v4l2_id, 0, 0, width, height); + if (rc < 0) { + ALOGE("%s: Unable to set overlay win", __func__); + goto error; + } + + rc = exynos_v4l2_streamon_out(exynos_camera, v4l2_id); + if (rc < 0) { + ALOGE("%s: Unable to start stream", __func__); + goto error; + } + + memset(&fimc_buffer, 0, sizeof(fimc_buffer)); + + exynos_camera_yuv_planes(buffer_width, buffer_height, buffer_format, buffer_address, (int *) &fimc_buffer.base[0], (int *) &fimc_buffer.base[1], (int *) &fimc_buffer.base[2]); + + rc = exynos_v4l2_qbuf_out(exynos_camera, v4l2_id, 0, (unsigned long) &fimc_buffer); + if (rc < 0) { + ALOGE("%s: Unable to queue buffer", __func__); + goto error; + } + + rc = exynos_v4l2_dqbuf_out(exynos_camera, v4l2_id); + if (rc < 0) { + ALOGE("%s: Unable to dequeue buffer", __func__); + goto error; + } + + rc = exynos_v4l2_streamoff_out(exynos_camera, v4l2_id); + if (rc < 0) { + ALOGE("%s: Unable to stop stream", __func__); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +int exynos_v4l2_output_release(struct exynos_camera *exynos_camera, + struct exynos_v4l2_output *output) +{ + int buffers_count; + int memory_index; + + if (exynos_camera == NULL || output == NULL) + return -EINVAL; + +// ALOGD("%s()", __func__); + + buffers_count = output->buffers_count; + memory_index = output->memory_index; + + memory_index++; + output->memory_index = memory_index % buffers_count; + + return 0; +} diff --git a/camera/include/linux/fimc.h b/camera/include/linux/fimc.h new file mode 100644 index 0000000..40deab0 --- /dev/null +++ b/camera/include/linux/fimc.h @@ -0,0 +1,381 @@ +/* linux/drivers/media/video/samsung/fimc/fimc.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Header file for Samsung Camera Interface (FIMC) 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. +*/ + + +#ifndef __FIMC_H +#define __FIMC_H __FILE__ + +typedef unsigned int dma_addr_t; +typedef __u32 u32; +typedef __s32 s32; + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_BUSFREQ_OPP) || defined(CONFIG_BUSFREQ_LOCK_WRAPPER) +#include +#endif +#include +#include +#include +#endif + +#ifdef CONFIG_PM_RUNTIME +#include +#endif + +#define FIMC_NAME "s3c-fimc" +#define FIMC_CMA_NAME "fimc" + +#define FIMC_CORE_CLK "sclk_fimc" +#define FIMC_CLK_RATE 166750000 +#define EXYNOS_BUSFREQ_NAME "exynos-busfreq" + +#if defined(CONFIG_ARCH_EXYNOS4) +#define FIMC_DEVICES 4 +#define FIMC_PHYBUFS 32 +#define FIMC_MAXCAMS 7 +#else +#define FIMC_DEVICES 3 +#define FIMC_PHYBUFS 4 +#define FIMC_MAXCAMS 5 +#endif + +#define FIMC_SUBDEVS 3 +#define FIMC_OUTBUFS 3 +#define FIMC_INQUEUES 10 +#define FIMC_MAX_CTXS 4 +#define FIMC_TPID 3 +#define FIMC_CAPBUFS 32 +#define FIMC_ONESHOT_TIMEOUT 200 +#define FIMC_DQUEUE_TIMEOUT 1000 + +#define FIMC_FIFOOFF_CNT 1000000 /* Sufficiently big value for stop */ + +#define FORMAT_FLAGS_PACKED 0x1 +#define FORMAT_FLAGS_PLANAR 0x2 + +#define FIMC_ADDR_Y 0 +#define FIMC_ADDR_CB 1 +#define FIMC_ADDR_CR 2 + +#define FIMC_HD_WIDTH 1280 +#define FIMC_HD_HEIGHT 720 + +#define FIMC_FHD_WIDTH 1920 +#define FIMC_FHD_HEIGHT 1080 + +#define FIMC_MMAP_IDX -1 +#define FIMC_USERPTR_IDX -2 + +#define FIMC_HCLK 0 +#define FIMC_SCLK 1 +#define CSI_CH_0 0 +#define CSI_CH_1 1 +#if defined(CONFIG_VIDEO_FIMC_FIFO) +#define FIMC_OVLY_MODE FIMC_OVLY_FIFO +#elif defined(CONFIG_VIDEO_FIMC_DMA_AUTO) +#define FIMC_OVLY_MODE FIMC_OVLY_DMA_AUTO +#endif + +#define PINGPONG_2ADDR_MODE +#if defined(PINGPONG_2ADDR_MODE) +#define FIMC_PINGPONG 2 +#endif + +#define check_bit(data, loc) ((data) & (0x1<<(loc))) +#define FRAME_SEQ 0xf + +#define fimc_cam_use ((pdata->use_cam) ? 1 : 0) + +#define L2_FLUSH_ALL SZ_1M +#define L1_FLUSH_ALL SZ_64K + +/* + * ENUMERATIONS +*/ +enum fimc_status { + FIMC_READY_OFF = 0x00, + FIMC_STREAMOFF = 0x01, + FIMC_READY_ON = 0x02, + FIMC_STREAMON = 0x03, + FIMC_STREAMON_IDLE = 0x04, /* oneshot mode */ + FIMC_OFF_SLEEP = 0x05, + FIMC_ON_SLEEP = 0x06, + FIMC_ON_IDLE_SLEEP = 0x07, /* oneshot mode */ + FIMC_READY_RESUME = 0x08, + FIMC_BUFFER_STOP = 0x09, + FIMC_BUFFER_START = 0x0A, +}; + +enum fimc_fifo_state { + FIFO_CLOSE, + FIFO_SLEEP, +}; + +enum fimc_fimd_state { + FIMD_OFF, + FIMD_ON, +}; + +enum fimc_rot_flip { + FIMC_XFLIP = 0x01, + FIMC_YFLIP = 0x02, + FIMC_ROT = 0x10, +}; + +enum fimc_input { + FIMC_SRC_CAM, + FIMC_SRC_MSDMA, +}; + +enum fimc_overlay_mode { + FIMC_OVLY_NOT_FIXED = 0x0, /* Overlay mode isn't fixed. */ + FIMC_OVLY_FIFO = 0x1, /* Non-destructive Overlay with FIFO */ + FIMC_OVLY_DMA_AUTO = 0x2, /* Non-destructive Overlay with DMA */ + FIMC_OVLY_DMA_MANUAL = 0x3, /* Non-destructive Overlay with DMA */ + FIMC_OVLY_NONE_SINGLE_BUF = 0x4, /* Destructive Overlay with DMA single destination buffer */ + FIMC_OVLY_NONE_MULTI_BUF = 0x5, /* Destructive Overlay with DMA multiple dstination buffer */ +}; + +enum fimc_autoload { + FIMC_AUTO_LOAD, + FIMC_ONE_SHOT, +}; + +enum fimc_log { + FIMC_LOG_DEBUG = 0x1000, + FIMC_LOG_INFO_L2 = 0x0200, + FIMC_LOG_INFO_L1 = 0x0100, + FIMC_LOG_WARN = 0x0010, + FIMC_LOG_ERR = 0x0001, +}; + +enum fimc_range { + FIMC_RANGE_NARROW = 0x0, + FIMC_RANGE_WIDE = 0x1, +}; + +enum fimc_pixel_format_type{ + FIMC_RGB, + FIMC_YUV420, + FIMC_YUV422, + FIMC_YUV444, +}; + +enum fimc_framecnt_seq { + FIMC_FRAMECNT_SEQ_DISABLE, + FIMC_FRAMECNT_SEQ_ENABLE, +}; + +enum fimc_sysmmu_flag { + FIMC_SYSMMU_OFF, + FIMC_SYSMMU_ON, +}; + +enum fimc_id { + FIMC0 = 0x0, + FIMC1 = 0x1, + FIMC2 = 0x2, + FIMC3 = 0x3, +}; + +enum fimc_power_status { + FIMC_POWER_OFF, + FIMC_POWER_ON, + FIMC_POWER_SUSPEND, +}; + +enum cam_mclk_status { + CAM_MCLK_OFF, + CAM_MCLK_ON, +}; + +/* + * STRUCTURES +*/ + +/* for reserved memory */ +struct fimc_meminfo { + dma_addr_t base; /* buffer base */ + size_t size; /* total length */ + dma_addr_t curr; /* current addr */ + dma_addr_t vaddr_base; /* buffer base */ + dma_addr_t vaddr_curr; /* current addr */ +}; + +struct fimc_buf { + dma_addr_t base[3]; + size_t length[3]; +}; + +struct fimc_overlay_buf { + u32 vir_addr[3]; + size_t size[3]; + u32 phy_addr[3]; +}; + +struct fimc_overlay { + enum fimc_overlay_mode mode; + struct fimc_overlay_buf buf; + s32 req_idx; +}; + +/* for output overlay device */ +struct fimc_idx { + int ctx; + int idx; +}; + +struct fimc_ctx_idx { + struct fimc_idx prev; + struct fimc_idx active; + struct fimc_idx next; +}; + +/* scaler abstraction: local use recommended */ +struct fimc_scaler { + u32 bypass; + u32 hfactor; + u32 vfactor; + u32 pre_hratio; + u32 pre_vratio; + u32 pre_dst_width; + u32 pre_dst_height; + u32 scaleup_h; + u32 scaleup_v; + u32 main_hratio; + u32 main_vratio; + u32 real_width; + u32 real_height; + u32 shfactor; + u32 skipline; +}; + +struct s3cfb_user_window { + int x; + int y; +}; + +enum s3cfb_data_path_t { + DATA_PATH_FIFO = 0, + DATA_PATH_DMA = 1, + DATA_PATH_IPC = 2, +}; + +enum s3cfb_mem_owner_t { + DMA_MEM_NONE = 0, + DMA_MEM_FIMD = 1, + DMA_MEM_OTHER = 2, +}; +#define S3CFB_WIN_OFF_ALL _IO('F', 202) +#define S3CFB_WIN_POSITION _IOW('F', 203, struct s3cfb_user_window) +#define S3CFB_GET_LCD_WIDTH _IOR('F', 302, int) +#define S3CFB_GET_LCD_HEIGHT _IOR('F', 303, int) +#define S3CFB_SET_WRITEBACK _IOW('F', 304, u32) +#define S3CFB_SET_WIN_ON _IOW('F', 305, u32) +#define S3CFB_SET_WIN_OFF _IOW('F', 306, u32) +#define S3CFB_SET_WIN_PATH _IOW('F', 307, enum s3cfb_data_path_t) +#define S3CFB_SET_WIN_ADDR _IOW('F', 308, unsigned long) +#define S3CFB_SET_WIN_MEM _IOW('F', 309, enum s3cfb_mem_owner_t) +/* ------------------------------------------------------------------------ */ + +struct fimc_fbinfo { + struct fb_fix_screeninfo *fix; + struct fb_var_screeninfo *var; + int lcd_hres; + int lcd_vres; + u32 is_enable; + /* lcd fifo control */ + + int (*open_fifo)(int id, int ch, int (*do_priv)(void *), void *param); + int (*close_fifo)(int id, int (*do_priv)(void *), void *param); +}; + +struct fimc_limit { + u32 pre_dst_w; + u32 bypass_w; + u32 trg_h_no_rot; + u32 trg_h_rot; + u32 real_w_no_rot; + u32 real_h_rot; +}; + +enum FIMC_EFFECT_FIN { + FIMC_EFFECT_FIN_BYPASS = 0, + FIMC_EFFECT_FIN_ARBITRARY_CBCR, + FIMC_EFFECT_FIN_NEGATIVE, + FIMC_EFFECT_FIN_ART_FREEZE, + FIMC_EFFECT_FIN_EMBOSSING, + FIMC_EFFECT_FIN_SILHOUETTE, +}; + + +struct fimc_effect { + int ie_on; + int ie_after_sc; + enum FIMC_EFFECT_FIN fin; + int pat_cb; + int pat_cr; +}; + +/* debug macro */ +#define FIMC_LOG_DEFAULT (FIMC_LOG_WARN | FIMC_LOG_ERR) + +#define FIMC_DEBUG(fmt, ...) \ + do { \ + printk(KERN_DEBUG FIMC_NAME "%d: " \ + fmt, ctrl->id, ##__VA_ARGS__); \ + } while (0) + +#define FIMC_INFO_L2(fmt, ...) \ + do { \ + printk(KERN_INFO FIMC_NAME "%d: " \ + fmt, ctrl->id, ##__VA_ARGS__); \ + } while (0) + +#define FIMC_INFO_L1(fmt, ...) \ + do { \ + printk(KERN_INFO FIMC_NAME "%d: " \ + fmt, ctrl->id, ##__VA_ARGS__); \ + } while (0) + +#define FIMC_WARN(fmt, ...) \ + do { \ + printk(KERN_WARNING FIMC_NAME "%d: " \ + fmt, ctrl->id, ##__VA_ARGS__); \ + } while (0) + + +#define FIMC_ERROR(fmt, ...) \ + do { \ + printk(KERN_ERR FIMC_NAME "%d: " \ + fmt, ctrl->id, ##__VA_ARGS__); \ + } while (0) + + +#define fimc_dbg(fmt, ...) FIMC_DEBUG(fmt, ##__VA_ARGS__) +#define fimc_info2(fmt, ...) FIMC_INFO_L2(fmt, ##__VA_ARGS__) +#define fimc_info1(fmt, ...) FIMC_INFO_L1(fmt, ##__VA_ARGS__) +#define fimc_warn(fmt, ...) FIMC_WARN(fmt, ##__VA_ARGS__) +#define fimc_err(fmt, ...) FIMC_ERROR(fmt, ##__VA_ARGS__) + +#endif /* __FIMC_H */ diff --git a/camera/include/linux/ion.h b/camera/include/linux/ion.h new file mode 100644 index 0000000..29dba57 --- /dev/null +++ b/camera/include/linux/ion.h @@ -0,0 +1,449 @@ +/* + * include/linux/ion.h + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef _LINUX_ION_H +#define _LINUX_ION_H + +#include + +#define CONFIG_ION_EXYNOS + +/* This should be removed some day when phys_addr_t's are fully + plumbed in the kernel, and all instances of ion_phys_addr_t should + be converted to phys_addr_t. For the time being many kernel interfaces + do not accept phys_addr_t's that would have to */ +#define ion_phys_addr_t unsigned long + +struct ion_handle; +/** + * enum ion_heap_types - list of all possible types of heaps + * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc + * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc + * @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved + * carveout heap, allocations are physically + * contiguous + * @ION_HEAP_END: helper for iterating over heaps + */ +enum ion_heap_type { + ION_HEAP_TYPE_SYSTEM, + ION_HEAP_TYPE_SYSTEM_CONTIG, + ION_HEAP_TYPE_CARVEOUT, + ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always + are at the end of this enum */ +#ifdef CONFIG_ION_EXYNOS + ION_HEAP_TYPE_EXYNOS_CONTIG, + ION_HEAP_TYPE_EXYNOS, + ION_HEAP_TYPE_EXYNOS_USER, +#endif + ION_NUM_HEAPS, +}; + +#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM) +#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG) +#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT) + +#ifdef CONFIG_ION_EXYNOS +#define ION_HEAP_EXYNOS_MASK (1 << ION_HEAP_TYPE_EXYNOS) +#define ION_HEAP_EXYNOS_CONTIG_MASK (1 << ION_HEAP_TYPE_EXYNOS_CONTIG) +#define ION_HEAP_EXYNOS_USER_MASK (1 << ION_HEAP_TYPE_EXYNOS_USER) +#define ION_EXYNOS_NONCACHE_MASK (1 << (BITS_PER_LONG - 2)) +#define ION_EXYNOS_WRITE_MASK (1 << (BITS_PER_LONG - 1)) +#endif + +#ifdef __KERNEL__ +struct ion_device; +struct ion_heap; +struct ion_mapper; +struct ion_client; +struct ion_buffer; + +/** + * struct ion_platform_heap - defines a heap in the given platform + * @type: type of the heap from ion_heap_type enum + * @id: unique identifier for heap. When allocating (lower numbers + * will be allocated from first) + * @name: used for debug purposes + * @base: base address of heap in physical memory if applicable + * @size: size of the heap in bytes if applicable + * + * Provided by the board file. + */ +struct ion_platform_heap { + enum ion_heap_type type; + unsigned int id; + const char *name; + ion_phys_addr_t base; + size_t size; +}; + +/** + * struct ion_platform_data - array of platform heaps passed from board file + * @nr: number of structures in the array + * @heaps: array of platform_heap structions + * + * Provided by the board file in the form of platform data to a platform device. + */ +struct ion_platform_data { + int nr; + struct ion_platform_heap heaps[]; +}; + +/** + * ion_client_create() - allocate a client and returns it + * @dev: the global ion device + * @heap_mask: mask of heaps this client can allocate from + * @name: used for debugging + */ +struct ion_client *ion_client_create(struct ion_device *dev, + unsigned int heap_mask, const char *name); + +/** + * ion_client_destroy() - free's a client and all it's handles + * @client: the client + * + * Free the provided client and all it's resources including + * any handles it is holding. + */ +void ion_client_destroy(struct ion_client *client); + +/** + * ion_get_client() - obtain a user client from file descriptor from user + * @fd: the user client created by the request from user. This is + * passed from user. + * + * This function is requested by the device drivers that implement V4L2 and VB2 + * interfaces. Those device drivers just obtains virtual address of a buffer + * even though it is allocated and mapped by ION. While they can retrieve the + * handle of the buffer, they are unable to access it because they do not know + * what client the handle belongs to. + * Note that the client obtained by this function is not released until + * ion_put_client() is called and the client is given. + */ +struct ion_client *ion_get_user_client(unsigned int fd_client); + +/** + * ion_put_client() - release the user client obtained by ion_get_client() + * @client - The user client to release. + */ +void ion_put_user_client(struct ion_client *user_client); + +/** + * ion_alloc - allocate ion memory + * @client: the client + * @len: size of the allocation + * @align: requested allocation alignment, lots of hardware blocks have + * alignment requirements of some kind + * @flags: mask of heaps to allocate from, if multiple bits are set + * heaps will be tried in order from lowest to highest order bit + * + * Allocate memory in one of the heaps provided in heap mask and return + * an opaque handle to it. + */ +struct ion_handle *ion_alloc(struct ion_client *client, size_t len, + size_t align, unsigned int flags); + +/** + * ion_free - free a handle + * @client: the client + * @handle: the handle to free + * + * Free the provided handle. + */ +void ion_free(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_phys - returns the physical address and len of a handle + * @client: the client + * @handle: the handle + * @addr: a pointer to put the address in + * @len: a pointer to put the length in + * + * This function queries the heap for a particular handle to get the + * handle's physical address. It't output is only correct if + * a heap returns physically contiguous memory -- in other cases + * this api should not be implemented -- ion_map_dma should be used + * instead. Returns -EINVAL if the handle is invalid. This has + * no implications on the reference counting of the handle -- + * the returned value may not be valid if the caller is not + * holding a reference. + */ +int ion_phys(struct ion_client *client, struct ion_handle *handle, + ion_phys_addr_t *addr, size_t *len); + +/** + * ion_map_kernel - create mapping for the given handle + * @client: the client + * @handle: handle to map + * + * Map the given handle into the kernel and return a kernel address that + * can be used to access this address. + */ +void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_unmap_kernel() - destroy a kernel mapping for a handle + * @client: the client + * @handle: handle to unmap + */ +void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_map_dma - create a dma mapping for a given handle + * @client: the client + * @handle: handle to map + * + * Return an sglist describing the given handle + */ +struct scatterlist *ion_map_dma(struct ion_client *client, + struct ion_handle *handle); + +/** + * ion_unmap_dma() - destroy a dma mapping for a handle + * @client: the client + * @handle: handle to unmap + */ +void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_share() - given a handle, obtain a buffer to pass to other clients + * @client: the client + * @handle: the handle to share + * + * Given a handle, return a buffer, which exists in a global name + * space, and can be passed to other clients. Should be passed into ion_import + * to obtain a new handle for this buffer. + * + * NOTE: This function does do not an extra reference. The burden is on the + * caller to make sure the buffer doesn't go away while it's being passed to + * another client. That is, ion_free should not be called on this handle until + * the buffer has been imported into the other client. + */ +struct ion_buffer *ion_share(struct ion_client *client, + struct ion_handle *handle); + +/** + * ion_import() - given an buffer in another client, import it + * @client: this blocks client + * @buffer: the buffer to import (as obtained from ion_share) + * + * Given a buffer, add it to the client and return the handle to use to refer + * to it further. This is called to share a handle from one kernel client to + * another. + */ +struct ion_handle *ion_import(struct ion_client *client, + struct ion_buffer *buffer); + +/** + * ion_share_fd() - given a handle, obtain a buffer(fd) to pass to userspace + * @client: the client + * @handle: the handle to share + * + * Given a handle, return a fd of a buffer which can be passed to userspace. + * Should be passed into userspace or ion_import_fd to obtain a new handle for + * this buffer. + */ +int ion_share_fd(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_import_fd() - given an fd obtained via ION_IOC_SHARE ioctl, import it + * @client: this blocks client + * @fd: the fd + * + * A helper function for drivers that will be recieving ion buffers shared + * with them from userspace. These buffers are represented by a file + * descriptor obtained as the return from the ION_IOC_SHARE ioctl. + * This function coverts that fd into the underlying buffer, and returns + * the handle to use to refer to it further. + */ +struct ion_handle *ion_import_fd(struct ion_client *client, int fd); + +/** + * ion_import_uva() - given a virtual address from user, that is mmapped on an + * fd obtained via ION_IOCTL_SHARE ioctl, import it + * @client: this blocks client + * @uva: virtual address in userspace. + * @offset: How many bytes are distant from the beginning of the ION buffer + * + * A helper function for drivers that will be recieving ion buffers shared + * with them from userspace. These buffers are represented by a virtual + * address that is mmaped on a file descriptor obtained as the return from the + * ION_IOC_SHARE ioctl. + * This function does same job with ion_import_fd(). + */ +struct ion_handle *ion_import_uva(struct ion_client *client, unsigned long uva, + off_t *offset); + +#ifdef CONFIG_ION_EXYNOS +struct ion_handle *ion_exynos_get_user_pages(struct ion_client *client, + unsigned long uvaddr, size_t len, unsigned int flags); +#else +#include +static inline struct ion_handle *ion_exynos_get_user_pages( + struct ion_client *client, unsigned long uvaddr, + size_t len, unsigned int flags) +{ + return ERR_PTR(-ENOSYS); +} +#endif + +#endif /* __KERNEL__ */ + +/** + * DOC: Ion Userspace API + * + * create a client by opening /dev/ion + * most operations handled via following ioctls + * + */ + +/** + * struct ion_allocation_data - metadata passed from userspace for allocations + * @len: size of the allocation + * @align: required alignment of the allocation + * @flags: flags passed to heap + * @handle: pointer that will be populated with a cookie to use to refer + * to this allocation + * + * Provided by userspace as an argument to the ioctl + */ +struct ion_allocation_data { + size_t len; + size_t align; + unsigned int flags; + struct ion_handle *handle; +}; + +/** + * struct ion_fd_data - metadata passed to/from userspace for a handle/fd pair + * @handle: a handle + * @fd: a file descriptor representing that handle + * + * For ION_IOC_SHARE or ION_IOC_MAP userspace populates the handle field with + * the handle returned from ion alloc, and the kernel returns the file + * descriptor to share or map in the fd field. For ION_IOC_IMPORT, userspace + * provides the file descriptor and the kernel returns the handle. + */ +struct ion_fd_data { + struct ion_handle *handle; + int fd; +}; + +/** + * struct ion_handle_data - a handle passed to/from the kernel + * @handle: a handle + */ +struct ion_handle_data { + struct ion_handle *handle; +}; + +/** + * struct ion_custom_data - metadata passed to/from userspace for a custom ioctl + * @cmd: the custom ioctl function to call + * @arg: additional data to pass to the custom ioctl, typically a user + * pointer to a predefined structure + * + * This works just like the regular cmd and arg fields of an ioctl. + */ +struct ion_custom_data { + unsigned int cmd; + unsigned long arg; +}; + +enum ION_MSYNC_TYPE { + IMSYNC_DEV_TO_READ = 0, + IMSYNC_DEV_TO_WRITE = 1, + IMSYNC_DEV_TO_RW = 2, + IMSYNC_BUF_TYPES_MASK = 3, + IMSYNC_BUF_TYPES_NUM = 4, + IMSYNC_SYNC_FOR_DEV = 0x10000, + IMSYNC_SYNC_FOR_CPU = 0x20000, +}; + +struct ion_msync_data { + enum ION_MSYNC_TYPE dir; + int fd_buffer; + size_t size; + off_t offset; +}; + +struct ion_phys_data { + int fd_buffer; + ion_phys_addr_t phys; + size_t size; +}; + +enum ION_EXYNOS_CUSTOM_CMD { + ION_EXYNOS_CUSTOM_MSYNC, + ION_EXYNOS_CUSTOM_PHYS +}; + +#define ION_IOC_MAGIC 'I' + +/** + * DOC: ION_IOC_ALLOC - allocate memory + * + * Takes an ion_allocation_data struct and returns it with the handle field + * populated with the opaque handle for the allocation. + */ +#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ + struct ion_allocation_data) + +/** + * DOC: ION_IOC_FREE - free memory + * + * Takes an ion_handle_data struct and frees the handle. + */ +#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data) + +/** + * DOC: ION_IOC_MAP - get a file descriptor to mmap + * + * Takes an ion_fd_data struct with the handle field populated with a valid + * opaque handle. Returns the struct with the fd field set to a file + * descriptor open in the current address space. This file descriptor + * can then be used as an argument to mmap. + */ +#define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data) + +/** + * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation + * + * Takes an ion_fd_data struct with the handle field populated with a valid + * opaque handle. Returns the struct with the fd field set to a file + * descriptor open in the current address space. This file descriptor + * can then be passed to another process. The corresponding opaque handle can + * be retrieved via ION_IOC_IMPORT. + */ +#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data) + +/** + * DOC: ION_IOC_IMPORT - imports a shared file descriptor + * + * Takes an ion_fd_data struct with the fd field populated with a valid file + * descriptor obtained from ION_IOC_SHARE and returns the struct with the handle + * filed set to the corresponding opaque handle. + */ +#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, int) + +/** + * DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl + * + * Takes the argument of the architecture specific ioctl to call and + * passes appropriate userdata for that ioctl + */ +#define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data) + +#endif /* _LINUX_ION_H */ diff --git a/camera/include/linux/s5c73m3.h b/camera/include/linux/s5c73m3.h new file mode 100644 index 0000000..d2e57d5 --- /dev/null +++ b/camera/include/linux/s5c73m3.h @@ -0,0 +1,371 @@ +/* + * Driver for LSI S5C73M3 (ISP for 8MP Camera) + * + * 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. + */ + +#ifndef __S5C73M3_H +#define __S5C73M3_H + +#define CONFIG_CAM_DEBUG 1 +/*#define FEATURE_DEBUG_DUMP*/ + +#define cam_warn(fmt, ...) \ + do { \ + printk(KERN_WARNING "%s: " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#define cam_err(fmt, ...) \ + do { \ + printk(KERN_ERR "%s: " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#define cam_info(fmt, ...) \ + do { \ + printk(KERN_INFO "%s: " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#ifdef CONFIG_CAM_DEBUG +#define CAM_DEBUG (1 << 0) +#define CAM_TRACE (1 << 1) +#define CAM_I2C (1 << 2) + +#define cam_dbg(fmt, ...) \ + do { \ + if (to_state(sd)->dbg_level & CAM_DEBUG) \ + printk(KERN_DEBUG "%s: " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#define cam_trace(fmt, ...) \ + do { \ + if (to_state(sd)->dbg_level & CAM_TRACE) \ + printk(KERN_DEBUG "%s: " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#define cam_i2c_dbg(fmt, ...) \ + do { \ + if (to_state(sd)->dbg_level & CAM_I2C) \ + printk(KERN_DEBUG "%s: " fmt, __func__, ##__VA_ARGS__); \ + } while (0) +#else +#define cam_dbg(fmt, ...) +#define cam_trace(fmt, ...) +#define cam_i2c_dbg(fmt, ...) +#endif + +enum s5c73m3_fw_path{ + S5C73M3_SD_CARD, + S5C73M3_IN_DATA, + S5C73M3_IN_SYSTEM, + S5C73M3_PATH_MAX, +}; + +enum s5c73m3_prev_frmsize { + S5C73M3_PREVIEW_QCIF, + S5C73M3_PREVIEW_QCIF2, + S5C73M3_PREVIEW_QVGA, + S5C73M3_PREVIEW_CIF, + S5C73M3_PREVIEW_VGA, + S5C73M3_PREVIEW_D1, + S5C73M3_PREVIEW_WVGA, + S5C73M3_PREVIEW_704X576, + S5C73M3_PREVIEW_880X720, + S5C73M3_PREVIEW_960X640, + S5C73M3_PREVIEW_960X720, + S5C73M3_PREVIEW_1008X672, + S5C73M3_PREVIEW_1056X704, + S5C73M3_PREVIEW_1184X666, + S5C73M3_PREVIEW_720P, + S5C73M3_VDIS_720P, + S5C73M3_PREVIEW_1080P, + S5C73M3_VDIS_1080P, + S5C73M3_PREVIEW_HDR, +}; + +enum s5c73m3_cap_frmsize { + S5C73M3_CAPTURE_VGA, /* 640 x 480 */ + S5C73M3_CAPTURE_WVGA, /* 800 x 480 */ + S5C73M3_CAPTURE_1024X768, /* 1024 x 768 */ + S5C73M3_CAPTURE_HD, /* 1280 x 720 */ + S5C73M3_CAPTURE_W1MP, /* 1600 x 960 */ + S5C73M3_CAPTURE_2MP, /* UXGA - 1600 x 1200 */ + S5C73M3_CAPTURE_W2MP, /* 2048 x 1232 */ + S5C73M3_CAPTURE_3MP, /* QXGA - 2048 x 1536 */ + S5C73M3_CAPTURE_W4MP, /* WQXGA - 2560 x 1536 */ + S5C73M3_CAPTURE_5MP, /* 2560 x 1920 */ + S5C73M3_CAPTURE_W6MP, /* 3072 x 1856 */ + S5C73M3_CAPTURE_7MP, /* 3072 x 2304 */ + S5C73M3_CAPTURE_W7MP, /* WQXGA - 2560 x 1536 */ + S5C73M3_CAPTURE_3264X2176, /* 3264 x 2176 */ + S5C73M3_CAPTURE_8MP, /* 3264 x 2448 */ +}; + +enum s5c73m3_isneed_flash_tristate { + S5C73M3_ISNEED_FLASH_OFF = 0x00, + S5C73M3_ISNEED_FLASH_ON = 0x01, + S5C73M3_ISNEED_FLASH_UNDEFINED = 0x02, +}; + +#define S5C73M3_IMG_OUTPUT 0x0902 +#define S5C73M3_HDR_OUTPUT 0x0008 +#define S5C73M3_YUV_OUTPUT 0x0009 +#define S5C73M3_INTERLEAVED_OUTPUT 0x000D +#define S5C73M3_HYBRID_OUTPUT 0x0016 + +#define S5C73M3_STILL_PRE_FLASH 0x0A00 +#define S5C73M3_STILL_PRE_FLASH_FIRE 0x0000 +#define S5C73M3_STILL_PRE_FLASH_NON_FIRED 0x0000 +#define S5C73M3_STILL_PRE_FLASH_FIRED 0x0001 + +#define S5C73M3_STILL_MAIN_FLASH 0x0A02 +#define S5C73M3_STILL_MAIN_FLASH_CANCEL 0x0001 +#define S5C73M3_STILL_MAIN_FLASH_FIRE 0x0002 + + +#define S5C73M3_ZOOM_STEP 0x0B00 + + +#define S5C73M3_IMAGE_EFFECT 0x0B0A +#define S5C73M3_IMAGE_EFFECT_NONE 0x0001 +#define S5C73M3_IMAGE_EFFECT_NEGATIVE 0x0002 +#define S5C73M3_IMAGE_EFFECT_AQUA 0x0003 +#define S5C73M3_IMAGE_EFFECT_SEPIA 0x0004 +#define S5C73M3_IMAGE_EFFECT_MONO 0x0005 +#define S5C73M3_IMAGE_EFFECT_SKETCH 0x0006 +#define S5C73M3_IMAGE_EFFECT_WASHED 0x0007 +#define S5C73M3_IMAGE_EFFECT_VINTAGE_WARM 0x0008 +#define S5C73M3_IMAGE_EFFECT_VINTAGE_COLD 0x0009 +#define S5C73M3_IMAGE_EFFECT_SOLARIZE 0x000A +#define S5C73M3_IMAGE_EFFECT_POSTERIZE 0x000B +#define S5C73M3_IMAGE_EFFECT_POINT_BLUE 0x000C +#define S5C73M3_IMAGE_EFFECT_POINT_RED_YELLOW 0x000D +#define S5C73M3_IMAGE_EFFECT_POINT_COLOR_3 0x000E +#define S5C73M3_IMAGE_EFFECT_POINT_GREEN 0x000F + +#define S5C73M3_IMAGE_QUALITY 0x0B0C +#define S5C73M3_IMAGE_QUALITY_SUPERFINE 0x0000 +#define S5C73M3_IMAGE_QUALITY_FINE 0x0001 +#define S5C73M3_IMAGE_QUALITY_NORMAL 0x0002 + + +#define S5C73M3_FLASH_MODE 0x0B0E +#define S5C73M3_FLASH_MODE_OFF 0x0000 +#define S5C73M3_FLASH_MODE_ON 0x0001 +#define S5C73M3_FLASH_MODE_AUTO 0x0002 + +#define S5C73M3_FLASH_TORCH 0x0B12 +#define S5C73M3_FLASH_TORCH_OFF 0x0000 +#define S5C73M3_FLASH_TORCH_ON 0x0001 + +#define S5C73M3_AE_ISNEEDFLASH 0x0CBA +#define S5C73M3_AE_ISNEEDFLASH_OFF 0x0000 +#define S5C73M3_AE_ISNEEDFLASH_ON 0x0001 + + +#define S5C73M3_CHG_MODE 0x0B10 +#define S5C73M3_YUV_MODE 0x8000 +#define S5C73M3_INTERLEAVED_MODE 0x8000 + + +#define S5C73M3_AF_CON 0x0E00 +#define S5C73M3_AF_CON_STOP 0x0000 +#define S5C73M3_AF_CON_SCAN 0x0001/*AF_SCAN:Full Search*/ +#define S5C73M3_AF_CON_START 0x0002/*AF_START:Fast Search*/ + +#define S5C73M3_AF_STATUS 0x5E80 + +#define S5C73M3_AF_TOUCH_AF 0x0E0A + +#define S5C73M3_AF_CAL 0x0E06 + +#define S5C73M3_CAF_STATUS_FIND_SEARCHING_DIR 0x0001 +#define S5C73M3_CAF_STATUS_FOCUSING 0x0002 +#define S5C73M3_CAF_STATUS_FOCUSED 0x0003 +#define S5C73M3_CAF_STATUS_UNFOCUSED 0x0004 + +#define S5C73M3_AF_STATUS_INVALID 0x0010 +#define S5C73M3_AF_STATUS_FOCUSING 0x0020 +#define S5C73M3_AF_STATUS_FOCUSED 0x0030/*SUCCESS*/ +#define S5C73M3_AF_STATUS_UNFOCUSED 0x0040/*FAIL*/ + +#define S5C73M3_AF_TOUCH_POSITION 0x5E8E + +#define S5C73M3_AF_FACE_ZOOM 0x0E10 + +#define S5C73M3_AF_MODE 0x0E02 +#define S5C73M3_AF_MODE_NORMAL 0x0000 +#define S5C73M3_AF_MODE_MACRO 0x0001 +#define S5C73M3_AF_MODE_MOVIE_CAF_START 0x0002 +#define S5C73M3_AF_MODE_MOVIE_CAF_STOP 0x0003 +#define S5C73M3_AF_MODE_PREVIEW_CAF_START 0x0004 +#define S5C73M3_AF_MODE_PREVIEW_CAF_STOP 0x0005 + +#define S5C73M3_AF_SOFTLANDING 0x0E16 +#define S5C73M3_AF_SOFTLANDING_ON 0x0000 + +#define S5C73M3_FACE_DET 0x0E0C +#define S5C73M3_FACE_DET_OFF 0x0000 +#define S5C73M3_FACE_DET_ON 0x0001 + +#define S5C73M3_FACE_DET_OSD 0x0E0E +#define S5C73M3_FACE_DET_OSD_OFF 0x0000 +#define S5C73M3_FACE_DET_OSD_ON 0x0001 + +#define S5C73M3_AE_CON 0x0C00 +#define S5C73M3_AE_STOP 0x0000/*LOCK*/ +#define S5C73M3_AE_START 0x0001/*UNLOCK*/ + +#define S5C73M3_ISO 0x0C02 +#define S5C73M3_ISO_AUTO 0x0000 +#define S5C73M3_ISO_100 0x0001 +#define S5C73M3_ISO_200 0x0002 +#define S5C73M3_ISO_400 0x0003 +#define S5C73M3_ISO_800 0x0004 +#define S5C73M3_ISO_SPORTS 0x0005 +#define S5C73M3_ISO_NIGHT 0x0006 +#define S5C73M3_ISO_INDOOR 0x0007 + +#define S5C73M3_EV 0x0C04 +#define S5C73M3_EV_M20 0x0000 +#define S5C73M3_EV_M15 0x0001 +#define S5C73M3_EV_M10 0x0002 +#define S5C73M3_EV_M05 0x0003 +#define S5C73M3_EV_ZERO 0x0004 +#define S5C73M3_EV_P05 0x0005 +#define S5C73M3_EV_P10 0x0006 +#define S5C73M3_EV_P15 0x0007 +#define S5C73M3_EV_P20 0x0008 + +#define S5C73M3_METER 0x0C06 +#define S5C73M3_METER_CENTER 0x0000 +#define S5C73M3_METER_SPOT 0x0001 +#define S5C73M3_METER_AVERAGE 0x0002 +#define S5C73M3_METER_SMART 0x0003 + +#define S5C73M3_WDR 0x0C08 +#define S5C73M3_WDR_OFF 0x0000 +#define S5C73M3_WDR_ON 0x0001 + +#define S5C73M3_FLICKER_MODE 0x0C12 +#define S5C73M3_FLICKER_NONE 0x0000 +#define S5C73M3_FLICKER_MANUAL_50HZ 0x0001 +#define S5C73M3_FLICKER_MANUAL_60HZ 0x0002 +#define S5C73M3_FLICKER_AUTO 0x0003 +#define S5C73M3_FLICKER_AUTO_50HZ 0x0004 +#define S5C73M3_FLICKER_AUTO_60HZ 0x0005 + +#define S5C73M3_AE_MODE 0x0C1E +#define S5C73M3_AUTO_MODE_AE_SET 0x0000 +#define S5C73M3_FIXED_30FPS 0x0002 +#define S5C73M3_FIXED_20FPS 0x0003 +#define S5C73M3_FIXED_15FPS 0x0004 +#define S5C73M3_FIXED_120FPS 0x0008 +#define S5C73M3_FIXED_7FPS 0x0009 +#define S5C73M3_FIXED_10FPS 0x000A +#define S5C73M3_ANTI_SHAKE 0x0013 + +#define S5C73M3_SHARPNESS 0x0C14 +#define S5C73M3_SHARPNESS_0 0x0000 +#define S5C73M3_SHARPNESS_1 0x0001 +#define S5C73M3_SHARPNESS_2 0x0002 +#define S5C73M3_SHARPNESS_M1 0x0003 +#define S5C73M3_SHARPNESS_M2 0x0004 + +#define S5C73M3_SATURATION 0x0C16 +#define S5C73M3_SATURATION_0 0x0000 +#define S5C73M3_SATURATION_1 0x0001 +#define S5C73M3_SATURATION_2 0x0002 +#define S5C73M3_SATURATION_M1 0x0003 +#define S5C73M3_SATURATION_M2 0x0004 + +#define S5C73M3_CONTRAST 0x0C18 +#define S5C73M3_CONTRAST_0 0x0000 +#define S5C73M3_CONTRAST_1 0x0001 +#define S5C73M3_CONTRAST_2 0x0002 +#define S5C73M3_CONTRAST_M1 0x0003 +#define S5C73M3_CONTRAST_M2 0x0004 + +#define S5C73M3_SCENE_MODE 0x0C1A +#define S5C73M3_SCENE_MODE_NONE 0x0000 +#define S5C73M3_SCENE_MODE_PORTRAIT 0x0001 +#define S5C73M3_SCENE_MODE_LANDSCAPE 0x0002 +#define S5C73M3_SCENE_MODE_SPORTS 0x0003 +#define S5C73M3_SCENE_MODE_INDOOR 0x0004 +#define S5C73M3_SCENE_MODE_BEACH 0x0005 +#define S5C73M3_SCENE_MODE_SUNSET 0x0006 +#define S5C73M3_SCENE_MODE_DAWN 0x0007 +#define S5C73M3_SCENE_MODE_FALL 0x0008 +#define S5C73M3_SCENE_MODE_NIGHT 0x0009 +#define S5C73M3_SCENE_MODE_AGAINSTLIGHT 0x000A +#define S5C73M3_SCENE_MODE_FIRE 0x000B +#define S5C73M3_SCENE_MODE_TEXT 0x000C +#define S5C73M3_SCENE_MODE_CANDLE 0x000D + +#define S5C73M3_FIREWORK_CAPTURE 0x0C20 +#define S5C73M3_NIGHTSHOT_CAPTURE 0x0C22 + +#define S5C73M3_AE_AUTO_BRAKET 0x0B14 +#define S5C73M3_AE_AUTO_BRAKET_EV05 0x0080 +#define S5C73M3_AE_AUTO_BRAKET_EV10 0x0100 +#define S5C73M3_AE_AUTO_BRAKET_EV15 0x0180 +#define S5C73M3_AE_AUTO_BRAKET_EV20 0x0200 + +#define S5C73M3_SENSOR_STREAMING 0x090A +#define S5C73M3_SENSOR_STREAMING_OFF 0x0000 +#define S5C73M3_SENSOR_STREAMING_ON 0x0001 + +#define S5C73M3_AWB_MODE 0x0D02 +#define S5C73M3_AWB_MODE_INCANDESCENT 0x0000 +#define S5C73M3_AWB_MODE_FLUORESCENT1 0x0001 +#define S5C73M3_AWB_MODE_FLUORESCENT2 0x0002 +#define S5C73M3_AWB_MODE_DAYLIGHT 0x0003 +#define S5C73M3_AWB_MODE_CLOUDY 0x0004 +#define S5C73M3_AWB_MODE_AUTO 0x0005 + +#define S5C73M3_AWB_CON 0x0D00 +#define S5C73M3_AWB_STOP 0x0000/*LOCK*/ +#define S5C73M3_AWB_START 0x0001/*UNLOCK*/ + +#define S5C73M3_HYBRID_CAPTURE 0x0996 + +#define S5C73M3_STATUS 0x5080 +#define BOOT_SUB_MAIN_ENTER 0xFF01 +#define BOOT_SRAM_TIMING_OK 0xFF02 +#define BOOT_INTERRUPTS_ENABLE 0xFF03 +#define BOOT_R_PLL_DONE 0xFF04 +#define BOOT_R_PLL_LOCKTIME_DONE 0xFF05 +#define BOOT_DELAY_COUNT_DONE 0xFF06 +#define BOOT_I_PLL_DONE 0xFF07 +#define BOOT_I_PLL_LOCKTIME_DONE 0xFF08 +#define BOOT_PLL_INIT_OK 0xFF09 +#define BOOT_SENSOR_INIT_OK 0xFF0A +#define BOOT_GPIO_SETTING_OK 0xFF0B +#define BOOT_READ_CAL_DATA_OK 0xFF0C +#define BOOT_STABLE_AE_AWB_OK 0xFF0D +#define EXCEPTION_OCCURED 0xDEAD + +#define S5C73M3_I2C_SEQ_STATUS 0x59A6 +#define SEQ_END_PLL (1<<0x0) +#define SEQ_END_SENSOR (1<<0x1) +#define SEQ_END_GPIO (1<<0x2) +#define SEQ_END_FROM (1<<0x3) +#define SEQ_END_STABLE_AE_AWB (1<<0x4) +#define SEQ_END_READY_I2C_CMD (1<<0x5) + +#define S5C73M3_I2C_ERR_STATUS 0x599E +#define ERR_STATUS_CIS_I2C (1<<0x0) +#define ERR_STATUS_AF_INIT (1<<0x1) +#define ERR_STATUS_CAL_DATA (1<<0x2) +#define ERR_STATUS_FRAME_COUNT (1<<0x3) +#define ERR_STATUS_FROM_INIT (1<<0x4) +#define ERR_STATUS_I2C_CIS_STREAM_OFF (1<<0x5) +#define ERR_STATUS_I2C_N_CMD_OVER (1<<0x6) +#define ERROR_STATUS_I2C_N_CMD_MISMATCH (1<<0x7) +#define ERROR_STATUS_CHECK_BIN_CRC (1<<0x8) +#define ERROR_STATUS_EXCEPTION (1<<0x9) +#define ERROR_STATUS_INIF_INIT_STATE (0x8) + +#endif /* __S5C73M3_H */ diff --git a/camera/include/linux/videodev2.h b/camera/include/linux/videodev2.h new file mode 100644 index 0000000..a464469 --- /dev/null +++ b/camera/include/linux/videodev2.h @@ -0,0 +1,2364 @@ +/* + * Video for Linux Two header file + * + * Copyright (C) 1999-2007 the contributors + * + * 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. + * + * Alternatively you can redistribute this file under the terms of the + * BSD license as stated below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. The names of its contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Header file for v4l or V4L2 drivers and applications + * with public API. + * All kernel-specific stuff were moved to media/v4l2-dev.h, so + * no #if __KERNEL tests are allowed here + * + * See http://linuxtv.org for more info + * + * Author: Bill Dirks + * Justin Schoeman + * Hans Verkuil + * et al. + */ +#ifndef __LINUX_VIDEODEV2_H +#define __LINUX_VIDEODEV2_H + +#ifdef __KERNEL__ +#include /* need struct timeval */ +#else +#include +#endif +#include +#include +#include + +/* + * Common stuff for both V4L1 and V4L2 + * Moved from videodev.h + */ +#define VIDEO_MAX_FRAME 32 +#define VIDEO_MAX_PLANES 8 + +#ifndef __KERNEL__ + +/* These defines are V4L1 specific and should not be used with the V4L2 API! + They will be removed from this header in the future. */ + +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ +#endif + +/* + * M I S C E L L A N E O U S + */ + +/* Four-character-code (FOURCC) */ +#define v4l2_fourcc(a, b, c, d)\ + ((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24)) + +/* + * E N U M S + */ +enum v4l2_field { + V4L2_FIELD_ANY = 0, /* driver can choose from none, + top, bottom, interlaced + depending on whatever it thinks + is approximate ... */ + V4L2_FIELD_NONE = 1, /* this device has no fields ... */ + V4L2_FIELD_TOP = 2, /* top field only */ + V4L2_FIELD_BOTTOM = 3, /* bottom field only */ + V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */ + V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one + buffer, top-bottom order */ + V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */ + V4L2_FIELD_ALTERNATE = 7, /* both fields alternating into + separate buffers */ + V4L2_FIELD_INTERLACED_TB = 8, /* both fields interlaced, top field + first and the top field is + transmitted first */ + V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field + first and the bottom field is + transmitted first */ +}; +#define V4L2_FIELD_HAS_TOP(field) \ + ((field) == V4L2_FIELD_TOP ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_BOTTOM(field) \ + ((field) == V4L2_FIELD_BOTTOM ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_BOTH(field) \ + ((field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) + +enum v4l2_buf_type { + V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, + V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, + V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, + V4L2_BUF_TYPE_VBI_CAPTURE = 4, + V4L2_BUF_TYPE_VBI_OUTPUT = 5, + V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, + V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, +#if 1 + /* Experimental */ + V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, +#endif + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = 10, + V4L2_BUF_TYPE_PRIVATE = 0x80, +}; + +#define V4L2_TYPE_IS_MULTIPLANAR(type) \ + ((type) == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + +#define V4L2_TYPE_IS_OUTPUT(type) \ + ((type) == V4L2_BUF_TYPE_VIDEO_OUTPUT \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE \ + || (type) == V4L2_BUF_TYPE_VIDEO_OVERLAY \ + || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY \ + || (type) == V4L2_BUF_TYPE_VBI_OUTPUT \ + || (type) == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) + +enum v4l2_tuner_type { + V4L2_TUNER_RADIO = 1, + V4L2_TUNER_ANALOG_TV = 2, + V4L2_TUNER_DIGITAL_TV = 3, +}; + +enum v4l2_memory { + V4L2_MEMORY_MMAP = 1, + V4L2_MEMORY_USERPTR = 2, + V4L2_MEMORY_OVERLAY = 3, + V4L2_MEMORY_DMABUF = 4, +}; + +/* see also http://vektor.theorem.ca/graphics/ycbcr/ */ +enum v4l2_colorspace { + /* ITU-R 601 -- broadcast NTSC/PAL */ + V4L2_COLORSPACE_SMPTE170M = 1, + + /* 1125-Line (US) HDTV */ + V4L2_COLORSPACE_SMPTE240M = 2, + + /* HD and modern captures. */ + V4L2_COLORSPACE_REC709 = 3, + + /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */ + V4L2_COLORSPACE_BT878 = 4, + + /* These should be useful. Assume 601 extents. */ + V4L2_COLORSPACE_470_SYSTEM_M = 5, + V4L2_COLORSPACE_470_SYSTEM_BG = 6, + + /* I know there will be cameras that send this. So, this is + * unspecified chromaticities and full 0-255 on each of the + * Y'CbCr components + */ + V4L2_COLORSPACE_JPEG = 7, + + /* For RGB colourspaces, this is probably a good start. */ + V4L2_COLORSPACE_SRGB = 8, +}; + +enum v4l2_priority { + V4L2_PRIORITY_UNSET = 0, /* not initialized */ + V4L2_PRIORITY_BACKGROUND = 1, + V4L2_PRIORITY_INTERACTIVE = 2, + V4L2_PRIORITY_RECORD = 3, + V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE, +}; + +struct v4l2_rect { + __s32 left; + __s32 top; + __s32 width; + __s32 height; +}; + +struct v4l2_fract { + __u32 numerator; + __u32 denominator; +}; + +/* + * D R I V E R C A P A B I L I T I E S + */ +struct v4l2_capability { + __u8 driver[16]; /* i.e. "bttv" */ + __u8 card[32]; /* i.e. "Hauppauge WinTV" */ + __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ + __u32 version; /* should use KERNEL_VERSION() */ + __u32 capabilities; /* Device capabilities */ + __u32 reserved[4]; +}; + +/* Values for 'capabilities' field */ +#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */ +#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */ +#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */ +#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */ +#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */ +#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */ +#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */ +#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ +#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay */ +#define V4L2_CAP_HW_FREQ_SEEK 0x00000400 /* Can do hardware frequency seek */ +#define V4L2_CAP_RDS_OUTPUT 0x00000800 /* Is an RDS encoder */ + +/* Is a video capture device that supports multiplanar formats */ +#define V4L2_CAP_VIDEO_CAPTURE_MPLANE 0x00001000 +/* Is a video output device that supports multiplanar formats */ +#define V4L2_CAP_VIDEO_OUTPUT_MPLANE 0x00002000 + +#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ +#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ +#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ +#define V4L2_CAP_MODULATOR 0x00080000 /* has a modulator */ + +#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */ +#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ +#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ + +/* + * V I D E O I M A G E F O R M A T + */ +struct v4l2_pix_format { + __u32 width; + __u32 height; + __u32 pixelformat; + enum v4l2_field field; + __u32 bytesperline; /* for padding, zero if unused */ + __u32 sizeimage; + enum v4l2_colorspace colorspace; + __u32 priv; /* private data, depends on pixelformat */ +}; + +/* Pixel format FOURCC depth Description */ + +/* RGB formats */ +#define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R', 'G', 'B', '1') /* 8 RGB-3-3-2 */ +#define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R', '4', '4', '4') /* 16 xxxxrrrr ggggbbbb */ +#define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R', 'G', 'B', 'O') /* 16 RGB-5-5-5 */ +#define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */ +#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16 RGB-5-5-5 BE */ +#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16 RGB-5-6-5 BE */ +#define V4L2_PIX_FMT_BGR666 v4l2_fourcc('B', 'G', 'R', 'H') /* 18 BGR-6-6-6 */ +#define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */ +#define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */ +#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */ +#define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R', 'G', 'B', '4') /* 32 RGB-8-8-8-8 */ + +/* Grey formats */ +#define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */ +#define V4L2_PIX_FMT_Y4 v4l2_fourcc('Y', '0', '4', ' ') /* 4 Greyscale */ +#define V4L2_PIX_FMT_Y6 v4l2_fourcc('Y', '0', '6', ' ') /* 6 Greyscale */ +#define V4L2_PIX_FMT_Y10 v4l2_fourcc('Y', '1', '0', ' ') /* 10 Greyscale */ +#define V4L2_PIX_FMT_Y12 v4l2_fourcc('Y', '1', '2', ' ') /* 12 Greyscale */ +#define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y', '1', '6', ' ') /* 16 Greyscale */ + +/* Grey bit-packed formats */ +#define V4L2_PIX_FMT_Y10BPACK v4l2_fourcc('Y', '1', '0', 'B') /* 10 Greyscale bit-packed */ + +/* Palette formats */ +#define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P', 'A', 'L', '8') /* 8 8-bit palette */ + +/* Luminance+Chrominance formats */ +#define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y', 'V', 'U', '9') /* 9 YVU 4:1:0 */ +#define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y', 'V', '1', '2') /* 12 YVU 4:2:0 */ +#define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y', 'Y', 'U', 'V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */ +#define V4L2_PIX_FMT_UYVY v4l2_fourcc('U', 'Y', 'V', 'Y') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4', '2', '2', 'P') /* 16 YVU422 planar */ +#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4', '1', '1', 'P') /* 16 YVU411 planar */ +#define V4L2_PIX_FMT_Y41P v4l2_fourcc('Y', '4', '1', 'P') /* 12 YUV 4:1:1 */ +#define V4L2_PIX_FMT_YUV444 v4l2_fourcc('Y', '4', '4', '4') /* 16 xxxxyyyy uuuuvvvv */ +#define V4L2_PIX_FMT_YUV555 v4l2_fourcc('Y', 'U', 'V', 'O') /* 16 YUV-5-5-5 */ +#define V4L2_PIX_FMT_YUV565 v4l2_fourcc('Y', 'U', 'V', 'P') /* 16 YUV-5-6-5 */ +#define V4L2_PIX_FMT_YUV32 v4l2_fourcc('Y', 'U', 'V', '4') /* 32 YUV-8-8-8-8 */ +#define V4L2_PIX_FMT_YUV410 v4l2_fourcc('Y', 'U', 'V', '9') /* 9 YUV 4:1:0 */ +#define V4L2_PIX_FMT_YUV420 v4l2_fourcc('Y', 'U', '1', '2') /* 12 YUV 4:2:0 */ +#define V4L2_PIX_FMT_HI240 v4l2_fourcc('H', 'I', '2', '4') /* 8 8-bit color */ +#define V4L2_PIX_FMT_HM12 v4l2_fourcc('H', 'M', '1', '2') /* 8 YUV 4:2:0 16x16 macroblocks */ +#define V4L2_PIX_FMT_M420 v4l2_fourcc('M', '4', '2', '0') /* 12 YUV 4:2:0 2 lines y, 1 line uv interleaved */ + +/* two planes -- one Y, one Cr + Cb interleaved */ +#define V4L2_PIX_FMT_NV12 v4l2_fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */ +#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N', 'V', '2', '1') /* 12 Y/CrCb 4:2:0 */ +#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */ +#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */ +#define V4L2_PIX_FMT_NV24 v4l2_fourcc('N', 'V', '2', '4') /* 24 Y/CbCr 4:4:4 */ +#define V4L2_PIX_FMT_NV42 v4l2_fourcc('N', 'V', '4', '2') /* 24 Y/CrCb 4:4:4 */ + +/* two non contiguous planes - one Y, one Cr + Cb interleaved */ +#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */ +#define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */ + +/* three non contiguous planes - Y, Cb, Cr */ +#define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12 YUV420 planar */ + +/* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */ +#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R', 'G', 'G', 'B') /* 8 RGRG.. GBGB.. */ +#define V4L2_PIX_FMT_SBGGR10 v4l2_fourcc('B', 'G', '1', '0') /* 10 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10 RGRG.. GBGB.. */ +#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12 RGRG.. GBGB.. */ + /* 10bit raw bayer DPCM compressed to 8 bits */ +#define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0') + /* + * 10bit raw bayer, expanded to 16 bits + * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb... + */ +#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2') /* 16 BGBG.. GRGR.. */ + +/* compressed formats */ +#define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M', 'J', 'P', 'G') /* Motion-JPEG */ +#define V4L2_PIX_FMT_JPEG v4l2_fourcc('J', 'P', 'E', 'G') /* JFIF JPEG */ +#define V4L2_PIX_FMT_DV v4l2_fourcc('d', 'v', 's', 'd') /* 1394 */ +#define V4L2_PIX_FMT_MPEG v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 Multiplexed */ +#define V4L2_PIX_FMT_H264 v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */ +#define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */ +#define V4L2_PIX_FMT_H263 v4l2_fourcc('H', '2', '6', '3') /* H263 */ +#define V4L2_PIX_FMT_MPEG1 v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES */ +#define V4L2_PIX_FMT_MPEG2 v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES */ +#define V4L2_PIX_FMT_MPEG4 v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 ES */ +#define V4L2_PIX_FMT_XVID v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid */ +#define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */ +#define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */ + +/* Vendor-specific formats */ +#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */ +#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */ +#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */ +#define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */ +#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P', 'W', 'C', '1') /* pwc older webcam */ +#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P', 'W', 'C', '2') /* pwc newer webcam */ +#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E', '6', '2', '5') /* ET61X251 compression */ +#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S', '5', '0', '1') /* YUYV per line */ +#define V4L2_PIX_FMT_SPCA505 v4l2_fourcc('S', '5', '0', '5') /* YYUV per line */ +#define V4L2_PIX_FMT_SPCA508 v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */ +#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */ +#define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */ +#define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */ +#define V4L2_PIX_FMT_JL2005BCD v4l2_fourcc('J', 'L', '2', '0') /* compressed RGGB bayer */ +#define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */ +#define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */ +#define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */ +#define V4L2_PIX_FMT_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */ +#define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */ +#define V4L2_PIX_FMT_STV0680 v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */ +#define V4L2_PIX_FMT_TM6000 v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */ +#define V4L2_PIX_FMT_CIT_YYVYUY v4l2_fourcc('C', 'I', 'T', 'V') /* one line of Y then 1 line of VYUY */ +#define V4L2_PIX_FMT_KONICA420 v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */ +#define V4L2_PIX_FMT_JPGL v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */ +/* RGB x:10:10:10 */ +#define V4L2_PIX_FMT_INTC_RGB30 v4l2_fourcc('R', 'G', 'B', '0') +#define V4L2_PIX_FMT_SE401 v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */ + +/* + * F O R M A T E N U M E R A T I O N + */ +struct v4l2_fmtdesc { + __u32 index; /* Format number */ + enum v4l2_buf_type type; /* buffer type */ + __u32 flags; + __u8 description[32]; /* Description string */ + __u32 pixelformat; /* Format fourcc */ + __u32 reserved[4]; +}; + +#define V4L2_FMT_FLAG_COMPRESSED 0x0001 +#define V4L2_FMT_FLAG_EMULATED 0x0002 + +#if 1 + /* Experimental Frame Size and frame rate enumeration */ +/* + * F R A M E S I Z E E N U M E R A T I O N + */ +enum v4l2_frmsizetypes { + V4L2_FRMSIZE_TYPE_DISCRETE = 1, + V4L2_FRMSIZE_TYPE_CONTINUOUS = 2, + V4L2_FRMSIZE_TYPE_STEPWISE = 3, +}; + +struct v4l2_frmsize_discrete { + __u32 width; /* Frame width [pixel] */ + __u32 height; /* Frame height [pixel] */ +}; + +struct v4l2_frmsize_stepwise { + __u32 min_width; /* Minimum frame width [pixel] */ + __u32 max_width; /* Maximum frame width [pixel] */ + __u32 step_width; /* Frame width step size [pixel] */ + __u32 min_height; /* Minimum frame height [pixel] */ + __u32 max_height; /* Maximum frame height [pixel] */ + __u32 step_height; /* Frame height step size [pixel] */ +}; + +struct v4l2_frmsizeenum { + __u32 index; /* Frame size number */ + __u32 pixel_format; /* Pixel format */ + __u32 type; /* Frame size type the device supports. */ + + union { /* Frame size */ + struct v4l2_frmsize_discrete discrete; + struct v4l2_frmsize_stepwise stepwise; + }; + + __u32 reserved[2]; /* Reserved space for future use */ +}; + +/* + * F R A M E R A T E E N U M E R A T I O N + */ +enum v4l2_frmivaltypes { + V4L2_FRMIVAL_TYPE_DISCRETE = 1, + V4L2_FRMIVAL_TYPE_CONTINUOUS = 2, + V4L2_FRMIVAL_TYPE_STEPWISE = 3, +}; + +struct v4l2_frmival_stepwise { + struct v4l2_fract min; /* Minimum frame interval [s] */ + struct v4l2_fract max; /* Maximum frame interval [s] */ + struct v4l2_fract step; /* Frame interval step size [s] */ +}; + +struct v4l2_frmivalenum { + __u32 index; /* Frame format index */ + __u32 pixel_format; /* Pixel format */ + __u32 width; /* Frame width */ + __u32 height; /* Frame height */ + __u32 type; /* Frame interval type the device supports. */ + + union { /* Frame interval */ + struct v4l2_fract discrete; + struct v4l2_frmival_stepwise stepwise; + }; + + __u32 reserved[2]; /* Reserved space for future use */ +}; +#endif + +/* + * T I M E C O D E + */ +struct v4l2_timecode { + __u32 type; + __u32 flags; + __u8 frames; + __u8 seconds; + __u8 minutes; + __u8 hours; + __u8 userbits[4]; +}; + +/* Type */ +#define V4L2_TC_TYPE_24FPS 1 +#define V4L2_TC_TYPE_25FPS 2 +#define V4L2_TC_TYPE_30FPS 3 +#define V4L2_TC_TYPE_50FPS 4 +#define V4L2_TC_TYPE_60FPS 5 + +/* Flags */ +#define V4L2_TC_FLAG_DROPFRAME 0x0001 /* "drop-frame" mode */ +#define V4L2_TC_FLAG_COLORFRAME 0x0002 +#define V4L2_TC_USERBITS_field 0x000C +#define V4L2_TC_USERBITS_USERDEFINED 0x0000 +#define V4L2_TC_USERBITS_8BITCHARS 0x0008 +/* The above is based on SMPTE timecodes */ + +struct v4l2_jpegcompression { + int quality; + + int APPn; /* Number of APP segment to be written, + * must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ + + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ + + __u32 jpeg_markers; /* Which markers should go into the JPEG + * output. Unless you exactly know what + * you do, leave them untouched. + * Inluding less markers will make the + * resulting code smaller, but there will + * be fewer applications which can read it. + * The presence of the APP and COM marker + * is influenced by APP_len and COM_len + * ONLY, not by this property! */ + +#define V4L2_JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ +#define V4L2_JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ +#define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ +#define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ +#define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will + * allways use APP0 */ +}; + +/* + * M E M O R Y - M A P P I N G B U F F E R S + */ +struct v4l2_requestbuffers { + __u32 count; + enum v4l2_buf_type type; + enum v4l2_memory memory; + __u32 reserved[2]; +}; + +/** + * struct v4l2_plane - plane info for multi-planar buffers + * @bytesused: number of bytes occupied by data in the plane (payload) + * @length: size of this plane (NOT the payload) in bytes + * @mem_offset: when memory in the associated struct v4l2_buffer is + * V4L2_MEMORY_MMAP, equals the offset from the start of + * the device memory for this plane (or is a "cookie" that + * should be passed to mmap() called on the video node) + * @userptr: when memory is V4L2_MEMORY_USERPTR, a userspace pointer + * pointing to this plane + * @fd: when memory is V4L2_MEMORY_DMABUF, a userspace file + * descriptor associated with this plane + * @data_offset: offset in the plane to the start of data; usually 0, + * unless there is a header in front of the data + * + * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer + * with two planes can have one plane for Y, and another for interleaved CbCr + * components. Each plane can reside in a separate memory buffer, or even in + * a completely separate memory node (e.g. in embedded devices). + */ +struct v4l2_plane { + __u32 bytesused; + __u32 length; + union { + __u32 mem_offset; + unsigned long userptr; + int fd; + } m; + __u32 data_offset; + __u32 reserved[11]; +}; + +/** + * struct v4l2_buffer - video buffer info + * @index: id number of the buffer + * @type: buffer type (type == *_MPLANE for multiplanar buffers) + * @bytesused: number of bytes occupied by data in the buffer (payload); + * unused (set to 0) for multiplanar buffers + * @flags: buffer informational flags + * @field: field order of the image in the buffer + * @timestamp: frame timestamp + * @timecode: frame timecode + * @sequence: sequence count of this frame + * @memory: the method, in which the actual video data is passed + * @offset: for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP; + * offset from the start of the device memory for this plane, + * (or a "cookie" that should be passed to mmap() as offset) + * @userptr: for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR; + * a userspace pointer pointing to this buffer + * @fd: for non-multiplanar buffers with + * memory == V4L2_MEMORY_DMABUF; a userspace file descriptor + * associated with this buffer + * @planes: for multiplanar buffers; userspace pointer to the array of plane + * info structs for this buffer + * @length: size in bytes of the buffer (NOT its payload) for single-plane + * buffers (when type != *_MPLANE); number of elements in the + * planes array for multi-plane buffers + * @input: input number from which the video data has has been captured + * + * Contains data exchanged by application and driver using one of the Streaming + * I/O methods. + */ +struct v4l2_buffer { + __u32 index; + enum v4l2_buf_type type; + __u32 bytesused; + __u32 flags; + enum v4l2_field field; + struct timeval timestamp; + struct v4l2_timecode timecode; + __u32 sequence; + + /* memory location */ + enum v4l2_memory memory; + union { + __u32 offset; + unsigned long userptr; + struct v4l2_plane *planes; + int fd; + } m; + __u32 length; + __u32 input; + __u32 reserved; +}; + +/* Flags for 'flags' field */ +#define V4L2_BUF_FLAG_MAPPED 0x0001 /* Buffer is mapped (flag) */ +#define V4L2_BUF_FLAG_QUEUED 0x0002 /* Buffer is queued for processing */ +#define V4L2_BUF_FLAG_DONE 0x0004 /* Buffer is ready */ +#define V4L2_BUF_FLAG_KEYFRAME 0x0008 /* Image is a keyframe (I-frame) */ +#define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */ +#define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */ +/* Buffer is ready, but the data contained within is corrupted. */ +#define V4L2_BUF_FLAG_ERROR 0x0040 +#define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */ +#define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */ +#define V4L2_BUF_FLAG_PREPARED 0x0400 /* Buffer is prepared for queuing */ +/* Cache handling flags */ +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE 0x0800 +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN 0x1000 + +/* + * O V E R L A Y P R E V I E W + */ +struct v4l2_framebuffer { + __u32 capability; + __u32 flags; +/* FIXME: in theory we should pass something like PCI device + memory + * region + offset instead of some physical address */ + void *base; + struct v4l2_pix_format fmt; +}; +/* Flags for the 'capability' field. Read only */ +#define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 +#define V4L2_FBUF_CAP_CHROMAKEY 0x0002 +#define V4L2_FBUF_CAP_LIST_CLIPPING 0x0004 +#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008 +#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 +#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004 +#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; + struct v4l2_clip __user *next; +}; + +struct v4l2_window { + struct v4l2_rect w; + enum v4l2_field field; + __u32 chromakey; + struct v4l2_clip __user *clips; + __u32 clipcount; + void __user *bitmap; + __u8 global_alpha; +}; + +/* + * C A P T U R E P A R A M E T E R S + */ +struct v4l2_captureparm { + __u32 capability; /* Supported modes */ + __u32 capturemode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in .1us units */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 readbuffers; /* # of buffers for read */ + __u32 reserved[4]; +}; + +/* Flags for 'capability' and 'capturemode' fields */ +#define V4L2_MODE_HIGHQUALITY 0x0001 /* High quality imaging mode */ +#define V4L2_CAP_TIMEPERFRAME 0x1000 /* timeperframe field is supported */ + +struct v4l2_outputparm { + __u32 capability; /* Supported modes */ + __u32 outputmode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in seconds */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 writebuffers; /* # of buffers for write */ + __u32 reserved[4]; +}; + +/* + * I N P U T I M A G E C R O P P I N G + */ +struct v4l2_cropcap { + enum v4l2_buf_type type; + struct v4l2_rect bounds; + struct v4l2_rect defrect; + struct v4l2_fract pixelaspect; +}; + +struct v4l2_crop { + enum v4l2_buf_type type; + struct v4l2_rect c; +}; + +/* Hints for adjustments of selection rectangle */ +#define V4L2_SEL_FLAG_GE 0x00000001 +#define V4L2_SEL_FLAG_LE 0x00000002 + +/* Selection targets */ + +/* current cropping area */ +#define V4L2_SEL_TGT_CROP_ACTIVE 0 +/* default cropping area */ +#define V4L2_SEL_TGT_CROP_DEFAULT 1 +/* cropping bounds */ +#define V4L2_SEL_TGT_CROP_BOUNDS 2 +/* current composing area */ +#define V4L2_SEL_TGT_COMPOSE_ACTIVE 256 +/* default composing area */ +#define V4L2_SEL_TGT_COMPOSE_DEFAULT 257 +/* composing bounds */ +#define V4L2_SEL_TGT_COMPOSE_BOUNDS 258 +/* current composing area plus all padding pixels */ +#define V4L2_SEL_TGT_COMPOSE_PADDED 259 + +/** + * struct v4l2_selection - selection info + * @type: buffer type (do not use *_MPLANE types) + * @target: selection target, used to choose one of possible rectangles + * @flags: constraints flags + * @r: coordinates of selection window + * @reserved: for future use, rounds structure size to 64 bytes, set to zero + * + * Hardware may use multiple helper window to process a video stream. + * The structure is used to exchange this selection areas between + * an application and a driver. + */ +struct v4l2_selection { + __u32 type; + __u32 target; + __u32 flags; + struct v4l2_rect r; + __u32 reserved[9]; +}; + + +/* + * A N A L O G V I D E O S T A N D A R D + */ + +typedef __u64 v4l2_std_id; + +/* one bit for each */ +#define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001) +#define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002) +#define V4L2_STD_PAL_G ((v4l2_std_id)0x00000004) +#define V4L2_STD_PAL_H ((v4l2_std_id)0x00000008) +#define V4L2_STD_PAL_I ((v4l2_std_id)0x00000010) +#define V4L2_STD_PAL_D ((v4l2_std_id)0x00000020) +#define V4L2_STD_PAL_D1 ((v4l2_std_id)0x00000040) +#define V4L2_STD_PAL_K ((v4l2_std_id)0x00000080) + +#define V4L2_STD_PAL_M ((v4l2_std_id)0x00000100) +#define V4L2_STD_PAL_N ((v4l2_std_id)0x00000200) +#define V4L2_STD_PAL_Nc ((v4l2_std_id)0x00000400) +#define V4L2_STD_PAL_60 ((v4l2_std_id)0x00000800) + +#define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) /* BTSC */ +#define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) /* EIA-J */ +#define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) +#define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000) /* FM A2 */ + +#define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) +#define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) +#define V4L2_STD_SECAM_G ((v4l2_std_id)0x00040000) +#define V4L2_STD_SECAM_H ((v4l2_std_id)0x00080000) +#define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000) +#define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000) +#define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000) +#define V4L2_STD_SECAM_LC ((v4l2_std_id)0x00800000) + +/* ATSC/HDTV */ +#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000) +#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000) + +/* FIXME: + Although std_id is 64 bits, there is an issue on PPC32 architecture that + makes switch(__u64) to break. So, there's a hack on v4l2-common.c rounding + this value to 32 bits. + As, currently, the max value is for V4L2_STD_ATSC_16_VSB (30 bits wide), + it should work fine. However, if needed to add more than two standards, + v4l2-common.c should be fixed. + */ + +/* + * Some macros to merge video standards in order to make live easier for the + * drivers and V4L2 applications + */ + +/* + * "Common" NTSC/M - It should be noticed that V4L2_STD_NTSC_443 is + * Missing here. + */ +#define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ + V4L2_STD_NTSC_M_JP |\ + V4L2_STD_NTSC_M_KR) +/* Secam macros */ +#define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ + V4L2_STD_SECAM_K |\ + V4L2_STD_SECAM_K1) +/* All Secam Standards */ +#define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\ + V4L2_STD_SECAM_G |\ + V4L2_STD_SECAM_H |\ + V4L2_STD_SECAM_DK |\ + V4L2_STD_SECAM_L |\ + V4L2_STD_SECAM_LC) +/* PAL macros */ +#define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\ + V4L2_STD_PAL_B1 |\ + V4L2_STD_PAL_G) +#define V4L2_STD_PAL_DK (V4L2_STD_PAL_D |\ + V4L2_STD_PAL_D1 |\ + V4L2_STD_PAL_K) +/* + * "Common" PAL - This macro is there to be compatible with the old + * V4L1 concept of "PAL": /BGDKHI. + * Several PAL standards are mising here: /M, /N and /Nc + */ +#define V4L2_STD_PAL (V4L2_STD_PAL_BG |\ + V4L2_STD_PAL_DK |\ + V4L2_STD_PAL_H |\ + V4L2_STD_PAL_I) +/* Chroma "agnostic" standards */ +#define V4L2_STD_B (V4L2_STD_PAL_B |\ + V4L2_STD_PAL_B1 |\ + V4L2_STD_SECAM_B) +#define V4L2_STD_G (V4L2_STD_PAL_G |\ + V4L2_STD_SECAM_G) +#define V4L2_STD_H (V4L2_STD_PAL_H |\ + V4L2_STD_SECAM_H) +#define V4L2_STD_L (V4L2_STD_SECAM_L |\ + V4L2_STD_SECAM_LC) +#define V4L2_STD_GH (V4L2_STD_G |\ + V4L2_STD_H) +#define V4L2_STD_DK (V4L2_STD_PAL_DK |\ + V4L2_STD_SECAM_DK) +#define V4L2_STD_BG (V4L2_STD_B |\ + V4L2_STD_G) +#define V4L2_STD_MN (V4L2_STD_PAL_M |\ + V4L2_STD_PAL_N |\ + V4L2_STD_PAL_Nc |\ + V4L2_STD_NTSC) + +/* Standards where MTS/BTSC stereo could be found */ +#define V4L2_STD_MTS (V4L2_STD_NTSC_M |\ + V4L2_STD_PAL_M |\ + V4L2_STD_PAL_N |\ + V4L2_STD_PAL_Nc) + +/* Standards for Countries with 60Hz Line frequency */ +#define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ + V4L2_STD_PAL_60 |\ + V4L2_STD_NTSC |\ + V4L2_STD_NTSC_443) +/* Standards for Countries with 50Hz Line frequency */ +#define V4L2_STD_625_50 (V4L2_STD_PAL |\ + V4L2_STD_PAL_N |\ + V4L2_STD_PAL_Nc |\ + V4L2_STD_SECAM) + +#define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\ + V4L2_STD_ATSC_16_VSB) +/* Macros with none and all analog standards */ +#define V4L2_STD_UNKNOWN 0 +#define V4L2_STD_ALL (V4L2_STD_525_60 |\ + V4L2_STD_625_50) + +struct v4l2_standard { + __u32 index; + v4l2_std_id id; + __u8 name[24]; + struct v4l2_fract frameperiod; /* Frames, not fields */ + __u32 framelines; + __u32 reserved[4]; +}; + +/* + * V I D E O T I M I N G S D V P R E S E T + */ +struct v4l2_dv_preset { + __u32 preset; + __u32 reserved[4]; +}; + +/* + * D V P R E S E T S E N U M E R A T I O N + */ +struct v4l2_dv_enum_preset { + __u32 index; + __u32 preset; + __u8 name[32]; /* Name of the preset timing */ + __u32 width; + __u32 height; + __u32 reserved[4]; +}; + +/* + * D V P R E S E T V A L U E S + */ +#define V4L2_DV_INVALID 0 +#define V4L2_DV_480P59_94 1 /* BT.1362 */ +#define V4L2_DV_576P50 2 /* BT.1362 */ +#define V4L2_DV_720P24 3 /* SMPTE 296M */ +#define V4L2_DV_720P25 4 /* SMPTE 296M */ +#define V4L2_DV_720P30 5 /* SMPTE 296M */ +#define V4L2_DV_720P50 6 /* SMPTE 296M */ +#define V4L2_DV_720P59_94 7 /* SMPTE 274M */ +#define V4L2_DV_720P60 8 /* SMPTE 274M/296M */ +#define V4L2_DV_1080I29_97 9 /* BT.1120/ SMPTE 274M */ +#define V4L2_DV_1080I30 10 /* BT.1120/ SMPTE 274M */ +#define V4L2_DV_1080I25 11 /* BT.1120 */ +#define V4L2_DV_1080I50 12 /* SMPTE 296M */ +#define V4L2_DV_1080I60 13 /* SMPTE 296M */ +#define V4L2_DV_1080P24 14 /* SMPTE 296M */ +#define V4L2_DV_1080P25 15 /* SMPTE 296M */ +#define V4L2_DV_1080P30 16 /* SMPTE 296M */ +#define V4L2_DV_1080P50 17 /* BT.1120 */ +#define V4L2_DV_1080P60 18 /* BT.1120 */ + +#define V4L2_DV_480P60 19 +#define V4L2_DV_1080I59_94 20 +#define V4L2_DV_1080P59_94 21 + +#define V4L2_DV_720P60_FP 22 +#define V4L2_DV_720P60_SB_HALF 23 +#define V4L2_DV_720P60_TB 24 +#define V4L2_DV_720P59_94_FP 25 +#define V4L2_DV_720P59_94_SB_HALF 26 +#define V4L2_DV_720P59_94_TB 27 +#define V4L2_DV_720P50_FP 28 +#define V4L2_DV_720P50_SB_HALF 29 +#define V4L2_DV_720P50_TB 30 +#define V4L2_DV_1080P24_FP 31 +#define V4L2_DV_1080P24_SB_HALF 32 +#define V4L2_DV_1080P24_TB 33 +#define V4L2_DV_1080P23_98_FP 34 +#define V4L2_DV_1080P23_98_SB_HALF 35 +#define V4L2_DV_1080P23_98_TB 36 +#define V4L2_DV_1080I60_SB_HALF 37 +#define V4L2_DV_1080I59_94_SB_HALF 38 +#define V4L2_DV_1080I50_SB_HALF 39 +#define V4L2_DV_1080P60_SB_HALF 40 +#define V4L2_DV_1080P60_TB 41 +#define V4L2_DV_1080P30_FP 42 +#define V4L2_DV_1080P30_SB_HALF 43 +#define V4L2_DV_1080P30_TB 44 + +/* + * D V B T T I M I N G S + */ + +/* BT.656/BT.1120 timing data */ +struct v4l2_bt_timings { + __u32 width; /* width in pixels */ + __u32 height; /* height in lines */ + __u32 interlaced; /* Interlaced or progressive */ + __u32 polarities; /* Positive or negative polarity */ + __u64 pixelclock; /* Pixel clock in HZ. Ex. 74.25MHz->74250000 */ + __u32 hfrontporch; /* Horizpontal front porch in pixels */ + __u32 hsync; /* Horizontal Sync length in pixels */ + __u32 hbackporch; /* Horizontal back porch in pixels */ + __u32 vfrontporch; /* Vertical front porch in pixels */ + __u32 vsync; /* Vertical Sync length in lines */ + __u32 vbackporch; /* Vertical back porch in lines */ + __u32 il_vfrontporch; /* Vertical front porch for bottom field of + * interlaced field formats + */ + __u32 il_vsync; /* Vertical sync length for bottom field of + * interlaced field formats + */ + __u32 il_vbackporch; /* Vertical back porch for bottom field of + * interlaced field formats + */ + __u32 reserved[16]; +} __attribute__ ((packed)); + +/* Interlaced or progressive format */ +#define V4L2_DV_PROGRESSIVE 0 +#define V4L2_DV_INTERLACED 1 + +/* Polarities. If bit is not set, it is assumed to be negative polarity */ +#define V4L2_DV_VSYNC_POS_POL 0x00000001 +#define V4L2_DV_HSYNC_POS_POL 0x00000002 + + +/* DV timings */ +struct v4l2_dv_timings { + __u32 type; + union { + struct v4l2_bt_timings bt; + __u32 reserved[32]; + }; +} __attribute__ ((packed)); + +/* Values for the type field */ +#define V4L2_DV_BT_656_1120 0 /* BT.656/1120 timing type */ + +/* + * V I D E O I N P U T S + */ +struct v4l2_input { + __u32 index; /* Which input */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of input */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 tuner; /* Associated tuner */ + v4l2_std_id std; + __u32 status; + __u32 capabilities; + __u32 reserved[3]; +}; + +/* Values for the 'type' field */ +#define V4L2_INPUT_TYPE_TUNER 1 +#define V4L2_INPUT_TYPE_CAMERA 2 + +/* field 'status' - general */ +#define V4L2_IN_ST_NO_POWER 0x00000001 /* Attached device is off */ +#define V4L2_IN_ST_NO_SIGNAL 0x00000002 +#define V4L2_IN_ST_NO_COLOR 0x00000004 + +/* field 'status' - sensor orientation */ +/* If sensor is mounted upside down set both bits */ +#define V4L2_IN_ST_HFLIP 0x00000010 /* Frames are flipped horizontally */ +#define V4L2_IN_ST_VFLIP 0x00000020 /* Frames are flipped vertically */ + +/* field 'status' - analog */ +#define V4L2_IN_ST_NO_H_LOCK 0x00000100 /* No horizontal sync lock */ +#define V4L2_IN_ST_COLOR_KILL 0x00000200 /* Color killer is active */ + +/* field 'status' - digital */ +#define V4L2_IN_ST_NO_SYNC 0x00010000 /* No synchronization lock */ +#define V4L2_IN_ST_NO_EQU 0x00020000 /* No equalizer lock */ +#define V4L2_IN_ST_NO_CARRIER 0x00040000 /* Carrier recovery failed */ + +/* field 'status' - VCR and set-top box */ +#define V4L2_IN_ST_MACROVISION 0x01000000 /* Macrovision detected */ +#define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */ +#define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */ + +/* capabilities flags */ +#define V4L2_IN_CAP_PRESETS 0x00000001 /* Supports S_DV_PRESET */ +#define V4L2_IN_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */ +#define V4L2_IN_CAP_STD 0x00000004 /* Supports S_STD */ + +/* + * V I D E O O U T P U T S + */ +struct v4l2_output { + __u32 index; /* Which output */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of output */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 modulator; /* Associated modulator */ + v4l2_std_id std; + __u32 capabilities; + __u32 reserved[3]; +}; +/* Values for the 'type' field */ +#define V4L2_OUTPUT_TYPE_MODULATOR 1 +#define V4L2_OUTPUT_TYPE_ANALOG 2 +#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3 + +/* capabilities flags */ +#define V4L2_OUT_CAP_PRESETS 0x00000001 /* Supports S_DV_PRESET */ +#define V4L2_OUT_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */ +#define V4L2_OUT_CAP_STD 0x00000004 /* Supports S_STD */ + +/* + * C O N T R O L S + */ +struct v4l2_control { + __u32 id; + __s32 value; +}; + +struct v4l2_ext_control { + __u32 id; + __u32 size; + __u32 reserved2[1]; + union { + __s32 value; + __s64 value64; + char *string; + }; +} __attribute__ ((packed)); + +struct v4l2_ext_controls { + __u32 ctrl_class; + __u32 count; + __u32 error_idx; + __u32 reserved[2]; + struct v4l2_ext_control *controls; +}; + +/* Values for ctrl_class field */ +#define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ +#define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */ +#define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ +#define V4L2_CTRL_CLASS_FM_TX 0x009b0000 /* FM Modulator control class */ +#define V4L2_CTRL_CLASS_FLASH 0x009c0000 /* Camera flash controls */ +#define V4L2_CTRL_CLASS_FM_RX 0x009d0000 /* FM Tuner control class */ + +#define V4L2_CTRL_ID_MASK (0x0fffffff) +#define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) +#define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000) + +enum v4l2_ctrl_type { + V4L2_CTRL_TYPE_INTEGER = 1, + V4L2_CTRL_TYPE_BOOLEAN = 2, + V4L2_CTRL_TYPE_MENU = 3, + V4L2_CTRL_TYPE_BUTTON = 4, + V4L2_CTRL_TYPE_INTEGER64 = 5, + V4L2_CTRL_TYPE_CTRL_CLASS = 6, + V4L2_CTRL_TYPE_STRING = 7, + V4L2_CTRL_TYPE_BITMASK = 8, +}; + +/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ +struct v4l2_queryctrl { + __u32 id; + enum v4l2_ctrl_type type; + __u8 name[32]; /* Whatever */ + __s32 minimum; /* Note signedness */ + __s32 maximum; + __s32 step; + __s32 default_value; + __u32 flags; + __u32 reserved[2]; +}; + +/* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */ +struct v4l2_querymenu { + __u32 id; + __u32 index; + __u8 name[32]; /* Whatever */ + __u32 reserved; +}; + +/* Control flags */ +#define V4L2_CTRL_FLAG_DISABLED 0x0001 +#define V4L2_CTRL_FLAG_GRABBED 0x0002 +#define V4L2_CTRL_FLAG_READ_ONLY 0x0004 +#define V4L2_CTRL_FLAG_UPDATE 0x0008 +#define V4L2_CTRL_FLAG_INACTIVE 0x0010 +#define V4L2_CTRL_FLAG_SLIDER 0x0020 +#define V4L2_CTRL_FLAG_WRITE_ONLY 0x0040 +#define V4L2_CTRL_FLAG_VOLATILE 0x0080 + +/* Query flag, to be ORed with the control ID */ +#define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000 + +/* User-class control IDs defined by V4L2 */ +#define V4L2_CID_MAX_CTRLS 1024 +#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) +#define V4L2_CID_USER_BASE V4L2_CID_BASE +/* IDs reserved for driver specific controls */ +#define V4L2_CID_PRIVATE_BASE 0x08000000 + +#define V4L2_CID_USER_CLASS (V4L2_CTRL_CLASS_USER | 1) +#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0) +#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1) +#define V4L2_CID_SATURATION (V4L2_CID_BASE+2) +#define V4L2_CID_HUE (V4L2_CID_BASE+3) +#define V4L2_CID_AUDIO_VOLUME (V4L2_CID_BASE+5) +#define V4L2_CID_AUDIO_BALANCE (V4L2_CID_BASE+6) +#define V4L2_CID_AUDIO_BASS (V4L2_CID_BASE+7) +#define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8) +#define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9) +#define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10) +#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) /* Deprecated */ +#define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12) +#define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13) +#define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14) +#define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15) +#define V4L2_CID_GAMMA (V4L2_CID_BASE+16) +#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* Deprecated */ +#define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17) +#define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18) +#define V4L2_CID_GAIN (V4L2_CID_BASE+19) +#define V4L2_CID_HFLIP (V4L2_CID_BASE+20) +#define V4L2_CID_VFLIP (V4L2_CID_BASE+21) + +/* Deprecated; use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */ +#define V4L2_CID_HCENTER (V4L2_CID_BASE+22) +#define V4L2_CID_VCENTER (V4L2_CID_BASE+23) + +#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24) +enum v4l2_power_line_frequency { + V4L2_CID_POWER_LINE_FREQUENCY_DISABLED = 0, + V4L2_CID_POWER_LINE_FREQUENCY_50HZ = 1, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ = 2, + V4L2_CID_POWER_LINE_FREQUENCY_AUTO = 3, +}; +#define V4L2_CID_HUE_AUTO (V4L2_CID_BASE+25) +#define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE+26) +#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) +#define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28) +#define V4L2_CID_CHROMA_AGC (V4L2_CID_BASE+29) +#define V4L2_CID_COLOR_KILLER (V4L2_CID_BASE+30) +#define V4L2_CID_COLORFX (V4L2_CID_BASE+31) +enum v4l2_colorfx { + V4L2_COLORFX_NONE = 0, + V4L2_COLORFX_BW = 1, + V4L2_COLORFX_SEPIA = 2, + V4L2_COLORFX_NEGATIVE = 3, + V4L2_COLORFX_EMBOSS = 4, + V4L2_COLORFX_SKETCH = 5, + V4L2_COLORFX_SKY_BLUE = 6, + V4L2_COLORFX_GRASS_GREEN = 7, + V4L2_COLORFX_SKIN_WHITEN = 8, + V4L2_COLORFX_VIVID = 9, +}; +#define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) +#define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) + +#define V4L2_CID_ROTATE (V4L2_CID_BASE+34) +#define V4L2_CID_BG_COLOR (V4L2_CID_BASE+35) + +#define V4L2_CID_CHROMA_GAIN (V4L2_CID_BASE+36) + +#define V4L2_CID_ILLUMINATORS_1 (V4L2_CID_BASE+37) +#define V4L2_CID_ILLUMINATORS_2 (V4L2_CID_BASE+38) + +#define V4L2_CID_MIN_BUFFERS_FOR_CAPTURE (V4L2_CID_BASE+39) +#define V4L2_CID_MIN_BUFFERS_FOR_OUTPUT (V4L2_CID_BASE+40) + +#define V4L2_CID_ALPHA_COMPONENT (V4L2_CID_BASE+41) + +/* last CID + 1 */ +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+42) + +/* MPEG-class control IDs defined by V4L2 */ +#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) +#define V4L2_CID_MPEG_CLASS (V4L2_CTRL_CLASS_MPEG | 1) + +/* MPEG streams, specific to multiplexed streams */ +#define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_MPEG_BASE+0) +enum v4l2_mpeg_stream_type { + V4L2_MPEG_STREAM_TYPE_MPEG2_PS = 0, /* MPEG-2 program stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_TS = 1, /* MPEG-2 transport stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_SS = 2, /* MPEG-1 system stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_DVD = 3, /* MPEG-2 DVD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_VCD = 4, /* MPEG-1 VCD-compatible stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */ +}; +#define V4L2_CID_MPEG_STREAM_PID_PMT (V4L2_CID_MPEG_BASE+1) +#define V4L2_CID_MPEG_STREAM_PID_AUDIO (V4L2_CID_MPEG_BASE+2) +#define V4L2_CID_MPEG_STREAM_PID_VIDEO (V4L2_CID_MPEG_BASE+3) +#define V4L2_CID_MPEG_STREAM_PID_PCR (V4L2_CID_MPEG_BASE+4) +#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO (V4L2_CID_MPEG_BASE+5) +#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO (V4L2_CID_MPEG_BASE+6) +#define V4L2_CID_MPEG_STREAM_VBI_FMT (V4L2_CID_MPEG_BASE+7) +enum v4l2_mpeg_stream_vbi_fmt { + V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */ + V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, IVTV format */ +}; + +/* MPEG audio controls specific to multiplexed streams */ +#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ (V4L2_CID_MPEG_BASE+100) +enum v4l2_mpeg_audio_sampling_freq { + V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2, +}; +#define V4L2_CID_MPEG_AUDIO_ENCODING (V4L2_CID_MPEG_BASE+101) +enum v4l2_mpeg_audio_encoding { + V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, + V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, + V4L2_MPEG_AUDIO_ENCODING_AAC = 3, + V4L2_MPEG_AUDIO_ENCODING_AC3 = 4, +}; +#define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) +enum v4l2_mpeg_audio_l1_bitrate { + V4L2_MPEG_AUDIO_L1_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L1_BITRATE_64K = 1, + V4L2_MPEG_AUDIO_L1_BITRATE_96K = 2, + V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3, + V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4, + V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5, + V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6, + V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7, + V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8, + V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9, + V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10, + V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11, + V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12, + V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_L2_BITRATE (V4L2_CID_MPEG_BASE+103) +enum v4l2_mpeg_audio_l2_bitrate { + V4L2_MPEG_AUDIO_L2_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L2_BITRATE_48K = 1, + V4L2_MPEG_AUDIO_L2_BITRATE_56K = 2, + V4L2_MPEG_AUDIO_L2_BITRATE_64K = 3, + V4L2_MPEG_AUDIO_L2_BITRATE_80K = 4, + V4L2_MPEG_AUDIO_L2_BITRATE_96K = 5, + V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6, + V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7, + V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8, + V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9, + V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10, + V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11, + V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12, + V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_L3_BITRATE (V4L2_CID_MPEG_BASE+104) +enum v4l2_mpeg_audio_l3_bitrate { + V4L2_MPEG_AUDIO_L3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_L3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_L3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_L3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_L3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_L3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_MODE (V4L2_CID_MPEG_BASE+105) +enum v4l2_mpeg_audio_mode { + V4L2_MPEG_AUDIO_MODE_STEREO = 0, + V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1, + V4L2_MPEG_AUDIO_MODE_DUAL = 2, + V4L2_MPEG_AUDIO_MODE_MONO = 3, +}; +#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION (V4L2_CID_MPEG_BASE+106) +enum v4l2_mpeg_audio_mode_extension { + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4 = 0, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8 = 1, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3, +}; +#define V4L2_CID_MPEG_AUDIO_EMPHASIS (V4L2_CID_MPEG_BASE+107) +enum v4l2_mpeg_audio_emphasis { + V4L2_MPEG_AUDIO_EMPHASIS_NONE = 0, + V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1, + V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17 = 2, +}; +#define V4L2_CID_MPEG_AUDIO_CRC (V4L2_CID_MPEG_BASE+108) +enum v4l2_mpeg_audio_crc { + V4L2_MPEG_AUDIO_CRC_NONE = 0, + V4L2_MPEG_AUDIO_CRC_CRC16 = 1, +}; +#define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_MPEG_BASE+109) +#define V4L2_CID_MPEG_AUDIO_AAC_BITRATE (V4L2_CID_MPEG_BASE+110) +#define V4L2_CID_MPEG_AUDIO_AC3_BITRATE (V4L2_CID_MPEG_BASE+111) +enum v4l2_mpeg_audio_ac3_bitrate { + V4L2_MPEG_AUDIO_AC3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_AC3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_AC3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_AC3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_AC3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_AC3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_AC3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13, + V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14, + V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15, + V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16, + V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, + V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, +}; + +/* MPEG video controls specific to multiplexed streams */ +#define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) +enum v4l2_mpeg_video_encoding { + V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2, +}; +#define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_MPEG_BASE+201) +enum v4l2_mpeg_video_aspect { + V4L2_MPEG_VIDEO_ASPECT_1x1 = 0, + V4L2_MPEG_VIDEO_ASPECT_4x3 = 1, + V4L2_MPEG_VIDEO_ASPECT_16x9 = 2, + V4L2_MPEG_VIDEO_ASPECT_221x100 = 3, +}; +#define V4L2_CID_MPEG_VIDEO_B_FRAMES (V4L2_CID_MPEG_BASE+202) +#define V4L2_CID_MPEG_VIDEO_GOP_SIZE (V4L2_CID_MPEG_BASE+203) +#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE (V4L2_CID_MPEG_BASE+204) +#define V4L2_CID_MPEG_VIDEO_PULLDOWN (V4L2_CID_MPEG_BASE+205) +#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE (V4L2_CID_MPEG_BASE+206) +enum v4l2_mpeg_video_bitrate_mode { + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1, +}; +#define V4L2_CID_MPEG_VIDEO_BITRATE (V4L2_CID_MPEG_BASE+207) +#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK (V4L2_CID_MPEG_BASE+208) +#define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209) +#define V4L2_CID_MPEG_VIDEO_MUTE (V4L2_CID_MPEG_BASE+210) +#define V4L2_CID_MPEG_VIDEO_MUTE_YUV (V4L2_CID_MPEG_BASE+211) +#define V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE (V4L2_CID_MPEG_BASE+212) +#define V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER (V4L2_CID_MPEG_BASE+213) +#define V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB (V4L2_CID_MPEG_BASE+214) +#define V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE (V4L2_CID_MPEG_BASE+215) +#define V4L2_CID_MPEG_VIDEO_HEADER_MODE (V4L2_CID_MPEG_BASE+216) +enum v4l2_mpeg_video_header_mode { + V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE = 0, + V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME = 1, + +}; +#define V4L2_CID_MPEG_VIDEO_MAX_REF_PIC (V4L2_CID_MPEG_BASE+217) +#define V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE (V4L2_CID_MPEG_BASE+218) +#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES (V4L2_CID_MPEG_BASE+219) +#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB (V4L2_CID_MPEG_BASE+220) +#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE (V4L2_CID_MPEG_BASE+221) +enum v4l2_mpeg_video_multi_slice_mode { + V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE = 0, + V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB = 1, + V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES = 2, +}; +#define V4L2_CID_MPEG_VIDEO_VBV_SIZE (V4L2_CID_MPEG_BASE+222) +#define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP (V4L2_CID_MPEG_BASE+300) +#define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP (V4L2_CID_MPEG_BASE+301) +#define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP (V4L2_CID_MPEG_BASE+302) +#define V4L2_CID_MPEG_VIDEO_H263_MIN_QP (V4L2_CID_MPEG_BASE+303) +#define V4L2_CID_MPEG_VIDEO_H263_MAX_QP (V4L2_CID_MPEG_BASE+304) +#define V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP (V4L2_CID_MPEG_BASE+350) +#define V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP (V4L2_CID_MPEG_BASE+351) +#define V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP (V4L2_CID_MPEG_BASE+352) +#define V4L2_CID_MPEG_VIDEO_H264_MIN_QP (V4L2_CID_MPEG_BASE+353) +#define V4L2_CID_MPEG_VIDEO_H264_MAX_QP (V4L2_CID_MPEG_BASE+354) +#define V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM (V4L2_CID_MPEG_BASE+355) +#define V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE (V4L2_CID_MPEG_BASE+356) +#define V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE (V4L2_CID_MPEG_BASE+357) +enum v4l2_mpeg_video_h264_entropy_mode { + V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC = 0, + V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC = 1, +}; +#define V4L2_CID_MPEG_VIDEO_H264_I_PERIOD (V4L2_CID_MPEG_BASE+358) +#define V4L2_CID_MPEG_VIDEO_H264_LEVEL (V4L2_CID_MPEG_BASE+359) +enum v4l2_mpeg_video_h264_level { + V4L2_MPEG_VIDEO_H264_LEVEL_1_0 = 0, + V4L2_MPEG_VIDEO_H264_LEVEL_1B = 1, + V4L2_MPEG_VIDEO_H264_LEVEL_1_1 = 2, + V4L2_MPEG_VIDEO_H264_LEVEL_1_2 = 3, + V4L2_MPEG_VIDEO_H264_LEVEL_1_3 = 4, + V4L2_MPEG_VIDEO_H264_LEVEL_2_0 = 5, + V4L2_MPEG_VIDEO_H264_LEVEL_2_1 = 6, + V4L2_MPEG_VIDEO_H264_LEVEL_2_2 = 7, + V4L2_MPEG_VIDEO_H264_LEVEL_3_0 = 8, + V4L2_MPEG_VIDEO_H264_LEVEL_3_1 = 9, + V4L2_MPEG_VIDEO_H264_LEVEL_3_2 = 10, + V4L2_MPEG_VIDEO_H264_LEVEL_4_0 = 11, + V4L2_MPEG_VIDEO_H264_LEVEL_4_1 = 12, + V4L2_MPEG_VIDEO_H264_LEVEL_4_2 = 13, + V4L2_MPEG_VIDEO_H264_LEVEL_5_0 = 14, + V4L2_MPEG_VIDEO_H264_LEVEL_5_1 = 15, +}; +#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA (V4L2_CID_MPEG_BASE+360) +#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA (V4L2_CID_MPEG_BASE+361) +#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE (V4L2_CID_MPEG_BASE+362) +enum v4l2_mpeg_video_h264_loop_filter_mode { + V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED = 0, + V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED = 1, + V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY = 2, +}; +#define V4L2_CID_MPEG_VIDEO_H264_PROFILE (V4L2_CID_MPEG_BASE+363) +enum v4l2_mpeg_video_h264_profile { + V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE = 0, + V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE = 1, + V4L2_MPEG_VIDEO_H264_PROFILE_MAIN = 2, + V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED = 3, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH = 4, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10 = 5, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422 = 6, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE = 7, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA = 8, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA = 9, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA = 10, + V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA = 11, + V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE = 12, + V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH = 13, + V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA = 14, + V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH = 15, + V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH = 16, +}; +#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT (V4L2_CID_MPEG_BASE+364) +#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH (V4L2_CID_MPEG_BASE+365) +#define V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE (V4L2_CID_MPEG_BASE+366) +#define V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC (V4L2_CID_MPEG_BASE+367) +enum v4l2_mpeg_video_h264_vui_sar_idc { + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED = 0, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1 = 1, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11 = 2, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11 = 3, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11 = 4, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33 = 5, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11 = 6, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11 = 7, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11 = 8, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33 = 9, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11 = 10, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11 = 11, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33 = 12, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99 = 13, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3 = 14, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2 = 15, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1 = 16, + V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED = 17, +}; +#define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP (V4L2_CID_MPEG_BASE+400) +#define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP (V4L2_CID_MPEG_BASE+401) +#define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP (V4L2_CID_MPEG_BASE+402) +#define V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP (V4L2_CID_MPEG_BASE+403) +#define V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP (V4L2_CID_MPEG_BASE+404) +#define V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL (V4L2_CID_MPEG_BASE+405) +enum v4l2_mpeg_video_mpeg4_level { + V4L2_MPEG_VIDEO_MPEG4_LEVEL_0 = 0, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B = 1, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_1 = 2, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_2 = 3, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_3 = 4, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B = 5, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_4 = 6, + V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 = 7, +}; +#define V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE (V4L2_CID_MPEG_BASE+406) +enum v4l2_mpeg_video_mpeg4_profile { + V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE = 0, + V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE = 1, + V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE = 2, + V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE = 3, + V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY = 4, +}; +#define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL (V4L2_CID_MPEG_BASE+407) + +/* MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */ +#define V4L2_CID_MPEG_CX2341X_BASE (V4L2_CTRL_CLASS_MPEG | 0x1000) +#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+0) +enum v4l2_mpeg_cx2341x_video_spatial_filter_mode { + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+1) +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+2) +enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type { + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE = 3, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+3) +enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type { + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+4) +enum v4l2_mpeg_cx2341x_video_temporal_filter_mode { + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+5) +#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+6) +enum v4l2_mpeg_cx2341x_video_median_filter_type { + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG = 4, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+7) +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+8) +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+9) +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+10) +#define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS (V4L2_CID_MPEG_CX2341X_BASE+11) + +/* MPEG-class control IDs specific to the Samsung MFC 5.1 driver as defined by V4L2 */ +#define V4L2_CID_MPEG_MFC51_BASE (V4L2_CTRL_CLASS_MPEG | 0x1100) + +#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY (V4L2_CID_MPEG_MFC51_BASE+0) +#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE (V4L2_CID_MPEG_MFC51_BASE+1) +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE (V4L2_CID_MPEG_MFC51_BASE+2) +enum v4l2_mpeg_mfc51_video_frame_skip_mode { + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED = 0, + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT = 1, + V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT = 2, +}; +#define V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE (V4L2_CID_MPEG_MFC51_BASE+3) +enum v4l2_mpeg_mfc51_video_force_frame_type { + V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED = 0, + V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME = 1, + V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED = 2, +}; +#define V4L2_CID_MPEG_MFC51_VIDEO_PADDING (V4L2_CID_MPEG_MFC51_BASE+4) +#define V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV (V4L2_CID_MPEG_MFC51_BASE+5) +#define V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT (V4L2_CID_MPEG_MFC51_BASE+6) +#define V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF (V4L2_CID_MPEG_MFC51_BASE+7) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY (V4L2_CID_MPEG_MFC51_BASE+50) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK (V4L2_CID_MPEG_MFC51_BASE+51) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH (V4L2_CID_MPEG_MFC51_BASE+52) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC (V4L2_CID_MPEG_MFC51_BASE+53) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P (V4L2_CID_MPEG_MFC51_BASE+54) + +/* Camera class control IDs */ +#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900) +#define V4L2_CID_CAMERA_CLASS (V4L2_CTRL_CLASS_CAMERA | 1) + +#define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_CAMERA_CLASS_BASE+1) +enum v4l2_exposure_auto_type { + V4L2_EXPOSURE_AUTO = 0, + V4L2_EXPOSURE_MANUAL = 1, + V4L2_EXPOSURE_SHUTTER_PRIORITY = 2, + V4L2_EXPOSURE_APERTURE_PRIORITY = 3 +}; +#define V4L2_CID_EXPOSURE_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+2) +#define V4L2_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_CAMERA_CLASS_BASE+3) + +#define V4L2_CID_PAN_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+4) +#define V4L2_CID_TILT_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+5) +#define V4L2_CID_PAN_RESET (V4L2_CID_CAMERA_CLASS_BASE+6) +#define V4L2_CID_TILT_RESET (V4L2_CID_CAMERA_CLASS_BASE+7) + +#define V4L2_CID_PAN_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+8) +#define V4L2_CID_TILT_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+9) + +#define V4L2_CID_FOCUS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+10) +#define V4L2_CID_FOCUS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+11) +#define V4L2_CID_FOCUS_AUTO (V4L2_CID_CAMERA_CLASS_BASE+12) + +#define V4L2_CID_ZOOM_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+13) +#define V4L2_CID_ZOOM_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+14) +#define V4L2_CID_ZOOM_CONTINUOUS (V4L2_CID_CAMERA_CLASS_BASE+15) + +#define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) + +#define V4L2_CID_IRIS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+17) +#define V4L2_CID_IRIS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+18) + +/* FM Modulator class control IDs */ +#define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) +#define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1) + +#define V4L2_CID_RDS_TX_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 1) +#define V4L2_CID_RDS_TX_PI (V4L2_CID_FM_TX_CLASS_BASE + 2) +#define V4L2_CID_RDS_TX_PTY (V4L2_CID_FM_TX_CLASS_BASE + 3) +#define V4L2_CID_RDS_TX_PS_NAME (V4L2_CID_FM_TX_CLASS_BASE + 5) +#define V4L2_CID_RDS_TX_RADIO_TEXT (V4L2_CID_FM_TX_CLASS_BASE + 6) + +#define V4L2_CID_AUDIO_LIMITER_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 64) +#define V4L2_CID_AUDIO_LIMITER_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 65) +#define V4L2_CID_AUDIO_LIMITER_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 66) + +#define V4L2_CID_AUDIO_COMPRESSION_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 80) +#define V4L2_CID_AUDIO_COMPRESSION_GAIN (V4L2_CID_FM_TX_CLASS_BASE + 81) +#define V4L2_CID_AUDIO_COMPRESSION_THRESHOLD (V4L2_CID_FM_TX_CLASS_BASE + 82) +#define V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME (V4L2_CID_FM_TX_CLASS_BASE + 83) +#define V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 84) + +#define V4L2_CID_PILOT_TONE_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 96) +#define V4L2_CID_PILOT_TONE_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 97) +#define V4L2_CID_PILOT_TONE_FREQUENCY (V4L2_CID_FM_TX_CLASS_BASE + 98) + +#define V4L2_CID_TUNE_PREEMPHASIS (V4L2_CID_FM_TX_CLASS_BASE + 112) +enum v4l2_preemphasis { + V4L2_PREEMPHASIS_DISABLED = 0, + V4L2_PREEMPHASIS_50_uS = 1, + V4L2_PREEMPHASIS_75_uS = 2, +}; +#define V4L2_CID_TUNE_POWER_LEVEL (V4L2_CID_FM_TX_CLASS_BASE + 113) +#define V4L2_CID_TUNE_ANTENNA_CAPACITOR (V4L2_CID_FM_TX_CLASS_BASE + 114) +/* FM Tuner class control IDs */ +#define V4L2_CID_FM_RX_CLASS_BASE (V4L2_CTRL_CLASS_FM_RX | 0x900) +#define V4L2_CID_FM_RX_CLASS (V4L2_CTRL_CLASS_FM_RX | 1) + +#define V4L2_CID_TUNE_DEEMPHASIS (V4L2_CID_FM_RX_CLASS_BASE + 1) +enum v4l2_deemphasis { + V4L2_DEEMPHASIS_DISABLED = 0, + V4L2_DEEMPHASIS_50_uS = 1, + V4L2_DEEMPHASIS_75_uS = 2, +}; + +/* Flash and privacy (indicator) light controls */ +#define V4L2_CID_FLASH_CLASS_BASE (V4L2_CTRL_CLASS_FLASH | 0x900) +#define V4L2_CID_FLASH_CLASS (V4L2_CTRL_CLASS_FLASH | 1) + +#define V4L2_CID_FLASH_LED_MODE (V4L2_CID_FLASH_CLASS_BASE + 1) +enum v4l2_flash_led_mode { + V4L2_FLASH_LED_MODE_NONE, + V4L2_FLASH_LED_MODE_FLASH, + V4L2_FLASH_LED_MODE_TORCH, +}; + +#define V4L2_CID_FLASH_STROBE_SOURCE (V4L2_CID_FLASH_CLASS_BASE + 2) +enum v4l2_flash_strobe_source { + V4L2_FLASH_STROBE_SOURCE_SOFTWARE, + V4L2_FLASH_STROBE_SOURCE_EXTERNAL, +}; + +#define V4L2_CID_FLASH_STROBE (V4L2_CID_FLASH_CLASS_BASE + 3) +#define V4L2_CID_FLASH_STROBE_STOP (V4L2_CID_FLASH_CLASS_BASE + 4) +#define V4L2_CID_FLASH_STROBE_STATUS (V4L2_CID_FLASH_CLASS_BASE + 5) + +#define V4L2_CID_FLASH_TIMEOUT (V4L2_CID_FLASH_CLASS_BASE + 6) +#define V4L2_CID_FLASH_INTENSITY (V4L2_CID_FLASH_CLASS_BASE + 7) +#define V4L2_CID_FLASH_TORCH_INTENSITY (V4L2_CID_FLASH_CLASS_BASE + 8) +#define V4L2_CID_FLASH_INDICATOR_INTENSITY (V4L2_CID_FLASH_CLASS_BASE + 9) + +#define V4L2_CID_FLASH_FAULT (V4L2_CID_FLASH_CLASS_BASE + 10) +#define V4L2_FLASH_FAULT_OVER_VOLTAGE (1 << 0) +#define V4L2_FLASH_FAULT_TIMEOUT (1 << 1) +#define V4L2_FLASH_FAULT_OVER_TEMPERATURE (1 << 2) +#define V4L2_FLASH_FAULT_SHORT_CIRCUIT (1 << 3) +#define V4L2_FLASH_FAULT_OVER_CURRENT (1 << 4) +#define V4L2_FLASH_FAULT_INDICATOR (1 << 5) + +#define V4L2_CID_FLASH_CHARGE (V4L2_CID_FLASH_CLASS_BASE + 11) +#define V4L2_CID_FLASH_READY (V4L2_CID_FLASH_CLASS_BASE + 12) + +/* + * T U N I N G + */ +struct v4l2_tuner { + __u32 index; + __u8 name[32]; + enum v4l2_tuner_type type; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 rxsubchans; + __u32 audmode; + __s32 signal; + __s32 afc; + __u32 reserved[4]; +}; + +struct v4l2_modulator { + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 txsubchans; + __u32 reserved[4]; +}; + +/* Flags for the 'capability' field */ +#define V4L2_TUNER_CAP_LOW 0x0001 +#define V4L2_TUNER_CAP_NORM 0x0002 +#define V4L2_TUNER_CAP_STEREO 0x0010 +#define V4L2_TUNER_CAP_LANG2 0x0020 +#define V4L2_TUNER_CAP_SAP 0x0020 +#define V4L2_TUNER_CAP_LANG1 0x0040 +#define V4L2_TUNER_CAP_RDS 0x0080 +#define V4L2_TUNER_CAP_RDS_BLOCK_IO 0x0100 +#define V4L2_TUNER_CAP_RDS_CONTROLS 0x0200 + +/* Flags for the 'rxsubchans' field */ +#define V4L2_TUNER_SUB_MONO 0x0001 +#define V4L2_TUNER_SUB_STEREO 0x0002 +#define V4L2_TUNER_SUB_LANG2 0x0004 +#define V4L2_TUNER_SUB_SAP 0x0004 +#define V4L2_TUNER_SUB_LANG1 0x0008 +#define V4L2_TUNER_SUB_RDS 0x0010 + +/* Values for the 'audmode' field */ +#define V4L2_TUNER_MODE_MONO 0x0000 +#define V4L2_TUNER_MODE_STEREO 0x0001 +#define V4L2_TUNER_MODE_LANG2 0x0002 +#define V4L2_TUNER_MODE_SAP 0x0002 +#define V4L2_TUNER_MODE_LANG1 0x0003 +#define V4L2_TUNER_MODE_LANG1_LANG2 0x0004 + +struct v4l2_frequency { + __u32 tuner; + enum v4l2_tuner_type type; + __u32 frequency; + __u32 reserved[8]; +}; + +struct v4l2_hw_freq_seek { + __u32 tuner; + enum v4l2_tuner_type type; + __u32 seek_upward; + __u32 wrap_around; + __u32 spacing; + __u32 reserved[7]; +}; + +/* + * R D S + */ + +struct v4l2_rds_data { + __u8 lsb; + __u8 msb; + __u8 block; +} __attribute__ ((packed)); + +#define V4L2_RDS_BLOCK_MSK 0x7 +#define V4L2_RDS_BLOCK_A 0 +#define V4L2_RDS_BLOCK_B 1 +#define V4L2_RDS_BLOCK_C 2 +#define V4L2_RDS_BLOCK_D 3 +#define V4L2_RDS_BLOCK_C_ALT 4 +#define V4L2_RDS_BLOCK_INVALID 7 + +#define V4L2_RDS_BLOCK_CORRECTED 0x40 +#define V4L2_RDS_BLOCK_ERROR 0x80 + +/* + * A U D I O + */ +struct v4l2_audio { + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; +}; + +/* Flags for the 'capability' field */ +#define V4L2_AUDCAP_STEREO 0x00001 +#define V4L2_AUDCAP_AVL 0x00002 + +/* Flags for the 'mode' field */ +#define V4L2_AUDMODE_AVL 0x00001 + +struct v4l2_audioout { + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; +}; + +/* + * M P E G S E R V I C E S + * + * NOTE: EXPERIMENTAL API + */ +#if 1 +#define V4L2_ENC_IDX_FRAME_I (0) +#define V4L2_ENC_IDX_FRAME_P (1) +#define V4L2_ENC_IDX_FRAME_B (2) +#define V4L2_ENC_IDX_FRAME_MASK (0xf) + +struct v4l2_enc_idx_entry { + __u64 offset; + __u64 pts; + __u32 length; + __u32 flags; + __u32 reserved[2]; +}; + +#define V4L2_ENC_IDX_ENTRIES (64) +struct v4l2_enc_idx { + __u32 entries; + __u32 entries_cap; + __u32 reserved[4]; + 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) +#define V4L2_ENC_CMD_RESUME (3) + +/* Flags for V4L2_ENC_CMD_STOP */ +#define V4L2_ENC_CMD_STOP_AT_GOP_END (1 << 0) + +struct v4l2_encoder_cmd { + __u32 cmd; + __u32 flags; + union { + struct { + __u32 data[8]; + } raw; + }; +}; + +#endif + + +/* + * D A T A S E R V I C E S ( V B I ) + * + * Data services API by Michael Schimek + */ + +/* Raw VBI */ +struct v4l2_vbi_format { + __u32 sampling_rate; /* in 1 Hz */ + __u32 offset; + __u32 samples_per_line; + __u32 sample_format; /* V4L2_PIX_FMT_* */ + __s32 start[2]; + __u32 count[2]; + __u32 flags; /* V4L2_VBI_* */ + __u32 reserved[2]; /* must be zero */ +}; + +/* VBI flags */ +#define V4L2_VBI_UNSYNC (1 << 0) +#define V4L2_VBI_INTERLACED (1 << 1) + +/* Sliced VBI + * + * This implements is a proposal V4L2 API to allow SLICED VBI + * required for some hardware encoders. It should change without + * notice in the definitive implementation. + */ + +struct v4l2_sliced_vbi_format { + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + __u32 io_size; + __u32 reserved[2]; /* must be zero */ +}; + +/* Teletext World System Teletext + (WST), defined on ITU-R BT.653-2 */ +#define V4L2_SLICED_TELETEXT_B (0x0001) +/* Video Program System, defined on ETS 300 231*/ +#define V4L2_SLICED_VPS (0x0400) +/* Closed Caption, defined on EIA-608 */ +#define V4L2_SLICED_CAPTION_525 (0x1000) +/* Wide Screen System, defined on ITU-R BT1119.1 */ +#define V4L2_SLICED_WSS_625 (0x4000) + +#define V4L2_SLICED_VBI_525 (V4L2_SLICED_CAPTION_525) +#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625) + +struct v4l2_sliced_vbi_cap { + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + enum v4l2_buf_type type; + __u32 reserved[3]; /* must be 0 */ +}; + +struct v4l2_sliced_vbi_data { + __u32 id; + __u32 field; /* 0: first field, 1: second field */ + __u32 line; /* 1-23 */ + __u32 reserved; /* must be 0 */ + __u8 data[48]; +}; + +/* + * Sliced VBI data inserted into MPEG Streams + */ + +/* + * V4L2_MPEG_STREAM_VBI_FMT_IVTV: + * + * Structure of payload contained in an MPEG 2 Private Stream 1 PES Packet in an + * MPEG-2 Program Pack that contains V4L2_MPEG_STREAM_VBI_FMT_IVTV Sliced VBI + * data + * + * Note, the MPEG-2 Program Pack and Private Stream 1 PES packet header + * definitions are not included here. See the MPEG-2 specifications for details + * on these headers. + */ + +/* Line type IDs */ +#define V4L2_MPEG_VBI_IVTV_TELETEXT_B (1) +#define V4L2_MPEG_VBI_IVTV_CAPTION_525 (4) +#define V4L2_MPEG_VBI_IVTV_WSS_625 (5) +#define V4L2_MPEG_VBI_IVTV_VPS (7) + +struct v4l2_mpeg_vbi_itv0_line { + __u8 id; /* One of V4L2_MPEG_VBI_IVTV_* above */ + __u8 data[42]; /* Sliced VBI data for the line */ +} __attribute__ ((packed)); + +struct v4l2_mpeg_vbi_itv0 { + __le32 linemask[2]; /* Bitmasks of VBI service lines present */ + struct v4l2_mpeg_vbi_itv0_line line[35]; +} __attribute__ ((packed)); + +struct v4l2_mpeg_vbi_ITV0 { + struct v4l2_mpeg_vbi_itv0_line line[36]; +} __attribute__ ((packed)); + +#define V4L2_MPEG_VBI_IVTV_MAGIC0 "itv0" +#define V4L2_MPEG_VBI_IVTV_MAGIC1 "ITV0" + +struct v4l2_mpeg_vbi_fmt_ivtv { + __u8 magic[4]; + union { + struct v4l2_mpeg_vbi_itv0 itv0; + struct v4l2_mpeg_vbi_ITV0 ITV0; + }; +} __attribute__ ((packed)); + +/* + * A G G R E G A T E S T R U C T U R E S + */ + +/** + * struct v4l2_plane_pix_format - additional, per-plane format definition + * @sizeimage: maximum size in bytes required for data, for which + * this plane will be used + * @bytesperline: distance in bytes between the leftmost pixels in two + * adjacent lines + */ +struct v4l2_plane_pix_format { + __u32 sizeimage; + __u16 bytesperline; + __u16 reserved[7]; +} __attribute__ ((packed)); + +/** + * struct v4l2_pix_format_mplane - multiplanar format definition + * @width: image width in pixels + * @height: image height in pixels + * @pixelformat: little endian four character code (fourcc) + * @field: field order (for interlaced video) + * @colorspace: supplemental to pixelformat + * @plane_fmt: per-plane information + * @num_planes: number of planes for this format + */ +struct v4l2_pix_format_mplane { + __u32 width; + __u32 height; + __u32 pixelformat; + enum v4l2_field field; + enum v4l2_colorspace colorspace; + + struct v4l2_plane_pix_format plane_fmt[VIDEO_MAX_PLANES]; + __u8 num_planes; + __u8 reserved[11]; +} __attribute__ ((packed)); + +/** + * struct v4l2_format - stream data format + * @type: type of the data stream + * @pix: definition of an image format + * @pix_mp: definition of a multiplanar image format + * @win: definition of an overlaid image + * @vbi: raw VBI capture or output parameters + * @sliced: sliced VBI capture or output parameters + * @raw_data: placeholder for future extensions and custom formats + */ +struct v4l2_format { + enum v4l2_buf_type type; + union { + struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ + struct v4l2_pix_format_mplane pix_mp; /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */ + struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ + struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */ + struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */ + __u8 raw_data[200]; /* user-defined */ + } fmt; +}; + +/* Stream type-dependent parameters + */ +struct v4l2_streamparm { + enum v4l2_buf_type type; + union { + struct v4l2_captureparm capture; + struct v4l2_outputparm output; + __u8 raw_data[200]; /* user-defined */ + } parm; +}; + +/* + * E V E N T S + */ + +#define V4L2_EVENT_ALL 0 +#define V4L2_EVENT_VSYNC 1 +#define V4L2_EVENT_EOS 2 +#define V4L2_EVENT_CTRL 3 +#define V4L2_EVENT_FRAME_SYNC 4 +#define V4L2_EVENT_PRIVATE_START 0x08000000 + +/* Payload for V4L2_EVENT_VSYNC */ +struct v4l2_event_vsync { + /* Can be V4L2_FIELD_ANY, _NONE, _TOP or _BOTTOM */ + __u8 field; +} __attribute__ ((packed)); + +/* Payload for V4L2_EVENT_CTRL */ +#define V4L2_EVENT_CTRL_CH_VALUE (1 << 0) +#define V4L2_EVENT_CTRL_CH_FLAGS (1 << 1) + +struct v4l2_event_ctrl { + __u32 changes; + __u32 type; + union { + __s32 value; + __s64 value64; + }; + __u32 flags; + __s32 minimum; + __s32 maximum; + __s32 step; + __s32 default_value; +}; + +struct v4l2_event_frame_sync { + __u32 frame_sequence; +}; + +struct v4l2_event { + __u32 type; + union { + struct v4l2_event_vsync vsync; + struct v4l2_event_ctrl ctrl; + struct v4l2_event_frame_sync frame_sync; + __u8 data[64]; + } u; + __u32 pending; + __u32 sequence; + struct timespec timestamp; + __u32 id; + __u32 reserved[8]; +}; + +#define V4L2_EVENT_SUB_FL_SEND_INITIAL (1 << 0) +#define V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK (1 << 1) + +struct v4l2_event_subscription { + __u32 type; + __u32 id; + __u32 flags; + __u32 reserved[5]; +}; + +/* + * A D V A N C E D D E B U G G I N G + * + * NOTE: EXPERIMENTAL API, NEVER RELY ON THIS IN APPLICATIONS! + * FOR DEBUGGING, TESTING AND INTERNAL USE ONLY! + */ + +/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ + +#define V4L2_CHIP_MATCH_HOST 0 /* Match against chip ID on host (0 for the host) */ +#define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver name */ +#define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */ +#define V4L2_CHIP_MATCH_AC97 3 /* Match against anciliary AC97 chip */ + +struct v4l2_dbg_match { + __u32 type; /* Match type */ + union { /* Match this chip, meaning determined by type */ + __u32 addr; + char name[32]; + }; +} __attribute__ ((packed)); + +struct v4l2_dbg_register { + struct v4l2_dbg_match match; + __u32 size; /* register size in bytes */ + __u64 reg; + __u64 val; +} __attribute__ ((packed)); + +/* VIDIOC_DBG_G_CHIP_IDENT */ +struct v4l2_dbg_chip_ident { + struct v4l2_dbg_match match; + __u32 ident; /* chip identifier as specified in */ + __u32 revision; /* chip revision, chip specific */ +} __attribute__ ((packed)); + +/** + * struct v4l2_create_buffers - VIDIOC_CREATE_BUFS argument + * @index: on return, index of the first created buffer + * @count: entry: number of requested buffers, + * return: number of created buffers + * @memory: buffer memory type + * @format: frame format, for which buffers are requested + * @reserved: future extensions + */ +struct v4l2_create_buffers { + __u32 index; + __u32 count; + enum v4l2_memory memory; + struct v4l2_format format; + __u32 reserved[8]; +}; + +/* + * I O C T L C O D E S F O R V I D E O D E V I C E S + * + */ +#define VIDIOC_QUERYCAP _IOR('V', 0, struct v4l2_capability) +#define VIDIOC_RESERVED _IO('V', 1) +#define VIDIOC_ENUM_FMT _IOWR('V', 2, struct v4l2_fmtdesc) +#define VIDIOC_G_FMT _IOWR('V', 4, struct v4l2_format) +#define VIDIOC_S_FMT _IOWR('V', 5, struct v4l2_format) +#define VIDIOC_REQBUFS _IOWR('V', 8, struct v4l2_requestbuffers) +#define VIDIOC_QUERYBUF _IOWR('V', 9, struct v4l2_buffer) +#define VIDIOC_G_FBUF _IOR('V', 10, struct v4l2_framebuffer) +#define VIDIOC_S_FBUF _IOW('V', 11, struct v4l2_framebuffer) +#define VIDIOC_OVERLAY _IOW('V', 14, int) +#define VIDIOC_QBUF _IOWR('V', 15, struct v4l2_buffer) +#define VIDIOC_DQBUF _IOWR('V', 17, struct v4l2_buffer) +#define VIDIOC_STREAMON _IOW('V', 18, int) +#define VIDIOC_STREAMOFF _IOW('V', 19, int) +#define VIDIOC_G_PARM _IOWR('V', 21, struct v4l2_streamparm) +#define VIDIOC_S_PARM _IOWR('V', 22, struct v4l2_streamparm) +#define VIDIOC_G_STD _IOR('V', 23, v4l2_std_id) +#define VIDIOC_S_STD _IOW('V', 24, v4l2_std_id) +#define VIDIOC_ENUMSTD _IOWR('V', 25, struct v4l2_standard) +#define VIDIOC_ENUMINPUT _IOWR('V', 26, struct v4l2_input) +#define VIDIOC_G_CTRL _IOWR('V', 27, struct v4l2_control) +#define VIDIOC_S_CTRL _IOWR('V', 28, struct v4l2_control) +#define VIDIOC_G_TUNER _IOWR('V', 29, struct v4l2_tuner) +#define VIDIOC_S_TUNER _IOW('V', 30, struct v4l2_tuner) +#define VIDIOC_G_AUDIO _IOR('V', 33, struct v4l2_audio) +#define VIDIOC_S_AUDIO _IOW('V', 34, struct v4l2_audio) +#define VIDIOC_QUERYCTRL _IOWR('V', 36, struct v4l2_queryctrl) +#define VIDIOC_QUERYMENU _IOWR('V', 37, struct v4l2_querymenu) +#define VIDIOC_G_INPUT _IOR('V', 38, int) +#define VIDIOC_S_INPUT _IOWR('V', 39, int) +#define VIDIOC_G_OUTPUT _IOR('V', 46, int) +#define VIDIOC_S_OUTPUT _IOWR('V', 47, int) +#define VIDIOC_ENUMOUTPUT _IOWR('V', 48, struct v4l2_output) +#define VIDIOC_G_AUDOUT _IOR('V', 49, struct v4l2_audioout) +#define VIDIOC_S_AUDOUT _IOW('V', 50, struct v4l2_audioout) +#define VIDIOC_G_MODULATOR _IOWR('V', 54, struct v4l2_modulator) +#define VIDIOC_S_MODULATOR _IOW('V', 55, struct v4l2_modulator) +#define VIDIOC_G_FREQUENCY _IOWR('V', 56, struct v4l2_frequency) +#define VIDIOC_S_FREQUENCY _IOW('V', 57, struct v4l2_frequency) +#define VIDIOC_CROPCAP _IOWR('V', 58, struct v4l2_cropcap) +#define VIDIOC_G_CROP _IOWR('V', 59, struct v4l2_crop) +#define VIDIOC_S_CROP _IOW('V', 60, struct v4l2_crop) +#define VIDIOC_G_JPEGCOMP _IOR('V', 61, struct v4l2_jpegcompression) +#define VIDIOC_S_JPEGCOMP _IOW('V', 62, struct v4l2_jpegcompression) +#define VIDIOC_QUERYSTD _IOR('V', 63, v4l2_std_id) +#define VIDIOC_TRY_FMT _IOWR('V', 64, struct v4l2_format) +#define VIDIOC_ENUMAUDIO _IOWR('V', 65, struct v4l2_audio) +#define VIDIOC_ENUMAUDOUT _IOWR('V', 66, struct v4l2_audioout) +#define VIDIOC_G_PRIORITY _IOR('V', 67, enum v4l2_priority) +#define VIDIOC_S_PRIORITY _IOW('V', 68, enum v4l2_priority) +#define VIDIOC_G_SLICED_VBI_CAP _IOWR('V', 69, struct v4l2_sliced_vbi_cap) +#define VIDIOC_LOG_STATUS _IO('V', 70) +#define VIDIOC_G_EXT_CTRLS _IOWR('V', 71, struct v4l2_ext_controls) +#define VIDIOC_S_EXT_CTRLS _IOWR('V', 72, struct v4l2_ext_controls) +#define VIDIOC_TRY_EXT_CTRLS _IOWR('V', 73, struct v4l2_ext_controls) +#if 1 +#define VIDIOC_ENUM_FRAMESIZES _IOWR('V', 74, struct v4l2_frmsizeenum) +#define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct v4l2_frmivalenum) +#define VIDIOC_G_ENC_INDEX _IOR('V', 76, struct v4l2_enc_idx) +#define VIDIOC_ENCODER_CMD _IOWR('V', 77, struct v4l2_encoder_cmd) +#define VIDIOC_TRY_ENCODER_CMD _IOWR('V', 78, struct v4l2_encoder_cmd) +#endif + +#if 1 +/* Experimental, meant for debugging, testing and internal use. + Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined. + You must be root to use these ioctls. Never use these in applications! */ +#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) +#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) + +/* Experimental, meant for debugging, testing and internal use. + Never use this ioctl in applications! */ +#define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_dbg_chip_ident) +#endif + +#define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) +#define VIDIOC_ENUM_DV_PRESETS _IOWR('V', 83, struct v4l2_dv_enum_preset) +#define VIDIOC_S_DV_PRESET _IOWR('V', 84, struct v4l2_dv_preset) +#define VIDIOC_G_DV_PRESET _IOWR('V', 85, struct v4l2_dv_preset) +#define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct v4l2_dv_preset) +#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) +#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) +#define VIDIOC_DQEVENT _IOR('V', 89, struct v4l2_event) +#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription) +#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription) + +/* Experimental, the below two ioctls may change over the next couple of kernel + versions */ +#define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers) +#define VIDIOC_PREPARE_BUF _IOWR('V', 93, struct v4l2_buffer) + +/* Experimental selection API */ +#define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) +#define VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection) + +/* Reminder: when adding new ioctls please add support for them to + drivers/media/video/v4l2-compat-ioctl32.c as well! */ + +#define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ + +#endif /* __LINUX_VIDEODEV2_H */ diff --git a/camera/include/linux/videodev2_exynos_camera.h b/camera/include/linux/videodev2_exynos_camera.h new file mode 100644 index 0000000..b9967ce --- /dev/null +++ b/camera/include/linux/videodev2_exynos_camera.h @@ -0,0 +1,1363 @@ +/* + * Video for Linux Two header file for samsung + * + * Copyright (C) 2009, Dongsoo Nathaniel Kim + * + * This header file contains several v4l2 APIs to be proposed to v4l2 + * community and until bein accepted, will be used restrictly in Samsung's + * camera interface driver FIMC. + * + * 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. + */ + +#ifndef __LINUX_VIDEODEV2_SAMSUNG_H +#define __LINUX_VIDEODEV2_SAMSUNG_H + +/* Values for 'capabilities' field */ +/* Object detection device */ +#define V4L2_CAP_OBJ_RECOGNITION 0x10000000 +/* strobe control */ +#define V4L2_CAP_STROBE 0x20000000 + +#define V4L2_CID_FOCUS_MODE (V4L2_CID_CAMERA_CLASS_BASE+17) +/* Focus Methods */ +enum v4l2_focus_mode { + V4L2_FOCUS_MODE_AUTO = 0, + V4L2_FOCUS_MODE_MACRO = 1, + V4L2_FOCUS_MODE_MANUAL = 2, + V4L2_FOCUS_MODE_LASTP = 2, +}; + +#define V4L2_CID_ZOOM_MODE (V4L2_CID_CAMERA_CLASS_BASE+18) +/* Zoom Methods */ +enum v4l2_zoom_mode { + V4L2_ZOOM_MODE_CONTINUOUS = 0, + V4L2_ZOOM_MODE_OPTICAL = 1, + V4L2_ZOOM_MODE_DIGITAL = 2, + V4L2_ZOOM_MODE_LASTP = 2, +}; + +/* Exposure Methods */ +#define V4L2_CID_PHOTOMETRY (V4L2_CID_CAMERA_CLASS_BASE+19) +enum v4l2_photometry_mode { + V4L2_PHOTOMETRY_MULTISEG = 0, /*Multi Segment*/ + V4L2_PHOTOMETRY_CWA = 1, /*Centre Weighted Average*/ + V4L2_PHOTOMETRY_SPOT = 2, + V4L2_PHOTOMETRY_AFSPOT = 3, /*Spot metering on focused point*/ + V4L2_PHOTOMETRY_LASTP = V4L2_PHOTOMETRY_AFSPOT, +}; + +/* Manual exposure control items menu type: iris, shutter, iso */ +#define V4L2_CID_CAM_APERTURE (V4L2_CID_CAMERA_CLASS_BASE+20) +enum v4l2_aperture_mode { + APERTURE_F_AUTO = 0, + APERTURE_F_2_8, + APERTURE_F_3_2, + APERTURE_F_3_6, + APERTURE_F_4_0, + APERTURE_F_4_5, + APERTURE_F_5_1, + APERTURE_F_5_7, + APERTURE_F_6_4, + APERTURE_F_7_2, + APERTURE_MAX, +}; +#define V4L2_CID_CAM_SHUTTER (V4L2_CID_CAMERA_CLASS_BASE+21) +#define V4L2_CID_CAM_ISO (V4L2_CID_CAMERA_CLASS_BASE+22) + +/* Following CIDs are menu type */ +#define V4L2_CID_SCENEMODE (V4L2_CID_CAMERA_CLASS_BASE+23) +#define V4L2_CID_CAM_STABILIZE (V4L2_CID_CAMERA_CLASS_BASE+24) +#define V4L2_CID_CAM_MULTISHOT (V4L2_CID_CAMERA_CLASS_BASE+25) + +/* Control dynamic range */ +#define V4L2_CID_CAM_DR (V4L2_CID_CAMERA_CLASS_BASE+26) + +/* White balance preset control */ +#define V4L2_CID_WHITE_BALANCE_PRESET (V4L2_CID_CAMERA_CLASS_BASE+27) +#define V4L2_CID_CAM_SENSOR_FW_VER (V4L2_CID_CAMERA_CLASS_BASE + 28) +#define V4L2_CID_CAM_PHONE_FW_VER (V4L2_CID_CAMERA_CLASS_BASE + 29) + +/* CID extensions */ +#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_PADDR_Y (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_PADDR_CB (V4L2_CID_PRIVATE_BASE + 2) +#define V4L2_CID_PADDR_CR (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_PADDR_CBCR (V4L2_CID_PRIVATE_BASE + 4) +#define V4L2_CID_OVERLAY_AUTO (V4L2_CID_PRIVATE_BASE + 5) +#define V4L2_CID_OVERLAY_VADDR0 (V4L2_CID_PRIVATE_BASE + 6) +#define V4L2_CID_OVERLAY_VADDR1 (V4L2_CID_PRIVATE_BASE + 7) +#define V4L2_CID_OVERLAY_VADDR2 (V4L2_CID_PRIVATE_BASE + 8) +#define V4L2_CID_OVLY_MODE (V4L2_CID_PRIVATE_BASE + 9) +#define V4L2_CID_DST_INFO (V4L2_CID_PRIVATE_BASE + 10) +/* UMP secure id control */ +#define V4L2_CID_GET_UMP_SECURE_ID (V4L2_CID_PRIVATE_BASE + 11) +#define V4L2_CID_GET_PHY_SRC_YADDR (V4L2_CID_PRIVATE_BASE + 12) +#define V4L2_CID_GET_PHY_SRC_CADDR (V4L2_CID_PRIVATE_BASE + 13) +#define V4L2_CID_IMAGE_EFFECT_FN (V4L2_CID_PRIVATE_BASE + 16) +#define V4L2_CID_IMAGE_EFFECT_APPLY (V4L2_CID_PRIVATE_BASE + 17) +#define V4L2_CID_IMAGE_EFFECT_CB (V4L2_CID_PRIVATE_BASE + 18) +#define V4L2_CID_IMAGE_EFFECT_CR (V4L2_CID_PRIVATE_BASE + 19) +#define V4L2_CID_RESERVED_MEM_BASE_ADDR (V4L2_CID_PRIVATE_BASE + 20) +#define V4L2_CID_FIMC_VERSION (V4L2_CID_PRIVATE_BASE + 21) + +#define V4L2_CID_CACHE_FLUSH (V4L2_CID_PRIVATE_BASE + 61) +#define V4L2_CID_RESERVED_MEM_SIZE (V4L2_CID_PRIVATE_BASE + 63) +#define V4L2_CID_STREAM_PAUSE (V4L2_CID_PRIVATE_BASE + 53) +#define V4L2_CID_CACHE_FLUSH (V4L2_CID_PRIVATE_BASE + 61) +#define V4L2_CID_RESERVED_MEM_SIZE (V4L2_CID_PRIVATE_BASE + 63) + +/* CID Extensions for camera sensor operations */ +#define V4L2_CID_CAM_PREVIEW_ONOFF (V4L2_CID_PRIVATE_BASE + 64) +#define V4L2_CID_CAM_CAPTURE (V4L2_CID_PRIVATE_BASE + 65) +/* #define V4L2_CID_CAM_JPEG_MEMSIZE (V4L2_CID_PRIVATE_BASE + 66) */ + +#define V4L2_CID_CAM_DATE_INFO_YEAR (V4L2_CID_PRIVATE_BASE + 14) +#define V4L2_CID_CAM_DATE_INFO_MONTH (V4L2_CID_PRIVATE_BASE + 15) +#define V4L2_CID_CAM_DATE_INFO_DATE (V4L2_CID_PRIVATE_BASE + 22) +#define V4L2_CID_CAM_SENSOR_VER (V4L2_CID_PRIVATE_BASE + 23) +#define V4L2_CID_CAM_FW_MINOR_VER (V4L2_CID_PRIVATE_BASE + 24) +#define V4L2_CID_CAM_FW_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 25) +#define V4L2_CID_CAM_PRM_MINOR_VER (V4L2_CID_PRIVATE_BASE + 26) +#define V4L2_CID_CAM_PRM_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 27) +#define V4L2_CID_CAM_FW_VER (V4L2_CID_PRIVATE_BASE + 28) +#define V4L2_CID_CAM_SET_FW_ADDR (V4L2_CID_PRIVATE_BASE + 29) +#define V4L2_CID_CAM_SET_FW_SIZE (V4L2_CID_PRIVATE_BASE + 30) +#define V4L2_CID_CAM_UPDATE_FW (V4L2_CID_PRIVATE_BASE + 31) +enum v4l2_firmware_mode { + FW_MODE_NONE, + FW_MODE_VERSION, + FW_MODE_UPDATE, + FW_MODE_DUMP, +}; + +#define V4L2_CID_CAM_JPEG_MAIN_SIZE (V4L2_CID_PRIVATE_BASE + 32) +#define V4L2_CID_CAM_JPEG_MAIN_OFFSET (V4L2_CID_PRIVATE_BASE + 33) +#define V4L2_CID_CAM_JPEG_THUMB_SIZE (V4L2_CID_PRIVATE_BASE + 34) +#define V4L2_CID_CAM_JPEG_THUMB_OFFSET (V4L2_CID_PRIVATE_BASE + 35) +#define V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET (V4L2_CID_PRIVATE_BASE + 36) +#define V4L2_CID_CAM_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE + 37) +#define V4L2_CID_CAM_SENSOR_MAKER (V4L2_CID_PRIVATE_BASE + 38) +#define V4L2_CID_CAM_SENSOR_OPTICAL (V4L2_CID_PRIVATE_BASE + 39) +#define V4L2_CID_CAM_AF_VER_LOW (V4L2_CID_PRIVATE_BASE + 40) +#define V4L2_CID_CAM_AF_VER_HIGH (V4L2_CID_PRIVATE_BASE + 41) +#define V4L2_CID_CAM_GAMMA_RG_LOW (V4L2_CID_PRIVATE_BASE + 42) +#define V4L2_CID_CAM_GAMMA_RG_HIGH (V4L2_CID_PRIVATE_BASE + 43) +#define V4L2_CID_CAM_GAMMA_BG_LOW (V4L2_CID_PRIVATE_BASE + 44) +#define V4L2_CID_CAM_GAMMA_BG_HIGH (V4L2_CID_PRIVATE_BASE + 45) +#define V4L2_CID_CAM_DUMP_FW (V4L2_CID_PRIVATE_BASE + 46) +#define V4L2_CID_CAM_GET_DUMP_SIZE (V4L2_CID_PRIVATE_BASE + 47) +#define V4L2_CID_CAMERA_VT_MODE (V4L2_CID_PRIVATE_BASE + 48) +enum cam_vt_mode { + CAM_VT_MODE_NONE , + CAM_VT_MODE_3G , + CAM_VT_MODE_VOIP , +}; + +#define V4L2_CID_CAMERA_VGA_BLUR (V4L2_CID_PRIVATE_BASE + 49) +#define V4L2_CID_CAMERA_CAPTURE (V4L2_CID_PRIVATE_BASE + 50) +#define V4L2_CID_CAMERA_HDR (V4L2_CID_PRIVATE_BASE + 51) +#define V4L2_CID_CAMERA_HYBRID (V4L2_CID_PRIVATE_BASE + 52) +#define V4L2_CID_CAMERA_HYBRID_CAPTURE (V4L2_CID_PRIVATE_BASE + 62) +#define V4L2_CID_CAMERA_POSTVIEW_CAPTURE (V4L2_CID_PRIVATE_BASE + 67) +#define V4L2_CID_CAMERA_CAPTURE_MODE (V4L2_CID_PRIVATE_BASE + 68) +#define V4L2_CID_CAMERA_YUV_CAPTURE (V4L2_CID_PRIVATE_BASE + 69) + +#define V4L2_CID_MAIN_SW_DATE_INFO_YEAR (V4L2_CID_PRIVATE_BASE + 54) +#define V4L2_CID_MAIN_SW_DATE_INFO_MONTH (V4L2_CID_PRIVATE_BASE + 55) +#define V4L2_CID_MAIN_SW_DATE_INFO_DATE (V4L2_CID_PRIVATE_BASE + 56) +#define V4L2_CID_MAIN_SW_FW_MINOR_VER (V4L2_CID_PRIVATE_BASE + 57) +#define V4L2_CID_MAIN_SW_FW_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 58) +#define V4L2_CID_MAIN_SW_PRM_MINOR_VER (V4L2_CID_PRIVATE_BASE + 59) +#define V4L2_CID_MAIN_SW_PRM_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 60) + +#define V4L2_CID_FIMC_IS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x1000) +#define V4L2_CID_FIMC_IS_TUNE_BASE (V4L2_CTRL_CLASS_CAMERA | 0x2000) + +#define V4L2_CID_IS_LOAD_FW (V4L2_CID_FIMC_IS_BASE + 10) +#define V4L2_CID_IS_INIT_PARAM (V4L2_CID_FIMC_IS_BASE + 11) +#define V4L2_CID_IS_RESET (V4L2_CID_FIMC_IS_BASE + 12) +#define V4L2_CID_IS_S_POWER (V4L2_CID_FIMC_IS_BASE + 13) +enum is_set_power { + IS_POWER_OFF, + IS_POWER_ON +}; + +#define V4L2_CID_IS_S_STREAM (V4L2_CID_FIMC_IS_BASE + 14) +enum is_set_stream { + IS_DISABLE_STREAM, + IS_ENABLE_STREAM +}; + +#define V4L2_CID_IS_S_SCENARIO_MODE (V4L2_CID_FIMC_IS_BASE + 15) +#define V4L2_CID_IS_S_FORMAT_SCENARIO (V4L2_CID_FIMC_IS_BASE + 16) +enum scenario_mode { + IS_MODE_PREVIEW_STILL, + IS_MODE_PREVIEW_VIDEO, + IS_MODE_CAPTURE_STILL, + IS_MODE_CAPTURE_VIDEO, + IS_MODE_MAX +}; + +/* global */ +#define V4L2_CID_IS_CAMERA_SHOT_MODE_NORMAL (V4L2_CID_FIMC_IS_BASE + 101) +/* value : 1 : single shot , >=2 : continuous shot */ + +#define V4L2_CID_IS_CAMERA_SENSOR_NUM (V4L2_CID_FIMC_IS_BASE + 201) + +#define V4L2_CID_IS_CAMERA_FOCUS_MODE (V4L2_CID_FIMC_IS_BASE + 401) +enum is_focus_mode { + IS_FOCUS_MODE_AUTO, + IS_FOCUS_MODE_MACRO, + IS_FOCUS_MODE_INFINITY, + IS_FOCUS_MODE_CONTINUOUS, + IS_FOCUS_MODE_TOUCH, + IS_FOCUS_MODE_FACEDETECT, + IS_FOCUS_MODE_IDLE, + IS_FOCUS_MODE_MAX, +}; + +#define V4L2_CID_IS_CAMERA_FLASH_MODE (V4L2_CID_FIMC_IS_BASE + 402) +enum is_flash_mode { + IS_FLASH_MODE_OFF, + IS_FLASH_MODE_AUTO, + IS_FLASH_MODE_AUTO_REDEYE, + IS_FLASH_MODE_ON, + IS_FLASH_MODE_TORCH, + IS_FLASH_MODE_MAX +}; + +#define V4L2_CID_IS_CAMERA_AWB_MODE (V4L2_CID_FIMC_IS_BASE + 403) +enum is_awb_mode { + IS_AWB_AUTO, + IS_AWB_DAYLIGHT, + IS_AWB_CLOUDY, + IS_AWB_TUNGSTEN, + IS_AWB_FLUORESCENT, + IS_AWB_MAX +}; + +#define V4L2_CID_IS_CAMERA_IMAGE_EFFECT (V4L2_CID_FIMC_IS_BASE + 404) +enum is_image_effect { + IS_IMAGE_EFFECT_DISABLE, + IS_IMAGE_EFFECT_MONOCHROME, + IS_IMAGE_EFFECT_NEGATIVE_MONO, + IS_IMAGE_EFFECT_NEGATIVE_COLOR, + IS_IMAGE_EFFECT_SEPIA, + IS_IMAGE_EFFECT_SEPIA_CB, + IS_IMAGE_EFFECT_SEPIA_CR, + IS_IMAGE_EFFECT_NEGATIVE, + IS_IMAGE_EFFECT_ARTFREEZE, + IS_IMAGE_EFFECT_EMBOSSING, + IS_IMAGE_EFFECT_SILHOUETTE, + IS_IMAGE_EFFECT_MAX +}; + +#define V4L2_CID_IS_CAMERA_ISO (V4L2_CID_FIMC_IS_BASE + 405) +enum is_iso { + IS_ISO_AUTO, + IS_ISO_50, + IS_ISO_100, + IS_ISO_200, + IS_ISO_400, + IS_ISO_800, + IS_ISO_1600, + IS_ISO_MAX +}; + +#define V4L2_CID_IS_CAMERA_CONTRAST (V4L2_CID_FIMC_IS_BASE + 406) +enum is_contrast { + IS_CONTRAST_AUTO, + IS_CONTRAST_MINUS_2, + IS_CONTRAST_MINUS_1, + IS_CONTRAST_DEFAULT, + IS_CONTRAST_PLUS_1, + IS_CONTRAST_PLUS_2, + IS_CONTRAST_MAX +}; + +#define V4L2_CID_IS_CAMERA_SATURATION (V4L2_CID_FIMC_IS_BASE + 407) +enum is_saturation { + IS_SATURATION_MINUS_2, + IS_SATURATION_MINUS_1, + IS_SATURATION_DEFAULT, + IS_SATURATION_PLUS_1, + IS_SATURATION_PLUS_2, + IS_SATURATION_MAX +}; + +#define V4L2_CID_IS_CAMERA_SHARPNESS (V4L2_CID_FIMC_IS_BASE + 408) +enum is_sharpness { + IS_SHARPNESS_MINUS_2, + IS_SHARPNESS_MINUS_1, + IS_SHARPNESS_DEFAULT, + IS_SHARPNESS_PLUS_1, + IS_SHARPNESS_PLUS_2, + IS_SHARPNESS_MAX +}; + +#define V4L2_CID_IS_CAMERA_EXPOSURE (V4L2_CID_FIMC_IS_BASE + 409) +enum is_exposure { + IS_EXPOSURE_MINUS_4, + IS_EXPOSURE_MINUS_3, + IS_EXPOSURE_MINUS_2, + IS_EXPOSURE_MINUS_1, + IS_EXPOSURE_DEFAULT, + IS_EXPOSURE_PLUS_1, + IS_EXPOSURE_PLUS_2, + IS_EXPOSURE_PLUS_3, + IS_EXPOSURE_PLUS_4, + IS_EXPOSURE_MAX +}; + +#define V4L2_CID_IS_CAMERA_BRIGHTNESS (V4L2_CID_FIMC_IS_BASE + 410) +enum is_brightness { + IS_BRIGHTNESS_MINUS_2, + IS_BRIGHTNESS_MINUS_1, + IS_BRIGHTNESS_DEFAULT, + IS_BRIGHTNESS_PLUS_1, + IS_BRIGHTNESS_PLUS_2, + IS_BRIGHTNESS_MAX +}; + +#define V4L2_CID_IS_CAMERA_HUE (V4L2_CID_FIMC_IS_BASE + 411) +enum is_hue { + IS_HUE_MINUS_2, + IS_HUE_MINUS_1, + IS_HUE_DEFAULT, + IS_HUE_PLUS_1, + IS_HUE_PLUS_2, + IS_HUE_MAX +}; + +#define V4L2_CID_IS_CAMERA_METERING (V4L2_CID_FIMC_IS_BASE + 412) +enum is_metering { + IS_METERING_AVERAGE, + IS_METERING_SPOT, + IS_METERING_MATRIX, + IS_METERING_CENTER, + IS_METERING_MAX +}; +#define V4L2_CID_IS_CAMERA_METERING_POSITION_X (V4L2_CID_FIMC_IS_BASE + 500) +#define V4L2_CID_IS_CAMERA_METERING_POSITION_Y (V4L2_CID_FIMC_IS_BASE + 501) +#define V4L2_CID_IS_CAMERA_METERING_WINDOW_X (V4L2_CID_FIMC_IS_BASE + 502) +#define V4L2_CID_IS_CAMERA_METERING_WINDOW_Y (V4L2_CID_FIMC_IS_BASE + 503) + +#define V4L2_CID_IS_CAMERA_AFC_MODE (V4L2_CID_FIMC_IS_BASE + 413) +enum is_afc_mode { + IS_AFC_DISABLE, + IS_AFC_AUTO, + IS_AFC_MANUAL_50HZ, + IS_AFC_MANUAL_60HZ, + IS_AFC_MAX +}; + +#define V4L2_CID_IS_AWB_LOCK_UNLOCK (V4L2_CID_FIMC_IS_BASE + 496) +enum is_awb_lock_unlock { + IS_AWB_LOCK, + IS_AWB_UNLOCK, + IS_AWB_LOCK_UNLOCK_MAX +}; + +#define V4L2_CID_IS_AE_LOCK_UNLOCK (V4L2_CID_FIMC_IS_BASE + 497) +enum is_ae_lock_unlock { + IS_AE_LOCK, + IS_AE_UNLOCK, + IS_AE_LOCK_UNLOCK_MAX +}; + +#define V4L2_CID_IS_FD_GET_FACE_COUNT (V4L2_CID_FIMC_IS_BASE + 600) +#define V4L2_CID_IS_FD_GET_FACE_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 601) +#define V4L2_CID_IS_FD_GET_FACE_CONFIDENCE (V4L2_CID_FIMC_IS_BASE + 602) +#define V4L2_CID_IS_FD_GET_FACE_SMILE_LEVEL (V4L2_CID_FIMC_IS_BASE + 603) +#define V4L2_CID_IS_FD_GET_FACE_BLINK_LEVEL (V4L2_CID_FIMC_IS_BASE + 604) +#define V4L2_CID_IS_FD_GET_FACE_TOPLEFT_X (V4L2_CID_FIMC_IS_BASE + 605) +#define V4L2_CID_IS_FD_GET_FACE_TOPLEFT_Y (V4L2_CID_FIMC_IS_BASE + 606) +#define V4L2_CID_IS_FD_GET_FACE_BOTTOMRIGHT_X (V4L2_CID_FIMC_IS_BASE + 607) +#define V4L2_CID_IS_FD_GET_FACE_BOTTOMRIGHT_Y (V4L2_CID_FIMC_IS_BASE + 608) +#define V4L2_CID_IS_FD_GET_LEFT_EYE_TOPLEFT_X (V4L2_CID_FIMC_IS_BASE + 609) +#define V4L2_CID_IS_FD_GET_LEFT_EYE_TOPLEFT_Y (V4L2_CID_FIMC_IS_BASE + 610) +#define V4L2_CID_IS_FD_GET_LEFT_EYE_BOTTOMRIGHT_X (V4L2_CID_FIMC_IS_BASE + 611) +#define V4L2_CID_IS_FD_GET_LEFT_EYE_BOTTOMRIGHT_Y (V4L2_CID_FIMC_IS_BASE + 612) +#define V4L2_CID_IS_FD_GET_RIGHT_EYE_TOPLEFT_X (V4L2_CID_FIMC_IS_BASE + 613) +#define V4L2_CID_IS_FD_GET_RIGHT_EYE_TOPLEFT_Y (V4L2_CID_FIMC_IS_BASE + 614) +#define V4L2_CID_IS_FD_GET_RIGHT_EYE_BOTTOMRIGHT_X (V4L2_CID_FIMC_IS_BASE + 615) +#define V4L2_CID_IS_FD_GET_RIGHT_EYE_BOTTOMRIGHT_Y (V4L2_CID_FIMC_IS_BASE + 616) +#define V4L2_CID_IS_FD_GET_MOUTH_TOPLEFT_X (V4L2_CID_FIMC_IS_BASE + 617) +#define V4L2_CID_IS_FD_GET_MOUTH_TOPLEFT_Y (V4L2_CID_FIMC_IS_BASE + 618) +#define V4L2_CID_IS_FD_GET_MOUTH_BOTTOMRIGHT_X (V4L2_CID_FIMC_IS_BASE + 619) +#define V4L2_CID_IS_FD_GET_MOUTH_BOTTOMRIGHT_Y (V4L2_CID_FIMC_IS_BASE + 620) +#define V4L2_CID_IS_FD_GET_ANGLE (V4L2_CID_FIMC_IS_BASE + 621) +#define V4L2_CID_IS_FD_GET_YAW_ANGLE (V4L2_CID_FIMC_IS_BASE + 622) +#define V4L2_CID_IS_FD_GET_NEXT (V4L2_CID_FIMC_IS_BASE + 623) +#define V4L2_CID_IS_FD_GET_DATA (V4L2_CID_FIMC_IS_BASE + 624) + +#define V4L2_CID_IS_FD_SET_MAX_FACE_NUMBER (V4L2_CID_FIMC_IS_BASE + 650) +#define V4L2_CID_IS_FD_SET_ROLL_ANGLE (V4L2_CID_FIMC_IS_BASE + 651) + +enum is_fd_roll_angle { + /* 0, 45, 0, -45 */ + IS_FD_ROLL_ANGLE_BASIC = 0, + /* 0, 30, 0, -30, 0, 45, 0, -45 */ + IS_FD_ROLL_ANGLE_PRECISE_BASIC = 1, + /* 0, 90, 0, -90 */ + IS_FD_ROLL_ANGLE_SIDES = 2, + /* 0, 90, 0, -90 0, 45, 0, -45 */ + IS_FD_ROLL_ANGLE_PRECISE_SIDES = 3, + /* 0, 90, 0, -90, 0, 180 */ + IS_FD_ROLL_ANGLE_FULL = 4, + /* 0, 90, 0, -90, 0, 180, 0, 135, 0, -135 */ + IS_FD_ROLL_ANGLE_PRECISE_FULL = 5, +}; + +#define V4L2_CID_IS_FD_SET_YAW_ANGLE (V4L2_CID_FIMC_IS_BASE + 652) +enum is_fd_yaw_angle { + IS_FD_YAW_ANGLE_0 = 0, + IS_FD_YAW_ANGLE_45 = 1, + IS_FD_YAW_ANGLE_90 = 2, + IS_FD_YAW_ANGLE_45_90 = 3, +}; + +#define V4L2_CID_IS_FD_SET_SMILE_MODE (V4L2_CID_FIMC_IS_BASE + 653) +enum is_fd_smile_mode { + IS_FD_SMILE_MODE_DISABLE = 0, + IS_FD_SMILE_MODE_ENABLE = 1, +}; + +#define V4L2_CID_IS_FD_SET_BLINK_MODE (V4L2_CID_FIMC_IS_BASE + 654) +enum is_fd_blink_mode { + IS_FD_BLINK_MODE_DISABLE = 0, + IS_FD_BLINK_MODE_ENABLE = 1, +}; + +#define V4L2_CID_IS_FD_SET_EYE_DETECT_MODE (V4L2_CID_FIMC_IS_BASE + 655) +enum is_fd_eye_detect_mode { + IS_FD_EYE_DETECT_DISABLE = 0, + IS_FD_EYE_DETECT_ENABLE = 1, +}; + +#define V4L2_CID_IS_FD_SET_MOUTH_DETECT_MODE (V4L2_CID_FIMC_IS_BASE + 656) +enum is_fd_mouth_detect_mode { + IS_FD_MOUTH_DETECT_DISABLE = 0, + IS_FD_MOUTH_DETECT_ENABLE = 1, +}; + +#define V4L2_CID_IS_FD_SET_ORIENTATION_MODE (V4L2_CID_FIMC_IS_BASE + 657) +enum is_fd_orientation_mode { + IS_FD_ORIENTATION_DISABLE = 0, + IS_FD_ORIENTATION_ENABLE = 1, +}; + +#define V4L2_CID_IS_FD_SET_ORIENTATION (V4L2_CID_FIMC_IS_BASE + 658) +#define V4L2_CID_IS_FD_SET_DATA_ADDRESS (V4L2_CID_FIMC_IS_BASE + 659) + +#define V4L2_CID_IS_SET_ISP (V4L2_CID_FIMC_IS_BASE + 440) +enum is_isp_bypass_mode { + IS_ISP_BYPASS_DISABLE, + IS_ISP_BYPASS_ENABLE, + IS_ISP_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_DRC (V4L2_CID_FIMC_IS_BASE + 441) +enum is_drc_bypass_mode { + IS_DRC_BYPASS_DISABLE, + IS_DRC_BYPASS_ENABLE, + IS_DRC_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_FD (V4L2_CID_FIMC_IS_BASE + 442) +enum is_fd_bypass_mode { + IS_FD_BYPASS_DISABLE, + IS_FD_BYPASS_ENABLE, + IS_FD_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_ODC (V4L2_CID_FIMC_IS_BASE + 443) +enum is_odc_bypass_mode { + IS_ODC_BYPASS_DISABLE, + IS_ODC_BYPASS_ENABLE, + IS_ODC_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_DIS (V4L2_CID_FIMC_IS_BASE + 444) +enum is_dis_bypass_mode { + IS_DIS_BYPASS_DISABLE, + IS_DIS_BYPASS_ENABLE, + IS_DIS_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_3DNR (V4L2_CID_FIMC_IS_BASE + 445) +enum is_tdnr_bypass_mode { + IS_TDNR_BYPASS_DISABLE, + IS_TDNR_BYPASS_ENABLE, + IS_TDNR_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_SCALERC (V4L2_CID_FIMC_IS_BASE + 446) +enum is_scalerc_bypass_mode { + IS_SCALERC_BYPASS_DISABLE, + IS_SCALERC_BYPASS_ENABLE, + IS_SCALERC_BYPASS_MAX +}; + +#define V4L2_CID_IS_SET_SCALERP (V4L2_CID_FIMC_IS_BASE + 446) +enum is_scalerp_bypass_mode { + IS_SCALERP_BYPASS_DISABLE, + IS_SCALERP_BYPASS_ENABLE, + IS_SCALERP_BYPASS_MAX +}; + +#define V4L2_CID_IS_ROTATION_MODE (V4L2_CID_FIMC_IS_BASE + 450) +enum is_rotation_mode { + IS_ROTATION_0, + IS_ROTATION_90, + IS_ROTATION_180, + IS_ROTATION_270, + IS_ROTATION_MAX +}; + +#define V4L2_CID_IS_3DNR_1ST_FRAME_MODE (V4L2_CID_FIMC_IS_BASE + 451) +enum is_tdnr_1st_frame_mode { + IS_TDNR_1ST_FRAME_NOPROCESSING, + IS_TDNR_1ST_FRAME_2DNR, + IS_TDNR_MAX +}; + +#define V4L2_CID_IS_CAMERA_OBJECT_POSITION_X (V4L2_CID_FIMC_IS_BASE + 452) +#define V4L2_CID_IS_CAMERA_OBJECT_POSITION_Y (V4L2_CID_FIMC_IS_BASE + 453) +#define V4L2_CID_IS_CAMERA_WINDOW_SIZE_X (V4L2_CID_FIMC_IS_BASE + 454) +#define V4L2_CID_IS_CAMERA_WINDOW_SIZE_Y (V4L2_CID_FIMC_IS_BASE + 455) + +#define V4L2_CID_IS_CAMERA_EXIF_EXPTIME (V4L2_CID_FIMC_IS_BASE + 456) +#define V4L2_CID_IS_CAMERA_EXIF_FLASH (V4L2_CID_FIMC_IS_BASE + 457) +#define V4L2_CID_IS_CAMERA_EXIF_ISO (V4L2_CID_FIMC_IS_BASE + 458) +#define V4L2_CID_IS_CAMERA_EXIF_SHUTTERSPEED (V4L2_CID_FIMC_IS_BASE + 459) +#define V4L2_CID_IS_CAMERA_EXIF_BRIGHTNESS (V4L2_CID_FIMC_IS_BASE + 460) + +#define V4L2_CID_IS_CAMERA_ISP_SEL_INPUT (V4L2_CID_FIMC_IS_BASE + 461) +enum is_isp_sel_input { + IS_ISP_INPUT_OTF, + IS_ISP_INPUT_DMA1, + IS_ISP_INPUT_DMA2, + IS_ISP_INPUT_DMA12, + IS_ISP_INPUT_MAX +}; + +#define V4L2_CID_IS_CAMERA_ISP_SEL_OUTPUT (V4L2_CID_FIMC_IS_BASE + 462) +enum is_isp_sel_output { + IS_ISP_OUTPUT_OTF, + IS_ISP_OUTPUT_DMA1, + IS_ISP_OUTPUT_DMA2, + IS_ISP_OUTPUT_DMA12, + IS_ISP_OUTPUT_OTF_DMA1, + IS_ISP_OUTPUT_OTF_DMA2, + IS_ISP_OUTPUT_OTF_DMA12, + IS_ISP_OUTPUT_MAX +}; + +#define V4L2_CID_IS_CAMERA_DRC_SEL_INPUT (V4L2_CID_FIMC_IS_BASE + 463) +enum is_drc_sel_input { + IS_DRC_INPUT_OTF, + IS_DRC_INPUT_DMA, + IS_DRC_INPUT_MAX +}; + +#define V4L2_CID_IS_CAMERA_FD_SEL_INPUT (V4L2_CID_FIMC_IS_BASE + 464) +enum is_fd_sel_input { + IS_FD_INPUT_OTF, + IS_FD_INPUT_DMA, + IS_FD_INPUT_MAX +}; + +#define V4L2_CID_IS_CAMERA_INIT_WIDTH (V4L2_CID_FIMC_IS_BASE + 465) +#define V4L2_CID_IS_CAMERA_INIT_HEIGHT (V4L2_CID_FIMC_IS_BASE + 466) + +#define V4L2_CID_IS_CMD_ISP (V4L2_CID_FIMC_IS_BASE + 467) +enum is_isp_cmd_mode { + IS_ISP_COMMAND_STOP, + IS_ISP_COMMAND_START, + IS_ISP_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_DRC (V4L2_CID_FIMC_IS_BASE + 468) +enum is_drc_cmd_mode { + IS_DRC_COMMAND_STOP, + IS_DRC_COMMAND_START, + IS_DRC_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_FD (V4L2_CID_FIMC_IS_BASE + 469) +enum is_fd_cmd_mode { + IS_FD_COMMAND_STOP, + IS_FD_COMMAND_START, + IS_FD_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_ODC (V4L2_CID_FIMC_IS_BASE + 470) +enum is_odc_cmd_mode { + IS_ODC_COMMAND_STOP, + IS_ODC_COMMAND_START, + IS_ODC_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_DIS (V4L2_CID_FIMC_IS_BASE + 471) +enum is_dis_cmd_mode { + IS_DIS_COMMAND_STOP, + IS_DIS_COMMAND_START, + IS_DIS_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_TDNR (V4L2_CID_FIMC_IS_BASE + 472) +enum is_tdnr_cmd_mode { + IS_TDNR_COMMAND_STOP, + IS_TDNR_COMMAND_START, + IS_TDNR_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_SCALERC (V4L2_CID_FIMC_IS_BASE + 473) +enum is_scalerc_cmd_mode { + IS_SCALERC_COMMAND_STOP, + IS_SCALERC_COMMAND_START, + IS_SCALERC_COMMAND_MAX +}; + +#define V4L2_CID_IS_CMD_SCALERP (V4L2_CID_FIMC_IS_BASE + 474) +enum is_scalerp_cmd_mode { + IS_SCALERP_COMMAND_STOP, + IS_SCALERP_COMMAND_START, + IS_SCALERP_COMMAND_MAX +}; + +#define V4L2_CID_IS_GET_SENSOR_OFFSET_X (V4L2_CID_FIMC_IS_BASE + 480) +#define V4L2_CID_IS_GET_SENSOR_OFFSET_Y (V4L2_CID_FIMC_IS_BASE + 481) +#define V4L2_CID_IS_GET_SENSOR_WIDTH (V4L2_CID_FIMC_IS_BASE + 482) +#define V4L2_CID_IS_GET_SENSOR_HEIGHT (V4L2_CID_FIMC_IS_BASE + 483) + +#define V4L2_CID_IS_GET_FRAME_VALID (V4L2_CID_FIMC_IS_BASE + 484) +#define V4L2_CID_IS_SET_FRAME_VALID (V4L2_CID_FIMC_IS_BASE + 485) +#define V4L2_CID_IS_GET_FRAME_BADMARK (V4L2_CID_FIMC_IS_BASE + 486) +#define V4L2_CID_IS_SET_FRAME_BADMARK (V4L2_CID_FIMC_IS_BASE + 487) +#define V4L2_CID_IS_GET_FRAME_CAPTURED (V4L2_CID_FIMC_IS_BASE + 488) +#define V4L2_CID_IS_SET_FRAME_CAPTURED (V4L2_CID_FIMC_IS_BASE + 489) +#define V4L2_CID_IS_SET_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 490) +#define V4L2_CID_IS_GET_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 491) +#define V4L2_CID_IS_CLEAR_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 492) +#define V4L2_CID_IS_GET_LOSTED_FRAME_NUMBER (V4L2_CID_FIMC_IS_BASE + 493) +#define V4L2_CID_IS_ISP_DMA_BUFFER_NUM (V4L2_CID_FIMC_IS_BASE + 494) +#define V4L2_CID_IS_ISP_DMA_BUFFER_ADDRESS (V4L2_CID_FIMC_IS_BASE + 495) + +#define V4L2_CID_IS_ZOOM_STATE (V4L2_CID_FIMC_IS_BASE + 660) +#define V4L2_CID_IS_ZOOM_MAX_LEVEL (V4L2_CID_FIMC_IS_BASE + 661) +#define V4L2_CID_IS_ZOOM (V4L2_CID_FIMC_IS_BASE + 662) +#define V4L2_CID_IS_FW_DEBUG_REGION_ADDR (V4L2_CID_FIMC_IS_BASE + 663) + +#define V4L2_CID_IS_TUNE_SEL_ENTRY (V4L2_CID_FIMC_IS_TUNE_BASE) +#define V4L2_CID_IS_TUNE_SENSOR_EXPOSURE (V4L2_CID_FIMC_IS_TUNE_BASE + 1) +#define V4L2_CID_IS_TUNE_SENSOR_ANALOG_GAIN (V4L2_CID_FIMC_IS_TUNE_BASE + 2) +#define V4L2_CID_IS_TUNE_SENSOR_FRAME_RATE (V4L2_CID_FIMC_IS_TUNE_BASE + 3) +#define V4L2_CID_IS_TUNE_SENSOR_ACTUATOR_POS (V4L2_CID_FIMC_IS_TUNE_BASE + 4) + +enum v4l2_blur { + BLUR_LEVEL_0 = 0, + BLUR_LEVEL_1, + BLUR_LEVEL_2, + BLUR_LEVEL_3, + BLUR_LEVEL_MAX, +}; + +#if 1 +#define V4L2_CID_CAMERA_SCENE_MODE (V4L2_CID_PRIVATE_BASE+70) +enum v4l2_scene_mode { + SCENE_MODE_BASE, + SCENE_MODE_NONE, + SCENE_MODE_PORTRAIT, + SCENE_MODE_NIGHTSHOT, + SCENE_MODE_BACK_LIGHT, + SCENE_MODE_LANDSCAPE, + SCENE_MODE_SPORTS, + SCENE_MODE_PARTY_INDOOR, + SCENE_MODE_BEACH_SNOW, + SCENE_MODE_SUNSET, + SCENE_MODE_DUSK_DAWN, + SCENE_MODE_FALL_COLOR, + SCENE_MODE_FIREWORKS, + SCENE_MODE_TEXT, + SCENE_MODE_CANDLE_LIGHT, + SCENE_MODE_MAX, +}; + +#define V4L2_CID_CAMERA_FLASH_MODE (V4L2_CID_PRIVATE_BASE+71) +enum v4l2_flash_mode { + FLASH_MODE_BASE, + FLASH_MODE_OFF, + FLASH_MODE_AUTO, + FLASH_MODE_ON, + FLASH_MODE_TORCH, + FLASH_MODE_RED_EYE, + FLASH_MODE_FILL_IN, + FLASH_MODE_SLOW_SYNC, + FLASH_MODE_RED_EYE_FIX, + FLASH_MODE_MAX, +}; + +#define V4L2_CID_CAMERA_BRIGHTNESS (V4L2_CID_PRIVATE_BASE+72) +enum v4l2_ev_mode { + EV_MINUS_4 = -4, + EV_MINUS_3 = -3, + EV_MINUS_2 = -2, + EV_MINUS_1 = -1, + EV_DEFAULT = 0, + EV_PLUS_1 = 1, + EV_PLUS_2 = 2, + EV_PLUS_3 = 3, + EV_PLUS_4 = 4, + EV_MAX, + EV_MAX_V4L2 = EV_MAX, +}; + +enum v4l2_exposure { + EXPOSURE_MINUS_6 = -6, + EXPOSURE_MINUS_5 = -5, + EXPOSURE_MINUS_4 = -4, + EXPOSURE_MINUS_3 = -3, + EXPOSURE_MINUS_2 = -2, + EXPOSURE_MINUS_1 = -1, + EXPOSURE_DEFAULT = 0, + EXPOSURE_PLUS_1 = 1, + EXPOSURE_PLUS_2 = 2, + EXPOSURE_PLUS_3 = 3, + EXPOSURE_PLUS_4 = 4, + EXPOSURE_PLUS_5 = 5, + EXPOSURE_PLUS_6 = 6, + EXPOSURE_MAX, +}; + +#define V4L2_CID_CAMERA_WHITE_BALANCE (V4L2_CID_PRIVATE_BASE+73) +enum v4l2_wb_mode { + WHITE_BALANCE_BASE = 0, + WHITE_BALANCE_AUTO, + WHITE_BALANCE_SUNNY, + WHITE_BALANCE_CLOUDY, + WHITE_BALANCE_TUNGSTEN, + WHITE_BALANCE_FLUORESCENT, + WHITE_BALANCE_FLUORESCENT_H, + WHITE_BALANCE_FLUORESCENT_L, + WHITE_BALANCE_CUSTOM, + WHITE_BALANCE_K, + WHITE_BALANCE_MAX, +}; + +#define V4L2_CID_CAMERA_EFFECT (V4L2_CID_PRIVATE_BASE+74) +enum v4l2_effect_mode { + IMAGE_EFFECT_BASE = 0, + IMAGE_EFFECT_NONE, + IMAGE_EFFECT_BNW, + IMAGE_EFFECT_SEPIA, + IMAGE_EFFECT_AQUA, + IMAGE_EFFECT_ANTIQUE, + IMAGE_EFFECT_NEGATIVE, + IMAGE_EFFECT_SHARPEN, + IMAGE_EFFECT_SKETCH, + IMAGE_EFFECT_WASHED, + IMAGE_EFFECT_VINTAGE_WARM, + IMAGE_EFFECT_VINTAGE_COLD, + IMAGE_EFFECT_SOLARIZE, + IMAGE_EFFECT_POSTERIZE, + IMAGE_EFFECT_POINT_BLUE, + IMAGE_EFFECT_POINT_RED_YELLOW, + IMAGE_EFFECT_POINT_COLOR_3, + IMAGE_EFFECT_POINT_GREEN, + IMAGE_EFFECT_MAX, +}; + +#define V4L2_CID_CAMERA_ISO (V4L2_CID_PRIVATE_BASE+75) +enum v4l2_iso_mode { + ISO_AUTO = 0, + ISO_50, + ISO_100, + ISO_200, + ISO_400, + ISO_800, + ISO_1600, + ISO_SPORTS, + ISO_NIGHT, + ISO_MOVIE, + ISO_MAX, +}; + +#define V4L2_CID_CAMERA_METERING (V4L2_CID_PRIVATE_BASE+76) +enum v4l2_metering_mode { + METERING_BASE = 0, + METERING_MATRIX, + METERING_CENTER, + METERING_SPOT, + METERING_MAX, +}; + +#define V4L2_CID_CAMERA_CONTRAST (V4L2_CID_PRIVATE_BASE+77) +enum v4l2_contrast_mode { + CONTRAST_MINUS_2 = 0, + CONTRAST_MINUS_1, + CONTRAST_DEFAULT, + CONTRAST_PLUS_1, + CONTRAST_PLUS_2, + CONTRAST_MAX, +}; + +#define V4L2_CID_CAMERA_SATURATION (V4L2_CID_PRIVATE_BASE+78) +enum v4l2_saturation_mode { + SATURATION_MINUS_2 = 0, + SATURATION_MINUS_1, + SATURATION_DEFAULT, + SATURATION_PLUS_1, + SATURATION_PLUS_2, + SATURATION_MAX, +}; + +#define V4L2_CID_CAMERA_SHARPNESS (V4L2_CID_PRIVATE_BASE+79) +enum v4l2_sharpness_mode { + SHARPNESS_MINUS_2 = 0, + SHARPNESS_MINUS_1, + SHARPNESS_DEFAULT, + SHARPNESS_PLUS_1, + SHARPNESS_PLUS_2, + SHARPNESS_MAX, +}; + +#define V4L2_CID_CAMERA_WDR (V4L2_CID_PRIVATE_BASE+80) +enum v4l2_wdr_mode { + WDR_OFF, + WDR_ON, + WDR_MAX, +}; + +#define V4L2_CID_CAMERA_ANTI_SHAKE (V4L2_CID_PRIVATE_BASE+81) +enum v4l2_anti_shake_mode { + ANTI_SHAKE_OFF, + ANTI_SHAKE_STILL_ON, + ANTI_SHAKE_MOVIE_ON, + ANTI_SHAKE_MAX, +}; + +#define V4L2_CID_CAMERA_TOUCH_AF_START_STOP (V4L2_CID_PRIVATE_BASE+82) +enum v4l2_touch_af { + TOUCH_AF_STOP = 0, + TOUCH_AF_START, + TOUCH_AF_MAX, +}; + +#define V4L2_CID_CAMERA_SMART_AUTO (V4L2_CID_PRIVATE_BASE+83) +enum v4l2_smart_auto { + SMART_AUTO_OFF = 0, + SMART_AUTO_ON, + SMART_AUTO_MAX, +}; + +#define V4L2_CID_CAMERA_VINTAGE_MODE (V4L2_CID_PRIVATE_BASE+84) +enum v4l2_vintage_mode { + VINTAGE_MODE_BASE, + VINTAGE_MODE_OFF, + VINTAGE_MODE_NORMAL, + VINTAGE_MODE_WARM, + VINTAGE_MODE_COOL, + VINTAGE_MODE_BNW, + VINTAGE_MODE_MAX, +}; + +#define V4L2_CID_CAMERA_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE+85) +/* (V4L2_CID_PRIVATE_BASE+86) */ +#define V4L2_CID_CAMERA_GPS_LATITUDE (V4L2_CID_CAMERA_CLASS_BASE+30) +/* (V4L2_CID_PRIVATE_BASE+87) */ +#define V4L2_CID_CAMERA_GPS_LONGITUDE (V4L2_CID_CAMERA_CLASS_BASE + 31) +/* (V4L2_CID_PRIVATE_BASE+88) */ +#define V4L2_CID_CAMERA_GPS_TIMESTAMP (V4L2_CID_CAMERA_CLASS_BASE + 32) +/* (V4L2_CID_PRIVATE_BASE+89)*/ +#define V4L2_CID_CAMERA_GPS_ALTITUDE (V4L2_CID_CAMERA_CLASS_BASE + 33) +#define V4L2_CID_CAMERA_EXIF_TIME_INFO (V4L2_CID_CAMERA_CLASS_BASE + 34) +#define V4L2_CID_CAMERA_GPS_PROCESSINGMETHOD (V4L2_CID_CAMERA_CLASS_BASE+35) + +#define V4L2_CID_FOCUS_AUTO_MODE (V4L2_CID_CAMERA_CLASS_BASE+36) +enum v4l2_focus_mode_type { + V4L2_FOCUS_AUTO_NORMAL = 0, + V4L2_FOCUS_AUTO_MACRO, + V4L2_FOCUS_AUTO_CONTINUOUS, + V4L2_FOCUS_AUTO_FACE_DETECTION, + V4L2_FOCUS_AUTO_RECTANGLE, + V4L2_FOCUS_AUTO_MAX, +}; +#define V4L2_CID_FOCUS_AUTO_RECTANGLE_LEFT (V4L2_CID_CAMERA_CLASS_BASE+37) +#define V4L2_CID_FOCUS_AUTO_RECTANGLE_TOP (V4L2_CID_CAMERA_CLASS_BASE+38) +#define V4L2_CID_FOCUS_AUTO_RECTANGLE_WIDTH (V4L2_CID_CAMERA_CLASS_BASE+39) +#define V4L2_CID_FOCUS_AUTO_RECTANGLE_HEIGHT (V4L2_CID_CAMERA_CLASS_BASE+40) + +#define V4L2_CID_CAMERA_ZOOM (V4L2_CID_PRIVATE_BASE+90) +enum v4l2_zoom_level { + ZOOM_LEVEL_0 = 0, + ZOOM_LEVEL_1, + ZOOM_LEVEL_2, + ZOOM_LEVEL_3, + ZOOM_LEVEL_4, + ZOOM_LEVEL_5, + ZOOM_LEVEL_6, + ZOOM_LEVEL_7, + ZOOM_LEVEL_8, + ZOOM_LEVEL_9, + ZOOM_LEVEL_10, + ZOOM_LEVEL_11, + ZOOM_LEVEL_12, + ZOOM_LEVEL_MAX = 31, +}; + +#define V4L2_CID_CAMERA_FACE_DETECTION (V4L2_CID_PRIVATE_BASE+91) +enum v4l2_face_detection { + FACE_DETECTION_OFF = 0, + FACE_DETECTION_ON, + FACE_DETECTION_NOLINE, + FACE_DETECTION_ON_BEAUTY, + FACE_DETECTION_NORMAL, + FACE_DETECTION_SMILE_SHOT, + FACE_DETECTION_BLINK, + FACE_DETECTION_MAX, +}; + +#define V4L2_CID_CAMERA_SMART_AUTO_STATUS (V4L2_CID_PRIVATE_BASE+92) +enum v4l2_smart_auto_status { + SMART_AUTO_STATUS_AUTO = 0, + SMART_AUTO_STATUS_LANDSCAPE, + SMART_AUTO_STATUS_PORTRAIT, + SMART_AUTO_STATUS_MACRO, + SMART_AUTO_STATUS_NIGHT, + SMART_AUTO_STATUS_PORTRAIT_NIGHT, + SMART_AUTO_STATUS_BACKLIT, + SMART_AUTO_STATUS_PORTRAIT_BACKLIT, + SMART_AUTO_STATUS_ANTISHAKE, + SMART_AUTO_STATUS_PORTRAIT_ANTISHAKE, + SMART_AUTO_STATUS_MAX, +}; + +#define V4L2_CID_CAMERA_SET_AUTO_FOCUS (V4L2_CID_PRIVATE_BASE+93) +enum v4l2_auto_focus { + AUTO_FOCUS_OFF = 0, + AUTO_FOCUS_ON, + AUTO_FOCUS_MAX, +}; + +#define V4L2_CID_CAMERA_BEAUTY_SHOT (V4L2_CID_PRIVATE_BASE+94) +enum v4l2_beauty_shot { + BEAUTY_SHOT_OFF = 0, + BEAUTY_SHOT_ON, + BEAUTY_SHOT_MAX, +}; + +#define V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK (V4L2_CID_PRIVATE_BASE+95) +enum v4l2_ae_awb_lockunlock { + AE_UNLOCK_AWB_UNLOCK = 0, + AE_LOCK_AWB_UNLOCK, + AE_UNLOCK_AWB_LOCK, + AE_LOCK_AWB_LOCK, + AE_AWB_MAX +}; + +#define V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK (V4L2_CID_PRIVATE_BASE+96) +enum v4l2_face_lock { + FACE_LOCK_OFF = 0, + FACE_LOCK_ON, + FIRST_FACE_TRACKING, + FACE_LOCK_MAX, +}; + +#define V4L2_CID_CAMERA_OBJECT_POSITION_X (V4L2_CID_PRIVATE_BASE+97) +#define V4L2_CID_CAMERA_OBJECT_POSITION_Y (V4L2_CID_PRIVATE_BASE+98) +#define V4L2_CID_CAMERA_FOCUS_MODE (V4L2_CID_PRIVATE_BASE+99) +enum v4l2_focusmode { + FOCUS_MODE_AUTO = 0, + FOCUS_MODE_MACRO, + FOCUS_MODE_FACEDETECT, + FOCUS_MODE_AUTO_DEFAULT, + FOCUS_MODE_MACRO_DEFAULT, + FOCUS_MODE_FACEDETECT_DEFAULT, + FOCUS_MODE_INFINITY, + FOCUS_MODE_FIXED, + FOCUS_MODE_CONTINOUS, + FOCUS_MODE_CONTINOUS_PICTURE, + FOCUS_MODE_CONTINOUS_PICTURE_MACRO, + FOCUS_MODE_CONTINOUS_VIDEO, + FOCUS_MODE_TOUCH, + FOCUS_MODE_MAX, + FOCUS_MODE_DEFAULT = (1 << 8), +}; + +#define V4L2_CID_CAMERA_OBJ_TRACKING_STATUS (V4L2_CID_PRIVATE_BASE+100) +enum v4l2_obj_tracking_status { + OBJECT_TRACKING_STATUS_BASE, + OBJECT_TRACKING_STATUS_PROGRESSING, + OBJECT_TRACKING_STATUS_SUCCESS, + OBJECT_TRACKING_STATUS_FAIL, + OBJECT_TRACKING_STATUS_MISSING, + OBJECT_TRACKING_STATUS_MAX, +}; + +#define V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP (V4L2_CID_PRIVATE_BASE+101) +enum v4l2_ot_start_stop { + OT_STOP = 0, + OT_START, + OT_MAX, +}; + +#define V4L2_CID_CAMERA_CAF_START_STOP (V4L2_CID_PRIVATE_BASE+102) +enum v4l2_caf_start_stop { + CAF_STOP = 0, + CAF_START, + CAF_MAX, +}; + +#define V4L2_CID_CAMERA_AUTO_FOCUS_RESULT (V4L2_CID_PRIVATE_BASE+103) +enum v4l2_af_status { + CAMERA_AF_STATUS_IN_PROGRESS = 0, + CAMERA_AF_STATUS_SUCCESS, + CAMERA_AF_STATUS_FAIL, + CAMERA_AF_STATUS_1ST_SUCCESS, + CAMERA_AF_STATUS_RESTART, + CAMERA_AF_STATUS_MAX, +}; + +#define V4L2_CID_CAMERA_FRAME_RATE (V4L2_CID_PRIVATE_BASE+104) +enum v4l2_frame_rate { + FRAME_RATE_AUTO = 0, + FRAME_RATE_7 = 7, + FRAME_RATE_15 = 15, + FRAME_RATE_20 = 20, + FRAME_RATE_25 = 25, + FRAME_RATE_30 = 30, + FRAME_RATE_60 = 60, + FRAME_RATE_120 = 120, + FRAME_RATE_MAX +}; + +#define V4L2_CID_CAMERA_ANTI_BANDING (V4L2_CID_PRIVATE_BASE+105) +enum v4l2_anti_banding { + ANTI_BANDING_AUTO = 0, + ANTI_BANDING_50HZ = 1, + ANTI_BANDING_60HZ = 2, + ANTI_BANDING_OFF = 3, +}; + +#define V4L2_CID_CAMERA_SET_GAMMA (V4L2_CID_PRIVATE_BASE+106) +enum v4l2_gamma_mode { + GAMMA_OFF = 0, + GAMMA_ON = 1, + GAMMA_MAX, +}; + +#define V4L2_CID_CAMERA_SET_SLOW_AE (V4L2_CID_PRIVATE_BASE+107) +enum v4l2_slow_ae_mode { + SLOW_AE_OFF, + SLOW_AE_ON, + SLOW_AE_MAX, +}; + +#define V4L2_CID_CAMERA_BATCH_REFLECTION (V4L2_CID_PRIVATE_BASE+108) +#define V4L2_CID_CAMERA_EXIF_ORIENTATION (V4L2_CID_PRIVATE_BASE+109) +#define V4L2_CID_CAMERA_GET_LUX (V4L2_CID_PRIVATE_BASE+110) + +/* s1_camera [ Defense process by ESD input ] */ +#define V4L2_CID_CAMERA_RESET (V4L2_CID_PRIVATE_BASE+111) +#define V4L2_CID_CAMERA_CHECK_DATALINE (V4L2_CID_PRIVATE_BASE+112) +#define V4L2_CID_CAMERA_CHECK_DATALINE_STOP (V4L2_CID_PRIVATE_BASE+113) + +#endif + +/* Modify NTTS1 */ +#if defined(CONFIG_ARIES_NTT) +#define V4L2_CID_CAMERA_AE_AWB_DISABLE_LOCK (V4L2_CID_PRIVATE_BASE+114) +#endif +#define V4L2_CID_CAMERA_THUMBNAIL_NULL (V4L2_CID_PRIVATE_BASE+115) +#define V4L2_CID_CAMERA_SENSOR_MODE (V4L2_CID_PRIVATE_BASE+116) +enum v4l2_sensor_mode { + SENSOR_CAMERA, + SENSOR_MOVIE, +}; + +enum stream_mode_t { + STREAM_MODE_CAM_OFF, + STREAM_MODE_CAM_ON, + STREAM_MODE_MOVIE_OFF, + STREAM_MODE_MOVIE_ON, + STREAM_MODE_WAIT_OFF +}; + +#define V4L2_CID_CAMERA_EXIF_EXPTIME (V4L2_CID_PRIVATE_BASE+117) +#define V4L2_CID_CAMERA_EXIF_FLASH (V4L2_CID_PRIVATE_BASE+118) +#define V4L2_CID_CAMERA_EXIF_ISO (V4L2_CID_PRIVATE_BASE+119) +#define V4L2_CID_CAMERA_EXIF_TV (V4L2_CID_PRIVATE_BASE+120) +#define V4L2_CID_CAMERA_EXIF_BV (V4L2_CID_PRIVATE_BASE+121) +#define V4L2_CID_CAMERA_EXIF_EBV (V4L2_CID_PRIVATE_BASE+122) +#define V4L2_CID_CAMERA_CHECK_ESD (V4L2_CID_PRIVATE_BASE+123) +#define V4L2_CID_CAMERA_APP_CHECK (V4L2_CID_PRIVATE_BASE+124) +#define V4L2_CID_CAMERA_CHECK_SENSOR_STATUS (V4L2_CID_PRIVATE_BASE+150) +#define V4L2_CID_CAMERA_DEFAULT_FOCUS_POSITION (V4L2_CID_PRIVATE_BASE+151) +#define V4L2_CID_CAMERA_BUSFREQ_LOCK (V4L2_CID_PRIVATE_BASE+125) +#define V4L2_CID_CAMERA_BUSFREQ_UNLOCK (V4L2_CID_PRIVATE_BASE+126) + +/* If you would like to control AE and AWB lock with signle command, + * use V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK above. + */ +#define V4L2_CID_CAMERA_AE_LOCK_UNLOCK (V4L2_CID_PRIVATE_BASE + 127) +enum v4l2_ae_lockunlock { + AE_UNLOCK = 0, + AE_LOCK, + AE_LOCK_MAX +}; + +#define V4L2_CID_CAMERA_AWB_LOCK_UNLOCK (V4L2_CID_PRIVATE_BASE + 128) +enum v4l2_awb_lockunlock { + AWB_UNLOCK = 0, + AWB_LOCK, + AWB_LOCK_MAX +}; + +#define V4L2_CID_CAMERA_SENSOR_OUTPUT_SIZE (V4L2_CID_PRIVATE_BASE + 129) +#define V4L2_CID_EMBEDDEDDATA_ENABLE (V4L2_CID_PRIVATE_BASE + 130) +#define V4L2_CID_CAMERA_JPEG_RESOLUTION (V4L2_CID_PRIVATE_BASE + 131) +#define V4L2_CID_CAMERA_FACE_ZOOM (V4L2_CID_PRIVATE_BASE + 132) +enum v4l2_face_zoom { + FACE_ZOOM_STOP = 0, + FACE_ZOOM_START +}; + +/* control for post processing block in ISP */ +#define V4L2_CID_CAMERA_SET_ODC (V4L2_CID_PRIVATE_BASE+127) +enum set_odc_mode { + CAMERA_ODC_ON, + CAMERA_ODC_OFF +}; + +#define V4L2_CID_CAMERA_SET_DIS (V4L2_CID_PRIVATE_BASE+128) +enum set_dis_mode { + CAMERA_DIS_ON, + CAMERA_DIS_OFF +}; + +#define V4L2_CID_CAMERA_SET_3DNR (V4L2_CID_PRIVATE_BASE+129) +enum set_3dnr_mode { + CAMERA_3DNR_ON, + CAMERA_3DNR_OFF +}; + +#define V4L2_CID_CAMERA_BRACKET (V4L2_CID_PRIVATE_BASE+134) +enum v4l2_face_bracket_mode { + BRACKET_MODE_OFF = 0, + BRACKET_MODE_AEB, + BRACKET_MODE_WBB, + BRACKET_MODE_MAX, +}; + +#define V4L2_CID_CAMERA_BRACKET_AEB (V4L2_CID_PRIVATE_BASE+135) +enum v4l2_face_bracket_aeb_value { + BRACKET_AEB_VALUE1 = 1, + BRACKET_AEB_VALUE2, + BRACKET_AEB_VALUE3, + BRACKET_AEB_VALUE4, + BRACKET_AEB_VALUE5, + BRACKET_AEB_VALUE6, +}; + +#define V4L2_CID_CAMERA_BRACKET_WBB (V4L2_CID_PRIVATE_BASE+136) +enum v4l2_face_bracket_wbb_value { + BRACKET_WBB_VALUE1 = 1, + BRACKET_WBB_VALUE2, + BRACKET_WBB_VALUE3, + BRACKET_WBB_VALUE4, + BRACKET_WBB_VALUE5, + BRACKET_WBB_VALUE6, +}; + +#define V4L2_CID_CAMERA_DRIVE_DIAL (V4L2_CID_PRIVATE_BASE+137) +enum v4l2_drive_dial { + DRIVEDIAL_SINGLE = 1, + DRIVEDIAL_BKT = 2, + DRIVEDIAL_CONTI_3 = 3, + DRIVEDIAL_CONTI_5 = 5, + DRIVEDIAL_CONTI_10 = 10, +}; + +enum v4l2_running_cap_mode { + RUNNING_MODE_SINGLE = 0, + RUNNING_MODE_CONTINUOUS, + RUNNING_MODE_BRACKET, + RUNNING_MODE_HDR, + RUNNING_MODE_BLINK, + RUNNING_MODE_MAX +}; + +#define V4L2_CID_CAMERA_FD_EYE_BLINK_RESULT (V4L2_CID_PRIVATE_BASE+138) + +#define V4L2_CID_CAMERA_OPTICAL_ZOOM_STEP (V4L2_CID_PRIVATE_BASE + 139) +#define V4L2_CID_CAMERA_OPTICAL_ZOOM_CTRL (V4L2_CID_PRIVATE_BASE + 140) + +enum v4l2_optical_zoom_ctrl { + V4L2_OPTICAL_ZOOM_TELE, + V4L2_OPTICAL_ZOOM_WIDE, + V4L2_OPTICAL_ZOOM_STOP, +}; + +#define V4L2_CID_CAMERA_LDC (V4L2_CID_PRIVATE_BASE+142) +enum set_LDC_mode { + LDC_SET_OFF = 0, + LDC_SET_ON = 1, +}; + +#define V4L2_CID_CAMERA_LSC (V4L2_CID_PRIVATE_BASE+143) +enum set_LSC_mode { + LSC_SET_OFF = 0, + LSC_SET_ON = 1, +}; + +/* Pixel format FOURCC depth Description */ +enum v4l2_pix_format_mode { + V4L2_PIX_FMT_MODE_PREVIEW, + V4L2_PIX_FMT_MODE_CAPTURE, + V4L2_PIX_FMT_MODE_HDR, + V4L2_PIX_FMT_MODE_VT_MIRROR, + V4L2_PIX_FMT_MODE_VT_NONMIRROR, +}; + +/* 12 Y/CbCr 4:2:0 64x32 macroblocks */ +#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2') +#define V4L2_PIX_FMT_NV21T v4l2_fourcc('T', 'V', '2', '1') +#define V4L2_PIX_FMT_INTERLEAVED v4l2_fourcc('I', 'T', 'L', 'V') + +/* + * * V4L2 extention for digital camera + * */ +/* Strobe flash light */ +enum v4l2_strobe_control { + /* turn off the flash light */ + V4L2_STROBE_CONTROL_OFF = 0, + /* turn on the flash light */ + V4L2_STROBE_CONTROL_ON = 1, + /* act guide light before splash */ + V4L2_STROBE_CONTROL_AFGUIDE = 2, + /* charge the flash light */ + V4L2_STROBE_CONTROL_CHARGE = 3, +}; + +enum v4l2_strobe_conf { + V4L2_STROBE_OFF = 0, /* Always off */ + V4L2_STROBE_ON = 1, /* Always splashes */ + /* Auto control presets */ + V4L2_STROBE_AUTO = 2, + V4L2_STROBE_REDEYE_REDUCTION = 3, + V4L2_STROBE_SLOW_SYNC = 4, + V4L2_STROBE_FRONT_CURTAIN = 5, + V4L2_STROBE_REAR_CURTAIN = 6, + /* Extra manual control presets */ + /* keep turned on until turning off */ + V4L2_STROBE_PERMANENT = 7, + V4L2_STROBE_EXTERNAL = 8, +}; + +enum v4l2_strobe_status { + V4L2_STROBE_STATUS_OFF = 0, + /* while processing configurations */ + V4L2_STROBE_STATUS_BUSY = 1, + V4L2_STROBE_STATUS_ERR = 2, + V4L2_STROBE_STATUS_CHARGING = 3, + V4L2_STROBE_STATUS_CHARGED = 4, +}; + +/* capabilities field */ +/* No strobe supported */ +#define V4L2_STROBE_CAP_NONE 0x0000 +/* Always flash off mode */ +#define V4L2_STROBE_CAP_OFF 0x0001 +/* Always use flash light mode */ +#define V4L2_STROBE_CAP_ON 0x0002 +/* Flashlight works automatic */ +#define V4L2_STROBE_CAP_AUTO 0x0004 +/* Red-eye reduction */ +#define V4L2_STROBE_CAP_REDEYE 0x0008 +/* Slow sync */ +#define V4L2_STROBE_CAP_SLOWSYNC 0x0010 +/* Front curtain */ +#define V4L2_STROBE_CAP_FRONT_CURTAIN 0x0020 +/* Rear curtain */ +#define V4L2_STROBE_CAP_REAR_CURTAIN 0x0040 +/* keep turned on until turning off */ +#define V4L2_STROBE_CAP_PERMANENT 0x0080 +/* use external strobe */ +#define V4L2_STROBE_CAP_EXTERNAL 0x0100 + +/* Set mode and Get status */ +struct v4l2_strobe { + /* off/on/charge:0/1/2 */ + enum v4l2_strobe_control control; + /* supported strobe capabilities */ + __u32 capabilities; + enum v4l2_strobe_conf mode; + enum v4l2_strobe_status status; /* read only */ +/* default is 0 and range of value varies from each models */ + __u32 flash_ev; + __u32 reserved[4]; +}; + +#define VIDIOC_S_STROBE _IOWR('V', 83, struct v4l2_strobe) +#define VIDIOC_G_STROBE _IOR('V', 84, struct v4l2_strobe) + +/* Object recognition and collateral actions */ +enum v4l2_recog_mode { + V4L2_RECOGNITION_MODE_OFF = 0, + V4L2_RECOGNITION_MODE_ON = 1, + V4L2_RECOGNITION_MODE_LOCK = 2, +}; + +enum v4l2_recog_action { + V4L2_RECOGNITION_ACTION_NONE = 0, /* only recognition */ + V4L2_RECOGNITION_ACTION_BLINK = 1, /* Capture on blinking */ + V4L2_RECOGNITION_ACTION_SMILE = 2, /* Capture on smiling */ +}; + +enum v4l2_recog_pattern { + V4L2_RECOG_PATTERN_FACE = 0, /* Face */ + V4L2_RECOG_PATTERN_HUMAN = 1, /* Human */ + V4L2_RECOG_PATTERN_CHAR = 2, /* Character */ +}; + +struct v4l2_recog_rect { + enum v4l2_recog_pattern p; /* detected pattern */ + struct v4l2_rect o; /* detected area */ + __u32 reserved[4]; +}; + +struct v4l2_recog_data { + __u8 detect_cnt; /* detected object counter */ + struct v4l2_rect o; /* detected area */ + __u32 reserved[4]; +}; + +struct v4l2_recognition { + enum v4l2_recog_mode mode; + + /* Which pattern to detect */ + enum v4l2_recog_pattern pattern; + + /* How many object to detect */ + __u8 obj_num; + + /* select detected object */ + __u32 detect_idx; + + /* read only :Get object coordination */ + struct v4l2_recog_data data; + + enum v4l2_recog_action action; + __u32 reserved[4]; +}; + +#define VIDIOC_S_RECOGNITION _IOWR('V', 85, struct v4l2_recognition) +#define VIDIOC_G_RECOGNITION _IOR('V', 86, struct v4l2_recognition) + +#endif /* __LINUX_VIDEODEV2_SAMSUNG_H */ diff --git a/camera/include/linux/videodev2_exynos_media.h b/camera/include/linux/videodev2_exynos_media.h new file mode 100644 index 0000000..2768201 --- /dev/null +++ b/camera/include/linux/videodev2_exynos_media.h @@ -0,0 +1,225 @@ +/* + * Video for Linux Two header file for Exynos + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This header file contains several v4l2 APIs to be proposed to v4l2 + * community and until being accepted, will be used restrictly for Exynos. + * + * 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. + */ + +#ifndef __LINUX_VIDEODEV2_EXYNOS_H +#define __LINUX_VIDEODEV2_EXYNOS_H + +/* Pixel format FOURCC depth Description */ + +/* two planes -- one Y, one Cr + Cb interleaved */ +#define V4L2_PIX_FMT_YUV444_2P v4l2_fourcc('Y', 'U', '2', 'P') /* 24 Y/CbCr */ +#define V4L2_PIX_FMT_YVU444_2P v4l2_fourcc('Y', 'V', '2', 'P') /* 24 Y/CrCb */ + +/* three planes -- one Y, one Cr, one Cb */ +#define V4L2_PIX_FMT_YUV444_3P v4l2_fourcc('Y', 'U', '3', 'P') /* 24 Y/Cb/Cr */ + +/* two non contiguous planes - one Y, one Cr + Cb interleaved */ +/* 21 Y/CrCb 4:2:0 */ +#define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') +/* 12 Y/CbCr 4:2:0 16x16 macroblocks */ +#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') + +/* three non contiguous planes - Y, Cb, Cr */ +/* 12 YVU420 planar */ +#define V4L2_PIX_FMT_YVU420M v4l2_fourcc('Y', 'V', 'U', 'M') + +/* compressed formats */ +#define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC */ +#define V4L2_PIX_FMT_FIMV v4l2_fourcc('F', 'I', 'M', 'V') /* FIMV */ +#define V4L2_PIX_FMT_FIMV1 v4l2_fourcc('F', 'I', 'M', '1') /* FIMV1 */ +#define V4L2_PIX_FMT_FIMV2 v4l2_fourcc('F', 'I', 'M', '2') /* FIMV2 */ +#define V4L2_PIX_FMT_FIMV3 v4l2_fourcc('F', 'I', 'M', '3') /* FIMV3 */ +#define V4L2_PIX_FMT_FIMV4 v4l2_fourcc('F', 'I', 'M', '4') /* FIMV4 */ +#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* VP8 */ + +/* yuv444 of JFIF JPEG */ +#define V4L2_PIX_FMT_JPEG_444 v4l2_fourcc('J', 'P', 'G', '4') +/* yuv422 of JFIF JPEG */ +#define V4L2_PIX_FMT_JPEG_422 v4l2_fourcc('J', 'P', 'G', '2') +/* yuv420 of JFIF JPEG */ +#define V4L2_PIX_FMT_JPEG_420 v4l2_fourcc('J', 'P', 'G', '0') +/* grey of JFIF JPEG */ +#define V4L2_PIX_FMT_JPEG_GRAY v4l2_fourcc('J', 'P', 'G', 'G') + +/* + * C O N T R O L S + */ +/* CID base for Exynos controls (USER_CLASS) */ +#define V4L2_CID_EXYNOS_BASE (V4L2_CTRL_CLASS_USER | 0x2000) + +/* for rgb alpha function */ +#define V4L2_CID_GLOBAL_ALPHA (V4L2_CID_EXYNOS_BASE + 1) + +/* cacheable configuration */ +#define V4L2_CID_CACHEABLE (V4L2_CID_EXYNOS_BASE + 10) + +/* jpeg captured size */ +#define V4L2_CID_CAM_JPEG_MEMSIZE (V4L2_CID_EXYNOS_BASE + 20) +#define V4L2_CID_CAM_JPEG_ENCODEDSIZE (V4L2_CID_EXYNOS_BASE + 21) + +#define V4L2_CID_SET_SHAREABLE (V4L2_CID_EXYNOS_BASE + 40) + +/* TV configuration */ +#define V4L2_CID_TV_LAYER_BLEND_ENABLE (V4L2_CID_EXYNOS_BASE + 50) +#define V4L2_CID_TV_LAYER_BLEND_ALPHA (V4L2_CID_EXYNOS_BASE + 51) +#define V4L2_CID_TV_PIXEL_BLEND_ENABLE (V4L2_CID_EXYNOS_BASE + 52) +#define V4L2_CID_TV_CHROMA_ENABLE (V4L2_CID_EXYNOS_BASE + 53) +#define V4L2_CID_TV_CHROMA_VALUE (V4L2_CID_EXYNOS_BASE + 54) +#define V4L2_CID_TV_HPD_STATUS (V4L2_CID_EXYNOS_BASE + 55) +#define V4L2_CID_TV_LAYER_PRIO (V4L2_CID_EXYNOS_BASE + 56) +#define V4L2_CID_TV_SET_DVI_MODE (V4L2_CID_EXYNOS_BASE + 57) + +/* for color space conversion equation selection */ +#define V4L2_CID_CSC_EQ_MODE (V4L2_CID_EXYNOS_BASE + 100) +#define V4L2_CID_CSC_EQ (V4L2_CID_EXYNOS_BASE + 101) +#define V4L2_CID_CSC_RANGE (V4L2_CID_EXYNOS_BASE + 102) + +/* for DRM playback scenario */ +#define V4L2_CID_USE_SYSMMU (V4L2_CID_EXYNOS_BASE + 200) +#define V4L2_CID_M2M_CTX_NUM (V4L2_CID_EXYNOS_BASE + 201) + +/* CID base for MFC controls (MPEG_CLASS) */ +#define V4L2_CID_MPEG_MFC_BASE (V4L2_CTRL_CLASS_MPEG | 0x2000) + +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL \ + (V4L2_CID_MPEG_MFC_BASE + 1) +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID \ + (V4L2_CID_MPEG_MFC_BASE + 2) +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO \ + (V4L2_CID_MPEG_MFC_BASE + 3) +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS \ + (V4L2_CID_MPEG_MFC_BASE + 4) + +#define V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB \ + (V4L2_CID_MPEG_MFC_BASE + 5) +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG \ + (V4L2_CID_MPEG_MFC_BASE + 6) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE \ + (V4L2_CID_MPEG_MFC_BASE + 7) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA \ + (V4L2_CID_MPEG_MFC_BASE + 8) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA \ + (V4L2_CID_MPEG_MFC_BASE + 9) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA_BOT \ + (V4L2_CID_MPEG_MFC_BASE + 10) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA_BOT \ + (V4L2_CID_MPEG_MFC_BASE + 11) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_GENERATED \ + (V4L2_CID_MPEG_MFC_BASE + 12) +#define V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE \ + (V4L2_CID_MPEG_MFC_BASE + 13) +#define V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS \ + (V4L2_CID_MPEG_MFC_BASE + 14) + +#define V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR \ + (V4L2_CID_MPEG_MFC_BASE + 15) +#define V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR \ + (V4L2_CID_MPEG_MFC_BASE + 16) + +#define V4L2_CID_MPEG_MFC51_VIDEO_STREAM_SIZE \ + (V4L2_CID_MPEG_MFC_BASE + 17) +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_COUNT \ + (V4L2_CID_MPEG_MFC_BASE + 18) +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TYPE \ + (V4L2_CID_MPEG_MFC_BASE + 19) +enum v4l2_mpeg_mfc51_video_frame_type { + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_NOT_CODED = 0, + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_I_FRAME = 1, + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_P_FRAME = 2, + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_B_FRAME = 3, + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_SKIPPED = 4, + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_OTHERS = 5, +}; + +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE \ + (V4L2_CID_MPEG_MFC_BASE + 20) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE \ + (V4L2_CID_MPEG_MFC_BASE + 21) +#define V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_TIME_RES \ + (V4L2_CID_MPEG_MFC_BASE + 22) +#define V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA \ + (V4L2_CID_MPEG_MFC_BASE + 23) +#define V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE \ + (V4L2_CID_MPEG_MFC_BASE + 24) + +#define V4L2_CID_MPEG_MFC6X_VIDEO_FRAME_DELTA \ + (V4L2_CID_MPEG_MFC_BASE + 25) + +#define V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH V4L2_CID_MPEG_VIDEO_GOP_SIZE +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH \ + V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE +#define V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH V4L2_CID_MPEG_VIDEO_BITRATE + +/* proposed CIDs, based on 3.3-rc3 */ +#define V4L2_CID_MPEG_VIDEO_VBV_DELAY (V4L2_CID_MPEG_MFC_BASE + 26) + +#define V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_S_B \ + V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY + +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING \ + (V4L2_CID_MPEG_MFC_BASE + 27) +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0 \ + (V4L2_CID_MPEG_MFC_BASE + 28) +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE \ + (V4L2_CID_MPEG_MFC_BASE + 29) +enum v4l2_mpeg_video_h264_sei_fp_arrangement_type { + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_CHEKERBOARD = 0, + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_COLUMN = 1, + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_ROW = 2, + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_SIDE_BY_SIDE = 3, + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_TOP_BOTTOM = 4, + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_TEMPORAL = 5, +}; +#define V4L2_CID_MPEG_VIDEO_H264_FMO (V4L2_CID_MPEG_MFC_BASE + 30) +#define V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE (V4L2_CID_MPEG_MFC_BASE + 31) +enum v4l2_mpeg_video_h264_fmo_map_type { + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES = 0, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES = 1, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER = 2, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT = 3, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN = 4, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN = 5, + V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT = 6, +}; +#define V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP \ + (V4L2_CID_MPEG_MFC_BASE + 32) +#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION \ + (V4L2_CID_MPEG_MFC_BASE + 33) +enum v4l2_mpeg_video_h264_fmo_change_dir { + V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT = 0, + V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT = 1, +}; +#define V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE \ + (V4L2_CID_MPEG_MFC_BASE + 34) +#define V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH \ + (V4L2_CID_MPEG_MFC_BASE + 35) +#define V4L2_CID_MPEG_VIDEO_H264_ASO \ + (V4L2_CID_MPEG_MFC_BASE + 36) +#define V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER \ + (V4L2_CID_MPEG_MFC_BASE + 37) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING \ + (V4L2_CID_MPEG_MFC_BASE + 38) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE \ + (V4L2_CID_MPEG_MFC_BASE + 39) +enum v4l2_mpeg_video_h264_hierarchical_coding_type { + V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B = 0, + V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P = 1, +}; +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER \ + (V4L2_CID_MPEG_MFC_BASE + 40) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP \ + (V4L2_CID_MPEG_MFC_BASE + 41) +#define V4L2_CID_MPEG_VIDEO_H264_MVC_VIEW_ID \ + (V4L2_CID_MPEG_MFC_BASE + 42) +#endif /* __LINUX_VIDEODEV2_EXYNOS_H */ -- cgit v1.1 From 5db162876e904c3584156f7484332c15d474c8db Mon Sep 17 00:00:00 2001 From: Daniel Hillenbrand Date: Wed, 4 Sep 2013 20:36:21 +0200 Subject: smdk4412: camera: update headers Change-Id: Ia1cf27dc04e3468e10041d91d7d9f60a04e6c32b --- camera/include/linux/s5c73m3.h | 28 +- camera/include/linux/videodev2_exynos_camera.h | 718 ++++++++++++++++++++++++- 2 files changed, 714 insertions(+), 32 deletions(-) (limited to 'camera') diff --git a/camera/include/linux/s5c73m3.h b/camera/include/linux/s5c73m3.h index d2e57d5..ffb582e 100644 --- a/camera/include/linux/s5c73m3.h +++ b/camera/include/linux/s5c73m3.h @@ -64,41 +64,33 @@ enum s5c73m3_fw_path{ }; enum s5c73m3_prev_frmsize { - S5C73M3_PREVIEW_QCIF, - S5C73M3_PREVIEW_QCIF2, S5C73M3_PREVIEW_QVGA, S5C73M3_PREVIEW_CIF, S5C73M3_PREVIEW_VGA, S5C73M3_PREVIEW_D1, - S5C73M3_PREVIEW_WVGA, - S5C73M3_PREVIEW_704X576, + S5C73M3_PREVIEW_800X600, S5C73M3_PREVIEW_880X720, - S5C73M3_PREVIEW_960X640, S5C73M3_PREVIEW_960X720, S5C73M3_PREVIEW_1008X672, - S5C73M3_PREVIEW_1056X704, S5C73M3_PREVIEW_1184X666, S5C73M3_PREVIEW_720P, + S5C73M3_PREVIEW_1280X960, S5C73M3_VDIS_720P, S5C73M3_PREVIEW_1080P, S5C73M3_VDIS_1080P, - S5C73M3_PREVIEW_HDR, }; enum s5c73m3_cap_frmsize { S5C73M3_CAPTURE_VGA, /* 640 x 480 */ - S5C73M3_CAPTURE_WVGA, /* 800 x 480 */ + S5C73M3_CAPTURE_960x540, /* 960 x 540 */ + S5C73M3_CAPTURE_960x720, /* 960 x 720 */ S5C73M3_CAPTURE_1024X768, /* 1024 x 768 */ S5C73M3_CAPTURE_HD, /* 1280 x 720 */ - S5C73M3_CAPTURE_W1MP, /* 1600 x 960 */ S5C73M3_CAPTURE_2MP, /* UXGA - 1600 x 1200 */ S5C73M3_CAPTURE_W2MP, /* 2048 x 1232 */ S5C73M3_CAPTURE_3MP, /* QXGA - 2048 x 1536 */ - S5C73M3_CAPTURE_W4MP, /* WQXGA - 2560 x 1536 */ S5C73M3_CAPTURE_5MP, /* 2560 x 1920 */ S5C73M3_CAPTURE_W6MP, /* 3072 x 1856 */ - S5C73M3_CAPTURE_7MP, /* 3072 x 2304 */ - S5C73M3_CAPTURE_W7MP, /* WQXGA - 2560 x 1536 */ S5C73M3_CAPTURE_3264X2176, /* 3264 x 2176 */ S5C73M3_CAPTURE_8MP, /* 3264 x 2448 */ }; @@ -144,6 +136,7 @@ enum s5c73m3_isneed_flash_tristate { #define S5C73M3_IMAGE_EFFECT_POINT_RED_YELLOW 0x000D #define S5C73M3_IMAGE_EFFECT_POINT_COLOR_3 0x000E #define S5C73M3_IMAGE_EFFECT_POINT_GREEN 0x000F +#define S5C73M3_IMAGE_EFFECT_CARTOONIZE 0x001A #define S5C73M3_IMAGE_QUALITY 0x0B0C #define S5C73M3_IMAGE_QUALITY_SUPERFINE 0x0000 @@ -166,9 +159,9 @@ enum s5c73m3_isneed_flash_tristate { #define S5C73M3_CHG_MODE 0x0B10 -#define S5C73M3_YUV_MODE 0x8000 -#define S5C73M3_INTERLEAVED_MODE 0x8000 - +#define S5C73M3_DEFAULT_MODE 0x8000 +#define S5C73M3_FAST_MODE_SUBSAMPLING_HALF 0xA000 +#define S5C73M3_FAST_MODE_SUBSAMPLING_QUARTER 0xC000 #define S5C73M3_AF_CON 0x0E00 #define S5C73M3_AF_CON_STOP 0x0000 @@ -262,9 +255,11 @@ enum s5c73m3_isneed_flash_tristate { #define S5C73M3_FIXED_30FPS 0x0002 #define S5C73M3_FIXED_20FPS 0x0003 #define S5C73M3_FIXED_15FPS 0x0004 +#define S5C73M3_FIXED_60FPS 0x0007 #define S5C73M3_FIXED_120FPS 0x0008 #define S5C73M3_FIXED_7FPS 0x0009 #define S5C73M3_FIXED_10FPS 0x000A +#define S5C73M3_FIXED_90FPS 0x000B #define S5C73M3_ANTI_SHAKE 0x0013 #define S5C73M3_SHARPNESS 0x0C14 @@ -303,10 +298,13 @@ enum s5c73m3_isneed_flash_tristate { #define S5C73M3_SCENE_MODE_FIRE 0x000B #define S5C73M3_SCENE_MODE_TEXT 0x000C #define S5C73M3_SCENE_MODE_CANDLE 0x000D +#define S5C73M3_SCENE_MODE_LOW_LIGHT 0x0020 #define S5C73M3_FIREWORK_CAPTURE 0x0C20 #define S5C73M3_NIGHTSHOT_CAPTURE 0x0C22 +#define S5C73M3_AE_LOW_LIGHT_MODE 0x0C2C + #define S5C73M3_AE_AUTO_BRAKET 0x0B14 #define S5C73M3_AE_AUTO_BRAKET_EV05 0x0080 #define S5C73M3_AE_AUTO_BRAKET_EV10 0x0100 diff --git a/camera/include/linux/videodev2_exynos_camera.h b/camera/include/linux/videodev2_exynos_camera.h index b9967ce..557b5e1 100644 --- a/camera/include/linux/videodev2_exynos_camera.h +++ b/camera/include/linux/videodev2_exynos_camera.h @@ -159,12 +159,8 @@ enum cam_vt_mode { #define V4L2_CID_CAMERA_VGA_BLUR (V4L2_CID_PRIVATE_BASE + 49) #define V4L2_CID_CAMERA_CAPTURE (V4L2_CID_PRIVATE_BASE + 50) -#define V4L2_CID_CAMERA_HDR (V4L2_CID_PRIVATE_BASE + 51) +#define V4L2_CID_CAMERA_HDR (V4L2_CID_PRIVATE_BASE + 51) #define V4L2_CID_CAMERA_HYBRID (V4L2_CID_PRIVATE_BASE + 52) -#define V4L2_CID_CAMERA_HYBRID_CAPTURE (V4L2_CID_PRIVATE_BASE + 62) -#define V4L2_CID_CAMERA_POSTVIEW_CAPTURE (V4L2_CID_PRIVATE_BASE + 67) -#define V4L2_CID_CAMERA_CAPTURE_MODE (V4L2_CID_PRIVATE_BASE + 68) -#define V4L2_CID_CAMERA_YUV_CAPTURE (V4L2_CID_PRIVATE_BASE + 69) #define V4L2_CID_MAIN_SW_DATE_INFO_YEAR (V4L2_CID_PRIVATE_BASE + 54) #define V4L2_CID_MAIN_SW_DATE_INFO_MONTH (V4L2_CID_PRIVATE_BASE + 55) @@ -173,9 +169,20 @@ enum cam_vt_mode { #define V4L2_CID_MAIN_SW_FW_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 58) #define V4L2_CID_MAIN_SW_PRM_MINOR_VER (V4L2_CID_PRIVATE_BASE + 59) #define V4L2_CID_MAIN_SW_PRM_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 60) +#define V4L2_CID_CAMERA_HYBRID_CAPTURE (V4L2_CID_PRIVATE_BASE + 62) +#define V4L2_CID_CAMERA_FAST_MODE (V4L2_CID_PRIVATE_BASE + 66) +enum cam_fast_mode { + FAST_MODE_SUBSAMPLING_NONE , + FAST_MODE_SUBSAMPLING_HALF , + FAST_MODE_SUBSAMPLING_QUARTER , +}; +#define V4L2_CID_CAMERA_POSTVIEW_CAPTURE (V4L2_CID_PRIVATE_BASE + 67) +#define V4L2_CID_CAMERA_CAPTURE_MODE (V4L2_CID_PRIVATE_BASE + 68) +#define V4L2_CID_CAMERA_YUV_CAPTURE (V4L2_CID_PRIVATE_BASE + 69) #define V4L2_CID_FIMC_IS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x1000) #define V4L2_CID_FIMC_IS_TUNE_BASE (V4L2_CTRL_CLASS_CAMERA | 0x2000) +#define V4L2_CID_FIMC_IS_ISP_DBG_BASE (V4L2_CTRL_CLASS_CAMERA | 0x3000) #define V4L2_CID_IS_LOAD_FW (V4L2_CID_FIMC_IS_BASE + 10) #define V4L2_CID_IS_INIT_PARAM (V4L2_CID_FIMC_IS_BASE + 11) @@ -203,7 +210,7 @@ enum scenario_mode { }; /* global */ -#define V4L2_CID_IS_CAMERA_SHOT_MODE_NORMAL (V4L2_CID_FIMC_IS_BASE + 101) +#define V4L2_CID_IS_CAMERA_SHOT_MODE_NORMAL (V4L2_CID_FIMC_IS_BASE + 400) /* value : 1 : single shot , >=2 : continuous shot */ #define V4L2_CID_IS_CAMERA_SENSOR_NUM (V4L2_CID_FIMC_IS_BASE + 201) @@ -686,6 +693,7 @@ enum v4l2_scene_mode { SCENE_MODE_FIREWORKS, SCENE_MODE_TEXT, SCENE_MODE_CANDLE_LIGHT, + SCENE_MODE_LOW_LIGHT, SCENE_MODE_MAX, }; @@ -747,6 +755,10 @@ enum v4l2_wb_mode { WHITE_BALANCE_FLUORESCENT_L, WHITE_BALANCE_CUSTOM, WHITE_BALANCE_K, + WHITE_BALANCE_INCANDESCENT, + WHITE_BALANCE_PROHIBITION, + WHITE_BALANCE_HORIZON, + WHITE_BALANCE_LEDLIGHT, WHITE_BALANCE_MAX, }; @@ -770,6 +782,9 @@ enum v4l2_effect_mode { IMAGE_EFFECT_POINT_RED_YELLOW, IMAGE_EFFECT_POINT_COLOR_3, IMAGE_EFFECT_POINT_GREEN, + IMAGE_EFFECT_POINT_RED, + IMAGE_EFFECT_POINT_YELLOW, + IMAGE_EFFECT_CARTOONIZE, IMAGE_EFFECT_MAX, }; @@ -782,6 +797,7 @@ enum v4l2_iso_mode { ISO_400, ISO_800, ISO_1600, + ISO_3200, ISO_SPORTS, ISO_NIGHT, ISO_MOVIE, @@ -868,7 +884,9 @@ enum v4l2_vintage_mode { }; #define V4L2_CID_CAMERA_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE+85) -/* (V4L2_CID_PRIVATE_BASE+86) */ +#define V4L2_CID_CAMERA_CAPTURE_THUMB (V4L2_CID_PRIVATE_BASE + 86) +#define V4L2_CID_CAMERA_YUV_SNAPSHOT (V4L2_CID_PRIVATE_BASE + 87) +#define V4L2_CID_CAMERA_LOW_LIGHT_MODE (V4L2_CID_PRIVATE_BASE + 88) #define V4L2_CID_CAMERA_GPS_LATITUDE (V4L2_CID_CAMERA_CLASS_BASE+30) /* (V4L2_CID_PRIVATE_BASE+87) */ #define V4L2_CID_CAMERA_GPS_LONGITUDE (V4L2_CID_CAMERA_CLASS_BASE + 31) @@ -986,17 +1004,19 @@ enum v4l2_focusmode { FOCUS_MODE_CONTINOUS_PICTURE_MACRO, FOCUS_MODE_CONTINOUS_VIDEO, FOCUS_MODE_TOUCH, + FOCUS_MODE_MANUAL, + FOCUS_MODE_MULTI, + FOCUS_MODE_OBJECT_TRACKING, FOCUS_MODE_MAX, FOCUS_MODE_DEFAULT = (1 << 8), }; #define V4L2_CID_CAMERA_OBJ_TRACKING_STATUS (V4L2_CID_PRIVATE_BASE+100) enum v4l2_obj_tracking_status { - OBJECT_TRACKING_STATUS_BASE, - OBJECT_TRACKING_STATUS_PROGRESSING, - OBJECT_TRACKING_STATUS_SUCCESS, - OBJECT_TRACKING_STATUS_FAIL, - OBJECT_TRACKING_STATUS_MISSING, + OBJECT_TRACKING_STATUS_BASE = 0, + OBJECT_TRACKING_STATUS_SUCCESS = 1, + OBJECT_TRACKING_STATUS_MISSING = 2, + OBJECT_TRACKING_STATUS_FAIL = 3, OBJECT_TRACKING_STATUS_MAX, }; @@ -1042,7 +1062,8 @@ enum v4l2_anti_banding { ANTI_BANDING_AUTO = 0, ANTI_BANDING_50HZ = 1, ANTI_BANDING_60HZ = 2, - ANTI_BANDING_OFF = 3, + ANTI_BANDING_50_60Hz = 3, + ANTI_BANDING_OFF = 4, }; #define V4L2_CID_CAMERA_SET_GAMMA (V4L2_CID_PRIVATE_BASE+106) @@ -1167,6 +1188,7 @@ enum v4l2_face_bracket_aeb_value { #define V4L2_CID_CAMERA_BRACKET_WBB (V4L2_CID_PRIVATE_BASE+136) enum v4l2_face_bracket_wbb_value { + BRACKET_WBB_OFF = 0, BRACKET_WBB_VALUE1 = 1, BRACKET_WBB_VALUE2, BRACKET_WBB_VALUE3, @@ -1187,21 +1209,56 @@ enum v4l2_drive_dial { enum v4l2_running_cap_mode { RUNNING_MODE_SINGLE = 0, RUNNING_MODE_CONTINUOUS, - RUNNING_MODE_BRACKET, + RUNNING_MODE_BEST, + RUNNING_MODE_LOWLIGHT, + RUNNING_MODE_AE_BRACKET, + RUNNING_MODE_WB_BRACKET, RUNNING_MODE_HDR, RUNNING_MODE_BLINK, + RUNNING_MODE_RAW, + RUNNING_MODE_BURST, RUNNING_MODE_MAX }; +enum v4l2_continuous_mode { + CONTINUOUS_MODE_OFF = 0, + CONTINUOUS_MODE_ON, + CONTINUOUS_MODE_MAX, +}; + +enum v4l2_continuous_fps { + MULTI_CAPTURE_FPS_1 = 0, + MULTI_CAPTURE_FPS_10, + MULTI_CAPTURE_FPS_5, + MULTI_CAPTURE_FPS_3, + MULTI_CAPTURE_FPS_MAX, +}; + +enum v4l2_burst_mode { + BURST_MODE_OFF = 0, + BURST_MODE_ON, +}; + +enum v4l2_best_mode { + BEST_MODE_OFF = 0, + BEST_MODE_ON, + BEST_MODE_MAX,}; + +enum v4l2_lowlight_mode { + LOWLIGHT_MODE_OFF = 0, + LOWLIGHT_MODE_ON, + LOWLIGHT_MODE_MAX,}; + #define V4L2_CID_CAMERA_FD_EYE_BLINK_RESULT (V4L2_CID_PRIVATE_BASE+138) #define V4L2_CID_CAMERA_OPTICAL_ZOOM_STEP (V4L2_CID_PRIVATE_BASE + 139) #define V4L2_CID_CAMERA_OPTICAL_ZOOM_CTRL (V4L2_CID_PRIVATE_BASE + 140) - enum v4l2_optical_zoom_ctrl { - V4L2_OPTICAL_ZOOM_TELE, - V4L2_OPTICAL_ZOOM_WIDE, V4L2_OPTICAL_ZOOM_STOP, + V4L2_OPTICAL_ZOOM_TELE_START, + V4L2_OPTICAL_ZOOM_WIDE_START, + V4L2_OPTICAL_ZOOM_SLOW_TELE_START, + V4L2_OPTICAL_ZOOM_SLOW_WIDE_START, }; #define V4L2_CID_CAMERA_LDC (V4L2_CID_PRIVATE_BASE+142) @@ -1216,6 +1273,542 @@ enum set_LSC_mode { LSC_SET_ON = 1, }; +#define V4L2_CID_CAMERA_FACTORY_OIS (V4L2_CID_PRIVATE_BASE+147) +enum set_Factory_OIS { + FACTORY_OIS_RETURN_TO_CENTER = 0, + FACTORY_OIS_RUN = 1, + FACTORY_OIS_START = 2, + FACTORY_OIS_STOP = 3, + FACTORY_OIS_MODE_ON = 4, + FACTORY_OIS_MODE_OFF = 5, + FACTORY_OIS_LOG = 6, + FACTORY_OIS_ON = 7, +}; + +#define V4L2_CID_CAMERA_FACTORY_ZOOM_RANGE_CHECK_DATA_MIN \ + (V4L2_CID_PRIVATE_BASE+148) +#define V4L2_CID_CAMERA_FACTORY_ZOOM_RANGE_CHECK_DATA_MAX \ + (V4L2_CID_PRIVATE_BASE+149) +#define V4L2_CID_CAMERA_FACTORY_ZOOM_SLOPE_CHECK_DATA_MIN \ + (V4L2_CID_PRIVATE_BASE+152) +#define V4L2_CID_CAMERA_FACTORY_ZOOM_SLOPE_CHECK_DATA_MAX \ + (V4L2_CID_PRIVATE_BASE+153) +#define V4L2_CID_CAMERA_FACTORY_ZOOM_STEP (V4L2_CID_PRIVATE_BASE+154) +#define V4L2_CID_CAMERA_FACTORY_ZOOM (V4L2_CID_PRIVATE_BASE+155) +enum set_Factory_Zoom { + FACTORY_ZOOM_MOVE_STEP = 0, + FACTORY_ZOOM_RANGE_CHECK_START = 1, + FACTORY_ZOOM_RANGE_CHECK_STOP = 2, + FACTORY_ZOOM_SLOPE_CHECK_START = 3, + FACTORY_ZOOM_SLOPE_CHECK_STOP = 4, + FACTORY_ZOOM_SET_RANGE_CHECK_DATA = 5, + FACTORY_ZOOM_SET_SLOPE_CHECK_DATA = 6, + FACTORY_ZOOM_STEP_TELE = 7, + FACTORY_ZOOM_STEP_WIDE = 8, + FACTORY_ZOOM_MOVE_END_CHECK = 9, +}; + +#define V4L2_CID_CAMERA_FACTORY_PUNT_RANGE_DATA_MIN \ + (V4L2_CID_PRIVATE_BASE+156) +#define V4L2_CID_CAMERA_FACTORY_PUNT_RANGE_DATA_MAX \ + (V4L2_CID_PRIVATE_BASE+157) +#define V4L2_CID_CAMERA_FACTORY_PUNT_RANGE_DATA_NUM \ + (V4L2_CID_PRIVATE_BASE+158) +#define V4L2_CID_CAMERA_FACTORY_PUNT (V4L2_CID_PRIVATE_BASE+159) +enum set_Factory_Punt { + FACTORY_PUNT_RANGE_START = 0, + FACTORY_PUNT_RANGE_STOP = 1, + FACTORY_PUNT_SHORT_SCAN_DATA = 2, + FACTORY_PUNT_SHORT_SCAN_START = 3, + FACTORY_PUNT_SHORT_SCAN_STOP = 4, + FACTORY_PUNT_LONG_SCAN_DATA = 5, + FACTORY_PUNT_LONG_SCAN_START = 6, + FACTORY_PUNT_LONG_SCAN_STOP = 7, + FACTORY_PUNT_LOG = 8, + FACTORY_PUNT_SET_RANGE_DATA = 9, + FACTORY_PUNT_EEP_WRITE = 10, +}; + +#define V4L2_CID_CAMERA_FACTORY_FAIL_STOP (V4L2_CID_PRIVATE_BASE+160) +enum set_Factory_Fail_Stop { + FACTORY_FAIL_STOP_ON = 0, + FACTORY_FAIL_STOP_OFF = 1, + FACTORY_FAIL_STOP_RUN = 2, + FACTORY_FAIL_STOP_STOP = 3, +}; + +#define V4L2_CID_CAMERA_FACTORY_NODEFOCUS (V4L2_CID_PRIVATE_BASE+161) +enum set_Factory_NoDeFocus { + FACTORY_NODEFOCUSYES_ON = 0, + FACTORY_NODEFOCUSYES_OFF = 1, + FACTORY_NODEFOCUSYES_RUN = 2, + FACTORY_NODEFOCUSYES_STOP = 3, +}; + +#define V4L2_CID_CAMERA_FACTORY_INTERPOLATION (V4L2_CID_PRIVATE_BASE+162) +enum set_Factory_Interpolation { + FACTORY_INTERPOLATION_USE = 0, + FACTORY_INTERPOLATION_RELEASE = 1, +}; + +#define V4L2_CID_CAMERA_FACTORY_DOWN_RESULT (V4L2_CID_PRIVATE_BASE+163) +#define V4L2_CID_CAMERA_FACTORY_END_RESULT (V4L2_CID_PRIVATE_BASE+164) +#define V4L2_CID_CAMERA_FACTORY_COMMON (V4L2_CID_PRIVATE_BASE+165) +enum set_Factory_Common { + FACTORY_FIRMWARE_DOWNLOAD = 0, + FACTORY_DOWNLOAD_CHECK = 1, + FACTORY_END_CHECK = 2, + FACTORY_COMMON_SET_FOCUS_ZONE_MACRO = 3, + FACTORY_FPS30_ON = 4, + FACTORY_FPS30_OFF = 5, +}; + +#define V4L2_CID_CAMERA_FACTORY_VIB (V4L2_CID_PRIVATE_BASE+166) +enum set_Factory_Vib { + FACTORY_VIB_START = 0, + FACTORY_VIB_STOP = 1, + FACTORY_VIB_LOG = 2, +}; + +#define V4L2_CID_CAMERA_FACTORY_GYRO (V4L2_CID_PRIVATE_BASE+167) +enum set_Factory_Gyro { + FACTORY_GYRO_START = 0, + FACTORY_GYRO_STOP = 1, + FACTORY_GYRO_LOG = 2, +}; + +#define V4L2_CID_CAMERA_FACTORY_BACKLASH (V4L2_CID_PRIVATE_BASE+168) +enum set_Factory_Backlash { + FACTORY_BACKLASH_INPUT = 0, + FACTORY_BACKLASH_MAX_THR = 1, + FACTORY_BACKLASH_WIDE_RUN = 2, + FACTORY_BACKLASH_LOG = 3, +}; + +#define V4L2_CID_CAMERA_FACTORY_AF_STEP_SET (V4L2_CID_PRIVATE_BASE+169) +#define V4L2_CID_CAMERA_FACTORY_AF_POSITION (V4L2_CID_PRIVATE_BASE+170) +#define V4L2_CID_CAMERA_FACTORY_AF_INT_RESULT (V4L2_CID_PRIVATE_BASE+171) +#define V4L2_CID_CAMERA_FACTORY_AF (V4L2_CID_PRIVATE_BASE+172) +enum set_Factory_AF { + FACTORY_AF_LOCK_ON_SET = 0, + FACTORY_AF_LOCK_OFF_SET = 1, + FACTORY_AF_MOVE = 2, + FACTORY_AF_STEP_LOG = 3, + FACTORY_AF_LOCK_START = 4, + FACTORY_AF_LOCK_STOP = 5, + FACTORY_AF_FOCUS_LOG = 6, + FACTORY_AF_INT_SET = 7, + FACTORY_AF_SCAN_LIMIT_START = 8, + FACTORY_AF_SCAN_LIMIT_STOP = 10, + FACTORY_AF_SCAN_RANGE_START = 11, + FACTORY_AF_SCAN_RANGE_STOP = 12, + FACTORY_AF_STEP_SAVE = 13, + FACTORY_AF_LED_END_CHECK = 14, + FACTORY_AF_LED_LOG = 15, + FACTORY_AF_MOVE_END_CHECK = 16, + FACTORY_AF_SCAN_END_CHECK = 17, +}; + +#define V4L2_CID_CAMERA_FACTORY_DEFOCUS_WIDE (V4L2_CID_PRIVATE_BASE+173) +#define V4L2_CID_CAMERA_FACTORY_DEFOCUS_TELE (V4L2_CID_PRIVATE_BASE+174) +#define V4L2_CID_CAMERA_FACTORY_DEFOCUS (V4L2_CID_PRIVATE_BASE+175) +enum set_Factory_DeFocus { + FACTORY_DEFOCUS_RUN = 0, + FACTORY_DEFOCUS_STOP = 1, +}; + +#define V4L2_CID_CAMERA_FACTORY_RESOL_CAP (V4L2_CID_PRIVATE_BASE+176) +enum set_Factory_Resol_Cap { + FACTORY_CAP_COMP_ON = 0, + FACTORY_CAP_COMP_OFF = 1, + FACTORY_CAP_BARREL_ON = 2, + FACTORY_CAP_BARREL_OFF = 3, + FACTORY_CAP_BARREL_START = 4, + FACTORY_CAP_BARREL_STOP = 5, + FACTORY_CAP_COMP_START = 6, + FACTORY_CAP_COMP_STOP = 7, +}; + +#define V4L2_CID_CAMERA_SET_G_VALUE (V4L2_CID_PRIVATE_BASE + 177) +#define V4L2_CID_CAMERA_SET_B_VALUE (V4L2_CID_PRIVATE_BASE + 178) +#define V4L2_CID_CAMERA_SET_A_VALUE (V4L2_CID_PRIVATE_BASE + 179) +#define V4L2_CID_CAMERA_SET_M_VALUE (V4L2_CID_PRIVATE_BASE + 180) +#define V4L2_CID_CAMERA_SET_GBAM (V4L2_CID_PRIVATE_BASE + 181) +#define V4L2_CID_CAMERA_SET_K_VALUE (V4L2_CID_PRIVATE_BASE + 182) +#define V4L2_CID_CAMERA_SET_FLASH_EVC_STEP (V4L2_CID_PRIVATE_BASE + 183) + +#define V4L2_CID_CAMERA_APERTURE_CMD (V4L2_CID_PRIVATE_BASE+184) +enum set_Factory_Aperture_Cmd { + FACTORY_CMD_PREVIEW = 0, + FACTORY_CMD_CAPTURE = 1, +}; + +#define V4L2_CID_CAMERA_FACTORY_OIS_RANGE_DATA_X_MIN (V4L2_CID_PRIVATE_BASE+185) +#define V4L2_CID_CAMERA_FACTORY_OIS_RANGE_DATA_X_MAX (V4L2_CID_PRIVATE_BASE+186) +#define V4L2_CID_CAMERA_FACTORY_OIS_RANGE_DATA_Y_MIN (V4L2_CID_PRIVATE_BASE+187) +#define V4L2_CID_CAMERA_FACTORY_OIS_RANGE_DATA_Y_MAX (V4L2_CID_PRIVATE_BASE+188) +#define V4L2_CID_CAMERA_FACTORY_OIS_RANGE_DATA_X_GAIN \ + (V4L2_CID_PRIVATE_BASE+189) +#define V4L2_CID_CAMERA_FACTORY_OIS_RANGE_DATA_PEAK_X \ + (V4L2_CID_PRIVATE_BASE+190) +#define V4L2_CID_CAMERA_FACTORY_OIS_RANGE_DATA_PEAK_Y \ + (V4L2_CID_PRIVATE_BASE+191) + +#define V4L2_CID_CAMERA_FACTORY_VIB_RANGE_DATA_X_MIN (V4L2_CID_PRIVATE_BASE+192) +#define V4L2_CID_CAMERA_FACTORY_VIB_RANGE_DATA_X_MAX (V4L2_CID_PRIVATE_BASE+193) +#define V4L2_CID_CAMERA_FACTORY_VIB_RANGE_DATA_Y_MIN (V4L2_CID_PRIVATE_BASE+194) +#define V4L2_CID_CAMERA_FACTORY_VIB_RANGE_DATA_Y_MAX (V4L2_CID_PRIVATE_BASE+195) +#define V4L2_CID_CAMERA_FACTORY_VIB_RANGE_DATA_PEAK_X \ + (V4L2_CID_PRIVATE_BASE+196) +#define V4L2_CID_CAMERA_FACTORY_VIB_RANGE_DATA_PEAK_Y \ + (V4L2_CID_PRIVATE_BASE+197) + +#define V4L2_CID_CAMERA_FACTORY_GYRO_RANGE_DATA_X_MIN \ + (V4L2_CID_PRIVATE_BASE+198) +#define V4L2_CID_CAMERA_FACTORY_GYRO_RANGE_DATA_X_MAX \ + (V4L2_CID_PRIVATE_BASE+199) +#define V4L2_CID_CAMERA_FACTORY_GYRO_RANGE_DATA_Y_MIN \ + (V4L2_CID_PRIVATE_BASE+200) +#define V4L2_CID_CAMERA_FACTORY_GYRO_RANGE_DATA_Y_MAX \ + (V4L2_CID_PRIVATE_BASE+202) + +#define V4L2_CID_CAMERA_FACTORY_TEST_NUMBER (V4L2_CID_PRIVATE_BASE+203) + +#define V4L2_CID_CAMERA_FACTORY_BACKLASH_COUNT (V4L2_CID_PRIVATE_BASE+204) +#define V4L2_CID_CAMERA_FACTORY_BACKLASH_MAXTHRESHOLD \ + (V4L2_CID_PRIVATE_BASE+205) + +#define V4L2_CID_CAMERA_FACTORY_CAPTURE_CTRL (V4L2_CID_PRIVATE_BASE + 206) +enum set_Factory_Cap_Ctrl { + FACTORY_STILL_CAP_NORMAL = 0, + FACTORY_STILL_CAP_DUALCAP = 1, + FACTORY_DUAL_CAP_ON = 2, + FACTORY_DUAL_CAP_OFF = 3, +}; + +#define V4L2_CID_CAMERA_DUAL_POSTVIEW (V4L2_CID_PRIVATE_BASE + 207) +#define V4L2_CID_CAMERA_DUAL_CAPTURE (V4L2_CID_PRIVATE_BASE + 208) +#define V4L2_CID_CAMERA_SET_DUAL_CAPTURE (V4L2_CID_PRIVATE_BASE + 209) +#define V4L2_CID_CAMERA_DUAL_CAPTURE_MODE (V4L2_CID_PRIVATE_BASE + 210) + +#define V4L2_CID_CAMERA_FOCUS_AREA_MODE (V4L2_CID_PRIVATE_BASE + 211) +enum set_fouce_area { + V4L2_FOCUS_AREA_CENTER = 0, + V4L2_FOCUS_AREA_MULTI = 1, + V4L2_FOCUS_AREA_SMART_TOUCH = 2, +}; + +#define V4L2_CID_CAMERA_FACTORY_AF_SCAN_LIMIT_MIN (V4L2_CID_PRIVATE_BASE+212) +#define V4L2_CID_CAMERA_FACTORY_AF_SCAN_LIMIT_MAX (V4L2_CID_PRIVATE_BASE+213) +#define V4L2_CID_CAMERA_FACTORY_AF_SCAN_RANGE_MIN (V4L2_CID_PRIVATE_BASE+214) +#define V4L2_CID_CAMERA_FACTORY_AF_SCAN_RANGE_MAX (V4L2_CID_PRIVATE_BASE+215) +#define V4L2_CID_CAM_APERTURE_PREVIEW (V4L2_CID_PRIVATE_BASE+216) +#define V4L2_CID_CAM_APERTURE_CAPTURE (V4L2_CID_PRIVATE_BASE+217) + +#define V4L2_CID_CAMERA_FACTORY_AF_ZONE (V4L2_CID_PRIVATE_BASE+218) +enum set_Factory_AFZone_Cmd { + FACTORY_AFZONE_NORMAL = 0, + FACTORY_AFZONE_MACRO, + FACTORY_AFZONE_AUTO, +}; + +#define V4L2_CID_CAMERA_FACTORY_OIS_SHIFT (V4L2_CID_PRIVATE_BASE+219) +#define V4L2_CID_CAMERA_FACTORY_FLICKER (V4L2_CID_PRIVATE_BASE+220) +enum set_Factory_Flicker_Cmd { + FACTORY_FLICKER_AUTO = 0, + FACTORY_FLICKER_50HZ, + FACTORY_FLICKER_60HZ, + FACTORY_FLICKER_50_60, + FACTORY_FLICKER_OFF, +}; + +#define V4L2_CID_CAMERA_FACTORY_AF_LENS (V4L2_CID_PRIVATE_BASE+221) +enum set_Factory_AFLENS_Cmd { + FACTORY_AFLENS_OPEN = 0, + FACTORY_AFLENS_CLOSE, +}; + +#define V4L2_CID_CAMERA_FACTORY_LV_TARGET (V4L2_CID_PRIVATE_BASE+222) + +#define V4L2_CID_CAMERA_FACTORY_ADJ_IRIS_RANGE_MIN (V4L2_CID_PRIVATE_BASE+223) +#define V4L2_CID_CAMERA_FACTORY_ADJ_IRIS_RANGE_MAX (V4L2_CID_PRIVATE_BASE+224) +#define V4L2_CID_CAMERA_FACTORY_ADJ_IRIS (V4L2_CID_PRIVATE_BASE+225) +enum set_Factory_Adj_IRIS_Cmd { + FACTORY_ADJ_IRIS_RUN = 0, + FACTORY_ADJ_IRIS_STOP, + FACTORY_ADJ_IRIS_END_CHECK, + FACTORY_ADJ_IRIS_LOG, +}; + +#define V4L2_CID_CAMERA_FACTORY_ADJ_GAIN_LIVEVIEW_RANGE_MIN \ + (V4L2_CID_PRIVATE_BASE+226) +#define V4L2_CID_CAMERA_FACTORY_ADJ_GAIN_LIVEVIEW_RANGE_MAX \ + (V4L2_CID_PRIVATE_BASE+227) +#define V4L2_CID_CAMERA_FACTORY_ADJ_GAIN_LIVEVIEW (V4L2_CID_PRIVATE_BASE+228) +enum set_Factory_Adj_Gain_LiveView_Cmd { + FACTORY_ADJ_GAIN_LIVEVIEW_RUN = 0, + FACTORY_ADJ_GAIN_LIVEVIEW_STOP, + FACTORY_ADJ_GAIN_LIVEVIEW_END_CHECK, + FACTORY_ADJ_GAIN_LIVEVIEW_LOG, +}; + +#define V4L2_CID_CAMERA_FACTORY_SH_CLOSE_IRIS_NUM (V4L2_CID_PRIVATE_BASE+229) +#define V4L2_CID_CAMERA_FACTORY_SH_CLOSE_SET_IRIS (V4L2_CID_PRIVATE_BASE+230) +#define V4L2_CID_CAMERA_FACTORY_SH_CLOSE_ISO (V4L2_CID_PRIVATE_BASE+231) +#define V4L2_CID_CAMERA_FACTORY_SH_CLOSE_RANGE (V4L2_CID_PRIVATE_BASE+232) +#define V4L2_CID_CAMERA_FACTORY_SH_CLOSE_SPEEDTIME_X (V4L2_CID_PRIVATE_BASE+233) +#define V4L2_CID_CAMERA_FACTORY_SH_CLOSE_SPEEDTIME_Y (V4L2_CID_PRIVATE_BASE+234) +#define V4L2_CID_CAMERA_FACTORY_SH_CLOSE (V4L2_CID_PRIVATE_BASE+235) +enum set_Factory_SH_Close_Cmd { + FACTORY_SH_CLOSE_RUN = 0, + FACTORY_SH_CLOSE_STOP, + FACTORY_SH_CLOSE_END_CHECK, + FACTORY_SH_CLOSE_LOG, +}; + +#define V4L2_CID_CAMERA_FACTORY_CAPTURE_GAIN_RANGE_MIN \ + (V4L2_CID_PRIVATE_BASE+236) +#define V4L2_CID_CAMERA_FACTORY_CAPTURE_GAIN_RANGE_MAX \ + (V4L2_CID_PRIVATE_BASE+237) +#define V4L2_CID_CAMERA_FACTORY_CAPTURE_GAIN (V4L2_CID_PRIVATE_BASE+238) +enum set_Factory_Capture_Gain_Cmd { + FACTORY_CAPTURE_GAIN_RUN = 0, + FACTORY_CAPTURE_GAIN_STOP, + FACTORY_CAPTURE_GAIN_END_CHECK, + FACTORY_CAPTURE_GAIN_LOG, +}; + +#define V4L2_CID_CAMERA_FACTORY_LSC_TABLE (V4L2_CID_PRIVATE_BASE+239) +#define V4L2_CID_CAMERA_FACTORY_LSC_REFERENCE (V4L2_CID_PRIVATE_BASE+240) + +#define V4L2_CID_CAMERA_FACTORY_PUNT_SHORT_SCAN_DATA (V4L2_CID_PRIVATE_BASE+241) +#define V4L2_CID_CAMERA_FACTORY_PUNT_LONG_SCAN_DATA (V4L2_CID_PRIVATE_BASE+242) + +#define V4L2_CID_CAMERA_PASM_MODE (V4L2_CID_PRIVATE_BASE + 243) +enum set_camera_mode_Cmd { + MODE_SMART_AUTO = 0, + MODE_PROGRAM, + MODE_A, + MODE_S, + MODE_M, + MODE_VIDEO, + MODE_BACKGROUND_BLUR, + MODE_HIGH_SPEED, + MODE_LIGHT_TRAIL_SHOT, + MODE_WATERFALL, + MODE_SILHOUETTE, + MODE_SUNSET, + MODE_CLOSE_UP, + MODE_FIREWORKS, + MODE_CROSS_FILTER, + MODE_BACKLIGHT, + MODE_BLUE_SKY, + MODE_NATURAL_GREEN, + MODE_BEST_GROUP_POSE, + MODE_FOOD, + MODE_START_FILTER, + MODE_MOVING_SHOT, +}; + +#define V4L2_CID_CAMERA_SHUTTER_SPEED (V4L2_CID_PRIVATE_BASE + 244) +#define V4L2_CID_CAMERA_F_NUMBER (V4L2_CID_PRIVATE_BASE + 245) + +#define V4L2_CID_CAMERA_IMAGE_STABILIZER (V4L2_CID_PRIVATE_BASE + 246) +enum set_Image_Stabilizer { + V4L2_IMAGE_STABILIZER_OFF = 0, + V4L2_IMAGE_STABILIZER_OIS = 1, + V4L2_IMAGE_STABILIZER_DUALIS = 2, +}; + +#define V4L2_CID_CAMERA_IS_OIS_MODE (V4L2_CID_PRIVATE_BASE + 247) +enum set_IS_OIS_mode { + V4L2_IS_OIS_NONE = 0, + V4L2_IS_OIS_MOVIE = 1, + V4L2_IS_OIS_STILL = 2, + V4L2_IS_OIS_MULTI = 3, + V4L2_IS_OIS_VSS = 4, +}; + +#define V4L2_CID_CAMERA_FACTORY_AE_TARGET (V4L2_CID_PRIVATE_BASE + 248) + +#define V4L2_CID_CAMERA_AV (V4L2_CID_PRIVATE_BASE + 249) +#define V4L2_CID_CAMERA_TV (V4L2_CID_PRIVATE_BASE + 250) +#define V4L2_CID_CAMERA_SV (V4L2_CID_PRIVATE_BASE + 251) +#define V4L2_CID_CAMERA_EV (V4L2_CID_PRIVATE_BASE + 252) + +#define V4L2_CID_CAMERA_SCENE_SUB_MODE (V4L2_CID_PRIVATE_BASE + 253) + +#define V4L2_CID_CAMERA_WB_CUSTOM_X (V4L2_CID_PRIVATE_BASE + 254) +#define V4L2_CID_CAMERA_WB_CUSTOM_Y (V4L2_CID_PRIVATE_BASE + 255) +#define V4L2_CID_CAMERA_WB_CUSTOM_VALUE (V4L2_CID_PRIVATE_BASE + 256) + +#define V4L2_CID_CAMERA_RED_EYE_FIX_RESULT (V4L2_CID_PRIVATE_BASE + 257) +#define V4L2_CID_CAMERA_FACTORY_FLASH (V4L2_CID_PRIVATE_BASE + 258) +enum set_Factory_Flash_Cmd { + FACTORY_FLASH_STROBE_CHECK_ON = 0, + FACTORY_FLASH_STROBE_CHECK_OFF = 1, + FACTORY_FLASH_CHARGE = 2, + FACTORY_FLASH_LOG = 3, + FACTORY_FLASH_CHARGE_END_CHECK = 4, + FACTORY_FLASH_STROBE_CHARGE_END_CHECK = 5, + FACTORY_FLASH_WB_LOG = 6, + FACTORY_ADJ_FLASH_WB_LOG = 7, + FACTORY_ADJ_FLASH_WB_END_CHECK = 8, +}; + +#define V4L2_CID_CAMERA_FACTORY_WB (V4L2_CID_PRIVATE_BASE + 259) +enum set_Factory_WB_Cmd { + FACTORY_WB_INDOOR_RUN = 0, + FACTORY_WB_INDOOR_END_CHECK = 1, + FACTORY_WB_OUTDOOR_RUN = 2, + FACTORY_WB_OUTDOOR_END_CHECK = 3, + FACTORY_WB_LOG = 4, +}; + +#define V4L2_CID_CAMERA_FACTORY_FLASH_RANGE_X (V4L2_CID_PRIVATE_BASE + 260) +#define V4L2_CID_CAMERA_FACTORY_FLASH_RANGE_Y (V4L2_CID_PRIVATE_BASE + 261) + +#define V4L2_CID_CAMERA_FACTORY_WB_IN_RG_VALUE (V4L2_CID_PRIVATE_BASE + 262) +#define V4L2_CID_CAMERA_FACTORY_WB_IN_BG_VALUE (V4L2_CID_PRIVATE_BASE + 263) +#define V4L2_CID_CAMERA_FACTORY_WB_OUT_RG_VALUE (V4L2_CID_PRIVATE_BASE + 264) +#define V4L2_CID_CAMERA_FACTORY_WB_OUT_BG_VALUE (V4L2_CID_PRIVATE_BASE + 265) + +#define V4L2_CID_CAMERA_FACTORY_AFLED_RANGE_DATA_START_X \ + (V4L2_CID_PRIVATE_BASE + 266) +#define V4L2_CID_CAMERA_FACTORY_AFLED_RANGE_DATA_END_X \ + (V4L2_CID_PRIVATE_BASE + 267) +#define V4L2_CID_CAMERA_FACTORY_AFLED_RANGE_DATA_START_Y \ + (V4L2_CID_PRIVATE_BASE + 268) +#define V4L2_CID_CAMERA_FACTORY_AFLED_RANGE_DATA_END_Y \ + (V4L2_CID_PRIVATE_BASE + 269) + +#define V4L2_CID_CAMERA_FACTORY_AF_LED_TIME (V4L2_CID_PRIVATE_BASE + 270) + +#define V4L2_CID_CAMERA_FACTORY_AF_DIFF_CHECK_MIN (V4L2_CID_PRIVATE_BASE + 271) +#define V4L2_CID_CAMERA_FACTORY_AF_DIFF_CHECK_MAX (V4L2_CID_PRIVATE_BASE + 272) + +#define V4L2_CID_CAMERA_FACTORY_DEFECTPIXEL (V4L2_CID_PRIVATE_BASE + 273) +enum set_Factory_DefectPixel_Cmd { + FACTORY_DEFECTPIXEL_SCENARIO_6 = 0, + FACTORY_DEFECTPIXEL_RUN, + FACTORY_DEFECTPIXEL_END_CHECK, + FACTORY_DEFECTPIXEL_LOG, + FACTORY_DEFECTPIXEL_CID_1, + FACTORY_DEFECTPIXEL_CID_2, + FACTORY_DEFECTPIXEL_CID_3, + FACTORY_DEFECTPIXEL_WRITE_BLACK, + FACTORY_DEFECTPIXEL_WRITE_WHITE, + FACTORY_DEFECTPIXEL_CID_WRITE, + FACTORY_DEFECTPIXEL_FLASH_MERGE, + FACTORY_DEFECTPIXEL_DOT_WRITE_CHECK, +}; + +#define V4L2_CID_CAMERA_FACTORY_DFPX_NLV_CAP (V4L2_CID_PRIVATE_BASE + 274) +#define V4L2_CID_CAMERA_FACTORY_DFPX_NLV_DR0 (V4L2_CID_PRIVATE_BASE + 275) +#define V4L2_CID_CAMERA_FACTORY_DFPX_NLV_DR1 (V4L2_CID_PRIVATE_BASE + 276) +#define V4L2_CID_CAMERA_FACTORY_DFPX_NLV_DR2 (V4L2_CID_PRIVATE_BASE + 277) +#define V4L2_CID_CAMERA_FACTORY_DFPX_NLV_DR_HS (V4L2_CID_PRIVATE_BASE + 278) + +#define V4L2_CID_CAMERA_FACTORY_AF_LED_LV_MIN (V4L2_CID_PRIVATE_BASE + 279) +#define V4L2_CID_CAMERA_FACTORY_AF_LED_LV_MAX (V4L2_CID_PRIVATE_BASE + 280) + +#define V4L2_CID_CAMERA_FACTORY_CAM_SYS_MODE (V4L2_CID_PRIVATE_BASE + 281) +enum set_Factory_Sysmode_Cmd { + FACTORY_SYSMODE_CAPTURE = 0, + FACTORY_SYSMODE_MONITOR = 1, + FACTORY_SYSMODE_PARAM = 2, +}; + +#define V4L2_CID_CAMERA_FACTORY_ISP_FW_CHECK (V4L2_CID_PRIVATE_BASE + 282) +#define V4L2_CID_CAMERA_FACTORY_OIS_VER_CHECK (V4L2_CID_PRIVATE_BASE + 283) + +#define V4L2_CID_CAMERA_SMART_SCENE_DETECT (V4L2_CID_PRIVATE_BASE+284) +enum set_smartscenedetect_mode { + SMART_SCENE_DETECT_OFF = 0, + SMART_SCENE_DETECT_ON = 1, +}; +#define V4L2_CID_CAMERA_SMART_MOVIE_RECORDING (V4L2_CID_PRIVATE_BASE+285) +#define V4L2_CID_CAMERA_SMART_AUTO_S1_PUSH (V4L2_CID_PRIVATE_BASE+286) + +#define V4L2_CID_CAMERA_FACTORY_WB_RANGE_FLASH_WRITE \ + (V4L2_CID_PRIVATE_BASE + 287) + +#define V4L2_CID_CAMERA_FACTORY_FLASH_CHR_CHK_TM \ + (V4L2_CID_PRIVATE_BASE + 288) + +#define V4L2_CID_CAMERA_EXIF_AV (V4L2_CID_PRIVATE_BASE + 289) +#define V4L2_CID_CAMERA_FACE_DETECT_NUMBER (V4L2_CID_PRIVATE_BASE+290) +#define V4L2_CID_CAMERA_EXIF_FL (V4L2_CID_PRIVATE_BASE + 291) + +#define V4L2_CID_CAMERA_SMART_ZOOM (V4L2_CID_PRIVATE_BASE + 292) +enum set_Smart_Zoom { + V4L2_SMART_ZOOM_OFF = 0, + V4L2_SMART_ZOOM_ON = 1, +}; + +#define V4L2_CID_CAMERA_CAF (V4L2_CID_PRIVATE_BASE + 293) + +#define V4L2_CID_CAMERA_FACTORY_LIVEVIEW_OFFSET_MARK \ + (V4L2_CID_PRIVATE_BASE + 294) +#define V4L2_CID_CAMERA_FACTORY_LIVEVIEW_OFFSET_VAL \ + (V4L2_CID_PRIVATE_BASE + 295) + +#define V4L2_CID_CAMERA_FACTORY_CAPTURE_GAIN_OFFSET_MARK \ + (V4L2_CID_PRIVATE_BASE + 296) +#define V4L2_CID_CAMERA_FACTORY_CAPTURE_GAIN_OFFSET_VAL \ + (V4L2_CID_PRIVATE_BASE + 297) + +#define V4L2_CID_CAMERA_FACTORY_WB_RANGE (V4L2_CID_PRIVATE_BASE + 298) + +#define V4L2_CID_CAMERA_LV (V4L2_CID_PRIVATE_BASE + 299) + +#define V4L2_CID_PHYSICAL_ROTATION (V4L2_CID_PRIVATE_BASE + 300) + +#define V4L2_CID_CAMERA_FOCUS_RANGE (V4L2_CID_PRIVATE_BASE + 301) +enum set_fouce_range { + V4L2_FOCUS_RANGE_AUTO = 0, + V4L2_FOCUS_RANGE_MACRO = 1, + V4L2_FOCUS_RANGE_AUTO_MACRO = 2, +}; + +#define V4L2_CID_CAMERA_TIME_INFO (V4L2_CID_PRIVATE_BASE + 302) + +#define V4L2_CID_CAMERA_AF_LED (V4L2_CID_PRIVATE_BASE + 303) +enum set_AF_LED { + V4L2_AF_LED_OFF = 0, + V4L2_AF_LED_ON = 1, +}; + +#define V4L2_CID_CAMERA_LENS_TIMER (V4L2_CID_PRIVATE_BASE + 304) + +#define V4L2_CID_CAMERA_FLASH_BATT_INFO (V4L2_CID_PRIVATE_BASE + 305) +enum set_FLASH_BATT_INFO { + V4L2_FLASH_NORMAL_BATT = 0, + V4L2_FLASH_LOW_BATT = 1, +}; + +#define V4L2_CID_CAMERA_STREAM_PART2 (V4L2_CID_PRIVATE_BASE + 306) + +#define V4L2_CID_CAMERA_WIDGET_MODE_LEVEL (V4L2_CID_PRIVATE_BASE+307) +enum v4l2_widget_mode_level { + V4L2_WIDGET_MODE_LEVEL_1 = 1, + V4L2_WIDGET_MODE_LEVEL_2 = 2, + V4L2_WIDGET_MODE_LEVEL_3 = 3, +}; + +#define V4L2_CID_CAMERA_SMART_READ1 (V4L2_CID_PRIVATE_BASE + 308) +#define V4L2_CID_CAMERA_SMART_READ2 (V4L2_CID_PRIVATE_BASE + 309) + +#define V4L2_CID_CAMERA_PREVIEW_WIDTH (V4L2_CID_PRIVATE_BASE + 310) +#define V4L2_CID_CAMERA_PREVIEW_HEIGHT (V4L2_CID_PRIVATE_BASE + 311) +#define V4L2_CID_CAMERA_PREVIEW_SIZE (V4L2_CID_PRIVATE_BASE + 312) + +#define V4L2_CID_CAMERA_WARNING_CONDITION (V4L2_CID_PRIVATE_BASE + 313) +#define V4L2_CID_CAMERA_EXIF_FL_35mm (V4L2_CID_PRIVATE_BASE + 314) + +#define V4L2_CID_CAMERA_LENS_STATUS (V4L2_CID_PRIVATE_BASE + 315) +#define V4L2_CID_CAMERA_HOLD_LENS (V4L2_CID_PRIVATE_BASE + 316) + /* Pixel format FOURCC depth Description */ enum v4l2_pix_format_mode { V4L2_PIX_FMT_MODE_PREVIEW, @@ -1225,6 +1818,97 @@ enum v4l2_pix_format_mode { V4L2_PIX_FMT_MODE_VT_NONMIRROR, }; +#define V4L2_CID_SET_CONTINUE_FPS (V4L2_CID_PRIVATE_BASE + 500) +#define V4L2_CID_CONTINUESHOT_PROC (V4L2_CID_PRIVATE_BASE + 501) +enum v4l2_continuecshot_proc_state { + V4L2_INT_STATE_FRAME_SYNC = 0, + V4L2_INT_STATE_CAPTURE_SYNC, + V4L2_INT_STATE_CONTINUE_CANCEL, + V4L2_INT_STATE_CONTINUE_END, + V4L2_INT_STATE_START_CAPTURE, +}; + +#define V4L2_CID_CAMERA_GET_MODE (V4L2_CID_PRIVATE_BASE + 502) + +#define V4L2_CID_CAMERA_FACTORY_SEND_SETTING \ + (V4L2_CID_PRIVATE_BASE + 503) +#define V4L2_CID_CAMERA_FACTORY_SEND_VALUE \ + (V4L2_CID_PRIVATE_BASE + 504) + +#define V4L2_CID_CAMERA_FACTORY_TILT_SCAN_MIN \ + (V4L2_CID_PRIVATE_BASE + 505) +#define V4L2_CID_CAMERA_FACTORY_TILT_SCAN_MAX \ + (V4L2_CID_PRIVATE_BASE + 506) +#define V4L2_CID_CAMERA_FACTORY_TILT_FIELD \ + (V4L2_CID_PRIVATE_BASE + 507) +#define V4L2_CID_CAMERA_FACTORY_TILT_AF_RANGE_MIN \ + (V4L2_CID_PRIVATE_BASE + 508) +#define V4L2_CID_CAMERA_FACTORY_TILT_AF_RANGE_MAX \ + (V4L2_CID_PRIVATE_BASE + 509) +#define V4L2_CID_CAMERA_FACTORY_TILT_DIFF_RANGE_MIN \ + (V4L2_CID_PRIVATE_BASE + 510) +#define V4L2_CID_CAMERA_FACTORY_TILT_DIFF_RANGE_MAX \ + (V4L2_CID_PRIVATE_BASE + 511) + +#define V4L2_CID_CAMERA_FACTORY_IR_R_GAIN_MIN \ + (V4L2_CID_PRIVATE_BASE + 512) +#define V4L2_CID_CAMERA_FACTORY_IR_R_GAIN_MAX \ + (V4L2_CID_PRIVATE_BASE + 513) +#define V4L2_CID_CAMERA_FACTORY_IR_B_GAIN_MIN \ + (V4L2_CID_PRIVATE_BASE + 514) +#define V4L2_CID_CAMERA_FACTORY_IR_B_GAIN_MAX \ + (V4L2_CID_PRIVATE_BASE + 515) + +#define V4L2_CID_CAMERA_FACTORY_FLASH_MAN_CHARGE \ + (V4L2_CID_PRIVATE_BASE + 516) +#define V4L2_CID_CAMERA_FACTORY_FLASH_MAN_EN \ + (V4L2_CID_PRIVATE_BASE + 517) + +#define V4L2_CID_CAMERA_FACTORY_SEND_WORD_VALUE \ + (V4L2_CID_PRIVATE_BASE + 518) +#define V4L2_CID_CAMERA_FACTORY_SEND_LONG_VALUE \ + (V4L2_CID_PRIVATE_BASE + 519) + +#define V4L2_CID_CAMERA_FACTORY_DFPX_NLV_DR1_HD \ + (V4L2_CID_PRIVATE_BASE + 520) + +#define V4L2_CID_BURSTSHOT_PROC (V4L2_CID_PRIVATE_BASE + 521) +enum v4l2_burst_proc_state { + V4L2_INT_STATE_BURST_START = 0, + V4L2_INT_STATE_BURST_SYNC, + V4L2_INT_STATE_BURST_STOP, +}; + +#define V4L2_CID_CAMERA_FACTORY_TILT \ + (V4L2_CID_PRIVATE_BASE + 522) +enum set_Factory_Tilt { + FACTORY_TILT_ONE_SCRIPT_RUN = 0, + FACTORY_TILT_ONE_SCRIPT_DISP1, + FACTORY_TILT_ONE_SCRIPT_DISP2, + FACTORY_TILT_ONE_SCRIPT_DISP3, + FACTORY_TILT_ONE_SCRIPT_DISP4, + FACTORY_TILT_ONE_SCRIPT_DISP5, +}; + +#define V4L2_CID_CAMERA_FACTORY_IR_CHECK \ + (V4L2_CID_PRIVATE_BASE + 523) +enum set_Factory_IR_Check { + FACTORY_IR_CHECK_LOG = 0, +}; + +#define V4L2_CID_BURSTSHOT_SET_POSTVIEW_SIZE (V4L2_CID_PRIVATE_BASE + 524) + +#define V4L2_CID_BURSTSHOT_SET_SNAPSHOT_SIZE (V4L2_CID_PRIVATE_BASE + 525) + +/* ISP DEBUG CODE */ +#define V4L2_CID_ISP_DEBUG_READ (V4L2_CID_FIMC_IS_ISP_DBG_BASE + 1) +#define V4L2_CID_ISP_DEBUG_WRITE (V4L2_CID_FIMC_IS_ISP_DBG_BASE + 2) +#define V4L2_CID_ISP_DEBUG_READ_MEM (V4L2_CID_FIMC_IS_ISP_DBG_BASE + 3) +#define V4L2_CID_ISP_DEBUG_WRITE_MEM (V4L2_CID_FIMC_IS_ISP_DBG_BASE + 4) +#define V4L2_CID_ISP_DEBUG_READ_FILE (V4L2_CID_FIMC_IS_ISP_DBG_BASE + 5) +#define V4L2_CID_ISP_DEBUG_WRITE_FILE (V4L2_CID_FIMC_IS_ISP_DBG_BASE + 6) +#define V4L2_CID_ISP_DEBUG_LOGV (V4L2_CID_FIMC_IS_ISP_DBG_BASE + 7) + /* 12 Y/CbCr 4:2:0 64x32 macroblocks */ #define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2') #define V4L2_PIX_FMT_NV21T v4l2_fourcc('T', 'V', '2', '1') -- cgit v1.1 From 918238b84247c5e1eb4e1e521b762167647af27b Mon Sep 17 00:00:00 2001 From: XpLoDWilD Date: Fri, 6 Sep 2013 11:45:44 +0200 Subject: camera: Fix camera crashing when bashing shutter Prevents the picture thread from being restarted or freezing when it is already started, or when auto-focus is being done. Prevents gallery crash. Change-Id: Ib540f2a47423778b45dfc8df440e33b2ac254ae8 --- camera/exynos_camera.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index e002231..66c9ce3 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -3002,7 +3002,7 @@ int exynos_camera_picture_thread_start(struct exynos_camera *exynos_camera) if (exynos_camera->picture_thread_enabled) { ALOGE("Picture thread was already started!"); - return -1; + return 0; } if (exynos_camera->camera_picture_format) @@ -4034,6 +4034,12 @@ int exynos_camera_take_picture(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; + if (exynos_camera->picture_thread_running + || exynos_camera->auto_focus_thread_enabled) + { + return 0; + } + exynos_camera->callback_lock = 1; rc = exynos_camera_picture_thread_start(exynos_camera); exynos_camera->callback_lock = 0; -- cgit v1.1 From 15ca29a0f9d92d6f6e942b3a1bdb49de7ec84320 Mon Sep 17 00:00:00 2001 From: Javier Ferrer Date: Mon, 9 Sep 2013 13:53:49 +0200 Subject: camera: auto antibanding Add 60 Hz and auto antibanding, with "auto" as default. Change-Id: I460524f70afe0ac0aa0bf4c0be9a81acc4dbbb94 --- camera/exynos_camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 66c9ce3..2c3e9dd 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -124,8 +124,8 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .whitebalance = "auto", .whitebalance_values = "auto,incandescent,fluorescent,daylight,cloudy-daylight", - .antibanding = "50hz", - .antibanding_values = "50hz,off", + .antibanding = "auto", + .antibanding_values = "off,auto,50hz,60hz", .scene_mode = "auto", .scene_mode_values = "auto,portrait,landscape,night,beach,snow,sunset,fireworks,sports,party,candlelight,dusk-dawn,fall-color,text,back-light", -- cgit v1.1 From 80d632788089b29b4578e29e03e34c0696b60768 Mon Sep 17 00:00:00 2001 From: sbrissen Date: Tue, 10 Sep 2013 07:35:49 -0400 Subject: smdk4412-common: remove i925 from camera Android.mk i925 note 10.1 lte uses a different back cam sensor. Change-Id: Ic03a9b3ef34c9325523a685f2e23cb1da18b31b7 --- camera/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'camera') diff --git a/camera/Android.mk b/camera/Android.mk index dc48ea1..0f54340 100644 --- a/camera/Android.mk +++ b/camera/Android.mk @@ -15,7 +15,7 @@ # along with this program. If not, see . # -ifneq ($(filter i9300 i9305 n7100 t0lte t0lteatt t0ltetmo i605 l900 r950 i925,$(TARGET_DEVICE)),) +ifneq ($(filter i9300 i9305 n7100 t0lte t0lteatt t0ltetmo i605 l900 r950,$(TARGET_DEVICE)),) LOCAL_PATH := $(call my-dir) -- cgit v1.1 From 30219ee2b54042acc48d379c5674cb71d5c2d192 Mon Sep 17 00:00:00 2001 From: Javier Ferrer Date: Mon, 9 Sep 2013 14:01:10 +0200 Subject: camera: improve taking shot with focal on low light conditions I have taken borrowed the scene mode "high-sensitivity" for this purpose. Maybe can we find a better scene mode for it in the future. Change-Id: I3e7379a7b8e8e0f982f2dc125174dd30617d39ed --- camera/exynos_camera.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 2c3e9dd..a6c6d19 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -128,7 +128,7 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .antibanding_values = "off,auto,50hz,60hz", .scene_mode = "auto", - .scene_mode_values = "auto,portrait,landscape,night,beach,snow,sunset,fireworks,sports,party,candlelight,dusk-dawn,fall-color,text,back-light", + .scene_mode_values = "auto,portrait,landscape,night,beach,snow,sunset,fireworks,sports,party,candlelight,dusk-dawn,fall-color,text,back-light,high-sensitivity", .effect = "none", .effect_values = "none,mono,negative,sepia,solarize,posterize,washed,vintage-warm,vintage-cold,point-blue,point-red-yellow,point-green", @@ -987,6 +987,8 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) scene_mode = SCENE_MODE_BACK_LIGHT; else if (strcmp(scene_mode_string, "text") == 0) scene_mode = SCENE_MODE_TEXT; + else if (strcmp(scene_mode_string, "high-sensitivity") == 0) + scene_mode = SCENE_MODE_LOW_LIGHT; else scene_mode = SCENE_MODE_NONE; -- cgit v1.1 From 98d50c6ba12aab110fddb9bbcc97bc3d2d1dd34b Mon Sep 17 00:00:00 2001 From: Javier Ferrer Date: Tue, 17 Sep 2013 23:49:39 +0200 Subject: camera: add image-stabilization parameter Focal will find it and will enable it before taking shot, disabling it after the shot is taken. Change-Id: I476f2d13e6662f211d395d432c855d70ba53d61f --- camera/exynos_camera.c | 32 ++++++++++++++++++++++++++++++++ camera/exynos_camera.h | 4 ++++ 2 files changed, 36 insertions(+) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index a6c6d19..0c840dd 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -135,6 +135,9 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .iso = "auto", .iso_values = "auto,ISO100,ISO200,ISO400,ISO800", + + .image_stabilization = "off", + .image_stabilization_values = "on,off", }, .mbus_resolutions = NULL, .mbus_resolutions_count = 0, @@ -210,6 +213,9 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .iso = "auto", .iso_values = "auto", + + .image_stabilization = "off", + .image_stabilization_values = "off", }, .mbus_resolutions = (struct exynos_camera_mbus_resolution *) &exynos_camera_mbus_resolutions_s5k6a3_smdk4x12, .mbus_resolutions_count = 8, @@ -523,6 +529,13 @@ int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id) exynos_param_string_set(exynos_camera, "iso-values", exynos_camera->config->presets[id].params.iso_values); + // Image stabilization (Anti-shake) + + exynos_param_string_set(exynos_camera, "image-stabilization", + exynos_camera->config->presets[id].params.image_stabilization); + exynos_param_string_set(exynos_camera, "image-stabilization-values", + exynos_camera->config->presets[id].params.image_stabilization_values); + // Camera exynos_param_float_set(exynos_camera, "focal-length", @@ -604,6 +617,9 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) char *iso_string; int iso; + char *image_stabilization_string; + int image_stabilization; + int w, h; char *k; int rc; @@ -1072,6 +1088,22 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) } } + // Image stabilization (Anti-shake) + + image_stabilization_string = exynos_param_string_get(exynos_camera, "image-stabilization"); + if (image_stabilization_string != NULL) { + if (strcmp(image_stabilization_string, "on") == 0) + image_stabilization = ANTI_SHAKE_STILL_ON; + else + image_stabilization = ANTI_SHAKE_OFF; + + if (image_stabilization != exynos_camera->image_stabilization || force) { + exynos_camera->image_stabilization = image_stabilization; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_ANTI_SHAKE, image_stabilization); + if (rc < 0) + ALOGE("%s: Unable to set image-stabilization", __func__); + } + } ALOGD("%s: Preview size: %dx%d, picture size: %dx%d, recording size: %dx%d", __func__, preview_width, preview_height, picture_width, picture_height, recording_width, recording_height); return 0; diff --git a/camera/exynos_camera.h b/camera/exynos_camera.h index 9db8dfb..547b90f 100644 --- a/camera/exynos_camera.h +++ b/camera/exynos_camera.h @@ -172,6 +172,9 @@ struct exynos_camera_params { char *iso; char *iso_values; + + char *image_stabilization; // Anti-shake + char *image_stabilization_values; }; struct exynos_camera_preset { @@ -417,6 +420,7 @@ struct exynos_camera { int effect; int iso; int metering; + int image_stabilization; }; struct exynos_camera_addrs { -- cgit v1.1 From 7607d3d42484c80b5689e7cb0362bfbe40daf263 Mon Sep 17 00:00:00 2001 From: Javier Ferrer Date: Sat, 5 Oct 2013 16:29:09 +0200 Subject: camera: Add AWB and AE lock Change-Id: I5ac305414a4d1af61fe4434fc89e794121196bdf --- camera/exynos_camera.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ camera/exynos_camera.h | 8 +++++++ 2 files changed, 72 insertions(+) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 0c840dd..3abba99 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -113,6 +113,12 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .zoom = 0, .max_zoom = 30, + .auto_exposure_lock_supported = 1, + .auto_exposure_lock = 0, + + .auto_white_balance_lock_supported = 1, + .auto_white_balance_lock = 0, + .flash_mode = "off", .flash_mode_values = "off,auto,on,torch", @@ -191,6 +197,12 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .zoom_supported = 0, + .auto_exposure_lock_supported = 0, + .auto_exposure_lock = 0, + + .auto_white_balance_lock_supported = 0, + .auto_white_balance_lock = 0, + .flash_mode = NULL, .flash_mode_values = NULL, @@ -476,6 +488,26 @@ int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id) exynos_param_string_set(exynos_camera, "zoom-supported", "false"); } + // AE lock + if (exynos_camera->config->presets[id].params.auto_exposure_lock_supported == 1) { + exynos_param_string_set(exynos_camera, "auto-exposure-lock-supported", "true"); + + if (exynos_camera->config->presets[id].params.auto_exposure_lock) + exynos_param_string_set(exynos_camera, "auto-exposure-lock", "true"); + else + exynos_param_string_set(exynos_camera, "auto-exposure-lock", "false"); + } + + // AWB lock + if (exynos_camera->config->presets[id].params.auto_white_balance_lock_supported == 1) { + exynos_param_string_set(exynos_camera, "auto-whitebalance-lock-supported", "true"); + + if (exynos_camera->config->presets[id].params.auto_white_balance_lock) + exynos_param_string_set(exynos_camera, "auto-whitebalance-lock", "true"); + else + exynos_param_string_set(exynos_camera, "auto-whitebalance-lock", "false"); + } + // Flash exynos_param_string_set(exynos_camera, "flash-mode", @@ -595,6 +627,13 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) char *zoom_supported_string; int zoom, max_zoom; + char *ae_lock_supported_string; + int ae_lock = 0; + + char *awb_lock_supported_string; + int awb_lock = 0; + int aeawb = 0; + char *flash_mode_string; int flash_mode; @@ -884,6 +923,31 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) } + // AE lock + + ae_lock_supported_string = exynos_param_string_get(exynos_camera, "auto-exposure-lock-supported"); + if (ae_lock_supported_string != NULL && strcmp(ae_lock_supported_string, "true") == 0) { + ae_lock = strcmp(exynos_param_string_get(exynos_camera, "auto-exposure-lock"), "true") ? 1 : 0; + } + + // AWB lock + + awb_lock_supported_string = exynos_param_string_get(exynos_camera, "auto-whitebalance-lock-supported"); + if (awb_lock_supported_string != NULL && strcmp(awb_lock_supported_string, "true") == 0) { + awb_lock = strcmp(exynos_param_string_get(exynos_camera, "auto-whitebalance-lock"), "true") ? 1 : 0; + } + + if ( (ae_lock != exynos_camera->ae_lock) || (awb_lock != exynos_camera->awb_lock) || force ) { + aeawb = (ae_lock ? 0x1 : 0x0) | (awb_lock ? 0x2 : 0x0); + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, aeawb); + if (rc < 0) + ALOGE("%s:Unable to set AEAWB lock", __func__); + else { + exynos_camera->ae_lock = ae_lock; + exynos_camera->awb_lock = awb_lock; + } + } + // Flash flash_mode_string = exynos_param_string_get(exynos_camera, "flash-mode"); diff --git a/camera/exynos_camera.h b/camera/exynos_camera.h index 547b90f..8c0977a 100644 --- a/camera/exynos_camera.h +++ b/camera/exynos_camera.h @@ -150,6 +150,12 @@ struct exynos_camera_params { int zoom; int max_zoom; + int auto_exposure_lock_supported; + int auto_exposure_lock; + + int auto_white_balance_lock_supported; + int auto_white_balance_lock; + char *flash_mode; char *flash_mode_values; @@ -412,6 +418,8 @@ struct exynos_camera { int focus_x; int focus_y; int zoom; + int ae_lock; + int awb_lock; int flash_mode; int exposure_compensation; int whitebalance; -- cgit v1.1 From ec1a0fa790023e4511bf694891b7e12a6393ca69 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Tue, 8 Oct 2013 17:48:25 +0200 Subject: Revert "camera: Add AWB and AE lock" This reverts commit 7607d3d42484c80b5689e7cb0362bfbe40daf263. Change-Id: I6f222c23cff1526ec6c9d0b0ae874e5652d861cb --- camera/exynos_camera.c | 64 -------------------------------------------------- camera/exynos_camera.h | 8 ------- 2 files changed, 72 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 3abba99..0c840dd 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -113,12 +113,6 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .zoom = 0, .max_zoom = 30, - .auto_exposure_lock_supported = 1, - .auto_exposure_lock = 0, - - .auto_white_balance_lock_supported = 1, - .auto_white_balance_lock = 0, - .flash_mode = "off", .flash_mode_values = "off,auto,on,torch", @@ -197,12 +191,6 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .zoom_supported = 0, - .auto_exposure_lock_supported = 0, - .auto_exposure_lock = 0, - - .auto_white_balance_lock_supported = 0, - .auto_white_balance_lock = 0, - .flash_mode = NULL, .flash_mode_values = NULL, @@ -488,26 +476,6 @@ int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id) exynos_param_string_set(exynos_camera, "zoom-supported", "false"); } - // AE lock - if (exynos_camera->config->presets[id].params.auto_exposure_lock_supported == 1) { - exynos_param_string_set(exynos_camera, "auto-exposure-lock-supported", "true"); - - if (exynos_camera->config->presets[id].params.auto_exposure_lock) - exynos_param_string_set(exynos_camera, "auto-exposure-lock", "true"); - else - exynos_param_string_set(exynos_camera, "auto-exposure-lock", "false"); - } - - // AWB lock - if (exynos_camera->config->presets[id].params.auto_white_balance_lock_supported == 1) { - exynos_param_string_set(exynos_camera, "auto-whitebalance-lock-supported", "true"); - - if (exynos_camera->config->presets[id].params.auto_white_balance_lock) - exynos_param_string_set(exynos_camera, "auto-whitebalance-lock", "true"); - else - exynos_param_string_set(exynos_camera, "auto-whitebalance-lock", "false"); - } - // Flash exynos_param_string_set(exynos_camera, "flash-mode", @@ -627,13 +595,6 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) char *zoom_supported_string; int zoom, max_zoom; - char *ae_lock_supported_string; - int ae_lock = 0; - - char *awb_lock_supported_string; - int awb_lock = 0; - int aeawb = 0; - char *flash_mode_string; int flash_mode; @@ -923,31 +884,6 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) } - // AE lock - - ae_lock_supported_string = exynos_param_string_get(exynos_camera, "auto-exposure-lock-supported"); - if (ae_lock_supported_string != NULL && strcmp(ae_lock_supported_string, "true") == 0) { - ae_lock = strcmp(exynos_param_string_get(exynos_camera, "auto-exposure-lock"), "true") ? 1 : 0; - } - - // AWB lock - - awb_lock_supported_string = exynos_param_string_get(exynos_camera, "auto-whitebalance-lock-supported"); - if (awb_lock_supported_string != NULL && strcmp(awb_lock_supported_string, "true") == 0) { - awb_lock = strcmp(exynos_param_string_get(exynos_camera, "auto-whitebalance-lock"), "true") ? 1 : 0; - } - - if ( (ae_lock != exynos_camera->ae_lock) || (awb_lock != exynos_camera->awb_lock) || force ) { - aeawb = (ae_lock ? 0x1 : 0x0) | (awb_lock ? 0x2 : 0x0); - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, aeawb); - if (rc < 0) - ALOGE("%s:Unable to set AEAWB lock", __func__); - else { - exynos_camera->ae_lock = ae_lock; - exynos_camera->awb_lock = awb_lock; - } - } - // Flash flash_mode_string = exynos_param_string_get(exynos_camera, "flash-mode"); diff --git a/camera/exynos_camera.h b/camera/exynos_camera.h index 8c0977a..547b90f 100644 --- a/camera/exynos_camera.h +++ b/camera/exynos_camera.h @@ -150,12 +150,6 @@ struct exynos_camera_params { int zoom; int max_zoom; - int auto_exposure_lock_supported; - int auto_exposure_lock; - - int auto_white_balance_lock_supported; - int auto_white_balance_lock; - char *flash_mode; char *flash_mode_values; @@ -418,8 +412,6 @@ struct exynos_camera { int focus_x; int focus_y; int zoom; - int ae_lock; - int awb_lock; int flash_mode; int exposure_compensation; int whitebalance; -- cgit v1.1 From 199a88beb4c9dc88d11176e6db6e0acdabcc50c7 Mon Sep 17 00:00:00 2001 From: Javier Ferrer Date: Tue, 8 Oct 2013 17:47:29 +0200 Subject: camera: Add AWB and AE lock Signed-off-by: Paul Kocialkowski Change-Id: Idea7b7af7eb7adb4e02e6f527dda96e78f3e0f16 --- camera/exynos_camera.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ camera/exynos_camera.h | 8 ++++++ 2 files changed, 78 insertions(+) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 0c840dd..ef9ee6b 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -113,6 +113,12 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .zoom = 0, .max_zoom = 30, + .auto_exposure_lock_supported = 1, + .auto_exposure_lock = 0, + + .auto_white_balance_lock_supported = 1, + .auto_white_balance_lock = 0, + .flash_mode = "off", .flash_mode_values = "off,auto,on,torch", @@ -191,6 +197,12 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .zoom_supported = 0, + .auto_exposure_lock_supported = 0, + .auto_exposure_lock = 0, + + .auto_white_balance_lock_supported = 0, + .auto_white_balance_lock = 0, + .flash_mode = NULL, .flash_mode_values = NULL, @@ -476,6 +488,28 @@ int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id) exynos_param_string_set(exynos_camera, "zoom-supported", "false"); } + // AE lock + + if (exynos_camera->config->presets[id].params.auto_exposure_lock_supported == 1) { + exynos_param_string_set(exynos_camera, "auto-exposure-lock-supported", "true"); + + if (exynos_camera->config->presets[id].params.auto_exposure_lock) + exynos_param_string_set(exynos_camera, "auto-exposure-lock", "true"); + else + exynos_param_string_set(exynos_camera, "auto-exposure-lock", "false"); + } + + // AWB lock + + if (exynos_camera->config->presets[id].params.auto_white_balance_lock_supported == 1) { + exynos_param_string_set(exynos_camera, "auto-whitebalance-lock-supported", "true"); + + if (exynos_camera->config->presets[id].params.auto_white_balance_lock) + exynos_param_string_set(exynos_camera, "auto-whitebalance-lock", "true"); + else + exynos_param_string_set(exynos_camera, "auto-whitebalance-lock", "false"); + } + // Flash exynos_param_string_set(exynos_camera, "flash-mode", @@ -595,6 +629,15 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) char *zoom_supported_string; int zoom, max_zoom; + char *ae_lock_supported_string; + char *ae_lock_string; + int ae_lock = 0; + + char *awb_lock_supported_string; + char *awb_lock_string; + int awb_lock = 0; + int aeawb = 0; + char *flash_mode_string; int flash_mode; @@ -884,6 +927,33 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) } + // AE lock + + ae_lock_supported_string = exynos_param_string_get(exynos_camera, "auto-exposure-lock-supported"); + ae_lock_string = exynos_param_string_get(exynos_camera, "auto-exposure-lock"); + if (ae_lock_supported_string != NULL && ae_lock_string != NULL && strcmp(ae_lock_supported_string, "true") == 0 && strcmp(ae_lock_string, "true") == 0) + ae_lock = 1; + else + ae_lock = 0; + + // AWB lock + + awb_lock_supported_string = exynos_param_string_get(exynos_camera, "auto-whitebalance-lock-supported"); + awb_lock_string = exynos_param_string_get(exynos_camera, "auto-whitebalance-lock"); + if (awb_lock_supported_string != NULL && awb_lock_string != NULL && strcmp(awb_lock_supported_string, "true") == 0 && strcmp(awb_lock_string, "true") == 0) + awb_lock = 1; + else + awb_lock = 0; + + if (ae_lock != exynos_camera->ae_lock || awb_lock != exynos_camera->awb_lock || force) { + exynos_camera->ae_lock = ae_lock; + exynos_camera->awb_lock = awb_lock; + aeawb = (ae_lock ? 0x1 : 0x0) | (awb_lock ? 0x2 : 0x0); + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, aeawb); + if (rc < 0) + ALOGE("%s: Unable to set AEAWB lock", __func__); + } + // Flash flash_mode_string = exynos_param_string_get(exynos_camera, "flash-mode"); diff --git a/camera/exynos_camera.h b/camera/exynos_camera.h index 547b90f..8c0977a 100644 --- a/camera/exynos_camera.h +++ b/camera/exynos_camera.h @@ -150,6 +150,12 @@ struct exynos_camera_params { int zoom; int max_zoom; + int auto_exposure_lock_supported; + int auto_exposure_lock; + + int auto_white_balance_lock_supported; + int auto_white_balance_lock; + char *flash_mode; char *flash_mode_values; @@ -412,6 +418,8 @@ struct exynos_camera { int focus_x; int focus_y; int zoom; + int ae_lock; + int awb_lock; int flash_mode; int exposure_compensation; int whitebalance; -- cgit v1.1 From 39a1ebdfea1a37d01f9c382b98cfd48a96e98184 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Tue, 8 Oct 2013 17:52:26 +0200 Subject: camera: Wait for continous focus to complete before taking a picture Signed-off-by: Paul Kocialkowski Change-Id: I2aef0e3e413c9a8708fe1c87860beb287c844a1c --- camera/exynos_camera.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index ef9ee6b..0bd7a1e 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -2603,6 +2603,11 @@ int exynos_camera_picture_callback(struct exynos_camera *exynos_camera, pthread_mutex_lock(&exynos_camera->picture_mutex); if (!exynos_camera->picture_enabled && !exynos_camera->camera_fimc_is) { + if (exynos_camera->focus_mode == FOCUS_MODE_CONTINOUS_PICTURE && exynos_camera->capture_auto_focus_result == CAMERA_AF_STATUS_IN_PROGRESS) { + pthread_mutex_unlock(&exynos_camera->picture_mutex); + return 0; + } + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_CAPTURE, 0); if (rc < 0) { ALOGE("%s: Unable to set capture", __func__); -- cgit v1.1 From b931db8c307db6b94fcc52ea3ff9adda5b8d9de4 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 29 Oct 2013 17:06:21 +0000 Subject: camera: Block out endlessly looping focus clause capture_auto_focus_result isn't updated from any realtime focus callback, so waiting for it to change in order to complete the capture introduces delay, and in some cases an infinite loop. Remove the focus state verification, at least until such a callback can be put in place. Change-Id: If4c6815563cb63009e717ee65a0a8fb816cc813e --- camera/exynos_camera.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 0bd7a1e..ed618e3 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -2603,10 +2603,12 @@ int exynos_camera_picture_callback(struct exynos_camera *exynos_camera, pthread_mutex_lock(&exynos_camera->picture_mutex); if (!exynos_camera->picture_enabled && !exynos_camera->camera_fimc_is) { +#if 0 if (exynos_camera->focus_mode == FOCUS_MODE_CONTINOUS_PICTURE && exynos_camera->capture_auto_focus_result == CAMERA_AF_STATUS_IN_PROGRESS) { pthread_mutex_unlock(&exynos_camera->picture_mutex); return 0; } +#endif rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_CAPTURE, 0); if (rc < 0) { -- cgit v1.1 From 78012f3513540230a4617d95b81114218593f921 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Wed, 30 Oct 2013 15:28:21 +0000 Subject: camera: Fix android.hardware.cts.CameraTest#testFaceDetection junit.framework.AssertionFailedError: Should throw an exception if face detection is not supported. Change-Id: I2cf8d26e94c0943838db7300ab05b4c0172b15c1 --- camera/exynos_camera.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index ed618e3..f6817a3 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -4238,6 +4238,13 @@ int exynos_camera_send_command(struct camera_device *dev, int32_t cmd, int32_t arg1, int32_t arg2) { ALOGD("%s(%p, %d, %d, %d)", __func__, dev, cmd, arg1, arg2); + switch (cmd) { + case CAMERA_CMD_START_FACE_DETECTION: + return -EINVAL; + break; + default: + break; + } return 0; } -- cgit v1.1 From 51420db3f615a78736153165a4439d1f099e15b7 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Wed, 30 Oct 2013 16:47:04 +0000 Subject: camera: Fix various focus-related errors * Validate that the focus region is within legal boundaries * Reset the region to sane values if bad ones are given * Set a default empty region * If auto focus exists, it must be the default Fixes android.hardware.cts.CameraTest#testFocusAreas and android.hardware.cts.CameraTest#testParameters Change-Id: I3aafcccc2c6081ba44edb3283a850c55178fa90a --- camera/exynos_camera.c | 43 ++++++++++++++++++++++++++++++++++++------- camera/exynos_camera.h | 1 + 2 files changed, 37 insertions(+), 7 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index f6817a3..b19ac6d 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -101,10 +101,10 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .recording_size_values = "1280x720,1920x1080,720x480,640x480,352x288,320x240,176x144", .recording_format = "yuv420sp", - .focus_mode = "continuous-picture", + .focus_mode = "auto", .focus_mode_values = "auto,infinity,macro,fixed,continuous-picture,continuous-video", .focus_distances = "0.15,1.20,Infinity", - .focus_areas = NULL, + .focus_areas = "(0,0,0,0,0)", .max_num_focus_areas = 1, .zoom_supported = 1, @@ -466,6 +466,8 @@ int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id) if (exynos_camera->config->presets[id].params.max_num_focus_areas > 0) { exynos_param_string_set(exynos_camera, "focus-areas", exynos_camera->config->presets[id].params.focus_areas); + sprintf(exynos_camera->raw_focus_areas,"%s", + exynos_camera->config->presets[id].params.focus_areas); exynos_param_int_set(exynos_camera, "max-num-focus-areas", exynos_camera->config->presets[id].params.max_num_focus_areas); } @@ -588,6 +590,28 @@ int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id) return 0; } +static int validate_focus_areas(int l, int t, int r, int b, int w) { + if (!(l || r || t || b || w)) { + // All zeros is a valid area + return 0; + } + + // If existing, a focus area must be contained between -1000 and 1000, + // on both dimensions + if (l < -1000 || t < -1000 || r > 1000 || b > 1000) { + return -EINVAL; + } + // No superimposed or reverted edges + if (l >= r || t >= b) { + return -EINVAL; + } + // If there's an area defined, weight must be positive and up to 1000 + if ((l !=0 || r !=0) && (w < 1 || w > 1000)) { + return -EINVAL; + } + return 0; +} + int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) { char *recording_hint_string; @@ -622,7 +646,7 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) char *focus_mode_string; int focus_mode = 0; char *focus_areas_string; - int focus_left, focus_top, focus_right, focus_bottom, focus_weigth; + int focus_left, focus_top, focus_right, focus_bottom, focus_weight; int focus_x; int focus_y; @@ -852,13 +876,18 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) focus_areas_string = exynos_param_string_get(exynos_camera, "focus-areas"); if (focus_areas_string != NULL) { - focus_left = focus_top = focus_right = focus_bottom = focus_weigth = 0; + focus_left = focus_top = focus_right = focus_bottom = focus_weight = 0; rc = sscanf(focus_areas_string, "(%d,%d,%d,%d,%d)", - &focus_left, &focus_top, &focus_right, &focus_bottom, &focus_weigth); + &focus_left, &focus_top, &focus_right, &focus_bottom, &focus_weight); if (rc != 5) { ALOGE("%s: Unable to scan focus areas", __func__); - } else if (focus_left != 0 && focus_top != 0 && focus_right != 0 && focus_bottom != 0) { + } else if (validate_focus_areas(focus_left, focus_top, focus_right, focus_bottom, focus_weight) != 0 || strstr(focus_areas_string, "),(")) { + exynos_param_string_set(exynos_camera, "focus-areas", + exynos_camera->raw_focus_areas); + return -EINVAL; + } else if ((focus_left != 0 || focus_right != 0) && (focus_top != 0 || focus_bottom != 0)) { + sprintf(exynos_camera->raw_focus_areas,"%s",focus_areas_string); focus_x = (((focus_left + focus_right) / 2) + 1000) * preview_width / 2000; focus_y = (((focus_top + focus_bottom) / 2) + 1000) * preview_height / 2000; @@ -3750,7 +3779,7 @@ int exynos_camera_auto_focus_thread_start(struct exynos_camera *exynos_camera) if (exynos_camera->auto_focus_thread_enabled) { ALOGE("Auto-focus thread was already started!"); - return -1; + return 0; } pthread_mutex_init(&exynos_camera->auto_focus_mutex, NULL); diff --git a/camera/exynos_camera.h b/camera/exynos_camera.h index 8c0977a..9e3d4f8 100644 --- a/camera/exynos_camera.h +++ b/camera/exynos_camera.h @@ -429,6 +429,7 @@ struct exynos_camera { int iso; int metering; int image_stabilization; + char raw_focus_areas[PAGE_SIZE]; }; struct exynos_camera_addrs { -- cgit v1.1 From 2d2391e849650ecab9dc3344b58b649c201293b2 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Wed, 30 Oct 2013 17:23:03 +0000 Subject: camera: Fix invalid parameter returns The camera API expects invalid parameters not to return silently; They should throw an exception, and set the bad parameter(s) back to the last known good value. Fixes android.hardware.cts.CameraTest#testImmediateZoom and android.hardware.cts.CameraTest#testInvalidParameters Change-Id: I6556369322b7560b0bb35fca57366b42579effbd --- camera/exynos_camera.c | 26 ++++++++++++++++++++++---- camera/exynos_camera.h | 2 ++ 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index b19ac6d..7b2875b 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -700,6 +700,13 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) if (preview_size_string != NULL) { sscanf(preview_size_string, "%dx%d", &preview_width, &preview_height); + if (preview_width < 0 && preview_height < 0) { + char reset_preview[128]; + sprintf(reset_preview, "%dx%d", exynos_camera->preview_width, exynos_camera->preview_height); + exynos_param_string_set(exynos_camera, "preview-size", + reset_preview); + return -EINVAL; + } if (preview_width != 0 && preview_width != exynos_camera->preview_width) exynos_camera->preview_width = preview_width; if (preview_height != 0 && preview_height != exynos_camera->preview_height) @@ -928,8 +935,11 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) focus_mode = FOCUS_MODE_CONTINOUS_VIDEO; else if (strcmp(focus_mode_string, "continuous-picture") == 0) focus_mode = FOCUS_MODE_CONTINOUS_PICTURE; - else - focus_mode = FOCUS_MODE_AUTO; + else { + exynos_param_string_set(exynos_camera, "focus-mode", + exynos_camera->raw_focus_mode); + return -EINVAL; + } } if (focus_mode != exynos_camera->focus_mode || force) { @@ -939,6 +949,7 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) } exynos_camera->focus_mode = focus_mode; + sprintf(exynos_camera->raw_focus_mode, "%s", focus_mode_string); } // Zoom @@ -952,6 +963,9 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_ZOOM, zoom); if (rc < 0) ALOGE("%s: Unable to set camera zoom", __func__); + } else if (zoom > max_zoom) { + exynos_param_int_set(exynos_camera, "zoom", max_zoom); + return -EINVAL; } } @@ -995,11 +1009,15 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) flash_mode = FLASH_MODE_ON; else if (strcmp(flash_mode_string, "torch") == 0) flash_mode = FLASH_MODE_TORCH; - else - flash_mode = FLASH_MODE_AUTO; + else { + exynos_param_string_set(exynos_camera, "flash-mode", + exynos_camera->raw_flash_mode); + return -EINVAL; + } if (flash_mode != exynos_camera->flash_mode || force) { exynos_camera->flash_mode = flash_mode; + sprintf(exynos_camera->raw_flash_mode, "%s", flash_mode_string); rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_FLASH_MODE, flash_mode); if (rc < 0) ALOGE("%s:Unable to set flash mode", __func__); diff --git a/camera/exynos_camera.h b/camera/exynos_camera.h index 9e3d4f8..9895ef5 100644 --- a/camera/exynos_camera.h +++ b/camera/exynos_camera.h @@ -430,6 +430,8 @@ struct exynos_camera { int metering; int image_stabilization; char raw_focus_areas[PAGE_SIZE]; + char raw_focus_mode[64]; + char raw_flash_mode[64]; }; struct exynos_camera_addrs { -- cgit v1.1 From 28cd3f3375476cbf437241bfc5efb223a73955b8 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Wed, 30 Oct 2013 18:08:11 +0000 Subject: camera: Fix disabling location If Camera.removeGpsData() is invoked from the userland API, we must invalidate the previously stored GPS data to prevent it from being saved in EXIF. Fixes the invalid storing of location data after an explicit disable Fixes android.hardware.cts.CameraTest#testJpegExif Change-Id: I9618a27ab9def974bac1d69871c3454300fb4c29 --- camera/exynos_camera.c | 9 +++++++++ camera/exynos_exif.c | 3 +++ 2 files changed, 12 insertions(+) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 7b2875b..2a12243 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -4237,6 +4237,15 @@ int exynos_camera_set_parameters(struct camera_device *dev, exynos_camera = (struct exynos_camera *) dev->priv; + if (strstr(params, "gps-timestamp=") == NULL) { + /* Make sure the GPS data is ignored, it may have + * been explicitly erased with removeGpsData() + */ + exynos_param_int_set(exynos_camera, "gps-timestamp", -1); + exynos_param_int_set(exynos_camera, "gps-latitude", -1); + exynos_param_int_set(exynos_camera, "gps-longitude", -1); + } + rc = exynos_params_string_set(exynos_camera, (char *) params); if (rc < 0) { ALOGE("%s: Unable to set params string", __func__); diff --git a/camera/exynos_exif.c b/camera/exynos_exif.c index 2ba4ca1..b0d1656 100644 --- a/camera/exynos_exif.c +++ b/camera/exynos_exif.c @@ -195,6 +195,7 @@ int exynos_exif_attributes_create_gps(struct exynos_camera *exynos_camera, snprintf((char *) attributes->gps_datestamp, sizeof(attributes->gps_datestamp), "%04d:%02d:%02d", time_info.tm_year + 1900, time_info.tm_mon + 1, time_info.tm_mday); + strcpy((char *) attributes->gps_processing_method, gps_processing_method_string); attributes->enableGps = true; return 0; @@ -423,6 +424,8 @@ int exynos_exif_start(struct exynos_camera *exynos_camera, struct exynos_exif *e return -1; } + memset(&exif->attributes, 0, sizeof(exif_attribute_t)); + rc = exynos_exif_attributes_create_static(exynos_camera, exif); if (rc < 0) { ALOGE("%s: Unable to create exif attributes", __func__); -- cgit v1.1 From 2f654f9bd16149687f472a9abf647c7b6cfc809d Mon Sep 17 00:00:00 2001 From: mcampbellsmith Date: Fri, 6 Dec 2013 00:07:26 +1100 Subject: exynos_camera: update sports scene name The 'sports' scene mode has been renamed to 'action' scene mode to match the 4.4 camera configuration Change-Id: I1efcd57f137ee0d73f22ab20031832c7f283381c --- camera/exynos_camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 2a12243..44a0039 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -134,7 +134,7 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .antibanding_values = "off,auto,50hz,60hz", .scene_mode = "auto", - .scene_mode_values = "auto,portrait,landscape,night,beach,snow,sunset,fireworks,sports,party,candlelight,dusk-dawn,fall-color,text,back-light,high-sensitivity", + .scene_mode_values = "auto,portrait,landscape,night,beach,snow,sunset,fireworks,action,party,candlelight,dusk-dawn,fall-color,text,back-light,high-sensitivity", .effect = "none", .effect_values = "none,mono,negative,sepia,solarize,posterize,washed,vintage-warm,vintage-cold,point-blue,point-red-yellow,point-green", @@ -1106,7 +1106,7 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) scene_mode = SCENE_MODE_SUNSET; else if (strcmp(scene_mode_string, "fireworks") == 0) scene_mode = SCENE_MODE_FIREWORKS; - else if (strcmp(scene_mode_string, "sports") == 0) + else if (strcmp(scene_mode_string, "action") == 0) scene_mode = SCENE_MODE_SPORTS; else if (strcmp(scene_mode_string, "party") == 0) scene_mode = SCENE_MODE_PARTY_INDOOR; -- cgit v1.1 From a50844d698f0fbdcaacffb8b52381d44752d85c8 Mon Sep 17 00:00:00 2001 From: Dheeraj CVR Date: Sat, 14 Dec 2013 10:54:53 -0600 Subject: smdk4412-common: camera: squashed updates from cm-10.2 smdk4412-common: camera: fix EXIF attributes for S5C73M3 sensor S5C73M3 sensor which is the back camera, doesn't return the EXIF attributes using V4L2 IOCTL. This sensor interleaves YUV and JPEG frames along with Metadata which contains the EXIF information. This patch does the following: Manually extract the EXIF information from the interleaved metadata and implement ISO, Flash, Exposure, Exposure Time and Exposure Bias EXIF attributes for S5C73M3. Fix incorrect Exposure EXIF attribute that was reporting as 1'. Change-Id: Id9faa64af498645099cccc9cbf28f2dbdfecd254 smdk4412-common: camera: fix scene mode snapshot capture crashes Few Scene Modes (like Night, High Sensitivity) if set as default, after the camera opens, require the scene mode to be set when the stream is turned on inorder to properly take effect. Not doing so will result in crashes while trying to capture the snapshot. Change-Id: I9e6b67c59699495da6922ac737232f58d98c2b40 smdk4412-common: camera: reorganize camera parameters Few Scene modes require Flash and few don't. However all of the scene modes require the focus to be AUTO. Reorganize the camera parameters to set the Flash and Focus modes based on the scene mode. Changes adapted from Exynos5 Camera HAL. Change-Id: If3ab62a1d8aecf84d2a04d1e899f71d4315a66ea Conflicts: camera/exynos_camera.c smdk4412-common: camera: several fixes for autofocus Setting the AutoFocus off using V4L2_CID_CAMERA_SET_AUTO_FOCUS will reset the AF position of the sensor and this was done whenever autofocus was completed. This totally defeated the purpose of touch to focus since the sensor AF position was being reset after focus and had to be refocussed while taking the snapshot. This also led to several issues with third party applications since this kind of focus behaviour was not intended. S5C73M3 Back camera Interleaves YUV and JPEG along with metadata. This metadata contains the AutoFocus result. Hence we could parse the autofocus result instead of using V4L2 IOCTL, which is more efficient. Also, the sensor exhibits issues when AutoExposure and AutoWhite Balance locks are used with Flash ON. Improper locking could lead to freezing of the sensor while taking a snapshot. Hence, only lock AEAWB when flash is OFF and unlock them after AutoFocus finishes. Change-Id: Ief28005dcacd0f8f04990ef8eafebff4a2f109d5 smdk4412-common: camera: enable ZSL mode on front camera We are querying FIMC2 for the capture output and hence we have no reason to restart the preview to have the preview resolution match the capture resolution, which is not how Zero Shutter Lag works. We could have different resolutions for the preview and capture, hence don't stop the preview for resizing. Change-Id: Iaf2b4d0c51dbedb9516b7c3cdde09aa18cd95f73 smdk4412-common: camera: fix incorrect jpeg thumbnail height Change-Id: I139823883d91ddaa48e2516511539ff5fe150e25 smdk4412-common: camera: fix heap corruption Change-Id: I0111615b9d4552a7880598a83bc98060fa900b13 smdk4412-common: camera: include support for face detection Change-Id: I1d176bdf17abdcf0c593fceb01808348b87b75ce --- camera/exynos_camera.c | 599 ++++++++++++++++++++++++++++--------------------- camera/exynos_camera.h | 23 +- camera/exynos_exif.c | 109 +++++---- camera/exynos_v4l2.c | 63 ++++++ 4 files changed, 494 insertions(+), 300 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 44a0039..7cea71a 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -90,7 +90,7 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .picture_format = "jpeg", .jpeg_thumbnail_size_values = "160x120,160x90,144x96", .jpeg_thumbnail_width = 160, - .jpeg_thumbnail_height = 160, + .jpeg_thumbnail_height = 120, .jpeg_thumbnail_quality = 100, .jpeg_quality = 90, @@ -107,6 +107,8 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .focus_areas = "(0,0,0,0,0)", .max_num_focus_areas = 1, + .max_detected_faces = 15, + .zoom_supported = 1, .smooth_zoom_supported = 0, .zoom_ratios = "100,102,104,109,111,113,119,121,124,131,134,138,146,150,155,159,165,170,182,189,200,213,222,232,243,255,283,300,319,364,400", @@ -172,7 +174,7 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .preview_fps_range_values = "(8000,8000),(15000,15000),(15000,30000),(30000,30000)", .preview_fps_range = "15000,30000", - .picture_size_values = "1344x756,1280x720,1392x1044,1280x960,960x720,640x480,1392x1392", + .picture_size_values = "1280x960,1392x1392,640x480,1280x720,720x480,320x240", .picture_size = "1280x960", .picture_format_values = "jpeg", .picture_format = "jpeg", @@ -206,6 +208,8 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .flash_mode = NULL, .flash_mode_values = NULL, + .max_detected_faces = 5, + .exposure_compensation = 0, .exposure_compensation_step = 0.5, .min_exposure_compensation = -4, @@ -472,6 +476,11 @@ int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id) exynos_camera->config->presets[id].params.max_num_focus_areas); } + // Face Detection + exynos_camera->max_detected_faces = exynos_camera->config->presets[id].params.max_detected_faces; + exynos_param_int_set(exynos_camera, "max-num-detected-faces-hw", + exynos_camera->max_detected_faces); + // Zoom if (exynos_camera->config->presets[id].params.zoom_supported == 1) { @@ -663,7 +672,7 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) int aeawb = 0; char *flash_mode_string; - int flash_mode; + int flash_mode = 0; int exposure_compensation; int min_exposure_compensation; @@ -913,45 +922,9 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) if (rc < 0) ALOGE("%s: Unable to set object y position", __func__); } - - focus_mode = FOCUS_MODE_TOUCH; } } - focus_mode_string = exynos_param_string_get(exynos_camera, "focus-mode"); - if (focus_mode_string != NULL) { - if (focus_mode == 0) { - if (strcmp(focus_mode_string, "auto") == 0) - focus_mode = FOCUS_MODE_AUTO; - else if (strcmp(focus_mode_string, "infinity") == 0) - focus_mode = FOCUS_MODE_INFINITY; - else if (strcmp(focus_mode_string, "macro") == 0) - focus_mode = FOCUS_MODE_MACRO; - else if (strcmp(focus_mode_string, "fixed") == 0) - focus_mode = FOCUS_MODE_FIXED; - else if (strcmp(focus_mode_string, "facedetect") == 0) - focus_mode = FOCUS_MODE_FACEDETECT; - else if (strcmp(focus_mode_string, "continuous-video") == 0) - focus_mode = FOCUS_MODE_CONTINOUS_VIDEO; - else if (strcmp(focus_mode_string, "continuous-picture") == 0) - focus_mode = FOCUS_MODE_CONTINOUS_PICTURE; - else { - exynos_param_string_set(exynos_camera, "focus-mode", - exynos_camera->raw_focus_mode); - return -EINVAL; - } - } - - if (focus_mode != exynos_camera->focus_mode || force) { - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode); - if (rc < 0) - ALOGE("%s: Unable to set focus mode", __func__); - } - - exynos_camera->focus_mode = focus_mode; - sprintf(exynos_camera->raw_focus_mode, "%s", focus_mode_string); - } - // Zoom zoom_supported_string = exynos_param_string_get(exynos_camera, "zoom-supported"); @@ -988,31 +961,78 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) else awb_lock = 0; - if (ae_lock != exynos_camera->ae_lock || awb_lock != exynos_camera->awb_lock || force) { - exynos_camera->ae_lock = ae_lock; - exynos_camera->awb_lock = awb_lock; - aeawb = (ae_lock ? 0x1 : 0x0) | (awb_lock ? 0x2 : 0x0); - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, aeawb); - if (rc < 0) - ALOGE("%s: Unable to set AEAWB lock", __func__); + // Scene mode + + scene_mode_string = exynos_param_string_get(exynos_camera, "scene-mode"); + if (scene_mode_string != NULL) { + if (strcmp(scene_mode_string, "auto") == 0) + scene_mode = SCENE_MODE_NONE; + else if (strcmp(scene_mode_string, "portrait") == 0) { + scene_mode = SCENE_MODE_PORTRAIT; + flash_mode = FLASH_MODE_AUTO; + } else if (strcmp(scene_mode_string, "landscape") == 0) + scene_mode = SCENE_MODE_LANDSCAPE; + else if (strcmp(scene_mode_string, "night") == 0) + scene_mode = SCENE_MODE_NIGHTSHOT; + else if (strcmp(scene_mode_string, "beach") == 0) + scene_mode = SCENE_MODE_BEACH_SNOW; + else if (strcmp(scene_mode_string, "snow") == 0) + scene_mode = SCENE_MODE_BEACH_SNOW; + else if (strcmp(scene_mode_string, "sunset") == 0) + scene_mode = SCENE_MODE_SUNSET; + else if (strcmp(scene_mode_string, "fireworks") == 0) + scene_mode = SCENE_MODE_FIREWORKS; + else if (strcmp(scene_mode_string, "action") == 0) + scene_mode = SCENE_MODE_SPORTS; + else if (strcmp(scene_mode_string, "party") == 0) { + scene_mode = SCENE_MODE_PARTY_INDOOR; + flash_mode = FLASH_MODE_AUTO; + } else if (strcmp(scene_mode_string, "candlelight") == 0) + scene_mode = SCENE_MODE_CANDLE_LIGHT; + else if (strcmp(scene_mode_string, "dusk-dawn") == 0) + scene_mode = SCENE_MODE_DUSK_DAWN; + else if (strcmp(scene_mode_string, "fall-color") == 0) + scene_mode = SCENE_MODE_FALL_COLOR; + else if (strcmp(scene_mode_string, "back-light") == 0) + scene_mode = SCENE_MODE_BACK_LIGHT; + else if (strcmp(scene_mode_string, "text") == 0) + scene_mode = SCENE_MODE_TEXT; + else if (strcmp(scene_mode_string, "high-sensitivity") == 0) + scene_mode = SCENE_MODE_LOW_LIGHT; + else + scene_mode = SCENE_MODE_NONE; + + if (scene_mode != exynos_camera->scene_mode || force) { + exynos_camera->scene_mode = scene_mode; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SCENE_MODE, scene_mode); + if (rc < 0) + ALOGE("%s: Unable to set scene mode", __func__); + } + + if (scene_mode != SCENE_MODE_NONE && !flash_mode && !focus_mode) { + flash_mode = FLASH_MODE_OFF; + focus_mode = FOCUS_MODE_AUTO; + } } // Flash flash_mode_string = exynos_param_string_get(exynos_camera, "flash-mode"); if (flash_mode_string != NULL) { - if (strcmp(flash_mode_string, "off") == 0) - flash_mode = FLASH_MODE_OFF; - else if (strcmp(flash_mode_string, "auto") == 0) - flash_mode = FLASH_MODE_AUTO; - else if (strcmp(flash_mode_string, "on") == 0) - flash_mode = FLASH_MODE_ON; - else if (strcmp(flash_mode_string, "torch") == 0) - flash_mode = FLASH_MODE_TORCH; - else { - exynos_param_string_set(exynos_camera, "flash-mode", - exynos_camera->raw_flash_mode); - return -EINVAL; + if (flash_mode == 0) { + if (strcmp(flash_mode_string, "off") == 0) + flash_mode = FLASH_MODE_OFF; + else if (strcmp(flash_mode_string, "auto") == 0) + flash_mode = FLASH_MODE_AUTO; + else if (strcmp(flash_mode_string, "on") == 0) + flash_mode = FLASH_MODE_ON; + else if (strcmp(flash_mode_string, "torch") == 0) + flash_mode = FLASH_MODE_TORCH; + else { + exynos_param_string_set(exynos_camera, "flash-mode", + exynos_camera->raw_flash_mode); + return -EINVAL; + } } if (flash_mode != exynos_camera->flash_mode || force) { @@ -1024,6 +1044,51 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) } } + // Lock Auto Exposure and White Balance only when Flash is OFF + if ((ae_lock != exynos_camera->ae_lock || awb_lock != exynos_camera->awb_lock || force) && + exynos_camera->flash_mode == FLASH_MODE_OFF) { + exynos_camera->ae_lock = ae_lock; + exynos_camera->awb_lock = awb_lock; + aeawb = (ae_lock ? 0x1 : 0x0) | (awb_lock ? 0x2 : 0x0); + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, aeawb); + if (rc < 0) + ALOGE("%s: Unable to set AEAWB lock", __func__); + } + + focus_mode_string = exynos_param_string_get(exynos_camera, "focus-mode"); + if (focus_mode_string != NULL) { + if (focus_mode == 0) { + if (strcmp(focus_mode_string, "auto") == 0) + focus_mode = FOCUS_MODE_AUTO; + else if (strcmp(focus_mode_string, "infinity") == 0) + focus_mode = FOCUS_MODE_INFINITY; + else if (strcmp(focus_mode_string, "macro") == 0) + focus_mode = FOCUS_MODE_MACRO; + else if (strcmp(focus_mode_string, "fixed") == 0) + focus_mode = FOCUS_MODE_FIXED; + else if (strcmp(focus_mode_string, "facedetect") == 0) + focus_mode = FOCUS_MODE_FACEDETECT; + else if (strcmp(focus_mode_string, "continuous-video") == 0) + focus_mode = FOCUS_MODE_CONTINOUS_VIDEO; + else if (strcmp(focus_mode_string, "continuous-picture") == 0) + focus_mode = FOCUS_MODE_CONTINOUS_PICTURE; + else { + exynos_param_string_set(exynos_camera, "focus-mode", + exynos_camera->raw_focus_mode); + return -EINVAL; + } + } + + if (focus_mode != exynos_camera->focus_mode || force) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode); + if (rc < 0) + ALOGE("%s: Unable to set focus mode", __func__); + } + + exynos_camera->focus_mode = focus_mode; + sprintf(exynos_camera->raw_focus_mode, "%s", focus_mode_string); + } + // Exposure exposure_compensation = exynos_param_int_get(exynos_camera, "exposure-compensation"); @@ -1086,53 +1151,6 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) } } - // Scene mode - - scene_mode_string = exynos_param_string_get(exynos_camera, "scene-mode"); - if (scene_mode_string != NULL) { - if (strcmp(scene_mode_string, "auto") == 0) - scene_mode = SCENE_MODE_NONE; - else if (strcmp(scene_mode_string, "portrait") == 0) - scene_mode = SCENE_MODE_PORTRAIT; - else if (strcmp(scene_mode_string, "landscape") == 0) - scene_mode = SCENE_MODE_LANDSCAPE; - else if (strcmp(scene_mode_string, "night") == 0) - scene_mode = SCENE_MODE_NIGHTSHOT; - else if (strcmp(scene_mode_string, "beach") == 0) - scene_mode = SCENE_MODE_BEACH_SNOW; - else if (strcmp(scene_mode_string, "snow") == 0) - scene_mode = SCENE_MODE_BEACH_SNOW; - else if (strcmp(scene_mode_string, "sunset") == 0) - scene_mode = SCENE_MODE_SUNSET; - else if (strcmp(scene_mode_string, "fireworks") == 0) - scene_mode = SCENE_MODE_FIREWORKS; - else if (strcmp(scene_mode_string, "action") == 0) - scene_mode = SCENE_MODE_SPORTS; - else if (strcmp(scene_mode_string, "party") == 0) - scene_mode = SCENE_MODE_PARTY_INDOOR; - else if (strcmp(scene_mode_string, "candlelight") == 0) - scene_mode = SCENE_MODE_CANDLE_LIGHT; - else if (strcmp(scene_mode_string, "dusk-dawn") == 0) - scene_mode = SCENE_MODE_DUSK_DAWN; - else if (strcmp(scene_mode_string, "fall-color") == 0) - scene_mode = SCENE_MODE_FALL_COLOR; - else if (strcmp(scene_mode_string, "back-light") == 0) - scene_mode = SCENE_MODE_BACK_LIGHT; - else if (strcmp(scene_mode_string, "text") == 0) - scene_mode = SCENE_MODE_TEXT; - else if (strcmp(scene_mode_string, "high-sensitivity") == 0) - scene_mode = SCENE_MODE_LOW_LIGHT; - else - scene_mode = SCENE_MODE_NONE; - - if (scene_mode != exynos_camera->scene_mode || force) { - exynos_camera->scene_mode = scene_mode; - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SCENE_MODE, scene_mode); - if (rc < 0) - ALOGE("%s: Unable to set scene mode", __func__); - } - } - // Effect effect_string = exynos_param_string_get(exynos_camera, "effect"); @@ -1228,12 +1246,17 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) // Capture -int s5c73m3_interleaved_decode(void *data, int size, +int s5c73m3_interleaved_decode(struct exynos_camera *exynos_camera, void *data, int size, void *yuv_data, int *yuv_size, int yuv_width, int yuv_height, - void *jpeg_data, int *jpeg_size, int *decoded, int *auto_focus_result) + void *jpeg_data, int *jpeg_size, int *decoded, int *auto_focus_result, + struct exynos_exif *exif) { + exif_attribute_t *attributes; + camera_face_t caface[exynos_camera->max_detected_faces]; int yuv_length; int jpeg_length; + int num_detected_faces; + int face; unsigned char *yuv_p; unsigned char *jpeg_p; unsigned char *data_p; @@ -1265,25 +1288,7 @@ int s5c73m3_interleaved_decode(void *data, int size, data_p += size - 0x1000; // End of the first plane (interleaved buffer) data_p += 50; // Experimental offset for auto-focus result - s5c73m3_auto_focus_result = *data_p; - - switch (s5c73m3_auto_focus_result) { - case S5C73M3_CAF_STATUS_FOCUSING: - case S5C73M3_CAF_STATUS_FIND_SEARCHING_DIR: - case S5C73M3_AF_STATUS_INVALID: - *auto_focus_result = CAMERA_AF_STATUS_IN_PROGRESS; - break; - case S5C73M3_AF_STATUS_FOCUSED: - case S5C73M3_CAF_STATUS_FOCUSED: - *auto_focus_result = CAMERA_AF_STATUS_SUCCESS; - break; - - case S5C73M3_CAF_STATUS_UNFOCUSED: - case S5C73M3_AF_STATUS_UNFOCUSED: - default: - *auto_focus_result = CAMERA_AF_STATUS_FAIL; - break; - } + *auto_focus_result = (int) *data_p; data_p = (unsigned char *) data; data_p += size - 0x1000; // End of the first plane (interleaved buffer) @@ -1299,9 +1304,63 @@ int s5c73m3_interleaved_decode(void *data, int size, offset_p = (unsigned int *) data_p; pointers_array_size = BIG2LITTLE_ENDIAN(*offset_p); + // FaceDetection Information + data_p = (unsigned char *) data; + data_p += size - 0x1000; // End of the first plane (interleaved buffer) + data_p += 108; //Number of Faces Detected + + num_detected_faces = (int) *data_p; + data_p += 2; //Start of Face Detection Info + + exynos_camera->mFaceData.faces = caface; + if (num_detected_faces > 0 && num_detected_faces < exynos_camera->max_detected_faces) + { + for (face = 0; face < num_detected_faces; face++) { + exynos_camera->mFaceData.faces[face].rect[0] = (short)(data_p[1] << 8) + data_p[0]; + data_p += 2; + exynos_camera->mFaceData.faces[face].rect[1] = (short)(data_p[1] << 8) + data_p[0]; + data_p += 2; + exynos_camera->mFaceData.faces[face].rect[2] = (short)(data_p[1] << 8) + data_p[0]; + data_p += 2; + exynos_camera->mFaceData.faces[face].rect[3] = (short)(data_p[1] << 8) + data_p[0]; + data_p += 2; + exynos_camera->mFaceData.faces[face].score = (short)(data_p[1] << 8) + data_p[0]; + data_p += 2; + exynos_camera->mFaceData.faces[face].id = (short)(data_p[1] << 8) + data_p[0]; + data_p += 2; + } + } + exynos_camera->mFaceData.number_of_faces = num_detected_faces; + if (!*decoded) return 0; + attributes = &exif->attributes; + + //Extract the EXIF from the Metadata + //Flash + data_p = (unsigned char *) data; + data_p += size - 0x1000; // End of the first plane (interleaved buffer) + data_p += 4; // EXIF Flash Offset + attributes->flash = (int) data_p[0]; + + //ISO + data_p += 4; // EXIF ISO Offset + attributes->iso_speed_rating = (data_p[1] << 8) + data_p[0]; + + //Exposure + data_p += 4; // EXIF Exposure Offset + attributes->brightness.num = (int) data_p[0]; + + //Exposure Bias + data_p += 4; // EXIF Exposure Bias Offset + attributes->exposure_bias.num = (data_p[1] << 8) + data_p[0]; + + //Exposure Time + data_p += 8; // EXIF Exposure Time Offset + attributes->exposure_time.den = (data_p[1] << 8) + data_p[0]; + + ALOGD("%s: Interleaved pointers array is at offset 0x%x, 0x%x bytes long\n", __func__, pointers_array_offset, pointers_array_size); if ((int) pointers_array_offset > size || (int) pointers_array_size > size || (int) pointers_array_size < yuv_height * (int) sizeof(unsigned int)) { @@ -1386,6 +1445,7 @@ int exynos_camera_capture(struct exynos_camera *exynos_camera) int buffers_count; int buffer_length; int auto_focus_result; + int current_af; int decoded; int busy; void *pointer; @@ -1446,17 +1506,36 @@ int exynos_camera_capture(struct exynos_camera *exynos_camera) yuv_length = jpeg_length = 0; auto_focus_result = decoded = 0; - rc = s5c73m3_interleaved_decode(pointer, buffer_length, exynos_camera->capture_yuv_buffer, &yuv_length, width, height, exynos_camera->capture_jpeg_buffer, &jpeg_length, &decoded, &auto_focus_result); + rc = s5c73m3_interleaved_decode(exynos_camera, pointer, buffer_length, exynos_camera->capture_yuv_buffer, &yuv_length, width, height, exynos_camera->capture_jpeg_buffer, &jpeg_length, &decoded, &auto_focus_result, &exynos_camera->exif); if (rc < 0) { ALOGE("%s: Unable to decode S5C73M3 interleaved", __func__); goto error; } - if (auto_focus_result != exynos_camera->capture_auto_focus_result) { - exynos_camera->capture_auto_focus_result = auto_focus_result; + // AutoFocus + switch (auto_focus_result) { + case S5C73M3_CAF_STATUS_FOCUSING: + case S5C73M3_CAF_STATUS_FIND_SEARCHING_DIR: + case S5C73M3_AF_STATUS_FOCUSING: + current_af = CAMERA_AF_STATUS_IN_PROGRESS; + break; + case S5C73M3_CAF_STATUS_FOCUSED: + case S5C73M3_AF_STATUS_FOCUSED: + current_af = CAMERA_AF_STATUS_SUCCESS; + break; + case S5C73M3_CAF_STATUS_UNFOCUSED: + case S5C73M3_AF_STATUS_UNFOCUSED: + current_af = CAMERA_AF_STATUS_FAIL; + break; + case S5C73M3_AF_STATUS_INVALID: + default: + current_af = CAMERA_AF_STATUS_RESTART; + } - if (!exynos_camera->auto_focus_thread_enabled) { - rc = exynos_camera_auto_focus(exynos_camera, auto_focus_result); + if (current_af != exynos_camera->auto_focus_result) { + exynos_camera->auto_focus_result = current_af; + if (exynos_camera->auto_focus_enabled) { + rc = exynos_camera_auto_focus(exynos_camera, current_af); if (rc < 0) { ALOGE("%s: Unable to auto focus", __func__); goto error; @@ -1505,6 +1584,8 @@ int exynos_camera_capture(struct exynos_camera *exynos_camera) buffer->format = V4L2_PIX_FMT_JPEG; exynos_camera->capture_hybrid = 0; + + exynos_exif_create(exynos_camera, &exynos_camera->exif); } break; case V4L2_PIX_FMT_JPEG: @@ -1555,6 +1636,7 @@ int exynos_camera_capture(struct exynos_camera *exynos_camera) buffer->width = exynos_camera->jpeg_thumbnail_width; buffer->height = exynos_camera->jpeg_thumbnail_height; buffer->format = V4L2_PIX_FMT_JPEG; + break; default: buffers_count = 1; @@ -1932,6 +2014,10 @@ int exynos_camera_capture_start(struct exynos_camera *exynos_camera) } exynos_camera->capture_memory = memory; + + memory = exynos_camera->callbacks.request_memory(-1, 1, 1, exynos_camera->callbacks.user); + + exynos_camera->face_data = memory; } else { ALOGE("%s: No memory request function!", __func__); goto error; @@ -1942,6 +2028,10 @@ int exynos_camera_capture_start(struct exynos_camera *exynos_camera) exynos_camera->capture_jpeg_buffer = malloc(buffer_length); } + // Start EXIF + memset(&exynos_camera->exif, 0, sizeof(exynos_camera->exif)); + exynos_exif_start(exynos_camera, &exynos_camera->exif); + for (i = 0; i < buffers_count; i++) { rc = exynos_v4l2_qbuf_cap(exynos_camera, 0, i); if (rc < 0) { @@ -1980,6 +2070,21 @@ int exynos_camera_capture_start(struct exynos_camera *exynos_camera) goto error; } + // Few Scene Modes require to be set after stream on + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SCENE_MODE, exynos_camera->scene_mode); + if (rc < 0) { + ALOGE("%s: Unable to set scene mode", __func__); + goto error; + } + + if (exynos_camera->camera_fimc_is) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_IS_CMD_FD, IS_FD_COMMAND_START); + if (rc < 0) { + ALOGE("%s: Unable to start face detection", __func__); + goto error; + } + } + exynos_camera->capture_enabled = 1; pthread_mutex_unlock(&exynos_camera->capture_lock_mutex); @@ -2020,6 +2125,12 @@ void exynos_camera_capture_stop(struct exynos_camera *exynos_camera) ALOGE("%s: Unable to set hybrid", __func__); } + if (exynos_camera->camera_fimc_is) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_IS_CMD_FD, IS_FD_COMMAND_STOP); + if (rc < 0) + ALOGE("%s: Unable to stop face detection", __func__); + } + rc = exynos_v4l2_streamoff_cap(exynos_camera, 0); if (rc < 0) { ALOGE("%s: Unable to stop stream", __func__); @@ -2040,6 +2151,11 @@ void exynos_camera_capture_stop(struct exynos_camera *exynos_camera) exynos_camera->capture_jpeg_buffer = NULL; } + if (&exynos_camera->exif != NULL) { + exynos_exif_stop(exynos_camera, &exynos_camera->exif); + free(&exynos_camera->exif); + } + exynos_camera->capture_enabled = 0; } @@ -2155,10 +2271,12 @@ struct exynos_camera_capture_listener *exynos_camera_capture_listener_register( if (exynos_camera->capture_listeners == NULL) exynos_camera->capture_listeners = listener; - rc = exynos_camera_capture_setup(exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to setup capture", __func__); - goto error; + if (!(exynos_camera->camera_fimc_is && exynos_camera->picture_thread_enabled)) { + rc = exynos_camera_capture_setup(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to setup capture", __func__); + goto error; + } } rc = 0; @@ -2397,6 +2515,7 @@ int exynos_camera_preview(struct exynos_camera *exynos_camera) void *window_data; int window_stride; camera_memory_t *memory; + camera_face_t caface[exynos_camera->max_detected_faces]; void *memory_pointer; int memory_index; int memory_size; @@ -2447,10 +2566,19 @@ int exynos_camera_preview(struct exynos_camera *exynos_camera) exynos_camera->preview_window->enqueue_buffer(exynos_camera->preview_window, window_buffer); } + if (exynos_camera->camera_fimc_is) { + exynos_camera->mFaceData.faces = caface; + exynos_v4l2_s_ext_ctrl_face_detection(exynos_camera, 0, &exynos_camera->mFaceData); + } + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_PREVIEW_FRAME) && EXYNOS_CAMERA_CALLBACK_DEFINED(data) && !exynos_camera->callback_lock) { exynos_camera->callbacks.data(CAMERA_MSG_PREVIEW_FRAME, memory, memory_index, NULL, exynos_camera->callbacks.user); } + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_PREVIEW_METADATA) && EXYNOS_CAMERA_CALLBACK_DEFINED(data) && !exynos_camera->callback_lock) { + exynos_camera->callbacks.data(CAMERA_MSG_PREVIEW_METADATA, exynos_camera->face_data, 0, &exynos_camera->mFaceData, exynos_camera->callbacks.user); + } + if (exynos_camera->preview_output_enabled) { rc = exynos_v4l2_output_release(exynos_camera, output); if (rc < 0) { @@ -2650,12 +2778,10 @@ int exynos_camera_picture_callback(struct exynos_camera *exynos_camera, pthread_mutex_lock(&exynos_camera->picture_mutex); if (!exynos_camera->picture_enabled && !exynos_camera->camera_fimc_is) { -#if 0 - if (exynos_camera->focus_mode == FOCUS_MODE_CONTINOUS_PICTURE && exynos_camera->capture_auto_focus_result == CAMERA_AF_STATUS_IN_PROGRESS) { + if (exynos_camera->auto_focus_result == CAMERA_AF_STATUS_IN_PROGRESS) { pthread_mutex_unlock(&exynos_camera->picture_mutex); return 0; } -#endif rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_CAPTURE, 0); if (rc < 0) { @@ -2692,7 +2818,7 @@ int exynos_camera_picture_callback(struct exynos_camera *exynos_camera, else if (buffers->width == thumbnail_width && buffers->height == thumbnail_height) jpeg_thumbnail_buffer = buffers; } else { - if (buffers->width >= width && buffers->height >= height) + if ((buffers->width >= width && buffers->height >= height) || exynos_camera->camera_fimc_is) yuv_buffer = buffers; if (buffers->width >= thumbnail_width && buffers->height >= thumbnail_height) yuv_thumbnail_buffer = buffers; @@ -2762,7 +2888,6 @@ int exynos_camera_picture(struct exynos_camera *exynos_camera) struct exynos_camera_buffer *yuv_thumbnail_buffer; struct exynos_v4l2_output output; struct exynos_jpeg jpeg; - struct exynos_exif exif; int output_enabled = 0; int width, height, format; int buffer_width, buffer_height, buffer_format, buffer_address; @@ -2832,7 +2957,7 @@ int exynos_camera_picture(struct exynos_camera *exynos_camera) buffer_format = yuv_buffer->format; buffer_address = yuv_buffer->address; - if (width != buffer_width && height != buffer_height) { + if ((width != buffer_width && height != buffer_height) || exynos_camera->camera_fimc_is) { format = EXYNOS_CAMERA_PICTURE_OUTPUT_FORMAT; memset(&output, 0, sizeof(output)); @@ -2862,6 +2987,9 @@ int exynos_camera_picture(struct exynos_camera *exynos_camera) yuv_data = output.memory->data; yuv_address = output.memory_address; yuv_size = output.buffer_length; + + if (exynos_camera->camera_fimc_is) + exynos_exif_create(exynos_camera, &exynos_camera->exif); } memset(&jpeg, 0, sizeof(jpeg)); @@ -3022,24 +3150,16 @@ int exynos_camera_picture(struct exynos_camera *exynos_camera) } // EXIF + exynos_camera->exif.jpeg_thumbnail_data = jpeg_thumbnail_data; + exynos_camera->exif.jpeg_thumbnail_size = jpeg_thumbnail_size; - memset(&exif, 0, sizeof(exif)); - exif.jpeg_thumbnail_data = jpeg_thumbnail_data; - exif.jpeg_thumbnail_size = jpeg_thumbnail_size; - - rc = exynos_exif_start(exynos_camera, &exif); - if (rc < 0) { - ALOGE("%s: Unable to start exif", __func__); - goto error; - } - - rc = exynos_exif(exynos_camera, &exif); + rc = exynos_exif(exynos_camera, &exynos_camera->exif); if (rc < 0) { ALOGE("%s: Unable to exif", __func__); goto error; } - memory_size = exif.memory_size + jpeg_size; + memory_size = exynos_camera->exif.memory_size + jpeg_size; if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { memory = exynos_camera->callbacks.request_memory(-1, memory_size, 1, exynos_camera->callbacks.user); @@ -3059,14 +3179,12 @@ int exynos_camera_picture(struct exynos_camera *exynos_camera) p += 2; // Copy the EXIF data - memcpy(p, exif.memory->data, exif.memory_size); - p += exif.memory_size; + memcpy(p, exynos_camera->exif.memory->data, exynos_camera->exif.memory_size); + p += exynos_camera->exif.memory_size; // Copy the JPEG picture memcpy(p, (void *) ((unsigned char *) jpeg_data + 2), jpeg_size - 2); - exynos_exif_stop(exynos_camera, &exif); - exynos_camera->picture_memory = memory; rc = 0; @@ -3724,69 +3842,20 @@ int exynos_camera_auto_focus(struct exynos_camera *exynos_camera, int auto_focus case CAMERA_AF_STATUS_SUCCESS: if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS, 1, 0, exynos_camera->callbacks.user); + exynos_camera_auto_focus_finish(exynos_camera); break; case CAMERA_AF_STATUS_FAIL: - default: if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS, 0, 0, exynos_camera->callbacks.user); + exynos_camera_auto_focus_finish(exynos_camera); break; } return 0; } -void *exynos_camera_auto_focus_thread(void *data) -{ - struct exynos_camera *exynos_camera; - int auto_focus_status = CAMERA_AF_STATUS_FAIL; - int auto_focus_completed = 0; - int rc; - - if (data == NULL) - return NULL; - - exynos_camera = (struct exynos_camera *) data; - - ALOGE("%s: Starting thread", __func__); - exynos_camera->auto_focus_thread_running = 1; - - while (exynos_camera->auto_focus_thread_enabled) { - pthread_mutex_lock(&exynos_camera->auto_focus_mutex); - - rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT, &auto_focus_status); - if (rc < 0) { - ALOGE("%s: Unable to get auto-focus result", __func__); - auto_focus_status = CAMERA_AF_STATUS_FAIL; - } - - rc = exynos_camera_auto_focus(exynos_camera, auto_focus_status); - if (rc < 0) { - ALOGE("%s: Unable to auto-focus", __func__); - auto_focus_status = CAMERA_AF_STATUS_FAIL; - } - - if (auto_focus_status == CAMERA_AF_STATUS_IN_PROGRESS) - usleep(10000); - else - auto_focus_completed = 1; - - pthread_mutex_unlock(&exynos_camera->auto_focus_mutex); - - if (auto_focus_completed) { - exynos_camera->auto_focus_thread_running = 0; - exynos_camera_auto_focus_thread_stop(exynos_camera); - } - } - - exynos_camera->auto_focus_thread_running = 0; - ALOGE("%s: Exiting thread", __func__); - - return NULL; -} - -int exynos_camera_auto_focus_thread_start(struct exynos_camera *exynos_camera) +int exynos_camera_auto_focus_start(struct exynos_camera *exynos_camera) { - pthread_attr_t thread_attr; int auto_focus; int rc; @@ -3795,13 +3864,6 @@ int exynos_camera_auto_focus_thread_start(struct exynos_camera *exynos_camera) ALOGD("%s()", __func__); - if (exynos_camera->auto_focus_thread_enabled) { - ALOGE("Auto-focus thread was already started!"); - return 0; - } - - pthread_mutex_init(&exynos_camera->auto_focus_mutex, NULL); - auto_focus = AUTO_FOCUS_ON | (exynos_camera->preview_width & 0xfff) << 20 | (exynos_camera->preview_height & 0xfff) << 8; rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SET_AUTO_FOCUS, auto_focus); @@ -3810,22 +3872,12 @@ int exynos_camera_auto_focus_thread_start(struct exynos_camera *exynos_camera) goto error; } - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - - exynos_camera->auto_focus_thread_enabled = 1; - - rc = pthread_create(&exynos_camera->auto_focus_thread, &thread_attr, exynos_camera_auto_focus_thread, (void *) exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to create thread", __func__); - goto error; - } + exynos_camera->auto_focus_enabled = 1; rc = 0; goto complete; error: - pthread_mutex_destroy(&exynos_camera->auto_focus_mutex); rc = -1; @@ -3833,38 +3885,40 @@ complete: return rc; } -void exynos_camera_auto_focus_thread_stop(struct exynos_camera *exynos_camera) +void exynos_camera_auto_focus_finish(struct exynos_camera *exynos_camera) { int rc; - int i; - - if (exynos_camera == NULL) - return; ALOGD("%s()", __func__); - if (!exynos_camera->auto_focus_thread_enabled) { - ALOGE("Auto-focus thread was already stopped!"); + if (!exynos_camera->auto_focus_enabled) { return; } - exynos_camera->auto_focus_thread_enabled = 0; + exynos_camera->auto_focus_enabled = 0; - // Wait for the thread to end - i = 0; - while (exynos_camera->auto_focus_thread_running) { - if (i++ > 10000) { - ALOGE("Auto-focus thread is taking too long to end, something is going wrong"); - break; - } - usleep(100); - } + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, AE_UNLOCK_AWB_UNLOCK); + if (rc < 0) + ALOGE("%s: Unable to set AEAWB lock", __func__); +} + +void exynos_camera_auto_focus_stop(struct exynos_camera *exynos_camera) +{ + int rc; + int i; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF); if (rc < 0) ALOGE("%s: Unable to set auto-focus off", __func__); - pthread_mutex_destroy(&exynos_camera->auto_focus_mutex); + if (exynos_camera->auto_focus_enabled) + exynos_camera_auto_focus_finish(exynos_camera); + } /* @@ -4161,7 +4215,7 @@ int exynos_camera_start_auto_focus(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; - return exynos_camera_auto_focus_thread_start(exynos_camera); + return exynos_camera_auto_focus_start(exynos_camera); } int exynos_camera_cancel_auto_focus(struct camera_device *dev) @@ -4175,7 +4229,7 @@ int exynos_camera_cancel_auto_focus(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; - exynos_camera_auto_focus_thread_stop(exynos_camera); + exynos_camera_auto_focus_stop(exynos_camera); return 0; } @@ -4192,8 +4246,7 @@ int exynos_camera_take_picture(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; - if (exynos_camera->picture_thread_running - || exynos_camera->auto_focus_thread_enabled) + if (exynos_camera->picture_thread_running) { return 0; } @@ -4290,13 +4343,59 @@ void exynos_camera_put_parameters(struct camera_device *dev, char *params) free(params); } +int setFaceDetect(struct exynos_camera *exynos_camera, int face_detect) +{ + ALOGD("%s(face_detect(%d))", __func__, face_detect); + if (exynos_camera->camera_fimc_is) { + if (face_detect < IS_FD_COMMAND_STOP || IS_FD_COMMAND_MAX <= face_detect) { + ALOGE("ERR(%s):Invalid face_detect value (%d)", __func__, face_detect); + return -1; + } + } else { + if (face_detect < FACE_DETECTION_OFF || FACE_DETECTION_MAX <= face_detect) { + ALOGE("ERR(%s):Invalid face_detect value (%d)", __func__, face_detect); + return -1; + } + } + + if (exynos_camera->camera_fimc_is) { + if (exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_IS_CMD_FD, face_detect) < 0) { + ALOGE("ERR(%s):Fail on V4L2_CID_IS_CMD_FD", __func__); + return -1; + } + } else { + if (exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_FACE_DETECTION, face_detect) < 0) { + ALOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FACE_DETECTION", __func__); + return -1; + } + } + + return 0; +} + int exynos_camera_send_command(struct camera_device *dev, int32_t cmd, int32_t arg1, int32_t arg2) { + struct exynos_camera *exynos_camera; + exynos_camera = (struct exynos_camera *) dev->priv; + ALOGD("%s(%p, %d, %d, %d)", __func__, dev, cmd, arg1, arg2); switch (cmd) { case CAMERA_CMD_START_FACE_DETECTION: - return -EINVAL; + if (setFaceDetect(exynos_camera, FACE_DETECTION_ON) < 0) { + ALOGE("ERR: Fail on setFaceDetect(ON)"); + return -EINVAL; + } else { + return 0; + } + break; + case CAMERA_CMD_STOP_FACE_DETECTION: + if (setFaceDetect(exynos_camera, FACE_DETECTION_OFF) < 0) { + ALOGE("ERR: Fail on setFaceDetect(OFF)"); + return -EINVAL; + } else { + return 0; + } break; default: break; diff --git a/camera/exynos_camera.h b/camera/exynos_camera.h index 9895ef5..6579305 100644 --- a/camera/exynos_camera.h +++ b/camera/exynos_camera.h @@ -144,6 +144,8 @@ struct exynos_camera_params { char *focus_areas; int max_num_focus_areas; + int max_detected_faces; + int zoom_supported; int smooth_zoom_supported; char *zoom_ratios; @@ -312,12 +314,13 @@ struct exynos_camera { int capture_enabled; struct exynos_camera_capture_listener *capture_listeners; + struct exynos_exif exif; camera_memory_t *capture_memory; int capture_memory_address; int capture_memory_index; void *capture_yuv_buffer; void *capture_jpeg_buffer; - int capture_auto_focus_result; + int auto_focus_result; int capture_hybrid; int capture_width; int capture_height; @@ -356,6 +359,11 @@ struct exynos_camera { struct exynos_camera_buffer picture_yuv_buffer; struct exynos_camera_buffer picture_yuv_thumbnail_buffer; + // Face Detection + camera_frame_metadata_t mFaceData; + camera_memory_t *face_data; + int max_detected_faces; + // Recording pthread_t recording_thread; @@ -376,10 +384,7 @@ struct exynos_camera { // Auto-focus - pthread_t auto_focus_thread; - pthread_mutex_t auto_focus_mutex; - int auto_focus_thread_enabled; - int auto_focus_thread_running; + int auto_focus_enabled; // Camera params @@ -508,14 +513,16 @@ void exynos_camera_recording_thread_stop(struct exynos_camera *exynos_camera); // Auto-focus int exynos_camera_auto_focus(struct exynos_camera *exynos_camera, int auto_focus_status); -int exynos_camera_auto_focus_thread_start(struct exynos_camera *exynos_camera); -void exynos_camera_auto_focus_thread_stop(struct exynos_camera *exynos_camera); +int exynos_camera_auto_focus_start(struct exynos_camera *exynos_camera); +void exynos_camera_auto_focus_finish(struct exynos_camera *exynos_camera); +void exynos_camera_auto_focus_stop(struct exynos_camera *exynos_camera); /* * EXIF */ int exynos_exif_start(struct exynos_camera *exynos_camera, struct exynos_exif *exif); +int exynos_exif_create(struct exynos_camera *exynos_camera, struct exynos_exif *exif); void exynos_exif_stop(struct exynos_camera *exynos_camera, struct exynos_exif *exif); int exynos_exif(struct exynos_camera *exynos_camera, struct exynos_exif *exif); @@ -590,6 +597,8 @@ int exynos_v4l2_ioctl(struct exynos_camera *exynos_camera, int exynos_v4l2_id, int exynos_v4l2_poll(struct exynos_camera *exynos_camera, int exynos_v4l2_id); int exynos_v4l2_qbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, int type, int memory, int index, unsigned long userptr); +int exynos_v4l2_s_ext_ctrl_face_detection(struct exynos_camera *exynos_camera, + int id, void *value); int exynos_v4l2_qbuf_cap(struct exynos_camera *exynos_camera, int exynos_v4l2_id, int index); int exynos_v4l2_qbuf_out(struct exynos_camera *exynos_camera, int exynos_v4l2_id, diff --git a/camera/exynos_exif.c b/camera/exynos_exif.c index b0d1656..486b256 100644 --- a/camera/exynos_exif.c +++ b/camera/exynos_exif.c @@ -262,63 +262,68 @@ int exynos_exif_attributes_create_params(struct exynos_camera *exynos_camera, attributes->focal_length.num = exynos_camera->camera_focal_length; attributes->focal_length.den = EXIF_DEF_FOCAL_LEN_DEN; - shutter_speed = 100; - rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_TV, - &shutter_speed); - if (rc < 0) - ALOGE("%s: Unable to get shutter speed", __func__); + // Only Query the Front Camera Sensor for EXIF Attributes. + if (exynos_camera->camera_fimc_is) { + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_EXPTIME, + &exposure_time); + if (rc < 0) + ALOGE("%s: Unable to get exposure time", __func__); - attributes->shutter_speed.num = shutter_speed; - attributes->shutter_speed.den = 100; - - attributes->exposure_time.num = 1; - attributes->exposure_time.den = APEX_SHUTTER_TO_EXPOSURE(shutter_speed); + attributes->exposure_time.den = exposure_time; - rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_ISO, - &iso_speed); - if (rc < 0) - ALOGE("%s: Unable to get iso", __func__); + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_ISO, + &iso_speed); + if (rc < 0) + ALOGE("%s: Unable to get iso", __func__); - attributes->iso_speed_rating = iso_speed; + attributes->iso_speed_rating = iso_speed; - rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_FLASH, - &flash_results); - if (rc < 0) - ALOGE("%s: Unable to get flash", __func__); + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_FLASH, + &flash_results); + if (rc < 0) + ALOGE("%s: Unable to get flash", __func__); - attributes->flash = flash_results; + attributes->flash = flash_results; - rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_BV, + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_BV, (int *) &bv); - if (rc < 0) { - ALOGE("%s: Unable to get bv", __func__); - goto bv_static; - } + if (rc < 0) { + ALOGE("%s: Unable to get bv", __func__); + goto bv_static; + } - rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_EBV, - (int *) &ev); - if (rc < 0) { - ALOGE("%s: Unable to get ebv", __func__); - goto bv_static; - } + rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_EBV, + (int *) &ev); + if (rc < 0) { + ALOGE("%s: Unable to get ebv", __func__); + goto bv_static; + } - goto bv_ioctl; + goto bv_ioctl; bv_static: - exposure = exynos_param_int_get(exynos_camera, "exposure-compensation"); - if (exposure < 0) - exposure = EV_DEFAULT; + exposure = exynos_param_int_get(exynos_camera, "exposure-compensation"); + if (exposure < 0) + exposure = EV_DEFAULT; + + av = APEX_FNUM_TO_APERTURE((double) attributes->fnumber.num / + attributes->fnumber.den); + tv = APEX_EXPOSURE_TO_SHUTTER((double) attributes->exposure_time.num / + attributes->exposure_time.den); + sv = APEX_ISO_TO_FILMSENSITIVITY(iso_speed); + bv = av + tv - sv; + ev = exposure - EV_DEFAULT; - av = APEX_FNUM_TO_APERTURE((double) attributes->fnumber.num / - attributes->fnumber.den); - tv = APEX_EXPOSURE_TO_SHUTTER((double) attributes->exposure_time.num / - attributes->exposure_time.den); - sv = APEX_ISO_TO_FILMSENSITIVITY(iso_speed); - bv = av + tv - sv; - ev = exposure - EV_DEFAULT; bv_ioctl: - attributes->brightness.num = bv; + attributes->brightness.num = bv; + } + + attributes->shutter_speed.num = APEX_EXPOSURE_TO_SHUTTER(attributes->exposure_time.den); + attributes->shutter_speed.den = 100; + + attributes->exposure_time.num = 1; + attributes->brightness.den = EXIF_DEF_APEX_DEN; if (exynos_camera->scene_mode == SCENE_MODE_BEACH_SNOW) { @@ -450,6 +455,24 @@ complete: return rc; } +int exynos_exif_create(struct exynos_camera *exynos_camera, struct exynos_exif *exif) +{ + int rc; + + rc = exynos_exif_attributes_create_params(exynos_camera, exif); + if (rc < 0) { + ALOGE("%s: Unable to create exif parameters", __func__); + goto error; + } + + goto complete; +error: + rc = -1; + +complete: + return rc; +} + void exynos_exif_stop(struct exynos_camera *exynos_camera, struct exynos_exif *exif) { diff --git a/camera/exynos_v4l2.c b/camera/exynos_v4l2.c index 2e7fdaf..2768676 100644 --- a/camera/exynos_v4l2.c +++ b/camera/exynos_v4l2.c @@ -232,6 +232,69 @@ int exynos_v4l2_dqbuf(struct exynos_camera *exynos_camera, int exynos_v4l2_id, return buffer.index; } +int exynos_v4l2_s_ext_ctrl_face_detection(struct exynos_camera *exynos_camera, + int id, void *value) +{ + struct v4l2_ext_control ext_ctrl_fd[111]; + struct v4l2_ext_controls ext_ctrls_fd; + struct v4l2_ext_controls *ctrls; + camera_frame_metadata_t *facedata = (camera_frame_metadata_t *)value; + int i, ret; + + ext_ctrl_fd[0].id = V4L2_CID_IS_FD_GET_FACE_COUNT; + for (i = 0; i < exynos_camera->max_detected_faces; i++) { + ext_ctrl_fd[22*i+1].id = V4L2_CID_IS_FD_GET_FACE_FRAME_NUMBER; + ext_ctrl_fd[22*i+2].id = V4L2_CID_IS_FD_GET_FACE_CONFIDENCE; + ext_ctrl_fd[22*i+3].id = V4L2_CID_IS_FD_GET_FACE_SMILE_LEVEL; + ext_ctrl_fd[22*i+4].id = V4L2_CID_IS_FD_GET_FACE_BLINK_LEVEL; + ext_ctrl_fd[22*i+5].id = V4L2_CID_IS_FD_GET_FACE_TOPLEFT_X; + ext_ctrl_fd[22*i+6].id = V4L2_CID_IS_FD_GET_FACE_TOPLEFT_Y; + ext_ctrl_fd[22*i+7].id = V4L2_CID_IS_FD_GET_FACE_BOTTOMRIGHT_X; + ext_ctrl_fd[22*i+8].id = V4L2_CID_IS_FD_GET_FACE_BOTTOMRIGHT_Y; + ext_ctrl_fd[22*i+9].id = V4L2_CID_IS_FD_GET_LEFT_EYE_TOPLEFT_X; + ext_ctrl_fd[22*i+10].id = V4L2_CID_IS_FD_GET_LEFT_EYE_TOPLEFT_Y; + ext_ctrl_fd[22*i+11].id = V4L2_CID_IS_FD_GET_LEFT_EYE_BOTTOMRIGHT_X; + ext_ctrl_fd[22*i+12].id = V4L2_CID_IS_FD_GET_LEFT_EYE_BOTTOMRIGHT_Y; + ext_ctrl_fd[22*i+13].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_TOPLEFT_X; + ext_ctrl_fd[22*i+14].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_TOPLEFT_Y; + ext_ctrl_fd[22*i+15].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_BOTTOMRIGHT_X; + ext_ctrl_fd[22*i+16].id = V4L2_CID_IS_FD_GET_RIGHT_EYE_BOTTOMRIGHT_Y; + ext_ctrl_fd[22*i+17].id = V4L2_CID_IS_FD_GET_MOUTH_TOPLEFT_X; + ext_ctrl_fd[22*i+18].id = V4L2_CID_IS_FD_GET_MOUTH_TOPLEFT_Y; + ext_ctrl_fd[22*i+19].id = V4L2_CID_IS_FD_GET_MOUTH_BOTTOMRIGHT_X; + ext_ctrl_fd[22*i+20].id = V4L2_CID_IS_FD_GET_MOUTH_BOTTOMRIGHT_Y; + ext_ctrl_fd[22*i+21].id = V4L2_CID_IS_FD_GET_ANGLE; + ext_ctrl_fd[22*i+22].id = V4L2_CID_IS_FD_GET_NEXT; + } + + ext_ctrls_fd.ctrl_class = V4L2_CTRL_CLASS_CAMERA; + ext_ctrls_fd.count = 111; + ext_ctrls_fd.controls = ext_ctrl_fd; + ctrls = &ext_ctrls_fd; + + ret = exynos_v4l2_ioctl(exynos_camera, id, VIDIOC_G_EXT_CTRLS, &ext_ctrls_fd); + + facedata->number_of_faces = ext_ctrls_fd.controls[0].value; + + for(i = 0; i < facedata->number_of_faces; i++) { + facedata->faces[i].rect[0] = ext_ctrl_fd[22*i+5].value; + facedata->faces[i].rect[1] = ext_ctrl_fd[22*i+6].value; + facedata->faces[i].rect[2] = ext_ctrl_fd[22*i+7].value; + facedata->faces[i].rect[3] = ext_ctrl_fd[22*i+8].value; + facedata->faces[i].score = ext_ctrl_fd[22*i+2].value; + /* TODO : id is unique value for each face. We need to suppot this. */ + facedata->faces[i].id = 0; + facedata->faces[i].left_eye[0] = (ext_ctrl_fd[22*i+9].value + ext_ctrl_fd[22*i+11].value) / 2; + facedata->faces[i].left_eye[1] = (ext_ctrl_fd[22*i+10].value + ext_ctrl_fd[22*i+12].value) / 2; + facedata->faces[i].right_eye[0] = (ext_ctrl_fd[22*i+13].value + ext_ctrl_fd[22*i+15].value) / 2; + facedata->faces[i].right_eye[1] = (ext_ctrl_fd[22*i+14].value + ext_ctrl_fd[22*i+16].value) / 2; + facedata->faces[i].mouth[0] = (ext_ctrl_fd[22*i+17].value + ext_ctrl_fd[22*i+19].value) / 2; + facedata->faces[i].mouth[1] = (ext_ctrl_fd[22*i+18].value + ext_ctrl_fd[22*i+20].value) / 2; + } + + return ret; +} + int exynos_v4l2_dqbuf_cap(struct exynos_camera *exynos_camera, int exynos_v4l2_id) { -- cgit v1.1 From fecfc168ab1330c4076e1a4576ec0905afdff6a7 Mon Sep 17 00:00:00 2001 From: Dheeraj CVR Date: Sun, 29 Dec 2013 13:41:48 +0530 Subject: smdk4412-common: camera: don't defer picture if CAF is in progress CAF is considerably slower than Auto or Touch Focus and since we are deferring the picture while CAF is in progress, there are delays while taking the picture and these delays are sometimes huge. Disregard the CAF state since we could Touch to Focus if required. Change-Id: If981f6402cc97e0781060dc48fa7d8e44288168f --- camera/exynos_camera.c | 17 +++++------------ camera/exynos_camera.h | 1 - 2 files changed, 5 insertions(+), 13 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 7cea71a..8d6f109 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -1532,14 +1532,11 @@ int exynos_camera_capture(struct exynos_camera *exynos_camera) current_af = CAMERA_AF_STATUS_RESTART; } - if (current_af != exynos_camera->auto_focus_result) { - exynos_camera->auto_focus_result = current_af; - if (exynos_camera->auto_focus_enabled) { - rc = exynos_camera_auto_focus(exynos_camera, current_af); - if (rc < 0) { - ALOGE("%s: Unable to auto focus", __func__); - goto error; - } + if (exynos_camera->auto_focus_enabled) { + rc = exynos_camera_auto_focus(exynos_camera, current_af); + if (rc < 0) { + ALOGE("%s: Unable to auto focus", __func__); + goto error; } } @@ -2778,10 +2775,6 @@ int exynos_camera_picture_callback(struct exynos_camera *exynos_camera, pthread_mutex_lock(&exynos_camera->picture_mutex); if (!exynos_camera->picture_enabled && !exynos_camera->camera_fimc_is) { - if (exynos_camera->auto_focus_result == CAMERA_AF_STATUS_IN_PROGRESS) { - pthread_mutex_unlock(&exynos_camera->picture_mutex); - return 0; - } rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_CAPTURE, 0); if (rc < 0) { diff --git a/camera/exynos_camera.h b/camera/exynos_camera.h index 6579305..5118539 100644 --- a/camera/exynos_camera.h +++ b/camera/exynos_camera.h @@ -320,7 +320,6 @@ struct exynos_camera { int capture_memory_index; void *capture_yuv_buffer; void *capture_jpeg_buffer; - int auto_focus_result; int capture_hybrid; int capture_width; int capture_height; -- cgit v1.1 From 40279ba1fd2d4f02d889699df1eccf3d3a01df55 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Thu, 2 Jan 2014 20:43:03 +0000 Subject: camera: Fix loss of focus mode between shots exynos_camera->focus_mode can't be relied upon to verify the previous state, since a snapshot will reset the focus state. This was causing any mode besides auto-focus (enum 0) to fail after the first photo was taken, including the default continuous-picture. Always make sure the focus-mode is up to date when set_params is called Change-Id: I8e6f52093ad897bcf04bc5047bb1fcd4f109dc55 --- camera/exynos_camera.c | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 7cea71a..59cf23c 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -1057,33 +1057,29 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) focus_mode_string = exynos_param_string_get(exynos_camera, "focus-mode"); if (focus_mode_string != NULL) { - if (focus_mode == 0) { - if (strcmp(focus_mode_string, "auto") == 0) - focus_mode = FOCUS_MODE_AUTO; - else if (strcmp(focus_mode_string, "infinity") == 0) - focus_mode = FOCUS_MODE_INFINITY; - else if (strcmp(focus_mode_string, "macro") == 0) - focus_mode = FOCUS_MODE_MACRO; - else if (strcmp(focus_mode_string, "fixed") == 0) - focus_mode = FOCUS_MODE_FIXED; - else if (strcmp(focus_mode_string, "facedetect") == 0) - focus_mode = FOCUS_MODE_FACEDETECT; - else if (strcmp(focus_mode_string, "continuous-video") == 0) - focus_mode = FOCUS_MODE_CONTINOUS_VIDEO; - else if (strcmp(focus_mode_string, "continuous-picture") == 0) - focus_mode = FOCUS_MODE_CONTINOUS_PICTURE; - else { - exynos_param_string_set(exynos_camera, "focus-mode", - exynos_camera->raw_focus_mode); - return -EINVAL; - } + if (strcmp(focus_mode_string, "auto") == 0) + focus_mode = FOCUS_MODE_AUTO; + else if (strcmp(focus_mode_string, "infinity") == 0) + focus_mode = FOCUS_MODE_INFINITY; + else if (strcmp(focus_mode_string, "macro") == 0) + focus_mode = FOCUS_MODE_MACRO; + else if (strcmp(focus_mode_string, "fixed") == 0) + focus_mode = FOCUS_MODE_FIXED; + else if (strcmp(focus_mode_string, "facedetect") == 0) + focus_mode = FOCUS_MODE_FACEDETECT; + else if (strcmp(focus_mode_string, "continuous-video") == 0) + focus_mode = FOCUS_MODE_CONTINOUS_VIDEO; + else if (strcmp(focus_mode_string, "continuous-picture") == 0) + focus_mode = FOCUS_MODE_CONTINOUS_PICTURE; + else { + exynos_param_string_set(exynos_camera, "focus-mode", + exynos_camera->raw_focus_mode); + return -EINVAL; } - if (focus_mode != exynos_camera->focus_mode || force) { - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode); - if (rc < 0) - ALOGE("%s: Unable to set focus mode", __func__); - } + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode); + if (rc < 0) + ALOGE("%s: Unable to set focus mode", __func__); exynos_camera->focus_mode = focus_mode; sprintf(exynos_camera->raw_focus_mode, "%s", focus_mode_string); -- cgit v1.1 From a533cbc376c453adb678ddc4e9d799b89b47c200 Mon Sep 17 00:00:00 2001 From: Dheeraj CVR Date: Sat, 11 Jan 2014 15:10:10 +0530 Subject: smdk4412-common: camera: implement CAMERA_MSG_FOCUS_MOVE to report CAF Since we are querying the status of CAF in real time, implement CAMERA_MSG_FOCUS_MOVE to report the CAF status. Also monitor the state of AutoFocus and report success or failure only when AutoFocus has started. This prevents reporting false AutoFocus status which relates to the previous AutoFocus result. Change-Id: Icb151dca150f932b42b276c45ec392e3dae413cc --- camera/exynos_camera.c | 66 +++++++++++++++++++++++++++++++++++++++++++------- camera/exynos_camera.h | 2 ++ 2 files changed, 59 insertions(+), 9 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index c112663..f0cb0c3 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -1536,6 +1536,26 @@ int exynos_camera_capture(struct exynos_camera *exynos_camera) } } + // CAF + switch (auto_focus_result) { + case S5C73M3_CAF_STATUS_FOCUSING: + case S5C73M3_CAF_STATUS_FIND_SEARCHING_DIR: + current_af = CAMERA_AF_STATUS_IN_PROGRESS; + break; + case S5C73M3_CAF_STATUS_FOCUSED: + current_af = CAMERA_AF_STATUS_SUCCESS; + break; + case S5C73M3_CAF_STATUS_UNFOCUSED: + default: + current_af = CAMERA_AF_STATUS_RESTART; + } + + rc = exynos_camera_continuous_auto_focus(exynos_camera, current_af); + if (rc < 0) { + ALOGE("%s: Unable to continuous auto focus", __func__); + goto error; + } + if (!decoded) { buffers_count = 1; buffers = (struct exynos_camera_buffer *) calloc(buffers_count, sizeof(struct exynos_camera_buffer)); @@ -3822,21 +3842,48 @@ int exynos_camera_auto_focus(struct exynos_camera *exynos_camera, int auto_focus // ALOGD("%s()", __func__); switch (auto_focus_status) { + case CAMERA_AF_STATUS_SUCCESS: + if (exynos_camera->auto_focus_started) { + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) + exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS, 1, 0, exynos_camera->callbacks.user); + exynos_camera_auto_focus_finish(exynos_camera); + } + break; + case CAMERA_AF_STATUS_FAIL: + if (exynos_camera->auto_focus_started) { + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) + exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS, 0, 0, exynos_camera->callbacks.user); + exynos_camera_auto_focus_finish(exynos_camera); + } + break; + case CAMERA_AF_STATUS_IN_PROGRESS: + exynos_camera->auto_focus_started = 1; + break; + case CAMERA_AF_STATUS_RESTART: + default: + break; + } + + return 0; +} + +int exynos_camera_continuous_auto_focus(struct exynos_camera *exynos_camera, int auto_focus_status) +{ + if (exynos_camera == NULL) + return -EINVAL; + + switch (auto_focus_status) { case CAMERA_AF_STATUS_IN_PROGRESS: -/* if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS_MOVE) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS_MOVE, 1, 0, exynos_camera->callbacks.user); -*/ + break; case CAMERA_AF_STATUS_SUCCESS: - if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) - exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS, 1, 0, exynos_camera->callbacks.user); - exynos_camera_auto_focus_finish(exynos_camera); + if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS_MOVE) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) + exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS_MOVE, 0, 0, exynos_camera->callbacks.user); break; - case CAMERA_AF_STATUS_FAIL: - if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) - exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS, 0, 0, exynos_camera->callbacks.user); - exynos_camera_auto_focus_finish(exynos_camera); + case CAMERA_AF_STATUS_RESTART: + default: break; } @@ -3885,6 +3932,7 @@ void exynos_camera_auto_focus_finish(struct exynos_camera *exynos_camera) } exynos_camera->auto_focus_enabled = 0; + exynos_camera->auto_focus_started = 0; rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, AE_UNLOCK_AWB_UNLOCK); if (rc < 0) diff --git a/camera/exynos_camera.h b/camera/exynos_camera.h index 5118539..e3bed92 100644 --- a/camera/exynos_camera.h +++ b/camera/exynos_camera.h @@ -384,6 +384,7 @@ struct exynos_camera { // Auto-focus int auto_focus_enabled; + int auto_focus_started; // Camera params @@ -512,6 +513,7 @@ void exynos_camera_recording_thread_stop(struct exynos_camera *exynos_camera); // Auto-focus int exynos_camera_auto_focus(struct exynos_camera *exynos_camera, int auto_focus_status); +int exynos_camera_continuous_auto_focus(struct exynos_camera *exynos_camera, int auto_focus_status); int exynos_camera_auto_focus_start(struct exynos_camera *exynos_camera); void exynos_camera_auto_focus_finish(struct exynos_camera *exynos_camera); void exynos_camera_auto_focus_stop(struct exynos_camera *exynos_camera); -- cgit v1.1 From b5007ffc2decdfeacf02f722ff889f0b7ed3b68b Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Mon, 27 Jan 2014 21:16:04 +0000 Subject: camera: Hold 25 msec between preview cycles on restart If doing a preview restart with an active listener, give said listener a bit of time to clean up before starting up the preview again. This should be sufficient to prevent shutdown/start race conditions during externally triggered restarts. Change-Id: Id4a722c472eeffb50a332b0dabc29d9e23062883 --- camera/exynos_camera.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index f0cb0c3..9657eea 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -2636,6 +2636,8 @@ void *exynos_camera_preview_thread(void *data) } if (exynos_camera->preview_listener->busy) { + // Prevent preview restart race conditions + usleep((useconds_t)25 * 1000); rc = exynos_camera_preview(exynos_camera); if (rc < 0) { ALOGE("%s: Unable to preview", __func__); -- cgit v1.1 From 58f00475ce3549e300e7c14e9453f68076925d7e Mon Sep 17 00:00:00 2001 From: Dheeraj CVR Date: Fri, 31 Jan 2014 23:07:16 +0530 Subject: smdk4412-common: camera: properly enable touch to focus mode Touch to focus is not properly enforced unless the focus mode is set to FOCUS_MODE_TOUCH. https://github.com/CyanogenMod/android_kernel_samsung_smdk4412/blob/cm-11.0/drivers/media/video/s5c73m3.c#L1857 Change-Id: I67236ae7ae687fbc0b7450102d744472a81def99 --- camera/exynos_camera.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 9657eea..6b6bce3 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -653,7 +653,7 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) int fimc_is_mode = 0; char *focus_mode_string; - int focus_mode = 0; + int focus_mode = FOCUS_MODE_DEFAULT; char *focus_areas_string; int focus_left, focus_top, focus_right, focus_bottom, focus_weight; int focus_x; @@ -923,6 +923,9 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) ALOGE("%s: Unable to set object y position", __func__); } } + + focus_mode = FOCUS_MODE_TOUCH; + } // Zoom @@ -1009,7 +1012,7 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) ALOGE("%s: Unable to set scene mode", __func__); } - if (scene_mode != SCENE_MODE_NONE && !flash_mode && !focus_mode) { + if (scene_mode != SCENE_MODE_NONE && !flash_mode && focus_mode == FOCUS_MODE_DEFAULT) { flash_mode = FLASH_MODE_OFF; focus_mode = FOCUS_MODE_AUTO; } @@ -1057,24 +1060,26 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) focus_mode_string = exynos_param_string_get(exynos_camera, "focus-mode"); if (focus_mode_string != NULL) { - if (strcmp(focus_mode_string, "auto") == 0) - focus_mode = FOCUS_MODE_AUTO; - else if (strcmp(focus_mode_string, "infinity") == 0) - focus_mode = FOCUS_MODE_INFINITY; - else if (strcmp(focus_mode_string, "macro") == 0) - focus_mode = FOCUS_MODE_MACRO; - else if (strcmp(focus_mode_string, "fixed") == 0) - focus_mode = FOCUS_MODE_FIXED; - else if (strcmp(focus_mode_string, "facedetect") == 0) - focus_mode = FOCUS_MODE_FACEDETECT; - else if (strcmp(focus_mode_string, "continuous-video") == 0) - focus_mode = FOCUS_MODE_CONTINOUS_VIDEO; - else if (strcmp(focus_mode_string, "continuous-picture") == 0) - focus_mode = FOCUS_MODE_CONTINOUS_PICTURE; - else { - exynos_param_string_set(exynos_camera, "focus-mode", - exynos_camera->raw_focus_mode); - return -EINVAL; + if (focus_mode == FOCUS_MODE_DEFAULT) { + if (strcmp(focus_mode_string, "auto") == 0) + focus_mode = FOCUS_MODE_AUTO; + else if (strcmp(focus_mode_string, "infinity") == 0) + focus_mode = FOCUS_MODE_INFINITY; + else if (strcmp(focus_mode_string, "macro") == 0) + focus_mode = FOCUS_MODE_MACRO; + else if (strcmp(focus_mode_string, "fixed") == 0) + focus_mode = FOCUS_MODE_FIXED; + else if (strcmp(focus_mode_string, "facedetect") == 0) + focus_mode = FOCUS_MODE_FACEDETECT; + else if (strcmp(focus_mode_string, "continuous-video") == 0) + focus_mode = FOCUS_MODE_CONTINOUS_VIDEO; + else if (strcmp(focus_mode_string, "continuous-picture") == 0) + focus_mode = FOCUS_MODE_CONTINOUS_PICTURE; + else { + exynos_param_string_set(exynos_camera, "focus-mode", + exynos_camera->raw_focus_mode); + return -EINVAL; + } } rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode); -- cgit v1.1 From 0378c1e7c0d105d51d6326a87ba14b1890338311 Mon Sep 17 00:00:00 2001 From: Javier Ferrer Date: Sun, 23 Mar 2014 01:27:02 +0100 Subject: smdk4412-common: camera: Don't set focus to FOCUS_MODE_TOUCH after taking a picture After picture has been taken in stock camera app, FocusAreas is resetted to the center of the preview screen, causing the HAL to detect the non (0,0,0,0,0) as a tap in the screen. Change-Id: Id41d108c6bb59a05a0a98efbaef51d14f50741fd --- camera/exynos_camera.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 6b6bce3..2335173 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -922,9 +922,13 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) if (rc < 0) ALOGE("%s: Unable to set object y position", __func__); } - } - focus_mode = FOCUS_MODE_TOUCH; + /* After taking a picture, focus-areas is reseted by stock camera app to the center of the screen */ + if (! ( (focus_x == (preview_width / 2)) && (focus_y == (preview_height / 2)) )) { + //ALOGV("%s focus_mode changed to %d due to focus-areas='%s'", __func__, focus_mode, focus_areas_string); + focus_mode = FOCUS_MODE_TOUCH; + } + } } -- cgit v1.1 From 7998a46db189e42ff48dfa19e3b421402b72343e Mon Sep 17 00:00:00 2001 From: Dheeraj CVR Date: Mon, 24 Mar 2014 07:16:42 +0530 Subject: smdk4412-common: camera: release face detection memory when capture stops Change-Id: I6724ce6dde3c4b6242a06b73808905a6de094d4a --- camera/exynos_camera.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 2335173..a15d904 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -2114,6 +2114,11 @@ int exynos_camera_capture_start(struct exynos_camera *exynos_camera) goto complete; error: + if (exynos_camera->face_data != NULL && exynos_camera->face_data->release != NULL) { + exynos_camera->face_data->release(exynos_camera->face_data); + exynos_camera->face_data = NULL; + } + if (exynos_camera->capture_memory != NULL && exynos_camera->capture_memory->release != NULL) { exynos_camera->capture_memory->release(exynos_camera->capture_memory); exynos_camera->capture_memory = NULL; @@ -2158,6 +2163,11 @@ void exynos_camera_capture_stop(struct exynos_camera *exynos_camera) ALOGE("%s: Unable to stop stream", __func__); } + if (exynos_camera->face_data != NULL && exynos_camera->face_data->release != NULL) { + exynos_camera->face_data->release(exynos_camera->face_data); + exynos_camera->face_data = NULL; + } + if (exynos_camera->capture_memory != NULL && exynos_camera->capture_memory->release != NULL) { exynos_camera->capture_memory->release(exynos_camera->capture_memory); exynos_camera->capture_memory = NULL; -- cgit v1.1 From 0aed9830d0c2e7f3c9d4cdaa77bb89b0d519ff34 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Mon, 24 Mar 2014 12:15:33 +0100 Subject: smdk4412-common: camera: Proper recording memory release Change-Id: I4cb029f64564a6e5e41b36af6bdb3f35ac1fc464 --- camera/exynos_camera.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index a15d904..7e551dc 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -3812,6 +3812,7 @@ complete: void exynos_camera_recording_thread_stop(struct exynos_camera *exynos_camera) { + camera_memory_t *memory; int i; if (exynos_camera == NULL) @@ -3824,6 +3825,8 @@ void exynos_camera_recording_thread_stop(struct exynos_camera *exynos_camera) return; } + memory = exynos_camera->recording_memory; + if (exynos_camera->recording_listener != NULL) { exynos_camera_capture_listener_unregister(exynos_camera, exynos_camera->recording_listener); exynos_camera->recording_listener = NULL; @@ -3851,6 +3854,11 @@ void exynos_camera_recording_thread_stop(struct exynos_camera *exynos_camera) pthread_mutex_destroy(&exynos_camera->recording_mutex); pthread_mutex_destroy(&exynos_camera->recording_lock_mutex); + + if (memory != NULL && memory->release != NULL) { + memory->release(memory); + exynos_camera->recording_memory = NULL; + } } // Auto-focus -- cgit v1.1 From b6f26b5e415112fd5253a3eee52b996fc918380e Mon Sep 17 00:00:00 2001 From: Dheeraj CVR Date: Sat, 11 Jan 2014 15:35:45 +0530 Subject: Revert "camera: Fix loss of focus mode between shots" This reverts commit 40279ba1fd2d4f02d889699df1eccf3d3a01df55. V4L2_CID_CAMERA_FOCUS_MODE has the side effect of resetting the sensor AF position. Hence, the focus is lost each time SetParameters is called and this happens during a snapshot resulting in out of focus pictures. Change-Id: Ia644b62e3752196c0637053150af7899155d6a47 --- camera/exynos_camera.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 7e551dc..6ef2dc6 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -1086,9 +1086,11 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) } } - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode); - if (rc < 0) - ALOGE("%s: Unable to set focus mode", __func__); + if (focus_mode != exynos_camera->focus_mode || force) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode); + if (rc < 0) + ALOGE("%s: Unable to set focus mode", __func__); + } exynos_camera->focus_mode = focus_mode; sprintf(exynos_camera->raw_focus_mode, "%s", focus_mode_string); -- cgit v1.1 From 2afece3afb558a194d87e5d65d13085b2fa8f6b7 Mon Sep 17 00:00:00 2001 From: Dheeraj CVR Date: Fri, 28 Mar 2014 21:03:30 +0530 Subject: Video snapshot & Optimizations Change-Id: Ifb001b5854bb47c5af74a9b5d0e63b224aa901aa --- camera/exynos_camera.c | 1558 ++++++++++++------------------------------------ camera/exynos_camera.h | 80 +-- 2 files changed, 413 insertions(+), 1225 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 6ef2dc6..0a62ab3 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -59,6 +59,17 @@ struct exynos_camera_mbus_resolution exynos_camera_mbus_resolutions_s5k6a3_smdk4 { 320, 320, 1392, 1392 }, }; +struct exynos_camera_videosnapshot_resolution exynos_camera_videosnapshot_resolutions_s5c73m3[] = { + //Capture Size - Snapshot Size + { 1920, 1080, 3264, 1836 }, + { 1280, 720, 3264, 1836 }, + { 720, 480, 3264, 2176 }, + { 640, 480, 3264, 2488 }, + { 352, 288, 3264, 2488 }, + { 320, 240, 3264, 2488 }, + { 176, 144, 3264, 2488 }, +}; + struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { { .name = "S5C73M3", @@ -68,7 +79,7 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .hflip = 0, .vflip = 0, .capture_format = V4L2_PIX_FMT_INTERLEAVED, - .picture_format = 0, + .picture_format = V4L2_PIX_FMT_JPEG, .fimc_is = 0, .focal_length = 3.7f, .horizontal_view_angle = 63.0f, @@ -94,7 +105,7 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .jpeg_thumbnail_quality = 100, .jpeg_quality = 90, - .video_snapshot_supported = 0, + .video_snapshot_supported = 1, .full_video_snap_supported = 0, .recording_size = "1280x720", @@ -149,6 +160,9 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { }, .mbus_resolutions = NULL, .mbus_resolutions_count = 0, + + .videosnapshot_resolutions = (struct exynos_camera_videosnapshot_resolution *) &exynos_camera_videosnapshot_resolutions_s5c73m3, + .videosnapshot_resolutions_count = 7, }, { .name = "S5K6A3", @@ -157,8 +171,8 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .rotation = 0, .hflip = 0, .vflip = 0, - .capture_format = 0, - .picture_format = V4L2_PIX_FMT_YUYV, + .capture_format = V4L2_PIX_FMT_UYVY, + .picture_format = V4L2_PIX_FMT_JPEG, .fimc_is = 1, .focal_length = 2.73f, .horizontal_view_angle = 52.58f, @@ -184,8 +198,8 @@ struct exynos_camera_preset exynos_camera_presets_smdk4x12[] = { .jpeg_thumbnail_quality = 100, .jpeg_quality = 90, - .video_snapshot_supported = 0, - .full_video_snap_supported = 0, + .video_snapshot_supported = 1, + .full_video_snap_supported = 1, .recording_size = "1280x720", .recording_size_values = "1280x720,720x480,640x480,352x288,320x320,320x240,176x144", @@ -400,6 +414,10 @@ int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id) exynos_camera->camera_mbus_resolutions = exynos_camera->config->presets[id].mbus_resolutions; exynos_camera->camera_mbus_resolutions_count = exynos_camera->config->presets[id].mbus_resolutions_count; + exynos_camera->camera_videosnapshot_resolutions = exynos_camera->config->presets[id].videosnapshot_resolutions; + exynos_camera->camera_videosnapshot_resolutions_count = exynos_camera->config->presets[id].videosnapshot_resolutions_count; + + // Recording preview exynos_param_string_set(exynos_camera, "preferred-preview-size-for-video", @@ -698,7 +716,7 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) int w, h; char *k; - int rc; + int rc, i; if (exynos_camera == NULL) return -EINVAL; @@ -749,22 +767,6 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) // Picture - picture_size_string = exynos_param_string_get(exynos_camera, "picture-size"); - if (picture_size_string != NULL) { - sscanf(picture_size_string, "%dx%d", &picture_width, &picture_height); - - if (picture_width != 0 && picture_height != 0 && (picture_width != exynos_camera->picture_width || picture_height != exynos_camera->picture_height)) { - exynos_camera->picture_width = picture_width; - exynos_camera->picture_height = picture_height; - - if (exynos_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED) { - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_JPEG_RESOLUTION, (picture_width & 0xffff) << 16 | (picture_height & 0xffff)); - if (rc < 0) - ALOGE("%s: Unablet to set jpeg resolution", __func__); - } - } - } - picture_format_string = exynos_param_string_get(exynos_camera, "picture-format"); if (picture_format_string != NULL) { if (strcmp(picture_format_string, "jpeg") == 0) { @@ -871,6 +873,43 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force) fimc_is_mode = IS_MODE_PREVIEW_STILL; } + // Picture size and Video Snapshot Resolution + picture_size_string = exynos_param_string_get(exynos_camera, "picture-size"); + if (picture_size_string != NULL) { + sscanf(picture_size_string, "%dx%d", &picture_width, &picture_height); + + if (camera_sensor_mode == SENSOR_MOVIE) { + //Set Video Recording SnapShot Resolutions + if (exynos_camera->camera_videosnapshot_resolutions != NULL) { + //Back Camera + if (!exynos_camera->camera_fimc_is) { + for (i = 0; i < exynos_camera->camera_videosnapshot_resolutions_count; i++) { + if (exynos_camera->camera_videosnapshot_resolutions[i].video_width == exynos_camera->recording_width && exynos_camera->camera_videosnapshot_resolutions[i].video_height == exynos_camera->recording_height) { + picture_width = exynos_camera->camera_videosnapshot_resolutions[i].snapshot_width; + picture_height = exynos_camera->camera_videosnapshot_resolutions[i].snapshot_height; + break; + } + } + } else { + //Front Facing Camera - Use Recording size as Snapshot size + picture_width = exynos_camera->recording_width; + picture_height = exynos_camera->recording_height; + } + } + } + + if (picture_width != 0 && picture_height != 0 && (picture_width != exynos_camera->picture_width || picture_height != exynos_camera->picture_height)) { + exynos_camera->picture_width = picture_width; + exynos_camera->picture_height = picture_height; + + if (!exynos_camera->camera_fimc_is) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_JPEG_RESOLUTION, (picture_width & 0xffff) << 16 | (picture_height & 0xffff)); + if (rc < 0) + ALOGE("%s: Unable to set jpeg resolution", __func__); + } + } + } + // Switching modes if (camera_sensor_mode != exynos_camera->camera_sensor_mode) { @@ -1441,10 +1480,8 @@ int s5c73m3_interleaved_decode(struct exynos_camera *exynos_camera, void *data, int exynos_camera_capture(struct exynos_camera *exynos_camera) { - struct exynos_camera_capture_listener *listener; struct exynos_camera_buffer *buffers = NULL; struct exynos_camera_buffer *buffer; - struct list_head *list; int width, height, format; int yuv_length, jpeg_length; int jpeg_offset, jpeg_size; @@ -1456,6 +1493,7 @@ int exynos_camera_capture(struct exynos_camera *exynos_camera) int decoded; int busy; void *pointer; + void *picture_yuv_pointer = NULL; int address; int offset; int index; @@ -1508,214 +1546,174 @@ int exynos_camera_capture(struct exynos_camera *exynos_camera) // Buffers - switch (format) { - case V4L2_PIX_FMT_INTERLEAVED: - yuv_length = jpeg_length = 0; - auto_focus_result = decoded = 0; - - rc = s5c73m3_interleaved_decode(exynos_camera, pointer, buffer_length, exynos_camera->capture_yuv_buffer, &yuv_length, width, height, exynos_camera->capture_jpeg_buffer, &jpeg_length, &decoded, &auto_focus_result, &exynos_camera->exif); - if (rc < 0) { - ALOGE("%s: Unable to decode S5C73M3 interleaved", __func__); - goto error; - } - - // AutoFocus - switch (auto_focus_result) { - case S5C73M3_CAF_STATUS_FOCUSING: - case S5C73M3_CAF_STATUS_FIND_SEARCHING_DIR: - case S5C73M3_AF_STATUS_FOCUSING: - current_af = CAMERA_AF_STATUS_IN_PROGRESS; - break; - case S5C73M3_CAF_STATUS_FOCUSED: - case S5C73M3_AF_STATUS_FOCUSED: - current_af = CAMERA_AF_STATUS_SUCCESS; - break; - case S5C73M3_CAF_STATUS_UNFOCUSED: - case S5C73M3_AF_STATUS_UNFOCUSED: - current_af = CAMERA_AF_STATUS_FAIL; - break; - case S5C73M3_AF_STATUS_INVALID: - default: - current_af = CAMERA_AF_STATUS_RESTART; - } + if (!exynos_camera->camera_fimc_is) { + yuv_length = jpeg_length = 0; + auto_focus_result = decoded = 0; - if (exynos_camera->auto_focus_enabled) { - rc = exynos_camera_auto_focus(exynos_camera, current_af); - if (rc < 0) { - ALOGE("%s: Unable to auto focus", __func__); - goto error; - } - } + rc = s5c73m3_interleaved_decode(exynos_camera, pointer, buffer_length, exynos_camera->capture_yuv_buffer, &yuv_length, width, height, exynos_camera->capture_jpeg_buffer, &jpeg_length, &decoded, &auto_focus_result, &exynos_camera->exif); + if (rc < 0) { + ALOGE("%s: Unable to decode S5C73M3 interleaved", __func__); + goto error; + } - // CAF - switch (auto_focus_result) { - case S5C73M3_CAF_STATUS_FOCUSING: - case S5C73M3_CAF_STATUS_FIND_SEARCHING_DIR: - current_af = CAMERA_AF_STATUS_IN_PROGRESS; - break; - case S5C73M3_CAF_STATUS_FOCUSED: - current_af = CAMERA_AF_STATUS_SUCCESS; - break; - case S5C73M3_CAF_STATUS_UNFOCUSED: - default: - current_af = CAMERA_AF_STATUS_RESTART; - } + // AutoFocus + switch (auto_focus_result) { + case S5C73M3_CAF_STATUS_FOCUSING: + case S5C73M3_CAF_STATUS_FIND_SEARCHING_DIR: + case S5C73M3_AF_STATUS_FOCUSING: + current_af = CAMERA_AF_STATUS_IN_PROGRESS; + break; + case S5C73M3_CAF_STATUS_FOCUSED: + case S5C73M3_AF_STATUS_FOCUSED: + current_af = CAMERA_AF_STATUS_SUCCESS; + break; + case S5C73M3_CAF_STATUS_UNFOCUSED: + case S5C73M3_AF_STATUS_UNFOCUSED: + current_af = CAMERA_AF_STATUS_FAIL; + break; + case S5C73M3_AF_STATUS_INVALID: + default: + current_af = CAMERA_AF_STATUS_RESTART; + } - rc = exynos_camera_continuous_auto_focus(exynos_camera, current_af); + if (exynos_camera->auto_focus_enabled) { + rc = exynos_camera_auto_focus(exynos_camera, current_af); if (rc < 0) { - ALOGE("%s: Unable to continuous auto focus", __func__); + ALOGE("%s: Unable to auto focus", __func__); goto error; } + } - if (!decoded) { - buffers_count = 1; - buffers = (struct exynos_camera_buffer *) calloc(buffers_count, sizeof(struct exynos_camera_buffer)); - - buffer = buffers; - - buffer->pointer = pointer; - buffer->address = address; - buffer->length = exynos_camera_buffer_length(width, height, V4L2_PIX_FMT_UYVY); - buffer->width = width; - buffer->height = height; - buffer->format = V4L2_PIX_FMT_UYVY; - } else { - buffers_count = 2; - buffers = (struct exynos_camera_buffer *) calloc(buffers_count, sizeof(struct exynos_camera_buffer)); - - buffer = buffers; - - memcpy(pointer, exynos_camera->capture_yuv_buffer, yuv_length); - - buffer->pointer = pointer; - buffer->address = address; - buffer->length = yuv_length; - buffer->width = width; - buffer->height = height; - buffer->format = V4L2_PIX_FMT_UYVY; - - pointer = (void *) ((unsigned char *) pointer + yuv_length); - address += yuv_length; - buffer = (struct exynos_camera_buffer *) ((unsigned char *) buffer + sizeof(struct exynos_camera_buffer)); - - memcpy(pointer, exynos_camera->capture_jpeg_buffer, jpeg_length); - - buffer->pointer = pointer; - buffer->address = address; - buffer->length = jpeg_length; - buffer->width = exynos_camera->picture_width; - buffer->height = exynos_camera->picture_height; - buffer->format = V4L2_PIX_FMT_JPEG; - - exynos_camera->capture_hybrid = 0; - - exynos_exif_create(exynos_camera, &exynos_camera->exif); - } - break; - case V4L2_PIX_FMT_JPEG: - jpeg_size = jpeg_offset = 0; - jpeg_thumbnail_size = jpeg_thumbnail_offset = 0; - - rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_MAIN_SIZE, &jpeg_size); - if (rc < 0 || jpeg_size <= 0) { - ALOGE("%s: Unable to get jpeg size", __func__); - goto error; - } + // CAF + switch (auto_focus_result) { + case S5C73M3_CAF_STATUS_FOCUSING: + case S5C73M3_CAF_STATUS_FIND_SEARCHING_DIR: + current_af = CAMERA_AF_STATUS_IN_PROGRESS; + break; + case S5C73M3_CAF_STATUS_FOCUSED: + current_af = CAMERA_AF_STATUS_SUCCESS; + break; + case S5C73M3_CAF_STATUS_UNFOCUSED: + default: + current_af = CAMERA_AF_STATUS_RESTART; + } - rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_MAIN_OFFSET, &jpeg_offset); - if (rc < 0) { - ALOGE("%s: Unable to get jpeg offset", __func__); - goto error; - } + rc = exynos_camera_continuous_auto_focus(exynos_camera, current_af); + if (rc < 0) { + ALOGE("%s: Unable to continuous auto focus", __func__); + goto error; + } - rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_THUMB_SIZE, &jpeg_thumbnail_size); - if (rc < 0 || jpeg_thumbnail_size <= 0) { - ALOGE("%s: Unable to get jpeg thumbnail size", __func__); - goto error; - } + if (!decoded) { + buffers_count = 1; + buffers = (struct exynos_camera_buffer *) calloc(buffers_count, sizeof(struct exynos_camera_buffer)); - rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_THUMB_OFFSET, &jpeg_thumbnail_offset); - if (rc < 0) { - ALOGE("%s: Unable to get jpeg thumbnail offset", __func__); - goto error; - } + buffer = buffers; + buffer->pointer = pointer; + buffer->address = address; + buffer->length = buffer_length; + buffer->width = width; + buffer->height = height; + buffer->format = V4L2_PIX_FMT_UYVY; + } else { buffers_count = 2; buffers = (struct exynos_camera_buffer *) calloc(buffers_count, sizeof(struct exynos_camera_buffer)); buffer = buffers; - buffer->pointer = (void *) ((unsigned char *) pointer + jpeg_offset); - buffer->address = address + jpeg_offset; - buffer->length = jpeg_size; - buffer->width = exynos_camera->picture_width; - buffer->height = exynos_camera->picture_height; - buffer->format = V4L2_PIX_FMT_JPEG; + memcpy(pointer, exynos_camera->capture_yuv_buffer, yuv_length); - buffer = (struct exynos_camera_buffer *) ((unsigned char *) buffer + sizeof(struct exynos_camera_buffer)); + buffer->pointer = pointer; + buffer->address = address; + buffer->length = yuv_length; + buffer->width = width; + buffer->height = height; + buffer->format = V4L2_PIX_FMT_UYVY; - buffer->pointer = (void *) ((unsigned char *) pointer + jpeg_thumbnail_offset); - buffer->address = address + jpeg_thumbnail_offset; - buffer->length = jpeg_thumbnail_size; - buffer->width = exynos_camera->jpeg_thumbnail_width; - buffer->height = exynos_camera->jpeg_thumbnail_height; - buffer->format = V4L2_PIX_FMT_JPEG; + memcpy(&exynos_camera->picture_yuv_buffer, buffer, sizeof(struct exynos_camera_buffer)); - break; - default: - buffers_count = 1; - buffers = (struct exynos_camera_buffer *) calloc(buffers_count, sizeof(struct exynos_camera_buffer)); + pointer = (void *) ((unsigned char *) pointer + yuv_length); + address += yuv_length; + buffer = (struct exynos_camera_buffer *) ((unsigned char *) buffer + sizeof(struct exynos_camera_buffer)); - buffer = buffers; + memcpy(pointer, exynos_camera->capture_jpeg_buffer, jpeg_length); buffer->pointer = pointer; buffer->address = address; - buffer->length = buffer_length; - buffer->width = width; - buffer->height = height; - buffer->format = format; - break; - } + buffer->length = jpeg_length; + buffer->width = exynos_camera->picture_width; + buffer->height = exynos_camera->picture_height; + buffer->format = exynos_camera->picture_format; - // Listeners + memcpy(&exynos_camera->picture_jpeg_buffer, buffer, sizeof(struct exynos_camera_buffer)); - list = (struct list_head *) exynos_camera->capture_listeners; - while (list != NULL) { - listener = (struct exynos_camera_capture_listener *) list; + exynos_camera_picture_thread_start(exynos_camera); + + memcpy(buffer, &exynos_camera->picture_yuv_buffer, sizeof(struct exynos_camera_buffer)); + } + } else { + buffers_count = 1; + buffers = (struct exynos_camera_buffer *) calloc(buffers_count, sizeof(struct exynos_camera_buffer)); - if (listener->callback == NULL) - goto list_continue_callback; + buffer = buffers; - /* - * Callback must never call a capture-locked function or it will - * block. Hence, do not unregister the listener in callback. - */ + buffer->pointer = pointer; + buffer->address = address; + buffer->length = buffer_length; + buffer->width = width; + buffer->height = height; + buffer->format = format; - listener->callback(exynos_camera, buffers, buffers_count); + if (exynos_camera->picture_enabled) { + memcpy(&exynos_camera->picture_yuv_buffer, buffer, sizeof(struct exynos_camera_buffer)); + exynos_camera_picture_thread_start(exynos_camera); + } + } -list_continue_callback: - list = list->next; + // Preview + if (exynos_camera->preview_enabled) { + memcpy(&exynos_camera->preview_buffer, buffer, sizeof(struct exynos_camera_buffer)); + if (!exynos_camera->preview_output_enabled) { + rc = exynos_camera_preview_output_start(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to start Preview Output", __func__); + goto error; + } + } + rc = exynos_camera_preview(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to process Camera Preview", __func__); + goto error; + } } - do { - busy = 0; + //Recording + if (exynos_camera->recording_enabled) { + if (exynos_camera->recording_output_enabled) { + memcpy(&exynos_camera->recording_buffer, buffer, sizeof(struct exynos_camera_buffer)); - list = (struct list_head *) exynos_camera->capture_listeners; - while (list != NULL) { - listener = (struct exynos_camera_capture_listener *) list; + exynos_camera->recording_memory_index = index; - if (listener->callback == NULL) - goto list_continue_busy; + rc = exynos_camera_recording(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to process Camera Recording", __func__); + goto error; + } + } else { + memcpy(&exynos_camera->recording_buffer, buffer, sizeof(struct exynos_camera_buffer)); - busy |= listener->busy; + rc = exynos_camera_recording_output_start(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to start recording output", __func__); + goto error; + } -list_continue_busy: - list = list->next; } - - if (busy) - usleep(1000); - } while (busy); + } else { + if (exynos_camera->recording_output_enabled) + exynos_camera_recording_output_stop(exynos_camera); + } rc = exynos_v4l2_qbuf_cap(exynos_camera, 0, index); if (rc < 0) { @@ -1780,6 +1778,28 @@ void *exynos_camera_capture_thread(void *data) return NULL; } +void exynos_camera_picture_thread_start(struct exynos_camera *exynos_camera) +{ + int rc; + + if (exynos_camera->picture_running) + return; + + exynos_camera->picture_completed = 0; + + pthread_attr_t thread_attr; + pthread_attr_init(&thread_attr); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + + rc = pthread_create(&exynos_camera->picture_thread, &thread_attr, exynos_camera_picture, (void *) exynos_camera); + if (rc < 0) + ALOGE("%s: Unable to create thread", __func__); + + exynos_camera->picture_running = 1; + + return; +} + int exynos_camera_capture_thread_start(struct exynos_camera *exynos_camera) { pthread_attr_t thread_attr; @@ -1892,16 +1912,14 @@ int exynos_camera_capture_start(struct exynos_camera *exynos_camera) // V4L2 - if (format == V4L2_PIX_FMT_INTERLEAVED) { + if (!exynos_camera->camera_fimc_is) { ALOGD("Enabling hybrid capture"); rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_HYBRID, 1); if (rc < 0) { ALOGE("%s: Unable to set hybrid", __func__); goto error; } - } - - if (exynos_camera->camera_fimc_is) { + } else { rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_IS_S_FORMAT_SCENARIO, exynos_camera->fimc_is_mode); if (rc < 0) { ALOGE("%s: Unable to set FIMC-IS scenario", __func__); @@ -1950,32 +1968,31 @@ int exynos_camera_capture_start(struct exynos_camera *exynos_camera) ALOGE("%s: Unable to set MBUS capture pixel format", __func__); goto error; } - } - if (format == V4L2_PIX_FMT_INTERLEAVED) rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CACHEABLE, 0); - else - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CACHEABLE, 1); - if (rc < 0) { - ALOGE("%s: Unable to set cacheable", __func__); - goto error; - } - - if (exynos_camera->camera_fimc_is) { - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_IS_S_SCENARIO_MODE, exynos_camera->fimc_is_mode); if (rc < 0) { - ALOGE("%s: Unable to set FIMC-IS scenario mode", __func__); + ALOGE("%s: Unable to set cacheable", __func__); goto error; } - } - if (format == V4L2_PIX_FMT_INTERLEAVED) { // This must be set to 1 for interleaved data decoding rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_EMBEDDEDDATA_ENABLE, 1); if (rc < 0) { ALOGE("%s: Unable to set embdedded data enable", __func__); goto error; } + } else { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CACHEABLE, 1); + if (rc < 0) { + ALOGE("%s: Unable to set cacheable", __func__); + goto error; + } + + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_IS_S_SCENARIO_MODE, exynos_camera->fimc_is_mode); + if (rc < 0) { + ALOGE("%s: Unable to set FIMC-IS scenario mode", __func__); + goto error; + } } // Let's assume FIMC0 has memory available through mmap @@ -2047,13 +2064,13 @@ int exynos_camera_capture_start(struct exynos_camera *exynos_camera) goto error; } - if (format == V4L2_PIX_FMT_INTERLEAVED) { + if (!exynos_camera->camera_fimc_is) { exynos_camera->capture_yuv_buffer = malloc(buffer_length); exynos_camera->capture_jpeg_buffer = malloc(buffer_length); } // Start EXIF - memset(&exynos_camera->exif, 0, sizeof(exynos_camera->exif)); + memset(&exynos_camera->exif, 0, sizeof(struct exynos_exif)); exynos_exif_start(exynos_camera, &exynos_camera->exif); for (i = 0; i < buffers_count; i++) { @@ -2120,7 +2137,6 @@ error: exynos_camera->face_data->release(exynos_camera->face_data); exynos_camera->face_data = NULL; } - if (exynos_camera->capture_memory != NULL && exynos_camera->capture_memory->release != NULL) { exynos_camera->capture_memory->release(exynos_camera->capture_memory); exynos_camera->capture_memory = NULL; @@ -2147,7 +2163,7 @@ void exynos_camera_capture_stop(struct exynos_camera *exynos_camera) return; } - if (exynos_camera->capture_format == V4L2_PIX_FMT_INTERLEAVED) { + if (!exynos_camera->camera_fimc_is) { ALOGD("Disabling hybrid capture"); rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_HYBRID, 0); if (rc < 0) @@ -2185,18 +2201,14 @@ void exynos_camera_capture_stop(struct exynos_camera *exynos_camera) exynos_camera->capture_jpeg_buffer = NULL; } - if (&exynos_camera->exif != NULL) { + if (&exynos_camera->exif.enabled) exynos_exif_stop(exynos_camera, &exynos_camera->exif); - free(&exynos_camera->exif); - } exynos_camera->capture_enabled = 0; } int exynos_camera_capture_setup(struct exynos_camera *exynos_camera) { - struct exynos_camera_capture_listener *listener; - struct list_head *list; int width, height, format; int rc; @@ -2205,42 +2217,10 @@ int exynos_camera_capture_setup(struct exynos_camera *exynos_camera) ALOGD("%s()", __func__); - // No listener left - if (exynos_camera->capture_listeners == NULL && exynos_camera->capture_enabled) { - exynos_camera_capture_stop(exynos_camera); - return 0; - } - - width = height = format = 0; - - list = (struct list_head *) exynos_camera->capture_listeners; - while (list != NULL) { - listener = (struct exynos_camera_capture_listener *) list; + format = exynos_camera->camera_capture_format; - // Interleaved format already has the correct width and height for picture set through ioctl - if (exynos_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED) - if (listener->format == V4L2_PIX_FMT_JPEG || listener->format == V4L2_PIX_FMT_INTERLEAVED) - goto list_continue; - - if (listener->width >= width && listener->height >= height) { - width = listener->width; - height = listener->height; - format = listener->format; - } - -list_continue: - list = list->next; - } - - // Override the capture format - if (exynos_camera->camera_capture_format) - format = exynos_camera->camera_capture_format; - - // Only picture is listening, but we need some preview size anyway - if (format == V4L2_PIX_FMT_INTERLEAVED && (width == 0 || height == 0)) { - width = exynos_camera->preview_width; - height = exynos_camera->preview_height; - } + width = exynos_camera->preview_width; + height = exynos_camera->preview_height; ALOGD("%s: Selected width: %d, height: %d, format: 0x%x", __func__, width, height, format); @@ -2271,99 +2251,6 @@ list_continue: return 0; } -struct exynos_camera_capture_listener *exynos_camera_capture_listener_register( - struct exynos_camera *exynos_camera, int width, int height, int format, - int (*callback)(struct exynos_camera *exynos_camera, struct exynos_camera_buffer *buffers, int buffers_count)) -{ - struct exynos_camera_capture_listener *listener = NULL; - struct list_head *list_end; - struct list_head *list; - int rc; - - if (exynos_camera == NULL || callback == NULL) - return NULL; - - pthread_mutex_lock(&exynos_camera->capture_mutex); - - listener = calloc(1, sizeof(struct exynos_camera_capture_listener)); - if (listener == NULL) - goto error; - - listener->width = width; - listener->height = height; - listener->format = format; - listener->callback = callback; - listener->busy = 0; - - list_end = (struct list_head *) exynos_camera->capture_listeners; - while (list_end != NULL && list_end->next != NULL) - list_end = list_end->next; - - list = (struct list_head *) listener; - list_head_insert(list, list_end, NULL); - - if (exynos_camera->capture_listeners == NULL) - exynos_camera->capture_listeners = listener; - - if (!(exynos_camera->camera_fimc_is && exynos_camera->picture_thread_enabled)) { - rc = exynos_camera_capture_setup(exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to setup capture", __func__); - goto error; - } - } - - rc = 0; - goto complete; - -error: - listener = NULL; - -complete: - pthread_mutex_unlock(&exynos_camera->capture_mutex); - - return listener; -} - -void exynos_camera_capture_listener_unregister( - struct exynos_camera *exynos_camera, - struct exynos_camera_capture_listener *listener) -{ - struct list_head *list; - int rc; - - if (exynos_camera == NULL || listener == NULL) - return; - - pthread_mutex_lock(&exynos_camera->capture_mutex); - - list = (struct list_head *) exynos_camera->capture_listeners; - while (list != NULL) { - if ((void *) list == (void *) listener) { - list_head_remove(list); - - if ((void *) list == (void *) exynos_camera->capture_listeners) - exynos_camera->capture_listeners = (struct exynos_camera_capture_listener *) list->next; - - memset(listener, 0, sizeof(struct exynos_camera_capture_listener)); - free(listener); - - break; - } -list_continue: - list = list->next; - } - - rc = exynos_camera_capture_setup(exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to setup capture", __func__); - goto complete; - } - -complete: - pthread_mutex_unlock(&exynos_camera->capture_mutex); -} - // Preview int exynos_camera_preview_output_start(struct exynos_camera *exynos_camera) @@ -2432,118 +2319,9 @@ void exynos_camera_preview_output_stop(struct exynos_camera *exynos_camera) exynos_camera->preview_output_enabled = 0; } -int exynos_camera_preview_callback(struct exynos_camera *exynos_camera, - struct exynos_camera_buffer *buffers, int buffers_count) +int exynos_camera_preview(struct exynos_camera *exynos_camera) { - struct exynos_camera_buffer *buffer = NULL; - int width, height, format; - int buffer_width, buffer_height, buffer_format; - int rc; - int i; - - if (exynos_camera == NULL || buffers == NULL || buffers_count <= 0) - return -EINVAL; - -// ALOGD("%s()", __func__); - - if (exynos_camera->preview_listener == NULL) - return -1; - - if (exynos_camera->preview_listener->busy) { - ALOGE("%s: Dropping buffer", __func__); - return 0; - } - - exynos_camera->preview_listener->busy = 1; - - width = exynos_camera->preview_width; - height = exynos_camera->preview_height; - format = exynos_camera->preview_format; - - for (i = 0; i < buffers_count; i++) { - if (buffers->format == V4L2_PIX_FMT_JPEG) - goto buffers_continue; - - if (buffers->format == V4L2_PIX_FMT_INTERLEAVED) - goto buffers_continue; - - // Optimal buffer - if (buffers->width == width && buffers->height == height) { - buffer = buffers; - break; - } - - // Might-work buffer, but not optimal - buffer = buffers; - -buffers_continue: - buffers = (struct exynos_camera_buffer *) ((unsigned char *) buffers + sizeof(struct exynos_camera_buffer)); - } - - if (buffer == NULL) { - ALOGE("%s: Unable to find an appropriate buffer for preview", __func__); - exynos_camera->preview_listener->busy = 0; - return 0; - } - - buffer_width = buffer->width; - buffer_height = buffer->height; - buffer_format = buffer->format; - - pthread_mutex_lock(&exynos_camera->preview_mutex); - - if (buffer_width != width || buffer_height != height || buffer_format != format) { - if (!exynos_camera->preview_output_enabled) { - memcpy(&exynos_camera->preview_buffer, buffer, sizeof(struct exynos_camera_buffer)); - - rc = exynos_camera_preview_output_start(exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to start preview", __func__); - goto error; - } - } else if (exynos_camera->preview_buffer.width != buffer_width || exynos_camera->preview_buffer.height != buffer_height || exynos_camera->preview_buffer.format != buffer_format) { - exynos_camera_preview_output_stop(exynos_camera); - - memcpy(&exynos_camera->preview_buffer, buffer, sizeof(struct exynos_camera_buffer)); - - rc = exynos_camera_preview_output_start(exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to start preview", __func__); - goto error; - } - } else { - memcpy(&exynos_camera->preview_buffer, buffer, sizeof(struct exynos_camera_buffer)); - } - } else { - // The buffer format exactly matches our expectations - - if (exynos_camera->preview_output_enabled) - exynos_camera_preview_output_stop(exynos_camera); - - memcpy(&exynos_camera->preview_buffer, buffer, sizeof(struct exynos_camera_buffer)); - } - - pthread_mutex_unlock(&exynos_camera->preview_lock_mutex); - - pthread_mutex_unlock(&exynos_camera->preview_mutex); - - rc = 0; - goto complete; - -error: - pthread_mutex_unlock(&exynos_camera->preview_mutex); - - exynos_camera->preview_listener->busy = 0; - - rc = -1; - -complete: - return rc; -} - -int exynos_camera_preview(struct exynos_camera *exynos_camera) -{ - struct exynos_v4l2_output *output; + struct exynos_v4l2_output *output; int width, height, format; buffer_handle_t *window_buffer; void *window_data; @@ -2558,7 +2336,7 @@ int exynos_camera_preview(struct exynos_camera *exynos_camera) if (exynos_camera == NULL) goto error; -// ALOGD("%s()", __func__); +// ALOGD("%s()", __func__); width = exynos_camera->preview_width; height = exynos_camera->preview_height; @@ -2628,109 +2406,29 @@ error: rc = -1; complete: - exynos_camera->preview_listener->busy = 0; - return rc; } -void *exynos_camera_preview_thread(void *data) -{ - struct exynos_camera *exynos_camera; - int rc; - - if (data == NULL) - return NULL; - - exynos_camera = (struct exynos_camera *) data; - - ALOGE("%s: Starting thread", __func__); - exynos_camera->preview_thread_running = 1; - - while (exynos_camera->preview_thread_enabled) { - pthread_mutex_lock(&exynos_camera->preview_lock_mutex); - - pthread_mutex_lock(&exynos_camera->preview_mutex); - - if (exynos_camera->preview_listener == NULL) { - pthread_mutex_unlock(&exynos_camera->preview_mutex); - break; - } - - if (exynos_camera->preview_listener->busy) { - // Prevent preview restart race conditions - usleep((useconds_t)25 * 1000); - rc = exynos_camera_preview(exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to preview", __func__); - pthread_mutex_unlock(&exynos_camera->preview_mutex); - break; - } - } - - pthread_mutex_unlock(&exynos_camera->preview_mutex); - } - - exynos_camera->preview_thread_running = 0; - ALOGE("%s: Exiting thread", __func__); - - return NULL; -} - -int exynos_camera_preview_thread_start(struct exynos_camera *exynos_camera) +int exynos_camera_preview_start(struct exynos_camera *exynos_camera) { - struct exynos_camera_capture_listener *listener; - pthread_attr_t thread_attr; - int rc; - if (exynos_camera == NULL) return -EINVAL; ALOGD("%s()", __func__); - if (exynos_camera->preview_thread_enabled) { - ALOGE("Preview thread was already started!"); + if (exynos_camera->preview_enabled) { + ALOGE("Preview was already started!"); return -1; } - pthread_mutex_init(&exynos_camera->preview_mutex, NULL); - pthread_mutex_init(&exynos_camera->preview_lock_mutex, NULL); + exynos_camera_capture_setup(exynos_camera); - // Initial lock - pthread_mutex_lock(&exynos_camera->preview_lock_mutex); + exynos_camera->preview_enabled = 1; - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - - exynos_camera->preview_thread_enabled = 1; - - rc = pthread_create(&exynos_camera->preview_thread, &thread_attr, exynos_camera_preview_thread, (void *) exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to create thread", __func__); - goto error; - } - - listener = exynos_camera_capture_listener_register(exynos_camera, exynos_camera->preview_width, exynos_camera->preview_height, exynos_camera->preview_format, exynos_camera_preview_callback); - if (listener == NULL) { - ALOGE("%s: Unable to register preview capture listener", __func__); - goto error; - } - - exynos_camera->preview_listener = listener; - - rc = 0; - goto complete; - -error: - pthread_mutex_destroy(&exynos_camera->preview_mutex); - pthread_mutex_destroy(&exynos_camera->preview_lock_mutex); - - rc = -1; - -complete: - return rc; + return 0; } -void exynos_camera_preview_thread_stop(struct exynos_camera *exynos_camera) +void exynos_camera_preview_stop(struct exynos_camera *exynos_camera) { int i; @@ -2739,185 +2437,32 @@ void exynos_camera_preview_thread_stop(struct exynos_camera *exynos_camera) ALOGD("%s()", __func__); - if (!exynos_camera->preview_thread_enabled) { - ALOGE("Preview thread was already stopped!"); + if (!exynos_camera->preview_enabled) { + ALOGE("Preview was already stopped!"); return; } - if (exynos_camera->preview_listener != NULL) { - exynos_camera_capture_listener_unregister(exynos_camera, exynos_camera->preview_listener); - exynos_camera->preview_listener = NULL; - } - - exynos_camera->preview_thread_enabled = 0; + exynos_camera->preview_enabled = 0; - pthread_mutex_unlock(&exynos_camera->preview_lock_mutex); - - // Wait for the thread to end - i = 0; - while (exynos_camera->preview_thread_running) { - if (i++ > 10000) { - ALOGE("Preview thread is taking too long to end, something is going wrong"); - break; - } - usleep(100); + if (exynos_camera->capture_enabled) { + pthread_mutex_lock(&exynos_camera->capture_mutex); + exynos_camera_capture_stop(exynos_camera); + pthread_mutex_unlock(&exynos_camera->capture_mutex); } - if (exynos_camera->preview_output_enabled) { - pthread_mutex_lock(&exynos_camera->preview_mutex); + if (exynos_camera->preview_output_enabled) exynos_camera_preview_output_stop(exynos_camera); - pthread_mutex_unlock(&exynos_camera->preview_mutex); - } - pthread_mutex_destroy(&exynos_camera->preview_mutex); - pthread_mutex_destroy(&exynos_camera->preview_lock_mutex); - - // Invalidate the preview window exynos_camera->preview_window = NULL; } // Picture -int exynos_camera_picture_callback(struct exynos_camera *exynos_camera, - struct exynos_camera_buffer *buffers, int buffers_count) -{ - struct exynos_camera_buffer *jpeg_buffer = NULL; - struct exynos_camera_buffer *jpeg_thumbnail_buffer = NULL; - struct exynos_camera_buffer *yuv_buffer = NULL; - struct exynos_camera_buffer *yuv_thumbnail_buffer = NULL; - int width, height; - int thumbnail_width, thumbnail_height; - int rc; - int i; - - if (exynos_camera == NULL || buffers == NULL || buffers_count <= 0) - return -EINVAL; - -// ALOGD("%s()", __func__); - - width = exynos_camera->picture_width; - height = exynos_camera->picture_height; - thumbnail_width = exynos_camera->jpeg_thumbnail_width; - thumbnail_height = exynos_camera->jpeg_thumbnail_height; - - if (exynos_camera->picture_completed) - return -1; - - if (exynos_camera->picture_listener == NULL) - return -1; - - if (exynos_camera->picture_listener->busy) { - ALOGE("%s: Dropping buffer", __func__); - return 0; - } - - pthread_mutex_lock(&exynos_camera->picture_mutex); - - if (!exynos_camera->picture_enabled && !exynos_camera->camera_fimc_is) { - - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_CAPTURE, 0); - if (rc < 0) { - ALOGE("%s: Unable to set capture", __func__); - goto error; - } - - if (exynos_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED && !exynos_camera->capture_hybrid) { - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_HYBRID_CAPTURE, 1); - if (rc < 0) { - ALOGE("%s: Unable to set hybrid capture", __func__); - goto error; - } - - exynos_camera->capture_hybrid = 1; - } - - exynos_camera->picture_enabled = 1; - - pthread_mutex_unlock(&exynos_camera->picture_mutex); - return 0; - } - - pthread_mutex_unlock(&exynos_camera->picture_mutex); - - exynos_camera->picture_listener->busy = 1; - - // Let's assume the picture format is JPEG - - for (i = 0; i < buffers_count; i++) { - if (buffers->format == V4L2_PIX_FMT_JPEG) { - if (buffers->width == width && buffers->height == height) - jpeg_buffer = buffers; - else if (buffers->width == thumbnail_width && buffers->height == thumbnail_height) - jpeg_thumbnail_buffer = buffers; - } else { - if ((buffers->width >= width && buffers->height >= height) || exynos_camera->camera_fimc_is) - yuv_buffer = buffers; - if (buffers->width >= thumbnail_width && buffers->height >= thumbnail_height) - yuv_thumbnail_buffer = buffers; - } - -buffers_continue: - buffers = (struct exynos_camera_buffer *) ((unsigned char *) buffers + sizeof(struct exynos_camera_buffer)); - } - - if (jpeg_buffer == NULL && yuv_buffer == NULL) { -// ALOGE("%s: Unable to find an appropriate buffer for picture", __func__); - exynos_camera->picture_listener->busy = 0; - return 0; - } - - // Interleaved must not use a preview frame as picture - if (exynos_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED && jpeg_buffer == NULL) { - exynos_camera->picture_listener->busy = 0; - return 0; - } - - pthread_mutex_lock(&exynos_camera->picture_mutex); - - if (jpeg_buffer == NULL) - memset(&exynos_camera->picture_jpeg_buffer, 0, sizeof(exynos_camera->picture_jpeg_buffer)); - else - memcpy(&exynos_camera->picture_jpeg_buffer, jpeg_buffer, sizeof(struct exynos_camera_buffer)); - - if (jpeg_thumbnail_buffer == NULL) - memset(&exynos_camera->picture_jpeg_thumbnail_buffer, 0, sizeof(exynos_camera->picture_jpeg_thumbnail_buffer)); - else - memcpy(&exynos_camera->picture_jpeg_thumbnail_buffer, jpeg_thumbnail_buffer, sizeof(struct exynos_camera_buffer)); - - if (yuv_buffer == NULL) - memset(&exynos_camera->picture_yuv_buffer, 0, sizeof(exynos_camera->picture_yuv_buffer)); - else - memcpy(&exynos_camera->picture_yuv_buffer, yuv_buffer, sizeof(struct exynos_camera_buffer)); - - if (yuv_thumbnail_buffer == NULL) - memset(&exynos_camera->picture_yuv_thumbnail_buffer, 0, sizeof(exynos_camera->picture_yuv_thumbnail_buffer)); - else - memcpy(&exynos_camera->picture_yuv_thumbnail_buffer, yuv_thumbnail_buffer, sizeof(struct exynos_camera_buffer)); - - pthread_mutex_unlock(&exynos_camera->picture_lock_mutex); - - pthread_mutex_unlock(&exynos_camera->picture_mutex); - - rc = 0; - goto complete; - -error: - pthread_mutex_unlock(&exynos_camera->picture_mutex); - - exynos_camera->picture_listener->busy = 0; - - rc = -1; - -complete: - return rc; -} - -int exynos_camera_picture(struct exynos_camera *exynos_camera) +void *exynos_camera_picture(void *data) { + struct exynos_camera *exynos_camera; struct exynos_camera_buffer *jpeg_buffer; - struct exynos_camera_buffer *jpeg_thumbnail_buffer; struct exynos_camera_buffer *yuv_buffer; - struct exynos_camera_buffer *yuv_thumbnail_buffer; struct exynos_v4l2_output output; struct exynos_jpeg jpeg; int output_enabled = 0; @@ -2933,45 +2478,34 @@ int exynos_camera_picture(struct exynos_camera *exynos_camera) void *jpeg_thumbnail_data = NULL; int jpeg_thumbnail_size = 0; void *yuv_data = NULL; - int yuv_address; + int yuv_address = 0; int yuv_size = 0; void *yuv_thumbnail_data = NULL; int yuv_thumbnail_address; int yuv_thumbnail_size = 0; int rc; + exynos_camera = (struct exynos_camera *) data; + if (exynos_camera == NULL) goto error; -// ALOGD("%s()", __func__); + ALOGD("%s()", __func__); jpeg_buffer = &exynos_camera->picture_jpeg_buffer; - jpeg_thumbnail_buffer = &exynos_camera->picture_jpeg_thumbnail_buffer; yuv_buffer = &exynos_camera->picture_yuv_buffer; - yuv_thumbnail_buffer = &exynos_camera->picture_yuv_thumbnail_buffer; if (jpeg_buffer->pointer != NULL && jpeg_buffer->length > 0) { jpeg_data = jpeg_buffer->pointer; jpeg_size = jpeg_buffer->length; } - if (jpeg_thumbnail_buffer->pointer != NULL && jpeg_thumbnail_buffer->length > 0) { - jpeg_thumbnail_data = jpeg_thumbnail_buffer->pointer; - jpeg_thumbnail_size = jpeg_thumbnail_buffer->length; - } - if (yuv_buffer->pointer != NULL && yuv_buffer->length > 0) { yuv_data = yuv_buffer->pointer; yuv_address = yuv_buffer->address; yuv_size = yuv_buffer->length; } - if (yuv_thumbnail_buffer->pointer != NULL && yuv_thumbnail_buffer->length > 0) { - yuv_thumbnail_data = yuv_thumbnail_buffer->pointer; - yuv_thumbnail_address = yuv_thumbnail_buffer->address; - yuv_thumbnail_size = yuv_thumbnail_buffer->length; - } - // JPEG if (jpeg_data == NULL) { @@ -3080,108 +2614,108 @@ int exynos_camera_picture(struct exynos_camera *exynos_camera) // Thumbnail - if (jpeg_thumbnail_data == NULL) { - if (yuv_thumbnail_data == NULL || yuv_thumbnail_size <= 0) { - ALOGE("%s: Unable to create jpeg thumbnail without an YUV buffer", __func__); - goto error; - } - - width = exynos_camera->jpeg_thumbnail_width; - height = exynos_camera->jpeg_thumbnail_height; - format = yuv_thumbnail_buffer->format; - - buffer_width = yuv_thumbnail_buffer->width; - buffer_height = yuv_thumbnail_buffer->height; - buffer_format = yuv_thumbnail_buffer->format; - buffer_address = yuv_thumbnail_buffer->address; + if (yuv_data == NULL || yuv_size <= 0) { + ALOGE("%s: Unable to create jpeg thumbnail without an YUV buffer", __func__); + goto error; + } - if (width != buffer_width && height != buffer_height) { - format = EXYNOS_CAMERA_PICTURE_OUTPUT_FORMAT; + width = exynos_camera->jpeg_thumbnail_width; + height = exynos_camera->jpeg_thumbnail_height; + format = yuv_buffer->format; - memset(&output, 0, sizeof(output)); - output.v4l2_id = 2; - output.width = width; - output.height = height; - output.format = format; - output.buffer_width = buffer_width; - output.buffer_height = buffer_height; - output.buffer_format = buffer_format; - output.buffers_count = 1; + buffer_width = yuv_buffer->width; + buffer_height = yuv_buffer->height; + buffer_format = yuv_buffer->format; + buffer_address = yuv_buffer->address; - rc = exynos_v4l2_output_start(exynos_camera, &output); - if (rc < 0) { - ALOGE("%s: Unable to start thumbnail picture output", __func__); - goto error; - } + if (width != buffer_width && height != buffer_height) { + format = EXYNOS_CAMERA_PICTURE_OUTPUT_FORMAT; - output_enabled = 1; + memset(&output, 0, sizeof(output)); + output.v4l2_id = 2; + output.width = width; + output.height = height; + output.format = format; + output.buffer_width = buffer_width; + output.buffer_height = buffer_height; + output.buffer_format = buffer_format; + output.buffers_count = 1; - rc = exynos_v4l2_output(exynos_camera, &output, buffer_address); - if (rc < 0) { - ALOGE("%s: Unable to output thumbnail picture", __func__); - goto error; - } - - yuv_thumbnail_data = output.memory->data; - yuv_thumbnail_address = output.memory_address; - yuv_thumbnail_size = output.buffer_length; + rc = exynos_v4l2_output_start(exynos_camera, &output); + if (rc < 0) { + ALOGE("%s: Unable to start thumbnail picture output", __func__); + goto error; } - memset(&jpeg, 0, sizeof(jpeg)); - jpeg.width = width; - jpeg.height = height; - jpeg.format = format; - jpeg.quality = exynos_camera->jpeg_thumbnail_quality; + output_enabled = 1; - rc = exynos_jpeg_start(exynos_camera, &jpeg); + rc = exynos_v4l2_output(exynos_camera, &output, buffer_address); if (rc < 0) { - ALOGE("%s: Unable to start jpeg", __func__); + ALOGE("%s: Unable to output thumbnail picture", __func__); goto error; } - if (jpeg.memory_in_pointer == NULL) { - ALOGE("%s: Invalid memory input pointer", __func__); - goto error; - } + yuv_thumbnail_data = output.memory->data; + yuv_thumbnail_address = output.memory_address; + yuv_thumbnail_size = output.buffer_length; + } - memcpy(jpeg.memory_in_pointer, yuv_thumbnail_data, yuv_thumbnail_size); + memset(&jpeg, 0, sizeof(jpeg)); + jpeg.width = width; + jpeg.height = height; + jpeg.format = format; + jpeg.quality = exynos_camera->jpeg_thumbnail_quality; - rc = exynos_jpeg(exynos_camera, &jpeg); - if (rc < 0) { - ALOGE("%s: Unable to jpeg", __func__); - goto error; - } + rc = exynos_jpeg_start(exynos_camera, &jpeg); + if (rc < 0) { + ALOGE("%s: Unable to start jpeg", __func__); + goto error; + } - jpeg_thumbnail_size = jpeg.memory_out_size; - if (jpeg_thumbnail_size <= 0) { - ALOGE("%s: Invalid jpeg size", __func__); - goto error; - } + if (jpeg.memory_in_pointer == NULL) { + ALOGE("%s: Invalid memory input pointer", __func__); + goto error; + } + + memcpy(jpeg.memory_in_pointer, yuv_thumbnail_data, yuv_thumbnail_size); + + rc = exynos_jpeg(exynos_camera, &jpeg); + if (rc < 0) { + ALOGE("%s: Unable to jpeg", __func__); + goto error; + } - if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { - jpeg_thumbnail_memory = exynos_camera->callbacks.request_memory(-1, jpeg_thumbnail_size, 1, exynos_camera->callbacks.user); - if (jpeg_thumbnail_memory == NULL || jpeg_thumbnail_memory->data == NULL || jpeg_thumbnail_memory->data == MAP_FAILED) { - ALOGE("%s: Unable to request memory", __func__); - goto error; - } - } else { - ALOGE("%s: No memory request function!", __func__); + jpeg_thumbnail_size = jpeg.memory_out_size; + if (jpeg_thumbnail_size <= 0) { + ALOGE("%s: Invalid jpeg size", __func__); + goto error; + } + + if (EXYNOS_CAMERA_CALLBACK_DEFINED(request_memory)) { + jpeg_thumbnail_memory = exynos_camera->callbacks.request_memory(-1, jpeg_thumbnail_size, 1, exynos_camera->callbacks.user); + if (jpeg_thumbnail_memory == NULL || jpeg_thumbnail_memory->data == NULL || jpeg_thumbnail_memory->data == MAP_FAILED) { + ALOGE("%s: Unable to request memory", __func__); goto error; } + } else { + ALOGE("%s: No memory request function!", __func__); + goto error; + } - jpeg_thumbnail_data = jpeg_thumbnail_memory->data; + jpeg_thumbnail_data = jpeg_thumbnail_memory->data; - memcpy(jpeg_thumbnail_data, jpeg.memory_out_pointer, jpeg_thumbnail_size); + memcpy(jpeg_thumbnail_data, jpeg.memory_out_pointer, jpeg_thumbnail_size); - exynos_jpeg_stop(exynos_camera, &jpeg); + exynos_jpeg_stop(exynos_camera, &jpeg); - if (output_enabled) { - exynos_v4l2_output_stop(exynos_camera, &output); - output_enabled = 0; - } + if (output_enabled) { + exynos_v4l2_output_stop(exynos_camera, &output); + output_enabled = 0; } // EXIF + exynos_exif_create(exynos_camera, &exynos_camera->exif); + exynos_camera->exif.jpeg_thumbnail_data = jpeg_thumbnail_data; exynos_camera->exif.jpeg_thumbnail_size = jpeg_thumbnail_size; @@ -3219,7 +2753,6 @@ int exynos_camera_picture(struct exynos_camera *exynos_camera) exynos_camera->picture_memory = memory; - rc = 0; goto complete; error: @@ -3234,8 +2767,6 @@ error: if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_ERROR) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify) && !exynos_camera->callback_lock) exynos_camera->callbacks.notify(CAMERA_MSG_ERROR, -1, 0, exynos_camera->callbacks.user); - rc = -1; - complete: if (jpeg_memory != NULL && jpeg_memory->release != NULL) jpeg_memory->release(jpeg_memory); @@ -3243,64 +2774,17 @@ complete: if (jpeg_thumbnail_memory != NULL && jpeg_thumbnail_memory->release != NULL) jpeg_thumbnail_memory->release(jpeg_thumbnail_memory); - exynos_camera->picture_completed = 1; - exynos_camera->picture_listener->busy = 0; - - return rc; -} - -void *exynos_camera_picture_thread(void *data) -{ - struct exynos_camera *exynos_camera; - int rc; - - if (data == NULL) - return NULL; - - exynos_camera = (struct exynos_camera *) data; - - ALOGE("%s: Starting thread", __func__); - exynos_camera->picture_thread_running = 1; - - while (exynos_camera->picture_thread_enabled) { - pthread_mutex_lock(&exynos_camera->picture_lock_mutex); - - pthread_mutex_lock(&exynos_camera->picture_mutex); - - if (exynos_camera->picture_listener == NULL) { - pthread_mutex_unlock(&exynos_camera->picture_mutex); - break; - } - - if (exynos_camera->picture_listener->busy) { - rc = exynos_camera_picture(exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to take picture", __func__); - pthread_mutex_unlock(&exynos_camera->picture_mutex); - break; - } - } - - pthread_mutex_unlock(&exynos_camera->picture_mutex); - if (exynos_camera->picture_completed) { - exynos_camera->picture_thread_running = 0; - exynos_camera_picture_thread_stop(exynos_camera); - break; - } - } + exynos_camera->picture_completed = 1; - exynos_camera->picture_thread_running = 0; - ALOGE("%s: Exiting thread", __func__); + exynos_camera_picture_stop(exynos_camera); + exynos_camera->picture_running = 0; return NULL; } -int exynos_camera_picture_thread_start(struct exynos_camera *exynos_camera) +int exynos_camera_picture_start(struct exynos_camera *exynos_camera) { - struct exynos_camera_capture_listener *listener; - pthread_attr_t thread_attr; - int format; int rc; if (exynos_camera == NULL) @@ -3308,101 +2792,47 @@ int exynos_camera_picture_thread_start(struct exynos_camera *exynos_camera) ALOGD("%s()", __func__); - if (exynos_camera->picture_thread_enabled) { - ALOGE("Picture thread was already started!"); + if (exynos_camera->picture_enabled) { + ALOGE("Picture was already started!"); return 0; } - if (exynos_camera->camera_picture_format) - format = exynos_camera->camera_picture_format; - else - format = exynos_camera->picture_format; - - pthread_mutex_init(&exynos_camera->picture_mutex, NULL); - pthread_mutex_init(&exynos_camera->picture_lock_mutex, NULL); - - // Initial lock - pthread_mutex_lock(&exynos_camera->picture_lock_mutex); - - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - - exynos_camera->picture_thread_enabled = 1; - - rc = pthread_create(&exynos_camera->picture_thread, &thread_attr, exynos_camera_picture_thread, (void *) exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to create thread", __func__); - goto error; - } - - exynos_camera->picture_completed = 0; + if (!exynos_camera->camera_fimc_is) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_CAPTURE, 0); + if (rc < 0) { + ALOGE("%s: Unable to set capture", __func__); + return -1; + } - listener = exynos_camera_capture_listener_register(exynos_camera, exynos_camera->picture_width, exynos_camera->picture_height, format, exynos_camera_picture_callback); - if (listener == NULL) { - ALOGE("%s: Unable to register picture capture listener", __func__); - goto error; + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_HYBRID_CAPTURE, 1); + if (rc < 0) { + ALOGE("%s: Unable to set hybrid capture", __func__); + return -1; + } } - exynos_camera->picture_listener = listener; - - rc = 0; - goto complete; - -error: - pthread_mutex_destroy(&exynos_camera->picture_mutex); - pthread_mutex_destroy(&exynos_camera->picture_lock_mutex); - - rc = -1; + exynos_camera->picture_enabled = 1; -complete: - return rc; + return 0; } -void exynos_camera_picture_thread_stop(struct exynos_camera *exynos_camera) +void exynos_camera_picture_stop(struct exynos_camera *exynos_camera) { camera_memory_t *memory; - int i; + int rc, i; if (exynos_camera == NULL) return; ALOGD("%s()", __func__); - if (!exynos_camera->picture_thread_enabled) { - ALOGE("Picture thread was already stopped!"); + if (!exynos_camera->picture_enabled) { + ALOGE("Picture was already stopped!"); return; } memory = exynos_camera->picture_memory; - if (exynos_camera->picture_listener != NULL) { - exynos_camera_capture_listener_unregister(exynos_camera, exynos_camera->picture_listener); - exynos_camera->picture_listener = NULL; - } - - exynos_camera->picture_thread_enabled = 0; - - pthread_mutex_unlock(&exynos_camera->picture_lock_mutex); - - // Wait for the thread to end - i = 0; - while (exynos_camera->picture_thread_running) { - if (i++ > 10000) { - ALOGE("Picture thread is taking too long to end, something is going wrong"); - break; - } - usleep(100); - } - - if (exynos_camera->picture_enabled) { - pthread_mutex_lock(&exynos_camera->picture_mutex); - exynos_camera->picture_enabled = 0; - pthread_mutex_unlock(&exynos_camera->picture_mutex); - } - - pthread_mutex_destroy(&exynos_camera->picture_mutex); - pthread_mutex_destroy(&exynos_camera->picture_lock_mutex); - if (exynos_camera->picture_completed && memory != NULL) { // It is important to return at this point (and not before) for burst @@ -3417,6 +2847,12 @@ void exynos_camera_picture_thread_stop(struct exynos_camera *exynos_camera) exynos_camera->picture_memory = NULL; } } + + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, AE_UNLOCK_AWB_UNLOCK); + if (rc < 0) + ALOGE("%s: Unable to set AEAWB lock", __func__); + + exynos_camera->picture_enabled = 0; } // Recording @@ -3487,106 +2923,6 @@ void exynos_camera_recording_output_stop(struct exynos_camera *exynos_camera) exynos_camera->recording_output_enabled = 0; } -int exynos_camera_recording_callback(struct exynos_camera *exynos_camera, - struct exynos_camera_buffer *buffers, int buffers_count) -{ - struct exynos_camera_buffer *buffer = NULL; - int width, height, format; - int buffer_width, buffer_height, buffer_format; - int rc; - int i; - - if (exynos_camera == NULL || buffers == NULL || buffers_count <= 0) - return -EINVAL; - -// ALOGD("%s()", __func__); - - if (exynos_camera->recording_listener == NULL) - return -1; - - if (exynos_camera->recording_listener->busy) { - ALOGE("%s: Dropping buffer", __func__); - return 0; - } - - exynos_camera->recording_listener->busy = 1; - - width = exynos_camera->recording_width; - height = exynos_camera->recording_height; - format = exynos_camera->recording_format; - - for (i = 0; i < buffers_count; i++) { - if (buffers->format == V4L2_PIX_FMT_JPEG) - goto buffers_continue; - - if (buffers->format == V4L2_PIX_FMT_INTERLEAVED) - goto buffers_continue; - - // Optimal buffer - if (buffers->width == width && buffers->height == height) { - buffer = buffers; - break; - } - - // Might-work buffer, but not optimal - buffer = buffers; - -buffers_continue: - buffers = (struct exynos_camera_buffer *) ((unsigned char *) buffers + sizeof(struct exynos_camera_buffer)); - } - - if (buffer == NULL) { - ALOGE("%s: Unable to find an appropriate buffer for recording", __func__); - exynos_camera->recording_listener->busy = 0; - return 0; - } - - buffer_width = buffer->width; - buffer_height = buffer->height; - buffer_format = buffer->format; - - pthread_mutex_lock(&exynos_camera->recording_mutex); - - if (!exynos_camera->recording_output_enabled) { - memcpy(&exynos_camera->recording_buffer, buffer, sizeof(struct exynos_camera_buffer)); - - rc = exynos_camera_recording_output_start(exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to start recording", __func__); - goto error; - } - } else if (exynos_camera->recording_buffer.width != buffer_width || exynos_camera->recording_buffer.height != buffer_height || exynos_camera->recording_buffer.format != buffer_format) { - exynos_camera_recording_output_stop(exynos_camera); - - memcpy(&exynos_camera->recording_buffer, buffer, sizeof(struct exynos_camera_buffer)); - - rc = exynos_camera_recording_output_start(exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to start recording", __func__); - goto error; - } - } else { - memcpy(&exynos_camera->recording_buffer, buffer, sizeof(struct exynos_camera_buffer)); - } - - pthread_mutex_unlock(&exynos_camera->recording_lock_mutex); - - pthread_mutex_unlock(&exynos_camera->recording_mutex); - - rc = 0; - goto complete; - -error: - pthread_mutex_unlock(&exynos_camera->recording_mutex); - - exynos_camera->recording_listener->busy = 0; - - rc = -1; - -complete: - return rc; -} - void exynos_camera_recording_frame_release(struct exynos_camera *exynos_camera) { struct exynos_v4l2_output *output; @@ -3672,11 +3008,6 @@ int exynos_camera_recording(struct exynos_camera *exynos_camera) else exynos_camera_recording_frame_release(exynos_camera); - if (exynos_camera->recording_metadata) { - memory_index++; - exynos_camera->recording_memory_index = memory_index % buffers_count; - } - rc = 0; goto complete; @@ -3684,87 +3015,28 @@ error: rc = -1; complete: - exynos_camera->recording_listener->busy = 0; - return rc; } -void *exynos_camera_recording_thread(void *data) +int exynos_camera_recording_start(struct exynos_camera *exynos_camera) { - struct exynos_camera *exynos_camera; int rc; - if (data == NULL) - return NULL; - - exynos_camera = (struct exynos_camera *) data; - - ALOGE("%s: Starting thread", __func__); - exynos_camera->recording_thread_running = 1; - - while (exynos_camera->recording_thread_enabled) { - pthread_mutex_lock(&exynos_camera->recording_lock_mutex); - - pthread_mutex_lock(&exynos_camera->recording_mutex); - - if (exynos_camera->recording_listener == NULL) { - pthread_mutex_unlock(&exynos_camera->recording_mutex); - break; - } - - if (exynos_camera->recording_listener->busy) { - rc = exynos_camera_recording(exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to record", __func__); - pthread_mutex_unlock(&exynos_camera->recording_mutex); - break; - } - } - - pthread_mutex_unlock(&exynos_camera->recording_mutex); - } - - exynos_camera->recording_thread_running = 0; - ALOGE("%s: Exiting thread", __func__); - - return NULL; -} - -int exynos_camera_recording_thread_start(struct exynos_camera *exynos_camera) -{ - struct exynos_camera_capture_listener *listener; - pthread_attr_t thread_attr; camera_memory_t *memory = NULL; int buffer_length; int buffers_count; - int rc; if (exynos_camera == NULL) return -EINVAL; ALOGD("%s()", __func__); - if (exynos_camera->recording_thread_enabled) { - ALOGE("Recording thread was already started!"); + if (exynos_camera->recording_enabled) { + ALOGE("Recording was already started!"); return -1; } - pthread_mutex_init(&exynos_camera->recording_mutex, NULL); - pthread_mutex_init(&exynos_camera->recording_lock_mutex, NULL); - - // Initial lock - pthread_mutex_lock(&exynos_camera->recording_lock_mutex); - - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - - exynos_camera->recording_thread_enabled = 1; - - rc = pthread_create(&exynos_camera->recording_thread, &thread_attr, exynos_camera_recording_thread, (void *) exynos_camera); - if (rc < 0) { - ALOGE("%s: Unable to create thread", __func__); - goto error; - } + exynos_camera->recording_enabled = 1; if (exynos_camera->recording_metadata) { buffer_length = sizeof(struct exynos_camera_addrs); @@ -3786,14 +3058,6 @@ int exynos_camera_recording_thread_start(struct exynos_camera *exynos_camera) exynos_camera->recording_buffers_count = buffers_count; } - listener = exynos_camera_capture_listener_register(exynos_camera, exynos_camera->recording_width, exynos_camera->recording_height, exynos_camera->recording_format, exynos_camera_recording_callback); - if (listener == NULL) { - ALOGE("%s: Unable to register recording capture listener", __func__); - goto error; - } - - exynos_camera->recording_listener = listener; - rc = 0; goto complete; @@ -3803,18 +3067,14 @@ error: exynos_camera->recording_memory = NULL; } - pthread_mutex_destroy(&exynos_camera->recording_mutex); - pthread_mutex_destroy(&exynos_camera->recording_lock_mutex); - rc = -1; complete: return rc; } -void exynos_camera_recording_thread_stop(struct exynos_camera *exynos_camera) +void exynos_camera_recording_stop(struct exynos_camera *exynos_camera) { - camera_memory_t *memory; int i; if (exynos_camera == NULL) @@ -3822,49 +3082,18 @@ void exynos_camera_recording_thread_stop(struct exynos_camera *exynos_camera) ALOGD("%s()", __func__); - if (!exynos_camera->recording_thread_enabled) { - ALOGE("Recording thread was already stopped!"); + if (!exynos_camera->recording_enabled) { + ALOGE("Recording was already stopped!"); return; } - memory = exynos_camera->recording_memory; - - if (exynos_camera->recording_listener != NULL) { - exynos_camera_capture_listener_unregister(exynos_camera, exynos_camera->recording_listener); - exynos_camera->recording_listener = NULL; - } - - exynos_camera->recording_thread_enabled = 0; - - pthread_mutex_unlock(&exynos_camera->recording_lock_mutex); - - // Wait for the thread to end - i = 0; - while (exynos_camera->recording_thread_running) { - if (i++ > 10000) { - ALOGE("Recording thread is taking too long to end, something is going wrong"); - break; - } - usleep(100); - } - - if (exynos_camera->recording_output_enabled) { - pthread_mutex_lock(&exynos_camera->recording_mutex); - exynos_camera_recording_output_stop(exynos_camera); - pthread_mutex_unlock(&exynos_camera->recording_mutex); - } - - pthread_mutex_destroy(&exynos_camera->recording_mutex); - pthread_mutex_destroy(&exynos_camera->recording_lock_mutex); + exynos_camera->recording_enabled = 0; - if (memory != NULL && memory->release != NULL) { - memory->release(memory); - exynos_camera->recording_memory = NULL; - } } // Auto-focus + int exynos_camera_auto_focus(struct exynos_camera *exynos_camera, int auto_focus_status) { if (exynos_camera == NULL) @@ -4013,9 +3242,6 @@ int exynos_camera_set_preview_window(struct camera_device *dev, exynos_camera = (struct exynos_camera *) dev->priv; - if (exynos_camera->preview_thread_enabled) - pthread_mutex_lock(&exynos_camera->preview_mutex); - if (w == NULL) { exynos_camera->preview_window = NULL; return 0; @@ -4074,9 +3300,6 @@ error: rc = -1; complete: - if (exynos_camera->preview_thread_enabled) - pthread_mutex_unlock(&exynos_camera->preview_mutex); - return rc; } @@ -4158,7 +3381,7 @@ int exynos_camera_start_preview(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; exynos_camera->callback_lock = 1; - rc = exynos_camera_preview_thread_start(exynos_camera); + rc = exynos_camera_preview_start(exynos_camera); exynos_camera->callback_lock = 0; return rc; @@ -4176,7 +3399,7 @@ void exynos_camera_stop_preview(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; exynos_camera->callback_lock = 1; - exynos_camera_preview_thread_stop(exynos_camera); + exynos_camera_preview_stop(exynos_camera); exynos_camera->callback_lock = 0; } @@ -4191,7 +3414,7 @@ int exynos_camera_preview_enabled(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; - return exynos_camera->preview_thread_enabled; + return exynos_camera->preview_enabled; } int exynos_camera_store_meta_data_in_buffers(struct camera_device *dev, @@ -4206,7 +3429,7 @@ int exynos_camera_store_meta_data_in_buffers(struct camera_device *dev, exynos_camera = (struct exynos_camera *) dev->priv; - if (!exynos_camera->recording_thread_enabled) + if (!exynos_camera->recording_enabled) exynos_camera->recording_metadata = enable; else ALOGE("%s: Recording is running!", __func__); @@ -4224,7 +3447,7 @@ int exynos_camera_start_recording(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; exynos_camera->callback_lock = 1; - rc = exynos_camera_recording_thread_start(exynos_camera); + rc = exynos_camera_recording_start(exynos_camera); exynos_camera->callback_lock = 0; return rc; @@ -4239,7 +3462,7 @@ void exynos_camera_stop_recording(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; exynos_camera->callback_lock = 1; - exynos_camera_recording_thread_stop(exynos_camera); + exynos_camera_recording_stop(exynos_camera); exynos_camera->callback_lock = 0; } @@ -4254,7 +3477,7 @@ int exynos_camera_recording_enabled(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; - return exynos_camera->recording_thread_enabled; + return exynos_camera->recording_enabled; } void exynos_camera_release_recording_frame(struct camera_device *dev, @@ -4314,13 +3537,8 @@ int exynos_camera_take_picture(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; - if (exynos_camera->picture_thread_running) - { - return 0; - } - exynos_camera->callback_lock = 1; - rc = exynos_camera_picture_thread_start(exynos_camera); + rc = exynos_camera_picture_start(exynos_camera); exynos_camera->callback_lock = 0; return rc; @@ -4339,7 +3557,7 @@ int exynos_camera_cancel_picture(struct camera_device *dev) exynos_camera = (struct exynos_camera *) dev->priv; exynos_camera->callback_lock = 1; - exynos_camera_picture_thread_stop(exynos_camera); + exynos_camera_picture_stop(exynos_camera); exynos_camera->callback_lock = 0; return 0; @@ -4656,7 +3874,7 @@ struct camera_module HAL_MODULE_INFO_SYM = { .hal_api_version = HARDWARE_HAL_API_VERSION, .module_api_version = CAMERA_MODULE_API_VERSION_1_0, .id = CAMERA_HARDWARE_MODULE_ID, - .name = "Exynos Camera", + .name = "Exynos Camera - Dheeraj CVR", .author = "Paul Kocialkowski", .methods = &exynos_camera_module_methods, }, diff --git a/camera/exynos_camera.h b/camera/exynos_camera.h index e3bed92..e411b73 100644 --- a/camera/exynos_camera.h +++ b/camera/exynos_camera.h @@ -93,17 +93,6 @@ struct exynos_camera_buffer { int format; }; -struct exynos_camera_capture_listener { - struct list_head list; - - int width; - int height; - int format; - - int (*callback)(struct exynos_camera *exynos_camera, struct exynos_camera_buffer *buffers, int buffers_count); - int busy; -}; - struct exynos_camera_mbus_resolution { int width; int height; @@ -111,6 +100,13 @@ struct exynos_camera_mbus_resolution { int mbus_height; }; +struct exynos_camera_videosnapshot_resolution { + int video_width; + int video_height; + int snapshot_width; + int snapshot_height; +}; + struct exynos_camera_params { char *preview_size_values; char *preview_size; @@ -207,6 +203,8 @@ struct exynos_camera_preset { struct exynos_camera_params params; struct exynos_camera_mbus_resolution *mbus_resolutions; int mbus_resolutions_count; + struct exynos_camera_videosnapshot_resolution *videosnapshot_resolutions; + int videosnapshot_resolutions_count; }; struct exynos_v4l2_node { @@ -313,14 +311,12 @@ struct exynos_camera { int capture_thread_enabled; int capture_enabled; - struct exynos_camera_capture_listener *capture_listeners; struct exynos_exif exif; camera_memory_t *capture_memory; int capture_memory_address; int capture_memory_index; void *capture_yuv_buffer; void *capture_jpeg_buffer; - int capture_hybrid; int capture_width; int capture_height; int capture_format; @@ -328,15 +324,10 @@ struct exynos_camera { int capture_buffer_length; // Preview - - pthread_t preview_thread; - pthread_mutex_t preview_mutex; - pthread_mutex_t preview_lock_mutex; - int preview_thread_running; - int preview_thread_enabled; + int preview_enabled; + int preview_stopping; int preview_output_enabled; - struct exynos_camera_capture_listener *preview_listener; struct preview_stream_ops *preview_window; struct exynos_camera_buffer preview_buffer; struct exynos_v4l2_output preview_output; @@ -344,19 +335,13 @@ struct exynos_camera { // Picture pthread_t picture_thread; - pthread_mutex_t picture_mutex; - pthread_mutex_t picture_lock_mutex; - int picture_thread_running; - int picture_thread_enabled; - + int picture_running; int picture_enabled; + int picture_completed; - struct exynos_camera_capture_listener *picture_listener; camera_memory_t *picture_memory; struct exynos_camera_buffer picture_jpeg_buffer; - struct exynos_camera_buffer picture_jpeg_thumbnail_buffer; struct exynos_camera_buffer picture_yuv_buffer; - struct exynos_camera_buffer picture_yuv_thumbnail_buffer; // Face Detection camera_frame_metadata_t mFaceData; @@ -365,14 +350,10 @@ struct exynos_camera { // Recording - pthread_t recording_thread; - pthread_mutex_t recording_mutex; - pthread_mutex_t recording_lock_mutex; - int recording_thread_running; - int recording_thread_enabled; + int recording_running; + int recording_enabled; int recording_output_enabled; - struct exynos_camera_capture_listener *recording_listener; camera_memory_t *recording_memory; int recording_memory_index; struct exynos_camera_buffer recording_buffer; @@ -399,6 +380,8 @@ struct exynos_camera { struct exynos_camera_mbus_resolution *camera_mbus_resolutions; int camera_mbus_resolutions_count; + struct exynos_camera_videosnapshot_resolution *camera_videosnapshot_resolutions; + int camera_videosnapshot_resolutions_count; int camera_sensor_mode; int fimc_is_mode; @@ -473,43 +456,30 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera, int force); // Capture int exynos_camera_capture(struct exynos_camera *exynos_camera); -int exynos_camera_capture_thread_start(struct exynos_camera *exynos_camera); -void exynos_camera_capture_thread_stop(struct exynos_camera *exynos_camera); int exynos_camera_capture_start(struct exynos_camera *exynos_camera); void exynos_camera_capture_stop(struct exynos_camera *exynos_camera); int exynos_camera_capture_setup(struct exynos_camera *exynos_camera); -struct exynos_camera_capture_listener *exynos_camera_capture_listener_register( - struct exynos_camera *exynos_camera, int width, int height, int format, - int (*callback)(struct exynos_camera *exynos_camera, struct exynos_camera_buffer *buffers, int buffers_count)); -void exynos_camera_capture_listener_unregister( - struct exynos_camera *exynos_camera, - struct exynos_camera_capture_listener *listener); // Preview int exynos_camera_preview_output_start(struct exynos_camera *exynos_camera); void exynos_camera_preview_output_stop(struct exynos_camera *exynos_camera); -int exynos_camera_preview_callback(struct exynos_camera *exynos_camera, - struct exynos_camera_buffer *buffers, int buffers_count); int exynos_camera_preview(struct exynos_camera *exynos_camera); -int exynos_camera_preview_thread_start(struct exynos_camera *exynos_camera); -void exynos_camera_preview_thread_stop(struct exynos_camera *exynos_camera); +int exynos_camera_preview_start(struct exynos_camera *exynos_camera); +void exynos_camera_preview_stop(struct exynos_camera *exynos_camera); // Picture -int exynos_camera_picture_callback(struct exynos_camera *exynos_camera, - struct exynos_camera_buffer *buffers, int buffers_count); -int exynos_camera_picture(struct exynos_camera *exynos_camera); -int exynos_camera_picture_thread_start(struct exynos_camera *exynos_camera); -void exynos_camera_picture_thread_stop(struct exynos_camera *exynos_camera); +void *exynos_camera_picture(void *data); +int exynos_camera_picture_start(struct exynos_camera *exynos_camera); +void exynos_camera_picture_thread_start(struct exynos_camera *exynos_camera); +void exynos_camera_picture_stop(struct exynos_camera *exynos_camera); // Recording int exynos_camera_recording_output_start(struct exynos_camera *exynos_camera); void exynos_camera_recording_output_stop(struct exynos_camera *exynos_camera); -int exynos_camera_recording_callback(struct exynos_camera *exynos_camera, - struct exynos_camera_buffer *buffers, int buffers_count); void exynos_camera_recording_frame_release(struct exynos_camera *exynos_camera); int exynos_camera_recording(struct exynos_camera *exynos_camera); -int exynos_camera_recording_thread_start(struct exynos_camera *exynos_camera); -void exynos_camera_recording_thread_stop(struct exynos_camera *exynos_camera); +int exynos_camera_recording_start(struct exynos_camera *exynos_camera); +void exynos_camera_recording_stop(struct exynos_camera *exynos_camera); // Auto-focus int exynos_camera_auto_focus(struct exynos_camera *exynos_camera, int auto_focus_status); -- cgit v1.1 From 738dd96fe583731731e36f8d0c58859eeb2e4b93 Mon Sep 17 00:00:00 2001 From: sbrissen Date: Fri, 21 Nov 2014 10:12:37 -0500 Subject: smdk4412-common: fix camera build Change-Id: If1d23405240838946e8fbd5b556805f3218bf1db --- camera/Android.mk | 1 + 1 file changed, 1 insertion(+) (limited to 'camera') diff --git a/camera/Android.mk b/camera/Android.mk index 0f54340..a830b3d 100644 --- a/camera/Android.mk +++ b/camera/Android.mk @@ -32,6 +32,7 @@ LOCAL_SRC_FILES := \ LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/include \ + system/media/camera/include \ hardware/samsung/exynos4/hal/include LOCAL_SHARED_LIBRARIES := libutils libcutils liblog libcamera_client libhardware -- cgit v1.1 From 402e50994e14785d3dc0328b27fd74021a8744ca Mon Sep 17 00:00:00 2001 From: Dheeraj CVR Date: Wed, 24 Dec 2014 08:28:20 +0530 Subject: smdk4412-common: camera: don't propogate cancel autofocus in CAF Setting AUTO_FOCUS_OFF during CAF mode seems to be dangerous and hangs the sensor. Hence, we only propogate V4L2_CID_CAMERA_SET_AUTO_FOCUS if we have previously started the Autofocus (Manual/Touch). Change-Id: Ia081257c16f2b7a2e2d6a1e93e239179f39c3fec --- camera/exynos_camera.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'camera') diff --git a/camera/exynos_camera.c b/camera/exynos_camera.c index 0a62ab3..8501bea 100644 --- a/camera/exynos_camera.c +++ b/camera/exynos_camera.c @@ -3209,12 +3209,12 @@ void exynos_camera_auto_focus_stop(struct exynos_camera *exynos_camera) ALOGD("%s()", __func__); - rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF); - if (rc < 0) - ALOGE("%s: Unable to set auto-focus off", __func__); - - if (exynos_camera->auto_focus_enabled) - exynos_camera_auto_focus_finish(exynos_camera); + if (exynos_camera->auto_focus_enabled) { + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF); + if (rc < 0) + ALOGE("%s: Unable to set auto-focus off", __func__); + exynos_camera_auto_focus_finish(exynos_camera); + } } -- cgit v1.1