From 5fe9b2c621b08a16b00e7080c30b9875155fdc43 Mon Sep 17 00:00:00 2001 From: Wolfgang Wiedmeyer Date: Fri, 18 Mar 2016 15:40:14 +0100 Subject: camera: switch to CyanogenMod's version of the free software camera Replicant's version locks up, sometimes already after taking only one picture. CyanogenMod's camera seems more stable. Only the preview format was changed to RGB565. TODO: Incorporate fixes from both version. Signed-off-by: Wolfgang Wiedmeyer --- camera/Android.mk | 32 +- camera/MODULE_LICENSE_GPL | 0 camera/NOTICE | 674 ++++ camera/exynos_camera.c | 3887 ++++++++++++++++++++ camera/exynos_camera.h | 674 ++++ camera/exynos_exif.c | 899 +++++ camera/exynos_ion.c | 159 + camera/exynos_jpeg.c | 404 +++ camera/exynos_param.c | 492 +++ camera/exynos_utils.c | 158 + camera/exynos_v4l2.c | 802 +++++ camera/exynos_v4l2_output.c | 387 ++ camera/include/fimc.h | 405 --- camera/include/ion.h | 449 --- camera/include/linux/ion.h | 449 +++ camera/include/linux/s5c73m3.h | 369 ++ camera/include/linux/videodev2_exynos_camera.h | 2047 +++++++++++ camera/include/linux/videodev2_exynos_media.h | 225 ++ camera/include/s5c73m3.h | 369 -- camera/smdk4x12_camera.c | 4530 ------------------------ camera/smdk4x12_camera.h | 695 ---- camera/smdk4x12_exif.c | 888 ----- camera/smdk4x12_ion.c | 159 - camera/smdk4x12_jpeg.c | 402 --- camera/smdk4x12_param.c | 492 --- camera/smdk4x12_utils.c | 174 - camera/smdk4x12_v4l2.c | 739 ---- camera/smdk4x12_v4l2_output.c | 387 -- 28 files changed, 11645 insertions(+), 9702 deletions(-) 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 delete mode 100644 camera/include/fimc.h delete mode 100644 camera/include/ion.h create mode 100644 camera/include/linux/ion.h create mode 100644 camera/include/linux/s5c73m3.h create mode 100644 camera/include/linux/videodev2_exynos_camera.h create mode 100644 camera/include/linux/videodev2_exynos_media.h delete mode 100644 camera/include/s5c73m3.h delete mode 100644 camera/smdk4x12_camera.c delete mode 100644 camera/smdk4x12_camera.h delete mode 100644 camera/smdk4x12_exif.c delete mode 100644 camera/smdk4x12_ion.c delete mode 100644 camera/smdk4x12_jpeg.c delete mode 100644 camera/smdk4x12_param.c delete mode 100644 camera/smdk4x12_utils.c delete mode 100644 camera/smdk4x12_v4l2.c delete mode 100644 camera/smdk4x12_v4l2_output.c (limited to 'camera') diff --git a/camera/Android.mk b/camera/Android.mk index 60bd5d7..a830b3d 100644 --- a/camera/Android.mk +++ b/camera/Android.mk @@ -1,4 +1,5 @@ -# Copyright (C) 2013-2014 Paul Kocialkowski +# +# 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 @@ -21,26 +22,31 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - smdk4x12_camera.c \ - smdk4x12_exif.c \ - smdk4x12_jpeg.c \ - smdk4x12_param.c \ - smdk4x12_utils.c \ - smdk4x12_v4l2.c \ - smdk4x12_v4l2_output.c \ - smdk4x12_ion.c + 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 \ system/media/camera/include \ hardware/samsung/exynos4/hal/include -LOCAL_CFLAGS += -DEXYNOS_ION - -LOCAL_SHARED_LIBRARIES := libutils libcutils liblog libcamera_client libhardware libhwjpeg +LOCAL_SHARED_LIBRARIES := libutils libcutils liblog libcamera_client libhardware LOCAL_PRELINK_MODULE := false -LOCAL_MODULE := camera.smdk4x12 +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 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..12360ae --- /dev/null +++ b/camera/exynos_camera.c @@ -0,0 +1,3887 @@ +/* + * 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_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", + .facing = CAMERA_FACING_BACK, + .orientation = 90, + .rotation = 0, + .hflip = 0, + .vflip = 0, + .capture_format = V4L2_PIX_FMT_INTERLEAVED, + .picture_format = V4L2_PIX_FMT_JPEG, + .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 = "rgb565", + .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 = 120, + .jpeg_thumbnail_quality = 100, + .jpeg_quality = 90, + + .video_snapshot_supported = 1, + .full_video_snap_supported = 0, + + .recording_size = "1280x720", + .recording_size_values = "1280x720,1920x1080,720x480,640x480,352x288,320x240,176x144", + .recording_format = "yuv420sp", + + .focus_mode = "auto", + .focus_mode_values = "auto,infinity,macro,fixed,continuous-picture,continuous-video", + .focus_distances = "0.15,1.20,Infinity", + .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", + .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", + + .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 = "auto", + .antibanding_values = "off,auto,50hz,60hz", + + .scene_mode = "auto", + .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", + + .iso = "auto", + .iso_values = "auto,ISO100,ISO200,ISO400,ISO800", + + .image_stabilization = "off", + .image_stabilization_values = "on,off", + }, + .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", + .facing = CAMERA_FACING_FRONT, + .orientation = 270, + .rotation = 0, + .hflip = 0, + .vflip = 0, + .capture_format = V4L2_PIX_FMT_UYVY, + .picture_format = V4L2_PIX_FMT_JPEG, + .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 = "rgb565", + .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 = "1280x960,1392x1392,640x480,1280x720,720x480,320x240", + .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 = 1, + .full_video_snap_supported = 1, + + .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, + + .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, + + .max_detected_faces = 5, + + .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", + + .image_stabilization = "off", + .image_stabilization_values = "off", + }, + .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; + + 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", + 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); + 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); + } + + // 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) { + 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"); + } + + // 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", + 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); + + // 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", + 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; +} + +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; + 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 = FOCUS_MODE_DEFAULT; + char *focus_areas_string; + int focus_left, focus_top, focus_right, focus_bottom, focus_weight; + int focus_x; + int focus_y; + + 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 = 0; + + 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; + + char *image_stabilization_string; + int image_stabilization; + + int w, h; + char *k; + int rc, i; + + 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_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) + 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_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; + } + + // 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) { + 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_weight = 0; + + rc = sscanf(focus_areas_string, "(%d,%d,%d,%d,%d)", + &focus_left, &focus_top, &focus_right, &focus_bottom, &focus_weight); + if (rc != 5) { + ALOGE("%s: Unable to scan focus areas", __func__); + } 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; + + 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__); + } + + /* 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; + } + } + + } + + // 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__); + } else if (zoom > max_zoom) { + exynos_param_int_set(exynos_camera, "zoom", max_zoom); + return -EINVAL; + } + + } + + // 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; + + // 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 == FOCUS_MODE_DEFAULT) { + 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 (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) { + 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__); + } + } + + // 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 == 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; + } + } + + 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"); + 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__); + } + } + + // 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__); + } + } + + // 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; +} + +// Capture + +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, + 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; + 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 + + *auto_focus_result = (int) *data_p; + + 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); + + // 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)) { + 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_buffer *buffers = NULL; + struct exynos_camera_buffer *buffer; + 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 current_af; + int decoded; + int busy; + void *pointer; + void *picture_yuv_pointer = NULL; + 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 + + if (!exynos_camera->camera_fimc_is) { + 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->auto_focus_enabled) { + rc = exynos_camera_auto_focus(exynos_camera, current_af); + if (rc < 0) { + ALOGE("%s: Unable to auto focus", __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_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)); + + 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; + + 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; + + memcpy(&exynos_camera->picture_yuv_buffer, buffer, 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)); + + 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 = exynos_camera->picture_format; + + memcpy(&exynos_camera->picture_jpeg_buffer, buffer, sizeof(struct exynos_camera_buffer)); + + 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)); + + buffer = buffers; + + buffer->pointer = pointer; + buffer->address = address; + buffer->length = buffer_length; + buffer->width = width; + buffer->height = height; + buffer->format = format; + + if (exynos_camera->picture_enabled) { + memcpy(&exynos_camera->picture_yuv_buffer, buffer, sizeof(struct exynos_camera_buffer)); + exynos_camera_picture_thread_start(exynos_camera); + } + } + + // 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; + } + } + + //Recording + if (exynos_camera->recording_enabled) { + if (exynos_camera->recording_output_enabled) { + memcpy(&exynos_camera->recording_buffer, buffer, sizeof(struct exynos_camera_buffer)); + + exynos_camera->recording_memory_index = index; + + 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)); + + rc = exynos_camera_recording_output_start(exynos_camera); + if (rc < 0) { + ALOGE("%s: Unable to start recording output", __func__); + goto error; + } + + } + } 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) { + 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; +} + +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; + 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 (!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; + } + } 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__); + 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; + } + + rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CACHEABLE, 0); + if (rc < 0) { + ALOGE("%s: Unable to set cacheable", __func__); + goto error; + } + + // 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 + + 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; + + 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; + } + + 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(struct exynos_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) { + 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; + } + + // 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); + + rc = 0; + 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; + } + + 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->camera_fimc_is) { + 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__); + } + + 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__); + } + + 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; + } + + 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; + } + + if (&exynos_camera->exif.enabled) + exynos_exif_stop(exynos_camera, &exynos_camera->exif); + + exynos_camera->capture_enabled = 0; +} + +int exynos_camera_capture_setup(struct exynos_camera *exynos_camera) +{ + int width, height, format; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + format = exynos_camera->camera_capture_format; + + 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; +} + +// 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(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; + camera_face_t caface[exynos_camera->max_detected_faces]; + 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) { + int ret = exynos_camera->preview_window->dequeue_buffer(exynos_camera->preview_window, &window_buffer, &window_stride); + if (ret < 0) { + ALOGE("%s: Error in dequeueing buffer", __func__); + goto error; + } + ret = exynos_camera->gralloc->lock(exynos_camera->gralloc, *window_buffer, GRALLOC_USAGE_YUV_ADDR | GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0, width, height, &window_data); + + if (window_data == NULL || ret == -EINVAL) { + 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->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) { + ALOGE("%s: Unable to release preview output", __func__); + goto error; + } + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +int exynos_camera_preview_start(struct exynos_camera *exynos_camera) +{ + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exynos_camera->preview_enabled) { + ALOGE("Preview was already started!"); + return -1; + } + + exynos_camera_capture_setup(exynos_camera); + + exynos_camera->preview_enabled = 1; + + return 0; +} + +void exynos_camera_preview_stop(struct exynos_camera *exynos_camera) +{ + int i; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exynos_camera->preview_enabled) { + ALOGE("Preview was already stopped!"); + return; + } + + exynos_camera->preview_enabled = 0; + + 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) + exynos_camera_preview_output_stop(exynos_camera); + + exynos_camera->preview_window = NULL; +} + +// Picture + +void *exynos_camera_picture(void *data) +{ + struct exynos_camera *exynos_camera; + struct exynos_camera_buffer *jpeg_buffer; + struct exynos_camera_buffer *yuv_buffer; + struct exynos_v4l2_output output; + struct exynos_jpeg jpeg; + 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 = 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__); + + jpeg_buffer = &exynos_camera->picture_jpeg_buffer; + yuv_buffer = &exynos_camera->picture_yuv_buffer; + + if (jpeg_buffer->pointer != NULL && jpeg_buffer->length > 0) { + jpeg_data = jpeg_buffer->pointer; + jpeg_size = jpeg_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; + } + + // 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) || exynos_camera->camera_fimc_is) { + 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; + + if (exynos_camera->camera_fimc_is) + exynos_exif_create(exynos_camera, &exynos_camera->exif); + } + + 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 (yuv_data == NULL || yuv_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_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 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 + 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; + + rc = exynos_exif(exynos_camera, &exynos_camera->exif); + if (rc < 0) { + ALOGE("%s: Unable to exif", __func__); + goto error; + } + + 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); + 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, 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_camera->picture_memory = memory; + + 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); + +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_stop(exynos_camera); + exynos_camera->picture_running = 0; + + return NULL; +} + +int exynos_camera_picture_start(struct exynos_camera *exynos_camera) +{ + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exynos_camera->picture_enabled) { + ALOGE("Picture was already started!"); + return 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; + } + + 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_enabled = 1; + + return 0; +} + +void exynos_camera_picture_stop(struct exynos_camera *exynos_camera) +{ + camera_memory_t *memory; + int rc, i; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exynos_camera->picture_enabled) { + ALOGE("Picture was already stopped!"); + return; + } + + memory = exynos_camera->picture_memory; + + 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; + } + } + + 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 + +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; +} + +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); + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +int exynos_camera_recording_start(struct exynos_camera *exynos_camera) +{ + int rc; + + camera_memory_t *memory = NULL; + int buffer_length; + int buffers_count; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + if (exynos_camera->recording_enabled) { + ALOGE("Recording was already started!"); + return -1; + } + + exynos_camera->recording_enabled = 1; + + 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; + } + + rc = 0; + goto complete; + +error: + if (memory != NULL && memory->release != NULL) { + memory->release(memory); + exynos_camera->recording_memory = NULL; + } + + rc = -1; + +complete: + return rc; +} + +void exynos_camera_recording_stop(struct exynos_camera *exynos_camera) +{ + int i; + + if (exynos_camera == NULL) + return; + + ALOGD("%s()", __func__); + + if (!exynos_camera->recording_enabled) { + ALOGE("Recording was already stopped!"); + return; + } + + exynos_camera->recording_enabled = 0; + +} + +// 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_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_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_RESTART: + default: + break; + } + + return 0; +} + +int exynos_camera_auto_focus_start(struct exynos_camera *exynos_camera) +{ + int auto_focus; + int rc; + + if (exynos_camera == NULL) + return -EINVAL; + + ALOGD("%s()", __func__); + + 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; + } + + exynos_camera->auto_focus_enabled = 1; + + rc = 0; + goto complete; + +error: + + rc = -1; + +complete: + return rc; +} + +void exynos_camera_auto_focus_finish(struct exynos_camera *exynos_camera) +{ + int rc; + + ALOGD("%s()", __func__); + + if (!exynos_camera->auto_focus_enabled) { + return; + } + + 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) + 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__); + + 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); + } + +} + +/* + * 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 (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: + 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_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_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_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_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_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_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_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_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_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_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_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; + + 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__); + 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 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: + 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; + } + + 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 - Dheeraj CVR", + .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..e411b73 --- /dev/null +++ b/camera/exynos_camera.h @@ -0,0 +1,674 @@ +/* + * 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_mbus_resolution { + int width; + int height; + int mbus_width; + 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; + 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 max_detected_faces; + + int zoom_supported; + int smooth_zoom_supported; + char *zoom_ratios; + 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; + + 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; + + char *image_stabilization; // Anti-shake + char *image_stabilization_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_camera_videosnapshot_resolution *videosnapshot_resolutions; + int videosnapshot_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_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_width; + int capture_height; + int capture_format; + int capture_buffers_count; + int capture_buffer_length; + + // Preview + int preview_enabled; + int preview_stopping; + + int preview_output_enabled; + struct preview_stream_ops *preview_window; + struct exynos_camera_buffer preview_buffer; + struct exynos_v4l2_output preview_output; + + // Picture + + pthread_t picture_thread; + int picture_running; + int picture_enabled; + + int picture_completed; + camera_memory_t *picture_memory; + struct exynos_camera_buffer picture_jpeg_buffer; + struct exynos_camera_buffer picture_yuv_buffer; + + // Face Detection + camera_frame_metadata_t mFaceData; + camera_memory_t *face_data; + int max_detected_faces; + + // Recording + + int recording_running; + int recording_enabled; + + int recording_output_enabled; + 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 + + int auto_focus_enabled; + int auto_focus_started; + + // 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; + struct exynos_camera_videosnapshot_resolution *camera_videosnapshot_resolutions; + int camera_videosnapshot_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 ae_lock; + int awb_lock; + int flash_mode; + int exposure_compensation; + int whitebalance; + int antibanding; + int scene_mode; + int effect; + int iso; + 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 { + 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_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); + +// 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(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 +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); +void exynos_camera_recording_frame_release(struct exynos_camera *exynos_camera); +int exynos_camera_recording(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); +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); + +/* + * 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); + +/* + * 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_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, + 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..486b256 --- /dev/null +++ b/camera/exynos_exif.c @@ -0,0 +1,899 @@ +/* + * 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); + + strcpy((char *) attributes->gps_processing_method, gps_processing_method_string); + 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; + + // 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->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__); + + 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->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) { + 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; + } + + 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__); + 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; +} + +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) +{ + 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..2768676 --- /dev/null +++ b/camera/exynos_v4l2.c @@ -0,0 +1,802 @@ +/* + * 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_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) +{ + 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/fimc.h b/camera/include/fimc.h deleted file mode 100644 index 3e7732d..0000000 --- a/camera/include/fimc.h +++ /dev/null @@ -1,405 +0,0 @@ -/* 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 -#ifdef CONFIG_SLP_DMABUF -#include -#endif -#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" - -extern int fimc_clk_rate(void); - -#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 -#if defined(CONFIG_SLP) -#define FIMC_MAX_CTXS 8 -#else -#define FIMC_MAX_CTXS 4 -#endif -#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, -}; - -enum fimc_plane_num { - PLANE_1 = 0x1, - PLANE_2 = 0x2, - PLANE_3 = 0x3, - PLANE_4 = 0x4, -}; - -/* - * STRUCTURES -*/ - -/* for reserved memory */ -struct fimc_meminfo { -#ifdef CONFIG_USE_FIMC_CMA - void *cpu_addr; -#endif - 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 { \ - if (ctrl->log & FIMC_LOG_DEBUG) \ - printk(KERN_DEBUG FIMC_NAME "%d: " \ - fmt, ctrl->id, ##__VA_ARGS__); \ - } while (0) - -#define FIMC_INFO_L2(fmt, ...) \ - do { \ - if (ctrl->log & FIMC_LOG_INFO_L2) \ - printk(KERN_INFO FIMC_NAME "%d: " \ - fmt, ctrl->id, ##__VA_ARGS__); \ - } while (0) - -#define FIMC_INFO_L1(fmt, ...) \ - do { \ - if (ctrl->log & FIMC_LOG_INFO_L1) \ - printk(KERN_INFO FIMC_NAME "%d: " \ - fmt, ctrl->id, ##__VA_ARGS__); \ - } while (0) - -#define FIMC_WARN(fmt, ...) \ - do { \ - if (ctrl->log & FIMC_LOG_WARN) \ - printk(KERN_WARNING FIMC_NAME "%d: " \ - fmt, ctrl->id, ##__VA_ARGS__); \ - } while (0) - - -#define FIMC_ERROR(fmt, ...) \ - do { \ - if (ctrl->log & FIMC_LOG_ERR) \ - 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/ion.h b/camera/include/ion.h deleted file mode 100644 index 29dba57..0000000 --- a/camera/include/ion.h +++ /dev/null @@ -1,449 +0,0 @@ -/* - * 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/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..ffb582e --- /dev/null +++ b/camera/include/linux/s5c73m3.h @@ -0,0 +1,369 @@ +/* + * 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_QVGA, + S5C73M3_PREVIEW_CIF, + S5C73M3_PREVIEW_VGA, + S5C73M3_PREVIEW_D1, + S5C73M3_PREVIEW_800X600, + S5C73M3_PREVIEW_880X720, + S5C73M3_PREVIEW_960X720, + S5C73M3_PREVIEW_1008X672, + S5C73M3_PREVIEW_1184X666, + S5C73M3_PREVIEW_720P, + S5C73M3_PREVIEW_1280X960, + S5C73M3_VDIS_720P, + S5C73M3_PREVIEW_1080P, + S5C73M3_VDIS_1080P, +}; + +enum s5c73m3_cap_frmsize { + S5C73M3_CAPTURE_VGA, /* 640 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_2MP, /* UXGA - 1600 x 1200 */ + S5C73M3_CAPTURE_W2MP, /* 2048 x 1232 */ + S5C73M3_CAPTURE_3MP, /* QXGA - 2048 x 1536 */ + S5C73M3_CAPTURE_5MP, /* 2560 x 1920 */ + S5C73M3_CAPTURE_W6MP, /* 3072 x 1856 */ + 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_EFFECT_CARTOONIZE 0x001A + +#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_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 +#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_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 +#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_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 +#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_exynos_camera.h b/camera/include/linux/videodev2_exynos_camera.h new file mode 100644 index 0000000..557b5e1 --- /dev/null +++ b/camera/include/linux/videodev2_exynos_camera.h @@ -0,0 +1,2047 @@ +/* + * 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_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_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) +#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 + 400) +/* 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_LOW_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_INCANDESCENT, + WHITE_BALANCE_PROHIBITION, + WHITE_BALANCE_HORIZON, + WHITE_BALANCE_LEDLIGHT, + 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_POINT_RED, + IMAGE_EFFECT_POINT_YELLOW, + IMAGE_EFFECT_CARTOONIZE, + 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_3200, + 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) +#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) +/* (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_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 = 0, + OBJECT_TRACKING_STATUS_SUCCESS = 1, + OBJECT_TRACKING_STATUS_MISSING = 2, + OBJECT_TRACKING_STATUS_FAIL = 3, + 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_50_60Hz = 3, + ANTI_BANDING_OFF = 4, +}; + +#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_OFF = 0, + 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_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_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) +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, +}; + +#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, + V4L2_PIX_FMT_MODE_CAPTURE, + V4L2_PIX_FMT_MODE_HDR, + V4L2_PIX_FMT_MODE_VT_MIRROR, + 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') +#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 */ diff --git a/camera/include/s5c73m3.h b/camera/include/s5c73m3.h deleted file mode 100644 index ffb582e..0000000 --- a/camera/include/s5c73m3.h +++ /dev/null @@ -1,369 +0,0 @@ -/* - * 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_QVGA, - S5C73M3_PREVIEW_CIF, - S5C73M3_PREVIEW_VGA, - S5C73M3_PREVIEW_D1, - S5C73M3_PREVIEW_800X600, - S5C73M3_PREVIEW_880X720, - S5C73M3_PREVIEW_960X720, - S5C73M3_PREVIEW_1008X672, - S5C73M3_PREVIEW_1184X666, - S5C73M3_PREVIEW_720P, - S5C73M3_PREVIEW_1280X960, - S5C73M3_VDIS_720P, - S5C73M3_PREVIEW_1080P, - S5C73M3_VDIS_1080P, -}; - -enum s5c73m3_cap_frmsize { - S5C73M3_CAPTURE_VGA, /* 640 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_2MP, /* UXGA - 1600 x 1200 */ - S5C73M3_CAPTURE_W2MP, /* 2048 x 1232 */ - S5C73M3_CAPTURE_3MP, /* QXGA - 2048 x 1536 */ - S5C73M3_CAPTURE_5MP, /* 2560 x 1920 */ - S5C73M3_CAPTURE_W6MP, /* 3072 x 1856 */ - 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_EFFECT_CARTOONIZE 0x001A - -#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_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 -#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_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 -#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_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 -#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/smdk4x12_camera.c b/camera/smdk4x12_camera.c deleted file mode 100644 index 53cc16f..0000000 --- a/camera/smdk4x12_camera.c +++ /dev/null @@ -1,4530 +0,0 @@ -/* - * Copyright (C) 2013-2014 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 "smdk4x12_camera" -#include -#include - -#include "smdk4x12_camera.h" - -#define BIG2LITTLE_ENDIAN(big) ((big & 0xff) << 24 | (big & 0xff00) << 8 | (big & 0xff0000) >> 8 | (big & 0xff000000) >> 24) - -/* - * Devices configurations - */ - -struct smdk4x12_camera_mbus_resolution smdk4x12_camera_mbus_resolutions_s5k6a3_galaxys3[] = { - // 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 smdk4x12_camera_preset smdk4x12_camera_presets_galaxys3[] = { - { - .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 = "rgb565", - .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 = 120, - .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, - - .auto_exposure_lock_supported = 1, - .auto_exposure_lock = 0, - - .auto_white_balance_lock_supported = 1, - .auto_white_balance_lock = 0, - - .flash_mode = "auto", - .flash_mode_values = "auto,on,torch,off", - - .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 = "auto", - .antibanding_values = "auto,60hz,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", - - .image_stabilization = "off", - .image_stabilization_values = "on,off", - }, - .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 = "rgb565", - .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, - - .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, - - .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", - - .image_stabilization = "off", - .image_stabilization_values = "off", - }, - .mbus_resolutions = (struct smdk4x12_camera_mbus_resolution *) &smdk4x12_camera_mbus_resolutions_s5k6a3_galaxys3, - .mbus_resolutions_count = 8, - }, -}; - -struct smdk4x12_v4l2_node smdk4x12_v4l2_nodes_galaxys3[] = { - { // 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 smdk4x12_camera_config_galaxys3 = { - .presets = (struct smdk4x12_camera_preset *) &smdk4x12_camera_presets_galaxys3, - .presets_count = 2, - .v4l2_nodes = (struct smdk4x12_v4l2_node *) &smdk4x12_v4l2_nodes_galaxys3, - .v4l2_nodes_count = 4, -}; - -/* - * SMDK4x12 Camera - */ - -struct exynox_camera_config *smdk4x12_camera_config = - &smdk4x12_camera_config_galaxys3; - -int smdk4x12_camera_start(struct smdk4x12_camera *smdk4x12_camera, int id) -{ - int rc; - - if (smdk4x12_camera == NULL || id >= smdk4x12_camera->config->presets_count) - return -EINVAL; - - // ION - -#ifdef EXYNOS_ION - rc = smdk4x12_ion_init(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to init ION", __func__); - goto error; - } - - rc = smdk4x12_ion_open(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to open ION", __func__); - goto error; - } -#endif - - // V4L2 - - rc = smdk4x12_v4l2_init(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to init v4l2", __func__); - goto error; - } - - // FIMC0 - - rc = smdk4x12_v4l2_open(smdk4x12_camera, 0); - if (rc < 0) { - ALOGE("%s: Unable to open v4l2 device", __func__); - goto error; - } - - rc = smdk4x12_v4l2_querycap_cap(smdk4x12_camera, 0); - if (rc < 0) { - ALOGE("%s: Unable to query capabilities", __func__); - goto error; - } - - rc = smdk4x12_v4l2_enum_input(smdk4x12_camera, 0, id); - if (rc < 0) { - ALOGE("%s: Unable to enumerate input", __func__); - goto error; - } - - rc = smdk4x12_v4l2_s_input(smdk4x12_camera, 0, id); - if (rc < 0) { - ALOGE("%s: Unable to set inputs", __func__); - goto error; - } - - // Recording - - smdk4x12_camera->recording_metadata = 1; - - // Params - - rc = smdk4x12_camera_params_init(smdk4x12_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 **) &smdk4x12_camera->gralloc); - if (rc) - ALOGE("%s: Unable to get gralloc module", __func__); - - rc = 0; - goto complete; - -error: - smdk4x12_v4l2_close(smdk4x12_camera, 0); - -#ifdef EXYNOS_ION - smdk4x12_ion_close(smdk4x12_camera); -#endif - - rc = -1; - -complete: - return rc; -} - -void smdk4x12_camera_stop(struct smdk4x12_camera *smdk4x12_camera) -{ - int i; - int id; - - if (smdk4x12_camera == NULL || smdk4x12_camera->config == NULL) - return; - - smdk4x12_v4l2_close(smdk4x12_camera, 0); - -#ifdef EXYNOS_ION - smdk4x12_ion_close(smdk4x12_camera); -#endif -} - -// Params - -int smdk4x12_camera_params_init(struct smdk4x12_camera *smdk4x12_camera, int id) -{ - int rc; - - if (smdk4x12_camera == NULL || id >= smdk4x12_camera->config->presets_count) - return -EINVAL; - - // Camera params - - smdk4x12_camera->camera_rotation = smdk4x12_camera->config->presets[id].rotation; - smdk4x12_camera->camera_hflip = smdk4x12_camera->config->presets[id].hflip; - smdk4x12_camera->camera_vflip = smdk4x12_camera->config->presets[id].vflip; - smdk4x12_camera->camera_capture_format = smdk4x12_camera->config->presets[id].capture_format; - smdk4x12_camera->camera_picture_format = smdk4x12_camera->config->presets[id].picture_format; - smdk4x12_camera->camera_fimc_is = smdk4x12_camera->config->presets[id].fimc_is; - smdk4x12_camera->camera_focal_length = (int) (smdk4x12_camera->config->presets[id].focal_length * 100); - smdk4x12_camera->camera_metering = smdk4x12_camera->config->presets[id].metering; - - smdk4x12_camera->camera_mbus_resolutions = smdk4x12_camera->config->presets[id].mbus_resolutions; - smdk4x12_camera->camera_mbus_resolutions_count = smdk4x12_camera->config->presets[id].mbus_resolutions_count; - - // Recording preview - - smdk4x12_param_string_set(smdk4x12_camera, "preferred-preview-size-for-video", - smdk4x12_camera->config->presets[id].params.preview_size); - - // Preview - - smdk4x12_param_string_set(smdk4x12_camera, "preview-size-values", - smdk4x12_camera->config->presets[id].params.preview_size_values); - smdk4x12_param_string_set(smdk4x12_camera, "preview-size", - smdk4x12_camera->config->presets[id].params.preview_size); - smdk4x12_param_string_set(smdk4x12_camera, "preview-format-values", - smdk4x12_camera->config->presets[id].params.preview_format_values); - smdk4x12_param_string_set(smdk4x12_camera, "preview-format", - smdk4x12_camera->config->presets[id].params.preview_format); - smdk4x12_param_string_set(smdk4x12_camera, "preview-frame-rate-values", - smdk4x12_camera->config->presets[id].params.preview_frame_rate_values); - smdk4x12_param_int_set(smdk4x12_camera, "preview-frame-rate", - smdk4x12_camera->config->presets[id].params.preview_frame_rate); - smdk4x12_param_string_set(smdk4x12_camera, "preview-fps-range-values", - smdk4x12_camera->config->presets[id].params.preview_fps_range_values); - smdk4x12_param_string_set(smdk4x12_camera, "preview-fps-range", - smdk4x12_camera->config->presets[id].params.preview_fps_range); - - // Picture - - smdk4x12_param_string_set(smdk4x12_camera, "picture-size-values", - smdk4x12_camera->config->presets[id].params.picture_size_values); - smdk4x12_param_string_set(smdk4x12_camera, "picture-size", - smdk4x12_camera->config->presets[id].params.picture_size); - smdk4x12_param_string_set(smdk4x12_camera, "picture-format-values", - smdk4x12_camera->config->presets[id].params.picture_format_values); - smdk4x12_param_string_set(smdk4x12_camera, "picture-format", - smdk4x12_camera->config->presets[id].params.picture_format); - smdk4x12_param_string_set(smdk4x12_camera, "jpeg-thumbnail-size-values", - smdk4x12_camera->config->presets[id].params.jpeg_thumbnail_size_values); - smdk4x12_param_int_set(smdk4x12_camera, "jpeg-thumbnail-width", - smdk4x12_camera->config->presets[id].params.jpeg_thumbnail_width); - smdk4x12_param_int_set(smdk4x12_camera, "jpeg-thumbnail-height", - smdk4x12_camera->config->presets[id].params.jpeg_thumbnail_height); - smdk4x12_param_int_set(smdk4x12_camera, "jpeg-thumbnail-quality", - smdk4x12_camera->config->presets[id].params.jpeg_thumbnail_quality); - smdk4x12_param_int_set(smdk4x12_camera, "jpeg-quality", - smdk4x12_camera->config->presets[id].params.jpeg_quality); - - if (smdk4x12_camera->config->presets[id].params.video_snapshot_supported == 1) - smdk4x12_param_string_set(smdk4x12_camera, "video-snapshot-supported", "true"); - if (smdk4x12_camera->config->presets[id].params.full_video_snap_supported == 1) - smdk4x12_param_string_set(smdk4x12_camera, "full-video-snap-supported", "true"); - - // Recording - - smdk4x12_param_string_set(smdk4x12_camera, "video-size", - smdk4x12_camera->config->presets[id].params.recording_size); - smdk4x12_param_string_set(smdk4x12_camera, "video-size-values", - smdk4x12_camera->config->presets[id].params.recording_size_values); - smdk4x12_param_string_set(smdk4x12_camera, "video-frame-format", - smdk4x12_camera->config->presets[id].params.recording_format); - - // Focus - - smdk4x12_param_string_set(smdk4x12_camera, "focus-mode", - smdk4x12_camera->config->presets[id].params.focus_mode); - smdk4x12_param_string_set(smdk4x12_camera, "focus-mode-values", - smdk4x12_camera->config->presets[id].params.focus_mode_values); - smdk4x12_param_string_set(smdk4x12_camera, "focus-distances", - smdk4x12_camera->config->presets[id].params.focus_distances); - if (smdk4x12_camera->config->presets[id].params.max_num_focus_areas > 0) { - smdk4x12_param_string_set(smdk4x12_camera, "focus-areas", - smdk4x12_camera->config->presets[id].params.focus_areas); - smdk4x12_param_int_set(smdk4x12_camera, "max-num-focus-areas", - smdk4x12_camera->config->presets[id].params.max_num_focus_areas); - } - - // Zoom - - if (smdk4x12_camera->config->presets[id].params.zoom_supported == 1) { - smdk4x12_param_string_set(smdk4x12_camera, "zoom-supported", "true"); - - if (smdk4x12_camera->config->presets[id].params.smooth_zoom_supported == 1) - smdk4x12_param_string_set(smdk4x12_camera, "smooth-zoom-supported", "true"); - - if (smdk4x12_camera->config->presets[id].params.zoom_ratios != NULL) - smdk4x12_param_string_set(smdk4x12_camera, "zoom-ratios", smdk4x12_camera->config->presets[id].params.zoom_ratios); - - smdk4x12_param_int_set(smdk4x12_camera, "zoom", smdk4x12_camera->config->presets[id].params.zoom); - smdk4x12_param_int_set(smdk4x12_camera, "max-zoom", smdk4x12_camera->config->presets[id].params.max_zoom); - - } else { - smdk4x12_param_string_set(smdk4x12_camera, "zoom-supported", "false"); - } - - // AE lock - - if (smdk4x12_camera->config->presets[id].params.auto_exposure_lock_supported == 1) { - smdk4x12_param_string_set(smdk4x12_camera, "auto-exposure-lock-supported", "true"); - - if (smdk4x12_camera->config->presets[id].params.auto_exposure_lock) - smdk4x12_param_string_set(smdk4x12_camera, "auto-exposure-lock", "true"); - else - smdk4x12_param_string_set(smdk4x12_camera, "auto-exposure-lock", "false"); - } - - // AWB lock - - if (smdk4x12_camera->config->presets[id].params.auto_white_balance_lock_supported == 1) { - smdk4x12_param_string_set(smdk4x12_camera, "auto-whitebalance-lock-supported", "true"); - - if (smdk4x12_camera->config->presets[id].params.auto_white_balance_lock) - smdk4x12_param_string_set(smdk4x12_camera, "auto-whitebalance-lock", "true"); - else - smdk4x12_param_string_set(smdk4x12_camera, "auto-whitebalance-lock", "false"); - } - - // Flash - - smdk4x12_param_string_set(smdk4x12_camera, "flash-mode", - smdk4x12_camera->config->presets[id].params.flash_mode); - smdk4x12_param_string_set(smdk4x12_camera, "flash-mode-values", - smdk4x12_camera->config->presets[id].params.flash_mode_values); - - // Exposure - - smdk4x12_param_int_set(smdk4x12_camera, "exposure-compensation", - smdk4x12_camera->config->presets[id].params.exposure_compensation); - smdk4x12_param_float_set(smdk4x12_camera, "exposure-compensation-step", - smdk4x12_camera->config->presets[id].params.exposure_compensation_step); - smdk4x12_param_int_set(smdk4x12_camera, "min-exposure-compensation", - smdk4x12_camera->config->presets[id].params.min_exposure_compensation); - smdk4x12_param_int_set(smdk4x12_camera, "max-exposure-compensation", - smdk4x12_camera->config->presets[id].params.max_exposure_compensation); - - // Antibanding - - smdk4x12_param_string_set(smdk4x12_camera, "antibanding", - smdk4x12_camera->config->presets[id].params.antibanding); - smdk4x12_param_string_set(smdk4x12_camera, "antibanding-values", - smdk4x12_camera->config->presets[id].params.antibanding_values); - - // WB - - smdk4x12_param_string_set(smdk4x12_camera, "whitebalance", - smdk4x12_camera->config->presets[id].params.whitebalance); - smdk4x12_param_string_set(smdk4x12_camera, "whitebalance-values", - smdk4x12_camera->config->presets[id].params.whitebalance_values); - - // Scene mode - - smdk4x12_param_string_set(smdk4x12_camera, "scene-mode", - smdk4x12_camera->config->presets[id].params.scene_mode); - smdk4x12_param_string_set(smdk4x12_camera, "scene-mode-values", - smdk4x12_camera->config->presets[id].params.scene_mode_values); - - // Effect - - smdk4x12_param_string_set(smdk4x12_camera, "effect", - smdk4x12_camera->config->presets[id].params.effect); - smdk4x12_param_string_set(smdk4x12_camera, "effect-values", - smdk4x12_camera->config->presets[id].params.effect_values); - - // ISO - - smdk4x12_param_string_set(smdk4x12_camera, "iso", - smdk4x12_camera->config->presets[id].params.iso); - smdk4x12_param_string_set(smdk4x12_camera, "iso-values", - smdk4x12_camera->config->presets[id].params.iso_values); - - // Image stabilization - - smdk4x12_param_string_set(smdk4x12_camera, "image-stabilization", - smdk4x12_camera->config->presets[id].params.image_stabilization); - smdk4x12_param_string_set(smdk4x12_camera, "image-stabilization-values", - smdk4x12_camera->config->presets[id].params.image_stabilization_values); - - // Camera - - smdk4x12_param_float_set(smdk4x12_camera, "focal-length", - smdk4x12_camera->config->presets[id].focal_length); - smdk4x12_param_float_set(smdk4x12_camera, "horizontal-view-angle", - smdk4x12_camera->config->presets[id].horizontal_view_angle); - smdk4x12_param_float_set(smdk4x12_camera, "vertical-view-angle", - smdk4x12_camera->config->presets[id].vertical_view_angle); - - rc = smdk4x12_camera_params_apply(smdk4x12_camera, 1); - if (rc < 0) { - ALOGE("%s: Unable to apply params", __func__); - return -1; - } - - return 0; -} - -int smdk4x12_camera_params_apply(struct smdk4x12_camera *smdk4x12_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 *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; - - 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; - - char *image_stabilization_string; - int image_stabilization; - - int w, h; - char *k; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - // Preview - - preview_size_string = smdk4x12_param_string_get(smdk4x12_camera, "preview-size"); - if (preview_size_string != NULL) { - sscanf(preview_size_string, "%dx%d", &preview_width, &preview_height); - - if (preview_width != 0 && preview_width != smdk4x12_camera->preview_width) - smdk4x12_camera->preview_width = preview_width; - if (preview_height != 0 && preview_height != smdk4x12_camera->preview_height) - smdk4x12_camera->preview_height = preview_height; - } - - preview_format_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->preview_format) - smdk4x12_camera->preview_format = preview_format; - } - - preview_fps = smdk4x12_param_int_get(smdk4x12_camera, "preview-frame-rate"); - if (preview_fps > 0) - smdk4x12_camera->preview_fps = preview_fps; - else - smdk4x12_camera->preview_fps = 0; - - // Picture - - picture_size_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->picture_width || picture_height != smdk4x12_camera->picture_height)) { - smdk4x12_camera->picture_width = picture_width; - smdk4x12_camera->picture_height = picture_height; - - if (smdk4x12_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED) { - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_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 = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->picture_format) - smdk4x12_camera->picture_format = picture_format; - } - - jpeg_thumbnail_width = smdk4x12_param_int_get(smdk4x12_camera, "jpeg-thumbnail-width"); - if (jpeg_thumbnail_width > 0) - smdk4x12_camera->jpeg_thumbnail_width = jpeg_thumbnail_width; - - jpeg_thumbnail_height = smdk4x12_param_int_get(smdk4x12_camera, "jpeg-thumbnail-height"); - if (jpeg_thumbnail_height > 0) - smdk4x12_camera->jpeg_thumbnail_height = jpeg_thumbnail_height; - - jpeg_thumbnail_quality = smdk4x12_param_int_get(smdk4x12_camera, "jpeg-thumbnail-quality"); - if (jpeg_thumbnail_quality > 0) - smdk4x12_camera->jpeg_thumbnail_quality = jpeg_thumbnail_quality; - - jpeg_quality = smdk4x12_param_int_get(smdk4x12_camera, "jpeg-quality"); - if (jpeg_quality <= 100 && jpeg_quality >= 0 && (jpeg_quality != smdk4x12_camera->jpeg_quality || force)) { - smdk4x12_camera->jpeg_quality = jpeg_quality; - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAM_JPEG_QUALITY, jpeg_quality); - if (rc < 0) - ALOGE("%s: Unable to set jpeg quality", __func__); - } - - // Recording - - video_size_string = smdk4x12_param_string_get(smdk4x12_camera, "video-size"); - if (video_size_string == NULL) - video_size_string = smdk4x12_param_string_get(smdk4x12_camera, "preview-size"); - - if (video_size_string != NULL) { - sscanf(video_size_string, "%dx%d", &recording_width, &recording_height); - - if (recording_width != 0 && recording_width != smdk4x12_camera->recording_width) - smdk4x12_camera->recording_width = recording_width; - if (recording_height != 0 && recording_height != smdk4x12_camera->recording_height) - smdk4x12_camera->recording_height = recording_height; - } - - video_frame_format_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->recording_format) - smdk4x12_camera->recording_format = recording_format; - } - - recording_hint_string = smdk4x12_param_string_get(smdk4x12_camera, "recording-hint"); - if (recording_hint_string != NULL && strcmp(recording_hint_string, "true") == 0) { - camera_sensor_mode = SENSOR_MOVIE; - - k = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->preview_width) - smdk4x12_camera->preview_width = preview_width; - if (preview_height != 0 && preview_height != smdk4x12_camera->preview_height) - smdk4x12_camera->preview_height = preview_height; - - if (smdk4x12_camera->camera_fimc_is) - fimc_is_mode = IS_MODE_PREVIEW_VIDEO; - } else { - camera_sensor_mode = SENSOR_CAMERA; - - if (smdk4x12_camera->camera_fimc_is) - fimc_is_mode = IS_MODE_PREVIEW_STILL; - } - - // Switching modes - - if (camera_sensor_mode != smdk4x12_camera->camera_sensor_mode) { - smdk4x12_camera->camera_sensor_mode = camera_sensor_mode; - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_SENSOR_MODE, camera_sensor_mode); - if (rc < 0) - ALOGE("%s: Unable to set sensor mode", __func__); - } - - if (smdk4x12_camera->camera_fimc_is && fimc_is_mode != smdk4x12_camera->fimc_is_mode) { - smdk4x12_camera->fimc_is_mode = fimc_is_mode; - - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_IS_S_FORMAT_SCENARIO, smdk4x12_camera->fimc_is_mode); - if (rc < 0) - ALOGE("%s: Unable to set FIMC-IS scenario", __func__); - } - - // Focus - - focus_areas_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->focus_x || force) { - smdk4x12_camera->focus_x = focus_x; - - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_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 != smdk4x12_camera->focus_y || force) { - smdk4x12_camera->focus_y = focus_y; - - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_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 = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->focus_mode || force) { - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode); - if (rc < 0) - ALOGE("%s: Unable to set focus mode", __func__); - } - - smdk4x12_camera->focus_mode = focus_mode; - } - - // Zoom - - zoom_supported_string = smdk4x12_param_string_get(smdk4x12_camera, "zoom-supported"); - if (zoom_supported_string != NULL && strcmp(zoom_supported_string, "true") == 0) { - zoom = smdk4x12_param_int_get(smdk4x12_camera, "zoom"); - max_zoom = smdk4x12_param_int_get(smdk4x12_camera, "max-zoom"); - if (zoom <= max_zoom && zoom >= 0 && (zoom != smdk4x12_camera->zoom || force)) { - smdk4x12_camera->zoom = zoom; - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_ZOOM, zoom); - if (rc < 0) - ALOGE("%s: Unable to set camera zoom", __func__); - } - - } - - // AE lock - - ae_lock_supported_string = smdk4x12_param_string_get(smdk4x12_camera, "auto-exposure-lock-supported"); - ae_lock_string = smdk4x12_param_string_get(smdk4x12_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 = smdk4x12_param_string_get(smdk4x12_camera, "auto-whitebalance-lock-supported"); - awb_lock_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->ae_lock || awb_lock != smdk4x12_camera->awb_lock || force) { - smdk4x12_camera->ae_lock = ae_lock; - smdk4x12_camera->awb_lock = awb_lock; - aeawb = (ae_lock ? 0x1 : 0x0) | (awb_lock ? 0x2 : 0x0); - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK, aeawb); - if (rc < 0) - ALOGE("%s: Unable to set AEAWB lock", __func__); - } - - // Flash - - flash_mode_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->flash_mode || force) { - smdk4x12_camera->flash_mode = flash_mode; - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_FLASH_MODE, flash_mode); - if (rc < 0) - ALOGE("%s:Unable to set flash mode", __func__); - } - } - - // Exposure - - exposure_compensation = smdk4x12_param_int_get(smdk4x12_camera, "exposure-compensation"); - min_exposure_compensation = smdk4x12_param_int_get(smdk4x12_camera, "min-exposure-compensation"); - max_exposure_compensation = smdk4x12_param_int_get(smdk4x12_camera, "max-exposure-compensation"); - - if (exposure_compensation <= max_exposure_compensation && exposure_compensation >= min_exposure_compensation && - (exposure_compensation != smdk4x12_camera->exposure_compensation || force)) { - smdk4x12_camera->exposure_compensation = exposure_compensation; - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_BRIGHTNESS, exposure_compensation); - if (rc < 0) - ALOGE("%s: Unable to set exposure", __func__); - } - - // Antibanding - - antibanding_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->antibanding || force) { - smdk4x12_camera->antibanding = antibanding; - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_ANTI_BANDING, antibanding); - if (rc < 0) - ALOGE("%s: Unable to set antibanding", __func__); - } - } - - // WB - - whitebalance_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->whitebalance || force) { - smdk4x12_camera->whitebalance = whitebalance; - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_WHITE_BALANCE, whitebalance); - if (rc < 0) - ALOGE("%s: Unable to set whitebalance", __func__); - } - } - - // Scene mode - - scene_mode_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->scene_mode || force) { - smdk4x12_camera->scene_mode = scene_mode; - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_SCENE_MODE, scene_mode); - if (rc < 0) - ALOGE("%s: Unable to set scene mode", __func__); - } - } - - // Effect - - effect_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->effect || force) { - smdk4x12_camera->effect = effect; - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_EFFECT, effect); - if (rc < 0) - ALOGE("%s: Unable to set effect", __func__); - } - } - - // ISO - - iso_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->iso || force) { - smdk4x12_camera->iso = iso; - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_ISO, iso); - if (rc < 0) - ALOGE("%s: Unable to set iso", __func__); - } - } - - // Image stabilization - - image_stabilization_string = smdk4x12_param_string_get(smdk4x12_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 != smdk4x12_camera->image_stabilization || force) { - smdk4x12_camera->image_stabilization = image_stabilization; - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_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; -} - -// 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 *exif_flash, int *exif_iso, int *exif_exposure, - int *exif_exposure_bias, int *exif_exposure_time) -{ - 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 || exif_flash == NULL || exif_iso == NULL || exif_exposure == NULL || exif_exposure_bias == NULL || exif_exposure_time == 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_AF_STATUS_FOCUSING: - case S5C73M3_CAF_STATUS_FOCUSING: - *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_AF_STATUS_INVALID: - case S5C73M3_CAF_STATUS_FIND_SEARCHING_DIR: - case S5C73M3_AF_STATUS_UNFOCUSED: - case S5C73M3_CAF_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 += 4; // EXIF flash offset - *exif_flash = (int) *data_p; - - data_p += 4; // EXIF ISO offset - *exif_iso = (int) ((data_p[1] << 8) | (data_p[0] & 0xff)); - - data_p += 4; // EXIF exposure offset - *exif_exposure = (int) *data_p; - - data_p += 4; // EXIF exposure bias offset - *exif_exposure_bias = (int) ((data_p[1] << 8) | (data_p[0] & 0xff)); - - data_p += 8; // EXIF exposure time offset - *exif_exposure_time = (int) ((data_p[1] << 8) | (data_p[0] & 0xff)); - - 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 smdk4x12_camera_capture(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_camera_capture_listener *listener; - struct smdk4x12_camera_buffer *buffers = NULL; - struct smdk4x12_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 (smdk4x12_camera == NULL) - return -EINVAL; - - width = smdk4x12_camera->capture_width; - height = smdk4x12_camera->capture_height; - format = smdk4x12_camera->capture_format; - - buffers_count = smdk4x12_camera->capture_buffers_count; - buffer_length = smdk4x12_camera->capture_buffer_length; - - // V4L2 - - index = smdk4x12_v4l2_dqbuf_cap(smdk4x12_camera, 0); - if (index < 0 || index >= buffers_count) { - rc = smdk4x12_v4l2_poll(smdk4x12_camera, 0); - if (rc < 0) { - ALOGE("%s Unable to poll", __func__); - goto error; - } else if (rc == 0) { - // Timeout - rc = 0; - goto complete; - } - - index = smdk4x12_v4l2_dqbuf_cap(smdk4x12_camera, 0); - if (index < 0 || index >= buffers_count) { - ALOGE("%s: Unable to dequeue buffer", __func__); - goto error; - } - } - - smdk4x12_camera->capture_memory_index = index; - - address = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_PADDR_Y, index); - if (address == 0 || address == (int) 0xffffffff) { - ALOGE("%s: Unable to get address", __func__); - goto error; - } - - offset = address - smdk4x12_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 *) smdk4x12_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, smdk4x12_camera->capture_yuv_buffer, &yuv_length, width, height, smdk4x12_camera->capture_jpeg_buffer, &jpeg_length, &decoded, &auto_focus_result, &smdk4x12_camera->capture_exif_flash, &smdk4x12_camera->capture_exif_iso, &smdk4x12_camera->capture_exif_exposure, &smdk4x12_camera->capture_exif_exposure_bias, &smdk4x12_camera->capture_exif_exposure_time); - if (rc < 0) { - ALOGE("%s: Unable to decode S5C73M3 interleaved", __func__); - goto error; - } - - if (auto_focus_result != smdk4x12_camera->auto_focus_result) { - if (!smdk4x12_camera->auto_focus_thread_enabled) { - smdk4x12_camera->auto_focus_result = auto_focus_result; - - rc = smdk4x12_camera_auto_focus(smdk4x12_camera, auto_focus_result); - if (rc < 0) { - ALOGE("%s: Unable to auto focus", __func__); - goto error; - } - } - } - - if (!decoded) { - buffers_count = 1; - buffers = (struct smdk4x12_camera_buffer *) calloc(buffers_count, sizeof(struct smdk4x12_camera_buffer)); - - buffer = buffers; - - buffer->pointer = pointer; - buffer->address = address; - buffer->length = smdk4x12_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 smdk4x12_camera_buffer *) calloc(buffers_count, sizeof(struct smdk4x12_camera_buffer)); - - buffer = buffers; - - memcpy(pointer, smdk4x12_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 smdk4x12_camera_buffer *) ((unsigned char *) buffer + sizeof(struct smdk4x12_camera_buffer)); - - memcpy(pointer, smdk4x12_camera->capture_jpeg_buffer, jpeg_length); - - buffer->pointer = pointer; - buffer->address = address; - buffer->length = jpeg_length; - buffer->width = smdk4x12_camera->picture_width; - buffer->height = smdk4x12_camera->picture_height; - buffer->format = V4L2_PIX_FMT_JPEG; - - smdk4x12_camera->capture_hybrid = 0; - } - break; - case V4L2_PIX_FMT_JPEG: - jpeg_size = jpeg_offset = 0; - jpeg_thumbnail_size = jpeg_thumbnail_offset = 0; - - rc = smdk4x12_v4l2_g_ctrl(smdk4x12_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 = smdk4x12_v4l2_g_ctrl(smdk4x12_camera, 0, V4L2_CID_CAM_JPEG_MAIN_OFFSET, &jpeg_offset); - if (rc < 0) { - ALOGE("%s: Unable to get jpeg offset", __func__); - goto error; - } - - rc = smdk4x12_v4l2_g_ctrl(smdk4x12_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 = smdk4x12_v4l2_g_ctrl(smdk4x12_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 smdk4x12_camera_buffer *) calloc(buffers_count, sizeof(struct smdk4x12_camera_buffer)); - - buffer = buffers; - - buffer->pointer = (void *) ((unsigned char *) pointer + jpeg_offset); - buffer->address = address + jpeg_offset; - buffer->length = jpeg_size; - buffer->width = smdk4x12_camera->picture_width; - buffer->height = smdk4x12_camera->picture_height; - buffer->format = V4L2_PIX_FMT_JPEG; - - buffer = (struct smdk4x12_camera_buffer *) ((unsigned char *) buffer + sizeof(struct smdk4x12_camera_buffer)); - - buffer->pointer = (void *) ((unsigned char *) pointer + jpeg_thumbnail_offset); - buffer->address = address + jpeg_thumbnail_offset; - buffer->length = jpeg_thumbnail_size; - buffer->width = smdk4x12_camera->jpeg_thumbnail_width; - buffer->height = smdk4x12_camera->jpeg_thumbnail_height; - buffer->format = V4L2_PIX_FMT_JPEG; - break; - default: - buffers_count = 1; - buffers = (struct smdk4x12_camera_buffer *) calloc(buffers_count, sizeof(struct smdk4x12_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 *) smdk4x12_camera->capture_listeners; - while (list != NULL) { - listener = (struct smdk4x12_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(smdk4x12_camera, buffers, buffers_count); - -list_continue_callback: - list = list->next; - } - - do { - busy = 0; - - list = (struct list_head *) smdk4x12_camera->capture_listeners; - while (list != NULL) { - listener = (struct smdk4x12_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 = smdk4x12_v4l2_qbuf_cap(smdk4x12_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 *smdk4x12_camera_capture_thread(void *data) -{ - struct smdk4x12_camera *smdk4x12_camera; - int rc; - - if (data == NULL) - return NULL; - - smdk4x12_camera = (struct smdk4x12_camera *) data; - - ALOGE("%s: Starting thread", __func__); - smdk4x12_camera->capture_thread_running = 1; - - while (smdk4x12_camera->capture_thread_enabled) { - pthread_mutex_lock(&smdk4x12_camera->capture_lock_mutex); - - while (smdk4x12_camera->capture_enabled) { - pthread_mutex_lock(&smdk4x12_camera->capture_mutex); - - if (!smdk4x12_camera->capture_enabled) { - pthread_mutex_unlock(&smdk4x12_camera->capture_mutex); - break; - } - - rc = smdk4x12_camera_capture(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to capture", __func__); - pthread_mutex_unlock(&smdk4x12_camera->capture_mutex); - break; - } - - pthread_mutex_unlock(&smdk4x12_camera->capture_mutex); - - // Wait a bit to let others lock the mutex if they need to - usleep(10); - } - } - - smdk4x12_camera->capture_thread_running = 0; - ALOGE("%s: Exiting thread", __func__); - - return NULL; -} - -int smdk4x12_camera_capture_thread_start(struct smdk4x12_camera *smdk4x12_camera) -{ - pthread_attr_t thread_attr; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - ALOGD("%s()", __func__); - - if (smdk4x12_camera->capture_thread_enabled) { - ALOGE("Capture thread was already started!"); - return -1; - } - - pthread_mutex_init(&smdk4x12_camera->capture_mutex, NULL); - pthread_mutex_init(&smdk4x12_camera->capture_lock_mutex, NULL); - - // Initial lock - pthread_mutex_lock(&smdk4x12_camera->capture_lock_mutex); - - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - - smdk4x12_camera->capture_thread_enabled = 1; - - rc = pthread_create(&smdk4x12_camera->capture_thread, &thread_attr, smdk4x12_camera_capture_thread, (void *) smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to create thread", __func__); - goto error; - } - - rc = 0; - goto complete; - -error: - pthread_mutex_destroy(&smdk4x12_camera->capture_mutex); - pthread_mutex_destroy(&smdk4x12_camera->capture_lock_mutex); - - rc = -1; - -complete: - return rc; -} - -void smdk4x12_camera_capture_thread_stop(struct smdk4x12_camera *smdk4x12_camera) -{ - int i; - - if (smdk4x12_camera == NULL) - return; - - ALOGD("%s()", __func__); - - if (!smdk4x12_camera->capture_thread_enabled) { - ALOGE("Capture thread was already stopped!"); - return; - } - - smdk4x12_camera->capture_enabled = 0; - smdk4x12_camera->capture_thread_enabled = 0; - - pthread_mutex_unlock(&smdk4x12_camera->capture_lock_mutex); - - // Wait for the thread to end - i = 0; - while (smdk4x12_camera->capture_thread_running) { - if (i++ > 10000) { - ALOGE("Capture thread is taking too long to end, something is going wrong"); - break; - } - usleep(100); - } - - if (smdk4x12_camera->capture_enabled) { - pthread_mutex_lock(&smdk4x12_camera->capture_mutex); - smdk4x12_camera_capture_stop(smdk4x12_camera); - pthread_mutex_unlock(&smdk4x12_camera->capture_mutex); - } - - pthread_mutex_destroy(&smdk4x12_camera->capture_mutex); - pthread_mutex_destroy(&smdk4x12_camera->capture_lock_mutex); -} - -int smdk4x12_camera_capture_start(struct smdk4x12_camera *smdk4x12_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 (smdk4x12_camera == NULL) - return -EINVAL; - - ALOGD("%s()", __func__); - - if (smdk4x12_camera->capture_enabled) { - ALOGE("Capture was already started!"); - return -1; - } - - width = smdk4x12_camera->capture_width; - height = smdk4x12_camera->capture_height; - format = smdk4x12_camera->capture_format; - - // V4L2 - - if (format == V4L2_PIX_FMT_INTERLEAVED) { - ALOGD("Enabling hybrid capture"); - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_HYBRID, 1); - if (rc < 0) { - ALOGE("%s: Unable to set hybrid", __func__); - goto error; - } - } - - if (smdk4x12_camera->camera_fimc_is) { - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_IS_S_FORMAT_SCENARIO, smdk4x12_camera->fimc_is_mode); - if (rc < 0) { - ALOGE("%s: Unable to set FIMC-IS scenario", __func__); - goto error; - } - } - - rc = smdk4x12_v4l2_enum_fmt_cap(smdk4x12_camera, 0, format); - if (rc < 0) { - ALOGE("%s: Unable to enumerate formats", __func__); - goto error; - } - - mbus_width = width; - mbus_height = height; - - if (smdk4x12_camera->camera_mbus_resolutions != NULL) { - for (i = 0; i < smdk4x12_camera->camera_mbus_resolutions_count; i++) { - if (smdk4x12_camera->camera_mbus_resolutions[i].width == width && smdk4x12_camera->camera_mbus_resolutions[i].height == height) { - mbus_width = smdk4x12_camera->camera_mbus_resolutions[i].mbus_width; - mbus_height = smdk4x12_camera->camera_mbus_resolutions[i].mbus_height; - break; - } - } - } - - if (smdk4x12_camera->camera_fimc_is) { - // Set MBUS width/height/format - rc = smdk4x12_v4l2_s_fmt_pix(smdk4x12_camera, 0, V4L2_BUF_TYPE_PRIVATE, mbus_width, mbus_height, format, smdk4x12_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 = smdk4x12_v4l2_s_fmt_pix_cap(smdk4x12_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 (!smdk4x12_camera->camera_fimc_is) { - // Set MBUS width/height/format - rc = smdk4x12_v4l2_s_fmt_pix(smdk4x12_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 = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CACHEABLE, 0); - else - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CACHEABLE, 1); - if (rc < 0) { - ALOGE("%s: Unable to set cacheable", __func__); - goto error; - } - - if (smdk4x12_camera->camera_fimc_is) { - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_IS_S_SCENARIO_MODE, smdk4x12_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 = smdk4x12_v4l2_s_ctrl(smdk4x12_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 = SMDK4x12_CAMERA_CAPTURE_BUFFERS_COUNT; i > 0; i--) { - rc = smdk4x12_v4l2_reqbufs_cap(smdk4x12_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 = smdk4x12_camera->preview_fps; - - rc = smdk4x12_v4l2_s_parm_cap(smdk4x12_camera, 0, &fps_param); - if (rc < 0) { - ALOGE("%s: Unable to set fps", __func__); - goto error; - } - - for (i = 0; i < buffers_count; i++) { - rc = smdk4x12_v4l2_querybuf_cap(smdk4x12_camera, 0, i); - if (rc < 0) { - ALOGE("%s: Unable to query buffers", __func__); - goto error; - } - } - - buffer_length = rc; - - value = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_PADDR_Y, 0); - if (value == 0 || value == (int) 0xffffffff) { - ALOGE("%s: Unable to get address", __func__); - goto error; - } - - smdk4x12_camera->capture_memory_address = value; - - if (SMDK4x12_CAMERA_CALLBACK_DEFINED(request_memory)) { - fd = smdk4x12_v4l2_fd(smdk4x12_camera, 0); - if (fd < 0) { - ALOGE("%s: Unable to get v4l2 fd for id %d", __func__, 0); - goto error; - } - - smdk4x12_camera->capture_memory = NULL; - - memory = smdk4x12_camera->callbacks.request_memory(fd, buffer_length, buffers_count, smdk4x12_camera->callbacks.user); - if (memory == NULL || memory->data == NULL || memory->data == MAP_FAILED) { - ALOGE("%s: Unable to request memory", __func__); - goto error; - } - - smdk4x12_camera->capture_memory = memory; - } else { - ALOGE("%s: No memory request function!", __func__); - goto error; - } - - if (format == V4L2_PIX_FMT_INTERLEAVED) { - smdk4x12_camera->capture_yuv_buffer = malloc(buffer_length); - smdk4x12_camera->capture_jpeg_buffer = malloc(buffer_length); - } - - for (i = 0; i < buffers_count; i++) { - rc = smdk4x12_v4l2_qbuf_cap(smdk4x12_camera, 0, i); - if (rc < 0) { - ALOGE("%s: Unable to queue buffer", __func__); - goto error; - } - } - - smdk4x12_camera->capture_buffers_count = buffers_count; - smdk4x12_camera->capture_buffer_length = buffer_length; - - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_ROTATION, - smdk4x12_camera->camera_rotation); - if (rc < 0) { - ALOGE("%s: Unable to set rotation", __func__); - goto error; - } - - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_HFLIP, - smdk4x12_camera->camera_hflip); - if (rc < 0) { - ALOGE("%s: Unable to set hflip", __func__); - goto error; - } - - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_VFLIP, - smdk4x12_camera->camera_vflip); - if (rc < 0) { - ALOGE("%s: Unable to set vflip", __func__); - goto error; - } - - rc = smdk4x12_v4l2_streamon_cap(smdk4x12_camera, 0); - if (rc < 0) { - ALOGE("%s: Unable to start stream", __func__); - goto error; - } - - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_SCENE_MODE, smdk4x12_camera->scene_mode); - if (rc < 0) { - ALOGE("%s: Unable to set scene mode", __func__); - goto error; - } - - smdk4x12_camera->capture_enabled = 1; - pthread_mutex_unlock(&smdk4x12_camera->capture_lock_mutex); - - rc = 0; - goto complete; - -error: - if (smdk4x12_camera->capture_memory != NULL && smdk4x12_camera->capture_memory->release != NULL) { - smdk4x12_camera->capture_memory->release(smdk4x12_camera->capture_memory); - smdk4x12_camera->capture_memory = NULL; - } - - rc = -1; - -complete: - return rc; -} - -void smdk4x12_camera_capture_stop(struct smdk4x12_camera *smdk4x12_camera) -{ - int rc; - int i; - - if (smdk4x12_camera == NULL) - return; - - ALOGD("%s()", __func__); - - if (!smdk4x12_camera->capture_enabled) { - ALOGE("Capture was already stopped!"); - return; - } - - if (smdk4x12_camera->capture_format == V4L2_PIX_FMT_INTERLEAVED) { - ALOGD("Disabling hybrid capture"); - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_HYBRID, 0); - if (rc < 0) - ALOGE("%s: Unable to set hybrid", __func__); - } - - rc = smdk4x12_v4l2_streamoff_cap(smdk4x12_camera, 0); - if (rc < 0) { - ALOGE("%s: Unable to stop stream", __func__); - } - - if (smdk4x12_camera->capture_memory != NULL && smdk4x12_camera->capture_memory->release != NULL) { - smdk4x12_camera->capture_memory->release(smdk4x12_camera->capture_memory); - smdk4x12_camera->capture_memory = NULL; - } - - if (smdk4x12_camera->capture_yuv_buffer != NULL) { - free(smdk4x12_camera->capture_yuv_buffer); - smdk4x12_camera->capture_yuv_buffer = NULL; - } - - if (smdk4x12_camera->capture_jpeg_buffer != NULL) { - free(smdk4x12_camera->capture_jpeg_buffer); - smdk4x12_camera->capture_jpeg_buffer = NULL; - } - - smdk4x12_camera->capture_enabled = 0; -} - -int smdk4x12_camera_capture_setup(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_camera_capture_listener *listener; - struct list_head *list; - int width, height, format; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - ALOGD("%s()", __func__); - - // No listener left - if (smdk4x12_camera->capture_listeners == NULL && smdk4x12_camera->capture_enabled) { - smdk4x12_camera_capture_stop(smdk4x12_camera); - return 0; - } - - width = height = format = 0; - - list = (struct list_head *) smdk4x12_camera->capture_listeners; - while (list != NULL) { - listener = (struct smdk4x12_camera_capture_listener *) list; - - // Interleaved format already has the correct width and height for picture set through ioctl - if (smdk4x12_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 (smdk4x12_camera->camera_capture_format) - format = smdk4x12_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 = smdk4x12_camera->preview_width; - height = smdk4x12_camera->preview_height; - } - - ALOGD("%s: Selected width: %d, height: %d, format: 0x%x", __func__, width, height, format); - - if (!smdk4x12_camera->capture_enabled) { - smdk4x12_camera->capture_width = width; - smdk4x12_camera->capture_height = height; - smdk4x12_camera->capture_format = format; - - rc = smdk4x12_camera_capture_start(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to start capture", __func__); - return -1; - } - } else if (smdk4x12_camera->capture_width != width || smdk4x12_camera->capture_height != height || smdk4x12_camera->capture_format != format) { - smdk4x12_camera_capture_stop(smdk4x12_camera); - - smdk4x12_camera->capture_width = width; - smdk4x12_camera->capture_height = height; - smdk4x12_camera->capture_format = format; - - rc = smdk4x12_camera_capture_start(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to start capture", __func__); - return -1; - } - } - - return 0; -} - -struct smdk4x12_camera_capture_listener *smdk4x12_camera_capture_listener_register( - struct smdk4x12_camera *smdk4x12_camera, int width, int height, int format, - int (*callback)(struct smdk4x12_camera *smdk4x12_camera, struct smdk4x12_camera_buffer *buffers, int buffers_count)) -{ - struct smdk4x12_camera_capture_listener *listener = NULL; - struct list_head *list_end; - struct list_head *list; - int rc; - - if (smdk4x12_camera == NULL || callback == NULL) - return NULL; - - pthread_mutex_lock(&smdk4x12_camera->capture_mutex); - - listener = calloc(1, sizeof(struct smdk4x12_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 *) smdk4x12_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 (smdk4x12_camera->capture_listeners == NULL) - smdk4x12_camera->capture_listeners = listener; - - rc = smdk4x12_camera_capture_setup(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to setup capture", __func__); - goto error; - } - - rc = 0; - goto complete; - -error: - listener = NULL; - -complete: - pthread_mutex_unlock(&smdk4x12_camera->capture_mutex); - - return listener; -} - -void smdk4x12_camera_capture_listener_unregister( - struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_camera_capture_listener *listener) -{ - struct list_head *list; - int rc; - - if (smdk4x12_camera == NULL || listener == NULL) - return; - - pthread_mutex_lock(&smdk4x12_camera->capture_mutex); - - list = (struct list_head *) smdk4x12_camera->capture_listeners; - while (list != NULL) { - if ((void *) list == (void *) listener) { - list_head_remove(list); - - if ((void *) list == (void *) smdk4x12_camera->capture_listeners) - smdk4x12_camera->capture_listeners = (struct smdk4x12_camera_capture_listener *) list->next; - - memset(listener, 0, sizeof(struct smdk4x12_camera_capture_listener)); - free(listener); - - break; - } -list_continue: - list = list->next; - } - - rc = smdk4x12_camera_capture_setup(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to setup capture", __func__); - goto complete; - } - -complete: - pthread_mutex_unlock(&smdk4x12_camera->capture_mutex); -} - -// Preview - -int smdk4x12_camera_preview_output_start(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_v4l2_output *output; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - ALOGD("%s()", __func__); - - if (smdk4x12_camera->preview_output_enabled) { - ALOGE("Preview was already started!"); - return -1; - } - - output = &smdk4x12_camera->preview_output; - - memset(output, 0, sizeof(struct smdk4x12_v4l2_output)); - output->v4l2_id = 1; - output->width = smdk4x12_camera->preview_width; - output->height = smdk4x12_camera->preview_height; - output->format = smdk4x12_camera->preview_format; - output->buffer_width = smdk4x12_camera->preview_buffer.width; - output->buffer_height = smdk4x12_camera->preview_buffer.height; - output->buffer_format = smdk4x12_camera->preview_buffer.format; - output->buffers_count = SMDK4x12_CAMERA_PREVIEW_BUFFERS_COUNT; - - rc = smdk4x12_v4l2_output_start(smdk4x12_camera, output); - if (rc < 0) { - ALOGE("%s: Unable to start preview output", __func__); - goto error; - } - - smdk4x12_camera->preview_output_enabled = 1; - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - return rc; -} - -void smdk4x12_camera_preview_output_stop(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_v4l2_output *output; - - if (smdk4x12_camera == NULL) - return; - - ALOGD("%s()", __func__); - - if (!smdk4x12_camera->preview_output_enabled) { - ALOGE("Preview was already stopped!"); - return; - } - - output = &smdk4x12_camera->preview_output; - - smdk4x12_v4l2_output_stop(smdk4x12_camera, output); - - smdk4x12_camera->preview_output_enabled = 0; -} - -int smdk4x12_camera_preview_callback(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_camera_buffer *buffers, int buffers_count) -{ - struct smdk4x12_camera_buffer *buffer = NULL; - int width, height, format; - int buffer_width, buffer_height, buffer_format; - int rc; - int i; - - if (smdk4x12_camera == NULL || buffers == NULL || buffers_count <= 0) - return -EINVAL; - -// ALOGD("%s()", __func__); - - if (smdk4x12_camera->preview_listener == NULL) - return -1; - - if (smdk4x12_camera->preview_listener->busy) { - ALOGE("%s: Dropping buffer", __func__); - return 0; - } - - if (smdk4x12_camera->preview_listener->width != smdk4x12_camera->preview_width || smdk4x12_camera->preview_listener->height != smdk4x12_camera->preview_height || smdk4x12_camera->preview_listener->format != smdk4x12_camera->preview_format) { - ALOGD("%s: Waiting for preview listener update", __func__); - pthread_mutex_unlock(&smdk4x12_camera->preview_lock_mutex); - return 0; - } - - smdk4x12_camera->preview_listener->busy = 1; - - width = smdk4x12_camera->preview_width; - height = smdk4x12_camera->preview_height; - format = smdk4x12_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 smdk4x12_camera_buffer *) ((unsigned char *) buffers + sizeof(struct smdk4x12_camera_buffer)); - } - - if (buffer == NULL) { - ALOGE("%s: Unable to find an appropriate buffer for preview", __func__); - smdk4x12_camera->preview_listener->busy = 0; - return 0; - } - - buffer_width = buffer->width; - buffer_height = buffer->height; - buffer_format = buffer->format; - - pthread_mutex_lock(&smdk4x12_camera->preview_mutex); - - if (buffer_width != width || buffer_height != height || buffer_format != format) { - if (!smdk4x12_camera->preview_output_enabled) { - memcpy(&smdk4x12_camera->preview_buffer, buffer, sizeof(struct smdk4x12_camera_buffer)); - - rc = smdk4x12_camera_preview_output_start(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to start preview", __func__); - goto error; - } - } else if (smdk4x12_camera->preview_buffer.width != buffer_width || smdk4x12_camera->preview_buffer.height != buffer_height || smdk4x12_camera->preview_buffer.format != buffer_format) { - smdk4x12_camera_preview_output_stop(smdk4x12_camera); - - memcpy(&smdk4x12_camera->preview_buffer, buffer, sizeof(struct smdk4x12_camera_buffer)); - - rc = smdk4x12_camera_preview_output_start(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to start preview", __func__); - goto error; - } - } else { - memcpy(&smdk4x12_camera->preview_buffer, buffer, sizeof(struct smdk4x12_camera_buffer)); - } - } else { - // The buffer format exactly matches our expectations - - if (smdk4x12_camera->preview_output_enabled) - smdk4x12_camera_preview_output_stop(smdk4x12_camera); - - memcpy(&smdk4x12_camera->preview_buffer, buffer, sizeof(struct smdk4x12_camera_buffer)); - } - - pthread_mutex_unlock(&smdk4x12_camera->preview_lock_mutex); - - pthread_mutex_unlock(&smdk4x12_camera->preview_mutex); - - rc = 0; - goto complete; - -error: - pthread_mutex_unlock(&smdk4x12_camera->preview_mutex); - - smdk4x12_camera->preview_listener->busy = 0; - - rc = -1; - -complete: - return rc; -} - -int smdk4x12_camera_preview(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_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 (smdk4x12_camera == NULL) - goto error; - -// ALOGD("%s()", __func__); - - width = smdk4x12_camera->preview_width; - height = smdk4x12_camera->preview_height; - format = smdk4x12_camera->preview_format; - - output = &smdk4x12_camera->preview_output; - - if (smdk4x12_camera->preview_output_enabled) { - rc = smdk4x12_v4l2_output(smdk4x12_camera, output, smdk4x12_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 = smdk4x12_camera->capture_memory; - memory_index = smdk4x12_camera->capture_memory_index; - memory_pointer = smdk4x12_camera->preview_buffer.pointer; - memory_size = smdk4x12_camera->preview_buffer.length; - } - - if (smdk4x12_camera->preview_window != NULL && smdk4x12_camera->gralloc != NULL) { - smdk4x12_camera->preview_window->dequeue_buffer(smdk4x12_camera->preview_window, &window_buffer, &window_stride); - smdk4x12_camera->gralloc->lock(smdk4x12_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); - - smdk4x12_camera->gralloc->unlock(smdk4x12_camera->gralloc, *window_buffer); - smdk4x12_camera->preview_window->enqueue_buffer(smdk4x12_camera->preview_window, window_buffer); - } - - if (SMDK4x12_CAMERA_MSG_ENABLED(CAMERA_MSG_PREVIEW_FRAME) && SMDK4x12_CAMERA_CALLBACK_DEFINED(data) && !smdk4x12_camera->callback_lock) { - smdk4x12_camera->callbacks.data(CAMERA_MSG_PREVIEW_FRAME, memory, memory_index, NULL, smdk4x12_camera->callbacks.user); - } - - if (smdk4x12_camera->preview_output_enabled) { - rc = smdk4x12_v4l2_output_release(smdk4x12_camera, output); - if (rc < 0) { - ALOGE("%s: Unable to release preview output", __func__); - goto error; - } - } - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - smdk4x12_camera->preview_listener->busy = 0; - - return rc; -} - -void *smdk4x12_camera_preview_thread(void *data) -{ - struct smdk4x12_camera *smdk4x12_camera; - struct smdk4x12_camera_capture_listener *listener; - int gralloc_format; - int rc; - - if (data == NULL) - return NULL; - - smdk4x12_camera = (struct smdk4x12_camera *) data; - - ALOGE("%s: Starting thread", __func__); - smdk4x12_camera->preview_thread_running = 1; - - while (smdk4x12_camera->preview_thread_enabled) { - pthread_mutex_lock(&smdk4x12_camera->preview_lock_mutex); - - pthread_mutex_lock(&smdk4x12_camera->preview_mutex); - - if (smdk4x12_camera->preview_listener == NULL) { - pthread_mutex_unlock(&smdk4x12_camera->preview_mutex); - break; - } - - if (smdk4x12_camera->preview_listener->busy) { - rc = smdk4x12_camera_preview(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to preview", __func__); - pthread_mutex_unlock(&smdk4x12_camera->preview_mutex); - break; - } - } - - if (smdk4x12_camera->preview_listener->width != smdk4x12_camera->preview_width || smdk4x12_camera->preview_listener->height != smdk4x12_camera->preview_height || smdk4x12_camera->preview_listener->format != smdk4x12_camera->preview_format) { - if (smdk4x12_camera->preview_output_enabled) - smdk4x12_camera_preview_output_stop(smdk4x12_camera); - - smdk4x12_camera_capture_listener_unregister(smdk4x12_camera, smdk4x12_camera->preview_listener); - - smdk4x12_camera->preview_listener = NULL; - - listener = smdk4x12_camera_capture_listener_register(smdk4x12_camera, smdk4x12_camera->preview_width, smdk4x12_camera->preview_height, smdk4x12_camera->preview_format, smdk4x12_camera_preview_callback); - if (listener == NULL) { - ALOGE("%s: Unable to register preview capture listener", __func__); - pthread_mutex_unlock(&smdk4x12_camera->preview_mutex); - break; - } - - smdk4x12_camera->preview_listener = listener; - - gralloc_format = smdk4x12_gralloc_format(smdk4x12_camera->preview_format); - - rc = smdk4x12_camera->preview_window->set_buffers_geometry(smdk4x12_camera->preview_window, smdk4x12_camera->preview_width, smdk4x12_camera->preview_height, gralloc_format); - if (rc) { - ALOGE("%s: Unable to set buffers geometry", __func__); - pthread_mutex_unlock(&smdk4x12_camera->preview_mutex); - break; - } - } - - pthread_mutex_unlock(&smdk4x12_camera->preview_mutex); - } - - smdk4x12_camera->preview_thread_running = 0; - ALOGE("%s: Exiting thread", __func__); - - return NULL; -} - -int smdk4x12_camera_preview_thread_start(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_camera_capture_listener *listener; - pthread_attr_t thread_attr; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - ALOGD("%s()", __func__); - - if (smdk4x12_camera->preview_thread_enabled) { - ALOGE("Preview thread was already started!"); - return -1; - } - - pthread_mutex_init(&smdk4x12_camera->preview_mutex, NULL); - pthread_mutex_init(&smdk4x12_camera->preview_lock_mutex, NULL); - - // Initial lock - pthread_mutex_lock(&smdk4x12_camera->preview_lock_mutex); - - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - - smdk4x12_camera->preview_thread_enabled = 1; - - rc = pthread_create(&smdk4x12_camera->preview_thread, &thread_attr, smdk4x12_camera_preview_thread, (void *) smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to create thread", __func__); - goto error; - } - - listener = smdk4x12_camera_capture_listener_register(smdk4x12_camera, smdk4x12_camera->preview_width, smdk4x12_camera->preview_height, smdk4x12_camera->preview_format, smdk4x12_camera_preview_callback); - if (listener == NULL) { - ALOGE("%s: Unable to register preview capture listener", __func__); - goto error; - } - - smdk4x12_camera->preview_listener = listener; - - rc = 0; - goto complete; - -error: - pthread_mutex_destroy(&smdk4x12_camera->preview_mutex); - pthread_mutex_destroy(&smdk4x12_camera->preview_lock_mutex); - - rc = -1; - -complete: - return rc; -} - -void smdk4x12_camera_preview_thread_stop(struct smdk4x12_camera *smdk4x12_camera) -{ - int i; - - if (smdk4x12_camera == NULL) - return; - - ALOGD("%s()", __func__); - - if (!smdk4x12_camera->preview_thread_enabled) { - ALOGE("Preview thread was already stopped!"); - return; - } - - if (smdk4x12_camera->preview_listener != NULL) { - smdk4x12_camera_capture_listener_unregister(smdk4x12_camera, smdk4x12_camera->preview_listener); - smdk4x12_camera->preview_listener = NULL; - } - - smdk4x12_camera->preview_thread_enabled = 0; - - pthread_mutex_unlock(&smdk4x12_camera->preview_lock_mutex); - - // Wait for the thread to end - i = 0; - while (smdk4x12_camera->preview_thread_running) { - if (i++ > 10000) { - ALOGE("Preview thread is taking too long to end, something is going wrong"); - break; - } - usleep(100); - } - - if (smdk4x12_camera->preview_output_enabled) { - pthread_mutex_lock(&smdk4x12_camera->preview_mutex); - smdk4x12_camera_preview_output_stop(smdk4x12_camera); - pthread_mutex_unlock(&smdk4x12_camera->preview_mutex); - } - - pthread_mutex_destroy(&smdk4x12_camera->preview_mutex); - pthread_mutex_destroy(&smdk4x12_camera->preview_lock_mutex); - - // Invalidate the preview window - smdk4x12_camera->preview_window = NULL; -} - -// Picture - -int smdk4x12_camera_picture_callback(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_camera_buffer *buffers, int buffers_count) -{ - struct smdk4x12_camera_buffer *jpeg_buffer = NULL; - struct smdk4x12_camera_buffer *jpeg_thumbnail_buffer = NULL; - struct smdk4x12_camera_buffer *yuv_buffer = NULL; - struct smdk4x12_camera_buffer *yuv_thumbnail_buffer = NULL; - int width, height; - int thumbnail_width, thumbnail_height; - time_t timestamp; - int rc; - int i; - - if (smdk4x12_camera == NULL || buffers == NULL || buffers_count <= 0) - return -EINVAL; - - ALOGD("%s()", __func__); - - width = smdk4x12_camera->picture_width; - height = smdk4x12_camera->picture_height; - thumbnail_width = smdk4x12_camera->jpeg_thumbnail_width; - thumbnail_height = smdk4x12_camera->jpeg_thumbnail_height; - - if (smdk4x12_camera->picture_completed) - return -1; - - if (smdk4x12_camera->picture_listener == NULL) - return -1; - - if (smdk4x12_camera->picture_listener->busy) { - ALOGE("%s: Dropping buffer", __func__); - return 0; - } - - ALOGE("%s: locking picture_mutex", __func__); - pthread_mutex_lock(&smdk4x12_camera->picture_mutex); - ALOGE("%s: locked picture_mutex", __func__); - - if (!smdk4x12_camera->picture_enabled && !smdk4x12_camera->camera_fimc_is) { - if (smdk4x12_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED && smdk4x12_camera->zoom == 0 && smdk4x12_camera->focus_mode == FOCUS_MODE_CONTINOUS_PICTURE) { - if (smdk4x12_camera->auto_focus_result == CAMERA_AF_STATUS_FAIL) { - // We don't want to take a picture out of focus, so wait a bit - timestamp = time(NULL); - - if (smdk4x12_camera->picture_focus_timestamp > 0) { - if ((timestamp - smdk4x12_camera->picture_focus_timestamp) > 2) { - ALOGE("%s: Picture will be taken out of focus", __func__); - } else { - pthread_mutex_unlock(&smdk4x12_camera->picture_mutex); - return 0; - } - } else { - smdk4x12_camera->picture_focus_timestamp = timestamp; - pthread_mutex_unlock(&smdk4x12_camera->picture_mutex); - return 0; - } - } else if (smdk4x12_camera->auto_focus_result == CAMERA_AF_STATUS_IN_PROGRESS) { - ALOGD("%s: Not asking for picture until auto focus is done", __func__); - pthread_mutex_unlock(&smdk4x12_camera->picture_mutex); - return 0; - } - } - - smdk4x12_camera->picture_focus_timestamp = 0; - - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_CAPTURE, 0); - if (rc < 0) { - ALOGE("%s: Unable to set capture", __func__); - goto error; - } - - if (smdk4x12_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED && !smdk4x12_camera->capture_hybrid) { - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_HYBRID_CAPTURE, 1); - if (rc < 0) { - ALOGE("%s: Unable to set hybrid capture", __func__); - goto error; - } - - smdk4x12_camera->capture_hybrid = 1; - } - - smdk4x12_camera->picture_enabled = 1; - - pthread_mutex_unlock(&smdk4x12_camera->picture_mutex); - return 0; - } - - ALOGE("%s: unlocking picture_mutex", __func__); - pthread_mutex_unlock(&smdk4x12_camera->picture_mutex); - ALOGE("%s: unlocked picture_mutex", __func__); - - smdk4x12_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 smdk4x12_camera_buffer *) ((unsigned char *) buffers + sizeof(struct smdk4x12_camera_buffer)); - } - - if (jpeg_buffer == NULL && yuv_buffer == NULL) { - ALOGE("%s: Unable to find an appropriate buffer for picture", __func__); - smdk4x12_camera->picture_listener->busy = 0; - return 0; - } - - // Interleaved must not use a preview frame as picture - if (smdk4x12_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED && jpeg_buffer == NULL) { - smdk4x12_camera->picture_listener->busy = 0; - return 0; - } - - pthread_mutex_lock(&smdk4x12_camera->picture_mutex); - - if (jpeg_buffer == NULL) - memset(&smdk4x12_camera->picture_jpeg_buffer, 0, sizeof(smdk4x12_camera->picture_jpeg_buffer)); - else - memcpy(&smdk4x12_camera->picture_jpeg_buffer, jpeg_buffer, sizeof(struct smdk4x12_camera_buffer)); - - if (jpeg_thumbnail_buffer == NULL) - memset(&smdk4x12_camera->picture_jpeg_thumbnail_buffer, 0, sizeof(smdk4x12_camera->picture_jpeg_thumbnail_buffer)); - else - memcpy(&smdk4x12_camera->picture_jpeg_thumbnail_buffer, jpeg_thumbnail_buffer, sizeof(struct smdk4x12_camera_buffer)); - - if (yuv_buffer == NULL) - memset(&smdk4x12_camera->picture_yuv_buffer, 0, sizeof(smdk4x12_camera->picture_yuv_buffer)); - else - memcpy(&smdk4x12_camera->picture_yuv_buffer, yuv_buffer, sizeof(struct smdk4x12_camera_buffer)); - - if (yuv_thumbnail_buffer == NULL) - memset(&smdk4x12_camera->picture_yuv_thumbnail_buffer, 0, sizeof(smdk4x12_camera->picture_yuv_thumbnail_buffer)); - else - memcpy(&smdk4x12_camera->picture_yuv_thumbnail_buffer, yuv_thumbnail_buffer, sizeof(struct smdk4x12_camera_buffer)); - - pthread_mutex_unlock(&smdk4x12_camera->picture_lock_mutex); - - pthread_mutex_unlock(&smdk4x12_camera->picture_mutex); - - rc = 0; - goto complete; - -error: - pthread_mutex_unlock(&smdk4x12_camera->picture_mutex); - - smdk4x12_camera->picture_listener->busy = 0; - - rc = -1; - -complete: - return rc; -} - -int smdk4x12_camera_picture(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_camera_buffer *jpeg_buffer; - struct smdk4x12_camera_buffer *jpeg_thumbnail_buffer; - struct smdk4x12_camera_buffer *yuv_buffer; - struct smdk4x12_camera_buffer *yuv_thumbnail_buffer; - struct smdk4x12_v4l2_output output; - struct smdk4x12_jpeg jpeg; - struct smdk4x12_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 (smdk4x12_camera == NULL) - goto error; - -// ALOGD("%s()", __func__); - - jpeg_buffer = &smdk4x12_camera->picture_jpeg_buffer; - jpeg_thumbnail_buffer = &smdk4x12_camera->picture_jpeg_thumbnail_buffer; - yuv_buffer = &smdk4x12_camera->picture_yuv_buffer; - yuv_thumbnail_buffer = &smdk4x12_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 = smdk4x12_camera->picture_width; - height = smdk4x12_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 = SMDK4x12_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 = smdk4x12_v4l2_output_start(smdk4x12_camera, &output); - if (rc < 0) { - ALOGE("%s: Unable to start picture output", __func__); - goto error; - } - - rc = smdk4x12_v4l2_output(smdk4x12_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 = smdk4x12_camera->jpeg_quality; - - rc = smdk4x12_jpeg_start(smdk4x12_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 = smdk4x12_jpeg(smdk4x12_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 (SMDK4x12_CAMERA_CALLBACK_DEFINED(request_memory)) { - jpeg_memory = smdk4x12_camera->callbacks.request_memory(-1, jpeg_size, 1, smdk4x12_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); - - smdk4x12_jpeg_stop(smdk4x12_camera, &jpeg); - - if (output_enabled) { - smdk4x12_v4l2_output_stop(smdk4x12_camera, &output); - output_enabled = 0; - } - } - - ALOGE("%s: finished jpeg", __func__); - - // 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 = smdk4x12_camera->jpeg_thumbnail_width; - height = smdk4x12_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 = SMDK4x12_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 = smdk4x12_v4l2_output_start(smdk4x12_camera, &output); - if (rc < 0) { - ALOGE("%s: Unable to start thumbnail picture output", __func__); - goto error; - } - - output_enabled = 1; - - rc = smdk4x12_v4l2_output(smdk4x12_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 = smdk4x12_camera->jpeg_thumbnail_quality; - - rc = smdk4x12_jpeg_start(smdk4x12_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 = smdk4x12_jpeg(smdk4x12_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 (SMDK4x12_CAMERA_CALLBACK_DEFINED(request_memory)) { - jpeg_thumbnail_memory = smdk4x12_camera->callbacks.request_memory(-1, jpeg_thumbnail_size, 1, smdk4x12_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); - - smdk4x12_jpeg_stop(smdk4x12_camera, &jpeg); - - if (output_enabled) { - smdk4x12_v4l2_output_stop(smdk4x12_camera, &output); - output_enabled = 0; - } - } - - ALOGE("%s: Thumbnail finished", __func__); - - // EXIF - - memset(&exif, 0, sizeof(exif)); - exif.jpeg_thumbnail_data = jpeg_thumbnail_data; - exif.jpeg_thumbnail_size = jpeg_thumbnail_size; - - rc = smdk4x12_exif_start(smdk4x12_camera, &exif); - if (rc < 0) { - ALOGE("%s: Unable to start exif", __func__); - goto error; - } - - rc = smdk4x12_exif(smdk4x12_camera, &exif); - if (rc < 0) { - ALOGE("%s: Unable to exif", __func__); - goto error; - } - - memory_size = exif.memory_size + jpeg_size; - - if (SMDK4x12_CAMERA_CALLBACK_DEFINED(request_memory)) { - memory = smdk4x12_camera->callbacks.request_memory(-1, memory_size, 1, smdk4x12_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; - } - - ALOGE("%s: exif finished", __func__); - - 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); - - smdk4x12_exif_stop(smdk4x12_camera, &exif); - - smdk4x12_camera->picture_memory = memory; - - rc = 0; - goto complete; - -error: - if (output_enabled) - smdk4x12_v4l2_output_stop(smdk4x12_camera, &output); - - if (memory != NULL && memory->release != NULL) { - memory->release(memory); - smdk4x12_camera->picture_memory = NULL; - } - - if (SMDK4x12_CAMERA_MSG_ENABLED(CAMERA_MSG_ERROR) && SMDK4x12_CAMERA_CALLBACK_DEFINED(notify) && !smdk4x12_camera->callback_lock) - smdk4x12_camera->callbacks.notify(CAMERA_MSG_ERROR, -1, 0, smdk4x12_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); - - smdk4x12_camera->picture_completed = 1; - smdk4x12_camera->picture_listener->busy = 0; - - return rc; -} - -void *smdk4x12_camera_picture_thread(void *data) -{ - struct smdk4x12_camera *smdk4x12_camera; - int rc; - - if (data == NULL) - return NULL; - - smdk4x12_camera = (struct smdk4x12_camera *) data; - - ALOGE("%s: Starting thread", __func__); - smdk4x12_camera->picture_thread_running = 1; - - while (smdk4x12_camera->picture_thread_enabled) { - ALOGE("%s: in while loop", __func__); - pthread_mutex_lock(&smdk4x12_camera->picture_lock_mutex); - ALOGE("%s: lock_mutex locked", __func__); - pthread_mutex_lock(&smdk4x12_camera->picture_mutex); - ALOGE("%s: picture_mutex locked", __func__); - - if (smdk4x12_camera->picture_listener == NULL) { - ALOGE("%s: no listener", __func__); - pthread_mutex_unlock(&smdk4x12_camera->picture_mutex); - break; - } - - if (smdk4x12_camera->picture_listener->busy) { - ALOGE("%s: listener busy", __func__); - rc = smdk4x12_camera_picture(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to take picture", __func__); - pthread_mutex_unlock(&smdk4x12_camera->picture_mutex); - break; - } - } - - pthread_mutex_unlock(&smdk4x12_camera->picture_mutex); - ALOGE("%s: picture_mutex unlocked", __func__); - - if (smdk4x12_camera->picture_completed) { - ALOGE("%s: picture completed", __func__); - smdk4x12_camera->picture_thread_running = 0; - smdk4x12_camera_picture_thread_stop(smdk4x12_camera); - break; - } - ALOGE("%s: still while loop", __func__); - } - - smdk4x12_camera->picture_thread_running = 0; - ALOGE("%s: Exiting thread", __func__); - - return NULL; -} - -int smdk4x12_camera_picture_thread_start(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_camera_capture_listener *listener; - pthread_attr_t thread_attr; - int format; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - ALOGD("%s()", __func__); - - if (smdk4x12_camera->picture_thread_enabled) { - ALOGE("Picture thread was already started!"); - return -1; - } - - if (smdk4x12_camera->camera_picture_format) - format = smdk4x12_camera->camera_picture_format; - else - format = smdk4x12_camera->picture_format; - - pthread_mutex_init(&smdk4x12_camera->picture_mutex, NULL); - pthread_mutex_init(&smdk4x12_camera->picture_lock_mutex, NULL); - - // Initial lock - pthread_mutex_lock(&smdk4x12_camera->picture_lock_mutex); - - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - - smdk4x12_camera->picture_thread_enabled = 1; - - rc = pthread_create(&smdk4x12_camera->picture_thread, &thread_attr, smdk4x12_camera_picture_thread, (void *) smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to create thread", __func__); - goto error; - } - - smdk4x12_camera->picture_completed = 0; - - listener = smdk4x12_camera_capture_listener_register(smdk4x12_camera, smdk4x12_camera->picture_width, smdk4x12_camera->picture_height, format, smdk4x12_camera_picture_callback); - if (listener == NULL) { - ALOGE("%s: Unable to register picture capture listener", __func__); - goto error; - } - - smdk4x12_camera->picture_listener = listener; - - rc = 0; - goto complete; - -error: - pthread_mutex_destroy(&smdk4x12_camera->picture_mutex); - pthread_mutex_destroy(&smdk4x12_camera->picture_lock_mutex); - - rc = -1; - -complete: - return rc; -} - -void smdk4x12_camera_picture_thread_stop(struct smdk4x12_camera *smdk4x12_camera) -{ - camera_memory_t *memory; - int i; - - if (smdk4x12_camera == NULL) - return; - - ALOGD("%s()", __func__); - - if (!smdk4x12_camera->picture_thread_enabled) { - ALOGE("Picture thread was already stopped!"); - return; - } - - memory = smdk4x12_camera->picture_memory; - - if (smdk4x12_camera->picture_listener != NULL) { - smdk4x12_camera_capture_listener_unregister(smdk4x12_camera, smdk4x12_camera->picture_listener); - smdk4x12_camera->picture_listener = NULL; - } - - smdk4x12_camera->picture_thread_enabled = 0; - - pthread_mutex_unlock(&smdk4x12_camera->picture_lock_mutex); - - // Wait for the thread to end - i = 0; - while (smdk4x12_camera->picture_thread_running) { - if (i++ > 10000) { - ALOGE("Picture thread is taking too long to end, something is going wrong"); - break; - } - usleep(100); - } - - if (smdk4x12_camera->picture_enabled) { - pthread_mutex_lock(&smdk4x12_camera->picture_mutex); - smdk4x12_camera->picture_enabled = 0; - pthread_mutex_unlock(&smdk4x12_camera->picture_mutex); - } - - pthread_mutex_destroy(&smdk4x12_camera->picture_mutex); - pthread_mutex_destroy(&smdk4x12_camera->picture_lock_mutex); - - if (smdk4x12_camera->picture_completed && memory != NULL) { - // It is important to return at this point (and not before) for burst - - if (SMDK4x12_CAMERA_MSG_ENABLED(CAMERA_MSG_SHUTTER) && SMDK4x12_CAMERA_CALLBACK_DEFINED(notify) && !smdk4x12_camera->callback_lock) - smdk4x12_camera->callbacks.notify(CAMERA_MSG_SHUTTER, 0, 0, smdk4x12_camera->callbacks.user); - - if (SMDK4x12_CAMERA_MSG_ENABLED(CAMERA_MSG_COMPRESSED_IMAGE) && SMDK4x12_CAMERA_CALLBACK_DEFINED(data) && !smdk4x12_camera->callback_lock) - smdk4x12_camera->callbacks.data(CAMERA_MSG_COMPRESSED_IMAGE, memory, 0, NULL, smdk4x12_camera->callbacks.user); - - if (memory->release != NULL) { - memory->release(memory); - smdk4x12_camera->picture_memory = NULL; - } - } -} - -// Recording - -int smdk4x12_camera_recording_output_start(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_v4l2_output *output; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - ALOGD("%s()", __func__); - - if (smdk4x12_camera->recording_output_enabled) { - ALOGE("Recording was already started!"); - return -1; - } - - output = &smdk4x12_camera->recording_output; - - memset(output, 0, sizeof(struct smdk4x12_v4l2_output)); - output->v4l2_id = 3; - output->width = smdk4x12_camera->recording_width; - output->height = smdk4x12_camera->recording_height; - output->format = smdk4x12_camera->recording_format; - output->buffer_width = smdk4x12_camera->recording_buffer.width; - output->buffer_height = smdk4x12_camera->recording_buffer.height; - output->buffer_format = smdk4x12_camera->recording_buffer.format; - output->buffers_count = SMDK4x12_CAMERA_RECORDING_BUFFERS_COUNT; - - rc = smdk4x12_v4l2_output_start(smdk4x12_camera, output); - if (rc < 0) { - ALOGE("%s: Unable to start recording output", __func__); - goto error; - } - - smdk4x12_camera->recording_output_enabled = 1; - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - return rc; -} - -void smdk4x12_camera_recording_output_stop(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_v4l2_output *output; - - if (smdk4x12_camera == NULL) - return; - - ALOGD("%s()", __func__); - - if (!smdk4x12_camera->recording_output_enabled) { - ALOGE("Recording was already stopped!"); - return; - } - - output = &smdk4x12_camera->recording_output; - - smdk4x12_v4l2_output_stop(smdk4x12_camera, output); - - smdk4x12_camera->recording_output_enabled = 0; -} - -int smdk4x12_camera_recording_callback(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_camera_buffer *buffers, int buffers_count) -{ - struct smdk4x12_camera_buffer *buffer = NULL; - int width, height, format; - int buffer_width, buffer_height, buffer_format; - int rc; - int i; - - if (smdk4x12_camera == NULL || buffers == NULL || buffers_count <= 0) - return -EINVAL; - -// ALOGD("%s()", __func__); - - if (smdk4x12_camera->recording_listener == NULL) - return -1; - - if (smdk4x12_camera->recording_listener->busy) { - ALOGE("%s: Dropping buffer", __func__); - return 0; - } - - smdk4x12_camera->recording_listener->busy = 1; - - width = smdk4x12_camera->recording_width; - height = smdk4x12_camera->recording_height; - format = smdk4x12_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 smdk4x12_camera_buffer *) ((unsigned char *) buffers + sizeof(struct smdk4x12_camera_buffer)); - } - - if (buffer == NULL) { - ALOGE("%s: Unable to find an appropriate buffer for recording", __func__); - smdk4x12_camera->recording_listener->busy = 0; - return 0; - } - - buffer_width = buffer->width; - buffer_height = buffer->height; - buffer_format = buffer->format; - - pthread_mutex_lock(&smdk4x12_camera->recording_mutex); - - if (!smdk4x12_camera->recording_output_enabled) { - memcpy(&smdk4x12_camera->recording_buffer, buffer, sizeof(struct smdk4x12_camera_buffer)); - - rc = smdk4x12_camera_recording_output_start(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to start recording", __func__); - goto error; - } - } else if (smdk4x12_camera->recording_buffer.width != buffer_width || smdk4x12_camera->recording_buffer.height != buffer_height || smdk4x12_camera->recording_buffer.format != buffer_format) { - smdk4x12_camera_recording_output_stop(smdk4x12_camera); - - memcpy(&smdk4x12_camera->recording_buffer, buffer, sizeof(struct smdk4x12_camera_buffer)); - - rc = smdk4x12_camera_recording_output_start(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to start recording", __func__); - goto error; - } - } else { - memcpy(&smdk4x12_camera->recording_buffer, buffer, sizeof(struct smdk4x12_camera_buffer)); - } - - pthread_mutex_unlock(&smdk4x12_camera->recording_lock_mutex); - - pthread_mutex_unlock(&smdk4x12_camera->recording_mutex); - - rc = 0; - goto complete; - -error: - pthread_mutex_unlock(&smdk4x12_camera->recording_mutex); - - smdk4x12_camera->recording_listener->busy = 0; - - rc = -1; - -complete: - return rc; -} - -void smdk4x12_camera_recording_frame_release(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_v4l2_output *output; - int rc; - - if (smdk4x12_camera == NULL) - return; - -// ALOGD("%s()", __func__); - - output = &smdk4x12_camera->recording_output; - - if (!smdk4x12_camera->recording_output_enabled) { - ALOGE("%s: Recording output should always be enabled", __func__); - return; - } - - rc = smdk4x12_v4l2_output_release(smdk4x12_camera, output); - if (rc < 0) { - ALOGE("%s: Unable to release recording output", __func__); - return; - } -} - -int smdk4x12_camera_recording(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_v4l2_output *output; - struct smdk4x12_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 (smdk4x12_camera == NULL) - goto error; - -// ALOGD("%s()", __func__); - - width = smdk4x12_camera->recording_width; - height = smdk4x12_camera->recording_height; - format = smdk4x12_camera->recording_format; - - output = &smdk4x12_camera->recording_output; - - buffer_length = smdk4x12_camera->recording_buffer_length; - buffers_count = smdk4x12_camera->recording_buffers_count; - - timestamp = systemTime(1); - - if (!smdk4x12_camera->recording_output_enabled) { - ALOGE("%s: Recording output should always be enabled", __func__); - goto error; - } - - rc = smdk4x12_v4l2_output(smdk4x12_camera, output, smdk4x12_camera->recording_buffer.address); - if (rc < 0) { - ALOGE("%s: Unable to output recording", __func__); - goto error; - } - - if (smdk4x12_camera->recording_metadata) { - memory = smdk4x12_camera->recording_memory; - memory_index = smdk4x12_camera->recording_memory_index; - memory_address = output->memory_address + output->buffer_length * output->memory_index; - - addrs = (struct smdk4x12_camera_addrs *) ((unsigned char *) memory->data + buffer_length * memory_index); - memset(addrs, 0, sizeof(struct smdk4x12_camera_addrs)); - addrs->type = 0; // kMetadataBufferTypeCameraSource - addrs->index = memory_index; - - smdk4x12_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 (SMDK4x12_CAMERA_MSG_ENABLED(CAMERA_MSG_VIDEO_FRAME) && SMDK4x12_CAMERA_CALLBACK_DEFINED(data_timestamp) && !smdk4x12_camera->callback_lock) - smdk4x12_camera->callbacks.data_timestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, memory, memory_index, smdk4x12_camera->callbacks.user); - else - smdk4x12_camera_recording_frame_release(smdk4x12_camera); - - if (smdk4x12_camera->recording_metadata) { - memory_index++; - smdk4x12_camera->recording_memory_index = memory_index % buffers_count; - } - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - smdk4x12_camera->recording_listener->busy = 0; - - return rc; -} - -void *smdk4x12_camera_recording_thread(void *data) -{ - struct smdk4x12_camera *smdk4x12_camera; - int rc; - - if (data == NULL) - return NULL; - - smdk4x12_camera = (struct smdk4x12_camera *) data; - - ALOGE("%s: Starting thread", __func__); - smdk4x12_camera->recording_thread_running = 1; - - while (smdk4x12_camera->recording_thread_enabled) { - pthread_mutex_lock(&smdk4x12_camera->recording_lock_mutex); - - pthread_mutex_lock(&smdk4x12_camera->recording_mutex); - - if (smdk4x12_camera->recording_listener == NULL) { - pthread_mutex_unlock(&smdk4x12_camera->recording_mutex); - break; - } - - if (smdk4x12_camera->recording_listener->busy) { - rc = smdk4x12_camera_recording(smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to record", __func__); - pthread_mutex_unlock(&smdk4x12_camera->recording_mutex); - break; - } - } - - pthread_mutex_unlock(&smdk4x12_camera->recording_mutex); - } - - smdk4x12_camera->recording_thread_running = 0; - ALOGE("%s: Exiting thread", __func__); - - return NULL; -} - -int smdk4x12_camera_recording_thread_start(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_camera_capture_listener *listener; - pthread_attr_t thread_attr; - camera_memory_t *memory = NULL; - int buffer_length; - int buffers_count; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - ALOGD("%s()", __func__); - - if (smdk4x12_camera->recording_thread_enabled) { - ALOGE("Recording thread was already started!"); - return -1; - } - - pthread_mutex_init(&smdk4x12_camera->recording_mutex, NULL); - pthread_mutex_init(&smdk4x12_camera->recording_lock_mutex, NULL); - - // Initial lock - pthread_mutex_lock(&smdk4x12_camera->recording_lock_mutex); - - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - - smdk4x12_camera->recording_thread_enabled = 1; - - rc = pthread_create(&smdk4x12_camera->recording_thread, &thread_attr, smdk4x12_camera_recording_thread, (void *) smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to create thread", __func__); - goto error; - } - - if (smdk4x12_camera->recording_metadata) { - buffer_length = sizeof(struct smdk4x12_camera_addrs); - buffers_count = SMDK4x12_CAMERA_RECORDING_BUFFERS_COUNT; - - if (SMDK4x12_CAMERA_CALLBACK_DEFINED(request_memory)) { - memory = smdk4x12_camera->callbacks.request_memory(-1, buffer_length, buffers_count, smdk4x12_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; - } - - smdk4x12_camera->recording_memory = memory; - smdk4x12_camera->recording_buffer_length = buffer_length; - smdk4x12_camera->recording_buffers_count = buffers_count; - } - - listener = smdk4x12_camera_capture_listener_register(smdk4x12_camera, smdk4x12_camera->recording_width, smdk4x12_camera->recording_height, smdk4x12_camera->recording_format, smdk4x12_camera_recording_callback); - if (listener == NULL) { - ALOGE("%s: Unable to register recording capture listener", __func__); - goto error; - } - - smdk4x12_camera->recording_listener = listener; - - rc = 0; - goto complete; - -error: - if (memory != NULL && memory->release != NULL) { - memory->release(memory); - smdk4x12_camera->recording_memory = NULL; - } - - pthread_mutex_destroy(&smdk4x12_camera->recording_mutex); - pthread_mutex_destroy(&smdk4x12_camera->recording_lock_mutex); - - rc = -1; - -complete: - return rc; -} - -void smdk4x12_camera_recording_thread_stop(struct smdk4x12_camera *smdk4x12_camera) -{ - camera_memory_t *memory; - int i; - - if (smdk4x12_camera == NULL) - return; - - ALOGD("%s()", __func__); - - if (!smdk4x12_camera->recording_thread_enabled) { - ALOGE("Recording thread was already stopped!"); - return; - } - - memory = smdk4x12_camera->recording_memory; - - if (smdk4x12_camera->recording_listener != NULL) { - smdk4x12_camera_capture_listener_unregister(smdk4x12_camera, smdk4x12_camera->recording_listener); - smdk4x12_camera->recording_listener = NULL; - } - - smdk4x12_camera->recording_thread_enabled = 0; - - pthread_mutex_unlock(&smdk4x12_camera->recording_lock_mutex); - - // Wait for the thread to end - i = 0; - while (smdk4x12_camera->recording_thread_running) { - if (i++ > 10000) { - ALOGE("Recording thread is taking too long to end, something is going wrong"); - break; - } - usleep(100); - } - - if (smdk4x12_camera->recording_output_enabled) { - pthread_mutex_lock(&smdk4x12_camera->recording_mutex); - smdk4x12_camera_recording_output_stop(smdk4x12_camera); - pthread_mutex_unlock(&smdk4x12_camera->recording_mutex); - } - - pthread_mutex_destroy(&smdk4x12_camera->recording_mutex); - pthread_mutex_destroy(&smdk4x12_camera->recording_lock_mutex); - - if (memory != NULL && memory->release != NULL) { - memory->release(memory); - smdk4x12_camera->recording_memory = NULL; - } -} - -// Auto-focus - -int smdk4x12_camera_auto_focus(struct smdk4x12_camera *smdk4x12_camera, int auto_focus_status) -{ - if (smdk4x12_camera == NULL) - return -EINVAL; - -// ALOGD("%s()", __func__); - - switch (auto_focus_status) { - case CAMERA_AF_STATUS_IN_PROGRESS: - if (SMDK4x12_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS_MOVE) && SMDK4x12_CAMERA_CALLBACK_DEFINED(notify) && !smdk4x12_camera->callback_lock) - smdk4x12_camera->callbacks.notify(CAMERA_MSG_FOCUS_MOVE, 1, 0, smdk4x12_camera->callbacks.user); - break; - case CAMERA_AF_STATUS_SUCCESS: - if (SMDK4x12_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && SMDK4x12_CAMERA_CALLBACK_DEFINED(notify) && !smdk4x12_camera->callback_lock) - smdk4x12_camera->callbacks.notify(CAMERA_MSG_FOCUS, 1, 0, smdk4x12_camera->callbacks.user); - break; - case CAMERA_AF_STATUS_FAIL: - default: - if (SMDK4x12_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && SMDK4x12_CAMERA_CALLBACK_DEFINED(notify) && !smdk4x12_camera->callback_lock) - smdk4x12_camera->callbacks.notify(CAMERA_MSG_FOCUS, 0, 0, smdk4x12_camera->callbacks.user); - break; - } - - return 0; -} - -void *smdk4x12_camera_auto_focus_thread(void *data) -{ - struct smdk4x12_camera *smdk4x12_camera; - int auto_focus_result = CAMERA_AF_STATUS_FAIL; - int auto_focus_completed = 0; - int rc; - - if (data == NULL) - return NULL; - - smdk4x12_camera = (struct smdk4x12_camera *) data; - - ALOGE("%s: Starting thread", __func__); - smdk4x12_camera->auto_focus_thread_running = 1; - - if (smdk4x12_camera->focus_mode == FOCUS_MODE_CONTINOUS_PICTURE) { - rc = smdk4x12_camera_auto_focus(smdk4x12_camera, smdk4x12_camera->auto_focus_result); - if (rc < 0) - ALOGE("%s: Unable to auto-focus", __func__); - - smdk4x12_camera->auto_focus_thread_enabled = 0; - } - - while (smdk4x12_camera->auto_focus_thread_enabled) { - pthread_mutex_lock(&smdk4x12_camera->auto_focus_mutex); - - rc = smdk4x12_v4l2_g_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT, &auto_focus_result); - if (rc < 0) { - ALOGE("%s: Unable to get auto-focus result", __func__); - auto_focus_result = CAMERA_AF_STATUS_FAIL; - } - - smdk4x12_camera->auto_focus_result = auto_focus_result; - - rc = smdk4x12_camera_auto_focus(smdk4x12_camera, auto_focus_result); - if (rc < 0) { - ALOGE("%s: Unable to auto-focus", __func__); - auto_focus_result = CAMERA_AF_STATUS_FAIL; - } - - if (auto_focus_result == CAMERA_AF_STATUS_IN_PROGRESS) - usleep(10000); - else - auto_focus_completed = 1; - - pthread_mutex_unlock(&smdk4x12_camera->auto_focus_mutex); - - if (auto_focus_completed) { - smdk4x12_camera->auto_focus_thread_running = 0; - smdk4x12_camera_auto_focus_thread_stop(smdk4x12_camera); - } - } - - smdk4x12_camera->auto_focus_thread_running = 0; - ALOGE("%s: Exiting thread", __func__); - - return NULL; -} - -int smdk4x12_camera_auto_focus_thread_start(struct smdk4x12_camera *smdk4x12_camera) -{ - pthread_attr_t thread_attr; - int auto_focus; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - ALOGD("%s()", __func__); - - if (smdk4x12_camera->auto_focus_thread_enabled) { - ALOGE("Auto-focus thread was already started!"); - return -1; - } - - pthread_mutex_init(&smdk4x12_camera->auto_focus_mutex, NULL); - - if (smdk4x12_camera->focus_mode != FOCUS_MODE_CONTINOUS_PICTURE) { - auto_focus = AUTO_FOCUS_ON | (smdk4x12_camera->preview_width & 0xfff) << 20 | (smdk4x12_camera->preview_height & 0xfff) << 8; - - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_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); - - smdk4x12_camera->auto_focus_thread_enabled = 1; - - rc = pthread_create(&smdk4x12_camera->auto_focus_thread, &thread_attr, smdk4x12_camera_auto_focus_thread, (void *) smdk4x12_camera); - if (rc < 0) { - ALOGE("%s: Unable to create thread", __func__); - goto error; - } - - rc = 0; - goto complete; - -error: - pthread_mutex_destroy(&smdk4x12_camera->auto_focus_mutex); - - rc = -1; - -complete: - return rc; -} - -void smdk4x12_camera_auto_focus_thread_stop(struct smdk4x12_camera *smdk4x12_camera) -{ - int rc; - int i; - - if (smdk4x12_camera == NULL) - return; - - ALOGD("%s()", __func__); - - if (!smdk4x12_camera->auto_focus_thread_enabled) { - ALOGE("Auto-focus thread was already stopped!"); - return; - } - - smdk4x12_camera->auto_focus_thread_enabled = 0; - - // Wait for the thread to end - i = 0; - while (smdk4x12_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); - } - if (smdk4x12_camera->focus_mode != FOCUS_MODE_CONTINOUS_PICTURE) { - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_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(&smdk4x12_camera->auto_focus_mutex); -} - -/* - * SMDK4x12 Camera OPS - */ - -int smdk4x12_camera_set_preview_window(struct camera_device *device, - struct preview_stream_ops *w) -{ - struct smdk4x12_camera *smdk4x12_camera; - - int width, height, format, gralloc_format; - - buffer_handle_t *buffer; - int stride; - void *addr = NULL; - - int rc; - - ALOGD("%s(%p, %p)", __func__, device, w); - - if (device == NULL || device->priv == NULL) - return -EINVAL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - if (smdk4x12_camera->preview_thread_enabled) - pthread_mutex_lock(&smdk4x12_camera->preview_mutex); - - if (w == NULL) { - smdk4x12_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, SMDK4x12_CAMERA_GRALLOC_BUFFERS_COUNT); - if (rc) { - ALOGE("%s: Unable to set buffer count: %d", __func__, SMDK4x12_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 = smdk4x12_camera->preview_width; - height = smdk4x12_camera->preview_height; - format = smdk4x12_camera->preview_format; - - gralloc_format = smdk4x12_gralloc_format(format); - - rc = w->set_buffers_geometry(w, width, height, gralloc_format); - if (rc) { - ALOGE("%s: Unable to set buffers geometry", __func__); - goto error; - } - - smdk4x12_camera->preview_window = w; - - rc = 0; - goto complete; - -error: - smdk4x12_camera->preview_window = NULL; - rc = -1; - -complete: - if (smdk4x12_camera->preview_thread_enabled) - pthread_mutex_unlock(&smdk4x12_camera->preview_mutex); - - return rc; -} - -void smdk4x12_camera_set_callbacks(struct camera_device *device, - 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 smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p, %p)", __func__, device, user); - - if (device == NULL || device->priv == NULL) - return; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera->callbacks.notify = notify_cb; - smdk4x12_camera->callbacks.data = data_cb; - smdk4x12_camera->callbacks.data_timestamp = data_cb_timestamp; - smdk4x12_camera->callbacks.request_memory = get_memory; - smdk4x12_camera->callbacks.user = user; -} - -void smdk4x12_camera_enable_msg_type(struct camera_device *device, - int32_t msg_type) -{ - struct smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p, %d)", __func__, device, msg_type); - - if (device == NULL || device->priv == NULL) - return; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera->messages_enabled |= msg_type; -} - -void smdk4x12_camera_disable_msg_type(struct camera_device *device, - int32_t msg_type) -{ - struct smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p, %d)", __func__, device, msg_type); - - if (device == NULL || device->priv == NULL) - return; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera->messages_enabled &= ~msg_type; -} - -int smdk4x12_camera_msg_type_enabled(struct camera_device *device, - int32_t msg_type) -{ - struct smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p, %d)", __func__, device, msg_type); - - if (device == NULL || device->priv == NULL) - return -EINVAL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - return smdk4x12_camera->messages_enabled & msg_type; -} - -int smdk4x12_camera_start_preview(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - int rc; - - ALOGD("%s(%p)", __func__, device); - - if (device == NULL || device->priv == NULL) - return -EINVAL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera->callback_lock = 1; - rc = smdk4x12_camera_preview_thread_start(smdk4x12_camera); - smdk4x12_camera->callback_lock = 0; - - return rc; -} - -void smdk4x12_camera_stop_preview(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p)", __func__, device); - - if (device == NULL || device->priv == NULL) - return; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera->callback_lock = 1; - smdk4x12_camera_preview_thread_stop(smdk4x12_camera); - smdk4x12_camera->callback_lock = 0; -} - -int smdk4x12_camera_preview_enabled(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p)", __func__, device); - - if (device == NULL || device->priv == NULL) - return -EINVAL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - return smdk4x12_camera->preview_thread_enabled; -} - -int smdk4x12_camera_store_meta_data_in_buffers(struct camera_device *device, - int enable) -{ - struct smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p, %d)", __func__, device, enable); - - if (device == NULL || device->priv == NULL) - return -EINVAL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - if (!smdk4x12_camera->recording_thread_enabled) - smdk4x12_camera->recording_metadata = enable; - else - ALOGE("%s: Recording is running!", __func__); - - return 0; -} - -int smdk4x12_camera_start_recording(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - int rc; - - ALOGD("%s(%p)", __func__, device); - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera->callback_lock = 1; - rc = smdk4x12_camera_recording_thread_start(smdk4x12_camera); - smdk4x12_camera->callback_lock = 0; - - return rc; -} - -void smdk4x12_camera_stop_recording(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p)", __func__, device); - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera->callback_lock = 1; - smdk4x12_camera_recording_thread_stop(smdk4x12_camera); - smdk4x12_camera->callback_lock = 0; -} - -int smdk4x12_camera_recording_enabled(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p)", __func__, device); - - if (device == NULL || device->priv == NULL) - return -EINVAL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - return smdk4x12_camera->recording_thread_enabled; -} - -void smdk4x12_camera_release_recording_frame(struct camera_device *device, - const void *opaque) -{ - struct smdk4x12_camera *smdk4x12_camera; - -// ALOGD("%s(%p, %p)", __func__, device, opaque); - - if (device == NULL || device->priv == NULL) - return; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera_recording_frame_release(smdk4x12_camera); -} - -int smdk4x12_camera_start_auto_focus(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p)", __func__, device); - - if (device == NULL || device->priv == NULL) - return -EINVAL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - return smdk4x12_camera_auto_focus_thread_start(smdk4x12_camera); -} - -int smdk4x12_camera_cancel_auto_focus(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p)", __func__, device); - - if (device == NULL || device->priv == NULL) - return -EINVAL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera_auto_focus_thread_stop(smdk4x12_camera); - - return 0; -} - -int smdk4x12_camera_take_picture(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - int rc; - - ALOGD("%s(%p)", __func__, device); - - if (device == NULL || device->priv == NULL) - return -EINVAL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera->callback_lock = 1; - rc = smdk4x12_camera_picture_thread_start(smdk4x12_camera); - smdk4x12_camera->callback_lock = 0; - - return rc; -} - -int smdk4x12_camera_cancel_picture(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - int rc; - - ALOGD("%s(%p)", __func__, device); - - if (device == NULL || device->priv == NULL) - return -EINVAL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera->callback_lock = 1; - smdk4x12_camera_picture_thread_stop(smdk4x12_camera); - smdk4x12_camera->callback_lock = 0; - - return 0; -} - -int smdk4x12_camera_set_parameters(struct camera_device *device, - const char *params) -{ - struct smdk4x12_camera *smdk4x12_camera; - int rc; - - ALOGD("%s(%p, %s)", __func__, device, params); - - if (device == NULL || device->priv == NULL || params == NULL) - return -EINVAL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - rc = smdk4x12_params_string_set(smdk4x12_camera, (char *) params); - if (rc < 0) { - ALOGE("%s: Unable to set params string", __func__); - return -1; - } - - rc = smdk4x12_camera_params_apply(smdk4x12_camera, 0); - if (rc < 0) { - ALOGE("%s: Unable to apply params", __func__); - return -1; - } - - return 0; -} - -char *smdk4x12_camera_get_parameters(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - char *params; - - ALOGD("%s(%p)", __func__, device); - - if (device == NULL || device->priv == NULL) - return NULL; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - params = smdk4x12_params_string_get(smdk4x12_camera); - if (params == NULL) { - ALOGE("%s: Couldn't find any param", __func__); - return strdup(""); - } - - return params; -} - -void smdk4x12_camera_put_parameters(struct camera_device *device, char *params) -{ - ALOGD("%s(%p)", __func__, device); - - if (params != NULL) - free(params); -} - -int smdk4x12_camera_send_command(struct camera_device *device, - int32_t cmd, int32_t arg1, int32_t arg2) -{ - ALOGD("%s(%p, %d, %d, %d)", __func__, device, cmd, arg1, arg2); - - return 0; -} - -void smdk4x12_camera_release(struct camera_device *device) -{ - struct smdk4x12_camera *smdk4x12_camera; - - ALOGD("%s(%p)", __func__, device); - - if (device == NULL || device->priv == NULL) - return; - - smdk4x12_camera = (struct smdk4x12_camera *) device->priv; - - smdk4x12_camera_capture_thread_stop(smdk4x12_camera); - - smdk4x12_camera_stop(smdk4x12_camera); -} - -int smdk4x12_camera_dump(struct camera_device *device, int fd) -{ - ALOGD("%s(%p, %d)", __func__, device, fd); - - return 0; -} - -/* - * Interface - */ - -struct camera_device_ops smdk4x12_camera_ops = { - .set_preview_window = smdk4x12_camera_set_preview_window, - .set_callbacks = smdk4x12_camera_set_callbacks, - .enable_msg_type = smdk4x12_camera_enable_msg_type, - .disable_msg_type = smdk4x12_camera_disable_msg_type, - .msg_type_enabled = smdk4x12_camera_msg_type_enabled, - .start_preview = smdk4x12_camera_start_preview, - .stop_preview = smdk4x12_camera_stop_preview, - .preview_enabled = smdk4x12_camera_preview_enabled, - .store_meta_data_in_buffers = smdk4x12_camera_store_meta_data_in_buffers, - .start_recording = smdk4x12_camera_start_recording, - .stop_recording = smdk4x12_camera_stop_recording, - .recording_enabled = smdk4x12_camera_recording_enabled, - .release_recording_frame = smdk4x12_camera_release_recording_frame, - .auto_focus = smdk4x12_camera_start_auto_focus, - .cancel_auto_focus = smdk4x12_camera_cancel_auto_focus, - .take_picture = smdk4x12_camera_take_picture, - .cancel_picture = smdk4x12_camera_cancel_picture, - .set_parameters = smdk4x12_camera_set_parameters, - .get_parameters = smdk4x12_camera_get_parameters, - .put_parameters = smdk4x12_camera_put_parameters, - .send_command = smdk4x12_camera_send_command, - .release = smdk4x12_camera_release, - .dump = smdk4x12_camera_dump, -}; - -int smdk4x12_camera_close(hw_device_t *device) -{ - struct camera_device *camera_device; - struct smdk4x12_camera *smdk4x12_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 smdk4x12_camera_open(const struct hw_module_t* module, const char *camera_id, - struct hw_device_t** device) -{ - struct camera_device *camera_device = NULL; - struct smdk4x12_camera *smdk4x12_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; - - smdk4x12_camera = calloc(1, sizeof(struct smdk4x12_camera)); - smdk4x12_camera->config = smdk4x12_camera_config; - - if (smdk4x12_camera->config->v4l2_nodes_count > SMDK4x12_CAMERA_MAX_V4L2_NODES_COUNT) - goto error_preset; - - if (id >= smdk4x12_camera->config->presets_count) - goto error_preset; - - rc = smdk4x12_camera_start(smdk4x12_camera, id); - if (rc < 0) { - ALOGE("%s: Unable to start camera", __func__); - goto error; - } - - rc = smdk4x12_camera_capture_thread_start(smdk4x12_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 = smdk4x12_camera_close; - - camera_device->ops = &smdk4x12_camera_ops; - camera_device->priv = smdk4x12_camera; - - *device = (struct hw_device_t *) &(camera_device->common); - - return 0; - -error: - smdk4x12_camera_stop(smdk4x12_camera); - -error_device: - if (camera_device != NULL) - free(camera_device); - -error_preset: - if (smdk4x12_camera != NULL) - free(smdk4x12_camera); - - return -1; -} - -int smdk4x12_camera_get_number_of_cameras(void) -{ - ALOGD("%s()", __func__); - - if (smdk4x12_camera_config == NULL || smdk4x12_camera_config->presets == NULL) { - ALOGE("%s: Unable to find proper camera config", __func__); - return -1; - } - - return smdk4x12_camera_config->presets_count; -} - -int smdk4x12_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 (smdk4x12_camera_config == NULL || smdk4x12_camera_config->presets == NULL) { - ALOGE("%s: Unable to find proper camera config", __func__); - return -1; - } - - if (id >= smdk4x12_camera_config->presets_count) - return -EINVAL; - - ALOGD("Selected camera: %s", smdk4x12_camera_config->presets[id].name); - - info->facing = smdk4x12_camera_config->presets[id].facing; - info->orientation = smdk4x12_camera_config->presets[id].orientation; - - return 0; -} - -struct hw_module_methods_t smdk4x12_camera_module_methods = { - .open = smdk4x12_camera_open, -}; - -struct camera_module HAL_MODULE_INFO_SYM = { - .common = { - .tag = HARDWARE_MODULE_TAG, - .version_major = 1, - .version_minor = 0, - .id = CAMERA_HARDWARE_MODULE_ID, - .name = "SMDK4x12 Camera", - .author = "Paul Kocialkowski", - .methods = &smdk4x12_camera_module_methods, - }, - .get_number_of_cameras = smdk4x12_camera_get_number_of_cameras, - .get_camera_info = smdk4x12_camera_get_camera_info, -}; diff --git a/camera/smdk4x12_camera.h b/camera/smdk4x12_camera.h deleted file mode 100644 index d1a3924..0000000 --- a/camera/smdk4x12_camera.h +++ /dev/null @@ -1,695 +0,0 @@ -/* - * Copyright (C) 2013-2014 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 - -#include -#include - -#ifndef _SMDK4x12_CAMERA_H_ -#define _SMDK4x12_CAMERA_H_ - -#define SMDK4x12_CAMERA_MAX_V4L2_NODES_COUNT 4 - -#define SMDK4x12_CAMERA_CAPTURE_BUFFERS_COUNT 6 -#define SMDK4x12_CAMERA_PREVIEW_BUFFERS_COUNT 6 -#define SMDK4x12_CAMERA_RECORDING_BUFFERS_COUNT 6 -#define SMDK4x12_CAMERA_GRALLOC_BUFFERS_COUNT 3 - -#define SMDK4x12_CAMERA_PICTURE_OUTPUT_FORMAT V4L2_PIX_FMT_YUYV - -#define SMDK4x12_CAMERA_MSG_ENABLED(msg) (smdk4x12_camera->messages_enabled & msg) -#define SMDK4x12_CAMERA_CALLBACK_DEFINED(cb) (smdk4x12_camera->callbacks.cb != NULL) - -#define SMDK4x12_CAMERA_ALIGN(value) ((value + (0x10000 - 1)) & ~(0x10000 - 1)) - -/* - * Structures - */ - -struct smdk4x12_camera; - -struct list_head { - struct list_head *next; - struct list_head *prev; -}; - -enum smdk4x12_param_type { - EXYNOS_PARAM_INT, - EXYNOS_PARAM_FLOAT, - EXYNOS_PARAM_STRING, -}; - -union smdk4x12_param_data { - int integer; - float floating; - char *string; -}; - -struct smdk4x12_param { - struct list_head list; - - char *key; - union smdk4x12_param_data data; - enum smdk4x12_param_type type; -}; - -struct smdk4x12_camera_buffer { - void *pointer; - int address; - int length; - - int width; - int height; - int format; -}; - -struct smdk4x12_camera_capture_listener { - struct list_head list; - - int width; - int height; - int format; - - int (*callback)(struct smdk4x12_camera *smdk4x12_camera, struct smdk4x12_camera_buffer *buffers, int buffers_count); - int busy; -}; - -struct smdk4x12_camera_mbus_resolution { - int width; - int height; - int mbus_width; - int mbus_height; -}; - -struct smdk4x12_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; - - 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; - - 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; - - char *image_stabilization; - char *image_stabilization_values; -}; - -struct smdk4x12_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 smdk4x12_camera_params params; - struct smdk4x12_camera_mbus_resolution *mbus_resolutions; - int mbus_resolutions_count; -}; - -struct smdk4x12_v4l2_node { - int id; - char *node; -}; - -struct smdk4x12_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 smdk4x12_exif { - int enabled; - - exif_attribute_t attributes; - void *jpeg_thumbnail_data; - int jpeg_thumbnail_size; - - camera_memory_t *memory; - int memory_size; -}; - -struct smdk4x12_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; -}; - -struct exynox_camera_config { - struct smdk4x12_camera_preset *presets; - int presets_count; - - struct smdk4x12_v4l2_node *v4l2_nodes; - int v4l2_nodes_count; -}; - -struct smdk4x12_camera_callbacks { - camera_notify_callback notify; - camera_data_callback data; - camera_data_timestamp_callback data_timestamp; - camera_request_memory request_memory; - void *user; -}; - -struct smdk4x12_camera { - int v4l2_fds[SMDK4x12_CAMERA_MAX_V4L2_NODES_COUNT]; - int ion_fd; - - struct exynox_camera_config *config; - struct smdk4x12_param *params; - - struct smdk4x12_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 smdk4x12_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_exif_flash; - int capture_exif_iso; - int capture_exif_exposure; - int capture_exif_exposure_bias; - int capture_exif_exposure_time; - 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 smdk4x12_camera_capture_listener *preview_listener; - struct preview_stream_ops *preview_window; - struct smdk4x12_camera_buffer preview_buffer; - struct smdk4x12_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 smdk4x12_camera_capture_listener *picture_listener; - camera_memory_t *picture_memory; - struct smdk4x12_camera_buffer picture_jpeg_buffer; - struct smdk4x12_camera_buffer picture_jpeg_thumbnail_buffer; - struct smdk4x12_camera_buffer picture_yuv_buffer; - struct smdk4x12_camera_buffer picture_yuv_thumbnail_buffer; - time_t picture_focus_timestamp; - - // 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 smdk4x12_camera_capture_listener *recording_listener; - camera_memory_t *recording_memory; - int recording_memory_index; - struct smdk4x12_camera_buffer recording_buffer; - struct smdk4x12_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; - - int auto_focus_result; - - // 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 smdk4x12_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 ae_lock; - int awb_lock; - int flash_mode; - int exposure_compensation; - int whitebalance; - int antibanding; - int scene_mode; - int effect; - int iso; - int metering; - int image_stabilization; -}; - -struct smdk4x12_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 smdk4x12_v4l2_ext_control { - __u32 id; - __u32 size; - __u32 reserved2[1]; - union { - __s32 value; - __s64 value64; - char *string; - } data; -} __attribute__ ((packed)); - -/* - * Camera - */ - -// Camera -int smdk4x12_camera_start(struct smdk4x12_camera *smdk4x12_camera, int id); -void smdk4x12_camera_stop(struct smdk4x12_camera *smdk4x12_camera); - -// Params -int smdk4x12_camera_params_init(struct smdk4x12_camera *smdk4x12_camera, int id); -int smdk4x12_camera_params_apply(struct smdk4x12_camera *smdk4x12_camera, int force); - -// Capture -int smdk4x12_camera_capture(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_camera_capture_thread_start(struct smdk4x12_camera *smdk4x12_camera); -void smdk4x12_camera_capture_thread_stop(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_camera_capture_start(struct smdk4x12_camera *smdk4x12_camera); -void smdk4x12_camera_capture_stop(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_camera_capture_setup(struct smdk4x12_camera *smdk4x12_camera); -struct smdk4x12_camera_capture_listener *smdk4x12_camera_capture_listener_register( - struct smdk4x12_camera *smdk4x12_camera, int width, int height, int format, - int (*callback)(struct smdk4x12_camera *smdk4x12_camera, struct smdk4x12_camera_buffer *buffers, int buffers_count)); -void smdk4x12_camera_capture_listener_unregister( - struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_camera_capture_listener *listener); - -// Preview -int smdk4x12_camera_preview_output_start(struct smdk4x12_camera *smdk4x12_camera); -void smdk4x12_camera_preview_output_stop(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_camera_preview_callback(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_camera_buffer *buffers, int buffers_count); -int smdk4x12_camera_preview(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_camera_preview_thread_start(struct smdk4x12_camera *smdk4x12_camera); -void smdk4x12_camera_preview_thread_stop(struct smdk4x12_camera *smdk4x12_camera); - -// Picture -int smdk4x12_camera_picture_callback(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_camera_buffer *buffers, int buffers_count); -int smdk4x12_camera_picture(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_camera_picture_thread_start(struct smdk4x12_camera *smdk4x12_camera); -void smdk4x12_camera_picture_thread_stop(struct smdk4x12_camera *smdk4x12_camera); - -// Recording -int smdk4x12_camera_recording_output_start(struct smdk4x12_camera *smdk4x12_camera); -void smdk4x12_camera_recording_output_stop(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_camera_recording_callback(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_camera_buffer *buffers, int buffers_count); -void smdk4x12_camera_recording_frame_release(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_camera_recording(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_camera_recording_thread_start(struct smdk4x12_camera *smdk4x12_camera); -void smdk4x12_camera_recording_thread_stop(struct smdk4x12_camera *smdk4x12_camera); - -// Auto-focus -int smdk4x12_camera_auto_focus(struct smdk4x12_camera *smdk4x12_camera, int auto_focus_status); -int smdk4x12_camera_auto_focus_thread_start(struct smdk4x12_camera *smdk4x12_camera); -void smdk4x12_camera_auto_focus_thread_stop(struct smdk4x12_camera *smdk4x12_camera); - -/* - * EXIF - */ - -int smdk4x12_exif_start(struct smdk4x12_camera *smdk4x12_camera, struct smdk4x12_exif *exif); -void smdk4x12_exif_stop(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_exif *exif); -int smdk4x12_exif(struct smdk4x12_camera *smdk4x12_camera, struct smdk4x12_exif *exif); - -/* - * ION - */ - -#ifdef EXYNOS_ION -int smdk4x12_ion_init(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_ion_open(struct smdk4x12_camera *smdk4x12_camera); -void smdk4x12_ion_close(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_ion_alloc(struct smdk4x12_camera *smdk4x12_camera, int size); -int smdk4x12_ion_free(struct smdk4x12_camera *smdk4x12_camera, int fd); -int smdk4x12_ion_phys(struct smdk4x12_camera *smdk4x12_camera, int fd); -int smdk4x12_ion_msync(struct smdk4x12_camera *smdk4x12_camera, int fd, - int offset, int size); -#endif - -/* - * Jpeg - */ - -int smdk4x12_jpeg_start(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_jpeg *jpeg); -void smdk4x12_jpeg_stop(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_jpeg *jpeg); -int smdk4x12_jpeg(struct smdk4x12_camera *smdk4x12_camera, struct smdk4x12_jpeg *jpeg); - -/* - * Param - */ - -int smdk4x12_param_int_get(struct smdk4x12_camera *smdk4x12_camera, - char *key); -float smdk4x12_param_float_get(struct smdk4x12_camera *smdk4x12_camera, - char *key); -char *smdk4x12_param_string_get(struct smdk4x12_camera *smdk4x12_camera, - char *key); -int smdk4x12_param_int_set(struct smdk4x12_camera *smdk4x12_camera, - char *key, int integer); -int smdk4x12_param_float_set(struct smdk4x12_camera *smdk4x12_camera, - char *key, float floating); -int smdk4x12_param_string_set(struct smdk4x12_camera *smdk4x12_camera, - char *key, char *string); -char *smdk4x12_params_string_get(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_params_string_set(struct smdk4x12_camera *smdk4x12_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 smdk4x12_camera_buffer_length(int width, int height, int format); -void smdk4x12_camera_yuv_planes(int width, int height, int format, int address, int *address_y, int *address_cb, int *address_cr); -int smdk4x12_gralloc_format(int format); - -/* - * V4L2 - */ - -int smdk4x12_v4l2_init(struct smdk4x12_camera *smdk4x12_camera); -int smdk4x12_v4l2_index(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id); -int smdk4x12_v4l2_fd(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id); - -int smdk4x12_v4l2_open(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id); -void smdk4x12_v4l2_close(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id); -int smdk4x12_v4l2_ioctl(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int request, void *data); -int smdk4x12_v4l2_poll(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id); -int smdk4x12_v4l2_qbuf(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int type, int memory, int index, unsigned long userptr); -int smdk4x12_v4l2_qbuf_cap(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int index); -int smdk4x12_v4l2_qbuf_out(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int index, unsigned long userptr); -int smdk4x12_v4l2_dqbuf(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int type, int memory); -int smdk4x12_v4l2_dqbuf_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id); -int smdk4x12_v4l2_dqbuf_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id); -int smdk4x12_v4l2_reqbufs(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type, int memory, int count); -int smdk4x12_v4l2_reqbufs_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int count); -int smdk4x12_v4l2_reqbufs_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int count); -int smdk4x12_v4l2_querybuf(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type, int memory, int index); -int smdk4x12_v4l2_querybuf_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int index); -int smdk4x12_v4l2_querybuf_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int index); -int smdk4x12_v4l2_querycap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int flags); -int smdk4x12_v4l2_querycap_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id); -int smdk4x12_v4l2_querycap_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id); -int smdk4x12_v4l2_streamon(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type); -int smdk4x12_v4l2_streamon_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id); -int smdk4x12_v4l2_streamon_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id); -int smdk4x12_v4l2_streamoff(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type); -int smdk4x12_v4l2_streamoff_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id); -int smdk4x12_v4l2_streamoff_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id); -int smdk4x12_v4l2_g_fmt(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int type, int *width, int *height, int *fmt); -int smdk4x12_v4l2_g_fmt_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int *width, int *height, int *fmt); -int smdk4x12_v4l2_g_fmt_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int *width, int *height, int *fmt); -int smdk4x12_v4l2_s_fmt_pix(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type, int width, int height, int fmt, int field, - int priv); -int smdk4x12_v4l2_s_fmt_pix_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int width, int height, int fmt, int priv); -int smdk4x12_v4l2_s_fmt_pix_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int width, int height, int fmt, int priv); -int smdk4x12_v4l2_s_fmt_win(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int left, int top, int width, int height); -int smdk4x12_v4l2_enum_fmt(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type, int fmt); -int smdk4x12_v4l2_enum_fmt_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int fmt); -int smdk4x12_v4l2_enum_fmt_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int fmt); -int smdk4x12_v4l2_enum_input(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int id); -int smdk4x12_v4l2_s_input(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int id); -int smdk4x12_v4l2_g_ext_ctrls(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, struct v4l2_ext_control *control, int count); -int smdk4x12_v4l2_g_ctrl(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int id, int *value); -int smdk4x12_v4l2_s_ctrl(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int id, int value); -int smdk4x12_v4l2_s_parm(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int type, struct v4l2_streamparm *streamparm); -int smdk4x12_v4l2_s_parm_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, struct v4l2_streamparm *streamparm); -int smdk4x12_v4l2_s_parm_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, struct v4l2_streamparm *streamparm); -int smdk4x12_v4l2_s_crop(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int type, int left, int top, int width, int height); -int smdk4x12_v4l2_s_crop_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int left, int top, int width, int height); -int smdk4x12_v4l2_s_crop_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int left, int top, int width, int height); -int smdk4x12_v4l2_g_fbuf(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - void **base, int *width, int *height, int *fmt); -int smdk4x12_v4l2_s_fbuf(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - void *base, int width, int height, int fmt); - -/* - * V4L2 Output - */ - -int smdk4x12_v4l2_output_start(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_v4l2_output *output); -void smdk4x12_v4l2_output_stop(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_v4l2_output *output); -int smdk4x12_v4l2_output(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_v4l2_output *output, int buffer_address); -int smdk4x12_v4l2_output_release(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_v4l2_output *output); - -#endif diff --git a/camera/smdk4x12_exif.c b/camera/smdk4x12_exif.c deleted file mode 100644 index f2024fd..0000000 --- a/camera/smdk4x12_exif.c +++ /dev/null @@ -1,888 +0,0 @@ -/* - * Copyright (C) 2013-2014 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 "smdk4x12_camera" -#include -#include - -#include "smdk4x12_camera.h" - -int smdk4x12_exif_attributes_create_static(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_exif *exif) -{ - exif_attribute_t *attributes; - unsigned char gps_version[] = { 0x02, 0x02, 0x00, 0x00 }; - char property[PROPERTY_VALUE_MAX]; - uint32_t av; - - if (smdk4x12_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 smdk4x12_exif_attributes_create_gps(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_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 (smdk4x12_camera == NULL || exif == NULL) - return -EINVAL; - - attributes = &exif->attributes; - - gps_latitude_float = smdk4x12_param_float_get(smdk4x12_camera, "gps-latitude"); - gps_longitude_float = smdk4x12_param_float_get(smdk4x12_camera, "gps-longitude"); - gps_altitude_float = smdk4x12_param_float_get(smdk4x12_camera, "gps-altitude"); - if (gps_altitude_float == -1) - gps_altitude_float = (float) smdk4x12_param_int_get(smdk4x12_camera, "gps-altitude"); - gps_timestamp_int = smdk4x12_param_int_get(smdk4x12_camera, "gps-timestamp"); - gps_processing_method_string = smdk4x12_param_string_get(smdk4x12_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 smdk4x12_exif_attributes_create_params(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_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 (smdk4x12_camera == NULL || exif == NULL) - return -EINVAL; - - attributes = &exif->attributes; - - // Picture size - - attributes->width = smdk4x12_camera->picture_width; - attributes->height = smdk4x12_camera->picture_height; - - // Thumbnail - - attributes->widthThumb = smdk4x12_camera->jpeg_thumbnail_width; - attributes->heightThumb = smdk4x12_camera->jpeg_thumbnail_height; - attributes->enableThumb = true; - - // Orientation - - rotation = smdk4x12_param_int_get(smdk4x12_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 = smdk4x12_camera->camera_focal_length; - attributes->focal_length.den = EXIF_DEF_FOCAL_LEN_DEN; - - if (smdk4x12_camera->camera_capture_format == V4L2_PIX_FMT_INTERLEAVED) { - attributes->shutter_speed.num = APEX_EXPOSURE_TO_SHUTTER(smdk4x12_camera->capture_exif_exposure_time); - attributes->shutter_speed.den = 100; - - attributes->exposure_time.num = 1; - attributes->exposure_time.den = smdk4x12_camera->capture_exif_exposure_time; - - attributes->iso_speed_rating = smdk4x12_camera->capture_exif_iso; - - attributes->flash = smdk4x12_camera->capture_exif_flash; - - bv = smdk4x12_camera->capture_exif_exposure; - ev = smdk4x12_camera->capture_exif_exposure_bias; - } else { - shutter_speed = 100; - rc = smdk4x12_v4l2_g_ctrl(smdk4x12_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 = smdk4x12_v4l2_g_ctrl(smdk4x12_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 = smdk4x12_v4l2_g_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_EXIF_FLASH, - &flash_results); - if (rc < 0) - ALOGE("%s: Unable to get flash", __func__); - - attributes->flash = flash_results; - - rc = smdk4x12_v4l2_g_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_EXIF_BV, - (int *) &bv); - if (rc < 0) { - ALOGE("%s: Unable to get bv", __func__); - goto bv_static; - } - - rc = smdk4x12_v4l2_g_ctrl(smdk4x12_camera, 0, V4L2_CID_CAMERA_EXIF_EBV, - (int *) &ev); - if (rc < 0) { - ALOGE("%s: Unable to get ebv", __func__); - goto bv_static; - } - } - - goto bv_camera; - -bv_static: - exposure = smdk4x12_param_int_get(smdk4x12_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_camera: - attributes->brightness.num = bv; - attributes->brightness.den = EXIF_DEF_APEX_DEN; - - if (smdk4x12_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 (smdk4x12_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 (smdk4x12_camera->whitebalance == WHITE_BALANCE_AUTO || - smdk4x12_camera->whitebalance == WHITE_BALANCE_BASE) - attributes->white_balance = EXIF_WB_AUTO; - else - attributes->white_balance = EXIF_WB_MANUAL; - - switch (smdk4x12_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 = smdk4x12_exif_attributes_create_gps(smdk4x12_camera, exif); - if (rc < 0) { - ALOGE("%s: Unable to create GPS attributes", __func__); - return -1; - } - - return 0; -} - -int smdk4x12_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 smdk4x12_exif_start(struct smdk4x12_camera *smdk4x12_camera, struct smdk4x12_exif *exif) -{ - int rc; - - if (smdk4x12_camera == NULL || exif == NULL) - return -EINVAL; - - ALOGD("%s()", __func__); - - if (exif->enabled) { - ALOGE("Exif was already started"); - return -1; - } - - rc = smdk4x12_exif_attributes_create_static(smdk4x12_camera, exif); - if (rc < 0) { - ALOGE("%s: Unable to create exif attributes", __func__); - goto error; - } - - rc = smdk4x12_exif_attributes_create_params(smdk4x12_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 smdk4x12_exif_stop(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_exif *exif) -{ - if (smdk4x12_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 smdk4x12_exif(struct smdk4x12_camera *smdk4x12_camera, struct smdk4x12_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 (smdk4x12_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 (SMDK4x12_CAMERA_CALLBACK_DEFINED(request_memory)) { - memory = smdk4x12_camera->callbacks.request_memory(-1, memory_size, 1, smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_IMAGE_WIDTH, - EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->width, sizeof(attributes->width)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_IMAGE_HEIGHT, - EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->height, sizeof(attributes->height)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_ORIENTATION, - EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->orientation, sizeof(attributes->orientation)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_DATE_TIME, - EXIF_TYPE_ASCII, 20, &offset, exif_ifd_start, &attributes->date_time, sizeof(char)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_YCBCR_POSITIONING, - EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->ycbcr_positioning, sizeof(attributes->ycbcr_positioning)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_FNUMBER, - EXIF_TYPE_RATIONAL, 1, &offset, exif_ifd_start, &attributes->fnumber, sizeof(attributes->fnumber)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_EXPOSURE_PROGRAM, - EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->exposure_program, sizeof(attributes->exposure_program)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_EXIF_VERSION, - EXIF_TYPE_UNDEFINED, 4, NULL, NULL, &attributes->exif_version, sizeof(char)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_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 = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_APERTURE, - EXIF_TYPE_RATIONAL, 1, &offset, exif_ifd_start, &attributes->aperture, sizeof(attributes->aperture)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_BRIGHTNESS, - EXIF_TYPE_SRATIONAL, 1, &offset, exif_ifd_start, &attributes->brightness, sizeof(attributes->brightness)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_METERING_MODE, - EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->metering_mode, sizeof(attributes->metering_mode)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_FLASH, - EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->flash, sizeof(attributes->flash)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_COLOR_SPACE, - EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->color_space, sizeof(attributes->color_space)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_PIXEL_X_DIMENSION, - EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->width, sizeof(attributes->width)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_PIXEL_Y_DIMENSION, - EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->height, sizeof(attributes->height)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_EXPOSURE_MODE, - EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->exposure_mode, sizeof(attributes->exposure_mode)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_WHITE_BALANCE, - EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->white_balance, sizeof(attributes->white_balance)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_GPS_VERSION_ID, - EXIF_TYPE_BYTE, 4, NULL, NULL, &attributes->gps_version_id, sizeof(char)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_GPS_LATITUDE_REF, - EXIF_TYPE_ASCII, 2, NULL, NULL, &attributes->gps_latitude_ref, sizeof(char)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_GPS_LONGITUDE_REF, - EXIF_TYPE_ASCII, 2, NULL, NULL, &attributes->gps_longitude_ref, sizeof(char)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_GPS_ALTITUDE_REF, - EXIF_TYPE_BYTE, 1, NULL, NULL, &attributes->gps_altitude_ref, sizeof(char)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_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 = smdk4x12_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 = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_IMAGE_WIDTH, - EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->widthThumb, sizeof(attributes->widthThumb)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_IMAGE_HEIGHT, - EXIF_TYPE_LONG, 1, NULL, NULL, &attributes->heightThumb, sizeof(attributes->heightThumb)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_COMPRESSION_SCHEME, - EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->compression_scheme, sizeof(attributes->compression_scheme)); - pointer += count; - - count = smdk4x12_exif_write_data(pointer, EXIF_TAG_ORIENTATION, - EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->orientation, sizeof(attributes->orientation)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_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 = smdk4x12_exif_write_data(pointer, EXIF_TAG_RESOLUTION_UNIT, - EXIF_TYPE_SHORT, 1, NULL, NULL, &attributes->resolution_unit, sizeof(attributes->resolution_unit)); - pointer += count; - - count = smdk4x12_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 = smdk4x12_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/smdk4x12_ion.c b/camera/smdk4x12_ion.c deleted file mode 100644 index 39b2b06..0000000 --- a/camera/smdk4x12_ion.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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 "smdk4x12_ion" -#include - -#include "smdk4x12_camera.h" - -int smdk4x12_ion_init(struct smdk4x12_camera *smdk4x12_camera) -{ - smdk4x12_camera->ion_fd = -1; - - return 0; -} - -int smdk4x12_ion_open(struct smdk4x12_camera *smdk4x12_camera) -{ - int fd; - - fd = open("/dev/ion", O_RDWR); - if (fd < 0) { - ALOGE("%s: Unable to open ion device", __func__); - return -1; - } - - smdk4x12_camera->ion_fd = fd; - - return 0; -} - -void smdk4x12_ion_close(struct smdk4x12_camera *smdk4x12_camera) -{ - if (smdk4x12_camera->ion_fd >= 0) - close(smdk4x12_camera->ion_fd); - - smdk4x12_camera->ion_fd = -1; -} - -int smdk4x12_ion_alloc(struct smdk4x12_camera *smdk4x12_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 = smdk4x12_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 smdk4x12_ion_free(struct smdk4x12_camera *smdk4x12_camera, int fd) -{ - close(fd); - return 0; -} - -int smdk4x12_ion_phys(struct smdk4x12_camera *smdk4x12_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 = smdk4x12_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 smdk4x12_ion_msync(struct smdk4x12_camera *smdk4x12_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 = smdk4x12_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/smdk4x12_jpeg.c b/camera/smdk4x12_jpeg.c deleted file mode 100644 index 88cdd71..0000000 --- a/camera/smdk4x12_jpeg.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * 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 "smdk4x12_jpeg" -#include - -#include "smdk4x12_camera.h" - -int smdk4x12_jpeg_start(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_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 (smdk4x12_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] = smdk4x12_camera_buffer_length(jpeg->width, jpeg->height, jpeg->format); - - memory_ion_fd = smdk4x12_ion_alloc(smdk4x12_camera, buffer_in->length[0]); - if (memory_ion_fd < 0) { - ALOGE("%s: Unable to alloc input ION memory", __func__); - goto error; - } - - address = smdk4x12_ion_phys(smdk4x12_camera, memory_ion_fd); - - if (SMDK4x12_CAMERA_CALLBACK_DEFINED(request_memory)) { - memory = smdk4x12_camera->callbacks.request_memory(memory_ion_fd, buffer_in->length[0], 1, smdk4x12_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 = smdk4x12_ion_alloc(smdk4x12_camera, buffer_out->length[0]); - if (memory_ion_fd < 0) { - ALOGE("%s: Unable to alloc output ION memory", __func__); - goto error; - } - - address = smdk4x12_ion_phys(smdk4x12_camera, memory_ion_fd); - - if (SMDK4x12_CAMERA_CALLBACK_DEFINED(request_memory)) { - memory = smdk4x12_camera->callbacks.request_memory(memory_ion_fd, buffer_out->length[0], 1, smdk4x12_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) { - smdk4x12_ion_free(smdk4x12_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) { - smdk4x12_ion_free(smdk4x12_camera, jpeg->memory_out_ion_fd); - jpeg->memory_out_ion_fd = -1; - } -#endif - } - - rc = -1; - -complete: - return rc; -} - -void smdk4x12_jpeg_stop(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_jpeg *jpeg) -{ - struct jpeg_buf *buffer_in; - struct jpeg_buf *buffer_out; - int fd = -1; - int rc; - - if (smdk4x12_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) { - smdk4x12_ion_free(smdk4x12_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) { - smdk4x12_ion_free(smdk4x12_camera, jpeg->memory_out_ion_fd); - jpeg->memory_out_ion_fd = -1; - } -#endif - } - - jpeg->enabled = 0; -} - -int smdk4x12_jpeg(struct smdk4x12_camera *smdk4x12_camera, struct smdk4x12_jpeg *jpeg) -{ - struct jpeg_buf *buffer_in; - struct jpeg_buf *buffer_out; - int memory_size; - int fd = -1; - int rc; - - if (smdk4x12_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 = smdk4x12_ion_msync(smdk4x12_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 = smdk4x12_ion_msync(smdk4x12_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) { - smdk4x12_ion_free(smdk4x12_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) { - smdk4x12_ion_free(smdk4x12_camera, jpeg->memory_out_ion_fd); - jpeg->memory_out_ion_fd = -1; - } -#endif - } - - rc = -1; - -complete: - return rc; -} diff --git a/camera/smdk4x12_param.c b/camera/smdk4x12_param.c deleted file mode 100644 index b39ec7e..0000000 --- a/camera/smdk4x12_param.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * 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 "smdk4x12_param" -#include - -#include "smdk4x12_camera.h" - -int smdk4x12_param_register(struct smdk4x12_camera *smdk4x12_camera, char *key, - union smdk4x12_param_data data, enum smdk4x12_param_type type) -{ - struct list_head *list_end; - struct list_head *list; - struct smdk4x12_param *param; - - if (smdk4x12_camera == NULL || key == NULL) - return -EINVAL; - - param = (struct smdk4x12_param *) calloc(1, sizeof(struct smdk4x12_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 *) smdk4x12_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 (smdk4x12_camera->params == NULL) - smdk4x12_camera->params = param; - - return 0; - -error: - if (param != NULL) { - if (param->key != NULL) - free(param->key); - - free(param); - } - - return -1; -} - -void smdk4x12_param_unregister(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_param *param) -{ - struct list_head *list; - - if (smdk4x12_camera == NULL || param == NULL) - return; - - list = (struct list_head *) smdk4x12_camera->params; - while (list != NULL) { - if ((void *) list == (void *) param) { - list_head_remove(list); - - if ((void *) list == (void *) smdk4x12_camera->params) - smdk4x12_camera->params = (struct smdk4x12_param *) list->next; - - if (param->type == EXYNOS_PARAM_STRING && param->data.string != NULL) - free(param->data.string); - - memset(param, 0, sizeof(struct smdk4x12_param)); - free(param); - - break; - } - -list_continue: - list = list->next; - } -} - -struct smdk4x12_param *smdk4x12_param_find_key(struct smdk4x12_camera *smdk4x12_camera, - char *key) -{ - struct smdk4x12_param *param; - struct list_head *list; - - if (smdk4x12_camera == NULL || key == NULL) - return NULL; - - list = (struct list_head *) smdk4x12_camera->params; - while (list != NULL) { - param = (struct smdk4x12_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 smdk4x12_param_data_set(struct smdk4x12_camera *smdk4x12_camera, char *key, - union smdk4x12_param_data data, enum smdk4x12_param_type type) -{ - struct smdk4x12_param *param; - - if (smdk4x12_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 = smdk4x12_param_find_key(smdk4x12_camera, key); - if (param == NULL) { - // The key isn't in the list yet - smdk4x12_param_register(smdk4x12_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 smdk4x12_param_data_get(struct smdk4x12_camera *smdk4x12_camera, char *key, - union smdk4x12_param_data *data, enum smdk4x12_param_type type) -{ - struct smdk4x12_param *param; - - if (smdk4x12_camera == NULL || key == NULL || data == NULL) - return -EINVAL; - - param = smdk4x12_param_find_key(smdk4x12_camera, key); - if (param == NULL || param->type != type) - return -1; - - memcpy(data, ¶m->data, sizeof(param->data)); - - return 0; -} - -int smdk4x12_param_int_get(struct smdk4x12_camera *smdk4x12_camera, - char *key) -{ - union smdk4x12_param_data data; - int rc; - - if (smdk4x12_camera == NULL || key == NULL) - return -EINVAL; - - rc = smdk4x12_param_data_get(smdk4x12_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 smdk4x12_param_float_get(struct smdk4x12_camera *smdk4x12_camera, - char *key) -{ - union smdk4x12_param_data data; - int rc; - - if (smdk4x12_camera == NULL || key == NULL) - return -EINVAL; - - rc = smdk4x12_param_data_get(smdk4x12_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 *smdk4x12_param_string_get(struct smdk4x12_camera *smdk4x12_camera, - char *key) -{ - union smdk4x12_param_data data; - int rc; - - if (smdk4x12_camera == NULL || key == NULL) - return NULL; - - rc = smdk4x12_param_data_get(smdk4x12_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 smdk4x12_param_int_set(struct smdk4x12_camera *smdk4x12_camera, - char *key, int integer) -{ - union smdk4x12_param_data data; - int rc; - - if (smdk4x12_camera == NULL || key == NULL) - return -EINVAL; - - data.integer = integer; - - rc = smdk4x12_param_data_set(smdk4x12_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 smdk4x12_param_float_set(struct smdk4x12_camera *smdk4x12_camera, - char *key, float floating) -{ - union smdk4x12_param_data data; - int rc; - - if (smdk4x12_camera == NULL || key == NULL) - return -EINVAL; - - data.floating = floating; - - rc = smdk4x12_param_data_set(smdk4x12_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 smdk4x12_param_string_set(struct smdk4x12_camera *smdk4x12_camera, - char *key, char *string) -{ - union smdk4x12_param_data data; - int rc; - - if (smdk4x12_camera == NULL || key == NULL || string == NULL) - return -EINVAL; - - data.string = string; - - rc = smdk4x12_param_data_set(smdk4x12_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 *smdk4x12_params_string_get(struct smdk4x12_camera *smdk4x12_camera) -{ - struct smdk4x12_param *param; - struct list_head *list; - char *string = NULL; - char *s = NULL; - int length = 0; - int l = 0; - - if (smdk4x12_camera == NULL) - return NULL; - - list = (struct list_head *) smdk4x12_camera->params; - while (list != NULL) { - param = (struct smdk4x12_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 *) smdk4x12_camera->params; - while (list != NULL) { - param = (struct smdk4x12_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 smdk4x12_params_string_set(struct smdk4x12_camera *smdk4x12_camera, char *string) -{ - union smdk4x12_param_data data; - enum smdk4x12_param_type type; - - char *d = NULL; - char *s = NULL; - char *k = NULL; - char *v = NULL; - - char *key; - char *value; - - int rc; - int i; - - if (smdk4x12_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 = smdk4x12_param_data_set(smdk4x12_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/smdk4x12_utils.c b/camera/smdk4x12_utils.c deleted file mode 100644 index 90d2167..0000000 --- a/camera/smdk4x12_utils.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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 "smdk4x12_utils" -#include - -#include "smdk4x12_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 smdk4x12_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 = SMDK4x12_CAMERA_ALIGN(width * height); - buffer_length += SMDK4x12_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 smdk4x12_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 += SMDK4x12_CAMERA_ALIGN(width * height); - - if (address_cb != NULL) - *address_cb = address; - - address += SMDK4x12_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 += SMDK4x12_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; - } -} - -int smdk4x12_gralloc_format(int format) -{ - switch (format) { - case V4L2_PIX_FMT_NV21: - return HAL_PIXEL_FORMAT_YCrCb_420_SP; - case V4L2_PIX_FMT_YUV420: - return HAL_PIXEL_FORMAT_YV12; - case V4L2_PIX_FMT_RGB565: - return HAL_PIXEL_FORMAT_RGB_565; - case V4L2_PIX_FMT_RGB32: - return HAL_PIXEL_FORMAT_RGBX_8888; - default: - return HAL_PIXEL_FORMAT_YCrCb_420_SP; - } -} diff --git a/camera/smdk4x12_v4l2.c b/camera/smdk4x12_v4l2.c deleted file mode 100644 index e8b130e..0000000 --- a/camera/smdk4x12_v4l2.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - * 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 "smdk4x12_v4l2" -#include - -#include "smdk4x12_camera.h" - -int smdk4x12_v4l2_init(struct smdk4x12_camera *smdk4x12_camera) -{ - int i; - - for (i = 0; i < SMDK4x12_CAMERA_MAX_V4L2_NODES_COUNT; i++) - smdk4x12_camera->v4l2_fds[i] = -1; - - return 0; -} - -int smdk4x12_v4l2_index(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id) -{ - int index; - int i; - - if (smdk4x12_camera == NULL || smdk4x12_camera->config == NULL || - smdk4x12_camera->config->v4l2_nodes == NULL) - return -EINVAL; - - if (smdk4x12_v4l2_id > smdk4x12_camera->config->v4l2_nodes_count) - return -1; - - index = -1; - for (i = 0; i < smdk4x12_camera->config->v4l2_nodes_count; i++) { - if (smdk4x12_camera->config->v4l2_nodes[i].id == smdk4x12_v4l2_id && - smdk4x12_camera->config->v4l2_nodes[i].node != NULL) { - index = i; - } - } - - return index; -} - -int smdk4x12_v4l2_fd(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id) -{ - int index; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - index = smdk4x12_v4l2_index(smdk4x12_camera, smdk4x12_v4l2_id); - if (index < 0) { - ALOGE("%s: Unable to get v4l2 index for id %d", __func__, smdk4x12_v4l2_id); - return -1; - } - - return smdk4x12_camera->v4l2_fds[index]; -} - -int smdk4x12_v4l2_open(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id) -{ - char *node; - int index; - int fd; - - if (smdk4x12_camera == NULL || smdk4x12_camera->config == NULL || - smdk4x12_camera->config->v4l2_nodes == NULL) - return -EINVAL; - - index = smdk4x12_v4l2_index(smdk4x12_camera, smdk4x12_v4l2_id); - if (index < 0) { - ALOGE("%s: Unable to get v4l2 node for id %d", __func__, smdk4x12_v4l2_id); - return -1; - } - - node = smdk4x12_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__, smdk4x12_v4l2_id); - return -1; - } - - smdk4x12_camera->v4l2_fds[index] = fd; - - return 0; -} - -void smdk4x12_v4l2_close(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id) -{ - int index; - - if (smdk4x12_camera == NULL || smdk4x12_camera->config == NULL || - smdk4x12_camera->config->v4l2_nodes == NULL) - return; - - index = smdk4x12_v4l2_index(smdk4x12_camera, smdk4x12_v4l2_id); - if (index < 0) { - ALOGE("%s: Unable to get v4l2 node for id %d", __func__, smdk4x12_v4l2_id); - return; - } - - if (smdk4x12_camera->v4l2_fds[index] >= 0) - close(smdk4x12_camera->v4l2_fds[index]); - - smdk4x12_camera->v4l2_fds[index] = -1; -} - -int smdk4x12_v4l2_ioctl(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int request, void *data) -{ - int fd; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - fd = smdk4x12_v4l2_fd(smdk4x12_camera, smdk4x12_v4l2_id); - if (fd < 0) { - ALOGE("%s: Unable to get v4l2 fd for id %d", __func__, smdk4x12_v4l2_id); - return -1; - } - - return ioctl(fd, request, data); -} - -int smdk4x12_v4l2_poll(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id) -{ - struct pollfd events; - int fd; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - fd = smdk4x12_v4l2_fd(smdk4x12_camera, smdk4x12_v4l2_id); - if (fd < 0) { - ALOGE("%s: Unable to get v4l2 fd for id %d", __func__, smdk4x12_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 smdk4x12_v4l2_qbuf(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int type, int memory, int index, unsigned long userptr) -{ - struct v4l2_buffer buffer; - int rc; - - if (smdk4x12_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 = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_QBUF, &buffer); - return rc; -} - -int smdk4x12_v4l2_qbuf_cap(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int index) -{ - return smdk4x12_v4l2_qbuf(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_MEMORY_MMAP, index, 0); -} - -int smdk4x12_v4l2_qbuf_out(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int index, unsigned long userptr) -{ - return smdk4x12_v4l2_qbuf(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, - V4L2_MEMORY_USERPTR, index, userptr); -} - -int smdk4x12_v4l2_dqbuf(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int type, int memory) -{ - struct v4l2_buffer buffer; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - memset(&buffer, 0, sizeof(buffer)); - buffer.type = type; - buffer.memory = memory; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_DQBUF, &buffer); - if (rc < 0) - return rc; - - return buffer.index; -} - -int smdk4x12_v4l2_dqbuf_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id) -{ - return smdk4x12_v4l2_dqbuf(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_MEMORY_MMAP); -} - -int smdk4x12_v4l2_dqbuf_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id) -{ - return smdk4x12_v4l2_dqbuf(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, - V4L2_MEMORY_USERPTR); -} - -int smdk4x12_v4l2_reqbufs(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type, int memory, int count) -{ - struct v4l2_requestbuffers requestbuffers; - int rc; - - if (smdk4x12_camera == NULL || count < 0) - return -EINVAL; - - requestbuffers.type = type; - requestbuffers.count = count; - requestbuffers.memory = memory; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_REQBUFS, &requestbuffers); - if (rc < 0) - return rc; - - return requestbuffers.count; -} - -int smdk4x12_v4l2_reqbufs_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int count) -{ - return smdk4x12_v4l2_reqbufs(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_MEMORY_MMAP, count); -} - -int smdk4x12_v4l2_reqbufs_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int count) -{ - return smdk4x12_v4l2_reqbufs(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, - V4L2_MEMORY_USERPTR, count); -} - -int smdk4x12_v4l2_querybuf(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type, int memory, int index) -{ - struct v4l2_buffer buffer; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - memset(&buffer, 0, sizeof(buffer)); - buffer.type = type; - buffer.memory = memory; - buffer.index = index; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_QUERYBUF, &buffer); - if (rc < 0) - return rc; - - return buffer.length; -} - -int smdk4x12_v4l2_querybuf_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int index) -{ - return smdk4x12_v4l2_querybuf(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_MEMORY_MMAP, index); -} - -int smdk4x12_v4l2_querybuf_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int index) -{ - return smdk4x12_v4l2_querybuf(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, - V4L2_MEMORY_USERPTR, index); -} - -int smdk4x12_v4l2_querycap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int flags) -{ - struct v4l2_capability cap; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_QUERYCAP, &cap); - if (rc < 0) - return rc; - - if (!(cap.capabilities & flags)) - return -1; - - return 0; -} - -int smdk4x12_v4l2_querycap_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id) -{ - return smdk4x12_v4l2_querycap(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_CAP_VIDEO_CAPTURE); -} - -int smdk4x12_v4l2_querycap_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id) -{ - return smdk4x12_v4l2_querycap(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_CAP_VIDEO_OUTPUT); -} - -int smdk4x12_v4l2_streamon(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type) -{ - enum v4l2_buf_type buf_type; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - buf_type = type; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_STREAMON, &buf_type); - return rc; -} - -int smdk4x12_v4l2_streamon_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id) -{ - return smdk4x12_v4l2_streamon(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE); -} - -int smdk4x12_v4l2_streamon_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id) -{ - return smdk4x12_v4l2_streamon(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT); -} - -int smdk4x12_v4l2_streamoff(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type) -{ - enum v4l2_buf_type buf_type; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - buf_type = type; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_STREAMOFF, &buf_type); - return rc; -} - -int smdk4x12_v4l2_streamoff_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id) -{ - return smdk4x12_v4l2_streamoff(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE); -} - -int smdk4x12_v4l2_streamoff_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id) -{ - return smdk4x12_v4l2_streamoff(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT); -} - -int smdk4x12_v4l2_g_fmt(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int type, int *width, int *height, int *fmt) -{ - struct v4l2_format format; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - format.type = type; - format.fmt.pix.field = V4L2_FIELD_NONE; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_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 smdk4x12_v4l2_g_fmt_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int *width, int *height, int *fmt) -{ - return smdk4x12_v4l2_g_fmt(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, - width, height, fmt); -} - -int smdk4x12_v4l2_g_fmt_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int *width, int *height, int *fmt) -{ - return smdk4x12_v4l2_g_fmt(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, - width, height, fmt); -} - -int smdk4x12_v4l2_s_fmt_pix(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type, int width, int height, int fmt, int field, - int priv) -{ - struct v4l2_format format; - int rc; - - if (smdk4x12_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 = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_S_FMT, &format); - return rc; - - return 0; -} - -int smdk4x12_v4l2_s_fmt_pix_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int width, int height, int fmt, int priv) -{ - return smdk4x12_v4l2_s_fmt_pix(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, - width, height, fmt, V4L2_FIELD_NONE, priv); -} - -int smdk4x12_v4l2_s_fmt_pix_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int width, int height, int fmt, int priv) -{ - return smdk4x12_v4l2_s_fmt_pix(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, - width, height, fmt, V4L2_FIELD_NONE, priv); -} - -int smdk4x12_v4l2_s_fmt_win(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int left, int top, int width, int height) -{ - struct v4l2_format format; - int rc; - - if (smdk4x12_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 = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_S_FMT, &format); - return rc; -} - -int smdk4x12_v4l2_enum_fmt(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int type, int fmt) -{ - struct v4l2_fmtdesc fmtdesc; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - fmtdesc.type = type; - fmtdesc.index = 0; - - do { - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_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 smdk4x12_v4l2_enum_fmt_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int fmt) -{ - return smdk4x12_v4l2_enum_fmt(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, - fmt); -} - -int smdk4x12_v4l2_enum_fmt_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int fmt) -{ - return smdk4x12_v4l2_enum_fmt(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, - fmt); -} - -int smdk4x12_v4l2_enum_input(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int id) -{ - struct v4l2_input input; - int rc; - - if (smdk4x12_camera == NULL || id < 0) - return -EINVAL; - - input.index = id; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_ENUMINPUT, &input); - if (rc < 0) - return rc; - - if (input.name[0] == '\0') - return -1; - - return 0; -} - -int smdk4x12_v4l2_s_input(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int id) -{ - struct v4l2_input input; - int rc; - - if (smdk4x12_camera == NULL || id < 0) - return -EINVAL; - - input.index = id; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_S_INPUT, &input); - return rc; -} - -int smdk4x12_v4l2_g_ext_ctrls(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, struct v4l2_ext_control *control, int count) -{ - struct v4l2_ext_controls controls; - int rc; - - if (smdk4x12_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 = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_G_EXT_CTRLS, &controls); - return rc; -} - -int smdk4x12_v4l2_g_ctrl(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int id, int *value) -{ - struct v4l2_control control; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - control.id = id; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_G_CTRL, &control); - if (rc < 0) - return rc; - - if (value != NULL) - *value = control.value; - - return 0; -} - -int smdk4x12_v4l2_s_ctrl(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int id, int value) -{ - struct v4l2_control control; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - control.id = id; - control.value = value; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_S_CTRL, &control); - if (rc < 0) - return rc; - - return control.value; -} - -int smdk4x12_v4l2_s_parm(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int type, struct v4l2_streamparm *streamparm) -{ - int rc; - - if (smdk4x12_camera == NULL || streamparm == NULL) - return -EINVAL; - - streamparm->type = type; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_S_PARM, streamparm); - return rc; -} - -int smdk4x12_v4l2_s_parm_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, struct v4l2_streamparm *streamparm) -{ - return smdk4x12_v4l2_s_parm(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, - streamparm); -} - -int smdk4x12_v4l2_s_parm_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, struct v4l2_streamparm *streamparm) -{ - return smdk4x12_v4l2_s_parm(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, - streamparm); -} - -int smdk4x12_v4l2_s_crop(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - int type, int left, int top, int width, int height) -{ - struct v4l2_crop crop; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - crop.type = type; - crop.c.left = left; - crop.c.top = top; - crop.c.width = width; - crop.c.height = height; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_S_CROP, &crop); - return rc; -} - -int smdk4x12_v4l2_s_crop_cap(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int left, int top, int width, int height) -{ - return smdk4x12_v4l2_s_crop(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_CAPTURE, - left, top, width, height); -} - -int smdk4x12_v4l2_s_crop_out(struct smdk4x12_camera *smdk4x12_camera, - int smdk4x12_v4l2_id, int left, int top, int width, int height) -{ - return smdk4x12_v4l2_s_crop(smdk4x12_camera, smdk4x12_v4l2_id, V4L2_BUF_TYPE_VIDEO_OUTPUT, - left, top, width, height); -} - -int smdk4x12_v4l2_g_fbuf(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - void **base, int *width, int *height, int *fmt) -{ - struct v4l2_framebuffer framebuffer; - int rc; - - if (smdk4x12_camera == NULL) - return -EINVAL; - - rc = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_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 smdk4x12_v4l2_s_fbuf(struct smdk4x12_camera *smdk4x12_camera, int smdk4x12_v4l2_id, - void *base, int width, int height, int fmt) -{ - struct v4l2_framebuffer framebuffer; - int rc; - - if (smdk4x12_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 = smdk4x12_v4l2_ioctl(smdk4x12_camera, smdk4x12_v4l2_id, VIDIOC_S_FBUF, &framebuffer); - return rc; -} diff --git a/camera/smdk4x12_v4l2_output.c b/camera/smdk4x12_v4l2_output.c deleted file mode 100644 index 0f8cad2..0000000 --- a/camera/smdk4x12_v4l2_output.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * 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 "smdk4x12_v4l2_output" -#include - -#include "smdk4x12_camera.h" - -int smdk4x12_v4l2_output_start(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_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 (smdk4x12_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 = smdk4x12_camera_buffer_length(width, height, format); - - rc = smdk4x12_v4l2_open(smdk4x12_camera, v4l2_id); - if (rc < 0) { - ALOGE("%s: Unable to open v4l2 device", __func__); - goto error; - } - - rc = smdk4x12_v4l2_querycap_out(smdk4x12_camera, v4l2_id); - if (rc < 0) { - ALOGE("%s: Unable to query capabilities", __func__); - goto error; - } - - rc = smdk4x12_v4l2_g_fmt_out(smdk4x12_camera, v4l2_id, NULL, NULL, NULL); - if (rc < 0) { - ALOGE("%s: Unable to get format", __func__); - goto error; - } - - value = 0; - rc = smdk4x12_v4l2_g_ctrl(smdk4x12_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 = smdk4x12_v4l2_g_ctrl(smdk4x12_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 = smdk4x12_v4l2_s_ctrl(smdk4x12_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 = smdk4x12_v4l2_s_fmt_pix_out(smdk4x12_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 = smdk4x12_v4l2_s_crop_out(smdk4x12_camera, v4l2_id, 0, 0, buffer_width, buffer_height); - if (rc < 0) { - ALOGE("%s: Unable to crop", __func__); - goto error; - } - - rc = smdk4x12_v4l2_reqbufs_out(smdk4x12_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 (SMDK4x12_CAMERA_CALLBACK_DEFINED(request_memory)) { - fd = smdk4x12_v4l2_fd(smdk4x12_camera, v4l2_id); - if (fd < 0) { - ALOGE("%s: Unable to get v4l2 fd for id %d", __func__, v4l2_id); - goto error; - } - - memory = smdk4x12_camera->callbacks.request_memory(fd, buffer_length, buffers_count, smdk4x12_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 = smdk4x12_ion_alloc(smdk4x12_camera, buffers_count * buffer_length); - if (memory_ion_fd < 0) { - ALOGE("%s: Unable to alloc ION memory", __func__); - goto error; - } - - if (SMDK4x12_CAMERA_CALLBACK_DEFINED(request_memory)) { - memory = smdk4x12_camera->callbacks.request_memory(memory_ion_fd, buffer_length, buffers_count, smdk4x12_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 = smdk4x12_ion_phys(smdk4x12_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) - smdk4x12_ion_free(smdk4x12_camera, memory_ion_fd); -#endif - - smdk4x12_v4l2_close(smdk4x12_camera, v4l2_id); - - rc = -1; - -complete: - return rc; -} - -void smdk4x12_v4l2_output_stop(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_v4l2_output *output) -{ - int v4l2_id; - int rc; - - if (smdk4x12_camera == NULL || output == NULL) - return; - -// ALOGD("%s()", __func__); - - if (!output->enabled) { - ALOGE("Output was already stopped"); - return; - } - - v4l2_id = output->v4l2_id; - - rc = smdk4x12_v4l2_reqbufs_out(smdk4x12_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) { - smdk4x12_ion_free(smdk4x12_camera, output->memory_ion_fd); - output->memory_ion_fd = -1; - } -#endif - - smdk4x12_v4l2_close(smdk4x12_camera, v4l2_id); - - output->enabled = 0; -} - -int smdk4x12_v4l2_output(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_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 (smdk4x12_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 = smdk4x12_v4l2_g_fbuf(smdk4x12_camera, v4l2_id, &fb_base, NULL, NULL, NULL); - if (rc < 0) { - ALOGE("%s: Unable to get fbuf", __func__); - goto error; - } - - rc = smdk4x12_v4l2_s_fbuf(smdk4x12_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; - - smdk4x12_camera_yuv_planes(width, height, format, address, (int *) &fimc_buffer.base[0], (int *) &fimc_buffer.base[1], (int *) &fimc_buffer.base[2]); - - rc = smdk4x12_v4l2_s_ctrl(smdk4x12_camera, v4l2_id, V4L2_CID_DST_INFO, (int) &fimc_buffer); - if (rc < 0) { - ALOGE("%s: Unable to set dst info", __func__); - goto error; - } - - rc = smdk4x12_v4l2_s_fmt_win(smdk4x12_camera, v4l2_id, 0, 0, width, height); - if (rc < 0) { - ALOGE("%s: Unable to set overlay win", __func__); - goto error; - } - - rc = smdk4x12_v4l2_streamon_out(smdk4x12_camera, v4l2_id); - if (rc < 0) { - ALOGE("%s: Unable to start stream", __func__); - goto error; - } - - memset(&fimc_buffer, 0, sizeof(fimc_buffer)); - - smdk4x12_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 = smdk4x12_v4l2_qbuf_out(smdk4x12_camera, v4l2_id, 0, (unsigned long) &fimc_buffer); - if (rc < 0) { - ALOGE("%s: Unable to queue buffer", __func__); - goto error; - } - - rc = smdk4x12_v4l2_dqbuf_out(smdk4x12_camera, v4l2_id); - if (rc < 0) { - ALOGE("%s: Unable to dequeue buffer", __func__); - goto error; - } - - rc = smdk4x12_v4l2_streamoff_out(smdk4x12_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 smdk4x12_v4l2_output_release(struct smdk4x12_camera *smdk4x12_camera, - struct smdk4x12_v4l2_output *output) -{ - int buffers_count; - int memory_index; - - if (smdk4x12_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; -} -- cgit v1.2.3