diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..4e6ee3b
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,17 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+ifeq ($(TARGET_BOOTLOADER_BOARD_NAME),s5pc110)
+ include $(all-subdir-makefiles)
+endif
diff --git a/BoardConfigCommon.mk b/BoardConfigCommon.mk
new file mode 100644
index 0000000..25a9c77
--- /dev/null
+++ b/BoardConfigCommon.mk
@@ -0,0 +1,106 @@
+#
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# BoardConfig.mk
+#
+# Product-specific compile-time definitions.
+#
+
+# Set this up here so that BoardVendorConfig.mk can override it
+BOARD_USES_GENERIC_AUDIO := false
+
+BOARD_USES_LIBSECRIL_STUB := true
+
+# ARMv7-A Cortex-A8 architecture
+TARGET_CPU_ABI := armeabi-v7a
+TARGET_CPU_ABI2 := armeabi
+TARGET_ARCH_VARIANT := armv7-a-neon
+ARCH_ARM_HAVE_TLS_REGISTER := true
+TARGET_GLOBAL_CFLAGS += -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp
+TARGET_GLOBAL_CPPFLAGS += -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp
+ARCH_ARM_HAVE_TLS_REGISTER := true
+
+TARGET_NO_BOOTLOADER := true
+TARGET_NO_RADIOIMAGE := true
+
+TARGET_PROVIDES_INIT := true
+TARGET_RECOVERY_INITRC := device/samsung/p1-common/recovery.rc
+
+TARGET_BOARD_PLATFORM := s5pc110
+TARGET_BOARD_PLATFORM_GPU := POWERVR_SGX540_120
+TARGET_BOOTLOADER_BOARD_NAME := s5pc110
+
+TARGET_PROVIDES_LIBAUDIO := true
+
+# Releasetools
+TARGET_RELEASETOOL_OTA_FROM_TARGET_SCRIPT := ./device/samsung/p1-common/releasetools/p1_ota_from_target_files
+TARGET_RELEASETOOL_IMG_FROM_TARGET_SCRIPT := ./device/samsung/p1-common/releasetools/p1_img_from_target_files
+
+# Bluetooth
+BOARD_HAVE_BLUETOOTH := true
+BOARD_HAVE_BLUETOOTH_BCM := true
+
+# WiFi related defines
+BOARD_WPA_SUPPLICANT_DRIVER := WEXT
+WPA_SUPPLICANT_VERSION := VER_0_8_X
+BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_wext
+BOARD_WLAN_DEVICE := bcm4329
+WIFI_DRIVER_MODULE_PATH := "/system/lib/modules/dhd.ko"
+WIFI_DRIVER_MODULE_ARG := "firmware_path=/system/etc/wifi/bcm4329_sta.bin nvram_path=/system/etc/wifi/nvram_net.txt dhd_watchdog_ms=10 dhd_poll=1"
+WIFI_DRIVER_FW_PATH_AP := "/system/etc/wifi/bcm4329_aps.bin"
+WIFI_DRIVER_FW_PATH_STA := "/system/etc/wifi/bcm4329_sta.bin"
+WIFI_DRIVER_MODULE_NAME := "dhd"
+BOARD_WEXT_NO_COMBO_SCAN := true
+
+USE_CAMERA_STUB := false
+ifeq ($(USE_CAMERA_STUB),false)
+BOARD_CAMERA_LIBRARIES := libcamera
+endif
+BOARD_V4L2_DEVICE := /dev/video1
+BOARD_CAMERA_DEVICE := /dev/video0
+BOARD_SECOND_CAMERA_DEVICE := /dev/video2
+
+# OpenGL stuff
+BOARD_EGL_CFG := device/samsung/p1-common/prebuilt/lib/egl/egl.cfg
+USE_OPENGL_RENDERER := true
+
+# skia
+BOARD_USE_SKIA_LCDTEXT := true
+
+# Device related defines
+BOARD_NAND_PAGE_SIZE := 4096 -s 128
+BOARD_KERNEL_BASE := 0x32000000
+BOARD_KERNEL_PAGESIZE := 4096
+BOARD_KERNEL_CMDLINE := console=ttyFIQ0,115200 init=/init no_console_suspend
+
+BOARD_BOOTIMAGE_PARTITION_SIZE := 7864320
+BOARD_SYSTEMIMAGE_PARTITION_SIZE := 262144000
+BOARD_USERDATAIMAGE_PARTITION_SIZE := 1319108608
+BOARD_FLASH_BLOCK_SIZE := 4096
+
+# Vold
+BOARD_VOLD_EMMC_SHARES_DEV_MAJOR := true
+TARGET_USE_CUSTOM_LUN_FILE_PATH := "/sys/devices/platform/usb_mass_storage/lun0/file"
+
+# Recovery
+TARGET_USERIMAGES_USE_EXT4 := true
+BOARD_HAS_NO_SELECT_BUTTON := true
+BOARD_CUSTOM_BOOTIMG_MK := device/samsung/p1-common/shbootimg.mk
+TARGET_RECOVERY_PRE_COMMAND := "echo 1 > /cache/.startrecovery; sync;"
+BOARD_CUSTOM_GRAPHICS := ../../../device/samsung/p1-common/recovery/graphics.c
+BOARD_USES_BML_OVER_MTD := true
+
+# MTP
+BOARD_MTP_DEVICE := "/dev/usb_mtp_gadget"
diff --git a/Credits.html b/Credits.html
new file mode 100644
index 0000000..133cd67
--- /dev/null
+++ b/Credits.html
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+CyanogenMod 9
+
+
+
+
+Th is
+is an unofficial port of
+cyanogenmod 9 for Galaxy Tab (P1).
+
+
+Official
+thread : http://forum.xda-developers.com/showthread.php?t=1385153
+Visit
+http://www.cyanogenmod.com
+!
+
+
+This
+ROM is free of charge and must not be sold. You are free to copy and
+distribute it as long as this file remains unchanged.
+
+
+
+
+Greetings to
+
+
+
+me (cdesai)
+
+angel_666
+
+koxudaxi
+
+Humberos
+
+red_rebel
+
+sbradymobile
+
+jt1134
+
+Techomancer
+
+Cyanogenmod Team
+
+TeamHacksung!
+
+Google!
+
+Samsung
+
+All the Tab community@xda
+
+All the folks who have worked on aries and the tab
+
+All the XDA developers
+
+And anyone else i forgot
+
+
+
+
+Enjoy
+this ROM!
+
+
+
+
+
+
+
+
diff --git a/P1Parts/Android.mk b/P1Parts/Android.mk
new file mode 100644
index 0000000..bb85b23
--- /dev/null
+++ b/P1Parts/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := P1Parts
+LOCAL_CERTIFICATE := platform
+
+# Required so that symbols used by the jni library doesn't get stripped out
+LOCAL_PROGUARD_ENABLED := disabled
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/P1Parts/AndroidManifest.xml b/P1Parts/AndroidManifest.xml
new file mode 100644
index 0000000..5f37a8a
--- /dev/null
+++ b/P1Parts/AndroidManifest.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/P1Parts/res/drawable/color_tuning_preview.xml b/P1Parts/res/drawable/color_tuning_preview.xml
new file mode 100644
index 0000000..2d83c10
--- /dev/null
+++ b/P1Parts/res/drawable/color_tuning_preview.xml
@@ -0,0 +1,9 @@
+
+
+
+
\ No newline at end of file
diff --git a/P1Parts/res/layout/preference_dialog_color_tuning.xml b/P1Parts/res/layout/preference_dialog_color_tuning.xml
new file mode 100644
index 0000000..f228541
--- /dev/null
+++ b/P1Parts/res/layout/preference_dialog_color_tuning.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/P1Parts/res/values-de/arrays.xml b/P1Parts/res/values-de/arrays.xml
new file mode 100644
index 0000000..7339912
--- /dev/null
+++ b/P1Parts/res/values-de/arrays.xml
@@ -0,0 +1,18 @@
+
+
+ - Standard (1,6 Sekunden)
+ - 0,5 Sekunden
+ - 2 Sekunden
+ - 5 Sekunden
+ - 10 Sekunden
+ - 15 Sekunden
+ - 30 Sekunden
+ - Nie
+
+
+
+ - Nur UMTS
+ - Nur HSDPA
+ - HSDPA + HSUPA
+
+
diff --git a/P1Parts/res/values-de/strings.xml b/P1Parts/res/values-de/strings.xml
new file mode 100644
index 0000000..b9f9d98
--- /dev/null
+++ b/P1Parts/res/values-de/strings.xml
@@ -0,0 +1,19 @@
+
+
+ Galaxy-Tab-Einstellungen
+
+ Bildschirm
+ Farbanpassung
+ Bildschirmfarben kalibrieren
+ Rot
+ Grün
+ Blau
+
+ Tasten
+ Beleuchtung
+ Verzögerung bis zum Abschalten der Tastenbeleuchtung einstellen
+
+ Funk
+ HSPA
+ HSDPA/HSUPA aktivieren
+
diff --git a/P1Parts/res/values-pl/arrays.xml b/P1Parts/res/values-pl/arrays.xml
new file mode 100644
index 0000000..4e4b53e
--- /dev/null
+++ b/P1Parts/res/values-pl/arrays.xml
@@ -0,0 +1,35 @@
+
+
+ - Domyślnie (1.6 sekundy)
+ - 0.5 sekundy
+ - 2 sekundy
+ - 5 sekund
+ - 10 sekund
+ - 15 sekund
+ - 30 sekund
+ - Nigdy
+
+
+
+ - 1600
+ - 500
+ - 2000
+ - 5000
+ - 10000
+ - 15000
+ - 30000
+ - -1
+
+
+
+ - Tylko UMTS
+ - Tylko HSDPA
+ - HSDPA lub HSUPA
+
+
+
+ - 21
+ - 22
+ - 23
+
+
diff --git a/P1Parts/res/values-pl/strings.xml b/P1Parts/res/values-pl/strings.xml
new file mode 100644
index 0000000..0105608
--- /dev/null
+++ b/P1Parts/res/values-pl/strings.xml
@@ -0,0 +1,19 @@
+
+
+ Ustawienia Galaxy Tab
+
+ Wyświetlacz
+ Modyfikacja kolorów
+ Kalibruj kolory wyświetlacza
+ Czerwony
+ Zielony
+ Niebieski
+
+ Przyciski dotykowe
+ Czas podświetlenia
+ Określ po jakim czasie podświetlenie klawiszy zgaśnie
+
+ Modem
+ HSPA
+ Włącz HSDPA/HSUPA
+
diff --git a/P1Parts/res/values-pt/arrays.xml b/P1Parts/res/values-pt/arrays.xml
new file mode 100644
index 0000000..75233fa
--- /dev/null
+++ b/P1Parts/res/values-pt/arrays.xml
@@ -0,0 +1,45 @@
+
+
+ - Padrão (1.6 segundos)
+ - 0.5 segundos
+ - 2 segundos
+ - 5 segundos
+ - 10 segundos
+ - 15 segundos
+ - 30 segundos
+ - Nunca
+
+
+
+ - 1600
+ - 500
+ - 2000
+ - 5000
+ - 10000
+ - 15000
+ - 30000
+ - -1
+
+
+
+ - UMTS Apenas
+ - HSDPA Apenas
+ - HSDPA + HSUPA
+
+
+
+ - 21
+ - 22
+ - 23
+
+
+
+ - NTSC
+ - PAL
+
+
+
+ - 1
+ - 2
+
+
diff --git a/P1Parts/res/values-pt/strings.xml b/P1Parts/res/values-pt/strings.xml
new file mode 100644
index 0000000..6e0937e
--- /dev/null
+++ b/P1Parts/res/values-pt/strings.xml
@@ -0,0 +1,27 @@
+
+
+ Configurações do Galaxy Tab
+
+ Tela
+ Ajuste de Cor
+ Calibrar as cores da tela
+ Vermelho
+ Verde
+ Azul
+
+ Botões Touch
+ Tempo Limite da Iluminação
+ Ajuste o tempo para desligar a iluminação dos Botões Touch
+
+ Radio
+ HSPA
+ Ativar HSDPA/HSUPA
+
+ Saída de TV
+ Saída de TV
+ Cabo para Saída de TV não conectado
+ Cabo para Saída de TV conectado, ative para usar
+ Saída de TV ativada
+ Sistema de TV
+ Ajuste seu sistema de TV para a Saída de TV
+
diff --git a/P1Parts/res/values-ru/arrays.xml b/P1Parts/res/values-ru/arrays.xml
new file mode 100644
index 0000000..52766a1
--- /dev/null
+++ b/P1Parts/res/values-ru/arrays.xml
@@ -0,0 +1,19 @@
+
+
+ - По умолчанию (1.6 секунды)
+ - 0.5 секунды
+ - 2 секунды
+ - 5 секунд
+ - 10 секунд
+ - 15 секунд
+ - 30 секунд
+ - Никогда
+
+
+
+ - Только UMTS
+ - Только HSDPA
+ - HSDPA + HSUPA
+
+
+
diff --git a/P1Parts/res/values-ru/strings.xml b/P1Parts/res/values-ru/strings.xml
new file mode 100644
index 0000000..1a875f8
--- /dev/null
+++ b/P1Parts/res/values-ru/strings.xml
@@ -0,0 +1,19 @@
+
+
+ Настройки Galaxy Tab
+
+ Экран
+ Настройки цвета
+ Калибровка цвета экрана
+ Красный
+ Зелёный
+ Синий
+
+ Сенсорные кнопки
+ Таймаут подсветки
+ Как долго работает подсветка сенсорных кнопок
+
+ Радиомодуль
+ HSPA
+ Включить HSDPA/HSUPA
+
diff --git a/P1Parts/res/values-zh-rTW/arrays.xml b/P1Parts/res/values-zh-rTW/arrays.xml
new file mode 100644
index 0000000..da23e46
--- /dev/null
+++ b/P1Parts/res/values-zh-rTW/arrays.xml
@@ -0,0 +1,22 @@
+
+
+ - 預設(1.6秒)
+ - 0.5秒
+ - 2秒
+ - 5秒
+ - 10秒
+ - 15秒
+ - 30秒
+ - 永不
+
+
+
+
+
+ - 僅 UMTS
+ - 僅 HSDPA
+ - HSDPA+HSUPA
+
+
+
+
diff --git a/P1Parts/res/values-zh-rTW/strings.xml b/P1Parts/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..9d2fba7
--- /dev/null
+++ b/P1Parts/res/values-zh-rTW/strings.xml
@@ -0,0 +1,19 @@
+
+
+ Galaxy Tab 設定
+
+ 螢幕
+ 色彩調整
+ 校正螢幕色彩
+ 紅
+ 綠
+ 藍
+
+ 觸控鍵
+ 背光逾時
+ 調整觸控鍵背光自動關閉前的延遲時間
+
+ 行動網路
+ HSPA
+ 啟用 HSDPA/HSUPA
+
diff --git a/P1Parts/res/values/arrays.xml b/P1Parts/res/values/arrays.xml
new file mode 100644
index 0000000..5d32de2
--- /dev/null
+++ b/P1Parts/res/values/arrays.xml
@@ -0,0 +1,45 @@
+
+
+ - Default (1.6 seconds)
+ - 0.5 seconds
+ - 2 seconds
+ - 5 seconds
+ - 10 seconds
+ - 15 seconds
+ - 30 seconds
+ - Never
+
+
+
+ - 1600
+ - 500
+ - 2000
+ - 5000
+ - 10000
+ - 15000
+ - 30000
+ - -1
+
+
+
+ - UMTS Only
+ - HSDPA Only
+ - HSDPA + HSUPA
+
+
+
+ - 21
+ - 22
+ - 23
+
+
+
+ - NTSC
+ - PAL
+
+
+
+ - 1
+ - 2
+
+
diff --git a/P1Parts/res/values/strings.xml b/P1Parts/res/values/strings.xml
new file mode 100644
index 0000000..fa8e314
--- /dev/null
+++ b/P1Parts/res/values/strings.xml
@@ -0,0 +1,34 @@
+
+
+ Galaxy Tab Settings
+
+ Screen
+ Color Tuning
+ Calibrate screen color
+ Red
+ Green
+ Blue
+
+ Touch Keys
+ Backlight Timeout
+ Adjust the delay before the touch key backlight automatically turns off
+
+ Radio
+ HSPA
+ Enable HSDPA/HSUPA
+
+ TV Out
+ TV Out
+ TV Out cable not connected
+ TV Out cable connected, check to enable
+ TV Out enabled
+ TV System
+ Set your TV system for TV Out
+
+ View Credits
+ Credits
+ Loading Credits ...\u2026
+ Error loading Credits\u2026
+ Unknown
+ Version
+
diff --git a/P1Parts/res/xml/main.xml b/P1Parts/res/xml/main.xml
new file mode 100644
index 0000000..5214ae4
--- /dev/null
+++ b/P1Parts/res/xml/main.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/P1Parts/src/android/hardware/TvOut.java b/P1Parts/src/android/hardware/TvOut.java
new file mode 100644
index 0000000..6137c43
--- /dev/null
+++ b/P1Parts/src/android/hardware/TvOut.java
@@ -0,0 +1,79 @@
+package android.hardware;
+
+import java.lang.ref.WeakReference;
+
+import android.graphics.Bitmap;
+import android.util.Log;
+
+public class TvOut {
+ private static final String TAG = "TvOut";
+
+ private int mListenerContext;
+ private int mNativeContext;
+
+ public native void _DisableTvOut();
+
+ public native void _EnableTvOut();
+
+ public native void _SetOrientation(int paramInt);
+
+ public native void _SetTvScreenSize(int paramInt);
+
+ public native void _SetTvSystem(int paramInt);
+
+ public native void _TvOutResume(int paramInt);
+
+ public native void _TvOutSetImageString(String paramString);
+
+ public native void _TvOutSuspend(String paramString);
+ public native void _TvOutHdmiSuspend(String paramString);
+
+ public native boolean _TvoutSubtitleIsEnable();
+
+ public native boolean _TvoutSubtitlePostBitmap(Bitmap paramBitmap, int paramInt);
+
+ public native boolean _TvoutSubtitleSetStatus(int paramInt);
+
+ public native int _getSubtitleHDMIHeight();
+
+ public native int _getSubtitleHDMIWidth();
+
+ public native boolean _isEnabled();
+ public native boolean _isHdmiEnabled();
+
+ public native boolean _isSuspended();
+ public native boolean _isHdmiSuspended();
+
+ public native boolean _isTvoutCableConnected();
+ public native boolean _isHdmiCableConnected();
+
+ private final native void _native_setup(Object paramObject);
+
+ private final native void _release();
+
+ public native void _setTvoutCableConnected(int paramInt);
+ public native void _setHdmiCableConnected(int paramInt);
+
+ public native boolean _SetTvoutHdmiStatus(int paramInt);
+ public native boolean _isHdmiDualEnabled();
+ public native void _SetTvoutHdmiDualStatus(int paramInt);
+
+ static {
+ System.loadLibrary("tvout_jni");
+ }
+
+ public TvOut() {
+ _native_setup(new WeakReference(this));
+ }
+
+ public void finalize() {
+ _release();
+ }
+
+ private static void postEventFromNative(Object tvOutRef, int what, int arg1, int arg2, Object obj) {
+ TvOut tvOut = (TvOut)((WeakReference)tvOutRef).get();
+
+ Log.d(TAG, "Native Event: " + what + " " + arg1 + " " + arg2);
+ }
+
+}
diff --git a/P1Parts/src/com/cyanogenmod/P1Parts/ColorTuningPreference.java b/P1Parts/src/com/cyanogenmod/P1Parts/ColorTuningPreference.java
new file mode 100644
index 0000000..db063a8
--- /dev/null
+++ b/P1Parts/src/com/cyanogenmod/P1Parts/ColorTuningPreference.java
@@ -0,0 +1,173 @@
+package com.cyanogenmod.P1Parts;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.preference.DialogPreference;
+import android.preference.PreferenceManager;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+/**
+ * Special preference type that allows configuration of both the ring volume and
+ * notification volume.
+ */
+public class ColorTuningPreference extends DialogPreference {
+
+ enum Colors {
+ RED,
+ GREEN,
+ BLUE
+ };
+
+ private static final int[] SEEKBAR_ID = new int[] {
+ R.id.color_red_seekbar,
+ R.id.color_green_seekbar,
+ R.id.color_blue_seekbar
+ };
+
+ private static final int[] VALUE_DISPLAY_ID = new int[] {
+ R.id.color_red_value,
+ R.id.color_green_value,
+ R.id.color_blue_value
+ };
+
+ private static final String[] FILE_PATH = new String[] {
+ "/sys/devices/virtual/misc/color_tuning/red_multiplier",
+ "/sys/devices/virtual/misc/color_tuning/green_multiplier",
+ "/sys/devices/virtual/misc/color_tuning/blue_multiplier"
+ };
+
+ private ColorSeekBar mSeekBars[] = new ColorSeekBar[3];
+
+ private static final int MAX_VALUE = Integer.MAX_VALUE;
+
+ // Track instances to know when to restore original color
+ // (when the orientation changes, a new dialog is created before the old one is destroyed)
+ private static int sInstances = 0;
+
+ public ColorTuningPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ setDialogLayoutResource(R.layout.preference_dialog_color_tuning);
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ sInstances++;
+
+ for (int i = 0; i < SEEKBAR_ID.length; i++) {
+ SeekBar seekBar = (SeekBar) view.findViewById(SEEKBAR_ID[i]);
+ TextView valueDisplay = (TextView) view.findViewById(VALUE_DISPLAY_ID[i]);
+ mSeekBars[i] = new ColorSeekBar(seekBar, valueDisplay, FILE_PATH[i]);
+ }
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+
+ sInstances--;
+
+ if (positiveResult) {
+ for (ColorSeekBar csb : mSeekBars) {
+ csb.save();
+ }
+ } else if (sInstances == 0) {
+ for (ColorSeekBar csb : mSeekBars) {
+ csb.reset();
+ }
+ }
+ }
+
+ /**
+ * Restore screen color tuning from SharedPreferences. (Write to kernel.)
+ * @param context The context to read the SharedPreferences from
+ */
+ public static void restore(Context context) {
+ if (!isSupported()) {
+ return;
+ }
+
+ SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+ for (String filePath : FILE_PATH) {
+ int value = sharedPrefs.getInt(filePath, MAX_VALUE);
+ Utils.writeColor(filePath, value);
+ }
+ }
+
+ /**
+ * Check whether the running kernel supports color tuning or not.
+ * @return Whether color tuning is supported or not
+ */
+ public static boolean isSupported() {
+ boolean supported = true;
+ for (String filePath : FILE_PATH) {
+ if (!Utils.fileExists(filePath)) {
+ supported = false;
+ }
+ }
+
+ return supported;
+ }
+
+ class ColorSeekBar implements SeekBar.OnSeekBarChangeListener {
+
+ private String mFilePath;
+ private int mOriginal;
+ private SeekBar mSeekBar;
+ private TextView mValueDisplay;
+
+ public ColorSeekBar(SeekBar seekBar, TextView valueDisplay, String filePath) {
+ mSeekBar = seekBar;
+ mValueDisplay = valueDisplay;
+ mFilePath = filePath;
+
+ // Read original value
+ SharedPreferences sharedPreferences = getSharedPreferences();
+ mOriginal = sharedPreferences.getInt(mFilePath, MAX_VALUE);
+
+ seekBar.setMax(MAX_VALUE);
+ reset();
+ seekBar.setOnSeekBarChangeListener(this);
+ }
+
+ public void reset() {
+ mSeekBar.setProgress(mOriginal);
+ updateValue(mOriginal);
+ }
+
+ public void save() {
+ Editor editor = getEditor();
+ editor.putInt(mFilePath, mSeekBar.getProgress());
+ editor.commit();
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress,
+ boolean fromUser) {
+ Utils.writeColor(mFilePath, progress);
+ updateValue(progress);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Do nothing
+ }
+
+ private void updateValue(int progress) {
+ mValueDisplay.setText(String.format("%.3f", (double) progress / MAX_VALUE));
+ }
+
+ }
+
+}
diff --git a/P1Parts/src/com/cyanogenmod/P1Parts/Credits.java b/P1Parts/src/com/cyanogenmod/P1Parts/Credits.java
new file mode 100644
index 0000000..808cad6
--- /dev/null
+++ b/P1Parts/src/com/cyanogenmod/P1Parts/Credits.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.P1Parts;
+
+import com.cyanogenmod.P1Parts.R;
+
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Config;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.Toast;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.app.AlertController;
+
+public class Credits extends AlertActivity {
+
+ private static final String CREDITS_PATH = "/system/etc/Credits.html";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ InputStreamReader inputReader = null;
+ StringBuilder data = null;
+ try {
+ data = new StringBuilder(2048);
+ char tmp[] = new char[2048];
+ int numRead;
+ inputReader = new FileReader(CREDITS_PATH);
+ while ((numRead = inputReader.read(tmp)) >= 0) {
+ data.append(tmp, 0, numRead);
+ }
+ } catch (IOException e) {
+ showErrorAndFinish();
+ return;
+ } finally {
+ try {
+ if (inputReader != null) {
+ inputReader.close();
+ }
+ } catch (IOException e) {
+ }
+ }
+
+ if (TextUtils.isEmpty(data)) {
+ showErrorAndFinish();
+ return;
+ }
+
+ WebView webView = new WebView(this);
+
+ // Begin the loading. This will be done in a separate thread in WebView.
+ webView.loadDataWithBaseURL(null, data.toString(), "text/html", "utf-8", null);
+ webView.setWebViewClient(new WebViewClient() {
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ // Change from 'Loading...' to the real title
+ mAlert.setTitle(getString(R.string.credits_dialog));
+ }
+ });
+
+ final AlertController.AlertParams p = mAlertParams;
+ p.mTitle = getString(R.string.credits_loading);
+ p.mView = webView;
+ p.mForceInverseBackground = true;
+ setupAlert();
+ }
+
+ private void showErrorAndFinish() {
+ Toast.makeText(this, R.string.credits_error, Toast.LENGTH_LONG)
+ .show();
+ finish();
+ }
+
+}
diff --git a/P1Parts/src/com/cyanogenmod/P1Parts/Hspa.java b/P1Parts/src/com/cyanogenmod/P1Parts/Hspa.java
new file mode 100644
index 0000000..24c8cff
--- /dev/null
+++ b/P1Parts/src/com/cyanogenmod/P1Parts/Hspa.java
@@ -0,0 +1,48 @@
+package com.cyanogenmod.P1Parts;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceManager;
+
+public class Hspa implements OnPreferenceChangeListener {
+
+ private static final String APK_FILE = "/system/app/SamsungServiceMode.apk";
+ private Context mCtx;
+
+ public Hspa(Context context) {
+ mCtx = context;
+ }
+
+ public static boolean isSupported() {
+ return Utils.fileExists(APK_FILE);
+ }
+
+ /**
+ * Restore HSPA setting from SharedPreferences. (Write to kernel.)
+ * @param context The context to read the SharedPreferences from
+ */
+ public static void restore(Context context) {
+ if (!isSupported()) {
+ return;
+ }
+
+ SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+ sendIntent(context, sharedPrefs.getString(P1Parts.KEY_HSPA, "23"));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ sendIntent(mCtx, (String) newValue);
+ return true;
+ }
+
+ private static void sendIntent(Context context, String value) {
+ Intent i = new Intent("com.cyanogenmod.SamsungServiceMode.EXECUTE");
+ i.putExtra("sub_type", 20); // HSPA Setting
+ i.putExtra("data", value);
+ context.sendBroadcast(i);
+ }
+}
diff --git a/P1Parts/src/com/cyanogenmod/P1Parts/P1Parts.java b/P1Parts/src/com/cyanogenmod/P1Parts/P1Parts.java
new file mode 100644
index 0000000..594774c
--- /dev/null
+++ b/P1Parts/src/com/cyanogenmod/P1Parts/P1Parts.java
@@ -0,0 +1,118 @@
+package com.cyanogenmod.P1Parts;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.TvOut;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+
+public class P1Parts extends PreferenceActivity {
+
+ public static final String KEY_COLOR_TUNING = "color_tuning";
+ public static final String KEY_BACKLIGHT_TIMEOUT = "backlight_timeout";
+ public static final String KEY_HSPA = "hspa";
+ public static final String KEY_TVOUT_ENABLE = "tvout_enable";
+ public static final String KEY_TVOUT_SYSTEM = "tvout_system";
+
+ private ColorTuningPreference mColorTuning;
+ private ListPreference mBacklightTimeout;
+ private ListPreference mHspa;
+ private CheckBoxPreference mTvOutEnable;
+ private ListPreference mTvOutSystem;
+ private TvOut mTvOut;
+
+ private BroadcastReceiver mHeadsetReceiver = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int state = intent.getIntExtra("state", 0);
+ updateTvOutEnable(state != 0);
+ }
+
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.main);
+
+ mColorTuning = (ColorTuningPreference) findPreference(KEY_COLOR_TUNING);
+ mColorTuning.setEnabled(ColorTuningPreference.isSupported());
+
+ mBacklightTimeout = (ListPreference) findPreference(KEY_BACKLIGHT_TIMEOUT);
+ mBacklightTimeout.setEnabled(TouchKeyBacklightTimeout.isSupported());
+ mBacklightTimeout.setOnPreferenceChangeListener(new TouchKeyBacklightTimeout());
+
+ mHspa = (ListPreference) findPreference(KEY_HSPA);
+ mHspa.setEnabled(Hspa.isSupported());
+ mHspa.setOnPreferenceChangeListener(new Hspa(this));
+
+ mTvOut = new TvOut();
+ mTvOutEnable = (CheckBoxPreference) findPreference(KEY_TVOUT_ENABLE);
+ mTvOutEnable.setChecked(mTvOut._isEnabled());
+
+ mTvOutEnable.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enable = (Boolean) newValue;
+ Intent i = new Intent(P1Parts.this, TvOutService.class);
+ i.putExtra(TvOutService.EXTRA_COMMAND, enable ? TvOutService.COMMAND_ENABLE : TvOutService.COMMAND_DISABLE);
+ startService(i);
+ return true;
+ }
+
+ });
+
+ mTvOutSystem = (ListPreference) findPreference(KEY_TVOUT_SYSTEM);
+ mTvOutSystem.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (mTvOut._isEnabled()) {
+ int newSystem = Integer.valueOf((String) newValue);
+ Intent i = new Intent(P1Parts.this, TvOutService.class);
+ i.putExtra(TvOutService.EXTRA_COMMAND, TvOutService.COMMAND_CHANGE_SYSTEM);
+ i.putExtra(TvOutService.EXTRA_SYSTEM, newSystem);
+ startService(i);
+ }
+ return true;
+ }
+
+ });
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ registerReceiver(mHeadsetReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ unregisterReceiver(mHeadsetReceiver);
+ }
+
+ private void updateTvOutEnable(boolean connected) {
+ mTvOutEnable.setEnabled(connected);
+ mTvOutEnable.setSummaryOff(connected ? R.string.tvout_enable_summary : R.string.tvout_enable_summary_nocable);
+
+ if (!connected && mTvOutEnable.isChecked()) {
+ // Disable on unplug (UI)
+ mTvOutEnable.setChecked(false);
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ mTvOut.finalize();
+ super.onDestroy();
+ }
+
+}
diff --git a/P1Parts/src/com/cyanogenmod/P1Parts/Startup.java b/P1Parts/src/com/cyanogenmod/P1Parts/Startup.java
new file mode 100644
index 0000000..183c8f8
--- /dev/null
+++ b/P1Parts/src/com/cyanogenmod/P1Parts/Startup.java
@@ -0,0 +1,16 @@
+package com.cyanogenmod.P1Parts;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class Startup extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(final Context context, final Intent bootintent) {
+ ColorTuningPreference.restore(context);
+ TouchKeyBacklightTimeout.restore(context);
+ Hspa.restore(context);
+ }
+
+}
diff --git a/P1Parts/src/com/cyanogenmod/P1Parts/TouchKeyBacklightTimeout.java b/P1Parts/src/com/cyanogenmod/P1Parts/TouchKeyBacklightTimeout.java
new file mode 100644
index 0000000..32d6678
--- /dev/null
+++ b/P1Parts/src/com/cyanogenmod/P1Parts/TouchKeyBacklightTimeout.java
@@ -0,0 +1,36 @@
+package com.cyanogenmod.P1Parts;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceManager;
+
+public class TouchKeyBacklightTimeout implements OnPreferenceChangeListener {
+
+ private static final String FILE = "/sys/class/misc/notification/bl_timeout";
+
+ public static boolean isSupported() {
+ return Utils.fileExists(FILE);
+ }
+
+ /**
+ * Restore backlight timeout setting from SharedPreferences. (Write to kernel.)
+ * @param context The context to read the SharedPreferences from
+ */
+ public static void restore(Context context) {
+ if (!isSupported()) {
+ return;
+ }
+
+ SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+ Utils.writeValue(FILE, sharedPrefs.getString(P1Parts.KEY_BACKLIGHT_TIMEOUT, "1600"));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ Utils.writeValue(FILE, (String) newValue);
+ return true;
+ }
+
+}
diff --git a/P1Parts/src/com/cyanogenmod/P1Parts/TvOutService.java b/P1Parts/src/com/cyanogenmod/P1Parts/TvOutService.java
new file mode 100644
index 0000000..f59dc03
--- /dev/null
+++ b/P1Parts/src/com/cyanogenmod/P1Parts/TvOutService.java
@@ -0,0 +1,146 @@
+package com.cyanogenmod.P1Parts;
+
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.hardware.TvOut;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.preference.PreferenceManager;
+import android.view.Display;
+import android.view.IRotationWatcher;
+import android.view.IWindowManager;
+import android.view.WindowManager;
+
+public class TvOutService extends Service {
+
+ public static final String EXTRA_COMMAND = "command";
+ public static final String EXTRA_SYSTEM = "system";
+ public static final String COMMAND_ENABLE = "enable";
+ public static final String COMMAND_DISABLE = "disable";
+ public static final String COMMAND_CHANGE_SYSTEM = "system";
+
+ private TvOut mTvOut;
+ private SharedPreferences mPref;
+ private int mSystem;
+ private boolean mWasOn = false; // For enabling on screen on
+
+ private BroadcastReceiver mReceiver = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_HEADSET_PLUG.equals(action)) {
+ int state = intent.getIntExtra("state", 0);
+ if (state == 0 && mTvOut._isEnabled()) {
+ // Disable when cable is unplugged
+ mWasOn = false;
+ disable();
+ stopSelf();
+ }
+ }
+ else if (Intent.ACTION_SCREEN_ON.equals(action)) {
+ if (mWasOn) {
+ SystemProperties.set("ctl.start", "tvouthack");
+ mWasOn = false;
+ }
+ }
+ else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+ if (mTvOut._isEnabled()) {
+ mWasOn = true;
+ SystemProperties.set("ctl.stop", "tvouthack");
+ }
+ }
+ }
+
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public void onCreate() {
+ mTvOut = new TvOut();
+ mPref = PreferenceManager.getDefaultSharedPreferences(this);
+
+ IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
+ try {
+ wm.watchRotation(new IRotationWatcher.Stub() {
+ @Override
+ public void onRotationChanged(int rotation) {
+ TvOutService.this.onRotationChanged(rotation);
+ }
+ });
+ }
+ catch (RemoteException e) { }
+
+ IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ registerReceiver(mReceiver, filter);
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (intent != null) {
+ String command = intent.getStringExtra("command");
+ if (COMMAND_ENABLE.equals(command)) {
+ mSystem = Integer.parseInt(mPref.getString(P1Parts.KEY_TVOUT_SYSTEM, "2")); // Default = PAL
+ enable();
+ }
+ else if (COMMAND_DISABLE.equals(command)) {
+ disable();
+ stopSelf();
+ }
+ else if (COMMAND_CHANGE_SYSTEM.equals(command)) {
+ if (mTvOut._isEnabled()) {
+ mSystem = intent.getIntExtra(EXTRA_SYSTEM, 2);
+ disable();
+ enable();
+ }
+ }
+ }
+
+ return START_STICKY;
+ }
+
+ @Override
+ public void onDestroy() {
+ unregisterReceiver(mReceiver);
+ mTvOut.finalize();
+ super.onDestroy();
+ }
+
+ public void onRotationChanged(int rotation) {
+ mTvOut._SetOrientation(rotation);
+ }
+
+ private void enable() {
+ mTvOut._SetTvSystem(mSystem);
+ mTvOut._TvOutSetImageString("TV-out not supported while application running. Phone display only");
+
+ Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+ mTvOut._SetOrientation(display.getRotation());
+
+ mTvOut._EnableTvOut();
+ mTvOut._setTvoutCableConnected(1);
+
+ // Start tvouthack service used to bombard screen refresh messages
+ SystemProperties.set("ctl.start", "tvouthack");
+ }
+
+ private void disable() {
+ SystemProperties.set("ctl.stop", "tvouthack");
+
+ mTvOut._DisableTvOut();
+ mTvOut._setTvoutCableConnected(0);
+ }
+
+}
diff --git a/P1Parts/src/com/cyanogenmod/P1Parts/Utils.java b/P1Parts/src/com/cyanogenmod/P1Parts/Utils.java
new file mode 100644
index 0000000..110d41d
--- /dev/null
+++ b/P1Parts/src/com/cyanogenmod/P1Parts/Utils.java
@@ -0,0 +1,47 @@
+package com.cyanogenmod.P1Parts;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class Utils {
+
+ /**
+ * Write a string value to the specified file.
+ * @param filename The filename
+ * @param value The value
+ */
+ public static void writeValue(String filename, String value) {
+ try {
+ FileOutputStream fos = new FileOutputStream(new File(filename));
+ fos.write(value.getBytes());
+ fos.flush();
+ fos.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Write the "color value" to the specified file. The value is scaled from
+ * an integer to an unsigned integer by multiplying by 2.
+ * @param filename The filename
+ * @param value The value of max value Integer.MAX
+ */
+ public static void writeColor(String filename, int value) {
+ writeValue(filename, String.valueOf((long) value * 2));
+ }
+
+ /**
+ * Check if the specified file exists.
+ * @param filename The filename
+ * @return Whether the file exists or not
+ */
+ public static boolean fileExists(String filename) {
+ return new File(filename).exists();
+ }
+
+}
diff --git a/bdaddr_read/Android.mk b/bdaddr_read/Android.mk
new file mode 100644
index 0000000..46f95cd
--- /dev/null
+++ b/bdaddr_read/Android.mk
@@ -0,0 +1,28 @@
+# Copyright (C) 2010 Ricardo Cerqueira
+# Copyright (C) 2011 Pawit Pornkitprasan
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := bdaddr_read.c
+
+LOCAL_SHARED_LIBRARIES := libcutils
+
+LOCAL_MODULE := bdaddr_read
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/bdaddr_read/bdaddr_read.c b/bdaddr_read/bdaddr_read.c
new file mode 100644
index 0000000..c6e08c9
--- /dev/null
+++ b/bdaddr_read/bdaddr_read.c
@@ -0,0 +1,54 @@
+#include
+#include
+#include
+#include
+
+#define LOG_TAG "bdaddr"
+#define SAMSUNG_BDADDR_PATH "/efs/imei/bt.txt"
+#define BDADDR_PATH "/data/bdaddr"
+
+/* Read bluetooth MAC from SAMSUNG_BDADDR_PATH (different format),
+ * write it to BDADDR_PATH, and set ro.bt.bdaddr_path to BDADDR_PATH
+ *
+ * Adapted from bdaddr_read.c of thunderg
+ */
+
+int main() {
+ char tmpbdaddr[23]; // bt_macaddr:xxxxxxxxxxxx
+ char bdaddr[18];
+ int count;
+ int fd;
+
+ fd = open(SAMSUNG_BDADDR_PATH, O_RDONLY);
+ if(fd < 0) {
+ fprintf(stderr, "open(%s) failed\n", SAMSUNG_BDADDR_PATH);
+ LOGE("Can't open %s\n", SAMSUNG_BDADDR_PATH);
+ return -1;
+ }
+
+ count = read(fd, tmpbdaddr, sizeof(tmpbdaddr));
+ if (count < 0) {
+ fprintf(stderr, "read(%s) failed\n", SAMSUNG_BDADDR_PATH);
+ LOGE("Can't read %s\n", SAMSUNG_BDADDR_PATH);
+ return -1;
+ }
+ else if (count != sizeof(tmpbdaddr)) {
+ fprintf(stderr, "read(%s) unexpected size %d\n", SAMSUNG_BDADDR_PATH, count);
+ LOGE("Error reading %s (unexpected size %d)\n", SAMSUNG_BDADDR_PATH, count);
+ return -1;
+ }
+
+ count = sprintf(bdaddr, "%2.2s:%2.2s:%2.2s:%2.2s:%2.2s:%2.2s\0",
+ tmpbdaddr+11,tmpbdaddr+13,tmpbdaddr+15,tmpbdaddr+17,tmpbdaddr+19,tmpbdaddr+21);
+
+ fd = open(BDADDR_PATH, O_WRONLY|O_CREAT|O_TRUNC, 00600|00060|00006);
+ if (fd < 0) {
+ fprintf(stderr, "open(%s) failed\n", BDADDR_PATH);
+ LOGE("Can't open %s\n", BDADDR_PATH);
+ return -2;
+ }
+ write(fd, bdaddr, 18);
+ close(fd);
+ property_set("ro.bt.bdaddr_path", BDADDR_PATH);
+ return 0;
+}
diff --git a/bml_over_mtd.sh b/bml_over_mtd.sh
new file mode 100644
index 0000000..be73e15
--- /dev/null
+++ b/bml_over_mtd.sh
@@ -0,0 +1,44 @@
+#!/sbin/busybox sh
+#
+# bml_over_mtd.sh
+# Take care of bad blocks while flashing kernel image to boot partition
+#
+
+PARTITION=$1
+PARTITION_START_BLOCK=$2
+RESERVOIRPARTITION=$3
+RESERVOIR_START_BLOCK=$4
+IMAGE=$5
+
+# remove old log
+rm -rf /sdcard/bml_over_mtd.log
+
+# everything is logged into /sdcard/bml_over_mtd.log
+exec >> /sdcard/bml_over_mtd.log 2>&1
+
+set -x
+export PATH=/:/sbin:/system/xbin:/system/bin:$PATH
+
+busybox cat < ../../../vendor/samsung/galaxytab7c/galaxytab7c-vendor-blobs.mk
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Prebuilt libraries that are needed to build open-source libraries
+PRODUCT_COPY_FILES := \\
+ vendor/samsung/galaxytab7c/proprietary/libril.so:obj/lib/libril.so \\
+ vendor/samsung/galaxytab7c/proprietary/libsecril-client.so:obj/lib/libsecril-client.so
+
+# radio
+PRODUCT_COPY_FILES += \\
+ vendor/samsung/galaxytab7c/proprietary/libril.so:system/lib/libril.so \\
+ vendor/samsung/galaxytab7c/proprietary/libsecril-client.so:system/lib/libsecril-client.so \\
+ vendor/samsung/galaxytab7c/proprietary/libsec-ril40.so:system/lib/libsec-ril40.so \\
+ vendor/samsung/galaxytab7c/proprietary/rild:system/bin/rild \\
+ vendor/samsung/galaxytab7c/proprietary/pppd_runner:system/bin/pppd_runner
+
+# gps
+PRODUCT_COPY_FILES += \\
+ vendor/samsung/galaxytab7c/proprietary/gps.s5pc110.so:system/lib/hw/gps.s5pc110.so \\
+ vendor/samsung/galaxytab7c/proprietary/gpsd:system/vendor/bin/gpsd \\
+ vendor/samsung/galaxytab7c/proprietary/gps.conf:system/etc/gps.conf
+
+# sensors
+PRODUCT_COPY_FILES += \\
+ vendor/samsung/galaxytab7c/proprietary/libakm.so:system/lib/libakm.so \\
+ vendor/samsung/galaxytab7c/proprietary/sensors.s5pc110.so:system/lib/hw/sensors.s5pc110.so
+
+# gfx
+PRODUCT_COPY_FILES += \\
+ vendor/samsung/galaxytab7c/proprietary/pvrsrvinit:system/bin/pvrsrvinit \\
+ vendor/samsung/galaxytab7c/proprietary/libGLES_android.so:system/lib/egl/libGLES_android.so \\
+ vendor/samsung/galaxytab7c/proprietary/libEGL_POWERVR_SGX540_120.so:system/vendor/lib/egl/libEGL_POWERVR_SGX540_120.so \\
+ vendor/samsung/galaxytab7c/proprietary/libGLESv1_CM_POWERVR_SGX540_120.so:system/vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so \\
+ vendor/samsung/galaxytab7c/proprietary/libGLESv2_POWERVR_SGX540_120.so:system/vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so \\
+ vendor/samsung/galaxytab7c/proprietary/gralloc.s5pc110.so:system/vendor/lib/hw/gralloc.s5pc110.so \\
+ vendor/samsung/galaxytab7c/proprietary/libglslcompiler.so:system/vendor/lib/libglslcompiler.so \\
+ vendor/samsung/galaxytab7c/proprietary/libIMGegl.so:system/vendor/lib/libIMGegl.so \\
+ vendor/samsung/galaxytab7c/proprietary/libpvr2d.so:system/vendor/lib/libpvr2d.so \\
+ vendor/samsung/galaxytab7c/proprietary/libpvrANDROID_WSEGL.so:system/vendor/lib/libpvrANDROID_WSEGL.so \\
+ vendor/samsung/galaxytab7c/proprietary/libPVRScopeServices.so:system/vendor/lib/libPVRScopeServices.so \\
+ vendor/samsung/galaxytab7c/proprietary/libsrv_init.so:system/vendor/lib/libsrv_init.so \\
+ vendor/samsung/galaxytab7c/proprietary/libsrv_um.so:system/vendor/lib/libsrv_um.so \\
+ vendor/samsung/galaxytab7c/proprietary/libusc.so:system/vendor/lib/libusc.so
+
+# wifi
+PRODUCT_COPY_FILES += \\
+ vendor/samsung/galaxytab7c/proprietary/nvram_net.txt:system/etc/wifi/nvram_net.txt \\
+ vendor/samsung/galaxytab7c/proprietary/nvram_mfg.txt:system/etc/wifi/nvram_mfg.txt \\
+ vendor/samsung/galaxytab7c/proprietary/bcm4329_aps.bin:system/etc/wifi/bcm4329_aps.bin \\
+ vendor/samsung/galaxytab7c/proprietary/bcm4329_mfg.bin:system/etc/wifi/bcm4329_mfg.bin \\
+ vendor/samsung/galaxytab7c/proprietary/bcm4329_sta.bin:system/etc/wifi/bcm4329_sta.bin
+
+# low power mode
+PRODUCT_COPY_FILES += \\
+ vendor/samsung/galaxytab7c/proprietary/charging_mode:system/bin/charging_mode \\
+ vendor/samsung/galaxytab7c/proprietary/playlpm:system/bin/playlpm \\
+ vendor/samsung/galaxytab7c/proprietary/libQmageDecoder.so:system/lib/libQmageDecoder.so \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_10.qmg:system/media/battery_charging_10.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_100.qmg:system/media/battery_charging_100.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_15.qmg:system/media/battery_charging_15.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_20.qmg:system/media/battery_charging_20.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_25.qmg:system/media/battery_charging_25.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_30.qmg:system/media/battery_charging_30.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_35.qmg:system/media/battery_charging_35.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_40.qmg:system/media/battery_charging_40.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_45.qmg:system/media/battery_charging_45.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_5.qmg:system/media/battery_charging_5.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_50.qmg:system/media/battery_charging_50.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_55.qmg:system/media/battery_charging_55.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_60.qmg:system/media/battery_charging_60.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_65.qmg:system/media/battery_charging_65.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_70.qmg:system/media/battery_charging_70.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_75.qmg:system/media/battery_charging_75.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_80.qmg:system/media/battery_charging_80.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_85.qmg:system/media/battery_charging_85.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_90.qmg:system/media/battery_charging_90.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/battery_charging_95.qmg:system/media/battery_charging_95.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/chargingwarning_disconnected.qmg:system/media/chargingwarning_disconnected.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/chargingwarning_temp.qmg:system/media/chargingwarning_temp.qmg \\
+ vendor/samsung/galaxytab7c/proprietary/usb_not_charging.qmg:system/media/usb_not_charging.qmg
+
+# bluetooth
+PRODUCT_COPY_FILES += \\
+ vendor/samsung/galaxytab7c/proprietary/BCM4329B1_002.002.023.0534.0571.hcd:system/bin/BCM4329B1_002.002.023.0534.0571.hcd
+
+EOF
+
+
+./setup-makefiles.sh
diff --git a/include/hal_public.h b/include/hal_public.h
new file mode 100644
index 0000000..60f33a9
--- /dev/null
+++ b/include/hal_public.h
@@ -0,0 +1,171 @@
+/* Copyright (c) Imagination Technologies Ltd.
+ *
+ * The contents of this file are subject to the MIT license as set out below.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HAL_PUBLIC_H
+#define HAL_PUBLIC_H
+
+/* Authors of third party hardware composer (HWC) modules will need to include
+ * this header to access functionality in the gralloc and framebuffer HALs.
+ */
+
+#include
+
+#define ALIGN(x,a) (((x) + (a) - 1L) & ~((a) - 1L))
+#define HW_ALIGN 32
+
+/* This can be tuned down as appropriate for the SOC.
+ *
+ * IMG formats are usually a single sub-alloc.
+ * Some OEM video formats are two sub-allocs (Y, UV planes).
+ * Future OEM video formats might be three sub-allocs (Y, U, V planes).
+ */
+#define MAX_SUB_ALLOCS 3
+
+typedef struct
+{
+ native_handle_t base;
+
+ /* These fields can be sent cross process. They are also valid
+ * to duplicate within the same process.
+ *
+ * A table is stored within psPrivateData on gralloc_module_t (this
+ * is obviously per-process) which maps stamps to a mapped
+ * PVRSRV_CLIENT_MEM_INFO in that process. Each map entry has a lock
+ * count associated with it, satisfying the requirements of the
+ * Android API. This also prevents us from leaking maps/allocations.
+ *
+ * This table has entries inserted either by alloc()
+ * (alloc_device_t) or map() (gralloc_module_t). Entries are removed
+ * by free() (alloc_device_t) and unmap() (gralloc_module_t).
+ *
+ * As a special case for framebuffer_device_t, framebuffer_open()
+ * will add and framebuffer_close() will remove from this table.
+ */
+
+#define IMG_NATIVE_HANDLE_NUMFDS MAX_SUB_ALLOCS
+ /* The `fd' field is used to "export" a meminfo to another process.
+ * Therefore, it is allocated by alloc_device_t, and consumed by
+ * gralloc_module_t. The framebuffer_device_t does not need a handle,
+ * and the special value IMG_FRAMEBUFFER_FD is used instead.
+ */
+ int fd[MAX_SUB_ALLOCS];
+
+#define IMG_NATIVE_HANDLE_NUMINTS ((sizeof(unsigned long long) / sizeof(int)) + 5)
+ /* A KERNEL unique identifier for any exported kernel meminfo. Each
+ * exported kernel meminfo will have a unique stamp, but note that in
+ * userspace, several meminfos across multiple processes could have
+ * the same stamp. As the native_handle can be dup(2)'d, there could be
+ * multiple handles with the same stamp but different file descriptors.
+ */
+ unsigned long long ui64Stamp;
+
+ /* This is used for buffer usage validation when locking a buffer,
+ * and also in WSEGL (for the composition bypass feature).
+ */
+ int usage;
+
+ //int dummy;
+ /* In order to do efficient cache flushes we need the buffer dimensions
+ * and format. These are available on the ANativeWindowBuffer,
+ * but the platform doesn't pass them down to the graphics HAL.
+ *
+ * These fields are also used in the composition bypass. In this
+ * capacity, these are the "real" values for the backing allocation.
+ */
+ int iWidth;
+ int iHeight;
+ int iFormat;
+ unsigned int uiBpp;
+}
+__attribute__((aligned(sizeof(int)),packed)) IMG_native_handle_t;
+
+typedef struct
+{
+ framebuffer_device_t base;
+
+ /* The HWC was loaded. post() is no longer responsible for presents */
+ int bBypassPost;
+
+ /* Custom-blit components in lieu of overlay hardware */
+ int (*Blit)(framebuffer_device_t *device, buffer_handle_t src,
+ buffer_handle_t dest, int w, int h, int x, int y);
+
+ /* HWC path for present posts */
+ int (*Post2)(framebuffer_device_t *fb, buffer_handle_t *buffers,
+ int num_buffers, void *data, int data_length);
+}
+IMG_framebuffer_device_public_t;
+
+typedef struct IMG_gralloc_module_public_t
+{
+ gralloc_module_t base;
+
+ /* If the framebuffer has been opened, this will point to the
+ * framebuffer device data required by the allocator, WSEGL
+ * modules and composerhal.
+ */
+ IMG_framebuffer_device_public_t *psFrameBufferDevice;
+
+ int (*GetPhyAddrs)(struct IMG_gralloc_module_public_t const* module,
+ buffer_handle_t handle,
+ unsigned int auiPhyAddr[MAX_SUB_ALLOCS]);
+ /* Custom-blit components in lieu of overlay hardware */
+ int (*Blit)(struct IMG_gralloc_module_public_t const *module,
+ buffer_handle_t src,
+ void *dest[MAX_SUB_ALLOCS], int format);
+
+ int (*Blit2)(struct IMG_gralloc_module_public_t const *module,
+ buffer_handle_t src, buffer_handle_t dest,
+ int w, int h, int x, int y);
+}
+IMG_gralloc_module_public_t;
+
+typedef struct
+{
+ int l, t, w, h;
+}
+IMG_write_lock_rect_t;
+
+typedef struct IMG_buffer_format_public_t
+{
+ /* Buffer formats are returned as a linked list */
+ struct IMG_buffer_format_public_t *psNext;
+
+ /* HAL_PIXEL_FORMAT_... enumerant */
+ int iHalPixelFormat;
+
+ /* WSEGL_PIXELFORMAT_... enumerant */
+ int iWSEGLPixelFormat;
+
+ /* Friendly name for format */
+ const char *const szName;
+
+ /* Bits (not bytes) per pixel */
+ unsigned int uiBpp;
+
+ /* GPU output format (creates EGLConfig for format) */
+ int bGPURenderable;
+}
+IMG_buffer_format_public_t;
+
+#endif /* HAL_PUBLIC_H */
diff --git a/include/s3c_bc.h b/include/s3c_bc.h
new file mode 100755
index 0000000..e8ea490
--- /dev/null
+++ b/include/s3c_bc.h
@@ -0,0 +1,63 @@
+/*!****************************************************************************
+@File s3c_bc.h
+
+@Title s3c_bc kernel driver parameters
+
+@Author Imagination Technologies
+ Samsung Electronics Co. LTD
+
+@Date 03/03/2010
+
+@Copyright Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+@Platform Generic
+
+@Description s3c_bc kernel driver parameters
+
+@DoxygenVer
+
+******************************************************************************/
+
+/******************************************************************************
+Modifications :-
+$Log: s3c_bc.h $
+******************************************************************************/
+#ifndef __S3C_BC_H__
+#define __S3C_BC_H__
+
+#include
+
+#define S3C_BC_DEVICE_NAME "s3c_bc"
+
+#define S3C_BC_DEVICE_ID 0
+#define S3C_BC_DEVICE_BUFFER_COUNT 4 /* TODO: Modify this accordingly. */
+
+#define S3C_BC_DEVICE_PHYS_PAGE_SIZE 0x1000 /* 4KB */
+
+typedef struct S3C_BC_ioctl_package_TAG
+{
+ int inputparam;
+ int outputparam;
+} S3C_BC_ioctl_package, *PS3C_BC_ioctl_package;
+
+/*!< Nov 2006: according to ioctl-number.txt 'g' wasn't in use. */
+#define S3C_BC_IOC_GID 'g'
+
+#define S3C_BC_IOWR(INDEX) _IOWR(S3C_BC_IOC_GID, INDEX, S3C_BC_ioctl_package)
+
+#define S3C_BC_ioctl_get_physical_base_address S3C_BC_IOWR(0)
+
+#endif /* __S3C_BC__H__ */
+/******************************************************************************
+ End of file (s3c_bc.h)
+******************************************************************************/
diff --git a/include/s3c_mem.h b/include/s3c_mem.h
new file mode 100755
index 0000000..d51398a
--- /dev/null
+++ b/include/s3c_mem.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _S3C_MEM_COMMON_H_
+#define _S3C_MEM_COMMON_H_
+
+#define MEM_IOCTL_MAGIC 'M'
+
+#define S3C_MEM_ALLOC _IOWR(MEM_IOCTL_MAGIC, 310, struct s3c_mem_alloc)
+#define S3C_MEM_FREE _IOWR(MEM_IOCTL_MAGIC, 311, struct s3c_mem_alloc)
+
+#define S3C_MEM_SHARE_ALLOC _IOWR(MEM_IOCTL_MAGIC, 314, struct s3c_mem_alloc)
+#define S3C_MEM_SHARE_FREE _IOWR(MEM_IOCTL_MAGIC, 315, struct s3c_mem_alloc)
+
+#define S3C_MEM_CACHEABLE_ALLOC _IOWR(MEM_IOCTL_MAGIC, 316, struct s3c_mem_alloc)
+#define S3C_MEM_CACHEABLE_SHARE_ALLOC _IOWR(MEM_IOCTL_MAGIC, 317, struct s3c_mem_alloc)
+
+#define S3C_MEM_DMA_COPY _IOWR(MEM_IOCTL_MAGIC, 318, struct s3c_mem_dma_param)
+#define S3C_MEM_DMA_SET _IOWR(MEM_IOCTL_MAGIC, 319, struct s3c_mem_dma_param)
+
+#define S3C_MEM_CACHE_INV _IOWR(MEM_IOCTL_MAGIC, 330, struct s3c_mem_dma_param)
+
+
+struct s3c_mem_alloc {
+ int size;
+ unsigned int vir_addr;
+ unsigned int phy_addr;
+};
+
+struct s3c_mem_dma_param {
+ int size;
+ unsigned int src_addr;
+ unsigned int dst_addr;
+ int cfg;
+};
+
+#if 0
+typedef struct _s3c_mem_t{
+ int dev_fd;
+ struct s3c_mem_alloc mem_alloc_info;
+}s3c_mem_t;
+#endif
+#endif // _S3C_MEM_COMMON_H_
diff --git a/include/s5p_fimc.h b/include/s5p_fimc.h
new file mode 100755
index 0000000..d2c760c
--- /dev/null
+++ b/include/s5p_fimc.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#ifndef _S5P_FIMC_H_
+#define _S5P_FIMC_H_
+
+#include
+
+/*
+ * G E N E R A L S
+ *
+*/
+#define MIN(x, y) ((x < y) ? x : y)
+
+/*
+ * P I X E L F O R M A T G U I D E
+ *
+ * The 'x' means 'DO NOT CARE'
+ * The '*' means 'FIMC SPECIFIC'
+ * For some fimc formats, we couldn't find equivalent format in the V4L2 FOURCC.
+ *
+ * FIMC TYPE PLANES ORDER V4L2_PIX_FMT
+ * ---------------------------------------------------------
+ * RGB565 x x V4L2_PIX_FMT_RGB565
+ * RGB888 x x V4L2_PIX_FMT_RGB24
+ * YUV420 2 LSB_CBCR V4L2_PIX_FMT_NV12
+ * YUV420 2 LSB_CRCB V4L2_PIX_FMT_NV21
+ * YUV420 2 MSB_CBCR V4L2_PIX_FMT_NV21X*
+ * YUV420 2 MSB_CRCB V4L2_PIX_FMT_NV12X*
+ * YUV420 3 x V4L2_PIX_FMT_YUV420
+ * YUV422 1 YCBYCR V4L2_PIX_FMT_YUYV
+ * YUV422 1 YCRYCB V4L2_PIX_FMT_YVYU
+ * YUV422 1 CBYCRY V4L2_PIX_FMT_UYVY
+ * YUV422 1 CRYCBY V4L2_PIX_FMT_VYUY*
+ * YUV422 2 LSB_CBCR V4L2_PIX_FMT_NV16*
+ * YUV422 2 LSB_CRCB V4L2_PIX_FMT_NV61*
+ * YUV422 2 MSB_CBCR V4L2_PIX_FMT_NV16X*
+ * YUV422 2 MSB_CRCB V4L2_PIX_FMT_NV61X*
+ * YUV422 3 x V4L2_PIX_FMT_YUV422P
+ *
+*/
+
+/*
+ * V 4 L 2 F I M C E X T E N S I O N S
+ *
+*/
+#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U')
+
+/* FOURCC for FIMC specific */
+#define V4L2_PIX_FMT_NV12X v4l2_fourcc('N', '1', '2', 'X')
+#define V4L2_PIX_FMT_NV21X v4l2_fourcc('N', '2', '1', 'X')
+#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y')
+#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6')
+#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1')
+#define V4L2_PIX_FMT_NV16X v4l2_fourcc('N', '1', '6', 'X')
+#define V4L2_PIX_FMT_NV61X v4l2_fourcc('N', '6', '1', 'X')
+
+#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */
+
+/* CID extensions */
+#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_RESERVED_MEM_BASE_ADDR (V4L2_CID_PRIVATE_BASE + 20)
+#define V4L2_CID_FIMC_VERSION (V4L2_CID_PRIVATE_BASE + 21)
+/*
+ * U S E R D E F I N E D T Y P E S
+ *
+*/
+
+typedef unsigned int dma_addr_t;
+
+struct fimc_buf {
+ dma_addr_t base[3];
+ size_t length[3];
+};
+
+struct fimc_buffer {
+ void *virt_addr;
+ void *phys_addr;
+ size_t length;
+};
+
+struct yuv_fmt_list {
+ const char *name;
+ const char *desc;
+ unsigned int fmt;
+ int bpp;
+ int planes;
+};
+
+struct img_offset {
+ int y_h;
+ int y_v;
+ int cb_h;
+ int cb_v;
+ int cr_h;
+ int cr_v;
+};
+
+//------------ STRUCT ---------------------------------------------------------//
+
+typedef struct
+{
+ unsigned int full_width; // Source Image Full Width (Virtual screen size)
+ unsigned int full_height; // Source Image Full Height (Virtual screen size)
+ unsigned int start_x; // Source Image Start width offset
+ unsigned int start_y; // Source Image Start height offset
+ unsigned int width; // Source Image Width
+ unsigned int height; // Source Image Height
+ unsigned int buf_addr_phy_rgb_y; // Base Address of the Source Image (RGB or Y): Physical Address
+ unsigned int buf_addr_phy_cb; // Base Address of the Source Image (CB Component) : Physical Address
+ unsigned int buf_addr_phy_cr; // Base Address of the Source Image (CR Component) : Physical Address
+ unsigned int color_space; // Color Space of the Source Image
+} s5p_fimc_img_info;
+
+typedef struct
+{
+ s5p_fimc_img_info src;
+ s5p_fimc_img_info dst;
+} s5p_fimc_params_t;
+
+typedef struct _s5p_fimc_t {
+ int dev_fd;
+ struct fimc_buffer out_buf;
+
+ s5p_fimc_params_t params;
+
+ int use_ext_out_mem;
+ unsigned int hw_ver;
+}s5p_fimc_t;
+
+//------------------------ functions for v4l2 ------------------------------//
+int fimc_v4l2_set_src(int fd, unsigned int hw_ver, s5p_fimc_img_info *src);
+int fimc_v4l2_set_dst(int fd, s5p_fimc_img_info *dst, int rotation, unsigned int addr);
+int fimc_v4l2_stream_on(int fd, enum v4l2_buf_type type);
+int fimc_v4l2_queue(int fd, struct fimc_buf *fimc_buf);
+int fimc_v4l2_dequeue(int fd);
+int fimc_v4l2_stream_off(int fd);
+int fimc_v4l2_clr_buf(int fd);
+int fimc_handle_oneshot(int fd, struct fimc_buf *fimc_buf);
+#endif
diff --git a/include/sec_format.h b/include/sec_format.h
new file mode 100755
index 0000000..99a47bf
--- /dev/null
+++ b/include/sec_format.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#ifndef _SEC_FORMAT_H_
+#define _SEC_FORMAT_H_
+
+/* enum related to pixel format */
+
+enum {
+ HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x100,
+ HAL_PIXEL_FORMAT_YCbCr_420_P = 0x101,
+ HAL_PIXEL_FORMAT_YCbCr_420_I = 0x102,
+ HAL_PIXEL_FORMAT_CbYCrY_422_I = 0x103,
+ HAL_PIXEL_FORMAT_CbYCrY_420_I = 0x104,
+ HAL_PIXEL_FORMAT_YCbCr_422_P = 0x105,
+ HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x106,
+ // support custom format for zero copy
+ HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP = 0x110,
+ HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP = 0x111,
+ HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED = 0x112,
+ HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP = 0x113,
+ HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP = 0x114,
+ HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I = 0x115,
+ HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I = 0x116,
+ HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I = 0x117,
+ HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I = 0x118,
+ HAL_PIXEL_FORMAT_CUSTOM_MAX
+};
+
+#endif
diff --git a/include/sec_lcd.h b/include/sec_lcd.h
new file mode 100755
index 0000000..b5451b7
--- /dev/null
+++ b/include/sec_lcd.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _SEC_FB_LCD_
+#define _SEC_FB_LCD_
+
+/*
+ * S T R U C T U R E S F O R C U S T O M I O C T L S
+ *
+*/
+struct secfb_user_window {
+ int x;
+ int y;
+};
+
+/*
+ * C U S T O M I O C T L S
+ *
+*/
+
+#define FBIO_WAITFORVSYNC _IO ('F', 32)
+#define SECFB_WIN_POSITION _IOW ('F', 203, struct secfb_user_window)
+
+
+#define DEFAULT_LCD_WIDTH (480)
+#define DEFAULT_LCD_HEIGHT (800)
+#define DEFAULT_LCD_BPP (32)
+
+/***************** LCD frame buffer *****************/
+#define FB0_NAME "/dev/fb0"
+#define FB1_NAME "/dev/fb1"
+#define FB2_NAME "/dev/fb2"
+#define FB3_NAME "/dev/fb3"
+#define FB4_NAME "/dev/fb4"
+
+#endif
diff --git a/include/sec_utils.h b/include/sec_utils.h
new file mode 100644
index 0000000..80b4493
--- /dev/null
+++ b/include/sec_utils.h
@@ -0,0 +1,331 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#ifndef __SAMSUNG_SYSLSI_SEC_COMMON_H__
+#define __SAMSUNG_SYSLSI_SEC_COMMON_H__
+
+//---------------------------------------------------------//
+// Include
+//---------------------------------------------------------//
+
+#include
+#include "sec_format.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+
+#ifdef __cplusplus
+}
+#endif
+
+//---------------------------------------------------------//
+// Common structure //
+//---------------------------------------------------------//
+struct ADDRS {
+ unsigned int addr_y;
+ unsigned int addr_cbcr;
+ unsigned int buf_idx;
+ unsigned int reserved;
+};
+
+//---------------------------------------------------------//
+// Common function //
+//---------------------------------------------------------//
+inline int HAL_PIXEL_FORMAT_2_V4L2_PIX(int HAL_PIXEL_FORMAT)
+{
+ int V4L2_PIX = -1;
+
+ switch (HAL_PIXEL_FORMAT) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ V4L2_PIX = V4L2_PIX_FMT_RGB32;
+ break;
+
+ case HAL_PIXEL_FORMAT_RGB_888:
+ V4L2_PIX = V4L2_PIX_FMT_RGB24;
+ break;
+
+ case HAL_PIXEL_FORMAT_RGB_565:
+ V4L2_PIX = V4L2_PIX_FMT_RGB565;
+ break;
+
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ //V4L2_PIX = V4L2_PIX_FMT_BGR32; // this is not proper on fimc.
+ V4L2_PIX = V4L2_PIX_FMT_RGB32;
+ break;
+
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ V4L2_PIX = V4L2_PIX_FMT_RGB555X;
+ break;
+
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ V4L2_PIX = V4L2_PIX_FMT_RGB444;
+ break;
+
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P:
+ V4L2_PIX = V4L2_PIX_FMT_YUV420;
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
+ V4L2_PIX = V4L2_PIX_FMT_NV61;
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
+ V4L2_PIX = V4L2_PIX_FMT_NV12;
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
+ V4L2_PIX = V4L2_PIX_FMT_YUYV;
+ break;
+
+ case HAL_PIXEL_FORMAT_YCbCr_422_P:
+ V4L2_PIX = V4L2_PIX_FMT_YUV422P;
+ break;
+
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
+ V4L2_PIX = V4L2_PIX_FMT_UYVY;
+ break;
+
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
+ V4L2_PIX = V4L2_PIX_FMT_NV16;
+ break;
+
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
+ V4L2_PIX = V4L2_PIX_FMT_NV21;
+ break;
+
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
+ V4L2_PIX = V4L2_PIX_FMT_NV12T;
+ break;
+
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
+ V4L2_PIX = V4L2_PIX_FMT_YVYU;
+ break;
+
+ case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
+ V4L2_PIX = V4L2_PIX_FMT_VYUY;
+ break;
+
+ default:
+ LOGE("%s::unmatched HAL_PIXEL_FORMAT color_space(0x%x)\n",
+ __func__, HAL_PIXEL_FORMAT);
+ break;
+ }
+
+ return V4L2_PIX;
+}
+
+inline int V4L2_PIX_2_HAL_PIXEL_FORMAT(int V4L2_PIX)
+{
+ int HAL_PIXEL_FORMAT = -1;
+
+ switch (V4L2_PIX) {
+ case V4L2_PIX_FMT_RGB32:
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888;
+ //HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGBX_8888;
+ break;
+
+ case V4L2_PIX_FMT_RGB24:
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGB_888;
+ break;
+
+ case V4L2_PIX_FMT_RGB565:
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGB_565;
+ break;
+
+ case V4L2_PIX_FMT_BGR32:
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_BGRA_8888;
+ break;
+
+ case V4L2_PIX_FMT_RGB555X:
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGBA_5551;
+ break;
+
+ case V4L2_PIX_FMT_RGB444:
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_RGBA_4444;
+ break;
+
+ case V4L2_PIX_FMT_YUV420:
+ //HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YV12;
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YCbCr_420_P;
+ break;
+
+ case V4L2_PIX_FMT_NV16:
+ //HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YCrCb_422_SP;
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP;
+ break;
+
+ case V4L2_PIX_FMT_NV12:
+ //HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP;
+ break;
+
+ case V4L2_PIX_FMT_YUYV:
+ //HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YCbCr_422_I;
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I;
+ break;
+
+ case V4L2_PIX_FMT_YUV422P:
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YCbCr_422_P;
+ break;
+
+ case V4L2_PIX_FMT_UYVY:
+ //HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CbYCrY_422_I;
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I;
+ break;
+
+ case V4L2_PIX_FMT_NV21:
+ //HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_YCbCr_420_SP;
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP;
+ break;
+
+ case V4L2_PIX_FMT_NV12T:
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED;
+ break;
+
+ case V4L2_PIX_FMT_NV61:
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP;
+ break;
+
+ case V4L2_PIX_FMT_YVYU:
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I;
+ break;
+
+ case V4L2_PIX_FMT_VYUY:
+ HAL_PIXEL_FORMAT = HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I;
+ break;
+
+ default:
+ LOGE("%s::unmatched V4L2_PIX color_space(%d)\n",
+ __func__, V4L2_PIX);
+ break;
+ }
+
+ return HAL_PIXEL_FORMAT;
+}
+
+#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5)
+#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7)
+#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13)
+
+#define GET_32BPP_FRAME_SIZE(w, h) (((w) * (h)) << 2)
+#define GET_24BPP_FRAME_SIZE(w, h) (((w) * (h)) * 3)
+#define GET_16BPP_FRAME_SIZE(w, h) (((w) * (h)) << 1)
+
+inline unsigned int FRAME_SIZE(int HAL_PIXEL_FORMAT, int w, int h)
+{
+ unsigned int frame_size = 0;
+ unsigned int size = 0;
+
+ switch (HAL_PIXEL_FORMAT) {
+ // 16bpp
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ //case HAL_PIXEL_FORMAT_ARGB_1555:
+ //case HAL_PIXEL_FORMAT_BGRA_5551:
+ //case HAL_PIXEL_FORMAT_ABGR_1555:
+
+ //case HAL_PIXEL_FORMAT_RGBX_5551:
+ //case HAL_PIXEL_FORMAT_XRGB_1555:
+ //case HAL_PIXEL_FORMAT_BGRX_5551:
+ //case HAL_PIXEL_FORMAT_XBGR_1555:
+
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ //case HAL_PIXEL_FORMAT_ARGB_4444:
+ //case HAL_PIXEL_FORMAT_BGRA_4444:
+ //case HAL_PIXEL_FORMAT_ABGR_4444:
+
+ //case HAL_PIXEL_FORMAT_RGBX_4444:
+ //case HAL_PIXEL_FORMAT_XRGB_4444:
+ //case HAL_PIXEL_FORMAT_BGRX_4444:
+ //case HAL_PIXEL_FORMAT_XBGR_4444:
+ frame_size = GET_16BPP_FRAME_SIZE(w, h);
+ break;
+
+ // 24bpp
+ case HAL_PIXEL_FORMAT_RGB_888:
+ frame_size = GET_24BPP_FRAME_SIZE(w, h);
+ break;
+
+ // 32bpp
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ //case HAL_PIXEL_FORMAT_ARGB_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ //case HAL_PIXEL_FORMAT_ABGR_8888:
+
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ //case HAL_PIXEL_FORMAT_XRGB_8888:
+ //case HAL_PIXEL_FORMAT_BGRX_8888:
+ //case HAL_PIXEL_FORMAT_XBGR_8888:
+ frame_size = GET_32BPP_FRAME_SIZE(w, h);
+ break;
+
+ // 12bpp
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_P:
+ case HAL_PIXEL_FORMAT_YCbCr_420_I:
+ case HAL_PIXEL_FORMAT_CbYCrY_420_I:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
+ size = w * h;
+ // frame_size = width * height * 3 / 2;
+ // sw5771.park : very curious...
+ // frame_size = size + ((size / 4) * 2);
+ frame_size = size + ((size >> 2) << 1);
+ break;
+
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
+ frame_size = ALIGN_TO_8KB(ALIGN_TO_128B(w) * ALIGN_TO_32B(h))
+ + ALIGN_TO_8KB(ALIGN_TO_128B(w) * ALIGN_TO_32B(h >> 1));
+ break;
+
+ // 16bpp
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_YCbCr_422_P:
+ case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
+ case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
+ frame_size = GET_16BPP_FRAME_SIZE(w, h);
+ break;
+
+ default:
+ LOGD("%s::no matching source colorformat(0x%x), w(%d), h(%d) fail\n",
+ __func__, HAL_PIXEL_FORMAT, w, h);
+ break;
+ }
+
+ return frame_size;
+}
+
+#endif //__SAMSUNG_SYSLSI_SEC_COMMON_H__
diff --git a/include/videodev2_samsung.h b/include/videodev2_samsung.h
new file mode 100755
index 0000000..f3f32eb
--- /dev/null
+++ b/include/videodev2_samsung.h
@@ -0,0 +1,653 @@
+/*
+ * Video for Linux Two header file for samsung
+ *
+ * Copyright (C) 2009, Samsung Electronics
+ *
+ * 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.
+ *
+ * Alternatively, Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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)
+#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)
+
+/* 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)
+#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_STREAM_PAUSE (V4L2_CID_PRIVATE_BASE + 53)
+
+/* 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)
+#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)
+#define V4L2_CID_CAMERA_VGA_BLUR (V4L2_CID_PRIVATE_BASE + 49)
+#define V4L2_CID_CAMERA_CAPTURE (V4L2_CID_PRIVATE_BASE + 50)
+
+#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)
+
+enum v4l2_blur {
+ BLUR_LEVEL_0 = 0,
+ BLUR_LEVEL_1,
+ BLUR_LEVEL_2,
+ BLUR_LEVEL_3,
+ BLUR_LEVEL_MAX,
+};
+
+#define V4L2_CID_CAMERA_SCENE_MODE (V4L2_CID_PRIVATE_BASE + 70)
+enum v4l2_scene_mode {
+ SCENE_MODE_BASE = 0,
+ 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_DUST_DAWN,
+ SCENE_MODE_FALL_COLOR,
+ SCENE_MODE_FIREWORKS,
+ SCENE_MODE_TEXT,
+ SCENE_MODE_CANDLE_LIGHT,
+ SCENE_MODE_MAX,
+};
+
+#define V4L2_CID_CAMERA_FLASH_MODE (V4L2_CID_PRIVATE_BASE + 71)
+enum v4l2_flash_mode {
+ FLASH_MODE_BASE = 0,
+ FLASH_MODE_OFF,
+ FLASH_MODE_AUTO,
+ FLASH_MODE_ON,
+ FLASH_MODE_TORCH,
+ FLASH_MODE_MAX,
+};
+
+#define V4L2_CID_CAMERA_BRIGHTNESS (V4L2_CID_PRIVATE_BASE + 72)
+enum v4l2_ev_mode {
+ EV_MINUS_4 = 0,
+ EV_MINUS_3,
+ EV_MINUS_2,
+ EV_MINUS_1,
+ EV_DEFAULT,
+ EV_PLUS_1,
+ EV_PLUS_2,
+ EV_PLUS_3,
+ EV_PLUS_4,
+ EV_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_DAYLIGHT,
+ WHITE_BALANCE_CLOUDY_DAYLIGHT,
+ WHITE_BALANCE_INCANDESCENT,
+ WHITE_BALANCE_TUNGSTEN,
+ WHITE_BALANCE_FLUORESCENT,
+ 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_MAX,
+};
+
+#define V4L2_CID_CAMERA_ISO (V4L2_CID_PRIVATE_BASE + 75)
+enum v4l2_iso_mode {
+ ISO_AUTO = 0,
+ ISO_50,
+ ISO_100,
+ ISO_200,
+ ISO_400,
+ ISO_800,
+ ISO_1600,
+ ISO_SPORTS,
+ ISO_NIGHT,
+ ISO_MOVIE,
+ ISO_MAX,
+};
+
+#define V4L2_CID_CAMERA_METERING (V4L2_CID_PRIVATE_BASE + 76)
+enum v4l2_metering_mode {
+ METERING_BASE = 0,
+ METERING_MATRIX,
+ METERING_CENTER,
+ METERING_SPOT,
+ METERING_MAX,
+};
+
+#define V4L2_CID_CAMERA_CONTRAST (V4L2_CID_PRIVATE_BASE + 77)
+enum v4l2_contrast_mode {
+ CONTRAST_MINUS_2 = 0,
+ CONTRAST_MINUS_1,
+ CONTRAST_DEFAULT,
+ CONTRAST_PLUS_1,
+ CONTRAST_PLUS_2,
+ CONTRAST_MAX,
+};
+
+#define V4L2_CID_CAMERA_SATURATION (V4L2_CID_PRIVATE_BASE + 78)
+enum v4l2_saturation_mode {
+ SATURATION_MINUS_2 = 0,
+ SATURATION_MINUS_1,
+ SATURATION_DEFAULT,
+ SATURATION_PLUS_1,
+ SATURATION_PLUS_2,
+ SATURATION_MAX,
+};
+
+#define V4L2_CID_CAMERA_SHARPNESS (V4L2_CID_PRIVATE_BASE + 79)
+enum v4l2_sharpness_mode {
+ SHARPNESS_MINUS_2 = 0,
+ SHARPNESS_MINUS_1,
+ SHARPNESS_DEFAULT,
+ SHARPNESS_PLUS_1,
+ SHARPNESS_PLUS_2,
+ SHARPNESS_MAX,
+};
+
+#define V4L2_CID_CAMERA_WDR (V4L2_CID_PRIVATE_BASE + 80)
+enum v4l2_wdr_mode {
+ WDR_OFF = 0,
+ WDR_ON,
+ WDR_MAX,
+};
+
+#define V4L2_CID_CAMERA_ANTI_SHAKE (V4L2_CID_PRIVATE_BASE + 81)
+enum v4l2_anti_shake_mode {
+ ANTI_SHAKE_OFF = 0,
+ 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 = 0,
+ 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)
+enum JPEG_QUALITY{
+ JPEG_QUALITY_ECONOMY = 0,
+ JPEG_QUALITY_NORMAL = 50,
+ JPEG_QUALITY_SUPERFINE = 100,
+ JPEG_QUALITY_MAX,
+};
+
+#define V4L2_CID_CAMERA_GPS_LATITUDE (V4L2_CID_CAMERA_CLASS_BASE + 30)
+#define V4L2_CID_CAMERA_GPS_LONGITUDE (V4L2_CID_CAMERA_CLASS_BASE + 31)
+#define V4L2_CID_CAMERA_GPS_TIMESTAMP (V4L2_CID_CAMERA_CLASS_BASE + 32)
+#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_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,
+};
+
+#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_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_STATUS,
+ 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_MAX,
+};
+
+#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_PROGRESSING,
+ OBJECT_TRACKING_STATUS_SUCCESS,
+ OBJECT_TRACKING_STATUS_FAIL,
+ OBJECT_TRACKING_STATUS_MISSING,
+ OBJECT_TRACKING_STATUS_MAX,
+};
+
+#define V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP (V4L2_CID_PRIVATE_BASE + 101)
+enum v4l2_ot_start_stop {
+ OT_STOP = 0,
+ OT_START,
+ OT_MAX,
+};
+
+#define V4L2_CID_CAMERA_CAF_START_STOP (V4L2_CID_PRIVATE_BASE + 102)
+enum v4l2_caf_start_stop {
+ CAF_STOP = 0,
+ CAF_START,
+ CAF_MAX,
+};
+
+#define V4L2_CID_CAMERA_AUTO_FOCUS_RESULT (V4L2_CID_PRIVATE_BASE + 103)
+#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_30 = 30,
+ FRAME_RATE_60 = 60,
+ FRAME_RATE_120 = 120,
+ FRAME_RATE_MAX
+};
+
+#define V4L2_CID_CAMERA_ANTI_BANDING (V4L2_CID_PRIVATE_BASE + 105)
+enum v4l2_anti_banding {
+ ANTI_BANDING_AUTO = 0,
+ ANTI_BANDING_50HZ = 1,
+ ANTI_BANDING_60HZ = 2,
+ ANTI_BANDING_OFF = 3,
+};
+
+#define V4L2_CID_CAMERA_SET_GAMMA (V4L2_CID_PRIVATE_BASE + 106)
+enum v4l2_gamma_mode {
+ GAMMA_OFF = 0,
+ GAMMA_ON = 1,
+ GAMMA_MAX,
+};
+
+#define V4L2_CID_CAMERA_SET_SLOW_AE (V4L2_CID_PRIVATE_BASE + 107)
+enum v4l2_slow_ae_mode {
+ SLOW_AE_OFF = 0,
+ 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_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)
+#define V4L2_CID_CAMERA_GET_ISO (V4L2_CID_PRIVATE_BASE + 114)
+#define V4L2_CID_CAMERA_GET_SHT_TIME (V4L2_CID_PRIVATE_BASE + 115)
+#define V4L2_CID_CAMERA_SENSOR_MODE (V4L2_CID_PRIVATE_BASE + 116)
+#define V4L2_CID_ESD_INT (V4L2_CID_PRIVATE_BASE + 117)
+#define V4L2_CID_CAMERA_GET_FLASH_ONOFF (V4L2_CID_PRIVATE_BASE + 118)
+#define V4L2_CID_CAMERA_APP_CHECK (V4L2_CID_PRIVATE_BASE + 119)
+#define V4L2_CID_CAMERA_CHECK_FLIP (V4L2_CID_PRIVATE_BASE + 120)
+
+#define V4L2_CID_CAM_SENSOR_TYPE (V4L2_CID_PRIVATE_BASE + 121)
+enum v4l2_camera_id {
+ CAMERA_ID_BACK = 0,
+ CAMERA_ID_FRONT = 1,
+ CAMERA_ID_MAX = 2,
+};
+
+/* Pixel format FOURCC depth Description */
+/* 12 Y/CbCr 4:2:0 64x32 macroblocks */
+#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2')
+
+/*
+ * * 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)
+
+/* We use this struct as the v4l2_streamparm raw_data for
+ * VIDIOC_G_PARM and VIDIOC_S_PARM
+ */
+struct sec_cam_parm {
+ struct v4l2_captureparm capture;
+ int contrast;
+ int effects;
+ int brightness;
+ int flash_mode;
+ int focus_mode;
+ int iso;
+ int metering;
+ int saturation;
+ int scene_mode;
+ int sharpness;
+ int white_balance;
+};
+
+#endif /* __LINUX_VIDEODEV2_SAMSUNG_H */
diff --git a/init.p1.usb.rc b/init.p1.usb.rc
new file mode 100755
index 0000000..a8f5413
--- /dev/null
+++ b/init.p1.usb.rc
@@ -0,0 +1,6 @@
+on property:sys.usb.config=mass_storage
+ setprop sys.usb.state $sys.usb.config
+
+on property:sys.usb.config=mass_storage,adb
+ start adbd
+ setprop sys.usb.state $sys.usb.config
diff --git a/libaudio/Android.mk b/libaudio/Android.mk
new file mode 100644
index 0000000..5c998d6
--- /dev/null
+++ b/libaudio/Android.mk
@@ -0,0 +1,52 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= aplay.c alsa_pcm.c alsa_mixer.c
+LOCAL_MODULE:= aplay
+LOCAL_SHARED_LIBRARIES:= libc libcutils
+LOCAL_MODULE_TAGS:= debug
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= arec.c alsa_pcm.c
+LOCAL_MODULE:= arec
+LOCAL_SHARED_LIBRARIES:= libc libcutils
+LOCAL_MODULE_TAGS:= debug
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= amix.c alsa_mixer.c
+LOCAL_MODULE:= amix
+LOCAL_SHARED_LIBRARIES := libc libcutils
+LOCAL_MODULE_TAGS:= debug
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= AudioHardware.cpp alsa_mixer.c alsa_pcm.c
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE:= audio.primary.s5pc110
+LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_LIBRARIES := libmedia_helper
+LOCAL_WHOLE_STATIC_LIBRARIES := libaudiohw_legacy
+LOCAL_SHARED_LIBRARIES:= libc libcutils libutils libmedia libhardware_legacy
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= AudioPolicyManager.cpp
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE:= audio_policy.s5pc110
+LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_LIBRARIES := libmedia_helper
+LOCAL_WHOLE_STATIC_LIBRARIES:= libaudiopolicy_legacy
+LOCAL_SHARED_LIBRARIES:= libc libcutils libutils libmedia
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+ LOCAL_CFLAGS += -DWITH_A2DP
+endif
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libaudio/AudioHardware.cpp b/libaudio/AudioHardware.cpp
new file mode 100644
index 0000000..d50a7c3
--- /dev/null
+++ b/libaudio/AudioHardware.cpp
@@ -0,0 +1,1961 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include
+
+#define LOG_NDEBUG 0
+
+#define LOG_TAG "AudioHardware"
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "AudioHardware.h"
+#include
+#include
+
+extern "C" {
+#include "alsa_audio.h"
+}
+
+
+namespace android_audio_legacy {
+
+const uint32_t AudioHardware::inputSamplingRates[] = {
+ 8000, 11025, 16000, 22050, 44100
+};
+
+// trace driver operations for dump
+//
+//#define DRIVER_TRACE
+
+enum {
+ DRV_NONE,
+ DRV_PCM_OPEN,
+ DRV_PCM_CLOSE,
+ DRV_PCM_WRITE,
+ DRV_PCM_READ,
+ DRV_MIXER_OPEN,
+ DRV_MIXER_CLOSE,
+ DRV_MIXER_GET,
+ DRV_MIXER_SEL
+};
+
+#ifdef DRIVER_TRACE
+#define TRACE_DRIVER_IN(op) mDriverOp = op;
+#define TRACE_DRIVER_OUT mDriverOp = DRV_NONE;
+#else
+#define TRACE_DRIVER_IN(op)
+#define TRACE_DRIVER_OUT
+#endif
+
+// ----------------------------------------------------------------------------
+
+const char *AudioHardware::inputPathNameDefault = "Default";
+const char *AudioHardware::inputPathNameCamcorder = "Camcorder";
+const char *AudioHardware::inputPathNameVoiceRecognition = "Voice Recognition";
+const char *AudioHardware::inputPathNameVoiceCommunication = "Voice Communication";
+
+AudioHardware::AudioHardware() :
+ mInit(false),
+ mMicMute(false),
+ mPcm(NULL),
+ mMixer(NULL),
+ mPcmOpenCnt(0),
+ mMixerOpenCnt(0),
+ mInCallAudioMode(false),
+ mInputSource(AUDIO_SOURCE_DEFAULT),
+ mBluetoothNrec(true),
+ mTTYMode(TTY_MODE_OFF),
+ mDriverOp(DRV_NONE)
+{
+ mInit = true;
+}
+
+AudioHardware::~AudioHardware()
+{
+ for (size_t index = 0; index < mInputs.size(); index++) {
+ closeInputStream(mInputs[index].get());
+ }
+ mInputs.clear();
+ closeOutputStream((AudioStreamOut*)mOutput.get());
+
+ if (mMixer) {
+ TRACE_DRIVER_IN(DRV_MIXER_CLOSE)
+ mixer_close(mMixer);
+ TRACE_DRIVER_OUT
+ }
+ if (mPcm) {
+ TRACE_DRIVER_IN(DRV_PCM_CLOSE)
+ pcm_close(mPcm);
+ TRACE_DRIVER_OUT
+ }
+
+ mInit = false;
+}
+
+status_t AudioHardware::initCheck()
+{
+ return mInit ? NO_ERROR : NO_INIT;
+}
+
+AudioStreamOut* AudioHardware::openOutputStream(
+ uint32_t devices, int *format, uint32_t *channels,
+ uint32_t *sampleRate, status_t *status)
+{
+ sp out;
+ status_t rc;
+
+ { // scope for the lock
+ Mutex::Autolock lock(mLock);
+
+ // only one output stream allowed
+ if (mOutput != 0) {
+ if (status) {
+ *status = INVALID_OPERATION;
+ }
+ return NULL;
+ }
+
+ out = new AudioStreamOutALSA();
+
+ rc = out->set(this, devices, format, channels, sampleRate);
+ if (rc == NO_ERROR) {
+ mOutput = out;
+ }
+ }
+
+ if (rc != NO_ERROR) {
+ if (out != 0) {
+ out.clear();
+ }
+ }
+ if (status) {
+ *status = rc;
+ }
+
+ return out.get();
+}
+
+void AudioHardware::closeOutputStream(AudioStreamOut* out) {
+ sp spOut;
+ {
+ Mutex::Autolock lock(mLock);
+ if (mOutput == 0 || mOutput.get() != out) {
+ LOGW("Attempt to close invalid output stream");
+ return;
+ }
+ spOut = mOutput;
+ mOutput.clear();
+ }
+ spOut.clear();
+}
+
+AudioStreamIn* AudioHardware::openInputStream(
+ uint32_t devices, int *format, uint32_t *channels,
+ uint32_t *sampleRate, status_t *status,
+ AudioSystem::audio_in_acoustics acoustic_flags)
+{
+ // check for valid input source
+ if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
+ if (status) {
+ *status = BAD_VALUE;
+ }
+ return NULL;
+ }
+
+ status_t rc = NO_ERROR;
+ sp in;
+
+ { // scope for the lock
+ Mutex::Autolock lock(mLock);
+
+ in = new AudioStreamInALSA();
+ rc = in->set(this, devices, format, channels, sampleRate, acoustic_flags);
+ if (rc == NO_ERROR) {
+ mInputs.add(in);
+ }
+ }
+
+ if (rc != NO_ERROR) {
+ if (in != 0) {
+ in.clear();
+ }
+ }
+ if (status) {
+ *status = rc;
+ }
+
+ LOGV("AudioHardware::openInputStream()%p", in.get());
+ return in.get();
+}
+
+void AudioHardware::closeInputStream(AudioStreamIn* in) {
+
+ sp spIn;
+ {
+ Mutex::Autolock lock(mLock);
+
+ ssize_t index = mInputs.indexOf((AudioStreamInALSA *)in);
+ if (index < 0) {
+ LOGW("Attempt to close invalid input stream");
+ return;
+ }
+ spIn = mInputs[index];
+ mInputs.removeAt(index);
+ }
+ LOGV("AudioHardware::closeInputStream()%p", in);
+ spIn.clear();
+}
+
+
+status_t AudioHardware::setMode(int mode)
+{
+ sp spOut;
+ sp spIn;
+ status_t status;
+
+ // Mutex acquisition order is always out -> in -> hw
+ AutoMutex lock(mLock);
+
+ spOut = mOutput;
+ while (spOut != 0) {
+ if (!spOut->checkStandby()) {
+ int cnt = spOut->prepareLock();
+ mLock.unlock();
+ spOut->lock();
+ mLock.lock();
+ // make sure that another thread did not change output state while the
+ // mutex is released
+ if ((spOut == mOutput) && (cnt == spOut->standbyCnt())) {
+ break;
+ }
+ spOut->unlock();
+ spOut = mOutput;
+ } else {
+ spOut.clear();
+ }
+ }
+ // spOut is not 0 here only if the output is active
+
+ spIn = getActiveInput_l();
+ while (spIn != 0) {
+ int cnt = spIn->prepareLock();
+ mLock.unlock();
+ spIn->lock();
+ mLock.lock();
+ // make sure that another thread did not change input state while the
+ // mutex is released
+ if ((spIn == getActiveInput_l()) && (cnt == spIn->standbyCnt())) {
+ break;
+ }
+ spIn->unlock();
+ spIn = getActiveInput_l();
+ }
+ // spIn is not 0 here only if the input is active
+
+ int prevMode = mMode;
+ status = AudioHardwareBase::setMode(mode);
+ LOGV("setMode() : new %d, old %d", mMode, prevMode);
+ if (status == NO_ERROR) {
+ if (mMode == AudioSystem::MODE_IN_CALL && !mInCallAudioMode) {
+ if (spOut != 0) {
+ LOGV("setMode() in call force output standby");
+ spOut->doStandby_l();
+ }
+ if (spIn != 0) {
+ LOGV("setMode() in call force input standby");
+ spIn->doStandby_l();
+ }
+
+ LOGV("setMode() openPcmOut_l()");
+ openPcmOut_l();
+ openMixer_l();
+ setInputSource_l(AUDIO_SOURCE_DEFAULT);
+ mInCallAudioMode = true;
+ }
+ if (mMode == AudioSystem::MODE_NORMAL && mInCallAudioMode) {
+ setInputSource_l(mInputSource);
+ if (mMixer != NULL) {
+ TRACE_DRIVER_IN(DRV_MIXER_GET)
+ struct mixer_ctl *ctl= mixer_get_control(mMixer, "Playback Path", 0);
+ TRACE_DRIVER_OUT
+ if (ctl != NULL) {
+ LOGV("setMode() reset Playback Path to SPK");
+ TRACE_DRIVER_IN(DRV_MIXER_SEL)
+ mixer_ctl_select(ctl, "SPK");
+ TRACE_DRIVER_OUT
+ }
+ }
+ LOGV("setMode() closePcmOut_l()");
+ closeMixer_l();
+ closePcmOut_l();
+
+ if (spOut != 0) {
+ LOGV("setMode() off call force output standby");
+ spOut->doStandby_l();
+ }
+ if (spIn != 0) {
+ LOGV("setMode() off call force input standby");
+ spIn->doStandby_l();
+ }
+
+ mInCallAudioMode = false;
+ }
+ }
+
+ if (spIn != 0) {
+ spIn->unlock();
+ }
+ if (spOut != 0) {
+ spOut->unlock();
+ }
+
+ return status;
+}
+
+status_t AudioHardware::setMicMute(bool state)
+{
+ LOGV("setMicMute(%d) mMicMute %d", state, mMicMute);
+ sp spIn;
+ {
+ AutoMutex lock(mLock);
+ if (mMicMute != state) {
+ mMicMute = state;
+ spIn = getActiveInput_l();
+ }
+ }
+
+ if (spIn != 0) {
+ spIn->standby();
+ }
+
+ return NO_ERROR;
+}
+
+status_t AudioHardware::getMicMute(bool* state)
+{
+ *state = mMicMute;
+ return NO_ERROR;
+}
+
+status_t AudioHardware::setParameters(const String8& keyValuePairs)
+{
+ AudioParameter param = AudioParameter(keyValuePairs);
+ String8 value;
+ String8 key;
+ const char BT_NREC_KEY[] = "bt_headset_nrec";
+ const char BT_NREC_VALUE_ON[] = "on";
+ const char TTY_MODE_KEY[] = "tty_mode";
+ const char TTY_MODE_VALUE_OFF[] = "tty_off";
+ const char TTY_MODE_VALUE_VCO[] = "tty_vco";
+ const char TTY_MODE_VALUE_HCO[] = "tty_hco";
+ const char TTY_MODE_VALUE_FULL[] = "tty_full";
+
+ key = String8(BT_NREC_KEY);
+ if (param.get(key, value) == NO_ERROR) {
+ if (value == BT_NREC_VALUE_ON) {
+ mBluetoothNrec = true;
+ } else {
+ mBluetoothNrec = false;
+ LOGD("Turning noise reduction and echo cancellation off for BT "
+ "headset");
+ }
+ param.remove(String8(BT_NREC_KEY));
+ }
+
+ key = String8(TTY_MODE_KEY);
+ if (param.get(key, value) == NO_ERROR) {
+ int ttyMode;
+ if (value == TTY_MODE_VALUE_OFF) {
+ ttyMode = TTY_MODE_OFF;
+ } else if (value == TTY_MODE_VALUE_VCO) {
+ ttyMode = TTY_MODE_VCO;
+ } else if (value == TTY_MODE_VALUE_HCO) {
+ ttyMode = TTY_MODE_HCO;
+ } else if (value == TTY_MODE_VALUE_FULL) {
+ ttyMode = TTY_MODE_FULL;
+ } else {
+ return BAD_VALUE;
+ }
+
+ if (ttyMode != mTTYMode) {
+ LOGV("new tty mode %d", ttyMode);
+ mTTYMode = ttyMode;
+ if (mOutput != 0 && mMode == AudioSystem::MODE_IN_CALL) {
+ setIncallPath_l(mOutput->device());
+ }
+ }
+ param.remove(String8(TTY_MODE_KEY));
+ }
+
+ return NO_ERROR;
+}
+
+String8 AudioHardware::getParameters(const String8& keys)
+{
+ AudioParameter request = AudioParameter(keys);
+ AudioParameter reply = AudioParameter();
+
+ LOGV("getParameters() %s", keys.string());
+
+ return reply.toString();
+}
+
+size_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+{
+ if (format != AudioSystem::PCM_16_BIT) {
+ LOGW("getInputBufferSize bad format: %d", format);
+ return 0;
+ }
+ if (channelCount < 1 || channelCount > 2) {
+ LOGW("getInputBufferSize bad channel count: %d", channelCount);
+ return 0;
+ }
+ if (sampleRate != 8000 && sampleRate != 11025 && sampleRate != 16000 &&
+ sampleRate != 22050 && sampleRate != 44100) {
+ LOGW("getInputBufferSize bad sample rate: %d", sampleRate);
+ return 0;
+ }
+
+ return AudioStreamInALSA::getBufferSize(sampleRate, channelCount);
+}
+
+
+status_t AudioHardware::setVoiceVolume(float volume)
+{
+ LOGD("### setVoiceVolume: %f", volume);
+
+ AutoMutex lock(mLock);
+
+ uint32_t device = AudioSystem::DEVICE_OUT_EARPIECE;
+ if (mOutput != 0) {
+ device = mOutput->device();
+ }
+ if (mMixer != NULL) {
+ struct mixer_ctl *ctl;
+ const char* name;
+ TRACE_DRIVER_IN(DRV_MIXER_GET)
+ switch (device) {
+ case AudioSystem::DEVICE_OUT_WIRED_HEADSET:
+ case AudioSystem::DEVICE_OUT_WIRED_HEADPHONE:
+ name = "Playback Headset Volume";
+ break;
+ default:
+ name = "Playback Spkr Volume";
+ break;
+ }
+ ctl= mixer_get_control(mMixer, name, 0);
+ TRACE_DRIVER_OUT
+
+ if (ctl != NULL) {
+ LOGV("setVoiceVolume() set %s to %f", name, volume);
+ TRACE_DRIVER_IN(DRV_MIXER_SET)
+ mixer_ctl_set(ctl, volume * 100);
+ TRACE_DRIVER_OUT
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t AudioHardware::setMasterVolume(float volume)
+{
+ LOGV("Set master volume to %f.\n", volume);
+ // We return an error code here to let the audioflinger do in-software
+ // volume on top of the maximum volume that we set through the SND API.
+ // return error - software mixer will handle it
+
+ return -1;
+}
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 20000;
+
+static bool tryLock(Mutex& mutex)
+{
+ bool locked = false;
+ for (int i = 0; i < kDumpLockRetries; ++i) {
+ if (mutex.tryLock() == NO_ERROR) {
+ locked = true;
+ break;
+ }
+ usleep(kDumpLockSleep);
+ }
+ return locked;
+}
+
+status_t AudioHardware::dump(int fd, const Vector& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ bool locked = tryLock(mLock);
+ if (!locked) {
+ snprintf(buffer, SIZE, "\n\tAudioHardware maybe deadlocked\n");
+ } else {
+ mLock.unlock();
+ }
+
+ snprintf(buffer, SIZE, "\tInit %s\n", (mInit) ? "OK" : "Failed");
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\tMic Mute %s\n", (mMicMute) ? "ON" : "OFF");
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\tmPcm: %p\n", mPcm);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\tmPcmOpenCnt: %d\n", mPcmOpenCnt);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\tmMixer: %p\n", mMixer);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\tmMixerOpenCnt: %d\n", mMixerOpenCnt);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\tIn Call Audio Mode %s\n",
+ (mInCallAudioMode) ? "ON" : "OFF");
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\tInput source %d\n", mInputSource);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\tmDriverOp: %d\n", mDriverOp);
+ result.append(buffer);
+
+ snprintf(buffer, SIZE, "\n\tmOutput %p dump:\n", mOutput.get());
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ if (mOutput != 0) {
+ mOutput->dump(fd, args);
+ }
+
+ snprintf(buffer, SIZE, "\n\t%d inputs opened:\n", mInputs.size());
+ write(fd, buffer, strlen(buffer));
+ for (size_t i = 0; i < mInputs.size(); i++) {
+ snprintf(buffer, SIZE, "\t- input %d dump:\n", i);
+ write(fd, buffer, strlen(buffer));
+ mInputs[i]->dump(fd, args);
+ }
+
+ return NO_ERROR;
+}
+
+status_t AudioHardware::setIncallPath_l(uint32_t device)
+{
+ LOGV("setIncallPath_l: device %x", device);
+
+ if (mMixer != NULL) {
+ TRACE_DRIVER_IN(DRV_MIXER_GET)
+ struct mixer_ctl *ctl= mixer_get_control(mMixer, "Voice Call Path", 0);
+ TRACE_DRIVER_OUT
+ LOGE_IF(ctl == NULL, "setIncallPath_l() could not get mixer ctl");
+ if (ctl != NULL) {
+ LOGV("setIncallPath_l() Voice Call Path, (%x)", device);
+ const char *router = getVoiceRouteFromDevice(device);
+ TRACE_DRIVER_IN(DRV_MIXER_SEL)
+ mixer_ctl_select(ctl,router);
+ TRACE_DRIVER_OUT
+ }
+ }
+ return NO_ERROR;
+}
+
+struct pcm *AudioHardware::openPcmOut_l()
+{
+ LOGD("openPcmOut_l() mPcmOpenCnt: %d", mPcmOpenCnt);
+ if (mPcmOpenCnt++ == 0) {
+ if (mPcm != NULL) {
+ LOGE("openPcmOut_l() mPcmOpenCnt == 0 and mPcm == %p\n", mPcm);
+ mPcmOpenCnt--;
+ return NULL;
+ }
+ unsigned flags = PCM_OUT;
+
+ flags |= (AUDIO_HW_OUT_PERIOD_MULT - 1) << PCM_PERIOD_SZ_SHIFT;
+ flags |= (AUDIO_HW_OUT_PERIOD_CNT - PCM_PERIOD_CNT_MIN) << PCM_PERIOD_CNT_SHIFT;
+
+ TRACE_DRIVER_IN(DRV_PCM_OPEN)
+ mPcm = pcm_open(flags);
+ TRACE_DRIVER_OUT
+ if (!pcm_ready(mPcm)) {
+ LOGE("openPcmOut_l() cannot open pcm_out driver: %s\n", pcm_error(mPcm));
+ TRACE_DRIVER_IN(DRV_PCM_CLOSE)
+ pcm_close(mPcm);
+ TRACE_DRIVER_OUT
+ mPcmOpenCnt--;
+ mPcm = NULL;
+ }
+ }
+ return mPcm;
+}
+
+void AudioHardware::closePcmOut_l()
+{
+ LOGD("closePcmOut_l() mPcmOpenCnt: %d", mPcmOpenCnt);
+ if (mPcmOpenCnt == 0) {
+ LOGE("closePcmOut_l() mPcmOpenCnt == 0");
+ return;
+ }
+
+ if (--mPcmOpenCnt == 0) {
+ TRACE_DRIVER_IN(DRV_PCM_CLOSE)
+ pcm_close(mPcm);
+ TRACE_DRIVER_OUT
+ mPcm = NULL;
+ }
+}
+
+struct mixer *AudioHardware::openMixer_l()
+{
+ LOGV("openMixer_l() mMixerOpenCnt: %d", mMixerOpenCnt);
+ if (mMixerOpenCnt++ == 0) {
+ if (mMixer != NULL) {
+ LOGE("openMixer_l() mMixerOpenCnt == 0 and mMixer == %p\n", mMixer);
+ mMixerOpenCnt--;
+ return NULL;
+ }
+ TRACE_DRIVER_IN(DRV_MIXER_OPEN)
+ mMixer = mixer_open();
+ TRACE_DRIVER_OUT
+ if (mMixer == NULL) {
+ LOGE("openMixer_l() cannot open mixer");
+ mMixerOpenCnt--;
+ return NULL;
+ }
+ }
+ return mMixer;
+}
+
+void AudioHardware::closeMixer_l()
+{
+ LOGV("closeMixer_l() mMixerOpenCnt: %d", mMixerOpenCnt);
+ if (mMixerOpenCnt == 0) {
+ LOGE("closeMixer_l() mMixerOpenCnt == 0");
+ return;
+ }
+
+ if (--mMixerOpenCnt == 0) {
+ TRACE_DRIVER_IN(DRV_MIXER_CLOSE)
+ mixer_close(mMixer);
+ TRACE_DRIVER_OUT
+ mMixer = NULL;
+ }
+}
+
+const char *AudioHardware::getOutputRouteFromDevice(uint32_t device)
+{
+ switch (device) {
+ case AudioSystem::DEVICE_OUT_EARPIECE:
+ case AudioSystem::DEVICE_OUT_SPEAKER:
+ if (mMode == AudioSystem::MODE_RINGTONE) return "RING_SPK";
+ else return "SPK";
+ case AudioSystem::DEVICE_OUT_WIRED_HEADPHONE:
+ if (mMode == AudioSystem::MODE_RINGTONE) return "RING_NO_MIC";
+ else return "HP_NO_MIC";
+ case AudioSystem::DEVICE_OUT_WIRED_HEADSET:
+ if (mMode == AudioSystem::MODE_RINGTONE) return "RING_HP";
+ else return "HP";
+ case (AudioSystem::DEVICE_OUT_SPEAKER|AudioSystem::DEVICE_OUT_WIRED_HEADPHONE):
+ case (AudioSystem::DEVICE_OUT_SPEAKER|AudioSystem::DEVICE_OUT_WIRED_HEADSET):
+ if (mMode == AudioSystem::MODE_RINGTONE) return "RING_SPK_HP";
+ else return "SPK_HP";
+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO:
+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
+ return "BT";
+ default:
+ return "OFF";
+ }
+}
+
+const char *AudioHardware::getVoiceRouteFromDevice(uint32_t device)
+{
+ switch (device) {
+ case AudioSystem::DEVICE_OUT_EARPIECE:
+ case AudioSystem::DEVICE_OUT_SPEAKER:
+ return "SPK";
+ case AudioSystem::DEVICE_OUT_WIRED_HEADPHONE:
+ case AudioSystem::DEVICE_OUT_WIRED_HEADSET:
+ switch (mTTYMode) {
+ case TTY_MODE_VCO:
+ return "TTY_VCO";
+ case TTY_MODE_HCO:
+ return "TTY_HCO";
+ case TTY_MODE_FULL:
+ return "TTY_FULL";
+ case TTY_MODE_OFF:
+ default:
+ if (device == AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
+ return "HP_NO_MIC";
+ } else {
+ return "HP";
+ }
+ }
+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO:
+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+ case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
+ return "BT";
+ default:
+ return "OFF";
+ }
+}
+
+const char *AudioHardware::getInputRouteFromDevice(uint32_t device)
+{
+ if (mMicMute) {
+ return "MIC OFF";
+ }
+
+ switch (device) {
+ case AudioSystem::DEVICE_IN_BUILTIN_MIC:
+ return "Main Mic";
+ case AudioSystem::DEVICE_IN_WIRED_HEADSET:
+ return "Hands Free Mic";
+ case AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET:
+ return "BT Sco Mic";
+ default:
+ return "MIC OFF";
+ }
+}
+
+uint32_t AudioHardware::getInputSampleRate(uint32_t sampleRate)
+{
+ uint32_t i;
+ uint32_t prevDelta;
+ uint32_t delta;
+
+ for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) {
+ delta = abs(sampleRate - inputSamplingRates[i]);
+ if (delta > prevDelta) break;
+ }
+ // i is always > 0 here
+ return inputSamplingRates[i-1];
+}
+
+// getActiveInput_l() must be called with mLock held
+sp AudioHardware::getActiveInput_l()
+{
+ sp< AudioHardware::AudioStreamInALSA> spIn;
+
+ for (size_t i = 0; i < mInputs.size(); i++) {
+ // return first input found not being in standby mode
+ // as only one input can be in this state
+ if (!mInputs[i]->checkStandby()) {
+ spIn = mInputs[i];
+ break;
+ }
+ }
+
+ return spIn;
+}
+
+status_t AudioHardware::setInputSource_l(audio_source source)
+{
+ LOGV("setInputSource_l(%d)", source);
+ if (source != mInputSource) {
+ if ((source == AUDIO_SOURCE_DEFAULT) || (mMode != AudioSystem::MODE_IN_CALL)) {
+ if (mMixer) {
+ TRACE_DRIVER_IN(DRV_MIXER_GET)
+ struct mixer_ctl *ctl= mixer_get_control(mMixer, "Input Source", 0);
+ TRACE_DRIVER_OUT
+ if (ctl == NULL) {
+ return NO_INIT;
+ }
+ const char* sourceName;
+ switch (source) {
+ case AUDIO_SOURCE_DEFAULT: // intended fall-through
+ case AUDIO_SOURCE_MIC:
+ sourceName = inputPathNameDefault;
+ break;
+ case AUDIO_SOURCE_VOICE_COMMUNICATION:
+ sourceName = inputPathNameVoiceCommunication;
+ break;
+ case AUDIO_SOURCE_CAMCORDER:
+ sourceName = inputPathNameCamcorder;
+ break;
+ case AUDIO_SOURCE_VOICE_RECOGNITION:
+ sourceName = inputPathNameVoiceRecognition;
+ break;
+ case AUDIO_SOURCE_VOICE_UPLINK: // intended fall-through
+ case AUDIO_SOURCE_VOICE_DOWNLINK: // intended fall-through
+ case AUDIO_SOURCE_VOICE_CALL: // intended fall-through
+ default:
+ return NO_INIT;
+ }
+ LOGV("mixer_ctl_select, Input Source, (%s)", sourceName);
+ TRACE_DRIVER_IN(DRV_MIXER_SEL)
+ mixer_ctl_select(ctl, sourceName);
+ TRACE_DRIVER_OUT
+ }
+ }
+ mInputSource = source;
+ }
+
+ return NO_ERROR;
+}
+
+
+//------------------------------------------------------------------------------
+// AudioStreamOutALSA
+//------------------------------------------------------------------------------
+
+AudioHardware::AudioStreamOutALSA::AudioStreamOutALSA() :
+ mHardware(0), mPcm(0), mMixer(0), mRouteCtl(0),
+ mStandby(true), mDevices(0), mChannels(AUDIO_HW_OUT_CHANNELS),
+ mSampleRate(AUDIO_HW_OUT_SAMPLERATE), mBufferSize(AUDIO_HW_OUT_PERIOD_BYTES),
+ mDriverOp(DRV_NONE), mStandbyCnt(0), mSleepReq(false)
+{
+}
+
+status_t AudioHardware::AudioStreamOutALSA::set(
+ AudioHardware* hw, uint32_t devices, int *pFormat,
+ uint32_t *pChannels, uint32_t *pRate)
+{
+ int lFormat = pFormat ? *pFormat : 0;
+ uint32_t lChannels = pChannels ? *pChannels : 0;
+ uint32_t lRate = pRate ? *pRate : 0;
+
+ mHardware = hw;
+ mDevices = devices;
+
+ // fix up defaults
+ if (lFormat == 0) lFormat = format();
+ if (lChannels == 0) lChannels = channels();
+ if (lRate == 0) lRate = sampleRate();
+
+ // check values
+ if ((lFormat != format()) ||
+ (lChannels != channels()) ||
+ (lRate != sampleRate())) {
+ if (pFormat) *pFormat = format();
+ if (pChannels) *pChannels = channels();
+ if (pRate) *pRate = sampleRate();
+ return BAD_VALUE;
+ }
+
+ if (pFormat) *pFormat = lFormat;
+ if (pChannels) *pChannels = lChannels;
+ if (pRate) *pRate = lRate;
+
+ mChannels = lChannels;
+ mSampleRate = lRate;
+ mBufferSize = AUDIO_HW_OUT_PERIOD_BYTES;
+
+ return NO_ERROR;
+}
+
+AudioHardware::AudioStreamOutALSA::~AudioStreamOutALSA()
+{
+ standby();
+}
+
+ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t bytes)
+{
+ // LOGV("AudioStreamOutALSA::write(%p, %u)", buffer, bytes);
+ status_t status = NO_INIT;
+ const uint8_t* p = static_cast(buffer);
+ int ret;
+
+ if (mHardware == NULL) return NO_INIT;
+
+ if (mSleepReq) {
+ // 10ms are always shorter than the time to reconfigure the audio path
+ // which is the only condition when mSleepReq would be true.
+ usleep(10000);
+ }
+
+ { // scope for the lock
+
+ AutoMutex lock(mLock);
+
+ if (mStandby) {
+ AutoMutex hwLock(mHardware->lock());
+
+ LOGD("AudioStreamOutALSA::write: AudioHardware pcm playback is exiting standby.");
+ acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioOutLock");
+
+ sp spIn = mHardware->getActiveInput_l();
+ while (spIn != 0) {
+ int cnt = spIn->prepareLock();
+ mHardware->lock().unlock();
+ // Mutex acquisition order is always out -> in -> hw
+ spIn->lock();
+ mHardware->lock().lock();
+ // make sure that another thread did not change input state
+ // while the mutex is released
+ if ((spIn == mHardware->getActiveInput_l()) &&
+ (cnt == spIn->standbyCnt())) {
+ LOGV("AudioStreamOutALSA::write() force input standby");
+ spIn->close_l();
+ break;
+ }
+ spIn->unlock();
+ spIn = mHardware->getActiveInput_l();
+ }
+ // spIn is not 0 here only if the input was active and has been
+ // closed above
+
+ // open output before input
+ open_l();
+
+ if (spIn != 0) {
+ if (spIn->open_l() != NO_ERROR) {
+ spIn->doStandby_l();
+ }
+ spIn->unlock();
+ }
+ if (mPcm == NULL) {
+ release_wake_lock("AudioOutLock");
+ goto Error;
+ }
+ mStandby = false;
+ }
+
+ TRACE_DRIVER_IN(DRV_PCM_WRITE)
+ ret = pcm_write(mPcm,(void*) p, bytes);
+ TRACE_DRIVER_OUT
+
+ if (ret == 0) {
+ return bytes;
+ }
+ LOGW("write error: %d", errno);
+ status = -errno;
+ }
+Error:
+
+ standby();
+
+ // Simulate audio output timing in case of error
+ usleep((((bytes * 1000) / frameSize()) * 1000) / sampleRate());
+
+ return status;
+}
+
+status_t AudioHardware::AudioStreamOutALSA::standby()
+{
+ if (mHardware == NULL) return NO_INIT;
+
+ AutoMutex lock(mLock);
+
+ { // scope for the AudioHardware lock
+ AutoMutex hwLock(mHardware->lock());
+
+ doStandby_l();
+ }
+
+ return NO_ERROR;
+}
+
+void AudioHardware::AudioStreamOutALSA::doStandby_l()
+{
+ mStandbyCnt++;
+
+ if (!mStandby) {
+ LOGD("AudioHardware pcm playback is going to standby.");
+ release_wake_lock("AudioOutLock");
+ mStandby = true;
+ }
+
+ close_l();
+}
+
+void AudioHardware::AudioStreamOutALSA::close_l()
+{
+ if (mMixer) {
+ mHardware->closeMixer_l();
+ mMixer = NULL;
+ mRouteCtl = NULL;
+ }
+ if (mPcm) {
+ mHardware->closePcmOut_l();
+ mPcm = NULL;
+ }
+}
+
+status_t AudioHardware::AudioStreamOutALSA::open_l()
+{
+ LOGV("open pcm_out driver");
+ mPcm = mHardware->openPcmOut_l();
+ if (mPcm == NULL) {
+ return NO_INIT;
+ }
+
+ mMixer = mHardware->openMixer_l();
+ if (mMixer) {
+ LOGV("open playback normal");
+ TRACE_DRIVER_IN(DRV_MIXER_GET)
+ mRouteCtl = mixer_get_control(mMixer, "Playback Path", 0);
+ TRACE_DRIVER_OUT
+ }
+ if (mHardware->mode() != AudioSystem::MODE_IN_CALL) {
+ const char *route = mHardware->getOutputRouteFromDevice(mDevices);
+ LOGV("write() wakeup setting route %s", route);
+ if (mRouteCtl) {
+ TRACE_DRIVER_IN(DRV_MIXER_SEL)
+ mixer_ctl_select(mRouteCtl, route);
+ TRACE_DRIVER_OUT
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t AudioHardware::AudioStreamOutALSA::dump(int fd, const Vector& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ bool locked = tryLock(mLock);
+ if (!locked) {
+ snprintf(buffer, SIZE, "\n\t\tAudioStreamOutALSA maybe deadlocked\n");
+ } else {
+ mLock.unlock();
+ }
+
+ snprintf(buffer, SIZE, "\t\tmHardware: %p\n", mHardware);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmPcm: %p\n", mPcm);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmMixer: %p\n", mMixer);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmRouteCtl: %p\n", mRouteCtl);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tStandby %s\n", (mStandby) ? "ON" : "OFF");
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmDevices: 0x%08x\n", mDevices);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmChannels: 0x%08x\n", mChannels);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmSampleRate: %d\n", mSampleRate);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmBufferSize: %d\n", mBufferSize);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmDriverOp: %d\n", mDriverOp);
+ result.append(buffer);
+
+ ::write(fd, result.string(), result.size());
+
+ return NO_ERROR;
+}
+
+bool AudioHardware::AudioStreamOutALSA::checkStandby()
+{
+ return mStandby;
+}
+
+status_t AudioHardware::AudioStreamOutALSA::setParameters(const String8& keyValuePairs)
+{
+ AudioParameter param = AudioParameter(keyValuePairs);
+
+ status_t status = NO_ERROR;
+ int device;
+ LOGD("AudioStreamOutALSA::setParameters() %s", keyValuePairs.string());
+
+ if (mHardware == NULL) return NO_INIT;
+
+ {
+ AutoMutex lock(mLock);
+
+ if (param.getInt(String8(AudioParameter::keyRouting), device) == NO_ERROR)
+ {
+ if (device != 0) {
+ AutoMutex hwLock(mHardware->lock());
+
+ if (mDevices != (uint32_t)device) {
+ mDevices = (uint32_t)device;
+
+ if (mHardware->mode() != AudioSystem::MODE_IN_CALL) {
+ doStandby_l();
+ }
+ }
+ if (mHardware->mode() == AudioSystem::MODE_IN_CALL) {
+ mHardware->setIncallPath_l(device);
+ }
+ }
+ param.remove(String8(AudioParameter::keyRouting));
+ }
+ }
+
+ if (param.size()) {
+ status = BAD_VALUE;
+ }
+
+ return status;
+}
+
+String8 AudioHardware::AudioStreamOutALSA::getParameters(const String8& keys)
+{
+ AudioParameter param = AudioParameter(keys);
+ String8 value;
+ String8 key = String8(AudioParameter::keyRouting);
+
+ if (param.get(key, value) == NO_ERROR) {
+ param.addInt(key, (int)mDevices);
+ }
+
+ LOGV("AudioStreamOutALSA::getParameters() %s", param.toString().string());
+ return param.toString();
+}
+
+status_t AudioHardware::AudioStreamOutALSA::getRenderPosition(uint32_t *dspFrames)
+{
+ //TODO
+ return INVALID_OPERATION;
+}
+
+int AudioHardware::AudioStreamOutALSA::prepareLock()
+{
+ // request sleep next time write() is called so that caller can acquire
+ // mLock
+ mSleepReq = true;
+ return mStandbyCnt;
+}
+
+void AudioHardware::AudioStreamOutALSA::lock()
+{
+ mLock.lock();
+ mSleepReq = false;
+}
+
+void AudioHardware::AudioStreamOutALSA::unlock() {
+ mLock.unlock();
+}
+
+//------------------------------------------------------------------------------
+// AudioStreamInALSA
+//------------------------------------------------------------------------------
+
+AudioHardware::AudioStreamInALSA::AudioStreamInALSA() :
+ mHardware(0), mPcm(0), mMixer(0), mRouteCtl(0),
+ mStandby(true), mDevices(0), mChannels(AUDIO_HW_IN_CHANNELS), mChannelCount(1),
+ mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_HW_IN_PERIOD_BYTES),
+ mDownSampler(NULL), mReadStatus(NO_ERROR), mDriverOp(DRV_NONE),
+ mStandbyCnt(0), mSleepReq(false)
+{
+}
+
+status_t AudioHardware::AudioStreamInALSA::set(
+ AudioHardware* hw, uint32_t devices, int *pFormat,
+ uint32_t *pChannels, uint32_t *pRate, AudioSystem::audio_in_acoustics acoustics)
+{
+ if (pFormat == 0 || *pFormat != AUDIO_HW_IN_FORMAT) {
+ *pFormat = AUDIO_HW_IN_FORMAT;
+ return BAD_VALUE;
+ }
+ if (pRate == 0) {
+ return BAD_VALUE;
+ }
+ uint32_t rate = AudioHardware::getInputSampleRate(*pRate);
+ if (rate != *pRate) {
+ *pRate = rate;
+ return BAD_VALUE;
+ }
+
+ if (pChannels == 0 || (*pChannels != AudioSystem::CHANNEL_IN_MONO &&
+ *pChannels != AudioSystem::CHANNEL_IN_STEREO)) {
+ *pChannels = AUDIO_HW_IN_CHANNELS;
+ return BAD_VALUE;
+ }
+
+ mHardware = hw;
+
+ LOGV("AudioStreamInALSA::set(%d, %d, %u)", *pFormat, *pChannels, *pRate);
+
+ mBufferSize = getBufferSize(*pRate, AudioSystem::popCount(*pChannels));
+ mDevices = devices;
+ mChannels = *pChannels;
+ mChannelCount = AudioSystem::popCount(mChannels);
+ mSampleRate = rate;
+ if (mSampleRate != AUDIO_HW_OUT_SAMPLERATE) {
+ mDownSampler = new AudioHardware::DownSampler(mSampleRate,
+ mChannelCount,
+ AUDIO_HW_IN_PERIOD_SZ,
+ this);
+ status_t status = mDownSampler->initCheck();
+ if (status != NO_ERROR) {
+ delete mDownSampler;
+ LOGW("AudioStreamInALSA::set() downsampler init failed: %d", status);
+ return status;
+ }
+
+ mPcmIn = new int16_t[AUDIO_HW_IN_PERIOD_SZ * mChannelCount];
+ }
+ return NO_ERROR;
+}
+
+AudioHardware::AudioStreamInALSA::~AudioStreamInALSA()
+{
+ standby();
+ if (mDownSampler != NULL) {
+ delete mDownSampler;
+ if (mPcmIn != NULL) {
+ delete[] mPcmIn;
+ }
+ }
+}
+
+ssize_t AudioHardware::AudioStreamInALSA::read(void* buffer, ssize_t bytes)
+{
+ // LOGV("AudioStreamInALSA::read(%p, %u)", buffer, bytes);
+ status_t status = NO_INIT;
+ int ret;
+
+ if (mHardware == NULL) return NO_INIT;
+
+ if (mSleepReq) {
+ // 10ms are always shorter than the time to reconfigure the audio path
+ // which is the only condition when mSleepReq would be true.
+ usleep(10000);
+ }
+
+ { // scope for the lock
+ AutoMutex lock(mLock);
+
+ if (mStandby) {
+ AutoMutex hwLock(mHardware->lock());
+
+ LOGD("AudioHardware pcm capture is exiting standby.");
+ acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioInLock");
+
+ sp spOut = mHardware->output();
+ while (spOut != 0) {
+ if (!spOut->checkStandby()) {
+ int cnt = spOut->prepareLock();
+ mHardware->lock().unlock();
+ mLock.unlock();
+ // Mutex acquisition order is always out -> in -> hw
+ spOut->lock();
+ mLock.lock();
+ mHardware->lock().lock();
+ // make sure that another thread did not change output state
+ // while the mutex is released
+ if ((spOut == mHardware->output()) && (cnt == spOut->standbyCnt())) {
+ LOGV("AudioStreamInALSA::read() force output standby");
+ spOut->close_l();
+ break;
+ }
+ spOut->unlock();
+ spOut = mHardware->output();
+ } else {
+ spOut.clear();
+ }
+ }
+ // spOut is not 0 here only if the output was active and has been
+ // closed above
+
+ // open output before input
+ if (spOut != 0) {
+ if (spOut->open_l() != NO_ERROR) {
+ spOut->doStandby_l();
+ }
+ spOut->unlock();
+ }
+
+ open_l();
+
+ if (mPcm == NULL) {
+ release_wake_lock("AudioInLock");
+ goto Error;
+ }
+ mStandby = false;
+ }
+
+
+ if (mDownSampler != NULL) {
+ size_t frames = bytes / frameSize();
+ size_t framesIn = 0;
+ mReadStatus = 0;
+ do {
+ size_t outframes = frames - framesIn;
+ mDownSampler->resample(
+ (int16_t *)buffer + (framesIn * mChannelCount),
+ &outframes);
+ framesIn += outframes;
+ } while ((framesIn < frames) && mReadStatus == 0);
+ ret = mReadStatus;
+ bytes = framesIn * frameSize();
+ } else {
+ TRACE_DRIVER_IN(DRV_PCM_READ)
+ ret = pcm_read(mPcm, buffer, bytes);
+ TRACE_DRIVER_OUT
+ }
+
+ if (ret == 0) {
+ return bytes;
+ }
+
+ LOGW("read error: %d", ret);
+ status = ret;
+ }
+
+Error:
+
+ standby();
+
+ // Simulate audio output timing in case of error
+ usleep((((bytes * 1000) / frameSize()) * 1000) / sampleRate());
+
+ return status;
+}
+
+status_t AudioHardware::AudioStreamInALSA::standby()
+{
+ if (mHardware == NULL) return NO_INIT;
+
+ AutoMutex lock(mLock);
+
+ { // scope for AudioHardware lock
+ AutoMutex hwLock(mHardware->lock());
+
+ doStandby_l();
+ }
+ return NO_ERROR;
+}
+
+void AudioHardware::AudioStreamInALSA::doStandby_l()
+{
+ mStandbyCnt++;
+
+ if (!mStandby) {
+ LOGD("AudioHardware pcm capture is going to standby.");
+ release_wake_lock("AudioInLock");
+ mStandby = true;
+ }
+ close_l();
+}
+
+void AudioHardware::AudioStreamInALSA::close_l()
+{
+ if (mMixer) {
+ mHardware->closeMixer_l();
+ mMixer = NULL;
+ mRouteCtl = NULL;
+ }
+
+ if (mPcm) {
+ TRACE_DRIVER_IN(DRV_PCM_CLOSE)
+ pcm_close(mPcm);
+ TRACE_DRIVER_OUT
+ mPcm = NULL;
+ }
+}
+
+status_t AudioHardware::AudioStreamInALSA::open_l()
+{
+ unsigned flags = PCM_IN;
+ if (mChannels == AudioSystem::CHANNEL_IN_MONO) {
+ flags |= PCM_MONO;
+ }
+ flags |= (AUDIO_HW_IN_PERIOD_MULT - 1) << PCM_PERIOD_SZ_SHIFT;
+ flags |= (AUDIO_HW_IN_PERIOD_CNT - PCM_PERIOD_CNT_MIN)
+ << PCM_PERIOD_CNT_SHIFT;
+
+ LOGV("open pcm_in driver");
+ TRACE_DRIVER_IN(DRV_PCM_OPEN)
+ mPcm = pcm_open(flags);
+ TRACE_DRIVER_OUT
+ if (!pcm_ready(mPcm)) {
+ LOGE("cannot open pcm_in driver: %s\n", pcm_error(mPcm));
+ TRACE_DRIVER_IN(DRV_PCM_CLOSE)
+ pcm_close(mPcm);
+ TRACE_DRIVER_OUT
+ mPcm = NULL;
+ return NO_INIT;
+ }
+
+ if (mDownSampler != NULL) {
+ mInPcmInBuf = 0;
+ mDownSampler->reset();
+ }
+
+ mMixer = mHardware->openMixer_l();
+ if (mMixer) {
+ TRACE_DRIVER_IN(DRV_MIXER_GET)
+ mRouteCtl = mixer_get_control(mMixer, "Capture MIC Path", 0);
+ TRACE_DRIVER_OUT
+ }
+
+ if (mHardware->mode() != AudioSystem::MODE_IN_CALL) {
+ const char *route = mHardware->getInputRouteFromDevice(mDevices);
+ LOGV("read() wakeup setting route %s", route);
+ if (mRouteCtl) {
+ TRACE_DRIVER_IN(DRV_MIXER_SEL)
+ mixer_ctl_select(mRouteCtl, route);
+ TRACE_DRIVER_OUT
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t AudioHardware::AudioStreamInALSA::dump(int fd, const Vector& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ bool locked = tryLock(mLock);
+ if (!locked) {
+ snprintf(buffer, SIZE, "\n\t\tAudioStreamInALSA maybe deadlocked\n");
+ } else {
+ mLock.unlock();
+ }
+
+ snprintf(buffer, SIZE, "\t\tmHardware: %p\n", mHardware);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmPcm: %p\n", mPcm);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmMixer: %p\n", mMixer);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tStandby %s\n", (mStandby) ? "ON" : "OFF");
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmDevices: 0x%08x\n", mDevices);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmChannels: 0x%08x\n", mChannels);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmSampleRate: %d\n", mSampleRate);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmBufferSize: %d\n", mBufferSize);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\tmDriverOp: %d\n", mDriverOp);
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+
+ return NO_ERROR;
+}
+
+bool AudioHardware::AudioStreamInALSA::checkStandby()
+{
+ return mStandby;
+}
+
+status_t AudioHardware::AudioStreamInALSA::setParameters(const String8& keyValuePairs)
+{
+ AudioParameter param = AudioParameter(keyValuePairs);
+ status_t status = NO_ERROR;
+ int value;
+
+ LOGD("AudioStreamInALSA::setParameters() %s", keyValuePairs.string());
+
+ if (mHardware == NULL) return NO_INIT;
+
+ {
+ AutoMutex lock(mLock);
+
+ if (param.getInt(String8(AudioParameter::keyInputSource), value) == NO_ERROR) {
+ AutoMutex hwLock(mHardware->lock());
+
+ mHardware->openMixer_l();
+ mHardware->setInputSource_l((audio_source)value);
+ mHardware->closeMixer_l();
+
+ param.remove(String8(AudioParameter::keyInputSource));
+ }
+
+ if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR)
+ {
+ if (value != 0) {
+ AutoMutex hwLock(mHardware->lock());
+
+ if (mDevices != (uint32_t)value) {
+ mDevices = (uint32_t)value;
+ if (mHardware->mode() != AudioSystem::MODE_IN_CALL) {
+ doStandby_l();
+ }
+ }
+ }
+ param.remove(String8(AudioParameter::keyRouting));
+ }
+ }
+
+
+ if (param.size()) {
+ status = BAD_VALUE;
+ }
+
+ return status;
+
+}
+
+String8 AudioHardware::AudioStreamInALSA::getParameters(const String8& keys)
+{
+ AudioParameter param = AudioParameter(keys);
+ String8 value;
+ String8 key = String8(AudioParameter::keyRouting);
+
+ if (param.get(key, value) == NO_ERROR) {
+ param.addInt(key, (int)mDevices);
+ }
+
+ LOGV("AudioStreamInALSA::getParameters() %s", param.toString().string());
+ return param.toString();
+}
+
+status_t AudioHardware::AudioStreamInALSA::getNextBuffer(AudioHardware::BufferProvider::Buffer* buffer)
+{
+ if (mPcm == NULL) {
+ buffer->raw = NULL;
+ buffer->frameCount = 0;
+ mReadStatus = NO_INIT;
+ return NO_INIT;
+ }
+
+ if (mInPcmInBuf == 0) {
+ TRACE_DRIVER_IN(DRV_PCM_READ)
+ mReadStatus = pcm_read(mPcm,(void*) mPcmIn, AUDIO_HW_IN_PERIOD_SZ * frameSize());
+ TRACE_DRIVER_OUT
+ if (mReadStatus != 0) {
+ buffer->raw = NULL;
+ buffer->frameCount = 0;
+ return mReadStatus;
+ }
+ mInPcmInBuf = AUDIO_HW_IN_PERIOD_SZ;
+ }
+
+ buffer->frameCount = (buffer->frameCount > mInPcmInBuf) ? mInPcmInBuf : buffer->frameCount;
+ buffer->i16 = mPcmIn + (AUDIO_HW_IN_PERIOD_SZ - mInPcmInBuf) * mChannelCount;
+
+ return mReadStatus;
+}
+
+void AudioHardware::AudioStreamInALSA::releaseBuffer(Buffer* buffer)
+{
+ mInPcmInBuf -= buffer->frameCount;
+}
+
+size_t AudioHardware::AudioStreamInALSA::getBufferSize(uint32_t sampleRate, int channelCount)
+{
+ size_t ratio;
+
+ switch (sampleRate) {
+ case 8000:
+ case 11025:
+ ratio = 4;
+ break;
+ case 16000:
+ case 22050:
+ ratio = 2;
+ break;
+ case 44100:
+ default:
+ ratio = 1;
+ break;
+ }
+
+ return (AUDIO_HW_IN_PERIOD_SZ*channelCount*sizeof(int16_t)) / ratio ;
+}
+
+int AudioHardware::AudioStreamInALSA::prepareLock()
+{
+ // request sleep next time read() is called so that caller can acquire
+ // mLock
+ mSleepReq = true;
+ return mStandbyCnt;
+}
+
+void AudioHardware::AudioStreamInALSA::lock()
+{
+ mLock.lock();
+ mSleepReq = false;
+}
+
+void AudioHardware::AudioStreamInALSA::unlock() {
+ mLock.unlock();
+}
+
+//------------------------------------------------------------------------------
+// DownSampler
+//------------------------------------------------------------------------------
+
+/*
+ * 2.30 fixed point FIR filter coefficients for conversion 44100 -> 22050.
+ * (Works equivalently for 22010 -> 11025 or any other halving, of course.)
+ *
+ * Transition band from about 18 kHz, passband ripple < 0.1 dB,
+ * stopband ripple at about -55 dB, linear phase.
+ *
+ * Design and display in MATLAB or Octave using:
+ *
+ * filter = fir1(19, 0.5); filter = round(filter * 2**30); freqz(filter * 2**-30);
+ */
+static const int32_t filter_22khz_coeff[] = {
+ 2089257, 2898328, -5820678, -10484531,
+ 19038724, 30542725, -50469415, -81505260,
+ 152544464, 478517512, 478517512, 152544464,
+ -81505260, -50469415, 30542725, 19038724,
+ -10484531, -5820678, 2898328, 2089257,
+};
+#define NUM_COEFF_22KHZ (sizeof(filter_22khz_coeff) / sizeof(filter_22khz_coeff[0]))
+#define OVERLAP_22KHZ (NUM_COEFF_22KHZ - 2)
+
+/*
+ * Convolution of signals A and reverse(B). (In our case, the filter response
+ * is symmetric, so the reversing doesn't matter.)
+ * A is taken to be in 0.16 fixed-point, and B is taken to be in 2.30 fixed-point.
+ * The answer will be in 16.16 fixed-point, unclipped.
+ *
+ * This function would probably be the prime candidate for SIMD conversion if
+ * you want more speed.
+ */
+int32_t fir_convolve(const int16_t* a, const int32_t* b, int num_samples)
+{
+ int32_t sum = 1 << 13;
+ for (int i = 0; i < num_samples; ++i) {
+ sum += a[i] * (b[i] >> 16);
+ }
+ return sum >> 14;
+}
+
+/* Clip from 16.16 fixed-point to 0.16 fixed-point. */
+int16_t clip(int32_t x)
+{
+ if (x < -32768) {
+ return -32768;
+ } else if (x > 32767) {
+ return 32767;
+ } else {
+ return x;
+ }
+}
+
+/*
+ * Convert a chunk from 44 kHz to 22 kHz. Will update num_samples_in and num_samples_out
+ * accordingly, since it may leave input samples in the buffer due to overlap.
+ *
+ * Input and output are taken to be in 0.16 fixed-point.
+ */
+void resample_2_1(int16_t* input, int16_t* output, int* num_samples_in, int* num_samples_out)
+{
+ if (*num_samples_in < (int)NUM_COEFF_22KHZ) {
+ *num_samples_out = 0;
+ return;
+ }
+
+ int odd_smp = *num_samples_in & 0x1;
+ int num_samples = *num_samples_in - odd_smp - OVERLAP_22KHZ;
+
+ for (int i = 0; i < num_samples; i += 2) {
+ output[i / 2] = clip(fir_convolve(input + i, filter_22khz_coeff, NUM_COEFF_22KHZ));
+ }
+
+ memmove(input, input + num_samples, (OVERLAP_22KHZ + odd_smp) * sizeof(*input));
+ *num_samples_out = num_samples / 2;
+ *num_samples_in = OVERLAP_22KHZ + odd_smp;
+}
+
+/*
+ * 2.30 fixed point FIR filter coefficients for conversion 22050 -> 16000,
+ * or 11025 -> 8000.
+ *
+ * Transition band from about 14 kHz, passband ripple < 0.1 dB,
+ * stopband ripple at about -50 dB, linear phase.
+ *
+ * Design and display in MATLAB or Octave using:
+ *
+ * filter = fir1(23, 16000 / 22050); filter = round(filter * 2**30); freqz(filter * 2**-30);
+ */
+static const int32_t filter_16khz_coeff[] = {
+ 2057290, -2973608, 1880478, 4362037,
+ -14639744, 18523609, -1609189, -38502470,
+ 78073125, -68353935, -59103896, 617555440,
+ 617555440, -59103896, -68353935, 78073125,
+ -38502470, -1609189, 18523609, -14639744,
+ 4362037, 1880478, -2973608, 2057290,
+};
+#define NUM_COEFF_16KHZ (sizeof(filter_16khz_coeff) / sizeof(filter_16khz_coeff[0]))
+#define OVERLAP_16KHZ (NUM_COEFF_16KHZ - 1)
+
+/*
+ * Convert a chunk from 22 kHz to 16 kHz. Will update num_samples_in and
+ * num_samples_out accordingly, since it may leave input samples in the buffer
+ * due to overlap.
+ *
+ * This implementation is rather ad-hoc; it first low-pass filters the data
+ * into a temporary buffer, and then converts chunks of 441 input samples at a
+ * time into 320 output samples by simple linear interpolation. A better
+ * implementation would use a polyphase filter bank to do these two operations
+ * in one step.
+ *
+ * Input and output are taken to be in 0.16 fixed-point.
+ */
+
+#define RESAMPLE_16KHZ_SAMPLES_IN 441
+#define RESAMPLE_16KHZ_SAMPLES_OUT 320
+
+void resample_441_320(int16_t* input, int16_t* output, int* num_samples_in, int* num_samples_out)
+{
+ const int num_blocks = (*num_samples_in - OVERLAP_16KHZ) / RESAMPLE_16KHZ_SAMPLES_IN;
+ if (num_blocks < 1) {
+ *num_samples_out = 0;
+ return;
+ }
+
+ for (int i = 0; i < num_blocks; ++i) {
+ uint32_t tmp[RESAMPLE_16KHZ_SAMPLES_IN];
+ for (int j = 0; j < RESAMPLE_16KHZ_SAMPLES_IN; ++j) {
+ tmp[j] = fir_convolve(input + i * RESAMPLE_16KHZ_SAMPLES_IN + j,
+ filter_16khz_coeff,
+ NUM_COEFF_16KHZ);
+ }
+
+ const float step_float = (float)RESAMPLE_16KHZ_SAMPLES_IN / (float)RESAMPLE_16KHZ_SAMPLES_OUT;
+ const uint32_t step = (uint32_t)(step_float * 32768.0f + 0.5f); // 17.15 fixed point
+
+ uint32_t in_sample_num = 0; // 17.15 fixed point
+ for (int j = 0; j < RESAMPLE_16KHZ_SAMPLES_OUT; ++j, in_sample_num += step) {
+ const uint32_t whole = in_sample_num >> 15;
+ const uint32_t frac = (in_sample_num & 0x7fff); // 0.15 fixed point
+ const int32_t s1 = tmp[whole];
+ const int32_t s2 = tmp[whole + 1];
+ *output++ = clip(s1 + (((s2 - s1) * (int32_t)frac) >> 15));
+ }
+
+ }
+
+ const int samples_consumed = num_blocks * RESAMPLE_16KHZ_SAMPLES_IN;
+ memmove(input, input + samples_consumed, (*num_samples_in - samples_consumed) * sizeof(*input));
+ *num_samples_in -= samples_consumed;
+ *num_samples_out = RESAMPLE_16KHZ_SAMPLES_OUT * num_blocks;
+}
+
+
+AudioHardware::DownSampler::DownSampler(uint32_t outSampleRate,
+ uint32_t channelCount,
+ uint32_t frameCount,
+ AudioHardware::BufferProvider* provider)
+ : mStatus(NO_INIT), mProvider(provider), mSampleRate(outSampleRate),
+ mChannelCount(channelCount), mFrameCount(frameCount),
+ mInLeft(NULL), mInRight(NULL), mTmpLeft(NULL), mTmpRight(NULL),
+ mTmp2Left(NULL), mTmp2Right(NULL), mOutLeft(NULL), mOutRight(NULL)
+
+{
+ LOGV("AudioHardware::DownSampler() cstor %p SR %d channels %d frames %d",
+ this, mSampleRate, mChannelCount, mFrameCount);
+
+ if (mSampleRate != 8000 && mSampleRate != 11025 && mSampleRate != 16000 &&
+ mSampleRate != 22050) {
+ LOGW("AudioHardware::DownSampler cstor: bad sampling rate: %d", mSampleRate);
+ return;
+ }
+
+ mInLeft = new int16_t[mFrameCount];
+ mInRight = new int16_t[mFrameCount];
+ mTmpLeft = new int16_t[mFrameCount];
+ mTmpRight = new int16_t[mFrameCount];
+ mTmp2Left = new int16_t[mFrameCount];
+ mTmp2Right = new int16_t[mFrameCount];
+ mOutLeft = new int16_t[mFrameCount];
+ mOutRight = new int16_t[mFrameCount];
+
+ mStatus = NO_ERROR;
+}
+
+AudioHardware::DownSampler::~DownSampler()
+{
+ if (mInLeft) delete[] mInLeft;
+ if (mInRight) delete[] mInRight;
+ if (mTmpLeft) delete[] mTmpLeft;
+ if (mTmpRight) delete[] mTmpRight;
+ if (mTmp2Left) delete[] mTmp2Left;
+ if (mTmp2Right) delete[] mTmp2Right;
+ if (mOutLeft) delete[] mOutLeft;
+ if (mOutRight) delete[] mOutRight;
+}
+
+void AudioHardware::DownSampler::reset()
+{
+ mInInBuf = 0;
+ mInTmpBuf = 0;
+ mInTmp2Buf = 0;
+ mOutBufPos = 0;
+ mInOutBuf = 0;
+}
+
+
+int AudioHardware::DownSampler::resample(int16_t* out, size_t *outFrameCount)
+{
+ if (mStatus != NO_ERROR) {
+ return mStatus;
+ }
+
+ if (out == NULL || outFrameCount == NULL) {
+ return BAD_VALUE;
+ }
+
+ int16_t *outLeft = mTmp2Left;
+ int16_t *outRight = mTmp2Left;
+ if (mSampleRate == 22050) {
+ outLeft = mTmpLeft;
+ outRight = mTmpRight;
+ } else if (mSampleRate == 8000){
+ outLeft = mOutLeft;
+ outRight = mOutRight;
+ }
+
+ int outFrames = 0;
+ int remaingFrames = *outFrameCount;
+
+ if (mInOutBuf) {
+ int frames = (remaingFrames > mInOutBuf) ? mInOutBuf : remaingFrames;
+
+ for (int i = 0; i < frames; ++i) {
+ out[i] = outLeft[mOutBufPos + i];
+ }
+ if (mChannelCount == 2) {
+ for (int i = 0; i < frames; ++i) {
+ out[i * 2] = outLeft[mOutBufPos + i];
+ out[i * 2 + 1] = outRight[mOutBufPos + i];
+ }
+ }
+ remaingFrames -= frames;
+ mInOutBuf -= frames;
+ mOutBufPos += frames;
+ outFrames += frames;
+ }
+
+ while (remaingFrames) {
+ LOGW_IF((mInOutBuf != 0), "mInOutBuf should be 0 here");
+
+ AudioHardware::BufferProvider::Buffer buf;
+ buf.frameCount = mFrameCount - mInInBuf;
+ int ret = mProvider->getNextBuffer(&buf);
+ if (buf.raw == NULL) {
+ *outFrameCount = outFrames;
+ return ret;
+ }
+
+ for (size_t i = 0; i < buf.frameCount; ++i) {
+ mInLeft[i + mInInBuf] = buf.i16[i];
+ }
+ if (mChannelCount == 2) {
+ for (size_t i = 0; i < buf.frameCount; ++i) {
+ mInLeft[i + mInInBuf] = buf.i16[i * 2];
+ mInRight[i + mInInBuf] = buf.i16[i * 2 + 1];
+ }
+ }
+ mInInBuf += buf.frameCount;
+ mProvider->releaseBuffer(&buf);
+
+ /* 44010 -> 22050 */
+ {
+ int samples_in_left = mInInBuf;
+ int samples_out_left;
+ resample_2_1(mInLeft, mTmpLeft + mInTmpBuf, &samples_in_left, &samples_out_left);
+
+ if (mChannelCount == 2) {
+ int samples_in_right = mInInBuf;
+ int samples_out_right;
+ resample_2_1(mInRight, mTmpRight + mInTmpBuf, &samples_in_right, &samples_out_right);
+ }
+
+ mInInBuf = samples_in_left;
+ mInTmpBuf += samples_out_left;
+ mInOutBuf = samples_out_left;
+ }
+
+ if (mSampleRate == 11025 || mSampleRate == 8000) {
+ /* 22050 - > 11025 */
+ int samples_in_left = mInTmpBuf;
+ int samples_out_left;
+ resample_2_1(mTmpLeft, mTmp2Left + mInTmp2Buf, &samples_in_left, &samples_out_left);
+
+ if (mChannelCount == 2) {
+ int samples_in_right = mInTmpBuf;
+ int samples_out_right;
+ resample_2_1(mTmpRight, mTmp2Right + mInTmp2Buf, &samples_in_right, &samples_out_right);
+ }
+
+
+ mInTmpBuf = samples_in_left;
+ mInTmp2Buf += samples_out_left;
+ mInOutBuf = samples_out_left;
+
+ if (mSampleRate == 8000) {
+ /* 11025 -> 8000*/
+ int samples_in_left = mInTmp2Buf;
+ int samples_out_left;
+ resample_441_320(mTmp2Left, mOutLeft, &samples_in_left, &samples_out_left);
+
+ if (mChannelCount == 2) {
+ int samples_in_right = mInTmp2Buf;
+ int samples_out_right;
+ resample_441_320(mTmp2Right, mOutRight, &samples_in_right, &samples_out_right);
+ }
+
+ mInTmp2Buf = samples_in_left;
+ mInOutBuf = samples_out_left;
+ } else {
+ mInTmp2Buf = 0;
+ }
+
+ } else if (mSampleRate == 16000) {
+ /* 22050 -> 16000*/
+ int samples_in_left = mInTmpBuf;
+ int samples_out_left;
+ resample_441_320(mTmpLeft, mTmp2Left, &samples_in_left, &samples_out_left);
+
+ if (mChannelCount == 2) {
+ int samples_in_right = mInTmpBuf;
+ int samples_out_right;
+ resample_441_320(mTmpRight, mTmp2Right, &samples_in_right, &samples_out_right);
+ }
+
+ mInTmpBuf = samples_in_left;
+ mInOutBuf = samples_out_left;
+ } else {
+ mInTmpBuf = 0;
+ }
+
+ int frames = (remaingFrames > mInOutBuf) ? mInOutBuf : remaingFrames;
+
+ for (int i = 0; i < frames; ++i) {
+ out[outFrames + i] = outLeft[i];
+ }
+ if (mChannelCount == 2) {
+ for (int i = 0; i < frames; ++i) {
+ out[(outFrames + i) * 2] = outLeft[i];
+ out[(outFrames + i) * 2 + 1] = outRight[i];
+ }
+ }
+ remaingFrames -= frames;
+ outFrames += frames;
+ mOutBufPos = frames;
+ mInOutBuf -= frames;
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
+//------------------------------------------------------------------------------
+// Factory
+//------------------------------------------------------------------------------
+
+extern "C" AudioHardwareInterface* createAudioHardware(void) {
+ return new AudioHardware();
+}
+
+}; // namespace android_audio_legacy
diff --git a/libaudio/AudioHardware.h b/libaudio/AudioHardware.h
new file mode 100644
index 0000000..f77028c
--- /dev/null
+++ b/libaudio/AudioHardware.h
@@ -0,0 +1,357 @@
+/*
+** Copyright 2008, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_AUDIO_HARDWARE_H
+#define ANDROID_AUDIO_HARDWARE_H
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+extern "C" {
+ struct pcm;
+ struct mixer;
+ struct mixer_ctl;
+};
+
+namespace android_audio_legacy {
+
+using namespace android;
+
+// TODO: determine actual audio DSP and hardware latency
+// Additionnal latency introduced by audio DSP and hardware in ms
+#define AUDIO_HW_OUT_LATENCY_MS 0
+// Default audio output sample rate
+#define AUDIO_HW_OUT_SAMPLERATE 44100
+// Default audio output channel mask
+#define AUDIO_HW_OUT_CHANNELS (AudioSystem::CHANNEL_OUT_STEREO)
+// Default audio output sample format
+#define AUDIO_HW_OUT_FORMAT (AudioSystem::PCM_16_BIT)
+// Kernel pcm out buffer size in frames at 44.1kHz
+#define AUDIO_HW_OUT_PERIOD_MULT 8 // (8 * 128 = 1024 frames)
+#define AUDIO_HW_OUT_PERIOD_SZ (PCM_PERIOD_SZ_MIN * AUDIO_HW_OUT_PERIOD_MULT)
+#define AUDIO_HW_OUT_PERIOD_CNT 4
+// Default audio output buffer size in bytes
+#define AUDIO_HW_OUT_PERIOD_BYTES (AUDIO_HW_OUT_PERIOD_SZ * 2 * sizeof(int16_t))
+
+// Default audio input sample rate
+#define AUDIO_HW_IN_SAMPLERATE 8000
+// Default audio input channel mask
+#define AUDIO_HW_IN_CHANNELS (AudioSystem::CHANNEL_IN_MONO)
+// Default audio input sample format
+#define AUDIO_HW_IN_FORMAT (AudioSystem::PCM_16_BIT)
+// Number of buffers in audio driver for input
+#define AUDIO_HW_NUM_IN_BUF 2
+// Kernel pcm in buffer size in frames at 44.1kHz (before resampling)
+#define AUDIO_HW_IN_PERIOD_MULT 16 // (16 * 128 = 2048 frames)
+#define AUDIO_HW_IN_PERIOD_SZ (PCM_PERIOD_SZ_MIN * AUDIO_HW_IN_PERIOD_MULT)
+#define AUDIO_HW_IN_PERIOD_CNT 2
+// Default audio input buffer size in bytes (8kHz mono)
+#define AUDIO_HW_IN_PERIOD_BYTES ((AUDIO_HW_IN_PERIOD_SZ*sizeof(int16_t))/8)
+
+
+class AudioHardware : public AudioHardwareBase
+{
+ class AudioStreamOutALSA;
+ class AudioStreamInALSA;
+public:
+
+ // input path names used to translate from input sources to driver paths
+ static const char *inputPathNameDefault;
+ static const char *inputPathNameCamcorder;
+ static const char *inputPathNameVoiceRecognition;
+ static const char *inputPathNameVoiceCommunication;
+
+ AudioHardware();
+ virtual ~AudioHardware();
+ virtual status_t initCheck();
+
+ virtual status_t setVoiceVolume(float volume);
+ virtual status_t setMasterVolume(float volume);
+
+ virtual status_t setMode(int mode);
+
+ virtual status_t setMicMute(bool state);
+ virtual status_t getMicMute(bool* state);
+
+ virtual status_t setParameters(const String8& keyValuePairs);
+ virtual String8 getParameters(const String8& keys);
+
+ virtual AudioStreamOut* openOutputStream(
+ uint32_t devices, int *format=0, uint32_t *channels=0,
+ uint32_t *sampleRate=0, status_t *status=0);
+
+ virtual AudioStreamIn* openInputStream(
+ uint32_t devices, int *format, uint32_t *channels,
+ uint32_t *sampleRate, status_t *status,
+ AudioSystem::audio_in_acoustics acoustics);
+
+ virtual void closeOutputStream(AudioStreamOut* out);
+ virtual void closeInputStream(AudioStreamIn* in);
+
+ virtual size_t getInputBufferSize(
+ uint32_t sampleRate, int format, int channelCount);
+
+ int mode() { return mMode; }
+ const char *getOutputRouteFromDevice(uint32_t device);
+ const char *getInputRouteFromDevice(uint32_t device);
+ const char *getVoiceRouteFromDevice(uint32_t device);
+
+ status_t setIncallPath_l(uint32_t device);
+
+ status_t setInputSource_l(audio_source source);
+
+ static uint32_t getInputSampleRate(uint32_t sampleRate);
+ sp getActiveInput_l();
+
+ Mutex& lock() { return mLock; }
+
+ struct pcm *openPcmOut_l();
+ void closePcmOut_l();
+
+ struct mixer *openMixer_l();
+ void closeMixer_l();
+
+ sp output() { return mOutput; }
+
+protected:
+ virtual status_t dump(int fd, const Vector& args);
+
+private:
+
+ enum tty_modes {
+ TTY_MODE_OFF,
+ TTY_MODE_VCO,
+ TTY_MODE_HCO,
+ TTY_MODE_FULL
+ };
+
+ bool mInit;
+ bool mMicMute;
+ sp mOutput;
+ SortedVector < sp > mInputs;
+ Mutex mLock;
+ struct pcm* mPcm;
+ struct mixer* mMixer;
+ uint32_t mPcmOpenCnt;
+ uint32_t mMixerOpenCnt;
+ bool mInCallAudioMode;
+
+ audio_source mInputSource;
+ bool mBluetoothNrec;
+ int mTTYMode;
+
+ // trace driver operations for dump
+ int mDriverOp;
+
+ static uint32_t checkInputSampleRate(uint32_t sampleRate);
+ static const uint32_t inputSamplingRates[];
+
+ class AudioStreamOutALSA : public AudioStreamOut, public RefBase
+ {
+ public:
+ AudioStreamOutALSA();
+ virtual ~AudioStreamOutALSA();
+ status_t set(AudioHardware* mHardware,
+ uint32_t devices,
+ int *pFormat,
+ uint32_t *pChannels,
+ uint32_t *pRate);
+ virtual uint32_t sampleRate()
+ const { return mSampleRate; }
+ virtual size_t bufferSize()
+ const { return mBufferSize; }
+ virtual uint32_t channels()
+ const { return mChannels; }
+ virtual int format()
+ const { return AUDIO_HW_OUT_FORMAT; }
+ virtual uint32_t latency()
+ const { return (1000 * AUDIO_HW_OUT_PERIOD_CNT *
+ (bufferSize()/frameSize()))/sampleRate() +
+ AUDIO_HW_OUT_LATENCY_MS; }
+ virtual status_t setVolume(float left, float right)
+ { return INVALID_OPERATION; }
+ virtual ssize_t write(const void* buffer, size_t bytes);
+ virtual status_t standby();
+ bool checkStandby();
+
+ virtual status_t dump(int fd, const Vector& args);
+ virtual status_t setParameters(const String8& keyValuePairs);
+ virtual String8 getParameters(const String8& keys);
+ uint32_t device() { return mDevices; }
+ virtual status_t getRenderPosition(uint32_t *dspFrames);
+
+ void doStandby_l();
+ void close_l();
+ status_t open_l();
+ int standbyCnt() { return mStandbyCnt; }
+
+ int prepareLock();
+ void lock();
+ void unlock();
+
+ private:
+
+ Mutex mLock;
+ AudioHardware* mHardware;
+ struct pcm *mPcm;
+ struct mixer *mMixer;
+ struct mixer_ctl *mRouteCtl;
+ const char *next_route;
+ bool mStandby;
+ uint32_t mDevices;
+ uint32_t mChannels;
+ uint32_t mSampleRate;
+ size_t mBufferSize;
+ // trace driver operations for dump
+ int mDriverOp;
+ int mStandbyCnt;
+ bool mSleepReq;
+ };
+
+ class DownSampler;
+
+ class BufferProvider
+ {
+ public:
+
+ struct Buffer {
+ union {
+ void* raw;
+ short* i16;
+ int8_t* i8;
+ };
+ size_t frameCount;
+ };
+
+ virtual ~BufferProvider() {}
+
+ virtual status_t getNextBuffer(Buffer* buffer) = 0;
+ virtual void releaseBuffer(Buffer* buffer) = 0;
+ };
+
+ class DownSampler {
+ public:
+ DownSampler(uint32_t outSampleRate,
+ uint32_t channelCount,
+ uint32_t frameCount,
+ BufferProvider* provider);
+
+ virtual ~DownSampler();
+
+ void reset();
+ status_t initCheck() { return mStatus; }
+ int resample(int16_t* out, size_t *outFrameCount);
+
+ private:
+ status_t mStatus;
+ BufferProvider* mProvider;
+ uint32_t mSampleRate;
+ uint32_t mChannelCount;
+ uint32_t mFrameCount;
+ int16_t *mInLeft;
+ int16_t *mInRight;
+ int16_t *mTmpLeft;
+ int16_t *mTmpRight;
+ int16_t *mTmp2Left;
+ int16_t *mTmp2Right;
+ int16_t *mOutLeft;
+ int16_t *mOutRight;
+ int mInInBuf;
+ int mInTmpBuf;
+ int mInTmp2Buf;
+ int mOutBufPos;
+ int mInOutBuf;
+ };
+
+
+ class AudioStreamInALSA : public AudioStreamIn, public BufferProvider, public RefBase
+ {
+
+ public:
+ AudioStreamInALSA();
+ virtual ~AudioStreamInALSA();
+ status_t set(AudioHardware* hw,
+ uint32_t devices,
+ int *pFormat,
+ uint32_t *pChannels,
+ uint32_t *pRate,
+ AudioSystem::audio_in_acoustics acoustics);
+ virtual size_t bufferSize() const { return mBufferSize; }
+ virtual uint32_t channels() const { return mChannels; }
+ virtual int format() const { return AUDIO_HW_IN_FORMAT; }
+ virtual uint32_t sampleRate() const { return mSampleRate; }
+ virtual status_t setGain(float gain) { return INVALID_OPERATION; }
+ virtual ssize_t read(void* buffer, ssize_t bytes);
+ virtual status_t dump(int fd, const Vector& args);
+ virtual status_t standby();
+ bool checkStandby();
+ virtual status_t setParameters(const String8& keyValuePairs);
+ virtual String8 getParameters(const String8& keys);
+ virtual unsigned int getInputFramesLost() const { return 0; }
+ uint32_t device() { return mDevices; }
+ void doStandby_l();
+ void close_l();
+ status_t open_l();
+ int standbyCnt() { return mStandbyCnt; }
+
+ static size_t getBufferSize(uint32_t sampleRate, int channelCount);
+
+ // BufferProvider
+ virtual status_t getNextBuffer(BufferProvider::Buffer* buffer);
+ virtual void releaseBuffer(BufferProvider::Buffer* buffer);
+
+ // Stubs (ICS)
+ virtual status_t addAudioEffect(effect_handle_t effect) { return INVALID_OPERATION; }
+ virtual status_t removeAudioEffect(effect_handle_t effect) { return INVALID_OPERATION; }
+
+ int prepareLock();
+ void lock();
+ void unlock();
+
+ private:
+ Mutex mLock;
+ AudioHardware* mHardware;
+ struct pcm *mPcm;
+ struct mixer *mMixer;
+ struct mixer_ctl *mRouteCtl;
+ const char *next_route;
+ bool mStandby;
+ uint32_t mDevices;
+ uint32_t mChannels;
+ uint32_t mChannelCount;
+ uint32_t mSampleRate;
+ size_t mBufferSize;
+ DownSampler *mDownSampler;
+ status_t mReadStatus;
+ size_t mInPcmInBuf;
+ int16_t *mPcmIn;
+ // trace driver operations for dump
+ int mDriverOp;
+ int mStandbyCnt;
+ bool mSleepReq;
+ };
+
+};
+
+}; // namespace android_audio_legacy
+
+#endif
diff --git a/libaudio/AudioPolicyManager.cpp b/libaudio/AudioPolicyManager.cpp
new file mode 100644
index 0000000..7557400
--- /dev/null
+++ b/libaudio/AudioPolicyManager.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioPolicyManager"
+#define LOG_NDEBUG 0
+#include
+#include "AudioPolicyManager.h"
+#include
+
+namespace android_audio_legacy {
+
+
+
+// ----------------------------------------------------------------------------
+// AudioPolicyManager for crespo platform
+// Common audio policy manager code is implemented in AudioPolicyManagerBase class
+// ----------------------------------------------------------------------------
+
+// --- class factory
+
+
+extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
+{
+ return new AudioPolicyManager(clientInterface);
+}
+
+extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
+{
+ delete interface;
+}
+
+
+}; // namespace android_audio_legacy
diff --git a/libaudio/AudioPolicyManager.h b/libaudio/AudioPolicyManager.h
new file mode 100644
index 0000000..d660e78
--- /dev/null
+++ b/libaudio/AudioPolicyManager.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+namespace android_audio_legacy {
+
+class AudioPolicyManager: public AudioPolicyManagerBase
+{
+
+public:
+ AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
+ : AudioPolicyManagerBase(clientInterface) {}
+
+ virtual ~AudioPolicyManager() {}
+
+protected:
+ // true is current platform implements a back microphone
+ virtual bool hasBackMicrophone() const { return false; }
+#ifdef WITH_A2DP
+ // true is current platform supports duplication of notifications and ringtones over A2DP output
+ virtual bool a2dpUsedForSonification() const { return true; }
+#endif
+
+};
+};
diff --git a/libaudio/alsa_audio.h b/libaudio/alsa_audio.h
new file mode 100644
index 0000000..3cb86d9
--- /dev/null
+++ b/libaudio/alsa_audio.h
@@ -0,0 +1,77 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef _AUDIO_H_
+#define _AUDIO_H_
+
+struct pcm;
+
+#define PCM_OUT 0x00000000
+#define PCM_IN 0x10000000
+
+#define PCM_STEREO 0x00000000
+#define PCM_MONO 0x01000000
+
+#define PCM_44100HZ 0x00000000
+#define PCM_48000HZ 0x00100000
+#define PCM_8000HZ 0x00200000
+#define PCM_RATE_MASK 0x00F00000
+
+#define PCM_PERIOD_CNT_MIN 2
+#define PCM_PERIOD_CNT_SHIFT 16
+#define PCM_PERIOD_CNT_MASK (0xF << PCM_PERIOD_CNT_SHIFT)
+#define PCM_PERIOD_SZ_MIN 128
+#define PCM_PERIOD_SZ_SHIFT 12
+#define PCM_PERIOD_SZ_MASK (0xF << PCM_PERIOD_SZ_SHIFT)
+
+/* Acquire/release a pcm channel.
+ * Returns non-zero on error
+ */
+struct pcm *pcm_open(unsigned flags);
+int pcm_close(struct pcm *pcm);
+int pcm_ready(struct pcm *pcm);
+
+/* Returns a human readable reason for the last error. */
+const char *pcm_error(struct pcm *pcm);
+
+/* Returns the buffer size (int bytes) that should be used for pcm_write.
+ * This will be 1/2 of the actual fifo size.
+ */
+unsigned pcm_buffer_size(struct pcm *pcm);
+
+/* Write data to the fifo.
+ * Will start playback on the first write or on a write that
+ * occurs after a fifo underrun.
+ */
+int pcm_write(struct pcm *pcm, void *data, unsigned count);
+int pcm_read(struct pcm *pcm, void *data, unsigned count);
+
+struct mixer;
+struct mixer_ctl;
+
+struct mixer *mixer_open(void);
+void mixer_close(struct mixer *mixer);
+void mixer_dump(struct mixer *mixer);
+
+struct mixer_ctl *mixer_get_control(struct mixer *mixer,
+ const char *name, unsigned index);
+struct mixer_ctl *mixer_get_nth_control(struct mixer *mixer, unsigned n);
+
+int mixer_ctl_set(struct mixer_ctl *ctl, unsigned percent);
+int mixer_ctl_select(struct mixer_ctl *ctl, const char *value);
+void mixer_ctl_print(struct mixer_ctl *ctl);
+
+#endif
diff --git a/libaudio/alsa_mixer.c b/libaudio/alsa_mixer.c
new file mode 100644
index 0000000..3036ef8
--- /dev/null
+++ b/libaudio/alsa_mixer.c
@@ -0,0 +1,371 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#define __force
+#define __bitwise
+#define __user
+#include "asound.h"
+
+#include "alsa_audio.h"
+
+static const char *elem_iface_name(snd_ctl_elem_iface_t n)
+{
+ switch (n) {
+ case SNDRV_CTL_ELEM_IFACE_CARD: return "CARD";
+ case SNDRV_CTL_ELEM_IFACE_HWDEP: return "HWDEP";
+ case SNDRV_CTL_ELEM_IFACE_MIXER: return "MIXER";
+ case SNDRV_CTL_ELEM_IFACE_PCM: return "PCM";
+ case SNDRV_CTL_ELEM_IFACE_RAWMIDI: return "MIDI";
+ case SNDRV_CTL_ELEM_IFACE_TIMER: return "TIMER";
+ case SNDRV_CTL_ELEM_IFACE_SEQUENCER: return "SEQ";
+ default: return "???";
+ }
+}
+
+static const char *elem_type_name(snd_ctl_elem_type_t n)
+{
+ switch (n) {
+ case SNDRV_CTL_ELEM_TYPE_NONE: return "NONE";
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return "BOOL";
+ case SNDRV_CTL_ELEM_TYPE_INTEGER: return "INT32";
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return "ENUM";
+ case SNDRV_CTL_ELEM_TYPE_BYTES: return "BYTES";
+ case SNDRV_CTL_ELEM_TYPE_IEC958: return "IEC958";
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64: return "INT64";
+ default: return "???";
+ }
+}
+
+
+struct mixer_ctl {
+ struct mixer *mixer;
+ struct snd_ctl_elem_info *info;
+ char **ename;
+};
+
+struct mixer {
+ int fd;
+ struct snd_ctl_elem_info *info;
+ struct mixer_ctl *ctl;
+ unsigned count;
+};
+
+void mixer_close(struct mixer *mixer)
+{
+ unsigned n,m;
+
+ if (mixer->fd >= 0)
+ close(mixer->fd);
+
+ if (mixer->ctl) {
+ for (n = 0; n < mixer->count; n++) {
+ if (mixer->ctl[n].ename) {
+ unsigned max = mixer->ctl[n].info->value.enumerated.items;
+ for (m = 0; m < max; m++)
+ free(mixer->ctl[n].ename[m]);
+ free(mixer->ctl[n].ename);
+ }
+ }
+ free(mixer->ctl);
+ }
+
+ if (mixer->info)
+ free(mixer->info);
+
+ free(mixer);
+}
+
+struct mixer *mixer_open(void)
+{
+ struct snd_ctl_elem_list elist;
+ struct snd_ctl_elem_info tmp;
+ struct snd_ctl_elem_id *eid = NULL;
+ struct mixer *mixer = NULL;
+ unsigned n, m;
+ int fd;
+
+ fd = open("/dev/snd/controlC0", O_RDWR);
+ if (fd < 0)
+ return 0;
+
+ memset(&elist, 0, sizeof(elist));
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
+ goto fail;
+
+ mixer = calloc(1, sizeof(*mixer));
+ if (!mixer)
+ goto fail;
+
+ mixer->ctl = calloc(elist.count, sizeof(struct mixer_ctl));
+ mixer->info = calloc(elist.count, sizeof(struct snd_ctl_elem_info));
+ if (!mixer->ctl || !mixer->info)
+ goto fail;
+
+ eid = calloc(elist.count, sizeof(struct snd_ctl_elem_id));
+ if (!eid)
+ goto fail;
+
+ mixer->count = elist.count;
+ mixer->fd = fd;
+ elist.space = mixer->count;
+ elist.pids = eid;
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
+ goto fail;
+
+ for (n = 0; n < mixer->count; n++) {
+ struct snd_ctl_elem_info *ei = mixer->info + n;
+ ei->id.numid = eid[n].numid;
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, ei) < 0)
+ goto fail;
+ mixer->ctl[n].info = ei;
+ mixer->ctl[n].mixer = mixer;
+ if (ei->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
+ char **enames = calloc(ei->value.enumerated.items, sizeof(char*));
+ if (!enames)
+ goto fail;
+ mixer->ctl[n].ename = enames;
+ for (m = 0; m < ei->value.enumerated.items; m++) {
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.id.numid = ei->id.numid;
+ tmp.value.enumerated.item = m;
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
+ goto fail;
+ enames[m] = strdup(tmp.value.enumerated.name);
+ if (!enames[m])
+ goto fail;
+ }
+ }
+ }
+
+ free(eid);
+ return mixer;
+
+fail:
+ if (eid)
+ free(eid);
+ if (mixer)
+ mixer_close(mixer);
+ else if (fd >= 0)
+ close(fd);
+ return 0;
+}
+
+void mixer_dump(struct mixer *mixer)
+{
+ unsigned n, m;
+
+ printf(" id iface dev sub idx num perms type name\n");
+ for (n = 0; n < mixer->count; n++) {
+ struct snd_ctl_elem_info *ei = mixer->info + n;
+
+ printf("%4d %5s %3d %3d %3d %3d %c%c%c%c%c%c%c%c%c %-6s %s",
+ ei->id.numid, elem_iface_name(ei->id.iface),
+ ei->id.device, ei->id.subdevice, ei->id.index,
+ ei->count,
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_READ) ? 'r' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ? 'w' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_VOLATILE) ? 'V' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TIMESTAMP) ? 'T' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) ? 'R' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) ? 'W' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) ? 'C' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) ? 'I' : ' ',
+ (ei->access & SNDRV_CTL_ELEM_ACCESS_LOCK) ? 'L' : ' ',
+ elem_type_name(ei->type),
+ ei->id.name);
+ switch (ei->type) {
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ printf(ei->value.integer.step ?
+ " { %ld-%ld, %ld }\n" : " { %ld-%ld }",
+ ei->value.integer.min,
+ ei->value.integer.max,
+ ei->value.integer.step);
+ break;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+ printf(ei->value.integer64.step ?
+ " { %lld-%lld, %lld }\n" : " { %lld-%lld }",
+ ei->value.integer64.min,
+ ei->value.integer64.max,
+ ei->value.integer64.step);
+ break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED: {
+ unsigned m;
+ printf(" { %s=0", mixer->ctl[n].ename[0]);
+ for (m = 1; m < ei->value.enumerated.items; m++)
+ printf(", %s=%d", mixer->ctl[n].ename[m],m);
+ printf(" }");
+ break;
+ }
+ }
+ printf("\n");
+ }
+}
+
+struct mixer_ctl *mixer_get_control(struct mixer *mixer,
+ const char *name, unsigned index)
+{
+ unsigned n;
+ for (n = 0; n < mixer->count; n++) {
+ if (mixer->info[n].id.index == index) {
+ if (!strcmp(name, (char*) mixer->info[n].id.name)) {
+ return mixer->ctl + n;
+ }
+ }
+ }
+ return 0;
+}
+
+struct mixer_ctl *mixer_get_nth_control(struct mixer *mixer, unsigned n)
+{
+ if (n < mixer->count)
+ return mixer->ctl + n;
+ return 0;
+}
+
+void mixer_ctl_print(struct mixer_ctl *ctl)
+{
+ struct snd_ctl_elem_value ev;
+ unsigned n;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.id.numid = ctl->info->id.numid;
+ if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev))
+ return;
+ printf("%s:", ctl->info->id.name);
+
+ switch (ctl->info->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ for (n = 0; n < ctl->info->count; n++)
+ printf(" %s", ev.value.integer.value[n] ? "ON" : "OFF");
+ break;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER: {
+ for (n = 0; n < ctl->info->count; n++)
+ printf(" %ld", ev.value.integer.value[n]);
+ break;
+ }
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+ for (n = 0; n < ctl->info->count; n++)
+ printf(" %lld", ev.value.integer64.value[n]);
+ break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ for (n = 0; n < ctl->info->count; n++) {
+ unsigned v = ev.value.enumerated.item[n];
+ printf(" %d (%s)", v,
+ (v < ctl->info->value.enumerated.items) ? ctl->ename[v] : "???");
+ }
+ break;
+ default:
+ printf(" ???");
+ }
+ printf("\n");
+}
+
+static long scale_int(struct snd_ctl_elem_info *ei, unsigned _percent)
+{
+ long percent;
+ long range;
+
+ if (_percent > 100)
+ percent = 100;
+ else
+ percent = (long) _percent;
+
+ range = (ei->value.integer.max - ei->value.integer.min);
+
+ return ei->value.integer.min + (range * percent) / 100LL;
+}
+
+static long long scale_int64(struct snd_ctl_elem_info *ei, unsigned _percent)
+{
+ long long percent;
+ long long range;
+
+ if (_percent > 100)
+ percent = 100;
+ else
+ percent = (long) _percent;
+
+ range = (ei->value.integer.max - ei->value.integer.min) * 100LL;
+
+ return ei->value.integer.min + (range / percent);
+}
+
+int mixer_ctl_set(struct mixer_ctl *ctl, unsigned percent)
+{
+ struct snd_ctl_elem_value ev;
+ unsigned n;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.id.numid = ctl->info->id.numid;
+ switch (ctl->info->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ for (n = 0; n < ctl->info->count; n++)
+ ev.value.integer.value[n] = !!percent;
+ break;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER: {
+ long value = scale_int(ctl->info, percent);
+ for (n = 0; n < ctl->info->count; n++)
+ ev.value.integer.value[n] = value;
+ break;
+ }
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64: {
+ long long value = scale_int64(ctl->info, percent);
+ for (n = 0; n < ctl->info->count; n++)
+ ev.value.integer64.value[n] = value;
+ break;
+ }
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
+}
+
+int mixer_ctl_select(struct mixer_ctl *ctl, const char *value)
+{
+ unsigned n, max;
+ struct snd_ctl_elem_value ev;
+
+ if (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ max = ctl->info->value.enumerated.items;
+ for (n = 0; n < max; n++) {
+ if (!strcmp(value, ctl->ename[n])) {
+ memset(&ev, 0, sizeof(ev));
+ ev.value.enumerated.item[0] = n;
+ ev.id.numid = ctl->info->id.numid;
+ if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev) < 0)
+ return -1;
+ return 0;
+ }
+ }
+
+ errno = EINVAL;
+ return -1;
+}
diff --git a/libaudio/alsa_pcm.c b/libaudio/alsa_pcm.c
new file mode 100644
index 0000000..7f9cdc0
--- /dev/null
+++ b/libaudio/alsa_pcm.c
@@ -0,0 +1,405 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "alsa_pcm"
+#define LOG_NDEBUG 0
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include "alsa_audio.h"
+
+#define __force
+#define __bitwise
+#define __user
+#include "asound.h"
+
+#define DEBUG 0
+
+/* alsa parameter manipulation cruft */
+
+#define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL
+
+static inline int param_is_mask(int p)
+{
+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
+ (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
+}
+
+static inline int param_is_interval(int p)
+{
+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) &&
+ (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL);
+}
+
+static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n)
+{
+ return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]);
+}
+
+static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
+{
+ return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
+}
+
+static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit)
+{
+ if (bit >= SNDRV_MASK_MAX)
+ return;
+ if (param_is_mask(n)) {
+ struct snd_mask *m = param_to_mask(p, n);
+ m->bits[0] = 0;
+ m->bits[1] = 0;
+ m->bits[bit >> 5] |= (1 << (bit & 31));
+ }
+}
+
+static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned val)
+{
+ if (param_is_interval(n)) {
+ struct snd_interval *i = param_to_interval(p, n);
+ i->min = val;
+ }
+}
+
+static void param_set_max(struct snd_pcm_hw_params *p, int n, unsigned val)
+{
+ if (param_is_interval(n)) {
+ struct snd_interval *i = param_to_interval(p, n);
+ i->max = val;
+ }
+}
+
+static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned val)
+{
+ if (param_is_interval(n)) {
+ struct snd_interval *i = param_to_interval(p, n);
+ i->min = val;
+ i->max = val;
+ i->integer = 1;
+ }
+}
+
+static void param_init(struct snd_pcm_hw_params *p)
+{
+ int n;
+ memset(p, 0, sizeof(*p));
+ for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
+ n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
+ struct snd_mask *m = param_to_mask(p, n);
+ m->bits[0] = ~0;
+ m->bits[1] = ~0;
+ }
+ for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
+ n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
+ struct snd_interval *i = param_to_interval(p, n);
+ i->min = 0;
+ i->max = ~0;
+ }
+}
+
+/* debugging gunk */
+
+#if DEBUG
+static const char *param_name[PARAM_MAX+1] = {
+ [SNDRV_PCM_HW_PARAM_ACCESS] = "access",
+ [SNDRV_PCM_HW_PARAM_FORMAT] = "format",
+ [SNDRV_PCM_HW_PARAM_SUBFORMAT] = "subformat",
+
+ [SNDRV_PCM_HW_PARAM_SAMPLE_BITS] = "sample_bits",
+ [SNDRV_PCM_HW_PARAM_FRAME_BITS] = "frame_bits",
+ [SNDRV_PCM_HW_PARAM_CHANNELS] = "channels",
+ [SNDRV_PCM_HW_PARAM_RATE] = "rate",
+ [SNDRV_PCM_HW_PARAM_PERIOD_TIME] = "period_time",
+ [SNDRV_PCM_HW_PARAM_PERIOD_SIZE] = "period_size",
+ [SNDRV_PCM_HW_PARAM_PERIOD_BYTES] = "period_bytes",
+ [SNDRV_PCM_HW_PARAM_PERIODS] = "periods",
+ [SNDRV_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time",
+ [SNDRV_PCM_HW_PARAM_BUFFER_SIZE] = "buffer_size",
+ [SNDRV_PCM_HW_PARAM_BUFFER_BYTES] = "buffer_bytes",
+ [SNDRV_PCM_HW_PARAM_TICK_TIME] = "tick_time",
+};
+
+static void param_dump(struct snd_pcm_hw_params *p)
+{
+ int n;
+
+ for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
+ n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
+ struct snd_mask *m = param_to_mask(p, n);
+ LOGV("%s = %08x%08x\n", param_name[n],
+ m->bits[1], m->bits[0]);
+ }
+ for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
+ n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
+ struct snd_interval *i = param_to_interval(p, n);
+ LOGV("%s = (%d,%d) omin=%d omax=%d int=%d empty=%d\n",
+ param_name[n], i->min, i->max, i->openmin,
+ i->openmax, i->integer, i->empty);
+ }
+ LOGV("info = %08x\n", p->info);
+ LOGV("msbits = %d\n", p->msbits);
+ LOGV("rate = %d/%d\n", p->rate_num, p->rate_den);
+ LOGV("fifo = %d\n", (int) p->fifo_size);
+}
+
+static void info_dump(struct snd_pcm_info *info)
+{
+ LOGV("device = %d\n", info->device);
+ LOGV("subdevice = %d\n", info->subdevice);
+ LOGV("stream = %d\n", info->stream);
+ LOGV("card = %d\n", info->card);
+ LOGV("id = '%s'\n", info->id);
+ LOGV("name = '%s'\n", info->name);
+ LOGV("subname = '%s'\n", info->subname);
+ LOGV("dev_class = %d\n", info->dev_class);
+ LOGV("dev_subclass = %d\n", info->dev_subclass);
+ LOGV("subdevices_count = %d\n", info->subdevices_count);
+ LOGV("subdevices_avail = %d\n", info->subdevices_avail);
+}
+#else
+static void param_dump(struct snd_pcm_hw_params *p) {}
+static void info_dump(struct snd_pcm_info *info) {}
+#endif
+
+#define PCM_ERROR_MAX 128
+
+struct pcm {
+ int fd;
+ unsigned flags;
+ int running:1;
+ int underruns;
+ unsigned buffer_size;
+ char error[PCM_ERROR_MAX];
+};
+
+unsigned pcm_buffer_size(struct pcm *pcm)
+{
+ return pcm->buffer_size;
+}
+
+const char* pcm_error(struct pcm *pcm)
+{
+ return pcm->error;
+}
+
+static int oops(struct pcm *pcm, int e, const char *fmt, ...)
+{
+ va_list ap;
+ int sz;
+
+ va_start(ap, fmt);
+ vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap);
+ va_end(ap);
+ sz = strlen(pcm->error);
+
+ if (errno)
+ snprintf(pcm->error + sz, PCM_ERROR_MAX - sz,
+ ": %s", strerror(e));
+ return -1;
+}
+
+int pcm_write(struct pcm *pcm, void *data, unsigned count)
+{
+ struct snd_xferi x;
+
+ if (pcm->flags & PCM_IN)
+ return -EINVAL;
+
+ x.buf = data;
+ x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4);
+
+ for (;;) {
+ if (!pcm->running) {
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
+ return oops(pcm, errno, "cannot prepare channel");
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
+ return oops(pcm, errno, "cannot write initial data");
+ pcm->running = 1;
+ return 0;
+ }
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
+ pcm->running = 0;
+ if (errno == EPIPE) {
+ /* we failed to make our window -- try to restart */
+ pcm->underruns++;
+ continue;
+ }
+ return oops(pcm, errno, "cannot write stream data");
+ }
+ return 0;
+ }
+}
+
+int pcm_read(struct pcm *pcm, void *data, unsigned count)
+{
+ struct snd_xferi x;
+
+ if (!(pcm->flags & PCM_IN))
+ return -EINVAL;
+
+ x.buf = data;
+ x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4);
+
+// LOGV("read() %d frames", x.frames);
+ for (;;) {
+ if (!pcm->running) {
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
+ return oops(pcm, errno, "cannot prepare channel");
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START))
+ return oops(pcm, errno, "cannot start channel");
+ pcm->running = 1;
+ }
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {
+ pcm->running = 0;
+ if (errno == EPIPE) {
+ /* we failed to make our window -- try to restart */
+ pcm->underruns++;
+ continue;
+ }
+ return oops(pcm, errno, "cannot read stream data");
+ }
+// LOGV("read() got %d frames", x.frames);
+ return 0;
+ }
+}
+
+static struct pcm bad_pcm = {
+ .fd = -1,
+};
+
+int pcm_close(struct pcm *pcm)
+{
+ if (pcm == &bad_pcm)
+ return 0;
+
+ if (pcm->fd >= 0)
+ close(pcm->fd);
+ pcm->running = 0;
+ pcm->buffer_size = 0;
+ pcm->fd = -1;
+ return 0;
+}
+
+struct pcm *pcm_open(unsigned flags)
+{
+ const char *dname;
+ struct pcm *pcm;
+ struct snd_pcm_info info;
+ struct snd_pcm_hw_params params;
+ struct snd_pcm_sw_params sparams;
+ unsigned period_sz;
+ unsigned period_cnt;
+
+ LOGV("pcm_open(0x%08x)",flags);
+
+ pcm = calloc(1, sizeof(struct pcm));
+ if (!pcm)
+ return &bad_pcm;
+
+ if (flags & PCM_IN) {
+ dname = "/dev/snd/pcmC0D0c";
+ } else {
+ dname = "/dev/snd/pcmC0D0p";
+ }
+
+ LOGV("pcm_open() period sz multiplier %d",
+ ((flags & PCM_PERIOD_SZ_MASK) >> PCM_PERIOD_SZ_SHIFT) + 1);
+ period_sz = 128 * (((flags & PCM_PERIOD_SZ_MASK) >> PCM_PERIOD_SZ_SHIFT) + 1);
+ LOGV("pcm_open() period cnt %d",
+ ((flags & PCM_PERIOD_CNT_MASK) >> PCM_PERIOD_CNT_SHIFT) + PCM_PERIOD_CNT_MIN);
+ period_cnt = ((flags & PCM_PERIOD_CNT_MASK) >> PCM_PERIOD_CNT_SHIFT) + PCM_PERIOD_CNT_MIN;
+
+ pcm->flags = flags;
+ pcm->fd = open(dname, O_RDWR);
+ if (pcm->fd < 0) {
+ oops(pcm, errno, "cannot open device '%s'");
+ return pcm;
+ }
+
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) {
+ oops(pcm, errno, "cannot get info - %s");
+ goto fail;
+ }
+ info_dump(&info);
+
+ LOGV("pcm_open() period_cnt %d period_sz %d channels %d",
+ period_cnt, period_sz, (flags & PCM_MONO) ? 1 : 2);
+
+ param_init(¶ms);
+ param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS,
+ SNDRV_PCM_ACCESS_RW_INTERLEAVED);
+ param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_FORMAT,
+ SNDRV_PCM_FORMAT_S16_LE);
+ param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_SUBFORMAT,
+ SNDRV_PCM_SUBFORMAT_STD);
+ param_set_min(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, period_sz);
+ param_set_int(¶ms, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
+ param_set_int(¶ms, SNDRV_PCM_HW_PARAM_FRAME_BITS,
+ (flags & PCM_MONO) ? 16 : 32);
+ param_set_int(¶ms, SNDRV_PCM_HW_PARAM_CHANNELS,
+ (flags & PCM_MONO) ? 1 : 2);
+ param_set_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS, period_cnt);
+ param_set_int(¶ms, SNDRV_PCM_HW_PARAM_RATE, 44100);
+
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms)) {
+ oops(pcm, errno, "cannot set hw params");
+ goto fail;
+ }
+ param_dump(¶ms);
+
+ memset(&sparams, 0, sizeof(sparams));
+ sparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
+ sparams.period_step = 1;
+ sparams.avail_min = 1;
+ sparams.start_threshold = period_cnt * period_sz;
+ sparams.stop_threshold = period_cnt * period_sz;
+ sparams.xfer_align = period_sz / 2; /* needed for old kernels */
+ sparams.silence_size = 0;
+ sparams.silence_threshold = 0;
+
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {
+ oops(pcm, errno, "cannot set sw params");
+ goto fail;
+ }
+
+ pcm->buffer_size = period_cnt * period_sz;
+ pcm->underruns = 0;
+ return pcm;
+
+fail:
+ close(pcm->fd);
+ pcm->fd = -1;
+ return pcm;
+}
+
+int pcm_ready(struct pcm *pcm)
+{
+ return pcm->fd >= 0;
+}
diff --git a/libaudio/amix.c b/libaudio/amix.c
new file mode 100644
index 0000000..d978caa
--- /dev/null
+++ b/libaudio/amix.c
@@ -0,0 +1,78 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include
+#include
+#include
+#include
+#include
+
+#include "alsa_audio.h"
+
+
+struct mixer_ctl *get_ctl(struct mixer *mixer, char *name)
+{
+ char *p;
+ unsigned idx = 0;
+
+ if (isdigit(name[0]))
+ return mixer_get_nth_control(mixer, atoi(name) - 1);
+
+ p = strrchr(name, '#');
+ if (p) {
+ *p++ = 0;
+ idx = atoi(p);
+ }
+
+ return mixer_get_control(mixer, name, idx);
+}
+
+int main(int argc, char **argv)
+{
+ struct mixer *mixer;
+ struct mixer_ctl *ctl;
+ int r;
+
+ mixer = mixer_open();
+ if (!mixer)
+ return -1;
+
+ if (argc == 1) {
+ mixer_dump(mixer);
+ return 0;
+ }
+
+ ctl = get_ctl(mixer, argv[1]);
+ argc -= 2;
+ argv += 2;
+
+ if (!ctl) {
+ fprintf(stderr,"can't find control\n");
+ return -1;
+ }
+
+ if (argc) {
+ if (isdigit(argv[0][0]))
+ r = mixer_ctl_set(ctl, atoi(argv[0]));
+ else
+ r = mixer_ctl_select(ctl, argv[0]);
+ if (r)
+ fprintf(stderr,"oops: %s\n", strerror(errno));
+ } else {
+ mixer_ctl_print(ctl);
+ }
+ return 0;
+}
diff --git a/libaudio/aplay.c b/libaudio/aplay.c
new file mode 100644
index 0000000..0ac0ac0
--- /dev/null
+++ b/libaudio/aplay.c
@@ -0,0 +1,140 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "alsa_audio.h"
+
+#define ID_RIFF 0x46464952
+#define ID_WAVE 0x45564157
+#define ID_FMT 0x20746d66
+#define ID_DATA 0x61746164
+
+#define FORMAT_PCM 1
+
+struct wav_header {
+ uint32_t riff_id;
+ uint32_t riff_sz;
+ uint32_t riff_fmt;
+ uint32_t fmt_id;
+ uint32_t fmt_sz;
+ uint16_t audio_format;
+ uint16_t num_channels;
+ uint32_t sample_rate;
+ uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */
+ uint16_t block_align; /* num_channels * bps / 8 */
+ uint16_t bits_per_sample;
+ uint32_t data_id;
+ uint32_t data_sz;
+};
+
+int play_file(unsigned rate, unsigned channels, int fd, unsigned count)
+{
+ struct pcm *pcm;
+ struct mixer *mixer;
+ struct pcm_ctl *ctl = NULL;
+ unsigned bufsize;
+ char *data;
+ unsigned flags = PCM_OUT;
+
+ if (channels == 1)
+ flags |= PCM_MONO;
+ else
+ flags |= PCM_STEREO;
+
+ pcm = pcm_open(flags);
+ if (!pcm_ready(pcm)) {
+ pcm_close(pcm);
+ return -1;
+ }
+
+ mixer = mixer_open();
+ if (mixer)
+ ctl = mixer_get_control(mixer,"Playback Path", 0);
+
+ bufsize = pcm_buffer_size(pcm);
+ data = malloc(bufsize);
+ if (!data) {
+ fprintf(stderr,"could not allocate %d bytes\n", count);
+ return -1;
+ }
+
+ while (read(fd, data, bufsize) == bufsize) {
+ if (pcm_write(pcm, data, bufsize))
+ break;
+
+ /* HACK: remove */
+ if (ctl) {
+ //mixer_ctl_select(ctl, "SPK");
+ ctl = 0;
+ }
+ }
+ pcm_close(pcm);
+ return 0;
+}
+
+int play_wav(const char *fn)
+{
+ struct wav_header hdr;
+ unsigned rate, channels;
+ int fd;
+ fd = open(fn, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "aplay: cannot open '%s'\n", fn);
+ return -1;
+ }
+ if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+ fprintf(stderr, "aplay: cannot read header\n");
+ return -1;
+ }
+ fprintf(stderr,"aplay: %d ch, %d hz, %d bit, %s\n",
+ hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample,
+ hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown");
+
+ if ((hdr.riff_id != ID_RIFF) ||
+ (hdr.riff_fmt != ID_WAVE) ||
+ (hdr.fmt_id != ID_FMT)) {
+ fprintf(stderr, "aplay: '%s' is not a riff/wave file\n", fn);
+ return -1;
+ }
+ if ((hdr.audio_format != FORMAT_PCM) ||
+ (hdr.fmt_sz != 16)) {
+ fprintf(stderr, "aplay: '%s' is not pcm format\n", fn);
+ return -1;
+ }
+ if (hdr.bits_per_sample != 16) {
+ fprintf(stderr, "aplay: '%s' is not 16bit per sample\n", fn);
+ return -1;
+ }
+
+ return play_file(hdr.sample_rate, hdr.num_channels, fd, hdr.data_sz);
+}
+
+int main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr,"usage: aplay \n");
+ return -1;
+ }
+
+ return play_wav(argv[1]);
+}
+
diff --git a/libaudio/arec.c b/libaudio/arec.c
new file mode 100644
index 0000000..b1e9eda
--- /dev/null
+++ b/libaudio/arec.c
@@ -0,0 +1,128 @@
+/*
+** Copyright 2010, The Android Open-Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "alsa_audio.h"
+
+#define ID_RIFF 0x46464952
+#define ID_WAVE 0x45564157
+#define ID_FMT 0x20746d66
+#define ID_DATA 0x61746164
+
+#define FORMAT_PCM 1
+
+struct wav_header {
+ uint32_t riff_id;
+ uint32_t riff_sz;
+ uint32_t riff_fmt;
+ uint32_t fmt_id;
+ uint32_t fmt_sz;
+ uint16_t audio_format;
+ uint16_t num_channels;
+ uint32_t sample_rate;
+ uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */
+ uint16_t block_align; /* num_channels * bps / 8 */
+ uint16_t bits_per_sample;
+ uint32_t data_id;
+ uint32_t data_sz;
+};
+
+int record_file(unsigned rate, unsigned channels, int fd, unsigned count)
+{
+ struct pcm *pcm;
+ unsigned avail, xfer, bufsize;
+ char *data, *next;
+ int r;
+
+ pcm = pcm_open(PCM_IN|PCM_MONO);
+ if (!pcm_ready(pcm)) {
+ pcm_close(pcm);
+ goto fail;
+ }
+
+ bufsize = pcm_buffer_size(pcm);
+
+ data = malloc(bufsize);
+ if (!data) {
+ fprintf(stderr,"could not allocate %d bytes\n", count);
+ return -1;
+ }
+
+ while (!pcm_read(pcm, data, bufsize)) {
+ if (write(fd, data, bufsize) != bufsize) {
+ fprintf(stderr,"could not write %d bytes\n", bufsize);
+ return -1;
+ }
+ }
+
+ close(fd);
+ pcm_close(pcm);
+ return 0;
+
+fail:
+ fprintf(stderr,"pcm error: %s\n", pcm_error(pcm));
+ return -1;
+}
+
+int rec_wav(const char *fn)
+{
+ struct wav_header hdr;
+ unsigned rate, channels;
+ int fd;
+ fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664);
+ if (fd < 0) {
+ fprintf(stderr, "arec: cannot open '%s'\n", fn);
+ return -1;
+ }
+
+ hdr.riff_id = ID_RIFF;
+ hdr.riff_fmt = ID_WAVE;
+ hdr.fmt_id = ID_FMT;
+ hdr.audio_format = FORMAT_PCM;
+ hdr.fmt_sz = 16;
+ hdr.bits_per_sample = 16;
+ hdr.num_channels = 1;
+ hdr.data_sz = 0;
+ hdr.sample_rate = 44100;
+
+ if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+ fprintf(stderr, "arec: cannot write header\n");
+ return -1;
+ }
+ fprintf(stderr,"arec: %d ch, %d hz, %d bit, %s\n",
+ hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample,
+ hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown");
+
+
+ return record_file(hdr.sample_rate, hdr.num_channels, fd, hdr.data_sz);
+}
+
+int main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr,"usage: arec \n");
+ return -1;
+ }
+
+ return rec_wav(argv[1]);
+}
+
diff --git a/libaudio/asound.h b/libaudio/asound.h
new file mode 100644
index 0000000..6a17f29
--- /dev/null
+++ b/libaudio/asound.h
@@ -0,0 +1,814 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __SOUND_ASOUND_H
+#define __SOUND_ASOUND_H
+
+#include
+
+#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
+#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
+#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
+#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
+#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
+
+struct snd_aes_iec958 {
+ unsigned char status[24];
+ unsigned char subcode[147];
+ unsigned char pad;
+ unsigned char dig_subframe[4];
+};
+
+#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+enum {
+ SNDRV_HWDEP_IFACE_OPL2 = 0,
+ SNDRV_HWDEP_IFACE_OPL3,
+ SNDRV_HWDEP_IFACE_OPL4,
+ SNDRV_HWDEP_IFACE_SB16CSP,
+ SNDRV_HWDEP_IFACE_EMU10K1,
+ SNDRV_HWDEP_IFACE_YSS225,
+ SNDRV_HWDEP_IFACE_ICS2115,
+ SNDRV_HWDEP_IFACE_SSCAPE,
+ SNDRV_HWDEP_IFACE_VX,
+ SNDRV_HWDEP_IFACE_MIXART,
+ SNDRV_HWDEP_IFACE_USX2Y,
+ SNDRV_HWDEP_IFACE_EMUX_WAVETABLE,
+ SNDRV_HWDEP_IFACE_BLUETOOTH,
+ SNDRV_HWDEP_IFACE_USX2Y_PCM,
+ SNDRV_HWDEP_IFACE_PCXHR,
+ SNDRV_HWDEP_IFACE_SB_RC,
+ SNDRV_HWDEP_IFACE_HDA,
+ SNDRV_HWDEP_IFACE_USB_STREAM,
+
+ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
+};
+
+struct snd_hwdep_info {
+ unsigned int device;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ int iface;
+ unsigned char reserved[64];
+};
+
+struct snd_hwdep_dsp_status {
+ unsigned int version;
+ unsigned char id[32];
+ unsigned int num_dsps;
+ unsigned int dsp_loaded;
+ unsigned int chip_ready;
+ unsigned char reserved[16];
+};
+
+struct snd_hwdep_dsp_image {
+ unsigned int index;
+ unsigned char name[64];
+ unsigned char __user *image;
+ size_t length;
+ unsigned long driver_data;
+};
+
+#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
+#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
+#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
+#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
+
+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10)
+
+typedef unsigned long snd_pcm_uframes_t;
+typedef signed long snd_pcm_sframes_t;
+
+enum {
+ SNDRV_PCM_CLASS_GENERIC = 0,
+ SNDRV_PCM_CLASS_MULTI,
+ SNDRV_PCM_CLASS_MODEM,
+ SNDRV_PCM_CLASS_DIGITIZER,
+
+ SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
+};
+
+enum {
+ SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0,
+ SNDRV_PCM_SUBCLASS_MULTI_MIX,
+
+ SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
+};
+
+enum {
+ SNDRV_PCM_STREAM_PLAYBACK = 0,
+ SNDRV_PCM_STREAM_CAPTURE,
+ SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
+};
+
+typedef int __bitwise snd_pcm_access_t;
+#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0)
+#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1)
+#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2)
+#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3)
+#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4)
+#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
+
+typedef int __bitwise snd_pcm_format_t;
+#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
+#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
+#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
+#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
+#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
+#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
+#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6)
+#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7)
+#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8)
+#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9)
+#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
+#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
+#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
+#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
+#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14)
+#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15)
+#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16)
+#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17)
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18)
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19)
+#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
+#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
+#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
+#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
+#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
+#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
+#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32)
+#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33)
+#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34)
+#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35)
+#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36)
+#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37)
+#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38)
+#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39)
+#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40)
+#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41)
+#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42)
+#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43)
+#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_U18_3BE
+
+#ifdef SNDRV_LITTLE_ENDIAN
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
+#endif
+#ifdef SNDRV_BIG_ENDIAN
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
+#endif
+
+typedef int __bitwise snd_pcm_subformat_t;
+#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
+#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
+
+#define SNDRV_PCM_INFO_MMAP 0x00000001
+#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002
+#define SNDRV_PCM_INFO_DOUBLE 0x00000004
+#define SNDRV_PCM_INFO_BATCH 0x00000010
+#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100
+#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200
+#define SNDRV_PCM_INFO_COMPLEX 0x00000400
+#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000
+#define SNDRV_PCM_INFO_OVERRANGE 0x00020000
+#define SNDRV_PCM_INFO_RESUME 0x00040000
+#define SNDRV_PCM_INFO_PAUSE 0x00080000
+#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000
+#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000
+#define SNDRV_PCM_INFO_SYNC_START 0x00400000
+#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000
+
+typedef int __bitwise snd_pcm_state_t;
+#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0)
+#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1)
+#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2)
+#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3)
+#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4)
+#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5)
+#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6)
+#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7)
+#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8)
+#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
+
+enum {
+ SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
+ SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
+ SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
+};
+
+union snd_pcm_sync_id {
+ unsigned char id[16];
+ unsigned short id16[8];
+ unsigned int id32[4];
+};
+
+struct snd_pcm_info {
+ unsigned int device;
+ unsigned int subdevice;
+ int stream;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned char subname[32];
+ int dev_class;
+ int dev_subclass;
+ unsigned int subdevices_count;
+ unsigned int subdevices_avail;
+ union snd_pcm_sync_id sync;
+ unsigned char reserved[64];
+};
+
+typedef int snd_pcm_hw_param_t;
+#define SNDRV_PCM_HW_PARAM_ACCESS 0
+#define SNDRV_PCM_HW_PARAM_FORMAT 1
+#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2
+#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
+#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
+
+#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8
+#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9
+#define SNDRV_PCM_HW_PARAM_CHANNELS 10
+#define SNDRV_PCM_HW_PARAM_RATE 11
+#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12
+#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13
+#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14
+#define SNDRV_PCM_HW_PARAM_PERIODS 15
+#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16
+#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17
+#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18
+#define SNDRV_PCM_HW_PARAM_TICK_TIME 19
+#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
+#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
+
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)
+
+struct snd_interval {
+ unsigned int min, max;
+ unsigned int openmin:1,
+ openmax:1,
+ integer:1,
+ empty:1;
+};
+
+#define SNDRV_MASK_MAX 256
+
+struct snd_mask {
+ __u32 bits[(SNDRV_MASK_MAX+31)/32];
+};
+
+struct snd_pcm_hw_params {
+ unsigned int flags;
+ struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
+ SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
+ struct snd_mask mres[5];
+ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
+ SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+ struct snd_interval ires[9];
+ unsigned int rmask;
+ unsigned int cmask;
+ unsigned int info;
+ unsigned int msbits;
+ unsigned int rate_num;
+ unsigned int rate_den;
+ snd_pcm_uframes_t fifo_size;
+ unsigned char reserved[64];
+};
+
+enum {
+ SNDRV_PCM_TSTAMP_NONE = 0,
+ SNDRV_PCM_TSTAMP_ENABLE,
+ SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
+};
+
+struct snd_pcm_sw_params {
+ int tstamp_mode;
+ unsigned int period_step;
+ unsigned int sleep_min;
+ snd_pcm_uframes_t avail_min;
+ snd_pcm_uframes_t xfer_align;
+ snd_pcm_uframes_t start_threshold;
+ snd_pcm_uframes_t stop_threshold;
+ snd_pcm_uframes_t silence_threshold;
+ snd_pcm_uframes_t silence_size;
+ snd_pcm_uframes_t boundary;
+ unsigned char reserved[64];
+};
+
+struct snd_pcm_channel_info {
+ unsigned int channel;
+ __kernel_off_t offset;
+ unsigned int first;
+ unsigned int step;
+};
+
+struct snd_pcm_status {
+ snd_pcm_state_t state;
+ struct timespec trigger_tstamp;
+ struct timespec tstamp;
+ snd_pcm_uframes_t appl_ptr;
+ snd_pcm_uframes_t hw_ptr;
+ snd_pcm_sframes_t delay;
+ snd_pcm_uframes_t avail;
+ snd_pcm_uframes_t avail_max;
+ snd_pcm_uframes_t overrange;
+ snd_pcm_state_t suspended_state;
+ unsigned char reserved[60];
+};
+
+struct snd_pcm_mmap_status {
+ snd_pcm_state_t state;
+ int pad1;
+ snd_pcm_uframes_t hw_ptr;
+ struct timespec tstamp;
+ snd_pcm_state_t suspended_state;
+};
+
+struct snd_pcm_mmap_control {
+ snd_pcm_uframes_t appl_ptr;
+ snd_pcm_uframes_t avail_min;
+};
+
+#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0)
+#define SNDRV_PCM_SYNC_PTR_APPL (1<<1)
+#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2)
+
+struct snd_pcm_sync_ptr {
+ unsigned int flags;
+ union {
+ struct snd_pcm_mmap_status status;
+ unsigned char reserved[64];
+ } s;
+ union {
+ struct snd_pcm_mmap_control control;
+ unsigned char reserved[64];
+ } c;
+};
+
+struct snd_xferi {
+ snd_pcm_sframes_t result;
+ void __user *buf;
+ snd_pcm_uframes_t frames;
+};
+
+struct snd_xfern {
+ snd_pcm_sframes_t result;
+ void __user * __user *bufs;
+ snd_pcm_uframes_t frames;
+};
+
+enum {
+ SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0,
+ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+ SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+};
+
+#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
+#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
+#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
+#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
+#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
+#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
+#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
+#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
+#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
+#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
+#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
+#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
+#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
+#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
+#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
+#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
+#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
+#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
+#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
+#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
+
+#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
+
+enum {
+ SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
+ SNDRV_RAWMIDI_STREAM_INPUT,
+ SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
+};
+
+#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
+#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
+#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
+
+struct snd_rawmidi_info {
+ unsigned int device;
+ unsigned int subdevice;
+ int stream;
+ int card;
+ unsigned int flags;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned char subname[32];
+ unsigned int subdevices_count;
+ unsigned int subdevices_avail;
+ unsigned char reserved[64];
+};
+
+struct snd_rawmidi_params {
+ int stream;
+ size_t buffer_size;
+ size_t avail_min;
+ unsigned int no_active_sensing: 1;
+ unsigned char reserved[16];
+};
+
+struct snd_rawmidi_status {
+ int stream;
+ struct timespec tstamp;
+ size_t avail;
+ size_t xruns;
+ unsigned char reserved[16];
+};
+
+#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
+#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
+#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
+#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
+#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
+#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
+
+#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
+
+enum {
+ SNDRV_TIMER_CLASS_NONE = -1,
+ SNDRV_TIMER_CLASS_SLAVE = 0,
+ SNDRV_TIMER_CLASS_GLOBAL,
+ SNDRV_TIMER_CLASS_CARD,
+ SNDRV_TIMER_CLASS_PCM,
+ SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
+};
+
+enum {
+ SNDRV_TIMER_SCLASS_NONE = 0,
+ SNDRV_TIMER_SCLASS_APPLICATION,
+ SNDRV_TIMER_SCLASS_SEQUENCER,
+ SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
+ SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
+};
+
+#define SNDRV_TIMER_GLOBAL_SYSTEM 0
+#define SNDRV_TIMER_GLOBAL_RTC 1
+#define SNDRV_TIMER_GLOBAL_HPET 2
+#define SNDRV_TIMER_GLOBAL_HRTIMER 3
+
+#define SNDRV_TIMER_FLG_SLAVE (1<<0)
+
+struct snd_timer_id {
+ int dev_class;
+ int dev_sclass;
+ int card;
+ int device;
+ int subdevice;
+};
+
+struct snd_timer_ginfo {
+ struct snd_timer_id tid;
+ unsigned int flags;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned long reserved0;
+ unsigned long resolution;
+ unsigned long resolution_min;
+ unsigned long resolution_max;
+ unsigned int clients;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_gparams {
+ struct snd_timer_id tid;
+ unsigned long period_num;
+ unsigned long period_den;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_gstatus {
+ struct snd_timer_id tid;
+ unsigned long resolution;
+ unsigned long resolution_num;
+ unsigned long resolution_den;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_select {
+ struct snd_timer_id id;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_info {
+ unsigned int flags;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned long reserved0;
+ unsigned long resolution;
+ unsigned char reserved[64];
+};
+
+#define SNDRV_TIMER_PSFLG_AUTO (1<<0)
+#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1)
+#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2)
+
+struct snd_timer_params {
+ unsigned int flags;
+ unsigned int ticks;
+ unsigned int queue_size;
+ unsigned int reserved0;
+ unsigned int filter;
+ unsigned char reserved[60];
+};
+
+struct snd_timer_status {
+ struct timespec tstamp;
+ unsigned int resolution;
+ unsigned int lost;
+ unsigned int overrun;
+ unsigned int queue;
+ unsigned char reserved[64];
+};
+
+#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
+#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
+#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
+#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
+#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
+#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
+#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
+#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
+#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
+#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
+
+#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
+#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
+#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
+#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
+
+struct snd_timer_read {
+ unsigned int resolution;
+ unsigned int ticks;
+};
+
+enum {
+ SNDRV_TIMER_EVENT_RESOLUTION = 0,
+ SNDRV_TIMER_EVENT_TICK,
+ SNDRV_TIMER_EVENT_START,
+ SNDRV_TIMER_EVENT_STOP,
+ SNDRV_TIMER_EVENT_CONTINUE,
+ SNDRV_TIMER_EVENT_PAUSE,
+ SNDRV_TIMER_EVENT_EARLY,
+ SNDRV_TIMER_EVENT_SUSPEND,
+ SNDRV_TIMER_EVENT_RESUME,
+
+ SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
+ SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
+ SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
+ SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
+ SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
+ SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
+};
+
+struct snd_timer_tread {
+ int event;
+ struct timespec tstamp;
+ unsigned int val;
+};
+
+#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
+
+struct snd_ctl_card_info {
+ int card;
+ int pad;
+ unsigned char id[16];
+ unsigned char driver[16];
+ unsigned char name[32];
+ unsigned char longname[80];
+ unsigned char reserved_[16];
+ unsigned char mixername[80];
+ unsigned char components[128];
+};
+
+typedef int __bitwise snd_ctl_elem_type_t;
+#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0)
+#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1)
+#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2)
+#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3)
+#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4)
+#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5)
+#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6)
+#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
+
+typedef int __bitwise snd_ctl_elem_iface_t;
+#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0)
+#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1)
+#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2)
+#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3)
+#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4)
+#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5)
+#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6)
+#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
+
+#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
+#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
+#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2)
+#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6)
+#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8)
+#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9)
+#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28)
+#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29)
+
+#define SNDRV_CTL_POWER_D0 0x0000
+#define SNDRV_CTL_POWER_D1 0x0100
+#define SNDRV_CTL_POWER_D2 0x0200
+#define SNDRV_CTL_POWER_D3 0x0300
+#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000)
+#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001)
+
+struct snd_ctl_elem_id {
+ unsigned int numid;
+ snd_ctl_elem_iface_t iface;
+ unsigned int device;
+ unsigned int subdevice;
+ unsigned char name[44];
+ unsigned int index;
+};
+
+struct snd_ctl_elem_list {
+ unsigned int offset;
+ unsigned int space;
+ unsigned int used;
+ unsigned int count;
+ struct snd_ctl_elem_id __user *pids;
+ unsigned char reserved[50];
+};
+
+struct snd_ctl_elem_info {
+ struct snd_ctl_elem_id id;
+ snd_ctl_elem_type_t type;
+ unsigned int access;
+ unsigned int count;
+ __kernel_pid_t owner;
+ union {
+ struct {
+ long min;
+ long max;
+ long step;
+ } integer;
+ struct {
+ long long min;
+ long long max;
+ long long step;
+ } integer64;
+ struct {
+ unsigned int items;
+ unsigned int item;
+ char name[64];
+ } enumerated;
+ unsigned char reserved[128];
+ } value;
+ union {
+ unsigned short d[4];
+ unsigned short *d_ptr;
+ } dimen;
+ unsigned char reserved[64-4*sizeof(unsigned short)];
+};
+
+struct snd_ctl_elem_value {
+ struct snd_ctl_elem_id id;
+ unsigned int indirect: 1;
+ union {
+ union {
+ long value[128];
+ long *value_ptr;
+ } integer;
+ union {
+ long long value[64];
+ long long *value_ptr;
+ } integer64;
+ union {
+ unsigned int item[128];
+ unsigned int *item_ptr;
+ } enumerated;
+ union {
+ unsigned char data[512];
+ unsigned char *data_ptr;
+ } bytes;
+ struct snd_aes_iec958 iec958;
+ } value;
+ struct timespec tstamp;
+ unsigned char reserved[128-sizeof(struct timespec)];
+};
+
+struct snd_ctl_tlv {
+ unsigned int numid;
+ unsigned int length;
+ unsigned int tlv[0];
+};
+
+#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
+#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
+#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
+#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
+#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
+#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
+#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
+#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
+#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
+#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
+#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
+#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
+
+enum sndrv_ctl_event_type {
+ SNDRV_CTL_EVENT_ELEM = 0,
+ SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
+};
+
+#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0)
+#define SNDRV_CTL_EVENT_MASK_INFO (1<<1)
+#define SNDRV_CTL_EVENT_MASK_ADD (1<<2)
+#define SNDRV_CTL_EVENT_MASK_TLV (1<<3)
+#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U)
+
+struct snd_ctl_event {
+ int type;
+ union {
+ struct {
+ unsigned int mask;
+ struct snd_ctl_elem_id id;
+ } elem;
+ unsigned char data8[60];
+ } data;
+};
+
+#define SNDRV_CTL_NAME_NONE ""
+#define SNDRV_CTL_NAME_PLAYBACK "Playback "
+#define SNDRV_CTL_NAME_CAPTURE "Capture "
+
+#define SNDRV_CTL_NAME_IEC958_NONE ""
+#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
+#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
+#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
+#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
+#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
+#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
+#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
+#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
+
+#endif
+
diff --git a/libcamera/Android.mk b/libcamera/Android.mk
new file mode 100644
index 0000000..5304cc5
--- /dev/null
+++ b/libcamera/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# HAL module implemenation stored in
+# hw/..so
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libs3cjpeg
+
+LOCAL_SRC_FILES:= \
+ SecCamera.cpp SecCameraHWInterface.cpp
+
+LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware
+LOCAL_SHARED_LIBRARIES+= libs3cjpeg
+
+LOCAL_MODULE := camera.s5pc110
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/libcamera/NOTICE b/libcamera/NOTICE
new file mode 100644
index 0000000..f921593
--- /dev/null
+++ b/libcamera/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/libcamera/SecCamera.cpp b/libcamera/SecCamera.cpp
new file mode 100755
index 0000000..4bd00c6
--- /dev/null
+++ b/libcamera/SecCamera.cpp
@@ -0,0 +1,2604 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ * Copyright 2010, Samsung Electronics Co. LTD
+ * Copyright 2011, The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+************************************
+* Filename: SecCamera.cpp
+* Author: Sachin P. Kamat
+* Purpose: This file interacts with the Camera and JPEG drivers.
+*************************************
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SecCamera"
+
+#include
+
+#include
+#include
+#include
+#include
+#include "SecCamera.h"
+#include "cutils/properties.h"
+
+using namespace android;
+
+#define CHECK(return_value) \
+ if (return_value < 0) { \
+ LOGE("%s::%d fail. errno: %s, m_camera_id = %d\n", \
+ __func__, __LINE__, strerror(errno), m_camera_id); \
+ return -1; \
+ }
+
+
+#define CHECK_PTR(return_value) \
+ if (return_value < 0) { \
+ LOGE("%s::%d fail, errno: %s, m_camera_id = %d\n", \
+ __func__,__LINE__, strerror(errno), m_camera_id); \
+ return NULL; \
+ }
+
+#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5)
+#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7)
+#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13)
+
+namespace android {
+
+// ======================================================================
+// Camera controls
+
+static struct timeval time_start;
+static struct timeval time_stop;
+
+unsigned long measure_time(struct timeval *start, struct timeval *stop)
+{
+ unsigned long sec, usec, time;
+
+ sec = stop->tv_sec - start->tv_sec;
+
+ if (stop->tv_usec >= start->tv_usec) {
+ usec = stop->tv_usec - start->tv_usec;
+ } else {
+ usec = stop->tv_usec + 1000000 - start->tv_usec;
+ sec--;
+ }
+
+ time = (sec * 1000000) + usec;
+
+ return time;
+}
+
+static int get_pixel_depth(unsigned int fmt)
+{
+ int depth = 0;
+
+ switch (fmt) {
+ case V4L2_PIX_FMT_NV12:
+ depth = 12;
+ break;
+ case V4L2_PIX_FMT_NV12T:
+ depth = 12;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ depth = 12;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ depth = 12;
+ break;
+
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_YUV422P:
+ depth = 16;
+ break;
+
+ case V4L2_PIX_FMT_RGB32:
+ depth = 32;
+ break;
+ }
+
+ return depth;
+}
+
+#define ALIGN_W(x) (((x) + 0x7F) & (~0x7F)) // Set as multiple of 128
+#define ALIGN_H(x) (((x) + 0x1F) & (~0x1F)) // Set as multiple of 32
+#define ALIGN_BUF(x) (((x) + 0x1FFF)& (~0x1FFF)) // Set as multiple of 8K
+
+static int fimc_poll(struct pollfd *events)
+{
+ int ret;
+
+ /* 10 second delay is because sensor can take a long time
+ * to do auto focus and capture in dark settings
+ */
+ ret = poll(events, 1, 10000);
+ if (ret < 0) {
+ LOGE("ERR(%s):poll error\n", __func__);
+ return ret;
+ }
+
+ if (ret == 0) {
+ LOGE("ERR(%s):No data in 10 secs..\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+int SecCamera::previewPoll(bool preview)
+{
+ int ret;
+
+ if (preview) {
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ int status = 0;
+
+ if (!(++m_esd_check_count % 60)) {
+ status = getCameraSensorESDStatus();
+ m_esd_check_count = 0;
+ if (status) {
+ LOGE("ERR(%s) ESD status(%d)", __func__, status);
+ return status;
+ }
+ }
+#endif
+
+ ret = poll(&m_events_c, 1, 1000);
+ } else {
+ ret = poll(&m_events_c2, 1, 1000);
+ }
+
+ if (ret < 0) {
+ LOGE("ERR(%s):poll error\n", __func__);
+ return ret;
+ }
+
+ if (ret == 0) {
+ LOGE("ERR(%s):No data in 1 secs.. Camera Device Reset \n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_querycap(int fp)
+{
+ struct v4l2_capability cap;
+ int ret = 0;
+
+ ret = ioctl(fp, VIDIOC_QUERYCAP, &cap);
+
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_QUERYCAP failed\n", __func__);
+ return -1;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
+ LOGE("ERR(%s):no capture devices\n", __func__);
+ return -1;
+ }
+
+ return ret;
+}
+
+static const __u8* fimc_v4l2_enuminput(int fp, int index)
+{
+ static struct v4l2_input input;
+
+ input.index = index;
+ if (ioctl(fp, VIDIOC_ENUMINPUT, &input) != 0) {
+ LOGE("ERR(%s):No matching index found\n", __func__);
+ return NULL;
+ }
+ LOGI("Name of input channel[%d] is %s\n", input.index, input.name);
+
+ return input.name;
+}
+
+
+static int fimc_v4l2_s_input(int fp, int index)
+{
+ struct v4l2_input input;
+ int ret;
+
+ input.index = index;
+
+ ret = ioctl(fp, VIDIOC_S_INPUT, &input);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_INPUT failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_s_fmt(int fp, int width, int height, unsigned int fmt, int flag_capture)
+{
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_pix_format pixfmt;
+ int ret;
+
+ v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ memset(&pixfmt, 0, sizeof(pixfmt));
+
+ pixfmt.width = width;
+ pixfmt.height = height;
+ pixfmt.pixelformat = fmt;
+
+ pixfmt.sizeimage = (width * height * get_pixel_depth(fmt)) / 8;
+
+ pixfmt.field = V4L2_FIELD_NONE;
+
+ v4l2_fmt.fmt.pix = pixfmt;
+
+ /* Set up for capture */
+ ret = ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_FMT failed\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_s_fmt_cap(int fp, int width, int height, unsigned int fmt)
+{
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_pix_format pixfmt;
+ int ret;
+
+ memset(&pixfmt, 0, sizeof(pixfmt));
+
+ v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ pixfmt.width = width;
+ pixfmt.height = height;
+ pixfmt.pixelformat = fmt;
+ if (fmt == V4L2_PIX_FMT_JPEG) {
+ pixfmt.colorspace = V4L2_COLORSPACE_JPEG;
+ }
+
+ pixfmt.sizeimage = (width * height * get_pixel_depth(fmt)) / 8;
+
+ v4l2_fmt.fmt.pix = pixfmt;
+
+ //LOGE("ori_w %d, ori_h %d, w %d, h %d\n", width, height, v4l2_fmt.fmt.pix.width, v4l2_fmt.fmt.pix.height);
+
+ /* Set up for capture */
+ ret = ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_FMT failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_enum_fmt(int fp, unsigned int fmt)
+{
+ struct v4l2_fmtdesc fmtdesc;
+ int found = 0;
+
+ fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmtdesc.index = 0;
+
+ while (ioctl(fp, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
+ if (fmtdesc.pixelformat == fmt) {
+ LOGV("passed fmt = %#x found pixel format[%d]: %s\n", fmt, fmtdesc.index, fmtdesc.description);
+ found = 1;
+ break;
+ }
+
+ fmtdesc.index++;
+ }
+
+ if (!found) {
+ LOGE("unsupported pixel format\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_reqbufs(int fp, enum v4l2_buf_type type, int nr_bufs)
+{
+ struct v4l2_requestbuffers req;
+ int ret;
+
+ req.count = nr_bufs;
+ req.type = type;
+ req.memory = V4L2_MEMORY_MMAP;
+
+ ret = ioctl(fp, VIDIOC_REQBUFS, &req);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_REQBUFS failed\n", __func__);
+ return -1;
+ }
+
+ return req.count;
+}
+
+static int fimc_v4l2_querybuf(int fp, struct fimc_buffer *buffer, enum v4l2_buf_type type)
+{
+ struct v4l2_buffer v4l2_buf;
+ int ret;
+
+ LOGI("%s :", __func__);
+
+ v4l2_buf.type = type;
+ v4l2_buf.memory = V4L2_MEMORY_MMAP;
+ v4l2_buf.index = 0;
+
+ ret = ioctl(fp , VIDIOC_QUERYBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_QUERYBUF failed\n", __func__);
+ return -1;
+ }
+
+ buffer->length = v4l2_buf.length;
+ if ((buffer->start = (char *)mmap(0, v4l2_buf.length,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ fp, v4l2_buf.m.offset)) < 0) {
+ LOGE("%s %d] mmap() failed\n",__func__, __LINE__);
+ return -1;
+ }
+
+ LOGI("%s: buffer->start = %p v4l2_buf.length = %d",
+ __func__, buffer->start, v4l2_buf.length);
+
+ return 0;
+}
+
+static int fimc_v4l2_streamon(int fp)
+{
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_STREAMON, &type);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_STREAMON failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_streamoff(int fp)
+{
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ int ret;
+
+ LOGV("%s :", __func__);
+ ret = ioctl(fp, VIDIOC_STREAMOFF, &type);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_STREAMOFF failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_qbuf(int fp, int index)
+{
+ struct v4l2_buffer v4l2_buf;
+ int ret;
+
+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ v4l2_buf.memory = V4L2_MEMORY_MMAP;
+ v4l2_buf.index = index;
+
+ ret = ioctl(fp, VIDIOC_QBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_QBUF failed\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_dqbuf(int fp)
+{
+ struct v4l2_buffer v4l2_buf;
+ int ret;
+
+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ v4l2_buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = ioctl(fp, VIDIOC_DQBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_DQBUF failed, dropped frame\n", __func__);
+ return ret;
+ }
+
+ return v4l2_buf.index;
+}
+
+static int fimc_v4l2_g_ctrl(int fp, unsigned int id)
+{
+ struct v4l2_control ctrl;
+ int ret;
+
+ ctrl.id = id;
+
+ ret = ioctl(fp, VIDIOC_G_CTRL, &ctrl);
+ if (ret < 0) {
+ LOGE("ERR(%s): VIDIOC_G_CTRL(id = 0x%x (%d)) failed, ret = %d\n",
+ __func__, id, id-V4L2_CID_PRIVATE_BASE, ret);
+ return ret;
+ }
+
+ return ctrl.value;
+}
+
+static int fimc_v4l2_s_ctrl(int fp, unsigned int id, unsigned int value)
+{
+ struct v4l2_control ctrl;
+ int ret;
+
+ ctrl.id = id;
+ ctrl.value = value;
+
+ ret = ioctl(fp, VIDIOC_S_CTRL, &ctrl);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_CTRL(id = %#x (%d), value = %d) failed ret = %d\n",
+ __func__, id, id-V4L2_CID_PRIVATE_BASE, value, ret);
+
+ return ret;
+ }
+
+ return ctrl.value;
+}
+
+static int fimc_v4l2_s_ext_ctrl(int fp, unsigned int id, void *value)
+{
+ struct v4l2_ext_controls ctrls;
+ struct v4l2_ext_control ctrl;
+ int ret;
+
+ ctrl.id = id;
+ ctrl.reserved = value;
+
+ ctrls.ctrl_class = V4L2_CTRL_CLASS_CAMERA;
+ ctrls.count = 1;
+ ctrls.controls = &ctrl;
+
+ ret = ioctl(fp, VIDIOC_S_EXT_CTRLS, &ctrls);
+ if (ret < 0)
+ LOGE("ERR(%s):VIDIOC_S_EXT_CTRLS failed\n", __func__);
+
+ return ret;
+}
+
+static int fimc_v4l2_g_parm(int fp, struct v4l2_streamparm *streamparm)
+{
+ int ret;
+
+ streamparm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ret = ioctl(fp, VIDIOC_G_PARM, streamparm);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_G_PARM failed\n", __func__);
+ return -1;
+ }
+
+ LOGV("%s : timeperframe: numerator %d, denominator %d\n", __func__,
+ streamparm->parm.capture.timeperframe.numerator,
+ streamparm->parm.capture.timeperframe.denominator);
+
+ return 0;
+}
+
+static int fimc_v4l2_s_parm(int fp, struct v4l2_streamparm *streamparm)
+{
+ int ret;
+
+ streamparm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ret = ioctl(fp, VIDIOC_S_PARM, streamparm);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_PARM failed\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+// ======================================================================
+// Constructor & Destructor
+
+SecCamera::SecCamera() :
+ m_flag_init(0),
+ m_camera_id(CAMERA_ID_BACK),
+ m_cam_fd(-1),
+ m_cam_fd2(-1),
+ m_preview_v4lformat(V4L2_PIX_FMT_NV21),
+ m_preview_width (0),
+ m_preview_height (0),
+ m_preview_max_width (MAX_BACK_CAMERA_PREVIEW_WIDTH),
+ m_preview_max_height (MAX_BACK_CAMERA_PREVIEW_HEIGHT),
+ m_snapshot_v4lformat(-1),
+ m_snapshot_width (0),
+ m_snapshot_height (0),
+ m_snapshot_max_width (MAX_BACK_CAMERA_SNAPSHOT_WIDTH),
+ m_snapshot_max_height (MAX_BACK_CAMERA_SNAPSHOT_HEIGHT),
+ m_angle(-1),
+ m_zoom_level(-1),
+ m_object_tracking(-1),
+ m_vtmode(0),
+ m_sensor_mode(-1),
+ m_shot_mode(-1),
+ m_exif_orientation(-1),
+ m_blur_level(-1),
+ m_chk_dataline(-1),
+ m_camera_af_flag(-1),
+ m_flag_camera_start(0),
+ m_jpeg_thumbnail_width (0),
+ m_jpeg_thumbnail_height(0),
+ m_jpeg_quality(100)
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ ,
+ m_esd_check_count(0)
+#endif // ENABLE_ESD_PREVIEW_CHECK
+{
+ m_params = (struct sec_cam_parm*)&m_streamparm.parm.raw_data;
+ struct v4l2_captureparm capture;
+ m_params->capture.timeperframe.numerator = 1;
+ m_params->capture.timeperframe.denominator = 0;
+ m_params->contrast = -1;
+ m_params->effects = -1;
+ m_params->brightness = -1;
+ m_params->flash_mode = -1;
+ m_params->focus_mode = -1;
+ m_params->iso = -1;
+ m_params->metering = -1;
+ m_params->saturation = -1;
+ m_params->scene_mode = -1;
+ m_params->sharpness = -1;
+ m_params->white_balance = -1;
+
+ memset(&m_capture_buf, 0, sizeof(m_capture_buf));
+
+ LOGV("%s :", __func__);
+}
+
+SecCamera::~SecCamera()
+{
+ LOGV("%s :", __func__);
+}
+
+int SecCamera::initCamera(int index)
+{
+ LOGV("%s :", __func__);
+ int ret = 0;
+
+ if (!m_flag_init) {
+ /* Arun C
+ * Reset the lense position only during camera starts; don't do
+ * reset between shot to shot
+ */
+ m_camera_af_flag = -1;
+
+ m_cam_fd = open(CAMERA_DEV_NAME, O_RDWR);
+ if (m_cam_fd < 0) {
+ LOGE("ERR(%s):Cannot open %s (error : %s)\n", __func__, CAMERA_DEV_NAME, strerror(errno));
+ return -1;
+ }
+ LOGV("%s: open(%s) --> m_cam_fd %d", __FUNCTION__, CAMERA_DEV_NAME, m_cam_fd);
+
+ LOGE("initCamera: m_cam_fd(%d), m_jpeg_fd(%d)", m_cam_fd, m_jpeg_fd);
+
+ ret = fimc_v4l2_querycap(m_cam_fd);
+ CHECK(ret);
+ if (!fimc_v4l2_enuminput(m_cam_fd, index))
+ return -1;
+ ret = fimc_v4l2_s_input(m_cam_fd, index);
+ CHECK(ret);
+
+ m_cam_fd2 = open(CAMERA_DEV_NAME2, O_RDWR);
+ LOGV("%s: open(%s) --> m_cam_fd2 = %d", __FUNCTION__, CAMERA_DEV_NAME2, m_cam_fd2);
+ if (m_cam_fd2 < 0) {
+ LOGE("ERR(%s):Cannot open %s (error : %s)\n", __func__, CAMERA_DEV_NAME2, strerror(errno));
+ return -1;
+ }
+
+ LOGE("initCamera: m_cam_fd2(%d)", m_cam_fd2);
+
+ ret = fimc_v4l2_querycap(m_cam_fd2);
+ CHECK(ret);
+ if (!fimc_v4l2_enuminput(m_cam_fd2, index))
+ return -1;
+ ret = fimc_v4l2_s_input(m_cam_fd2, index);
+ CHECK(ret);
+
+ m_camera_id = index;
+
+ switch (m_camera_id) {
+ case CAMERA_ID_FRONT:
+ m_preview_max_width = MAX_FRONT_CAMERA_PREVIEW_WIDTH;
+ m_preview_max_height = MAX_FRONT_CAMERA_PREVIEW_HEIGHT;
+ m_snapshot_max_width = MAX_FRONT_CAMERA_SNAPSHOT_WIDTH;
+ m_snapshot_max_height = MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT;
+ break;
+
+ case CAMERA_ID_BACK:
+ m_preview_max_width = MAX_BACK_CAMERA_PREVIEW_WIDTH;
+ m_preview_max_height = MAX_BACK_CAMERA_PREVIEW_HEIGHT;
+ m_snapshot_max_width = MAX_BACK_CAMERA_SNAPSHOT_WIDTH;
+ m_snapshot_max_height = MAX_BACK_CAMERA_SNAPSHOT_HEIGHT;
+ break;
+ }
+
+ setExifFixedAttribute();
+
+ m_flag_init = 1;
+ LOGI("%s : initialized", __FUNCTION__);
+ }
+ return 0;
+}
+
+void SecCamera::resetCamera()
+{
+ LOGV("%s :", __func__);
+ DeinitCamera();
+ initCamera(m_camera_id);
+}
+
+void SecCamera::DeinitCamera()
+{
+ LOGV("%s :", __func__);
+
+ if (m_flag_init) {
+
+ stopRecord();
+
+ /* close m_cam_fd after stopRecord() because stopRecord()
+ * uses m_cam_fd to change frame rate
+ */
+ LOGI("DeinitCamera: m_cam_fd(%d)", m_cam_fd);
+ if (m_cam_fd > -1) {
+ close(m_cam_fd);
+ m_cam_fd = -1;
+ }
+
+ LOGI("DeinitCamera: m_cam_fd2(%d)", m_cam_fd2);
+ if (m_cam_fd2 > -1) {
+ close(m_cam_fd2);
+ m_cam_fd2 = -1;
+ }
+
+ m_flag_init = 0;
+ }
+ else LOGI("%s : already deinitialized", __FUNCTION__);
+}
+
+
+int SecCamera::getCameraFd(void)
+{
+ return m_cam_fd;
+}
+
+// ======================================================================
+// Preview
+
+int SecCamera::startPreview(void)
+{
+ v4l2_streamparm streamparm;
+ struct sec_cam_parm *parms;
+ parms = (struct sec_cam_parm*)&streamparm.parm.raw_data;
+ LOGV("%s :", __func__);
+
+ // aleady started
+ if (m_flag_camera_start > 0) {
+ LOGE("ERR(%s):Preview was already started\n", __func__);
+ return 0;
+ }
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ m_events_c.fd = m_cam_fd;
+ m_events_c.events = POLLIN | POLLERR;
+
+ /* enum_fmt, s_fmt sample */
+ int ret = fimc_v4l2_enum_fmt(m_cam_fd,m_preview_v4lformat);
+ CHECK(ret);
+
+ if (m_camera_id == CAMERA_ID_BACK)
+ ret = fimc_v4l2_s_fmt(m_cam_fd, m_preview_width,m_preview_height,m_preview_v4lformat, 0);
+ else
+ ret = fimc_v4l2_s_fmt(m_cam_fd, m_preview_height,m_preview_width,m_preview_v4lformat, 0);
+ CHECK(ret);
+
+ ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, MAX_BUFFERS);
+ CHECK(ret);
+
+ LOGV("%s : m_preview_width: %d m_preview_height: %d m_angle: %d\n",
+ __func__, m_preview_width, m_preview_height, m_angle);
+
+ ret = fimc_v4l2_s_ctrl(m_cam_fd,
+ V4L2_CID_CAMERA_CHECK_DATALINE, m_chk_dataline);
+ CHECK(ret);
+
+ if (m_camera_id == CAMERA_ID_FRONT) {
+ /* VT mode setting */
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_VT_MODE, m_vtmode);
+ CHECK(ret);
+
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CHECK_FLIP, 0);
+ CHECK(ret);
+
+ }
+
+ /* start with all buffers in queue */
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ ret = fimc_v4l2_qbuf(m_cam_fd, i);
+ CHECK(ret);
+ }
+
+ ret = fimc_v4l2_streamon(m_cam_fd);
+ CHECK(ret);
+
+ m_flag_camera_start = 1;
+
+ if (m_camera_id == CAMERA_ID_BACK) {
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SCENE_MODE, m_params->scene_mode);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_WHITE_BALANCE, m_params->white_balance);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_EFFECT, m_params->effects);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FRAME_RATE, m_params->capture.timeperframe.denominator);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_METERING, m_params->metering);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SATURATION, m_params->saturation);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FOCUS_MODE, m_params->focus_mode);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CONTRAST, m_params->contrast);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SENSOR_MODE, 0);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ISO, m_params->iso);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_BRIGHTNESS, m_params->brightness);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SHARPNESS, m_params->sharpness);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FLASH_MODE, m_params->flash_mode);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_APP_CHECK, 0);
+ CHECK(ret);
+ }
+
+ ret = fimc_v4l2_s_parm(m_cam_fd, &m_streamparm);
+ CHECK(ret);
+
+ if (m_camera_id == CAMERA_ID_FRONT) {
+ /* Blur setting */
+ LOGV("m_blur_level = %d", m_blur_level);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_VGA_BLUR,
+ m_blur_level);
+ CHECK(ret);
+ }
+
+ ret = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_ESD_INT);
+ CHECK_PTR(ret);
+
+ LOGV("%s: got the first frame of the preview\n", __func__);
+
+ return 0;
+}
+
+int SecCamera::stopPreview(void)
+{
+ int ret;
+
+ LOGV("%s :", __func__);
+
+ if (m_flag_camera_start == 0) {
+ LOGW("%s: doing nothing because m_flag_camera_start is zero", __func__);
+ return 0;
+ }
+
+ if (m_params->flash_mode == FLASH_MODE_TORCH)
+ setFlashMode(FLASH_MODE_OFF);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ ret = fimc_v4l2_streamoff(m_cam_fd);
+ CHECK(ret);
+
+ m_flag_camera_start = 0;
+
+ return ret;
+}
+
+//Recording
+int SecCamera::startRecord(void)
+{
+ int ret, i;
+
+ LOGV("%s :", __func__);
+
+ // aleady started
+ if (m_flag_record_start > 0) {
+ LOGE("ERR(%s):Preview was already started\n", __func__);
+ return 0;
+ }
+
+ if (m_cam_fd2 <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ /* enum_fmt, s_fmt sample */
+ ret = fimc_v4l2_enum_fmt(m_cam_fd2, V4L2_PIX_FMT_NV12T);
+ CHECK(ret);
+
+ LOGI("%s: m_recording_width = %d, m_recording_height = %d\n",
+ __func__, m_recording_width, m_recording_height);
+
+ if (m_camera_id == CAMERA_ID_BACK) {
+ ret = fimc_v4l2_s_fmt(m_cam_fd2, m_recording_width,
+ m_recording_height, V4L2_PIX_FMT_NV12T, 0);
+ }
+ else {
+ ret = fimc_v4l2_s_fmt(m_cam_fd2, m_recording_height,
+ m_recording_width, V4L2_PIX_FMT_NV12T, 0);
+ }
+ CHECK(ret);
+
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FRAME_RATE,
+ m_params->capture.timeperframe.denominator);
+ CHECK(ret);
+
+ ret = fimc_v4l2_reqbufs(m_cam_fd2, V4L2_BUF_TYPE_VIDEO_CAPTURE, MAX_BUFFERS);
+ CHECK(ret);
+
+ /* start with all buffers in queue */
+ for (i = 0; i < MAX_BUFFERS; i++) {
+ ret = fimc_v4l2_qbuf(m_cam_fd2, i);
+ CHECK(ret);
+ }
+
+ ret = fimc_v4l2_streamon(m_cam_fd2);
+ CHECK(ret);
+
+ // Get and throw away the first frame since it is often garbled.
+ memset(&m_events_c2, 0, sizeof(m_events_c2));
+ m_events_c2.fd = m_cam_fd2;
+ m_events_c2.events = POLLIN | POLLERR;
+ ret = fimc_poll(&m_events_c2);
+ CHECK(ret);
+
+ m_flag_record_start = 1;
+
+ return 0;
+}
+
+int SecCamera::stopRecord(void)
+{
+ int ret;
+
+ LOGV("%s :", __func__);
+
+ if (m_flag_record_start == 0) {
+ LOGW("%s: doing nothing because m_flag_record_start is zero", __func__);
+ return 0;
+ }
+
+ if (m_cam_fd2 <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ m_flag_record_start = 0;
+
+ ret = fimc_v4l2_streamoff(m_cam_fd2);
+ CHECK(ret);
+
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FRAME_RATE,
+ FRAME_RATE_AUTO);
+ CHECK(ret);
+
+ return 0;
+}
+
+unsigned int SecCamera::getRecPhyAddrY(int index)
+{
+ unsigned int addr_y;
+
+ addr_y = fimc_v4l2_s_ctrl(m_cam_fd2, V4L2_CID_PADDR_Y, index);
+ CHECK((int)addr_y);
+ return addr_y;
+}
+
+unsigned int SecCamera::getRecPhyAddrC(int index)
+{
+ unsigned int addr_c;
+
+ addr_c = fimc_v4l2_s_ctrl(m_cam_fd2, V4L2_CID_PADDR_CBCR, index);
+ CHECK((int)addr_c);
+ return addr_c;
+}
+
+unsigned int SecCamera::getPhyAddrY(int index)
+{
+ unsigned int addr_y;
+
+ addr_y = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_PADDR_Y, index);
+ CHECK((int)addr_y);
+ return addr_y;
+}
+
+unsigned int SecCamera::getPhyAddrC(int index)
+{
+ unsigned int addr_c;
+
+ addr_c = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_PADDR_CBCR, index);
+ CHECK((int)addr_c);
+ return addr_c;
+}
+
+void SecCamera::pausePreview()
+{
+ fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_STREAM_PAUSE, 0);
+}
+
+int SecCamera::getPreview()
+{
+ int index;
+ int ret;
+
+ if (m_flag_camera_start == 0 || previewPoll(true) == 0) {
+ LOGE("ERR(%s):Start Camera Device Reset \n", __func__);
+ /* GAUDI Project([arun.c@samsung.com]) 2010.05.20. [Implemented ESD code] */
+ /*
+ * When there is no data for more than 1 second from the camera we inform
+ * the FIMC driver by calling fimc_v4l2_s_input() with a special value = 1000
+ * FIMC driver identify that there is something wrong with the camera
+ * and it restarts the sensor.
+ */
+ stopPreview();
+ /* Reset Only Camera Device */
+ ret = fimc_v4l2_querycap(m_cam_fd);
+ CHECK(ret);
+ if (fimc_v4l2_enuminput(m_cam_fd, m_camera_id))
+ return -1;
+ ret = fimc_v4l2_s_input(m_cam_fd, 1000);
+ CHECK(ret);
+ ret = startPreview();
+ if (ret < 0) {
+ LOGE("ERR(%s): startPreview() return %d\n", __func__, ret);
+ return 0;
+ }
+ }
+
+ index = fimc_v4l2_dqbuf(m_cam_fd);
+ if (!(0 <= index && index < MAX_BUFFERS)) {
+ LOGE("ERR(%s):wrong index = %d\n", __func__, index);
+ return -1;
+ }
+
+ ret = fimc_v4l2_qbuf(m_cam_fd, index);
+ CHECK(ret);
+
+ return index;
+}
+
+int SecCamera::getRecordFrame()
+{
+ if (m_flag_record_start == 0) {
+ LOGE("%s: m_flag_record_start is 0", __func__);
+ return -1;
+ }
+
+ previewPoll(false);
+ return fimc_v4l2_dqbuf(m_cam_fd2);
+}
+
+int SecCamera::releaseRecordFrame(int index)
+{
+ if (!m_flag_record_start) {
+ /* this can happen when recording frames are returned after
+ * the recording is stopped at the driver level. we don't
+ * need to return the buffers in this case and we've seen
+ * cases where fimc could crash if we called qbuf and it
+ * wasn't expecting it.
+ */
+ LOGI("%s: recording not in progress, ignoring", __func__);
+ return 0;
+ }
+
+ return fimc_v4l2_qbuf(m_cam_fd2, index);
+}
+
+int SecCamera::setPreviewSize(int width, int height, int pixel_format)
+{
+ LOGV("%s(width(%d), height(%d), format(%d))", __func__, width, height, pixel_format);
+
+ int v4lpixelformat = pixel_format;
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+ if (v4lpixelformat == V4L2_PIX_FMT_YUV420)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YUV420");
+ else if (v4lpixelformat == V4L2_PIX_FMT_NV12)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_NV12");
+ else if (v4lpixelformat == V4L2_PIX_FMT_NV12T)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_NV12T");
+ else if (v4lpixelformat == V4L2_PIX_FMT_NV21)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_NV21");
+ else if (v4lpixelformat == V4L2_PIX_FMT_YUV422P)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YUV422P");
+ else if (v4lpixelformat == V4L2_PIX_FMT_YUYV)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YUYV");
+ else if (v4lpixelformat == V4L2_PIX_FMT_RGB565)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_RGB565");
+ else
+ LOGV("PreviewFormat:UnknownFormat");
+#endif
+ m_preview_width = width;
+ m_preview_height = height;
+ m_preview_v4lformat = v4lpixelformat;
+
+ return 0;
+}
+
+int SecCamera::getPreviewSize(int *width, int *height, int *frame_size)
+{
+ *width = m_preview_width;
+ *height = m_preview_height;
+ *frame_size = m_frameSize(m_preview_v4lformat, m_preview_width, m_preview_height);
+
+ return 0;
+}
+
+int SecCamera::getPreviewMaxSize(int *width, int *height)
+{
+ *width = m_preview_max_width;
+ *height = m_preview_max_height;
+
+ return 0;
+}
+
+int SecCamera::getPreviewPixelFormat(void)
+{
+ return m_preview_v4lformat;
+}
+
+
+// ======================================================================
+// Snapshot
+/*
+ * Devide getJpeg() as two funcs, setSnapshotCmd() & getJpeg() because of the shutter sound timing.
+ * Here, just send the capture cmd to camera ISP to start JPEG capture.
+ */
+int SecCamera::setSnapshotCmd(void)
+{
+ LOGV("%s :", __func__);
+
+ int ret = 0;
+
+ LOG_TIME_DEFINE(0)
+ LOG_TIME_DEFINE(1)
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return 0;
+ }
+
+ if (m_flag_camera_start > 0) {
+ LOG_TIME_START(0)
+ LOGW("WARN(%s):Camera was in preview, should have been stopped\n", __func__);
+ stopPreview();
+ LOG_TIME_END(0)
+ }
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ m_events_c.fd = m_cam_fd;
+ m_events_c.events = POLLIN | POLLERR;
+
+ LOG_TIME_START(1) // prepare
+ int nframe = 1;
+
+ ret = fimc_v4l2_enum_fmt(m_cam_fd,m_snapshot_v4lformat);
+ CHECK(ret);
+ ret = fimc_v4l2_s_fmt_cap(m_cam_fd, m_snapshot_width, m_snapshot_height, V4L2_PIX_FMT_JPEG);
+ CHECK(ret);
+ ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, nframe);
+ CHECK(ret);
+ ret = fimc_v4l2_querybuf(m_cam_fd, &m_capture_buf, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ CHECK(ret);
+
+ ret = fimc_v4l2_qbuf(m_cam_fd, 0);
+ CHECK(ret);
+
+ ret = fimc_v4l2_streamon(m_cam_fd);
+ CHECK(ret);
+
+ LOG_TIME_END(1)
+
+ return 0;
+}
+
+int SecCamera::endSnapshot(void)
+{
+ int ret;
+
+ LOGI("%s :", __func__);
+ if (m_capture_buf.start) {
+ munmap(m_capture_buf.start, m_capture_buf.length);
+ LOGI("munmap():virt. addr %p size = %d\n",
+ m_capture_buf.start, m_capture_buf.length);
+ m_capture_buf.start = NULL;
+ m_capture_buf.length = 0;
+ }
+ return 0;
+}
+
+/*
+ * Set Jpeg quality & exif info and get JPEG data from camera ISP
+ */
+unsigned char* SecCamera::getJpeg(int *jpeg_size, unsigned int *phyaddr)
+{
+ LOGV("%s :", __func__);
+
+ int index, ret = 0;
+ unsigned char *addr;
+
+ LOG_TIME_DEFINE(2)
+
+ // capture
+ ret = fimc_poll(&m_events_c);
+ CHECK_PTR(ret);
+ index = fimc_v4l2_dqbuf(m_cam_fd);
+ if (index != 0) {
+ LOGE("ERR(%s):wrong index = %d\n", __func__, index);
+ return NULL;
+ }
+
+ *jpeg_size = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_MAIN_SIZE);
+ CHECK_PTR(*jpeg_size);
+
+ int main_offset = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_MAIN_OFFSET);
+ CHECK_PTR(main_offset);
+ m_postview_offset = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET);
+ CHECK_PTR(m_postview_offset);
+
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_STREAM_PAUSE, 0);
+ CHECK_PTR(ret);
+ LOGV("\nsnapshot dqueued buffer = %d snapshot_width = %d snapshot_height = %d, size = %d\n\n",
+ index, m_snapshot_width, m_snapshot_height, *jpeg_size);
+
+ addr = (unsigned char*)(m_capture_buf.start) + main_offset;
+ *phyaddr = getPhyAddrY(index) + m_postview_offset;
+
+ LOG_TIME_START(2) // post
+ ret = fimc_v4l2_streamoff(m_cam_fd);
+ CHECK_PTR(ret);
+ LOG_TIME_END(2)
+
+ return addr;
+}
+
+int SecCamera::getExif(unsigned char *pExifDst, unsigned char *pThumbSrc)
+{
+ JpegEncoder jpgEnc;
+
+ LOGV("%s : m_jpeg_thumbnail_width = %d, height = %d",
+ __func__, m_jpeg_thumbnail_width, m_jpeg_thumbnail_height);
+ if ((m_jpeg_thumbnail_width > 0) && (m_jpeg_thumbnail_height > 0)) {
+ int inFormat = JPG_MODESEL_YCBCR;
+ int outFormat = JPG_422;
+ switch (m_snapshot_v4lformat) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ outFormat = JPG_420;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUV422P:
+ outFormat = JPG_422;
+ break;
+ }
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_IN_FORMAT, inFormat) != JPG_SUCCESS)
+ return -1;
+
+ if (jpgEnc.setConfig(JPEG_SET_SAMPING_MODE, outFormat) != JPG_SUCCESS)
+ return -1;
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_QUALITY, JPG_QUALITY_LEVEL_2) != JPG_SUCCESS)
+ return -1;
+
+ int thumbWidth, thumbHeight, thumbSrcSize;
+ getThumbnailConfig(&thumbWidth, &thumbHeight, &thumbSrcSize);
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_WIDTH, thumbWidth) != JPG_SUCCESS)
+ return -1;
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_HEIGHT, thumbHeight) != JPG_SUCCESS)
+ return -1;
+
+ char *pInBuf = (char *)jpgEnc.getInBuf(thumbSrcSize);
+ if (pInBuf == NULL)
+ return -1;
+ memcpy(pInBuf, pThumbSrc, thumbSrcSize);
+
+ unsigned int thumbSize;
+
+ jpgEnc.encode(&thumbSize, NULL);
+
+ LOGV("%s : enableThumb set to true", __func__);
+ mExifInfo.enableThumb = true;
+ } else {
+ LOGV("%s : enableThumb set to false", __func__);
+ mExifInfo.enableThumb = false;
+ }
+
+ unsigned int exifSize;
+
+ setExifChangedAttribute();
+
+ LOGV("%s: calling jpgEnc.makeExif, mExifInfo.width set to %d, height to %d\n",
+ __func__, mExifInfo.width, mExifInfo.height);
+
+ jpgEnc.makeExif(pExifDst, &mExifInfo, &exifSize, true);
+
+ return exifSize;
+}
+
+void SecCamera::getPostViewConfig(int *width, int *height, int *size)
+{
+ if (m_preview_width == 1024) {
+ *width = BACK_CAMERA_POSTVIEW_WIDE_WIDTH;
+ *height = BACK_CAMERA_POSTVIEW_HEIGHT;
+ *size = BACK_CAMERA_POSTVIEW_WIDE_WIDTH * BACK_CAMERA_POSTVIEW_HEIGHT * BACK_CAMERA_POSTVIEW_BPP / 8;
+ } else {
+ *width = BACK_CAMERA_POSTVIEW_WIDTH;
+ *height = BACK_CAMERA_POSTVIEW_HEIGHT;
+ *size = BACK_CAMERA_POSTVIEW_WIDTH * BACK_CAMERA_POSTVIEW_HEIGHT * BACK_CAMERA_POSTVIEW_BPP / 8;
+ }
+ LOGV("[5B] m_preview_width : %d, mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d",
+ m_preview_width, *width, *height, *size);
+}
+
+void SecCamera::getThumbnailConfig(int *width, int *height, int *size)
+{
+ if (m_camera_id == CAMERA_ID_BACK) {
+ *width = BACK_CAMERA_THUMBNAIL_WIDTH;
+ *height = BACK_CAMERA_THUMBNAIL_HEIGHT;
+ *size = BACK_CAMERA_THUMBNAIL_WIDTH * BACK_CAMERA_THUMBNAIL_HEIGHT
+ * BACK_CAMERA_THUMBNAIL_BPP / 8;
+ } else {
+ *width = FRONT_CAMERA_THUMBNAIL_WIDTH;
+ *height = FRONT_CAMERA_THUMBNAIL_HEIGHT;
+ *size = FRONT_CAMERA_THUMBNAIL_WIDTH * FRONT_CAMERA_THUMBNAIL_HEIGHT
+ * FRONT_CAMERA_THUMBNAIL_BPP / 8;
+ }
+}
+
+int SecCamera::getPostViewOffset(void)
+{
+ return m_postview_offset;
+}
+
+int SecCamera::getSnapshotAndJpeg(unsigned char *yuv_buf, unsigned char *jpeg_buf,
+ unsigned int *output_size)
+{
+ LOGV("%s :", __func__);
+
+ int index;
+ //unsigned int addr;
+ unsigned char *addr;
+ int ret = 0;
+
+ LOG_TIME_DEFINE(0)
+ LOG_TIME_DEFINE(1)
+ LOG_TIME_DEFINE(2)
+ LOG_TIME_DEFINE(3)
+ LOG_TIME_DEFINE(4)
+ LOG_TIME_DEFINE(5)
+
+ //fimc_v4l2_streamoff(m_cam_fd); [zzangdol] remove - it is separate in HWInterface with camera_id
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ if (m_flag_camera_start > 0) {
+ LOG_TIME_START(0)
+ LOGW("WARN(%s):Camera was in preview, should have been stopped\n", __func__);
+ stopPreview();
+ LOG_TIME_END(0)
+ }
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ m_events_c.fd = m_cam_fd;
+ m_events_c.events = POLLIN | POLLERR;
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+ if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV420)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_YUV420");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_NV12");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12T)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_NV12T");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV21)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_NV21");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV422P)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_YUV422P");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUYV)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_YUYV");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_UYVY)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_UYVY");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_RGB565");
+ else
+ LOGV("SnapshotFormat:UnknownFormat");
+#endif
+
+ LOG_TIME_START(1) // prepare
+ int nframe = 1;
+
+ ret = fimc_v4l2_enum_fmt(m_cam_fd,m_snapshot_v4lformat);
+ CHECK(ret);
+ // FFC: Swap width and height
+ ret = fimc_v4l2_s_fmt_cap(m_cam_fd, m_snapshot_height, m_snapshot_width, m_snapshot_v4lformat);
+ CHECK(ret);
+ ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, nframe);
+ CHECK(ret);
+ ret = fimc_v4l2_querybuf(m_cam_fd, &m_capture_buf, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ CHECK(ret);
+
+ ret = fimc_v4l2_qbuf(m_cam_fd, 0);
+ CHECK(ret);
+
+ ret = fimc_v4l2_streamon(m_cam_fd);
+ CHECK(ret);
+ LOG_TIME_END(1)
+
+ LOG_TIME_START(2) // capture
+ fimc_poll(&m_events_c);
+ index = fimc_v4l2_dqbuf(m_cam_fd);
+ fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_STREAM_PAUSE, 0);
+ LOGV("\nsnapshot dequeued buffer = %d snapshot_width = %d snapshot_height = %d\n\n",
+ index, m_snapshot_width, m_snapshot_height);
+
+ LOG_TIME_END(2)
+
+ LOGI("%s : calling memcpy from m_capture_buf", __func__);
+ memcpy(yuv_buf, (unsigned char*)m_capture_buf.start, m_snapshot_width * m_snapshot_height * 2);
+ LOG_TIME_START(5) // post
+ fimc_v4l2_streamoff(m_cam_fd);
+ LOG_TIME_END(5)
+
+ LOG_CAMERA("getSnapshotAndJpeg intervals : stopPreview(%lu), prepare(%lu),"
+ " capture(%lu), memcpy(%lu), yuv2Jpeg(%lu), post(%lu) us",
+ LOG_TIME(0), LOG_TIME(1), LOG_TIME(2), LOG_TIME(3), LOG_TIME(4), LOG_TIME(5));
+ /* JPEG encoding */
+ JpegEncoder jpgEnc;
+ int inFormat = JPG_MODESEL_YCBCR;
+ int outFormat = JPG_422;
+
+ switch (m_snapshot_v4lformat) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ outFormat = JPG_420;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUV422P:
+ default:
+ outFormat = JPG_422;
+ break;
+ }
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_IN_FORMAT, inFormat) != JPG_SUCCESS)
+ LOGE("[JPEG_SET_ENCODE_IN_FORMAT] Error\n");
+
+ if (jpgEnc.setConfig(JPEG_SET_SAMPING_MODE, outFormat) != JPG_SUCCESS)
+ LOGE("[JPEG_SET_SAMPING_MODE] Error\n");
+
+ image_quality_type_t jpegQuality;
+ if (m_jpeg_quality >= 90)
+ jpegQuality = JPG_QUALITY_LEVEL_1;
+ else if (m_jpeg_quality >= 80)
+ jpegQuality = JPG_QUALITY_LEVEL_2;
+ else if (m_jpeg_quality >= 70)
+ jpegQuality = JPG_QUALITY_LEVEL_3;
+ else
+ jpegQuality = JPG_QUALITY_LEVEL_4;
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_QUALITY, jpegQuality) != JPG_SUCCESS)
+ LOGE("[JPEG_SET_ENCODE_QUALITY] Error\n");
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_WIDTH, m_snapshot_width) != JPG_SUCCESS)
+ LOGE("[JPEG_SET_ENCODE_WIDTH] Error\n");
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_HEIGHT, m_snapshot_height) != JPG_SUCCESS)
+ LOGE("[JPEG_SET_ENCODE_HEIGHT] Error\n");
+
+ unsigned int snapshot_size = m_snapshot_width * m_snapshot_height * 2;
+ unsigned char *pInBuf = (unsigned char *)jpgEnc.getInBuf(snapshot_size);
+
+ if (pInBuf == NULL) {
+ LOGE("JPEG input buffer is NULL!!\n");
+ return -1;
+ }
+ memcpy(pInBuf, yuv_buf, snapshot_size);
+
+ setExifChangedAttribute();
+ jpgEnc.encode(output_size, NULL);
+
+ uint64_t outbuf_size;
+ unsigned char *pOutBuf = (unsigned char *)jpgEnc.getOutBuf(&outbuf_size);
+
+ if (pOutBuf == NULL) {
+ LOGE("JPEG output buffer is NULL!!\n");
+ return -1;
+ }
+
+ memcpy(jpeg_buf, pOutBuf, outbuf_size);
+
+ return 0;
+}
+
+
+int SecCamera::setSnapshotSize(int width, int height)
+{
+ LOGV("%s(width(%d), height(%d))", __func__, width, height);
+
+ m_snapshot_width = width;
+ m_snapshot_height = height;
+
+ return 0;
+}
+
+int SecCamera::getSnapshotSize(int *width, int *height, int *frame_size)
+{
+ *width = m_snapshot_width;
+ *height = m_snapshot_height;
+
+ int frame = 0;
+
+ frame = m_frameSize(m_snapshot_v4lformat, m_snapshot_width, m_snapshot_height);
+
+ // set it big.
+ if (frame == 0)
+ frame = m_snapshot_width * m_snapshot_height * BPP;
+
+ *frame_size = frame;
+
+ return 0;
+}
+
+int SecCamera::getSnapshotMaxSize(int *width, int *height)
+{
+ switch (m_camera_id) {
+ case CAMERA_ID_FRONT:
+ m_snapshot_max_width = MAX_FRONT_CAMERA_SNAPSHOT_WIDTH;
+ m_snapshot_max_height = MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT;
+ break;
+
+ default:
+ case CAMERA_ID_BACK:
+ m_snapshot_max_width = MAX_BACK_CAMERA_SNAPSHOT_WIDTH;
+ m_snapshot_max_height = MAX_BACK_CAMERA_SNAPSHOT_HEIGHT;
+ break;
+ }
+
+ *width = m_snapshot_max_width;
+ *height = m_snapshot_max_height;
+
+ return 0;
+}
+
+int SecCamera::setSnapshotPixelFormat(int pixel_format)
+{
+ int v4lpixelformat= pixel_format;
+
+ if (m_snapshot_v4lformat != v4lpixelformat) {
+ m_snapshot_v4lformat = v4lpixelformat;
+ }
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+ if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV420)
+ LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_YUV420", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12T)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12T", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV21)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV21", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV422P)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUV422P", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUYV)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUYV", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_UYVY)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_UYVY", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_RGB565", __func__);
+ else
+ LOGD("SnapshotFormat:UnknownFormat");
+#endif
+ return 0;
+}
+
+int SecCamera::getSnapshotPixelFormat(void)
+{
+ return m_snapshot_v4lformat;
+}
+
+// ======================================================================
+// Settings
+
+int SecCamera::getCameraId(void)
+{
+ return m_camera_id;
+}
+
+// -----------------------------------
+
+int SecCamera::setAutofocus(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_ON) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int SecCamera::getAutoFocusResult(void)
+{
+ int af_result;
+
+ af_result = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT);
+
+ LOGV("%s : returning %d", __func__, af_result);
+
+ return af_result;
+}
+
+int SecCamera::cancelAutofocus(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+// -----------------------------------
+
+int SecCamera::zoomIn(void)
+{
+ LOGV("%s :", __func__);
+ return 0;
+}
+
+int SecCamera::zoomOut(void)
+{
+ LOGV("%s :", __func__);
+ return 0;
+}
+
+// -----------------------------------
+
+int SecCamera::setFrameRate(int frame_rate)
+{
+ LOGV("%s(FrameRate(%d))", __func__, frame_rate);
+
+ if (frame_rate < FRAME_RATE_AUTO || FRAME_RATE_MAX < frame_rate )
+ LOGE("ERR(%s):Invalid frame_rate(%d)", __func__, frame_rate);
+
+ if (m_params->capture.timeperframe.denominator != (unsigned)frame_rate) {
+ m_params->capture.timeperframe.denominator = frame_rate;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FRAME_RATE, frame_rate) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FRAME_RATE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------
+
+int SecCamera::setVerticalMirror(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_VFLIP, 0) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_VFLIP", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int SecCamera::setHorizontalMirror(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_HFLIP, 0) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_HFLIP", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+// -----------------------------------
+
+int SecCamera::setWhiteBalance(int white_balance)
+{
+ LOGV("%s(white_balance(%d))", __func__, white_balance);
+
+ if (white_balance <= WHITE_BALANCE_BASE || WHITE_BALANCE_MAX <= white_balance) {
+ LOGE("ERR(%s):Invalid white_balance(%d)", __func__, white_balance);
+ return -1;
+ }
+
+ if (m_params->white_balance != white_balance) {
+ m_params->white_balance = white_balance;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_WHITE_BALANCE, white_balance) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_WHITE_BALANCE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getWhiteBalance(void)
+{
+ LOGV("%s : white_balance(%d)", __func__, m_params->white_balance);
+ return m_params->white_balance;
+}
+
+// -----------------------------------
+
+int SecCamera::setBrightness(int brightness)
+{
+ LOGV("%s(brightness(%d))", __func__, brightness);
+
+ brightness += EV_DEFAULT;
+
+ if (brightness < EV_MINUS_4 || EV_PLUS_4 < brightness) {
+ LOGE("ERR(%s):Invalid brightness(%d)", __func__, brightness);
+ return -1;
+ }
+
+ if (m_params->brightness != brightness) {
+ m_params->brightness = brightness;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_BRIGHTNESS, brightness) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BRIGHTNESS", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getBrightness(void)
+{
+ LOGV("%s : brightness(%d)", __func__, m_params->brightness);
+ return m_params->brightness;
+}
+
+// -----------------------------------
+
+int SecCamera::setImageEffect(int image_effect)
+{
+ LOGV("%s(image_effect(%d))", __func__, image_effect);
+
+ if (image_effect <= IMAGE_EFFECT_BASE || IMAGE_EFFECT_MAX <= image_effect) {
+ LOGE("ERR(%s):Invalid image_effect(%d)", __func__, image_effect);
+ return -1;
+ }
+
+ if (m_params->effects != image_effect) {
+ m_params->effects = image_effect;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_EFFECT, image_effect) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_EFFECT", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getImageEffect(void)
+{
+ LOGV("%s : image_effect(%d)", __func__, m_params->effects);
+ return m_params->effects;
+}
+
+//======================================================================
+int SecCamera::setSceneMode(int scene_mode)
+{
+ LOGV("%s(scene_mode(%d))", __func__, scene_mode);
+
+ if (scene_mode <= SCENE_MODE_BASE || SCENE_MODE_MAX <= scene_mode) {
+ LOGE("ERR(%s):Invalid scene_mode (%d)", __func__, scene_mode);
+ return -1;
+ }
+
+ if (m_params->scene_mode != scene_mode) {
+ m_params->scene_mode = scene_mode;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SCENE_MODE, scene_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SCENE_MODE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getSceneMode(void)
+{
+ return m_params->scene_mode;
+}
+
+//======================================================================
+
+int SecCamera::setFlashMode(int flash_mode)
+{
+ LOGV("%s(flash_mode(%d))", __func__, flash_mode);
+
+ if (flash_mode <= FLASH_MODE_BASE || FLASH_MODE_MAX <= flash_mode) {
+ LOGE("ERR(%s):Invalid flash_mode (%d)", __func__, flash_mode);
+ return -1;
+ }
+
+ if (m_params->flash_mode != flash_mode) {
+ m_params->flash_mode = flash_mode;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FLASH_MODE, flash_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FLASH_MODE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getFlashMode(void)
+{
+ return m_params->flash_mode;
+}
+
+//======================================================================
+
+int SecCamera::setISO(int iso_value)
+{
+ LOGV("%s(iso_value(%d))", __func__, iso_value);
+ if (iso_value < ISO_AUTO || ISO_MAX <= iso_value) {
+ LOGE("ERR(%s):Invalid iso_value (%d)", __func__, iso_value);
+ return -1;
+ }
+
+ if (m_params->iso != iso_value) {
+ m_params->iso = iso_value;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ISO, iso_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ISO", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getISO(void)
+{
+ return m_params->iso;
+}
+
+//======================================================================
+
+int SecCamera::setContrast(int contrast_value)
+{
+ LOGV("%s(contrast_value(%d))", __func__, contrast_value);
+
+ if (contrast_value < CONTRAST_MINUS_2 || CONTRAST_MAX <= contrast_value) {
+ LOGE("ERR(%s):Invalid contrast_value (%d)", __func__, contrast_value);
+ return -1;
+ }
+
+ if (m_params->contrast != contrast_value) {
+ m_params->contrast = contrast_value;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CONTRAST, contrast_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_CONTRAST", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getContrast(void)
+{
+ return m_params->contrast;
+}
+
+//======================================================================
+
+int SecCamera::setSaturation(int saturation_value)
+{
+ LOGV("%s(saturation_value(%d))", __func__, saturation_value);
+
+ if (saturation_value saturation != saturation_value) {
+ m_params->saturation = saturation_value;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SATURATION, saturation_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SATURATION", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getSaturation(void)
+{
+ return m_params->saturation;
+}
+
+//======================================================================
+
+int SecCamera::setSharpness(int sharpness_value)
+{
+ LOGV("%s(sharpness_value(%d))", __func__, sharpness_value);
+
+ if (sharpness_value < SHARPNESS_MINUS_2 || SHARPNESS_MAX <= sharpness_value) {
+ LOGE("ERR(%s):Invalid sharpness_value (%d)", __func__, sharpness_value);
+ return -1;
+ }
+
+ if (m_params->sharpness != sharpness_value) {
+ m_params->sharpness = sharpness_value;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SHARPNESS, sharpness_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SHARPNESS", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getSharpness(void)
+{
+ return m_params->sharpness;
+}
+
+//======================================================================
+
+int SecCamera::setMetering(int metering_value)
+{
+ LOGV("%s(metering (%d))", __func__, metering_value);
+
+ if (metering_value <= METERING_BASE || METERING_MAX <= metering_value) {
+ LOGE("ERR(%s):Invalid metering_value (%d)", __func__, metering_value);
+ return -1;
+ }
+
+ if (m_params->metering != metering_value) {
+ m_params->metering = metering_value;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_METERING, metering_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_METERING", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getMetering(void)
+{
+ return m_params->metering;
+}
+
+//======================================================================
+
+int SecCamera::setJpegQuality(int jpeg_quality)
+{
+ LOGV("%s(jpeg_quality (%d))", __func__, jpeg_quality);
+
+ if (jpeg_quality < JPEG_QUALITY_ECONOMY || JPEG_QUALITY_MAX <= jpeg_quality) {
+ LOGE("ERR(%s):Invalid jpeg_quality (%d)", __func__, jpeg_quality);
+ return -1;
+ }
+
+ if (m_jpeg_quality != jpeg_quality) {
+ m_jpeg_quality = jpeg_quality;
+ if (m_flag_camera_start && (m_camera_id == CAMERA_ID_BACK)) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_QUALITY, jpeg_quality) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAM_JPEG_QUALITY", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getJpegQuality(void)
+{
+ return m_jpeg_quality;
+}
+
+//======================================================================
+
+int SecCamera::setZoom(int zoom_level)
+{
+ LOGV("%s(zoom_level (%d))", __func__, zoom_level);
+
+ if (zoom_level < ZOOM_LEVEL_0 || ZOOM_LEVEL_MAX <= zoom_level) {
+ LOGE("ERR(%s):Invalid zoom_level (%d)", __func__, zoom_level);
+ return -1;
+ }
+
+ if (m_zoom_level != zoom_level) {
+ m_zoom_level = zoom_level;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ZOOM, zoom_level) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ZOOM", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getZoom(void)
+{
+ return m_zoom_level;
+}
+
+//======================================================================
+
+int SecCamera::setObjectTracking(int object_tracking)
+{
+ LOGV("%s(object_tracking (%d))", __func__, object_tracking);
+
+ if (object_tracking < OBJECT_TRACKING_OFF || OBJECT_TRACKING_MAX <= object_tracking) {
+ LOGE("ERR(%s):Invalid object_tracking (%d)", __func__, object_tracking);
+ return -1;
+ }
+
+ if (m_object_tracking != object_tracking) {
+ m_object_tracking = object_tracking;
+ }
+
+ return 0;
+}
+
+int SecCamera::getObjectTracking(void)
+{
+ return m_object_tracking;
+}
+
+int SecCamera::getObjectTrackingStatus(void)
+{
+ int obj_status = 0;
+ obj_status = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJ_TRACKING_STATUS);
+ return obj_status;
+}
+
+int SecCamera::setObjectTrackingStartStop(int start_stop)
+{
+ LOGV("%s(object_tracking_start_stop (%d))", __func__, start_stop);
+
+ if (m_object_tracking_start_stop != start_stop) {
+ m_object_tracking_start_stop = start_stop;
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP, start_stop) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::setTouchAFStartStop(int start_stop)
+{
+ LOGV("%s(touch_af_start_stop (%d))", __func__, start_stop);
+
+ if (m_touch_af_start_stop != start_stop) {
+ m_touch_af_start_stop = start_stop;
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_TOUCH_AF_START_STOP, start_stop) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_TOUCH_AF_START_STOP", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+//======================================================================
+
+int SecCamera::setFocusMode(int focus_mode)
+{
+ LOGV("%s(focus_mode(%d))", __func__, focus_mode);
+
+ if (FOCUS_MODE_MAX <= focus_mode) {
+ LOGE("ERR(%s):Invalid focus_mode (%d)", __func__, focus_mode);
+ return -1;
+ }
+
+ if (m_params->focus_mode != focus_mode) {
+ m_params->focus_mode = focus_mode;
+
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FOCUS_MODE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getFocusMode(void)
+{
+ return m_params->focus_mode;
+}
+
+//======================================================================
+
+int SecCamera::setObjectPosition(int x, int y)
+{
+ LOGV("%s(setObjectPosition(x=%d, y=%d))", __func__, x, y);
+
+ if (m_preview_width ==640)
+ x = x - 80;
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJECT_POSITION_X, x) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJECT_POSITION_X", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJECT_POSITION_Y, y) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJECT_POSITION_Y", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+//======================================================================
+int SecCamera::setRecordingSize(int width, int height)
+{
+ LOGV("%s(width(%d), height(%d))", __func__, width, height);
+
+ m_recording_width = width;
+ m_recording_height = height;
+
+ return 0;
+}
+
+//======================================================================
+
+int SecCamera::setExifOrientationInfo(int orientationInfo)
+{
+ LOGV("%s(orientationInfo(%d))", __func__, orientationInfo);
+
+ if (orientationInfo < 0) {
+ LOGE("ERR(%s):Invalid orientationInfo (%d)", __func__, orientationInfo);
+ return -1;
+ }
+ m_exif_orientation = orientationInfo;
+
+ return 0;
+}
+
+/*Video call*/
+int SecCamera::setVTmode(int vtmode)
+{
+ LOGV("%s(vtmode (%d))", __func__, vtmode);
+
+ if (vtmode < VT_MODE_OFF || VT_MODE_MAX <= vtmode) {
+ LOGE("ERR(%s):Invalid vtmode (%d)", __func__, vtmode);
+ return -1;
+ }
+
+ if (m_vtmode != vtmode) {
+ m_vtmode = vtmode;
+ }
+
+ return 0;
+}
+
+/* Camcorder fix fps */
+int SecCamera::setSensorMode(int sensor_mode)
+{
+ LOGV("%s(sensor_mode (%d))", __func__, sensor_mode);
+
+ if (sensor_mode < SENSOR_MODE_CAMERA || SENSOR_MODE_MOVIE < sensor_mode) {
+ LOGE("ERR(%s):Invalid sensor mode (%d)", __func__, sensor_mode);
+ return -1;
+ }
+
+ if (m_sensor_mode != sensor_mode) {
+ m_sensor_mode = sensor_mode;
+ }
+
+ return 0;
+}
+
+/* Shot mode */
+/* SINGLE = 0
+* CONTINUOUS = 1
+* PANORAMA = 2
+* SMILE = 3
+* SELF = 6
+*/
+int SecCamera::setShotMode(int shot_mode)
+{
+ LOGV("%s(shot_mode (%d))", __func__, shot_mode);
+ if (shot_mode < SHOT_MODE_SINGLE || SHOT_MODE_SELF < shot_mode) {
+ LOGE("ERR(%s):Invalid shot_mode (%d)", __func__, shot_mode);
+ return -1;
+ }
+ m_shot_mode = shot_mode;
+
+ return 0;
+}
+
+int SecCamera::getVTmode(void)
+{
+ return m_vtmode;
+}
+
+int SecCamera::setBlur(int blur_level)
+{
+ LOGV("%s(level (%d))", __func__, blur_level);
+
+ if (blur_level < BLUR_LEVEL_0 || BLUR_LEVEL_MAX <= blur_level) {
+ LOGE("ERR(%s):Invalid level (%d)", __func__, blur_level);
+ return -1;
+ }
+
+ if (m_blur_level != blur_level) {
+ m_blur_level = blur_level;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_VGA_BLUR, blur_level) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_VGA_BLUR", __func__);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+int SecCamera::getBlur(void)
+{
+ return m_blur_level;
+}
+
+int SecCamera::setDataLineCheck(int chk_dataline)
+{
+ LOGV("%s(chk_dataline (%d))", __func__, chk_dataline);
+
+ if (chk_dataline < CHK_DATALINE_OFF || CHK_DATALINE_MAX <= chk_dataline) {
+ LOGE("ERR(%s):Invalid chk_dataline (%d)", __func__, chk_dataline);
+ return -1;
+ }
+
+ m_chk_dataline = chk_dataline;
+
+ return 0;
+}
+
+int SecCamera::getDataLineCheck(void)
+{
+ return m_chk_dataline;
+}
+
+int SecCamera::setDataLineCheckStop(void)
+{
+ LOGV("%s", __func__);
+
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CHECK_DATALINE_STOP, 1) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_CHECK_DATALINE_STOP", __func__);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+const __u8* SecCamera::getCameraSensorName(void)
+{
+ LOGV("%s", __func__);
+
+ return fimc_v4l2_enuminput(m_cam_fd, getCameraId());
+}
+
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+int SecCamera::getCameraSensorESDStatus(void)
+{
+ LOGV("%s", __func__);
+
+ // 0 : normal operation, 1 : abnormal operation
+ int status = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_ESD_INT);
+
+ return status;
+}
+#endif // ENABLE_ESD_PREVIEW_CHECK
+
+// ======================================================================
+// Jpeg
+
+int SecCamera::setJpegThumbnailSize(int width, int height)
+{
+ LOGV("%s(width(%d), height(%d))", __func__, width, height);
+
+ m_jpeg_thumbnail_width = width;
+ m_jpeg_thumbnail_height = height;
+
+ return 0;
+}
+
+int SecCamera::getJpegThumbnailSize(int *width, int *height)
+{
+ if (width)
+ *width = m_jpeg_thumbnail_width;
+ if (height)
+ *height = m_jpeg_thumbnail_height;
+
+ return 0;
+}
+
+void SecCamera::setExifFixedAttribute()
+{
+ char property[PROPERTY_VALUE_MAX];
+
+ //2 0th IFD TIFF Tags
+ //3 Maker
+ property_get("ro.product.brand", property, EXIF_DEF_MAKER);
+ strncpy((char *)mExifInfo.maker, property,
+ sizeof(mExifInfo.maker) - 1);
+ mExifInfo.maker[sizeof(mExifInfo.maker) - 1] = '\0';
+ //3 Model
+ property_get("ro.product.model", property, EXIF_DEF_MODEL);
+ strncpy((char *)mExifInfo.model, property,
+ sizeof(mExifInfo.model) - 1);
+ mExifInfo.model[sizeof(mExifInfo.model) - 1] = '\0';
+ //3 Software
+ property_get("ro.build.id", property, EXIF_DEF_SOFTWARE);
+ strncpy((char *)mExifInfo.software, property,
+ sizeof(mExifInfo.software) - 1);
+ mExifInfo.software[sizeof(mExifInfo.software) - 1] = '\0';
+
+ //3 YCbCr Positioning
+ mExifInfo.ycbcr_positioning = EXIF_DEF_YCBCR_POSITIONING;
+
+ //2 0th IFD Exif Private Tags
+ //3 F Number
+ mExifInfo.fnumber.num = EXIF_DEF_FNUMBER_NUM;
+ mExifInfo.fnumber.den = EXIF_DEF_FNUMBER_DEN;
+ //3 Exposure Program
+ mExifInfo.exposure_program = EXIF_DEF_EXPOSURE_PROGRAM;
+ //3 Exif Version
+ memcpy(mExifInfo.exif_version, EXIF_DEF_EXIF_VERSION, sizeof(mExifInfo.exif_version));
+ //3 Aperture
+ uint32_t av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num/mExifInfo.fnumber.den);
+ mExifInfo.aperture.num = av*EXIF_DEF_APEX_DEN;
+ mExifInfo.aperture.den = EXIF_DEF_APEX_DEN;
+ //3 Maximum lens aperture
+ mExifInfo.max_aperture.num = mExifInfo.aperture.num;
+ mExifInfo.max_aperture.den = mExifInfo.aperture.den;
+ //3 Lens Focal Length
+ if (m_camera_id == CAMERA_ID_BACK)
+ mExifInfo.focal_length.num = BACK_CAMERA_FOCAL_LENGTH;
+ else
+ mExifInfo.focal_length.num = FRONT_CAMERA_FOCAL_LENGTH;
+
+ mExifInfo.focal_length.den = EXIF_DEF_FOCAL_LEN_DEN;
+ //3 User Comments
+ strcpy((char *)mExifInfo.user_comment, EXIF_DEF_USERCOMMENTS);
+ //3 Color Space information
+ mExifInfo.color_space = EXIF_DEF_COLOR_SPACE;
+ //3 Exposure Mode
+ mExifInfo.exposure_mode = EXIF_DEF_EXPOSURE_MODE;
+
+ //2 1th IFD TIFF Tags
+ mExifInfo.compression_scheme = EXIF_DEF_COMPRESSION;
+ mExifInfo.x_resolution.num = EXIF_DEF_RESOLUTION_NUM;
+ mExifInfo.x_resolution.den = EXIF_DEF_RESOLUTION_DEN;
+ mExifInfo.y_resolution.num = EXIF_DEF_RESOLUTION_NUM;
+ mExifInfo.y_resolution.den = EXIF_DEF_RESOLUTION_DEN;
+ mExifInfo.resolution_unit = EXIF_DEF_RESOLUTION_UNIT;
+}
+
+void SecCamera::setExifChangedAttribute()
+{
+ //2 0th IFD TIFF Tags
+ //3 Width
+ mExifInfo.width = m_snapshot_width;
+ //3 Height
+ mExifInfo.height = m_snapshot_height;
+ //3 Orientation
+ switch (m_exif_orientation) {
+ case 0:
+ mExifInfo.orientation = EXIF_ORIENTATION_UP;
+ break;
+ case 90:
+ mExifInfo.orientation = EXIF_ORIENTATION_90;
+ break;
+ case 180:
+ mExifInfo.orientation = EXIF_ORIENTATION_180;
+ break;
+ case 270:
+ mExifInfo.orientation = EXIF_ORIENTATION_270;
+ break;
+ default:
+ mExifInfo.orientation = EXIF_ORIENTATION_UP;
+ break;
+ }
+ //3 Date time
+ time_t rawtime;
+ struct tm *timeinfo;
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+ strftime((char *)mExifInfo.date_time, 20, "%Y:%m:%d %H:%M:%S", timeinfo);
+
+ //2 0th IFD Exif Private Tags
+ //3 Exposure Time
+ int shutterSpeed = fimc_v4l2_g_ctrl(m_cam_fd,
+ V4L2_CID_CAMERA_GET_SHT_TIME);
+ /* TBD - front camera needs to be fixed to support this g_ctrl,
+ it current returns a negative err value, so avoid putting
+ odd value into exif for now */
+ if (shutterSpeed < 0) {
+ LOGE("%s: error %d getting shutterSpeed, camera_id = %d, using 100",
+ __func__, shutterSpeed, m_camera_id);
+ shutterSpeed = 100;
+ }
+ mExifInfo.exposure_time.num = 1;
+ // x us -> 1/x s */
+ mExifInfo.exposure_time.den = (uint32_t)(1000000 / shutterSpeed);
+
+ //3 ISO Speed Rating
+ int iso = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_GET_ISO);
+ /* TBD - front camera needs to be fixed to support this g_ctrl,
+ it current returns a negative err value, so avoid putting
+ odd value into exif for now */
+ if (iso < 0) {
+ LOGE("%s: error %d getting iso, camera_id = %d, using 100",
+ __func__, iso, m_camera_id);
+ iso = ISO_100;
+ }
+ switch(iso) {
+ case ISO_50:
+ mExifInfo.iso_speed_rating = 50;
+ break;
+ case ISO_100:
+ mExifInfo.iso_speed_rating = 100;
+ break;
+ case ISO_200:
+ mExifInfo.iso_speed_rating = 200;
+ break;
+ case ISO_400:
+ mExifInfo.iso_speed_rating = 400;
+ break;
+ case ISO_800:
+ mExifInfo.iso_speed_rating = 800;
+ break;
+ case ISO_1600:
+ mExifInfo.iso_speed_rating = 1600;
+ break;
+ default:
+ mExifInfo.iso_speed_rating = 100;
+ break;
+ }
+
+ uint32_t av, tv, bv, sv, ev;
+ av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num / mExifInfo.fnumber.den);
+ tv = APEX_EXPOSURE_TO_SHUTTER((double)mExifInfo.exposure_time.num / mExifInfo.exposure_time.den);
+ sv = APEX_ISO_TO_FILMSENSITIVITY(mExifInfo.iso_speed_rating);
+ bv = av + tv - sv;
+ ev = av + tv;
+ LOGD("Shutter speed=%d us, iso=%d\n", shutterSpeed, mExifInfo.iso_speed_rating);
+ LOGD("AV=%d, TV=%d, SV=%d\n", av, tv, sv);
+
+ //3 Shutter Speed
+ mExifInfo.shutter_speed.num = tv*EXIF_DEF_APEX_DEN;
+ mExifInfo.shutter_speed.den = EXIF_DEF_APEX_DEN;
+ //3 Brightness
+ mExifInfo.brightness.num = bv*EXIF_DEF_APEX_DEN;
+ mExifInfo.brightness.den = EXIF_DEF_APEX_DEN;
+ //3 Exposure Bias
+ if (m_params->scene_mode == SCENE_MODE_BEACH_SNOW) {
+ mExifInfo.exposure_bias.num = EXIF_DEF_APEX_DEN;
+ mExifInfo.exposure_bias.den = EXIF_DEF_APEX_DEN;
+ } else {
+ mExifInfo.exposure_bias.num = 0;
+ mExifInfo.exposure_bias.den = 0;
+ }
+ //3 Metering Mode
+ switch (m_params->metering) {
+ case METERING_SPOT:
+ mExifInfo.metering_mode = EXIF_METERING_SPOT;
+ break;
+ case METERING_MATRIX:
+ mExifInfo.metering_mode = EXIF_METERING_AVERAGE;
+ break;
+ case METERING_CENTER:
+ mExifInfo.metering_mode = EXIF_METERING_CENTER;
+ break;
+ default :
+ mExifInfo.metering_mode = EXIF_METERING_AVERAGE;
+ break;
+ }
+
+ //3 Flash
+ int flash = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_GET_FLASH_ONOFF);
+ if (flash < 0)
+ mExifInfo.flash = EXIF_DEF_FLASH;
+ else
+ mExifInfo.flash = flash;
+
+ //3 White Balance
+ if (m_params->white_balance == WHITE_BALANCE_AUTO)
+ mExifInfo.white_balance = EXIF_WB_AUTO;
+ else
+ mExifInfo.white_balance = EXIF_WB_MANUAL;
+ //3 Scene Capture Type
+ switch (m_params->scene_mode) {
+ case SCENE_MODE_PORTRAIT:
+ mExifInfo.scene_capture_type = EXIF_SCENE_PORTRAIT;
+ break;
+ case SCENE_MODE_LANDSCAPE:
+ mExifInfo.scene_capture_type = EXIF_SCENE_LANDSCAPE;
+ break;
+ case SCENE_MODE_NIGHTSHOT:
+ mExifInfo.scene_capture_type = EXIF_SCENE_NIGHT;
+ break;
+ default:
+ mExifInfo.scene_capture_type = EXIF_SCENE_STANDARD;
+ break;
+ }
+
+ //2 1th IFD TIFF Tags
+ mExifInfo.widthThumb = m_jpeg_thumbnail_width;
+ mExifInfo.heightThumb = m_jpeg_thumbnail_height;
+}
+
+// ======================================================================
+// Conversions
+
+inline int SecCamera::m_frameSize(int format, int width, int height)
+{
+ int size = 0;
+
+ switch (format) {
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ size = (width * height * 3 / 2);
+ break;
+
+ case V4L2_PIX_FMT_NV12T:
+ size = ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height)) +
+ ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height / 2));
+ break;
+
+ case V4L2_PIX_FMT_YUV422P:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ size = (width * height * 2);
+ break;
+
+ default :
+ LOGE("ERR(%s):Invalid V4L2 pixel format(%d)\n", __func__, format);
+ case V4L2_PIX_FMT_RGB565:
+ size = (width * height * BPP);
+ break;
+ }
+
+ return size;
+}
+
+status_t SecCamera::dump(int fd)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, 255, "dump(%d)\n", fd);
+ result.append(buffer);
+ ::write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+double SecCamera::jpeg_ratio = 0.7;
+int SecCamera::interleaveDataSize = 4261248;
+int SecCamera::jpegLineLength = 636;
+
+}; // namespace android
diff --git a/libcamera/SecCamera.h b/libcamera/SecCamera.h
new file mode 100644
index 0000000..2f219e6
--- /dev/null
+++ b/libcamera/SecCamera.h
@@ -0,0 +1,503 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_HARDWARE_CAMERA_SEC_H
+#define ANDROID_HARDWARE_CAMERA_SEC_H
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include "JpegEncoder.h"
+
+namespace android {
+
+#define ENABLE_ESD_PREVIEW_CHECK
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+#define LOG_CAMERA LOGD
+#define LOG_CAMERA_PREVIEW LOGD
+
+#define LOG_TIME_DEFINE(n) \
+ struct timeval time_start_##n, time_stop_##n; unsigned long log_time_##n = 0;
+
+#define LOG_TIME_START(n) \
+ gettimeofday(&time_start_##n, NULL);
+
+#define LOG_TIME_END(n) \
+ gettimeofday(&time_stop_##n, NULL); log_time_##n = measure_time(&time_start_##n, &time_stop_##n);
+
+#define LOG_TIME(n) \
+ log_time_##n
+
+#else
+#define LOG_CAMERA(...)
+#define LOG_CAMERA_PREVIEW(...)
+#define LOG_TIME_DEFINE(n)
+#define LOG_TIME_START(n)
+#define LOG_TIME_END(n)
+#define LOG_TIME(n)
+#endif
+
+#define JOIN(x, y) JOIN_AGAIN(x, y)
+#define JOIN_AGAIN(x, y) x ## y
+
+#define FRONT_CAM VGA
+#define BACK_CAM S5K4ECGX
+
+#if !defined (FRONT_CAM) || !defined(BACK_CAM)
+#error "Please define the Camera module"
+#endif
+
+#define S5K4ECGX_PREVIEW_WIDTH 1024
+#define S5K4ECGX_PREVIEW_HEIGHT 600
+#define S5K4ECGX_SNAPSHOT_WIDTH 2048
+#define S5K4ECGX_SNAPSHOT_HEIGHT 1536
+
+#define S5K4ECGX_POSTVIEW_WIDTH 512
+#define S5K4ECGX_POSTVIEW_WIDE_WIDTH 640
+#define S5K4ECGX_POSTVIEW_HEIGHT 384
+#define S5K4ECGX_POSTVIEW_BPP 16
+
+#define S5K4ECGX_THUMBNAIL_WIDTH 320
+#define S5K4ECGX_THUMBNAIL_HEIGHT 240
+#define S5K4ECGX_THUMBNAIL_BPP 16
+
+/* focal length of 2.78mm */
+#define S5K4ECGX_FOCAL_LENGTH 278
+
+#define VGA_PREVIEW_WIDTH 640
+#define VGA_PREVIEW_HEIGHT 480
+#define VGA_SNAPSHOT_WIDTH 640
+#define VGA_SNAPSHOT_HEIGHT 480
+
+#define VGA_THUMBNAIL_WIDTH 160
+#define VGA_THUMBNAIL_HEIGHT 120
+#define VGA_THUMBNAIL_BPP 16
+
+/* focal length of 0.9mm */
+#define VGA_FOCAL_LENGTH 90
+
+#define MAX_BACK_CAMERA_PREVIEW_WIDTH JOIN(BACK_CAM,_PREVIEW_WIDTH)
+#define MAX_BACK_CAMERA_PREVIEW_HEIGHT JOIN(BACK_CAM,_PREVIEW_HEIGHT)
+#define MAX_BACK_CAMERA_SNAPSHOT_WIDTH JOIN(BACK_CAM,_SNAPSHOT_WIDTH)
+#define MAX_BACK_CAMERA_SNAPSHOT_HEIGHT JOIN(BACK_CAM,_SNAPSHOT_HEIGHT)
+#define BACK_CAMERA_POSTVIEW_WIDTH JOIN(BACK_CAM,_POSTVIEW_WIDTH)
+#define BACK_CAMERA_POSTVIEW_WIDE_WIDTH JOIN(BACK_CAM,_POSTVIEW_WIDE_WIDTH)
+#define BACK_CAMERA_POSTVIEW_HEIGHT JOIN(BACK_CAM,_POSTVIEW_HEIGHT)
+#define BACK_CAMERA_POSTVIEW_BPP JOIN(BACK_CAM,_POSTVIEW_BPP)
+#define BACK_CAMERA_THUMBNAIL_WIDTH JOIN(BACK_CAM,_THUMBNAIL_WIDTH)
+#define BACK_CAMERA_THUMBNAIL_HEIGHT JOIN(BACK_CAM,_THUMBNAIL_HEIGHT)
+#define BACK_CAMERA_THUMBNAIL_BPP JOIN(BACK_CAM,_THUMBNAIL_BPP)
+
+#define BACK_CAMERA_FOCAL_LENGTH JOIN(BACK_CAM,_FOCAL_LENGTH)
+
+#define MAX_FRONT_CAMERA_PREVIEW_WIDTH JOIN(FRONT_CAM,_PREVIEW_WIDTH)
+#define MAX_FRONT_CAMERA_PREVIEW_HEIGHT JOIN(FRONT_CAM,_PREVIEW_HEIGHT)
+#define MAX_FRONT_CAMERA_SNAPSHOT_WIDTH JOIN(FRONT_CAM,_SNAPSHOT_WIDTH)
+#define MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT JOIN(FRONT_CAM,_SNAPSHOT_HEIGHT)
+
+#define FRONT_CAMERA_THUMBNAIL_WIDTH JOIN(FRONT_CAM,_THUMBNAIL_WIDTH)
+#define FRONT_CAMERA_THUMBNAIL_HEIGHT JOIN(FRONT_CAM,_THUMBNAIL_HEIGHT)
+#define FRONT_CAMERA_THUMBNAIL_BPP JOIN(FRONT_CAM,_THUMBNAIL_BPP)
+#define FRONT_CAMERA_FOCAL_LENGTH JOIN(FRONT_CAM,_FOCAL_LENGTH)
+
+#define DEFAULT_JPEG_THUMBNAIL_WIDTH 256
+#define DEFAULT_JPEG_THUMBNAIL_HEIGHT 192
+
+#define CAMERA_DEV_NAME "/dev/video0"
+#define CAMERA_DEV_NAME2 "/dev/video2"
+
+#define CAMERA_DEV_NAME_TEMP "/data/videotmp_000"
+#define CAMERA_DEV_NAME2_TEMP "/data/videotemp_002"
+
+
+#define BPP 2
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#define MAX_BUFFERS 9 // 11
+/*
+ * V 4 L 2 F I M C E X T E N S I O N S
+ *
+ */
+#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_STREAM_PAUSE (V4L2_CID_PRIVATE_BASE + 53)
+
+#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 TPATTERN_COLORBAR 1
+#define TPATTERN_HORIZONTAL 2
+#define TPATTERN_VERTICAL 3
+
+#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U')
+
+/* FOURCC for FIMC specific */
+#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y')
+#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6')
+#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1')
+#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2')
+/*
+ * U S E R D E F I N E D T Y P E S
+ *
+ */
+
+struct fimc_buffer {
+ void *start;
+ size_t length;
+};
+
+struct yuv_fmt_list {
+ const char *name;
+ const char *desc;
+ unsigned int fmt;
+ int depth;
+ int planes;
+};
+
+//s1 [Apply factory standard]
+struct camsensor_date_info {
+ unsigned int year;
+ unsigned int month;
+ unsigned int date;
+};
+
+class SecCamera : public virtual RefBase {
+public:
+
+ enum CAMERA_ID {
+ CAMERA_ID_BACK = 0,
+ CAMERA_ID_FRONT = 1,
+ };
+
+ enum JPEG_QUALITY {
+ JPEG_QUALITY_ECONOMY = 0,
+ JPEG_QUALITY_NORMAL = 50,
+ JPEG_QUALITY_SUPERFINE = 100,
+ JPEG_QUALITY_MAX,
+ };
+
+ enum OBJECT_TRACKING {
+ OBJECT_TRACKING_OFF,
+ OBJECT_TRACKING_ON,
+ OBJECT_TRACKING_MAX,
+ };
+
+ /*VT call*/
+ enum VT_MODE {
+ VT_MODE_OFF,
+ VT_MODE_ON,
+ VT_MODE_MAX,
+ };
+
+ /*Camera sensor mode - Camcorder fix fps*/
+ enum SENSOR_MODE {
+ SENSOR_MODE_CAMERA,
+ SENSOR_MODE_MOVIE,
+ };
+
+ /*Camera Shot mode*/
+ enum SHOT_MODE {
+ SHOT_MODE_SINGLE = 0,
+ SHOT_MODE_CONTINUOUS = 1,
+ SHOT_MODE_PANORAMA = 2,
+ SHOT_MODE_SMILE = 3,
+ SHOT_MODE_SELF = 6,
+ };
+
+ enum CHK_DATALINE {
+ CHK_DATALINE_OFF,
+ CHK_DATALINE_ON,
+ CHK_DATALINE_MAX,
+ };
+
+ int m_touch_af_start_stop;
+
+ SecCamera();
+ virtual ~SecCamera();
+
+ static SecCamera* createInstance(void)
+ {
+ static SecCamera singleton;
+ return &singleton;
+ }
+ status_t dump(int fd);
+
+ int getCameraId(void);
+
+ int startPreview(void);
+ int stopPreview(void);
+
+ int startRecord(void);
+ int stopRecord(void);
+ int getRecordFrame(void);
+ int releaseRecordFrame(int index);
+ unsigned int getRecPhyAddrY(int);
+ unsigned int getRecPhyAddrC(int);
+
+ int getPreview(void);
+ int setPreviewSize(int width, int height, int pixel_format);
+ int getPreviewSize(int *width, int *height, int *frame_size);
+ int getPreviewMaxSize(int *width, int *height);
+ int getPreviewPixelFormat(void);
+ int setPreviewImage(int index, unsigned char *buffer, int size);
+
+ int setSnapshotSize(int width, int height);
+ int getSnapshotSize(int *width, int *height, int *frame_size);
+ int getSnapshotMaxSize(int *width, int *height);
+ int setSnapshotPixelFormat(int pixel_format);
+ int getSnapshotPixelFormat(void);
+
+ unsigned char* getJpeg(unsigned char *snapshot_data, int snapshot_size, int *size);
+ unsigned char* yuv2Jpeg(unsigned char *raw_data, int raw_size,
+ int *jpeg_size,
+ int width, int height, int pixel_format);
+
+ int setJpegThumbnailSize(int width, int height);
+ int getJpegThumbnailSize(int *width, int *height);
+
+ int setAutofocus(void);
+ int zoomIn(void);
+ int zoomOut(void);
+
+ int setVerticalMirror(void);
+ int setHorizontalMirror(void);
+
+ int setWhiteBalance(int white_balance);
+ int getWhiteBalance(void);
+
+ int setBrightness(int brightness);
+ int getBrightness(void);
+
+ int setImageEffect(int image_effect);
+ int getImageEffect(void);
+
+ int setSceneMode(int scene_mode);
+ int getSceneMode(void);
+
+ int setFlashMode(int flash_mode);
+ int getFlashMode(void);
+
+ int setMetering(int metering_value);
+ int getMetering(void);
+
+ int setISO(int iso_value);
+ int getISO(void);
+
+ int setContrast(int contrast_value);
+ int getContrast(void);
+
+ int setSaturation(int saturation_value);
+ int getSaturation(void);
+
+ int setSharpness(int sharpness_value);
+ int getSharpness(void);
+
+ int setJpegQuality(int jpeg_qality);
+ int getJpegQuality(void);
+
+ int setZoom(int zoom_level);
+ int getZoom(void);
+
+ int setObjectTracking(int object_tracking);
+ int getObjectTracking(void);
+ int getObjectTrackingStatus(void);
+
+ int getAutosceneStatus(void);
+
+ int setFocusMode(int focus_mode);
+ int getFocusMode(void);
+
+ int cancelAutofocus(void);
+ int setObjectPosition(int x, int y);
+ int setObjectTrackingStartStop(int start_stop);
+ int setTouchAFStartStop(int start_stop);
+ int getAutoFocusResult(void);
+ int getPostview(void);
+ int setRecordingSize(int width, int height);
+ int setExifOrientationInfo(int orientationInfo);
+ int setSnapshotCmd(void);
+ int endSnapshot(void);
+ int setCameraSensorReset(void);
+ int setSensorMode(int sensor_mode); /* Camcorder fix fps */
+ int setShotMode(int shot_mode); /* Shot mode */
+ /*VT call*/
+ int setVTmode(int vtmode);
+ int getVTmode(void);
+ int setBlur(int blur_level);
+ int getBlur(void);
+ int setDataLineCheck(int chk_dataline);
+ int getDataLineCheck(void);
+ int setDataLineCheckStop(void);
+ int setDefultIMEI(int imei);
+ int getDefultIMEI(void);
+ const __u8* getCameraSensorName(void);
+ int previewPoll(bool preview);
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ int getCameraSensorESDStatus(void);
+#endif // ENABLE_ESD_PREVIEW_CHECK
+
+ int setFrameRate(int frame_rate);
+ unsigned char* getJpeg(int*, unsigned int*);
+ int getSnapshotAndJpeg(unsigned char *yuv_buf, unsigned char *jpeg_buf,
+ unsigned int *output_size);
+ int getExif(unsigned char *pExifDst, unsigned char *pThumbSrc);
+
+ void getPostViewConfig(int*, int*, int*);
+ void getThumbnailConfig(int *width, int *height, int *size);
+
+ int getPostViewOffset(void);
+ int getCameraFd(void);
+ int getJpegFd(void);
+ void SetJpgAddr(unsigned char *addr);
+ unsigned int getPhyAddrY(int);
+ unsigned int getPhyAddrC(int);
+ void pausePreview();
+ int initCamera(int index);
+ void DeinitCamera();
+ static void setJpegRatio(double ratio)
+ {
+ if((ratio < 0) || (ratio > 1))
+ return;
+
+ jpeg_ratio = ratio;
+ }
+
+ static double getJpegRatio()
+ {
+ return jpeg_ratio;
+ }
+
+ static void setInterleaveDataSize(int x)
+ {
+ interleaveDataSize = x;
+ }
+
+ static int getInterleaveDataSize()
+ {
+ return interleaveDataSize;
+ }
+
+ static void setJpegLineLength(int x)
+ {
+ jpegLineLength = x;
+ }
+
+ static int getJpegLineLength()
+ {
+ return jpegLineLength;
+ }
+
+
+private:
+ v4l2_streamparm m_streamparm;
+ struct sec_cam_parm *m_params;
+ int m_flag_init;
+
+ int m_camera_id;
+
+ int m_cam_fd;
+
+ int m_cam_fd2;
+ struct pollfd m_events_c2;
+ int m_flag_record_start;
+
+ int m_preview_v4lformat;
+ int m_preview_width;
+ int m_preview_height;
+ int m_preview_max_width;
+ int m_preview_max_height;
+
+ int m_snapshot_v4lformat;
+ int m_snapshot_width;
+ int m_snapshot_height;
+ int m_snapshot_max_width;
+ int m_snapshot_max_height;
+
+ int m_angle;
+ int m_zoom_level;
+ int m_object_tracking;
+ int m_object_tracking_start_stop;
+ int m_recording_width;
+ int m_recording_height;
+ int m_vtmode;
+ int m_sensor_mode; /*Camcorder fix fps */
+ int m_shot_mode; /* Shot mode */
+ int m_exif_orientation;
+ int m_blur_level;
+ int m_chk_dataline;
+ int m_default_imei;
+ int m_camera_af_flag;
+
+ int m_flag_camera_start;
+
+ int m_jpeg_fd;
+ int m_jpeg_thumbnail_width;
+ int m_jpeg_thumbnail_height;
+ int m_jpeg_quality;
+
+ int m_postview_offset;
+
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ int m_esd_check_count;
+#endif // ENABLE_ESD_PREVIEW_CHECK
+
+ exif_attribute_t mExifInfo;
+
+ struct fimc_buffer m_capture_buf;
+ struct pollfd m_events_c;
+
+ inline int m_frameSize(int format, int width, int height);
+
+ void setExifChangedAttribute();
+ void setExifFixedAttribute();
+ void resetCamera();
+
+ static double jpeg_ratio;
+ static int interleaveDataSize;
+ static int jpegLineLength;
+};
+
+extern unsigned long measure_time(struct timeval *start, struct timeval *stop);
+
+}; // namespace android
+
+#endif // ANDROID_HARDWARE_CAMERA_SEC_H
diff --git a/libcamera/SecCameraHWInterface.cpp b/libcamera/SecCameraHWInterface.cpp
new file mode 100755
index 0000000..50da359
--- /dev/null
+++ b/libcamera/SecCameraHWInterface.cpp
@@ -0,0 +1,2383 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+** Copyright 2011, The CyanogenMod Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CameraHardwareSec"
+#include
+
+#include "SecCameraHWInterface.h"
+#include
+#include
+#include
+#include
+#include
+
+#define VIDEO_COMMENT_MARKER_H 0xFFBE
+#define VIDEO_COMMENT_MARKER_L 0xFFBF
+#define VIDEO_COMMENT_MARKER_LENGTH 4
+#define JPEG_EOI_MARKER 0xFFD9
+#define HIBYTE(x) (((x) >> 8) & 0xFF)
+#define LOBYTE(x) ((x) & 0xFF)
+
+#define BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR "0.10,1.20,Infinity"
+#define BACK_CAMERA_MACRO_FOCUS_DISTANCES_STR "0.10,0.20,Infinity"
+#define BACK_CAMERA_INFINITY_FOCUS_DISTANCES_STR "0.10,1.20,Infinity"
+#define FRONT_CAMERA_FOCUS_DISTANCES_STR "0.20,0.25,Infinity"
+
+// FIXME:
+// -- The actual preview color is set to YV12. The preview frames
+// returned via preview callback must be generated by color
+// conversion if the requested preview color format for the
+// preview frames is _not_ YV12. The reason that YV12 is used
+// for actual preview is because that is the only color format
+// supported by gralloc. Matching the preview cor format with
+// gralloc color format improves performance since no color
+// conversion is needed for preview.
+//
+// -- we only support two preview color formats that client
+// applications can set: NV21 and YUV420/YV12.
+
+namespace android {
+
+struct addrs {
+ uint32_t type; // make sure that this is 4 byte.
+ unsigned int addr_y;
+ unsigned int addr_cbcr;
+ unsigned int buf_index;
+ unsigned int reserved;
+};
+
+struct addrs_cap {
+ unsigned int addr_y;
+ unsigned int width;
+ unsigned int height;
+};
+
+static const int INITIAL_SKIP_FRAME = 3;
+static const int EFFECT_SKIP_FRAME = 1;
+
+gralloc_module_t const* CameraHardwareSec::mGrallocHal;
+
+CameraHardwareSec::CameraHardwareSec(int cameraId, camera_device_t *dev)
+ :
+ mCaptureInProgress(false),
+ mParameters(),
+ mCameraSensorName(NULL),
+ mSkipFrame(0),
+ mNotifyCb(0),
+ mDataCb(0),
+ mDataCbTimestamp(0),
+ mCallbackCookie(0),
+ mMsgEnabled(0),
+ mRecordRunning(false),
+ mPostViewWidth(0),
+ mPostViewHeight(0),
+ mPostViewSize(0),
+ mHalDevice(dev)
+{
+ LOGV("%s :", __func__);
+ int ret = 0;
+
+ mPreviewWindow = NULL;
+ mSecCamera = SecCamera::createInstance();
+
+ mRawHeap = NULL;
+ mPreviewHeap = NULL;
+ mRecordHeap = NULL;
+
+ if (!mGrallocHal) {
+ ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&mGrallocHal);
+ if (ret)
+ LOGE("ERR(%s):Fail on loading gralloc HAL", __func__);
+ }
+
+ ret = mSecCamera->initCamera(cameraId);
+ if (ret < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera init", __func__);
+ }
+
+ mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize);
+ LOGV("mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d",
+ mPostViewWidth,mPostViewHeight,mPostViewSize);
+
+ initDefaultParameters(cameraId);
+
+ mExitAutoFocusThread = false;
+ mExitPreviewThread = false;
+ /* whether the PreviewThread is active in preview or stopped. we
+ * create the thread but it is initially in stopped state.
+ */
+ mPreviewRunning = false;
+ mPreviewStartDeferred = false;
+ mPreviewThread = new PreviewThread(this);
+ mAutoFocusThread = new AutoFocusThread(this);
+ mPictureThread = new PictureThread(this);
+}
+
+int CameraHardwareSec::getCameraId() const
+{
+ return mSecCamera->getCameraId();
+}
+
+void CameraHardwareSec::initDefaultParameters(int cameraId)
+{
+ if (mSecCamera == NULL) {
+ LOGE("ERR(%s):mSecCamera object is NULL", __func__);
+ return;
+ }
+
+ CameraParameters p;
+ CameraParameters ip;
+
+ mCameraSensorName = mSecCamera->getCameraSensorName();
+ LOGV("CameraSensorName: %s", mCameraSensorName);
+
+ int preview_max_width = 0;
+ int preview_max_height = 0;
+ int snapshot_max_width = 0;
+ int snapshot_max_height = 0;
+
+ if (cameraId == SecCamera::CAMERA_ID_BACK) {
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ "1024x600,800x600,720x480,176x144");
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ "2048x1536,2048x1232,1600x1200,1600x960,1024x600,800x600");
+ } else {
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ "640x480,320x240,176x144");
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ "640x480");
+ }
+
+ p.getSupportedPreviewSizes(mSupportedPreviewSizes);
+
+ // If these fail, then we are using an invalid cameraId and we'll leave the
+ // sizes at zero to catch the error.
+ if (mSecCamera->getPreviewMaxSize(&preview_max_width,
+ &preview_max_height) < 0)
+ LOGE("getPreviewMaxSize fail (%d / %d) \n",
+ preview_max_width, preview_max_height);
+ if (mSecCamera->getSnapshotMaxSize(&snapshot_max_width,
+ &snapshot_max_height) < 0)
+ LOGE("getSnapshotMaxSize fail (%d / %d) \n",
+ snapshot_max_width, snapshot_max_height);
+ String8 previewColorString;
+ previewColorString = CameraParameters::PIXEL_FORMAT_YUV420SP;
+ previewColorString.append(",");
+ previewColorString.append(CameraParameters::PIXEL_FORMAT_YUV420P);
+ p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, previewColorString.string());
+ p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, CameraParameters::PIXEL_FORMAT_YUV420P);
+ p.setPreviewSize(preview_max_width, preview_max_height);
+
+ p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
+ p.setPictureSize(snapshot_max_width, snapshot_max_height);
+ p.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // maximum quality
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
+ CameraParameters::PIXEL_FORMAT_JPEG);
+
+ String8 parameterString;
+
+ if (cameraId == SecCamera::CAMERA_ID_BACK) {
+ parameterString = CameraParameters::FOCUS_MODE_AUTO;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FOCUS_MODE_INFINITY);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FOCUS_MODE_MACRO);
+ p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
+ parameterString.string());
+ p.set(CameraParameters::KEY_FOCUS_MODE,
+ CameraParameters::FOCUS_MODE_AUTO);
+ p.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR);
+ p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
+ "320x240,0x0");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "320");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "240");
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, "30");
+ p.setPreviewFrameRate(30);
+ } else {
+ parameterString = CameraParameters::FOCUS_MODE_FIXED;
+ p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
+ parameterString.string());
+ p.set(CameraParameters::KEY_FOCUS_MODE,
+ CameraParameters::FOCUS_MODE_FIXED);
+ p.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ FRONT_CAMERA_FOCUS_DISTANCES_STR);
+ p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
+ "160x120,0x0");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "160");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "120");
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, "15");
+ p.setPreviewFrameRate(15);
+ }
+
+ parameterString = CameraParameters::EFFECT_NONE;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::EFFECT_MONO);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::EFFECT_NEGATIVE);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::EFFECT_SEPIA);
+ p.set(CameraParameters::KEY_SUPPORTED_EFFECTS, parameterString.string());
+
+ if (cameraId == SecCamera::CAMERA_ID_BACK) {
+ parameterString = CameraParameters::FLASH_MODE_ON;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FLASH_MODE_OFF);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FLASH_MODE_AUTO);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FLASH_MODE_TORCH);
+ p.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
+ parameterString.string());
+ p.set(CameraParameters::KEY_FLASH_MODE,
+ CameraParameters::FLASH_MODE_OFF);
+
+ parameterString = CameraParameters::SCENE_MODE_AUTO;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_PORTRAIT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_LANDSCAPE);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_NIGHT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_BEACH);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_SNOW);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_SUNSET);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_FIREWORKS);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_SPORTS);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_PARTY);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_CANDLELIGHT);
+ //p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES,
+ // parameterString.string());
+ p.set(CameraParameters::KEY_SCENE_MODE,
+ CameraParameters::SCENE_MODE_AUTO);
+
+ /* we have two ranges, 4-30fps for night mode and
+ * 15-30fps for all others
+ */
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(15000,30000)");
+ p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "15000,30000");
+
+ p.set(CameraParameters::KEY_FOCAL_LENGTH, "2.78");
+ } else {
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(7500,30000)");
+ p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "7500,30000");
+
+ p.set(CameraParameters::KEY_FOCAL_LENGTH, "0.9");
+ }
+
+ parameterString = CameraParameters::WHITE_BALANCE_AUTO;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_INCANDESCENT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_FLUORESCENT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_DAYLIGHT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT);
+ p.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
+ parameterString.string());
+
+ ip.set("sharpness-min", 0);
+ ip.set("sharpness-max", 4);
+ ip.set("saturation-min", 0);
+ ip.set("saturation-max", 4);
+ ip.set("contrast-min", 0);
+ ip.set("contrast-max", 4);
+
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "100");
+
+ p.set(CameraParameters::KEY_ROTATION, 0);
+ p.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_AUTO);
+
+ p.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_NONE);
+
+ ip.set("sharpness", SHARPNESS_DEFAULT);
+ ip.set("contrast", CONTRAST_DEFAULT);
+ ip.set("saturation", SATURATION_DEFAULT);
+ ip.set("iso", "auto");
+ ip.set("metering", "center");
+
+ ip.set("chk_dataline", 0);
+ if (cameraId == SecCamera::CAMERA_ID_FRONT) {
+ ip.set("vtmode", 0);
+ ip.set("blur", 0);
+ }
+
+ p.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "51.2");
+ p.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "39.4");
+
+ p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, "0");
+ p.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "4");
+ p.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-4");
+ p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "0.5");
+
+ mParameters = p;
+ mInternalParameters = ip;
+
+ /* make sure mSecCamera has all the settings we do. applications
+ * aren't required to call setParameters themselves (only if they
+ * want to change something.
+ */
+ setParameters(p);
+ mSecCamera->setISO(ISO_AUTO);
+ mSecCamera->setMetering(METERING_CENTER);
+ mSecCamera->setContrast(CONTRAST_DEFAULT);
+ mSecCamera->setSharpness(SHARPNESS_DEFAULT);
+ mSecCamera->setSaturation(SATURATION_DEFAULT);
+ if (cameraId == SecCamera::CAMERA_ID_BACK)
+ mSecCamera->setFrameRate(30);
+ else
+ mSecCamera->setFrameRate(15);
+}
+
+CameraHardwareSec::~CameraHardwareSec()
+{
+ LOGV("%s", __func__);
+ mSecCamera->DeinitCamera();
+}
+
+status_t CameraHardwareSec::setPreviewWindow(preview_stream_ops *w)
+{
+ int min_bufs;
+
+ mPreviewWindow = w;
+ LOGV("%s: mPreviewWindow %p", __func__, mPreviewWindow);
+
+ if (!w) {
+ LOGE("preview window is NULL!");
+ return OK;
+ }
+
+ mPreviewLock.lock();
+
+ if (mPreviewRunning && !mPreviewStartDeferred) {
+ LOGI("stop preview (window change)");
+ stopPreviewInternal();
+ }
+
+ if (w->get_min_undequeued_buffer_count(w, &min_bufs)) {
+ LOGE("%s: could not retrieve min undequeued buffer count", __func__);
+ return INVALID_OPERATION;
+ }
+
+ if (min_bufs >= kBufferCount) {
+ LOGE("%s: min undequeued buffer count %d is too high (expecting at most %d)", __func__,
+ min_bufs, kBufferCount - 1);
+ }
+
+ LOGV("%s: setting buffer count to %d", __func__, kBufferCount);
+ if (w->set_buffer_count(w, kBufferCount)) {
+ LOGE("%s: could not set buffer count", __func__);
+ return INVALID_OPERATION;
+ }
+
+ int preview_width;
+ int preview_height;
+ mParameters.getPreviewSize(&preview_width, &preview_height);
+ int hal_pixel_format = HAL_PIXEL_FORMAT_YV12;
+
+ const char *str_preview_format = mParameters.getPreviewFormat();
+ LOGV("%s: preview format %s", __func__, str_preview_format);
+
+ if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN)) {
+ LOGE("%s: could not set usage on gralloc buffer", __func__);
+ return INVALID_OPERATION;
+ }
+
+ if (w->set_buffers_geometry(w,
+ preview_width, preview_height,
+ hal_pixel_format)) {
+ LOGE("%s: could not set buffers geometry to %s",
+ __func__, str_preview_format);
+ return INVALID_OPERATION;
+ }
+
+ if (mPreviewRunning && mPreviewStartDeferred) {
+ LOGV("start/resume preview");
+ status_t ret = startPreviewInternal();
+ if (ret == OK) {
+ mPreviewStartDeferred = false;
+ mPreviewCondition.signal();
+ }
+ }
+ mPreviewLock.unlock();
+
+ return OK;
+}
+
+void CameraHardwareSec::setCallbacks(camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user)
+{
+ mNotifyCb = notify_cb;
+ mDataCb = data_cb;
+ mDataCbTimestamp = data_cb_timestamp;
+ mGetMemoryCb = get_memory;
+ mCallbackCookie = user;
+}
+
+void CameraHardwareSec::enableMsgType(int32_t msgType)
+{
+ LOGV("%s : msgType = 0x%x, mMsgEnabled before = 0x%x",
+ __func__, msgType, mMsgEnabled);
+ mMsgEnabled |= msgType;
+
+ LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled);
+}
+
+void CameraHardwareSec::disableMsgType(int32_t msgType)
+{
+ LOGV("%s : msgType = 0x%x, mMsgEnabled before = 0x%x",
+ __func__, msgType, mMsgEnabled);
+ mMsgEnabled &= ~msgType;
+ LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled);
+}
+
+bool CameraHardwareSec::msgTypeEnabled(int32_t msgType)
+{
+ return (mMsgEnabled & msgType);
+}
+
+// ---------------------------------------------------------------------------
+void CameraHardwareSec::setSkipFrame(int frame)
+{
+ Mutex::Autolock lock(mSkipFrameLock);
+ if (frame < mSkipFrame)
+ return;
+
+ mSkipFrame = frame;
+}
+
+int CameraHardwareSec::previewThreadWrapper()
+{
+ LOGI("%s: starting", __func__);
+ while (1) {
+ mPreviewLock.lock();
+ while (!mPreviewRunning) {
+ LOGI("%s: calling mSecCamera->stopPreview() and waiting", __func__);
+ mSecCamera->stopPreview();
+ /* signal that we're stopping */
+ mPreviewStoppedCondition.signal();
+ mPreviewCondition.wait(mPreviewLock);
+ LOGI("%s: return from wait", __func__);
+ }
+ mPreviewLock.unlock();
+
+ if (mExitPreviewThread) {
+ LOGI("%s: exiting", __func__);
+ mSecCamera->stopPreview();
+ return 0;
+ }
+ previewThread();
+ }
+}
+
+int CameraHardwareSec::previewThread()
+{
+ int index;
+ nsecs_t timestamp;
+ unsigned int phyYAddr;
+ unsigned int phyCAddr;
+ struct addrs *addrs;
+
+ index = mSecCamera->getPreview();
+ if (index < 0) {
+ LOGE("ERR(%s):Fail on SecCamera->getPreview()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+// LOGV("%s: index %d", __func__, index);
+
+ mSkipFrameLock.lock();
+ if (mSkipFrame > 0) {
+ mSkipFrame--;
+ mSkipFrameLock.unlock();
+ LOGV("%s: index %d skipping frame", __func__, index);
+ return NO_ERROR;
+ }
+ mSkipFrameLock.unlock();
+
+ timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ phyYAddr = mSecCamera->getPhyAddrY(index);
+ phyCAddr = mSecCamera->getPhyAddrC(index);
+
+ if (phyYAddr == 0xffffffff || phyCAddr == 0xffffffff) {
+ LOGE("ERR(%s):Fail on SecCamera getPhyAddr Y addr = %0x C addr = %0x",
+ __func__, phyYAddr, phyCAddr);
+ return UNKNOWN_ERROR;
+ }
+
+ int width, height, frame_size, offset;
+
+ mSecCamera->getPreviewSize(&width, &height, &frame_size);
+
+ offset = frame_size * index;
+
+ if (mPreviewWindow && mGrallocHal) {
+ buffer_handle_t *buf_handle;
+ int stride;
+ if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &buf_handle, &stride)) {
+ LOGE("Could not dequeue gralloc buffer!\n");
+ goto callbacks;
+ }
+
+ void *vaddr;
+ if (!mGrallocHal->lock(mGrallocHal,
+ *buf_handle,
+ GRALLOC_USAGE_SW_WRITE_OFTEN,
+ 0, 0, width, height, &vaddr)) {
+ char *frame = ((char *)mPreviewHeap->data) + offset;
+
+ // the code below assumes YUV, not RGB
+ {
+ int h;
+ char *src = frame;
+ char *ptr = (char *)vaddr;
+
+ // Copy the Y plane, while observing the stride
+ for (h = 0; h < height; h++) {
+ memcpy(ptr, src, width);
+ ptr += stride;
+ src += width;
+ }
+
+ {
+ // U
+ char *v = ptr;
+ ptr += stride * height / 4;
+ for (h = 0; h < height / 2; h++) {
+ memcpy(ptr, src, width / 2);
+ ptr += stride / 2;
+ src += width / 2;
+ }
+ // V
+ ptr = v;
+ for (h = 0; h < height / 2; h++) {
+ memcpy(ptr, src, width / 2);
+ ptr += stride / 2;
+ src += width / 2;
+ }
+ }
+ }
+
+ mGrallocHal->unlock(mGrallocHal, *buf_handle);
+ }
+ else
+ LOGE("%s: could not obtain gralloc buffer", __func__);
+
+ if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, buf_handle)) {
+ LOGE("Could not enqueue gralloc buffer!\n");
+ goto callbacks;
+ }
+ }
+
+callbacks:
+ // Notify the client of a new frame.
+ if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {
+ const char * preview_format = mParameters.getPreviewFormat();
+ if (!strcmp(preview_format, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
+ // Color conversion from YUV420 to NV21
+ char *vu = ((char *)mPreviewHeap->data) + offset + width * height;
+ const int uv_size = (width * height) >> 1;
+ char saved_uv[uv_size];
+ memcpy(saved_uv, vu, uv_size);
+ char *u = saved_uv;
+ char *v = u + (uv_size >> 1);
+
+ int h = 0;
+ while (h < width * height / 4) {
+ *vu++ = *v++;
+ *vu++ = *u++;
+ ++h;
+ }
+ }
+ mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap, index, NULL, mCallbackCookie);
+ }
+
+ Mutex::Autolock lock(mRecordLock);
+ if (mRecordRunning == true) {
+ index = mSecCamera->getRecordFrame();
+ if (index < 0) {
+ LOGE("ERR(%s):Fail on SecCamera->getRecord()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ phyYAddr = mSecCamera->getRecPhyAddrY(index);
+ phyCAddr = mSecCamera->getRecPhyAddrC(index);
+
+ if (phyYAddr == 0xffffffff || phyCAddr == 0xffffffff) {
+ LOGE("ERR(%s):Fail on SecCamera getRectPhyAddr Y addr = %0x C addr = %0x", __func__,
+ phyYAddr, phyCAddr);
+ return UNKNOWN_ERROR;
+ }
+
+ addrs = (struct addrs *)mRecordHeap->data;
+
+ addrs[index].type = kMetadataBufferTypeCameraSource;
+ addrs[index].addr_y = phyYAddr;
+ addrs[index].addr_cbcr = phyCAddr;
+ addrs[index].buf_index = index;
+
+ // Notify the client of a new frame.
+ if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
+ mDataCbTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME,
+ mRecordHeap, index, mCallbackCookie);
+ } else {
+ mSecCamera->releaseRecordFrame(index);
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::startPreview()
+{
+ int ret = 0; //s1 [Apply factory standard]
+
+ LOGV("%s :", __func__);
+
+ if (waitCaptureCompletion() != NO_ERROR) {
+ return TIMED_OUT;
+ }
+
+ mPreviewLock.lock();
+ if (mPreviewRunning) {
+ // already running
+ LOGE("%s : preview thread already running", __func__);
+ mPreviewLock.unlock();
+ return INVALID_OPERATION;
+ }
+
+ mPreviewRunning = true;
+ mPreviewStartDeferred = false;
+
+ if (!mPreviewWindow) {
+ LOGI("%s : deferring", __func__);
+ mPreviewStartDeferred = true;
+ mPreviewLock.unlock();
+ return NO_ERROR;
+ }
+
+ ret = startPreviewInternal();
+ if (ret == OK)
+ mPreviewCondition.signal();
+
+ mPreviewLock.unlock();
+ return ret;
+}
+
+status_t CameraHardwareSec::startPreviewInternal()
+{
+ LOGV("%s", __func__);
+
+ int ret = mSecCamera->startPreview();
+ LOGV("%s : mSecCamera->startPreview() returned %d", __func__, ret);
+
+ if (ret < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->startPreview()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ setSkipFrame(INITIAL_SKIP_FRAME);
+
+ int width, height, frame_size;
+
+ mSecCamera->getPreviewSize(&width, &height, &frame_size);
+
+ LOGD("mPreviewHeap(fd(%d), size(%d), width(%d), height(%d))",
+ mSecCamera->getCameraFd(), frame_size, width, height);
+ if (mPreviewHeap) {
+ mPreviewHeap->release(mPreviewHeap);
+ mPreviewHeap = 0;
+ }
+
+ mPreviewHeap = mGetMemoryCb((int)mSecCamera->getCameraFd(),
+ frame_size,
+ kBufferCount,
+ 0); // no cookie
+
+ mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize);
+ LOGV("CameraHardwareSec: mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d",
+ mPostViewWidth,mPostViewHeight,mPostViewSize);
+
+ return NO_ERROR;
+}
+
+void CameraHardwareSec::stopPreviewInternal()
+{
+ LOGV("%s :", __func__);
+
+ /* request that the preview thread stop. */
+ if (mPreviewRunning) {
+ mPreviewRunning = false;
+ if (!mPreviewStartDeferred) {
+ mPreviewCondition.signal();
+ /* wait until preview thread is stopped */
+ mPreviewStoppedCondition.wait(mPreviewLock);
+ }
+ else
+ LOGV("%s : preview running but deferred, doing nothing", __func__);
+ } else
+ LOGI("%s : preview not running, doing nothing", __func__);
+}
+
+void CameraHardwareSec::stopPreview()
+{
+ LOGV("%s :", __func__);
+
+ /* request that the preview thread stop. */
+ mPreviewLock.lock();
+ stopPreviewInternal();
+ mPreviewLock.unlock();
+}
+
+bool CameraHardwareSec::previewEnabled()
+{
+ Mutex::Autolock lock(mPreviewLock);
+ LOGV("%s : %d", __func__, mPreviewRunning);
+ return mPreviewRunning;
+}
+
+// ---------------------------------------------------------------------------
+
+status_t CameraHardwareSec::startRecording()
+{
+ LOGV("%s :", __func__);
+
+ Mutex::Autolock lock(mRecordLock);
+
+ if (mRecordHeap) {
+ mRecordHeap->release(mRecordHeap);
+ mRecordHeap = 0;
+ }
+ mRecordHeap = mGetMemoryCb(-1, sizeof(struct addrs), kBufferCount, NULL);
+ if (!mRecordHeap) {
+ LOGE("ERR(%s): Record heap creation fail", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ if (mRecordRunning == false) {
+ if (mSecCamera->startRecord() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->startRecord()", __func__);
+ return UNKNOWN_ERROR;
+ }
+ mRecordRunning = true;
+ }
+ return NO_ERROR;
+}
+
+void CameraHardwareSec::stopRecording()
+{
+ LOGV("%s :", __func__);
+
+ Mutex::Autolock lock(mRecordLock);
+
+ if (mRecordRunning == true) {
+ if (mSecCamera->stopRecord() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->stopRecord()", __func__);
+ return;
+ }
+ mRecordRunning = false;
+ }
+}
+
+bool CameraHardwareSec::recordingEnabled()
+{
+ LOGV("%s :", __func__);
+
+ return mRecordRunning;
+}
+
+void CameraHardwareSec::releaseRecordingFrame(const void *opaque)
+{
+ struct addrs *addrs = (struct addrs *)opaque;
+ mSecCamera->releaseRecordFrame(addrs->buf_index);
+}
+
+// ---------------------------------------------------------------------------
+
+int CameraHardwareSec::autoFocusThread()
+{
+ int count =0;
+ int af_status =0 ;
+
+ LOGV("%s : starting", __func__);
+
+ /* block until we're told to start. we don't want to use
+ * a restartable thread and requestExitAndWait() in cancelAutoFocus()
+ * because it would cause deadlock between our callbacks and the
+ * caller of cancelAutoFocus() which both want to grab the same lock
+ * in CameraServices layer.
+ */
+ mFocusLock.lock();
+ /* check early exit request */
+ if (mExitAutoFocusThread) {
+ mFocusLock.unlock();
+ LOGV("%s : exiting on request0", __func__);
+ return NO_ERROR;
+ }
+ mFocusCondition.wait(mFocusLock);
+ /* check early exit request */
+ if (mExitAutoFocusThread) {
+ mFocusLock.unlock();
+ LOGV("%s : exiting on request1", __func__);
+ return NO_ERROR;
+ }
+ mFocusLock.unlock();
+
+ LOGV("%s : calling setAutoFocus", __func__);
+ if (mSecCamera->setAutofocus() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setAutofocus()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ af_status = mSecCamera->getAutoFocusResult();
+
+ if (af_status == 0x01) {
+ LOGV("%s : AF Success!!", __func__);
+ if (mMsgEnabled & CAMERA_MSG_FOCUS)
+ mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+ } else if (af_status == 0x02) {
+ LOGV("%s : AF Cancelled !!", __func__);
+ if (mMsgEnabled & CAMERA_MSG_FOCUS) {
+ /* CAMERA_MSG_FOCUS only takes a bool. true for
+ * finished and false for failure. cancel is still
+ * considered a true result.
+ */
+ mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+ }
+ } else {
+ LOGV("%s : AF Fail !!", __func__);
+ LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled);
+ if (mMsgEnabled & CAMERA_MSG_FOCUS)
+ mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie);
+ }
+
+ LOGV("%s : exiting with no error", __func__);
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::autoFocus()
+{
+ LOGV("%s :", __func__);
+ /* signal autoFocusThread to run once */
+ mFocusCondition.signal();
+ return NO_ERROR;
+}
+
+/* 2009.10.14 by icarus for added interface */
+status_t CameraHardwareSec::cancelAutoFocus()
+{
+ LOGV("%s :", __func__);
+
+ // cancelAutoFocus should be allowed after preview is started. But if
+ // the preview is deferred, cancelAutoFocus will fail. Ignore it if that is
+ // the case.
+ if (mPreviewRunning && mPreviewStartDeferred) return NO_ERROR;
+
+ if (mSecCamera->cancelAutofocus() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->cancelAutofocus()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ return NO_ERROR;
+}
+
+int CameraHardwareSec::save_jpeg( unsigned char *real_jpeg, int jpeg_size)
+{
+ FILE *yuv_fp = NULL;
+ char filename[100], *buffer = NULL;
+
+ /* file create/open, note to "wb" */
+ yuv_fp = fopen("/data/camera_dump.jpeg", "wb");
+ if (yuv_fp == NULL) {
+ LOGE("Save jpeg file open error");
+ return -1;
+ }
+
+ LOGV("[BestIQ] real_jpeg size ========> %d\n", jpeg_size);
+ buffer = (char *) malloc(jpeg_size);
+ if (buffer == NULL) {
+ LOGE("Save YUV] buffer alloc failed");
+ if (yuv_fp)
+ fclose(yuv_fp);
+
+ return -1;
+ }
+
+ memcpy(buffer, real_jpeg, jpeg_size);
+
+ fflush(stdout);
+
+ fwrite(buffer, 1, jpeg_size, yuv_fp);
+
+ fflush(yuv_fp);
+
+ if (yuv_fp)
+ fclose(yuv_fp);
+ if (buffer)
+ free(buffer);
+
+ return 0;
+}
+
+void CameraHardwareSec::save_postview(const char *fname, uint8_t *buf, uint32_t size)
+{
+ int nw;
+ int cnt = 0;
+ uint32_t written = 0;
+
+ LOGD("opening file [%s]\n", fname);
+ int fd = open(fname, O_RDWR | O_CREAT);
+ if (fd < 0) {
+ LOGE("failed to create file [%s]: %s", fname, strerror(errno));
+ return;
+ }
+
+ LOGD("writing %d bytes to file [%s]\n", size, fname);
+ while (written < size) {
+ nw = ::write(fd, buf + written, size - written);
+ if (nw < 0) {
+ LOGE("failed to write to file %d [%s]: %s",written,fname, strerror(errno));
+ break;
+ }
+ written += nw;
+ cnt++;
+ }
+ LOGD("done writing %d bytes to file [%s] in %d passes\n",size, fname, cnt);
+ ::close(fd);
+}
+
+bool CameraHardwareSec::scaleDownYuv422(char *srcBuf, uint32_t srcWidth, uint32_t srcHeight,
+ char *dstBuf, uint32_t dstWidth, uint32_t dstHeight)
+{
+ int32_t step_x, step_y;
+ int32_t iXsrc, iXdst;
+ int32_t x, y, src_y_start_pos, dst_pos, src_pos;
+
+ if (dstWidth % 2 != 0 || dstHeight % 2 != 0){
+ LOGE("scale_down_yuv422: invalid width, height for scaling");
+ return false;
+ }
+
+ step_x = srcWidth / dstWidth;
+ step_y = srcHeight / dstHeight;
+
+ dst_pos = 0;
+ for (uint32_t y = 0; y < dstHeight; y++) {
+ src_y_start_pos = (y * step_y * (srcWidth * 2));
+
+ for (uint32_t x = 0; x < dstWidth; x += 2) {
+ src_pos = src_y_start_pos + (x * (step_x * 2));
+
+ dstBuf[dst_pos++] = srcBuf[src_pos ];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 1];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 2];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 3];
+ }
+ }
+
+ return true;
+}
+
+bool CameraHardwareSec::YUY2toNV21(void *srcBuf, void *dstBuf, uint32_t srcWidth, uint32_t srcHeight)
+{
+ int32_t x, y, src_y_start_pos, dst_cbcr_pos, dst_pos, src_pos;
+ unsigned char *srcBufPointer = (unsigned char *)srcBuf;
+ unsigned char *dstBufPointer = (unsigned char *)dstBuf;
+
+ dst_pos = 0;
+ dst_cbcr_pos = srcWidth*srcHeight;
+ for (uint32_t y = 0; y < srcHeight; y++) {
+ src_y_start_pos = (y * (srcWidth * 2));
+
+ for (uint32_t x = 0; x < (srcWidth * 2); x += 2) {
+ src_pos = src_y_start_pos + x;
+
+ dstBufPointer[dst_pos++] = srcBufPointer[src_pos];
+ }
+ }
+ for (uint32_t y = 0; y < srcHeight; y += 2) {
+ src_y_start_pos = (y * (srcWidth * 2));
+
+ for (uint32_t x = 0; x < (srcWidth * 2); x += 4) {
+ src_pos = src_y_start_pos + x;
+
+ dstBufPointer[dst_cbcr_pos++] = srcBufPointer[src_pos + 3];
+ dstBufPointer[dst_cbcr_pos++] = srcBufPointer[src_pos + 1];
+ }
+ }
+
+ return true;
+}
+
+int CameraHardwareSec::pictureThread()
+{
+ LOGV("%s :", __func__);
+
+ int jpeg_size = 0;
+ int ret = NO_ERROR;
+ unsigned char *jpeg_data = NULL;
+ int postview_offset = 0;
+ unsigned char *postview_data = NULL;
+
+ unsigned char *addr = NULL;
+ int mPostViewWidth, mPostViewHeight, mPostViewSize;
+ int mThumbWidth, mThumbHeight, mThumbSize;
+ int cap_width, cap_height, cap_frame_size;
+ int JpegImageSize, JpegExifSize;
+
+ unsigned int output_size = 0;
+
+ mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize);
+ mSecCamera->getThumbnailConfig(&mThumbWidth, &mThumbHeight, &mThumbSize);
+ int postviewHeapSize = mPostViewSize;
+ mSecCamera->getSnapshotSize(&cap_width, &cap_height, &cap_frame_size);
+ int mJpegHeapSize;
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK)
+ mJpegHeapSize = cap_frame_size * SecCamera::getJpegRatio();
+ else
+ mJpegHeapSize = cap_frame_size;
+
+ LOG_TIME_DEFINE(0)
+ LOG_TIME_START(0)
+// sp buffer = new MemoryBase(mRawHeap, 0, mPostViewSize + 8);
+
+ struct addrs_cap *addrs = (struct addrs_cap *)mRawHeap->data;
+
+ addrs[0].width = mPostViewWidth;
+ addrs[0].height = mPostViewHeight;
+ LOGV("[5B] mPostViewWidth = %d mPostViewHeight = %d\n",mPostViewWidth,mPostViewHeight);
+
+ camera_memory_t *JpegHeap = mGetMemoryCb(-1, mJpegHeapSize, 1, 0);
+ sp PostviewHeap = new MemoryHeapBase(mPostViewSize);
+ sp ThumbnailHeap = new MemoryHeapBase(mThumbSize);
+
+ LOG_TIME_DEFINE(1)
+ LOG_TIME_START(1)
+
+ int picture_size, picture_width, picture_height;
+ mSecCamera->getSnapshotSize(&picture_width, &picture_height, &picture_size);
+ int picture_format = mSecCamera->getSnapshotPixelFormat();
+
+ unsigned int phyAddr;
+
+ // Modified the shutter sound timing for Jpeg capture
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK)
+ mSecCamera->setSnapshotCmd();
+ if (mMsgEnabled & CAMERA_MSG_SHUTTER) {
+ mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
+ }
+
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK){
+ jpeg_data = mSecCamera->getJpeg(&jpeg_size, &phyAddr);
+ if (jpeg_data == NULL) {
+ LOGE("ERR(%s):Fail on SecCamera->getSnapshot()", __func__);
+ ret = UNKNOWN_ERROR;
+ goto out;
+ }
+ } else {
+ if (mSecCamera->getSnapshotAndJpeg((unsigned char*)PostviewHeap->base(),
+ (unsigned char*)JpegHeap->data, &output_size) < 0) {
+ ret = UNKNOWN_ERROR;
+ goto out;
+ }
+ LOGI("snapshotandjpeg done\n");
+ }
+
+ LOG_TIME_END(1)
+ LOG_CAMERA("getSnapshotAndJpeg interval: %lu us", LOG_TIME(1));
+
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK) {
+ // TODO: copy postview to PostviewHeap->base()
+ memcpy(JpegHeap->data, jpeg_data, jpeg_size);
+ JpegImageSize = jpeg_size;
+ } else {
+ JpegImageSize = static_cast(output_size);
+ }
+ scaleDownYuv422((char *)PostviewHeap->base(), mPostViewWidth, mPostViewHeight,
+ (char *)ThumbnailHeap->base(), mThumbWidth, mThumbHeight);
+
+ memcpy(mRawHeap->data, PostviewHeap->base(), postviewHeapSize);
+
+ if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
+ mDataCb(CAMERA_MSG_RAW_IMAGE, mRawHeap, 0, NULL, mCallbackCookie);
+ } else if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY) {
+ mNotifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCallbackCookie);
+ }
+
+ if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
+ camera_memory_t *ExifHeap =
+ mGetMemoryCb(-1, EXIF_FILE_SIZE + JPG_STREAM_BUF_SIZE, 1, 0);
+ JpegExifSize = mSecCamera->getExif((unsigned char *)ExifHeap->data,
+ (unsigned char *)ThumbnailHeap->base());
+
+ LOGV("JpegExifSize=%d", JpegExifSize);
+
+ if (JpegExifSize < 0) {
+ ret = UNKNOWN_ERROR;
+ ExifHeap->release(ExifHeap);
+ goto out;
+ }
+
+ camera_memory_t *mem = mGetMemoryCb(-1, JpegImageSize + JpegExifSize, 1, 0);
+ uint8_t *ptr = (uint8_t *) mem->data;
+ memcpy(ptr, JpegHeap->data, 2); ptr += 2;
+ memcpy(ptr, ExifHeap->data, JpegExifSize); ptr += JpegExifSize;
+ memcpy(ptr, (uint8_t *) JpegHeap->data + 2, JpegImageSize - 2);
+ mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, 0, NULL, mCallbackCookie);
+ mem->release(mem);
+ ExifHeap->release(ExifHeap);
+ }
+
+ LOG_TIME_END(0)
+ LOG_CAMERA("pictureThread interval: %lu us", LOG_TIME(0));
+
+ LOGV("%s : pictureThread end", __func__);
+
+out:
+ JpegHeap->release(JpegHeap);
+ mSecCamera->endSnapshot();
+ mCaptureLock.lock();
+ mCaptureInProgress = false;
+ mCaptureCondition.broadcast();
+ mCaptureLock.unlock();
+
+ return ret;
+}
+
+status_t CameraHardwareSec::waitCaptureCompletion() {
+ // 5 seconds timeout
+ nsecs_t endTime = 5000000000LL + systemTime(SYSTEM_TIME_MONOTONIC);
+ Mutex::Autolock lock(mCaptureLock);
+ while (mCaptureInProgress) {
+ nsecs_t remainingTime = endTime - systemTime(SYSTEM_TIME_MONOTONIC);
+ if (remainingTime <= 0) {
+ LOGE("Timed out waiting picture thread.");
+ return TIMED_OUT;
+ }
+ LOGD("Waiting for picture thread to complete.");
+ mCaptureCondition.waitRelative(mCaptureLock, remainingTime);
+ }
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::takePicture()
+{
+ LOGV("%s :", __func__);
+
+ stopPreview();
+
+ if (!mRawHeap) {
+ int rawHeapSize = mPostViewSize;
+ LOGV("mRawHeap : MemoryHeapBase(previewHeapSize(%d))", rawHeapSize);
+ mRawHeap = mGetMemoryCb(-1, rawHeapSize, 1, 0);
+ if (!mRawHeap) {
+ LOGE("ERR(%s): Raw heap creation fail", __func__);
+ }
+ }
+
+ if (waitCaptureCompletion() != NO_ERROR) {
+ return TIMED_OUT;
+ }
+
+ if (mPictureThread->run("CameraPictureThread", PRIORITY_DEFAULT) != NO_ERROR) {
+ LOGE("%s : couldn't run picture thread", __func__);
+ return INVALID_OPERATION;
+ }
+ mCaptureLock.lock();
+ mCaptureInProgress = true;
+ mCaptureLock.unlock();
+
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::cancelPicture()
+{
+ LOGV("%s", __func__);
+
+ if (mPictureThread.get()) {
+ LOGV("%s: waiting for picture thread to exit", __func__);
+ mPictureThread->requestExitAndWait();
+ LOGV("%s: picture thread has exited", __func__);
+ }
+
+ return NO_ERROR;
+}
+
+bool CameraHardwareSec::CheckVideoStartMarker(unsigned char *pBuf)
+{
+ if (!pBuf) {
+ LOGE("CheckVideoStartMarker() => pBuf is NULL\n");
+ return false;
+ }
+
+ if (HIBYTE(VIDEO_COMMENT_MARKER_H) == * pBuf && LOBYTE(VIDEO_COMMENT_MARKER_H) == *(pBuf + 1) &&
+ HIBYTE(VIDEO_COMMENT_MARKER_L) == *(pBuf + 2) && LOBYTE(VIDEO_COMMENT_MARKER_L) == *(pBuf + 3))
+ return true;
+
+ return false;
+}
+
+bool CameraHardwareSec::CheckEOIMarker(unsigned char *pBuf)
+{
+ if (!pBuf) {
+ LOGE("CheckEOIMarker() => pBuf is NULL\n");
+ return false;
+ }
+
+ // EOI marker [FF D9]
+ if (HIBYTE(JPEG_EOI_MARKER) == *pBuf && LOBYTE(JPEG_EOI_MARKER) == *(pBuf + 1))
+ return true;
+
+ return false;
+}
+
+bool CameraHardwareSec::FindEOIMarkerInJPEG(unsigned char *pBuf, int dwBufSize, int *pnJPEGsize)
+{
+ if (NULL == pBuf || 0 >= dwBufSize) {
+ LOGE("FindEOIMarkerInJPEG() => There is no contents.");
+ return false;
+ }
+
+ unsigned char *pBufEnd = pBuf + dwBufSize;
+
+ while (pBuf < pBufEnd) {
+ if (CheckEOIMarker(pBuf++))
+ return true;
+
+ (*pnJPEGsize)++;
+ }
+
+ return false;
+}
+
+status_t CameraHardwareSec::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ const Vector args;
+
+ if (mSecCamera != 0) {
+ mSecCamera->dump(fd);
+ mParameters.dump(fd, args);
+ mInternalParameters.dump(fd, args);
+ snprintf(buffer, 255, " preview running(%s)\n", mPreviewRunning?"true": "false");
+ result.append(buffer);
+ } else {
+ result.append("No camera client yet.\n");
+ }
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+bool CameraHardwareSec::isSupportedPreviewSize(const int width,
+ const int height) const
+{
+ unsigned int i;
+
+ for (i = 0; i < mSupportedPreviewSizes.size(); i++) {
+ if (mSupportedPreviewSizes[i].width == width &&
+ mSupportedPreviewSizes[i].height == height)
+ return true;
+ }
+
+ return false;
+}
+
+bool CameraHardwareSec::isSupportedParameter(const char * const parm,
+ const char * const supported_parm) const
+{
+ const char *pStart;
+ const char *pEnd;
+
+ if (!parm || !supported_parm)
+ return false;
+
+ pStart = supported_parm;
+
+ while (true) {
+ pEnd = strchr(pStart, ',');
+ if (!pEnd) {
+ if (!strcmp(parm, pStart))
+ return true;
+ else
+ return false;
+ }
+ if (!strncmp(parm, pStart, pEnd - pStart)) {
+ return true;
+ }
+ pStart = pEnd + 1;
+ }
+ /* NOTREACHED */
+}
+
+status_t CameraHardwareSec::setParameters(const CameraParameters& params)
+{
+ LOGV("%s :", __func__);
+
+ status_t ret = NO_ERROR;
+
+ /* if someone calls us while picture thread is running, it could screw
+ * up the sensor quite a bit so return error.
+ */
+ if (waitCaptureCompletion() != NO_ERROR) {
+ return TIMED_OUT;
+ }
+
+ // preview size
+ int new_preview_width = 0;
+ int new_preview_height = 0;
+ params.getPreviewSize(&new_preview_width, &new_preview_height);
+ const char *new_str_preview_format = params.getPreviewFormat();
+ LOGV("%s : new_preview_width x new_preview_height = %dx%d, format = %s",
+ __func__, new_preview_width, new_preview_height, new_str_preview_format);
+
+ if (strcmp(new_str_preview_format, CameraParameters::PIXEL_FORMAT_YUV420SP) &&
+ strcmp(new_str_preview_format, CameraParameters::PIXEL_FORMAT_YUV420P)) {
+ LOGE("Unsupported preview color format: %s", new_str_preview_format);
+ return BAD_VALUE;
+ }
+
+ if (0 < new_preview_width && 0 < new_preview_height &&
+ new_str_preview_format != NULL &&
+ isSupportedPreviewSize(new_preview_width, new_preview_height)) {
+ int new_preview_format = V4L2_PIX_FMT_YUV420;
+
+ int current_preview_width, current_preview_height, current_frame_size;
+ mSecCamera->getPreviewSize(¤t_preview_width,
+ ¤t_preview_height,
+ ¤t_frame_size);
+ int current_pixel_format = mSecCamera->getPreviewPixelFormat();
+
+ if (current_preview_width != new_preview_width ||
+ current_preview_height != new_preview_height ||
+ current_pixel_format != new_preview_format) {
+ if (mSecCamera->setPreviewSize(new_preview_width, new_preview_height,
+ new_preview_format) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setPreviewSize(width(%d), height(%d), format(%d))",
+ __func__, new_preview_width, new_preview_height, new_preview_format);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (mPreviewWindow) {
+ if (mPreviewRunning && !mPreviewStartDeferred) {
+ LOGE("ERR(%s): preview is running, cannot change size and format!",
+ __func__);
+ ret = INVALID_OPERATION;
+ }
+
+ LOGV("%s: mPreviewWindow (%p) set_buffers_geometry", __func__, mPreviewWindow);
+ LOGV("%s: mPreviewWindow->set_buffers_geometry (%p)", __func__,
+ mPreviewWindow->set_buffers_geometry);
+ mPreviewWindow->set_buffers_geometry(mPreviewWindow,
+ new_preview_width, new_preview_height,
+ new_preview_format);
+ LOGV("%s: DONE mPreviewWindow (%p) set_buffers_geometry", __func__, mPreviewWindow);
+ }
+
+ mParameters.setPreviewSize(new_preview_width, new_preview_height);
+ mParameters.setPreviewFormat(new_str_preview_format);
+ }
+ }
+ else LOGV("%s: preview size and format has not changed", __func__);
+ } else {
+ LOGE("%s: Invalid preview size(%dx%d)",
+ __func__, new_preview_width, new_preview_height);
+
+ ret = INVALID_OPERATION;
+ }
+
+ int new_picture_width = 0;
+ int new_picture_height = 0;
+
+ params.getPictureSize(&new_picture_width, &new_picture_height);
+ LOGV("%s : new_picture_width x new_picture_height = %dx%d", __func__, new_picture_width, new_picture_height);
+ if (0 < new_picture_width && 0 < new_picture_height) {
+ LOGV("%s: setSnapshotSize", __func__);
+ if (mSecCamera->setSnapshotSize(new_picture_width, new_picture_height) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSnapshotSize(width(%d), height(%d))",
+ __func__, new_picture_width, new_picture_height);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.setPictureSize(new_picture_width, new_picture_height);
+ }
+ }
+
+ // picture format
+ const char *new_str_picture_format = params.getPictureFormat();
+ LOGV("%s : new_str_picture_format %s", __func__, new_str_picture_format);
+ if (new_str_picture_format != NULL) {
+ int new_picture_format = 0;
+
+ if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_RGB565))
+ new_picture_format = V4L2_PIX_FMT_RGB565;
+ else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_RGBA8888))
+ new_picture_format = V4L2_PIX_FMT_RGB32;
+ else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_YUV420SP))
+ new_picture_format = V4L2_PIX_FMT_NV21;
+ else if (!strcmp(new_str_picture_format, "yuv420sp_custom"))
+ new_picture_format = V4L2_PIX_FMT_NV12T;
+ else if (!strcmp(new_str_picture_format, "yuv420p"))
+ new_picture_format = V4L2_PIX_FMT_YUV420;
+ else if (!strcmp(new_str_picture_format, "yuv422i"))
+ new_picture_format = V4L2_PIX_FMT_YUYV;
+ else if (!strcmp(new_str_picture_format, "uyv422i_custom")) //Zero copy UYVY format
+ new_picture_format = V4L2_PIX_FMT_UYVY;
+ else if (!strcmp(new_str_picture_format, "uyv422i")) //Non-zero copy UYVY format
+ new_picture_format = V4L2_PIX_FMT_UYVY;
+ else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_JPEG))
+ new_picture_format = V4L2_PIX_FMT_YUYV;
+ else if (!strcmp(new_str_picture_format, "yuv422p"))
+ new_picture_format = V4L2_PIX_FMT_YUV422P;
+ else
+ new_picture_format = V4L2_PIX_FMT_NV21; //for 3rd party
+
+ if (mSecCamera->setSnapshotPixelFormat(new_picture_format) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSnapshotPixelFormat(format(%d))", __func__, new_picture_format);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.setPictureFormat(new_str_picture_format);
+ }
+ }
+
+ //JPEG image quality
+ int new_jpeg_quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
+ LOGV("%s : new_jpeg_quality %d", __func__, new_jpeg_quality);
+ /* we ignore bad values */
+ if (new_jpeg_quality >=1 && new_jpeg_quality <= 100) {
+ if (mSecCamera->setJpegQuality(new_jpeg_quality) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setJpegQuality(quality(%d))", __func__, new_jpeg_quality);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_JPEG_QUALITY, new_jpeg_quality);
+ }
+ }
+
+ // JPEG thumbnail size
+ int new_jpeg_thumbnail_width = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ int new_jpeg_thumbnail_height= params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+ if (0 <= new_jpeg_thumbnail_width && 0 <= new_jpeg_thumbnail_height) {
+ if (mSecCamera->setJpegThumbnailSize(new_jpeg_thumbnail_width, new_jpeg_thumbnail_height) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setJpegThumbnailSize(width(%d), height(%d))", __func__, new_jpeg_thumbnail_width, new_jpeg_thumbnail_height);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, new_jpeg_thumbnail_width);
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, new_jpeg_thumbnail_height);
+ }
+ }
+
+ // frame rate
+ int new_frame_rate = params.getPreviewFrameRate();
+ /* ignore any fps request, we're determine fps automatically based
+ * on scene mode. don't return an error because it causes CTS failure.
+ */
+ if (new_frame_rate != mParameters.getPreviewFrameRate()) {
+ LOGW("WARN(%s): request for preview frame %d not allowed, != %d\n",
+ __func__, new_frame_rate, mParameters.getPreviewFrameRate());
+ }
+
+ // rotation
+ int new_rotation = params.getInt(CameraParameters::KEY_ROTATION);
+ LOGV("%s : new_rotation %d", __func__, new_rotation);
+ if (0 <= new_rotation) {
+ LOGV("%s : set orientation:%d\n", __func__, new_rotation);
+ if (mSecCamera->setExifOrientationInfo(new_rotation) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setExifOrientationInfo(%d)", __func__, new_rotation);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_ROTATION, new_rotation);
+ }
+ }
+
+ // brightness
+ int new_exposure_compensation = params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
+ int max_exposure_compensation = params.getInt(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION);
+ int min_exposure_compensation = params.getInt(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION);
+ LOGV("%s : new_exposure_compensation %d", __func__, new_exposure_compensation);
+ if ((min_exposure_compensation <= new_exposure_compensation) &&
+ (max_exposure_compensation >= new_exposure_compensation)) {
+ if (mSecCamera->setBrightness(new_exposure_compensation) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setBrightness(brightness(%d))", __func__, new_exposure_compensation);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, new_exposure_compensation);
+ }
+ }
+
+ // whitebalance
+ const char *new_white_str = params.get(CameraParameters::KEY_WHITE_BALANCE);
+ LOGV("%s : new_white_str %s", __func__, new_white_str);
+ if (new_white_str != NULL) {
+ int new_white = -1;
+
+ if (!strcmp(new_white_str, CameraParameters::WHITE_BALANCE_AUTO))
+ new_white = WHITE_BALANCE_AUTO;
+ else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_DAYLIGHT))
+ new_white = WHITE_BALANCE_SUNNY;
+ else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT))
+ new_white = WHITE_BALANCE_CLOUDY_DAYLIGHT;
+ else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_FLUORESCENT))
+ new_white = WHITE_BALANCE_FLUORESCENT;
+ else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_INCANDESCENT))
+ new_white = WHITE_BALANCE_TUNGSTEN;
+ else {
+ LOGE("ERR(%s):Invalid white balance(%s)", __func__, new_white_str); //twilight, shade, warm_flourescent
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_white) {
+ if (mSecCamera->setWhiteBalance(new_white) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setWhiteBalance(white(%d))", __func__, new_white);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_WHITE_BALANCE, new_white_str);
+ }
+ }
+ }
+
+ // scene mode
+ const char *new_scene_mode_str = params.get(CameraParameters::KEY_SCENE_MODE);
+ const char *current_scene_mode_str = mParameters.get(CameraParameters::KEY_SCENE_MODE);
+
+ // fps range
+ int new_min_fps = 0;
+ int new_max_fps = 0;
+ int current_min_fps, current_max_fps;
+ params.getPreviewFpsRange(&new_min_fps, &new_max_fps);
+ mParameters.getPreviewFpsRange(¤t_min_fps, ¤t_max_fps);
+ /* our fps range is determined by the sensor, reject any request
+ * that isn't exactly what we're already at.
+ * but the check is performed when requesting only changing fps range
+ */
+ if (new_scene_mode_str && current_scene_mode_str) {
+ if (!strcmp(new_scene_mode_str, current_scene_mode_str)) {
+ if ((new_min_fps != current_min_fps) || (new_max_fps != current_max_fps)) {
+ LOGW("%s : requested new_min_fps = %d, new_max_fps = %d not allowed",
+ __func__, new_min_fps, new_max_fps);
+ LOGE("%s : current_min_fps = %d, current_max_fps = %d",
+ __func__, current_min_fps, current_max_fps);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+ } else {
+ /* Check basic validation if scene mode is different */
+ if ((new_min_fps > new_max_fps) ||
+ (new_min_fps < 0) || (new_max_fps < 0))
+ ret = UNKNOWN_ERROR;
+ }
+
+ const char *new_focus_mode_str = params.get(CameraParameters::KEY_FOCUS_MODE);
+
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK) {
+ int new_scene_mode = -1;
+
+ const char *new_flash_mode_str = params.get(CameraParameters::KEY_FLASH_MODE);
+
+ // fps range is (15000,30000) by default.
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(15000,30000)");
+ mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE,
+ "15000,30000");
+
+ if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_AUTO)) {
+ new_scene_mode = SCENE_MODE_NONE;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "on,off,auto,torch");
+ } else {
+ // defaults for non-auto scene modes
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK) {
+ new_focus_mode_str = CameraParameters::FOCUS_MODE_AUTO;
+ }
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+
+ if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_PORTRAIT)) {
+ new_scene_mode = SCENE_MODE_PORTRAIT;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_AUTO;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "auto");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_LANDSCAPE)) {
+ new_scene_mode = SCENE_MODE_LANDSCAPE;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_SPORTS)) {
+ new_scene_mode = SCENE_MODE_SPORTS;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_PARTY)) {
+ new_scene_mode = SCENE_MODE_PARTY_INDOOR;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_AUTO;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "auto");
+ } else if ((!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_BEACH)) ||
+ (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_SNOW))) {
+ new_scene_mode = SCENE_MODE_BEACH_SNOW;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_SUNSET)) {
+ new_scene_mode = SCENE_MODE_SUNSET;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_NIGHT)) {
+ new_scene_mode = SCENE_MODE_NIGHTSHOT;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(4000,30000)");
+ mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE,
+ "4000,30000");
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_FIREWORKS)) {
+ new_scene_mode = SCENE_MODE_FIREWORKS;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_CANDLELIGHT)) {
+ new_scene_mode = SCENE_MODE_CANDLE_LIGHT;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else {
+ LOGE("%s::unmatched scene_mode(%s)",
+ __func__, new_scene_mode_str); //action, night-portrait, theatre, steadyphoto
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ // focus mode
+ if (new_focus_mode_str != NULL) {
+ int new_focus_mode = -1;
+
+ if (!strcmp(new_focus_mode_str,
+ CameraParameters::FOCUS_MODE_AUTO)) {
+ new_focus_mode = FOCUS_MODE_AUTO;
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR);
+ }
+ else if (!strcmp(new_focus_mode_str,
+ CameraParameters::FOCUS_MODE_MACRO)) {
+ new_focus_mode = FOCUS_MODE_MACRO;
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_MACRO_FOCUS_DISTANCES_STR);
+ }
+ else if (!strcmp(new_focus_mode_str,
+ CameraParameters::FOCUS_MODE_INFINITY)) {
+ new_focus_mode = FOCUS_MODE_INFINITY;
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_INFINITY_FOCUS_DISTANCES_STR);
+ }
+ else {
+ LOGE("%s::unmatched focus_mode(%s)", __func__, new_focus_mode_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_focus_mode) {
+ if (mSecCamera->setFocusMode(new_focus_mode) < 0) {
+ LOGE("%s::mSecCamera->setFocusMode(%d) fail", __func__, new_focus_mode);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_FOCUS_MODE, new_focus_mode_str);
+ }
+ }
+ }
+
+ // flash..
+ if (new_flash_mode_str != NULL) {
+ int new_flash_mode = -1;
+
+ if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_OFF))
+ new_flash_mode = FLASH_MODE_OFF;
+ else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_AUTO))
+ new_flash_mode = FLASH_MODE_AUTO;
+ else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_ON))
+ new_flash_mode = FLASH_MODE_ON;
+ else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_TORCH))
+ new_flash_mode = FLASH_MODE_TORCH;
+ else {
+ LOGE("%s::unmatched flash_mode(%s)", __func__, new_flash_mode_str); //red-eye
+ ret = UNKNOWN_ERROR;
+ }
+ if (0 <= new_flash_mode) {
+ if (mSecCamera->setFlashMode(new_flash_mode) < 0) {
+ LOGE("%s::mSecCamera->setFlashMode(%d) fail", __func__, new_flash_mode);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_FLASH_MODE, new_flash_mode_str);
+ }
+ }
+ }
+
+ // scene..
+ if (0 <= new_scene_mode) {
+ if (mSecCamera->setSceneMode(new_scene_mode) < 0) {
+ LOGE("%s::mSecCamera->setSceneMode(%d) fail", __func__, new_scene_mode);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_SCENE_MODE, new_scene_mode_str);
+ }
+ }
+ } else {
+ if (!isSupportedParameter(new_focus_mode_str,
+ mParameters.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES))) {
+ LOGE("%s: Unsupported focus mode: %s", __func__, new_focus_mode_str);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+
+ // image effect
+ const char *new_image_effect_str = params.get(CameraParameters::KEY_EFFECT);
+ if (new_image_effect_str != NULL) {
+
+ int new_image_effect = -1;
+
+ if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_NONE))
+ new_image_effect = IMAGE_EFFECT_NONE;
+ else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_MONO))
+ new_image_effect = IMAGE_EFFECT_BNW;
+ else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_SEPIA))
+ new_image_effect = IMAGE_EFFECT_SEPIA;
+ else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_AQUA))
+ new_image_effect = IMAGE_EFFECT_AQUA;
+ else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_NEGATIVE))
+ new_image_effect = IMAGE_EFFECT_NEGATIVE;
+ else {
+ //posterize, whiteboard, blackboard, solarize
+ LOGE("ERR(%s):Invalid effect(%s)", __func__, new_image_effect_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (new_image_effect >= 0) {
+ if (mSecCamera->setImageEffect(new_image_effect) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setImageEffect(effect(%d))", __func__, new_image_effect);
+ ret = UNKNOWN_ERROR;
+ } else {
+ const char *old_image_effect_str = mParameters.get(CameraParameters::KEY_EFFECT);
+
+ if (old_image_effect_str) {
+ if (strcmp(old_image_effect_str, new_image_effect_str)) {
+ setSkipFrame(EFFECT_SKIP_FRAME);
+ }
+ }
+
+ mParameters.set(CameraParameters::KEY_EFFECT, new_image_effect_str);
+ }
+ }
+ }
+
+ //vt mode
+ int new_vtmode = mInternalParameters.getInt("vtmode");
+ if (0 <= new_vtmode) {
+ if (mSecCamera->setVTmode(new_vtmode) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setVTMode(%d)", __func__, new_vtmode);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ //contrast
+ int new_contrast = mInternalParameters.getInt("contrast");
+
+ if (0 <= new_contrast) {
+ if (mSecCamera->setContrast(new_contrast) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setContrast(%d)", __func__, new_contrast);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ // Recording size
+ int new_recording_width = mInternalParameters.getInt("recording-size-width");
+ int new_recording_height= mInternalParameters.getInt("recording-size-height");
+
+ if (0 < new_recording_width && 0 < new_recording_height) {
+ if (mSecCamera->setRecordingSize(new_recording_width, new_recording_height) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setRecordingSize(width(%d), height(%d))", __func__, new_recording_width, new_recording_height);
+ ret = UNKNOWN_ERROR;
+ }
+ } else {
+ if (mSecCamera->setRecordingSize(new_preview_width, new_preview_height) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setRecordingSize(width(%d), height(%d))", __func__, new_preview_width, new_preview_height);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ /*Camcorder fix fps*/
+ int new_sensor_mode = mInternalParameters.getInt("cam_mode");
+
+ if (0 <= new_sensor_mode) {
+ if (mSecCamera->setSensorMode(new_sensor_mode) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSensorMode(%d)", __func__, new_sensor_mode);
+ ret = UNKNOWN_ERROR;
+ }
+ } else {
+ new_sensor_mode=0;
+ }
+
+ /*Shot mode*/
+ int new_shot_mode = mInternalParameters.getInt("shot_mode");
+
+ if (0 <= new_shot_mode) {
+ if (mSecCamera->setShotMode(new_shot_mode) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setShotMode(%d)", __func__, new_shot_mode);
+ ret = UNKNOWN_ERROR;
+ }
+ } else {
+ new_shot_mode=0;
+ }
+
+ //blur for Video call
+ int new_blur_level = mInternalParameters.getInt("blur");
+
+ if (0 <= new_blur_level) {
+ if (mSecCamera->setBlur(new_blur_level) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setBlur(%d)", __func__, new_blur_level);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+
+ // chk_dataline
+ int new_dataline = mInternalParameters.getInt("chk_dataline");
+
+ if (0 <= new_dataline) {
+ if (mSecCamera->setDataLineCheck(new_dataline) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setDataLineCheck(%d)", __func__, new_dataline);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+ LOGV("%s return ret = %d", __func__, ret);
+
+ return ret;
+}
+
+CameraParameters CameraHardwareSec::getParameters() const
+{
+ LOGV("%s :", __func__);
+ return mParameters;
+}
+
+status_t CameraHardwareSec::sendCommand(int32_t command, int32_t arg1, int32_t arg2)
+{
+ return BAD_VALUE;
+}
+
+void CameraHardwareSec::release()
+{
+ LOGV("%s", __func__);
+
+ /* shut down any threads we have that might be running. do it here
+ * instead of the destructor. we're guaranteed to be on another thread
+ * than the ones below. if we used the destructor, since the threads
+ * have a reference to this object, we could wind up trying to wait
+ * for ourself to exit, which is a deadlock.
+ */
+ if (mPreviewThread != NULL) {
+ /* this thread is normally already in it's threadLoop but blocked
+ * on the condition variable or running. signal it so it wakes
+ * up and can exit.
+ */
+ mPreviewThread->requestExit();
+ mExitPreviewThread = true;
+ mPreviewRunning = true; /* let it run so it can exit */
+ mPreviewCondition.signal();
+ mPreviewThread->requestExitAndWait();
+ mPreviewThread.clear();
+ }
+ if (mAutoFocusThread != NULL) {
+ /* this thread is normally already in it's threadLoop but blocked
+ * on the condition variable. signal it so it wakes up and can exit.
+ */
+ mFocusLock.lock();
+ mAutoFocusThread->requestExit();
+ mExitAutoFocusThread = true;
+ mFocusCondition.signal();
+ mFocusLock.unlock();
+ mAutoFocusThread->requestExitAndWait();
+ mAutoFocusThread.clear();
+ }
+ if (mPictureThread != NULL) {
+ mPictureThread->requestExitAndWait();
+ mPictureThread.clear();
+ }
+
+ if (mRawHeap) {
+ mRawHeap->release(mRawHeap);
+ mRawHeap = 0;
+ }
+ if (mPreviewHeap) {
+ mPreviewHeap->release(mPreviewHeap);
+ mPreviewHeap = 0;
+ }
+ if (mRecordHeap) {
+ mRecordHeap->release(mRecordHeap);
+ mRecordHeap = 0;
+ }
+
+ /* close after all the heaps are cleared since those
+ * could have dup'd our file descriptor.
+ */
+ mSecCamera->DeinitCamera();
+}
+
+status_t CameraHardwareSec::storeMetaDataInBuffers(bool enable)
+{
+ // FIXME:
+ // metadata buffer mode can be turned on or off.
+ // Samsung needs to fix this.
+ if (!enable) {
+ LOGE("Non-metadata buffer mode is not supported!");
+ return INVALID_OPERATION;
+ }
+ return OK;
+}
+
+static CameraInfo sCameraInfo[] = {
+ {
+ CAMERA_FACING_BACK,
+ 90, /* orientation */
+ },
+ {
+ CAMERA_FACING_FRONT,
+ 270, /* orientation */
+ }
+};
+
+/** Close this device */
+
+static camera_device_t *g_cam_device;
+
+static int HAL_camera_device_close(struct hw_device_t* device)
+{
+ LOGI("%s", __func__);
+ if (device) {
+ camera_device_t *cam_device = (camera_device_t *)device;
+ delete static_cast(cam_device->priv);
+ free(cam_device);
+ g_cam_device = 0;
+ }
+ return 0;
+}
+
+static inline CameraHardwareSec *obj(struct camera_device *dev)
+{
+ return reinterpret_cast(dev->priv);
+}
+
+/** Set the preview_stream_ops to which preview frames are sent */
+static int HAL_camera_device_set_preview_window(struct camera_device *dev,
+ struct preview_stream_ops *buf)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->setPreviewWindow(buf);
+}
+
+/** Set the notification and data callbacks */
+static void HAL_camera_device_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)
+{
+ LOGV("%s", __func__);
+ obj(dev)->setCallbacks(notify_cb, data_cb, data_cb_timestamp,
+ get_memory,
+ user);
+}
+
+/**
+ * The following three functions all take a msg_type, which is a bitmask of
+ * the messages defined in include/ui/Camera.h
+ */
+
+/**
+ * Enable a message, or set of messages.
+ */
+static void HAL_camera_device_enable_msg_type(struct camera_device *dev, int32_t msg_type)
+{
+ LOGV("%s", __func__);
+ obj(dev)->enableMsgType(msg_type);
+}
+
+/**
+ * Disable a message, or a set of messages.
+ *
+ * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera
+ * HAL should not rely on its client to call releaseRecordingFrame() to
+ * release video recording frames sent out by the cameral HAL before and
+ * after the disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera HAL
+ * clients must not modify/access any video recording frame after calling
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME).
+ */
+static void HAL_camera_device_disable_msg_type(struct camera_device *dev, int32_t msg_type)
+{
+ LOGV("%s", __func__);
+ obj(dev)->disableMsgType(msg_type);
+}
+
+/**
+ * Query whether a message, or a set of messages, is enabled. Note that
+ * this is operates as an AND, if any of the messages queried are off, this
+ * will return false.
+ */
+static int HAL_camera_device_msg_type_enabled(struct camera_device *dev, int32_t msg_type)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->msgTypeEnabled(msg_type);
+}
+
+/**
+ * Start preview mode.
+ */
+static int HAL_camera_device_start_preview(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->startPreview();
+}
+
+/**
+ * Stop a previously started preview.
+ */
+static void HAL_camera_device_stop_preview(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ obj(dev)->stopPreview();
+}
+
+/**
+ * Returns true if preview is enabled.
+ */
+static int HAL_camera_device_preview_enabled(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->previewEnabled();
+}
+
+/**
+ * Request the camera HAL to store meta data or real YUV data in the video
+ * buffers sent out via CAMERA_MSG_VIDEO_FRAME for a recording session. If
+ * it is not called, the default camera HAL behavior is to store real YUV
+ * data in the video buffers.
+ *
+ * This method should be called before startRecording() in order to be
+ * effective.
+ *
+ * If meta data is stored in the video buffers, it is up to the receiver of
+ * the video buffers to interpret the contents and to find the actual frame
+ * data with the help of the meta data in the buffer. How this is done is
+ * outside of the scope of this method.
+ *
+ * Some camera HALs may not support storing meta data in the video buffers,
+ * but all camera HALs should support storing real YUV data in the video
+ * buffers. If the camera HAL does not support storing the meta data in the
+ * video buffers when it is requested to do do, INVALID_OPERATION must be
+ * returned. It is very useful for the camera HAL to pass meta data rather
+ * than the actual frame data directly to the video encoder, since the
+ * amount of the uncompressed frame data can be very large if video size is
+ * large.
+ *
+ * @param enable if true to instruct the camera HAL to store
+ * meta data in the video buffers; false to instruct
+ * the camera HAL to store real YUV data in the video
+ * buffers.
+ *
+ * @return OK on success.
+ */
+static int HAL_camera_device_store_meta_data_in_buffers(struct camera_device *dev, int enable)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->storeMetaDataInBuffers(enable);
+}
+
+/**
+ * Start record mode. When a record image is available, a
+ * CAMERA_MSG_VIDEO_FRAME message is sent with the corresponding
+ * frame. Every record frame must be released by a camera HAL client via
+ * releaseRecordingFrame() before the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+ * responsibility to manage the life-cycle of the video recording frames,
+ * and the client must not modify/access any video recording frames.
+ */
+static int HAL_camera_device_start_recording(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->startRecording();
+}
+
+/**
+ * Stop a previously started recording.
+ */
+static void HAL_camera_device_stop_recording(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ obj(dev)->stopRecording();
+}
+
+/**
+ * Returns true if recording is enabled.
+ */
+static int HAL_camera_device_recording_enabled(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->recordingEnabled();
+}
+
+/**
+ * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
+ *
+ * It is camera HAL client's responsibility to release video recording
+ * frames sent out by the camera HAL before the camera HAL receives a call
+ * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+ * responsibility to manage the life-cycle of the video recording frames.
+ */
+static void HAL_camera_device_release_recording_frame(struct camera_device *dev,
+ const void *opaque)
+{
+ LOGV("%s", __func__);
+ obj(dev)->releaseRecordingFrame(opaque);
+}
+
+/**
+ * Start auto focus, the notification callback routine is called with
+ * CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() will be
+ * called again if another auto focus is needed.
+ */
+static int HAL_camera_device_auto_focus(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->autoFocus();
+}
+
+/**
+ * Cancels auto-focus function. If the auto-focus is still in progress,
+ * this function will cancel it. Whether the auto-focus is in progress or
+ * not, this function will return the focus position to the default. If
+ * the camera does not support auto-focus, this is a no-op.
+ */
+static int HAL_camera_device_cancel_auto_focus(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->cancelAutoFocus();
+}
+
+/**
+ * Take a picture.
+ */
+static int HAL_camera_device_take_picture(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->takePicture();
+}
+
+/**
+ * Cancel a picture that was started with takePicture. Calling this method
+ * when no picture is being taken is a no-op.
+ */
+static int HAL_camera_device_cancel_picture(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->cancelPicture();
+}
+
+/**
+ * Set the camera parameters. This returns BAD_VALUE if any parameter is
+ * invalid or not supported.
+ */
+static int HAL_camera_device_set_parameters(struct camera_device *dev,
+ const char *parms)
+{
+ LOGV("%s", __func__);
+ String8 str(parms);
+ CameraParameters p(str);
+ return obj(dev)->setParameters(p);
+}
+
+/** Return the camera parameters. */
+char *HAL_camera_device_get_parameters(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ String8 str;
+ CameraParameters parms = obj(dev)->getParameters();
+ str = parms.flatten();
+ return strdup(str.string());
+}
+
+void HAL_camera_device_put_parameters(struct camera_device *dev, char *parms)
+{
+ LOGV("%s", __func__);
+ free(parms);
+}
+
+/**
+ * Send command to camera driver.
+ */
+static int HAL_camera_device_send_command(struct camera_device *dev,
+ int32_t cmd, int32_t arg1, int32_t arg2)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->sendCommand(cmd, arg1, arg2);
+}
+
+/**
+ * Release the hardware resources owned by this object. Note that this is
+ * *not* done in the destructor.
+ */
+static void HAL_camera_device_release(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ obj(dev)->release();
+}
+
+/**
+ * Dump state of the camera hardware
+ */
+static int HAL_camera_device_dump(struct camera_device *dev, int fd)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->dump(fd);
+}
+
+static int HAL_getNumberOfCameras()
+{
+ LOGV("%s", __func__);
+ return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
+}
+
+static int HAL_getCameraInfo(int cameraId, struct camera_info *cameraInfo)
+{
+ LOGV("%s", __func__);
+ memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
+ return 0;
+}
+
+#define SET_METHOD(m) m : HAL_camera_device_##m
+
+static camera_device_ops_t camera_device_ops = {
+ SET_METHOD(set_preview_window),
+ SET_METHOD(set_callbacks),
+ SET_METHOD(enable_msg_type),
+ SET_METHOD(disable_msg_type),
+ SET_METHOD(msg_type_enabled),
+ SET_METHOD(start_preview),
+ SET_METHOD(stop_preview),
+ SET_METHOD(preview_enabled),
+ SET_METHOD(store_meta_data_in_buffers),
+ SET_METHOD(start_recording),
+ SET_METHOD(stop_recording),
+ SET_METHOD(recording_enabled),
+ SET_METHOD(release_recording_frame),
+ SET_METHOD(auto_focus),
+ SET_METHOD(cancel_auto_focus),
+ SET_METHOD(take_picture),
+ SET_METHOD(cancel_picture),
+ SET_METHOD(set_parameters),
+ SET_METHOD(get_parameters),
+ SET_METHOD(put_parameters),
+ SET_METHOD(send_command),
+ SET_METHOD(release),
+ SET_METHOD(dump),
+};
+
+#undef SET_METHOD
+
+static int HAL_camera_device_open(const struct hw_module_t* module,
+ const char *id,
+ struct hw_device_t** device)
+{
+ LOGV("%s", __func__);
+
+ int cameraId = atoi(id);
+ if (cameraId < 0 || cameraId >= HAL_getNumberOfCameras()) {
+ LOGE("Invalid camera ID %s", id);
+ return -EINVAL;
+ }
+
+ if (g_cam_device) {
+ if (obj(g_cam_device)->getCameraId() == cameraId) {
+ LOGV("returning existing camera ID %s", id);
+ goto done;
+ } else {
+ LOGE("Cannot open camera %d. camera %d is already running!",
+ cameraId, obj(g_cam_device)->getCameraId());
+ return -ENOSYS;
+ }
+ }
+
+ g_cam_device = (camera_device_t *)malloc(sizeof(camera_device_t));
+ if (!g_cam_device)
+ return -ENOMEM;
+
+ g_cam_device->common.tag = HARDWARE_DEVICE_TAG;
+ g_cam_device->common.version = 1;
+ g_cam_device->common.module = const_cast(module);
+ g_cam_device->common.close = HAL_camera_device_close;
+
+ g_cam_device->ops = &camera_device_ops;
+
+ LOGI("%s: open camera %s", __func__, id);
+
+ g_cam_device->priv = new CameraHardwareSec(cameraId, g_cam_device);
+
+done:
+ *device = (hw_device_t *)g_cam_device;
+ LOGI("%s: opened camera %s (%p)", __func__, id, *device);
+ return 0;
+}
+
+static hw_module_methods_t camera_module_methods = {
+ open : HAL_camera_device_open
+};
+
+extern "C" {
+ struct camera_module HAL_MODULE_INFO_SYM = {
+ common : {
+ tag : HARDWARE_MODULE_TAG,
+ version_major : 1,
+ version_minor : 0,
+ id : CAMERA_HARDWARE_MODULE_ID,
+ name : "GalaxyTab camera HAL",
+ author : "Samsung Corporation",
+ methods : &camera_module_methods,
+ },
+ get_number_of_cameras : HAL_getNumberOfCameras,
+ get_camera_info : HAL_getCameraInfo
+ };
+}
+
+}; // namespace android
diff --git a/libcamera/SecCameraHWInterface.h b/libcamera/SecCameraHWInterface.h
new file mode 100644
index 0000000..e99aff6
--- /dev/null
+++ b/libcamera/SecCameraHWInterface.h
@@ -0,0 +1,214 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_SEC_H
+#define ANDROID_HARDWARE_CAMERA_HARDWARE_SEC_H
+
+#include "SecCamera.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace android {
+ class CameraHardwareSec : public virtual RefBase {
+public:
+ virtual void setCallbacks(camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user);
+
+ virtual void enableMsgType(int32_t msgType);
+ virtual void disableMsgType(int32_t msgType);
+ virtual bool msgTypeEnabled(int32_t msgType);
+
+ virtual status_t startPreview();
+ virtual void stopPreview();
+ virtual bool previewEnabled();
+
+ virtual status_t startRecording();
+ virtual void stopRecording();
+ virtual bool recordingEnabled();
+ virtual void releaseRecordingFrame(const void *opaque);
+
+ virtual status_t autoFocus();
+ virtual status_t cancelAutoFocus();
+ virtual status_t takePicture();
+ virtual status_t cancelPicture();
+ virtual status_t dump(int fd) const;
+ virtual status_t setParameters(const CameraParameters& params);
+ virtual CameraParameters getParameters() const;
+ virtual status_t sendCommand(int32_t command, int32_t arg1, int32_t arg2);
+ virtual status_t setPreviewWindow(preview_stream_ops *w);
+ virtual status_t storeMetaDataInBuffers(bool enable);
+ virtual void release();
+
+ inline int getCameraId() const;
+
+ CameraHardwareSec(int cameraId, camera_device_t *dev);
+ virtual ~CameraHardwareSec();
+private:
+ status_t startPreviewInternal();
+ void stopPreviewInternal();
+
+ static const int kBufferCount = MAX_BUFFERS;
+ static const int kBufferCountForRecord = MAX_BUFFERS;
+
+ class PreviewThread : public Thread {
+ CameraHardwareSec *mHardware;
+ public:
+ PreviewThread(CameraHardwareSec *hw):
+ Thread(false),
+ mHardware(hw) { }
+ virtual void onFirstRef() {
+ run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
+ }
+ virtual bool threadLoop() {
+ mHardware->previewThreadWrapper();
+ return false;
+ }
+ };
+
+ class PictureThread : public Thread {
+ CameraHardwareSec *mHardware;
+ public:
+ PictureThread(CameraHardwareSec *hw):
+ Thread(false),
+ mHardware(hw) { }
+ virtual bool threadLoop() {
+ mHardware->pictureThread();
+ return false;
+ }
+ };
+
+ class AutoFocusThread : public Thread {
+ CameraHardwareSec *mHardware;
+ public:
+ AutoFocusThread(CameraHardwareSec *hw): Thread(false), mHardware(hw) { }
+ virtual void onFirstRef() {
+ run("CameraAutoFocusThread", PRIORITY_DEFAULT);
+ }
+ virtual bool threadLoop() {
+ mHardware->autoFocusThread();
+ return true;
+ }
+ };
+
+ void initDefaultParameters(int cameraId);
+ void initHeapLocked();
+
+ sp mPreviewThread;
+ int previewThread();
+ int previewThreadWrapper();
+
+ sp mAutoFocusThread;
+ int autoFocusThread();
+
+ sp mPictureThread;
+ int pictureThread();
+ bool mCaptureInProgress;
+
+ int save_jpeg(unsigned char *real_jpeg, int jpeg_size);
+ void save_postview(const char *fname, uint8_t *buf,
+ uint32_t size);
+ int decodeInterleaveData(unsigned char *pInterleaveData,
+ int interleaveDataSize,
+ int yuvWidth,
+ int yuvHeight,
+ int *pJpegSize,
+ void *pJpegData,
+ void *pYuvData);
+ bool YUY2toNV21(void *srcBuf, void *dstBuf, uint32_t srcWidth, uint32_t srcHeight);
+ bool scaleDownYuv422(char *srcBuf, uint32_t srcWidth,
+ uint32_t srcHight, char *dstBuf,
+ uint32_t dstWidth, uint32_t dstHight);
+
+ bool CheckVideoStartMarker(unsigned char *pBuf);
+ bool CheckEOIMarker(unsigned char *pBuf);
+ bool FindEOIMarkerInJPEG(unsigned char *pBuf,
+ int dwBufSize, int *pnJPEGsize);
+ bool SplitFrame(unsigned char *pFrame, int dwSize,
+ int dwJPEGLineLength, int dwVideoLineLength,
+ int dwVideoHeight, void *pJPEG,
+ int *pdwJPEGSize, void *pVideo,
+ int *pdwVideoSize);
+ void setSkipFrame(int frame);
+ bool isSupportedPreviewSize(const int width,
+ const int height) const;
+ bool isSupportedParameter(const char * const parm,
+ const char * const supported_parm) const;
+ status_t waitCaptureCompletion();
+ /* used by auto focus thread to block until it's told to run */
+ mutable Mutex mFocusLock;
+ mutable Condition mFocusCondition;
+ bool mExitAutoFocusThread;
+
+ /* used by preview thread to block until it's told to run */
+ mutable Mutex mPreviewLock;
+ mutable Condition mPreviewCondition;
+ mutable Condition mPreviewStoppedCondition;
+ bool mPreviewRunning;
+ bool mPreviewStartDeferred;
+ bool mExitPreviewThread;
+
+ preview_stream_ops *mPreviewWindow;
+
+ /* used to guard mCaptureInProgress */
+ mutable Mutex mCaptureLock;
+ mutable Condition mCaptureCondition;
+
+ CameraParameters mParameters;
+ CameraParameters mInternalParameters;
+
+ camera_memory_t *mPreviewHeap;
+ camera_memory_t *mRawHeap;
+ camera_memory_t *mRecordHeap;
+
+ SecCamera *mSecCamera;
+ const __u8 *mCameraSensorName;
+
+ mutable Mutex mSkipFrameLock;
+ int mSkipFrame;
+
+ camera_notify_callback mNotifyCb;
+ camera_data_callback mDataCb;
+ camera_data_timestamp_callback mDataCbTimestamp;
+ camera_request_memory mGetMemoryCb;
+ void *mCallbackCookie;
+
+ int32_t mMsgEnabled;
+
+ bool mRecordRunning;
+ mutable Mutex mRecordLock;
+ int mPostViewWidth;
+ int mPostViewHeight;
+ int mPostViewSize;
+
+ Vector mSupportedPreviewSizes;
+
+ camera_device_t *mHalDevice;
+ static gralloc_module_t const* mGrallocHal;
+};
+
+}; // namespace android
+
+#endif
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
new file mode 100644
index 0000000..223326b
--- /dev/null
+++ b/libhwcomposer/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+# HAL module implemenation, not prelinked and stored in
+# hw/..so
+
+include $(CLEAR_VARS)
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL libGLESv1_CM libhardware
+LOCAL_CFLAGS += -DLOG_TAG=\"hwcomposer\"
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../include
+
+LOCAL_SRC_FILES := SecHWCUtils.cpp SecHWC.cpp
+
+LOCAL_MODULE := hwcomposer.s5pc110
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/libhwcomposer/SecHWC.cpp b/libhwcomposer/SecHWC.cpp
new file mode 100644
index 0000000..31c0b2c
--- /dev/null
+++ b/libhwcomposer/SecHWC.cpp
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ *
+ * @author Rama, Meka(v.meka@samsung.com)
+ Sangwoo, Park(sw5771.park@samsung.com)
+ Jamie Oh (jung-min.oh@samsung.com)
+ * @date 2011-07-28
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include "SecHWCUtils.h"
+
+static IMG_gralloc_module_public_t *gpsGrallocModule;
+
+static int hwc_device_open(const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device);
+
+static struct hw_module_methods_t hwc_module_methods = {
+ open: hwc_device_open
+};
+
+hwc_module_t HAL_MODULE_INFO_SYM = {
+ common: {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: HWC_HARDWARE_MODULE_ID,
+ name: "Samsung S5PC11X hwcomposer module",
+ author: "SAMSUNG",
+ methods: &hwc_module_methods,
+ }
+};
+
+static void dump_layer(hwc_layer_t const* l) {
+ LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
+ l->compositionType, l->flags, l->handle, l->transform, l->blending,
+ l->sourceCrop.left,
+ l->sourceCrop.top,
+ l->sourceCrop.right,
+ l->sourceCrop.bottom,
+ l->displayFrame.left,
+ l->displayFrame.top,
+ l->displayFrame.right,
+ l->displayFrame.bottom);
+}
+
+static int set_src_dst_info(hwc_layer_t *cur,
+ struct hwc_win_info_t *win,
+ struct sec_img *src_img,
+ struct sec_img *dst_img,
+ struct sec_rect *src_rect,
+ struct sec_rect *dst_rect,
+ int win_idx)
+{
+ IMG_native_handle_t *prev_handle = (IMG_native_handle_t *)(cur->handle);
+
+ // set src image
+ src_img->w = prev_handle->iWidth;
+ src_img->h = prev_handle->iHeight;
+ src_img->format = prev_handle->iFormat;
+ src_img->base = NULL;
+ src_img->offset = 0;
+ src_img->mem_id =0;
+
+ src_img->mem_type = HWC_PHYS_MEM_TYPE;
+ src_img->w = (src_img->w + 15) & (~15);
+ src_img->h = (src_img->h + 1) & (~1) ;
+
+ //set src rect
+ src_rect->x = SEC_MAX(cur->sourceCrop.left, 0);
+ src_rect->y = SEC_MAX(cur->sourceCrop.top, 0);
+ src_rect->w = SEC_MAX(cur->sourceCrop.right - cur->sourceCrop.left, 0);
+ src_rect->w = SEC_MIN(src_rect->w, src_img->w - src_rect->x);
+ src_rect->h = SEC_MAX(cur->sourceCrop.bottom - cur->sourceCrop.top, 0);
+ src_rect->h = SEC_MIN(src_rect->h, src_img->h - src_rect->y);
+
+ //set dst image
+ dst_img->w = win->lcd_info.xres;
+ dst_img->h = win->lcd_info.yres;
+
+ switch (win->lcd_info.bits_per_pixel) {
+ case 32:
+ dst_img->format = HAL_PIXEL_FORMAT_RGBX_8888;
+ break;
+ default:
+ dst_img->format = HAL_PIXEL_FORMAT_RGB_565;
+ break;
+ }
+
+ dst_img->base = win->addr[win->buf_index];
+ dst_img->offset = 0;
+ dst_img->mem_id = 0;
+ dst_img->mem_type = HWC_PHYS_MEM_TYPE;
+
+ //set dst rect
+ //fimc dst image will be stored from left top corner
+ dst_rect->x = 0;
+ dst_rect->y = 0;
+ dst_rect->w = win->rect_info.w;
+ dst_rect->h = win->rect_info.h;
+
+ LOGV("%s::sr_x %d sr_y %d sr_w %d sr_h %d dr_x %d dr_y %d dr_w %d dr_h %d ",
+ __func__, src_rect->x, src_rect->y, src_rect->w, src_rect->h,
+ dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h);
+
+ return 0;
+}
+
+static int get_hwc_compos_decision(hwc_layer_t* cur)
+{
+ if(cur->flags & HWC_SKIP_LAYER || !cur->handle) {
+ LOGV("%s::is_skip_layer %d cur->handle %x",
+ __func__, cur->flags & HWC_SKIP_LAYER, (uint32_t)cur->handle);
+ return HWC_FRAMEBUFFER;
+ }
+
+ IMG_native_handle_t *prev_handle = (IMG_native_handle_t *)(cur->handle);
+ int compositionType = HWC_FRAMEBUFFER;
+
+ /* check here....if we have any resolution constraints */
+ if (((cur->sourceCrop.right - cur->sourceCrop.left) < 16) ||
+ ((cur->sourceCrop.bottom - cur->sourceCrop.top) < 8))
+ return compositionType;
+
+ if ((cur->transform == HAL_TRANSFORM_ROT_90) ||
+ (cur->transform == HAL_TRANSFORM_ROT_270)) {
+ if(((cur->displayFrame.right - cur->displayFrame.left) < 4)||
+ ((cur->displayFrame.bottom - cur->displayFrame.top) < 8))
+ return compositionType;
+ } else if (((cur->displayFrame.right - cur->displayFrame.left) < 8) ||
+ ((cur->displayFrame.bottom - cur->displayFrame.top) < 4))
+ return compositionType;
+
+ if((prev_handle->usage & GRALLOC_USAGE_PHYS_CONTIG) &&
+ (cur->blending == HWC_BLENDING_NONE))
+ compositionType = HWC_OVERLAY;
+ else
+ compositionType = HWC_FRAMEBUFFER;
+
+ LOGV("%s::compositionType %d bpp %d format %x usage %x",
+ __func__,compositionType, prev_handle->uiBpp, prev_handle->iFormat,
+ prev_handle->usage & GRALLOC_USAGE_PHYS_CONTIG);
+
+ return compositionType;
+}
+
+static int assign_overlay_window(struct hwc_context_t *ctx,
+ hwc_layer_t *cur,
+ int win_idx,
+ int layer_idx)
+{
+ struct hwc_win_info_t *win;
+ sec_rect rect;
+ int ret = 0;
+
+ if(NUM_OF_WIN <= win_idx)
+ return -1;
+
+ win = &ctx->win[win_idx];
+
+ rect.x = SEC_MAX(cur->displayFrame.left, 0);
+ rect.y = SEC_MAX(cur->displayFrame.top, 0);
+ rect.w = SEC_MIN(cur->displayFrame.right - rect.x, win->lcd_info.xres - rect.x);
+ rect.h = SEC_MIN(cur->displayFrame.bottom - rect.y, win->lcd_info.yres - rect.y);
+ win->set_win_flag = 0;
+
+ if((rect.x != win->rect_info.x) || (rect.y != win->rect_info.y) ||
+ (rect.w != win->rect_info.w) || (rect.h != win->rect_info.h)){
+ win->rect_info.x = rect.x;
+ win->rect_info.y = rect.y;
+ win->rect_info.w = rect.w;
+ win->rect_info.h = rect.h;
+ win->set_win_flag = 1;
+ win->layer_prev_buf = 0;
+ }
+
+ win->layer_index = layer_idx;
+ win->status = HWC_WIN_RESERVED;
+
+ LOGV("%s:: win_x %d win_y %d win_w %d win_h %d lay_idx %d win_idx %d",
+ __func__, win->rect_info.x, win->rect_info.y, win->rect_info.w,
+ win->rect_info.h, win->layer_index, win_idx );
+
+ return 0;
+}
+
+static void reset_win_rect_info(hwc_win_info_t *win)
+{
+ win->rect_info.x = 0;
+ win->rect_info.y = 0;
+ win->rect_info.w = 0;
+ win->rect_info.h = 0;
+ return;
+}
+
+static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list)
+{
+
+ struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
+ int overlay_win_cnt = 0;
+ int compositionType = 0;
+ int ret;
+
+ //if geometry is not changed, there is no need to do any work here
+ if( !list || (!(list->flags & HWC_GEOMETRY_CHANGED)))
+ return 0;
+
+ //all the windows are free here....
+ for (int i = 0; i < NUM_OF_WIN; i++) {
+ ctx->win[i].status = HWC_WIN_FREE;
+ ctx->win[i].buf_index = 0;
+ }
+ ctx->num_of_hwc_layer = 0;
+ ctx->num_of_fb_layer = 0;
+ LOGV("%s:: hwc_prepare list->numHwLayers %d", __func__, list->numHwLayers);
+
+ for (int i = 0; i < list->numHwLayers ; i++) {
+ hwc_layer_t* cur = &list->hwLayers[i];
+
+ if (overlay_win_cnt < NUM_OF_WIN) {
+ compositionType = get_hwc_compos_decision(cur);
+
+ if (compositionType == HWC_FRAMEBUFFER) {
+ cur->compositionType = HWC_FRAMEBUFFER;
+ ctx->num_of_fb_layer++;
+ } else {
+ ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i);
+ if (ret != 0) {
+ cur->compositionType = HWC_FRAMEBUFFER;
+ ctx->num_of_fb_layer++;
+ continue;
+ }
+
+ cur->compositionType = HWC_OVERLAY;
+ cur->hints = HWC_HINT_CLEAR_FB;
+ overlay_win_cnt++;
+ ctx->num_of_hwc_layer++;
+ }
+ } else {
+ cur->compositionType = HWC_FRAMEBUFFER;
+ ctx->num_of_fb_layer++;
+ }
+ }
+
+ if(list->numHwLayers != (ctx->num_of_fb_layer + ctx->num_of_hwc_layer))
+ LOGV("%s:: numHwLayers %d num_of_fb_layer %d num_of_hwc_layer %d ",
+ __func__, list->numHwLayers, ctx->num_of_fb_layer,
+ ctx->num_of_hwc_layer);
+
+ if (overlay_win_cnt < NUM_OF_WIN) {
+ //turn off the free windows
+ for (int i = overlay_win_cnt; i < NUM_OF_WIN; i++) {
+ window_hide(&ctx->win[i]);
+ reset_win_rect_info(&ctx->win[i]);
+ }
+ }
+ return 0;
+}
+
+static int hwc_set(hwc_composer_device_t *dev,
+ hwc_display_t dpy,
+ hwc_surface_t sur,
+ hwc_layer_list_t* list)
+{
+ struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
+ unsigned int phyAddr[MAX_NUM_PLANES];
+ int skipped_window_mask = 0;
+ hwc_layer_t* cur;
+ struct hwc_win_info_t *win;
+ int ret;
+ struct sec_img src_img;
+ struct sec_img dst_img;
+ struct sec_rect src_rect;
+ struct sec_rect dst_rect;
+
+
+ if (dpy == NULL && sur == NULL && list == NULL) {
+ // release our resources, the screen is turning off
+ // in our case, there is nothing to do.
+ ctx->num_of_fb_layer_prev = 0;
+ return 0;
+ }
+
+ bool need_swap_buffers = ctx->num_of_fb_layer > 0;
+
+ /*
+ * H/W composer documentation states:
+ * There is an implicit layer containing opaque black
+ * pixels behind all the layers in the list.
+ * It is the responsibility of the hwcomposer module to make
+ * sure black pixels are output (or blended from).
+ *
+ * Since we're using a blitter, we need to erase the frame-buffer when
+ * switching to all-overlay mode.
+ *
+ */
+ if (ctx->num_of_hwc_layer &&
+ ctx->num_of_fb_layer==0 && ctx->num_of_fb_layer_prev) {
+ /* we're clearing the screen using GLES here, this is very
+ * hack-ish, ideal we would use the fimc (if it can do it) */
+ glDisable(GL_SCISSOR_TEST);
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glEnable(GL_SCISSOR_TEST);
+ need_swap_buffers = true;
+ }
+
+ ctx->num_of_fb_layer_prev = ctx->num_of_fb_layer;
+
+ if (need_swap_buffers || !list) {
+ EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
+ if (!sucess) {
+ return HWC_EGL_ERROR;
+ }
+ }
+
+ if (!list) {
+ /* turn off the all windows */
+ for (int i = 0; i < NUM_OF_WIN; i++) {
+ window_hide(&ctx->win[i]);
+ reset_win_rect_info(&ctx->win[i]);
+ ctx->win[i].status = HWC_WIN_FREE;
+ }
+ ctx->num_of_hwc_layer = 0;
+ return 0;
+ }
+
+ if(ctx->num_of_hwc_layer > NUM_OF_WIN)
+ ctx->num_of_hwc_layer = NUM_OF_WIN;
+
+ /* compose hardware layers here */
+ for (uint32_t i = 0; i < ctx->num_of_hwc_layer; i++) {
+ win = &ctx->win[i];
+ if (win->status == HWC_WIN_RESERVED) {
+ cur = &list->hwLayers[win->layer_index];
+
+ if (cur->compositionType == HWC_OVERLAY) {
+
+ ret = gpsGrallocModule->GetPhyAddrs(gpsGrallocModule,
+ cur->handle, phyAddr);
+ if (ret) {
+ LOGE("%s::GetPhyAddrs fail : ret=%d\n", __func__, ret);
+ skipped_window_mask |= (1 << i);
+ continue;
+ }
+
+ /* initialize the src & dist context for fimc */
+ set_src_dst_info (cur, win, &src_img, &dst_img, &src_rect,
+ &dst_rect, i);
+
+ ret = runFimc(ctx, &src_img, &src_rect, &dst_img, &dst_rect,
+ phyAddr, cur->transform);
+ if (ret < 0){
+ LOGE("%s::runFimc fail : ret=%d\n", __func__, ret);
+ skipped_window_mask |= (1 << i);
+ continue;
+ }
+
+ if (win->set_win_flag == 1) {
+ /* turnoff the window and set the window position with new conf... */
+ if (window_set_pos(win) < 0) {
+ LOGE("%s::window_set_pos is failed : %s", __func__,
+ strerror(errno));
+ skipped_window_mask |= (1 << i);
+ continue;
+ }
+ win->set_win_flag = 0;
+ }
+
+ /* is the frame didn't change, it needs to be composited
+ * because something else below it could have changed, however
+ * it doesn't need to be swapped.
+ */
+ if (win->layer_prev_buf != (uint32_t)cur->handle) {
+ win->layer_prev_buf = (uint32_t)cur->handle;
+ window_pan_display(win);
+ win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF;
+ }
+
+ if(win->power_state == 0)
+ window_show(win);
+
+ } else {
+ LOGE("%s:: error : layer %d compositionType should have been \
+ HWC_OVERLAY", __func__, win->layer_index);
+ skipped_window_mask |= (1 << i);
+ continue;
+ }
+ } else {
+ LOGE("%s:: error : window status should have been HWC_WIN_RESERVED \
+ by now... ", __func__);
+ skipped_window_mask |= (1 << i);
+ continue;
+ }
+ }
+
+ if (skipped_window_mask) {
+ //turn off the free windows
+ for (int i = 0; i < NUM_OF_WIN; i++) {
+ if (skipped_window_mask & (1 << i))
+ window_hide(&ctx->win[i]);
+ }
+ }
+
+ return 0;
+}
+
+static int hwc_device_close(struct hw_device_t *dev)
+{
+ struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
+ int ret = 0;
+ int i;
+
+ if (ctx) {
+ if (destroyFimc(&ctx->fimc) < 0) {
+ LOGE("%s::destroyFimc fail", __func__);
+ ret = -1;
+ }
+
+ for (i = 0; i < NUM_OF_WIN; i++) {
+ if (window_close(&ctx->win[i]) < 0) {
+ LOGE("%s::window_close() fail", __func__);
+ ret = -1;
+ }
+ }
+
+ free(ctx);
+ }
+ return ret;
+}
+
+static int hwc_device_open(const struct hw_module_t* module, const char* name,
+ struct hw_device_t** device)
+{
+ int status = 0;
+ struct hwc_win_info_t *win;
+
+ if(hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+ (const hw_module_t**)&gpsGrallocModule))
+ return -EINVAL;
+
+ if(strcmp(gpsGrallocModule->base.common.author, "Imagination Technologies"))
+ return -EINVAL;
+
+ if (strcmp(name, HWC_HARDWARE_COMPOSER))
+ return -EINVAL;
+
+ struct hwc_context_t *dev;
+ dev = (hwc_context_t*)malloc(sizeof(*dev));
+
+ /* initialize our state here */
+ memset(dev, 0, sizeof(*dev));
+
+ /* initialize the procs */
+ dev->device.common.tag = HARDWARE_DEVICE_TAG;
+ dev->device.common.version = 0;
+ dev->device.common.module = const_cast(module);
+ dev->device.common.close = hwc_device_close;
+
+ dev->device.prepare = hwc_prepare;
+ dev->device.set = hwc_set;
+
+ *device = &dev->device.common;
+
+ /* initializing */
+ memset(&(dev->fimc), 0, sizeof(s5p_fimc_t));
+ dev->fimc.dev_fd = -1;
+
+ /* open WIN0 & WIN1 here */
+ for (int i = 0; i < NUM_OF_WIN; i++) {
+ if (window_open(&(dev->win[i]), i) < 0) {
+ LOGE("%s:: Failed to open window %d device ", __func__, i);
+ status = -EINVAL;
+ goto err;
+ }
+ }
+
+ /* get default window config */
+ if (window_get_global_lcd_info(&dev->lcd_info) < 0) {
+ LOGE("%s::window_get_global_lcd_info is failed : %s",
+ __func__, strerror(errno));
+ status = -EINVAL;
+ goto err;
+ }
+
+ dev->lcd_info.yres_virtual = dev->lcd_info.yres * NUM_OF_WIN_BUF;
+
+ /* initialize the window context */
+ for (int i = 0; i < NUM_OF_WIN; i++) {
+ win = &dev->win[i];
+ memcpy(&win->lcd_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
+ memcpy(&win->var_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
+
+ win->rect_info.x = 0;
+ win->rect_info.y = 0;
+ win->rect_info.w = win->var_info.xres;
+ win->rect_info.h = win->var_info.yres;
+
+ if (window_set_pos(win) < 0) {
+ LOGE("%s::window_set_pos is failed : %s",
+ __func__, strerror(errno));
+ status = -EINVAL;
+ goto err;
+ }
+
+ if (window_get_info(win) < 0) {
+ LOGE("%s::window_get_info is failed : %s",
+ __func__, strerror(errno));
+ status = -EINVAL;
+ goto err;
+ }
+
+ win->size = win->fix_info.line_length * win->var_info.yres;
+
+ if (!win->fix_info.smem_start){
+ LOGE("%s:: win-%d failed to get the reserved memory", __func__, i);
+ status = -EINVAL;
+ goto err;
+ }
+
+ for (int j = 0; j < NUM_OF_WIN_BUF; j++) {
+ win->addr[j] = win->fix_info.smem_start + (win->size * j);
+ LOGI("%s::win-%d add[%d] %x ", __func__, i, j, win->addr[j]);
+ }
+ }
+
+ /* open pp */
+ if (createFimc(&dev->fimc) < 0) {
+ LOGE("%s::creatFimc() fail", __func__);
+ status = -EINVAL;
+ goto err;
+ }
+
+ LOGD("%s:: success\n", __func__);
+
+ return 0;
+
+err:
+ if (destroyFimc(&dev->fimc) < 0)
+ LOGE("%s::destroyFimc() fail", __func__);
+
+ for (int i = 0; i < NUM_OF_WIN; i++) {
+ if (window_close(&dev->win[i]) < 0)
+ LOGE("%s::window_close() fail", __func__);
+ }
+
+ return status;
+}
diff --git a/libhwcomposer/SecHWCUtils.cpp b/libhwcomposer/SecHWCUtils.cpp
new file mode 100644
index 0000000..4a5b7b4
--- /dev/null
+++ b/libhwcomposer/SecHWCUtils.cpp
@@ -0,0 +1,890 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ *
+ * @author Rama, Meka(v.meka@samsung.com)
+ Sangwoo, Park(sw5771.park@samsung.com)
+ Jamie Oh (jung-min.oh@samsung.com)
+ * @date 2011-07-28
+ *
+ */
+
+#include "SecHWCUtils.h"
+
+int window_open(struct hwc_win_info_t *win, int id)
+{
+ char name[64];
+
+ char const * const device_template = "/dev/graphics/fb%u";
+ /* window & FB maping
+ fb0 -> win-id : 2
+ fb1 -> win-id : 3
+ fb2 -> win-id : 4
+ fb3 -> win-id : 0
+ fb4 -> win_id : 1
+ it is pre assumed that ...win0 or win1 is used here..
+ */
+ switch (id) {
+ case 0:
+ case 1:
+ case 2:
+ break;
+ default:
+ LOGE("%s::id(%d) is weird", __func__, id);
+ goto error;
+ }
+
+ snprintf(name, 64, device_template, (id + 3)%5);
+
+ win->fd = open(name, O_RDWR);
+ if (win->fd < 0) {
+ LOGE("%s::Failed to open window device (%s) : %s",
+ __func__, strerror(errno), device_template);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ if (0 <= win->fd)
+ close(win->fd);
+ win->fd = -1;
+
+ return -1;
+}
+
+int window_close(struct hwc_win_info_t *win)
+{
+ int ret = 0;
+
+ if (0 <= win->fd)
+ ret = close(win->fd);
+ win->fd = -1;
+
+ return ret;
+}
+
+int window_set_pos(struct hwc_win_info_t *win)
+{
+ struct secfb_user_window window;
+
+ /* before changing the screen configuration...powerdown the window */
+ if(window_hide(win) != 0)
+ return -1;
+
+ win->var_info.xres = win->rect_info.w;
+ win->var_info.yres = win->rect_info.h;
+
+ win->var_info.activate &= ~FB_ACTIVATE_MASK;
+ win->var_info.activate |= FB_ACTIVATE_FORCE;
+
+ if (ioctl(win->fd, FBIOPUT_VSCREENINFO, &(win->var_info)) < 0) {
+ LOGE("%s::FBIOPUT_VSCREENINFO(%d, %d) fail",
+ __func__, win->rect_info.w, win->rect_info.h);
+ return -1;
+ }
+
+ window.x = win->rect_info.x;
+ window.y = win->rect_info.y;
+
+ if (ioctl(win->fd, SECFB_WIN_POSITION, &window) < 0) {
+ LOGE("%s::S3CFB_WIN_POSITION(%d, %d) fail",
+ __func__, window.x, window.y);
+ return -1;
+ }
+
+ return 0;
+}
+
+int window_get_info(struct hwc_win_info_t *win)
+{
+ if (ioctl(win->fd, FBIOGET_FSCREENINFO, &win->fix_info) < 0) {
+ LOGE("FBIOGET_FSCREENINFO failed : %s", strerror(errno));
+ goto error;
+ }
+
+ return 0;
+
+error:
+ win->fix_info.smem_start = 0;
+
+ return -1;
+}
+
+int window_pan_display(struct hwc_win_info_t *win)
+{
+ struct fb_var_screeninfo *lcd_info = &(win->lcd_info);
+
+ lcd_info->yoffset = lcd_info->yres * win->buf_index;
+
+ if (ioctl(win->fd, FBIOPAN_DISPLAY, lcd_info) < 0) {
+ LOGE("%s::FBIOPAN_DISPLAY(%d / %d / %d) fail(%s)",
+ __func__, lcd_info->yres, win->buf_index, lcd_info->yres_virtual,
+ strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+int window_show(struct hwc_win_info_t *win)
+{
+ if(win->power_state == 0) {
+ if (ioctl(win->fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
+ LOGE("%s: FBIOBLANK failed : (%d:%s)", __func__, win->fd,
+ strerror(errno));
+ return -1;
+ }
+ win->power_state = 1;
+ }
+ return 0;
+}
+
+int window_hide(struct hwc_win_info_t *win)
+{
+ if (win->power_state == 1) {
+ if (ioctl(win->fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
+ LOGE("%s::FBIOBLANK failed : (%d:%s)",
+ __func__, win->fd, strerror(errno));
+ return -1;
+ }
+ win->power_state = 0;
+ }
+ return 0;
+}
+
+int window_get_global_lcd_info(struct fb_var_screeninfo *lcd_info)
+{
+ struct hwc_win_info_t win;
+ int ret = 0;
+
+ if (window_open(&win, 2) < 0) {
+ LOGE("%s:: Failed to open window 2 device ", __func__);
+ return -1;
+ }
+
+ if (ioctl(win.fd, FBIOGET_VSCREENINFO, lcd_info) < 0) {
+ LOGE("FBIOGET_VSCREENINFO failed : %s", strerror(errno));
+ ret = -1;
+ goto fun_err;
+ }
+
+ if (lcd_info->xres == 0) {
+ lcd_info->xres = DEFAULT_LCD_WIDTH;
+ lcd_info->xres_virtual = DEFAULT_LCD_WIDTH;
+ }
+
+ if (lcd_info->yres == 0) {
+ lcd_info->yres = DEFAULT_LCD_HEIGHT;
+ lcd_info->yres_virtual = DEFAULT_LCD_HEIGHT * NUM_OF_WIN_BUF;
+ }
+
+ if (lcd_info->bits_per_pixel == 0)
+ lcd_info->bits_per_pixel = DEFAULT_LCD_BPP;
+
+fun_err:
+ if (window_close(&win) < 0)
+ LOGE("%s::window2 close fail", __func__);
+
+ return ret;
+}
+
+int fimc_v4l2_set_src(int fd, unsigned int hw_ver, s5p_fimc_img_info *src)
+{
+ struct v4l2_format fmt;
+ struct v4l2_cropcap cropcap;
+ struct v4l2_crop crop;
+ struct v4l2_requestbuffers req;
+
+ /*
+ * To set size & format for source image (DMA-INPUT)
+ */
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ fmt.fmt.pix.width = src->full_width;
+ fmt.fmt.pix.height = src->full_height;
+ fmt.fmt.pix.pixelformat = src->color_space;
+ fmt.fmt.pix.field = V4L2_FIELD_NONE;
+
+ if (ioctl (fd, VIDIOC_S_FMT, &fmt) < 0) {
+ LOGE("VIDIOC_S_FMT failed : errno=%d (%s) : fd=%d", errno,
+ strerror(errno), fd);
+ return -1;
+ }
+
+ /*
+ * crop input size
+ */
+ crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (0x50 == hw_ver) {
+ crop.c.left = src->start_x;
+ crop.c.top = src->start_y;
+ } else {
+ crop.c.left = 0;
+ crop.c.top = 0;
+ }
+ crop.c.width = src->width;
+ crop.c.height = src->height;
+ if (ioctl(fd, VIDIOC_S_CROP, &crop) < 0) {
+ LOGE("Error in video VIDIOC_S_CROP (%d, %d, %d, %d)",
+ crop.c.left, crop.c.top, crop.c.width, crop.c.height);
+ return -1;
+ }
+
+ /*
+ * input buffer type
+ */
+ req.count = 1;
+ req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ req.memory = V4L2_MEMORY_USERPTR;
+
+ if (ioctl (fd, VIDIOC_REQBUFS, &req) < 0) {
+ LOGE("Error in VIDIOC_REQBUFS");
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_set_dst(int fd,
+ s5p_fimc_img_info *dst,
+ int rotation,
+ int flag_h_flip,
+ int flag_v_flip,
+ unsigned int addr)
+{
+ struct v4l2_format sFormat;
+ struct v4l2_control vc;
+ struct v4l2_framebuffer fbuf;
+
+ /*
+ * set rotation configuration
+ */
+ vc.id = V4L2_CID_HFLIP;
+ vc.value = flag_h_flip;
+ if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
+ LOGE("Error in video VIDIOC_S_CTRL - flag_h_flip (%d)", flag_h_flip);
+ return -1;
+ }
+
+ vc.id = V4L2_CID_VFLIP;
+ vc.value = flag_v_flip;
+ if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
+ LOGE("Error in video VIDIOC_S_CTRL - flag_v_flip (%d)", flag_v_flip);
+ return -1;
+ }
+
+ vc.id = V4L2_CID_ROTATION;
+ vc.value = rotation;
+ if (ioctl(fd, VIDIOC_S_CTRL, &vc) < 0) {
+ LOGE("Error in video VIDIOC_S_CTRL - rotation (%d)", rotation);
+ return -1;
+ }
+
+ /*
+ * set size, format & address for destination image (DMA-OUTPUT)
+ */
+ if (ioctl (fd, VIDIOC_G_FBUF, &fbuf) < 0) {
+ LOGE("Error in video VIDIOC_G_FBUF");
+ return -1;
+ }
+
+ fbuf.base = (void *)addr;
+ fbuf.fmt.width = dst->full_width;
+ fbuf.fmt.height = dst->full_height;
+ fbuf.fmt.pixelformat = dst->color_space;
+ if (ioctl (fd, VIDIOC_S_FBUF, &fbuf) < 0) {
+ LOGE("Error in video VIDIOC_S_FBUF 0x%x %d %d %d",
+ (void *)addr, dst->full_width, dst->full_height,
+ dst->color_space);
+ return -1;
+ }
+
+ /*
+ * set destination window
+ */
+ sFormat.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ sFormat.fmt.win.w.left = dst->start_x;
+ sFormat.fmt.win.w.top = dst->start_y;
+ sFormat.fmt.win.w.width = dst->width;
+ sFormat.fmt.win.w.height = dst->height;
+ if (ioctl(fd, VIDIOC_S_FMT, &sFormat) < 0) {
+ LOGE("Error in video VIDIOC_S_FMT %d %d %d %d",
+ dst->start_x, dst->start_y, dst->width, dst->height);
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_stream_on(int fd, enum v4l2_buf_type type)
+{
+ if (ioctl (fd, VIDIOC_STREAMON, &type) < 0) {
+ LOGE("Error in VIDIOC_STREAMON");
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_queue(int fd, struct fimc_buf *fimc_buf)
+{
+ struct v4l2_buffer buf;
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ buf.memory = V4L2_MEMORY_USERPTR;
+ buf.m.userptr = (unsigned long)fimc_buf;
+ buf.length = 0;
+ buf.index = 0;
+
+ if (ioctl (fd, VIDIOC_QBUF, &buf) < 0) {
+ LOGE("Error in VIDIOC_QBUF");
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_dequeue(int fd)
+{
+ struct v4l2_buffer buf;
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ buf.memory = V4L2_MEMORY_USERPTR;
+
+ if (ioctl (fd, VIDIOC_DQBUF, &buf) < 0) {
+ LOGE("Error in VIDIOC_DQBUF");
+ return -1;
+ }
+
+ return buf.index;
+}
+
+int fimc_v4l2_stream_off(int fd)
+{
+ enum v4l2_buf_type type;
+ type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+ if (ioctl (fd, VIDIOC_STREAMOFF, &type) < 0) {
+ LOGE("Error in VIDIOC_STREAMOFF");
+ return -1;
+ }
+
+ return 0;
+}
+
+int fimc_v4l2_clr_buf(int fd)
+{
+ struct v4l2_requestbuffers req;
+
+ req.count = 0;
+ req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ req.memory = V4L2_MEMORY_USERPTR;
+
+ if (ioctl (fd, VIDIOC_REQBUFS, &req) < 0) {
+ LOGE("Error in VIDIOC_REQBUFS");
+ }
+
+ return 0;
+}
+
+int fimc_handle_oneshot(int fd, struct fimc_buf *fimc_buf)
+{
+ int ret =0;
+
+ if (fimc_v4l2_stream_on(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT) < 0) {
+ LOGE("Fail : v4l2_stream_on()");
+ return -1;
+ }
+
+ if (fimc_v4l2_queue(fd, fimc_buf) < 0) {
+ LOGE("Fail : v4l2_queue()");
+ ret = -1;
+ goto stream_off;
+ }
+
+ if (fimc_v4l2_dequeue(fd) < 0) {
+ LOGE("Fail : v4l2_dequeue()");
+ ret = -1;
+ goto stream_off;
+ }
+
+stream_off:
+ if (fimc_v4l2_stream_off(fd) < 0) {
+ LOGE("Fail : v4l2_stream_off()");
+ return -1;
+ }
+
+ if (fimc_v4l2_clr_buf(fd) < 0) {
+ LOGE("Fail : v4l2_clr_buf()");
+ return -1;
+ }
+
+ return ret;
+}
+
+static int get_src_phys_addr(struct hwc_context_t *ctx,
+ sec_img *src_img,
+ unsigned int *phyAddr)
+{
+ s5p_fimc_t *fimc = &ctx->fimc;
+
+ if(src_img->mem_type == HWC_PHYS_MEM_TYPE) {
+ switch(src_img->format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ fimc->params.src.buf_addr_phy_rgb_y = phyAddr[0];
+ fimc->params.src.buf_addr_phy_cb = phyAddr[1];
+ break;
+ default:
+ LOGE("%s format error (format=0x%x)", __func__,
+ src_img->format);
+ return -1;
+ }
+ } else {
+ LOGE("%s mem_type error (mem_type=%d)", __func__, src_img->mem_type);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int get_dst_phys_addr(struct hwc_context_t *ctx,
+ sec_img *dst_img)
+{
+ unsigned int dst_phys_addr = 0;
+
+ if (HWC_PHYS_MEM_TYPE == dst_img->mem_type && 0 != dst_img->base)
+ dst_phys_addr = dst_img->base;
+ else {
+ LOGE("%s::get_dst_phys_addr fail ", __func__);
+ dst_phys_addr = 0;
+ }
+ return dst_phys_addr;
+}
+
+static inline int rotateValueHAL2PP(unsigned char transform,
+ int *flag_h_flip,
+ int *flag_v_flip)
+{
+ int rotate_result = 0;
+ int rotate_flag = transform & 0x7;
+
+ switch (rotate_flag) {
+ case HAL_TRANSFORM_ROT_90:
+ rotate_result = 90;
+ break;
+ case HAL_TRANSFORM_ROT_180:
+ rotate_result = 180;
+ break;
+ case HAL_TRANSFORM_ROT_270:
+ rotate_result = 270;
+ break;
+ }
+
+ switch (rotate_flag) {
+ case HAL_TRANSFORM_FLIP_H:
+ *flag_h_flip = 1;
+ *flag_v_flip = 0;
+ break;
+ case HAL_TRANSFORM_FLIP_V:
+ *flag_h_flip = 0;
+ *flag_v_flip = 1;
+ break;
+ default:
+ *flag_h_flip = 0;
+ *flag_v_flip = 0;
+ break;
+ }
+
+ return rotate_result;
+}
+
+static inline int multipleOfN(int number, int N)
+{
+ int result = number;
+ switch (N) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ case 256:
+ result = (number - (number & (N-1)));
+ break;
+ default:
+ result = number - (number % N);
+ break;
+ }
+ return result;
+}
+
+static inline int widthOfPP(unsigned int ver,
+ int pp_color_format,
+ int number)
+{
+ if (0x50 == ver) {
+ switch(pp_color_format) {
+ /* 422 1/2/3 plane */
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_YUV422P:
+
+ /* 420 2/3 plane */
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ return multipleOfN(number, 2);
+
+ default :
+ return number;
+ }
+ } else {
+ switch(pp_color_format) {
+ case V4L2_PIX_FMT_RGB565:
+ return multipleOfN(number, 8);
+
+ case V4L2_PIX_FMT_RGB32:
+ return multipleOfN(number, 4);
+
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ return multipleOfN(number, 4);
+
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV16:
+ return multipleOfN(number, 8);
+
+ case V4L2_PIX_FMT_YUV422P:
+ return multipleOfN(number, 16);
+
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ return multipleOfN(number, 8);
+
+ case V4L2_PIX_FMT_YUV420:
+ return multipleOfN(number, 16);
+
+ default :
+ return number;
+ }
+ }
+ return number;
+}
+
+static inline int heightOfPP(int pp_color_format,
+ int number)
+{
+ switch(pp_color_format) {
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ return multipleOfN(number, 2);
+
+ default :
+ return number;
+ }
+ return number;
+}
+
+static int runcFimcCore(struct hwc_context_t *ctx,
+ sec_img *src_img,
+ sec_rect *src_rect,
+ uint32_t src_color_space,
+ unsigned int dst_phys_addr,
+ sec_img *dst_img,
+ sec_rect *dst_rect,
+ uint32_t dst_color_space,
+ int transform)
+{
+ s5p_fimc_t * fimc = &ctx->fimc;
+ s5p_fimc_params_t * params = &(fimc->params);
+
+ unsigned int frame_size = 0;
+ struct fimc_buf fimc_src_buf;
+
+ int src_bpp, src_planes;
+ int flag_h_flip = 0;
+ int flag_v_flip = 0;
+ int rotate_value = rotateValueHAL2PP(transform, &flag_h_flip, &flag_v_flip);
+
+ /* set post processor configuration */
+ params->src.full_width = src_img->w;
+ params->src.full_height = src_img->h;
+ params->src.start_x = src_rect->x;
+ params->src.start_y = src_rect->y;
+ params->src.width = widthOfPP(fimc->hw_ver, src_color_space, src_rect->w);
+ params->src.height = heightOfPP(src_color_space, src_rect->h);
+ params->src.color_space = src_color_space;
+
+
+ /* check minimum */
+ if (src_rect->w < 16 || src_rect->h < 8) {
+ LOGE("%s src size is not supported by fimc : f_w=%d f_h=%d x=%d y=%d \
+ w=%d h=%d (ow=%d oh=%d) format=0x%x", __func__,
+ params->src.full_width, params->src.full_height,
+ params->src.start_x, params->src.start_y, params->src.width,
+ params->src.height, src_rect->w, src_rect->h,
+ params->src.color_space);
+ return -1;
+ }
+
+switch (rotate_value) {
+ case 0:
+ params->dst.full_width = dst_img->w;
+ params->dst.full_height = dst_img->h;
+
+ params->dst.start_x = dst_rect->x;
+ params->dst.start_y = dst_rect->y;
+
+ params->dst.width =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
+ params->dst.height = heightOfPP(dst_color_space, dst_rect->h);
+ break;
+ case 90:
+ params->dst.full_width = dst_img->h;
+ params->dst.full_height = dst_img->w;
+
+ params->dst.start_x = dst_rect->y;
+ params->dst.start_y = dst_img->w - (dst_rect->x + dst_rect->w);
+
+ params->dst.width =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->h);
+ params->dst.height =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
+
+ if (0x50 > fimc->hw_ver)
+ params->dst.start_y += (dst_rect->w - params->dst.height);
+ break;
+ case 180:
+ params->dst.full_width = dst_img->w;
+ params->dst.full_height = dst_img->h;
+
+ params->dst.start_x = dst_img->w - (dst_rect->x + dst_rect->w);
+ params->dst.start_y = dst_img->h - (dst_rect->y + dst_rect->h);
+
+ params->dst.width =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
+ params->dst.height = heightOfPP(dst_color_space, dst_rect->h);
+ break;
+ case 270:
+ params->dst.full_width = dst_img->h;
+ params->dst.full_height = dst_img->w;
+
+ params->dst.start_x = dst_img->h - (dst_rect->y + dst_rect->h);
+ params->dst.start_y = dst_rect->x;
+
+ params->dst.width =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->h);
+ params->dst.height =
+ widthOfPP(fimc->hw_ver, dst_color_space, dst_rect->w);
+
+ if (0x50 > fimc->hw_ver)
+ params->dst.start_y += (dst_rect->w - params->dst.height);
+ break;
+ }
+
+
+ params->dst.color_space = dst_color_space;
+
+ /* check minimum */
+ if (dst_rect->w < 8 || dst_rect->h < 4) {
+ LOGE("%s dst size is not supported by fimc : \
+ f_w=%d f_h=%d x=%d y=%d w=%d h=%d (ow=%d oh=%d) format=0x%x",
+ __func__, params->dst.full_width, params->dst.full_height,
+ params->dst.start_x, params->dst.start_y, params->dst.width,
+ params->dst.height, dst_rect->w, dst_rect->h,
+ params->dst.color_space);
+ return -1;
+ }
+
+ /* check scaling limit
+ * the scaling limie must not be more than MAX_RESIZING_RATIO_LIMIT
+ */
+ if (((src_rect->w > dst_rect->w) &&
+ ((src_rect->w / dst_rect->w) > MAX_RESIZING_RATIO_LIMIT)) ||
+ ((dst_rect->w > src_rect->w) &&
+ ((dst_rect->w / src_rect->w) > MAX_RESIZING_RATIO_LIMIT))) {
+ LOGE("%s over scaling limit : src.w=%d dst.w=%d (limit=%d)",
+ __func__, src_rect->w, dst_rect->w, MAX_RESIZING_RATIO_LIMIT);
+ return -1;
+ }
+
+
+ /* set configuration related to destination (DMA-OUT)
+ * - set input format & size
+ * - crop input size
+ * - set input buffer
+ * - set buffer type (V4L2_MEMORY_USERPTR)
+ */
+ if (fimc_v4l2_set_dst(fimc->dev_fd,
+ ¶ms->dst,
+ rotate_value,
+ flag_h_flip,
+ flag_v_flip,
+ dst_phys_addr) < 0) {
+ return -1;
+ }
+
+ /* set configuration related to source (DMA-INPUT)
+ * - set input format & size
+ * - crop input size
+ * - set input buffer
+ * - set buffer type (V4L2_MEMORY_USERPTR)
+ */
+ if (fimc_v4l2_set_src(fimc->dev_fd, fimc->hw_ver, ¶ms->src) < 0)
+ return -1;
+
+ /* set input dma address (Y/RGB, Cb, Cr) */
+ switch (src_img->format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ /* for video display zero copy case */
+ fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y;
+ fimc_src_buf.base[1] = params->src.buf_addr_phy_cb;
+ break;
+
+ default:
+ /* set source image */
+ fimc_src_buf.base[0] = params->src.buf_addr_phy_rgb_y;
+ break;
+ }
+
+ if (fimc_handle_oneshot(fimc->dev_fd, &fimc_src_buf) < 0) {
+ fimc_v4l2_clr_buf(fimc->dev_fd);
+ return -1;
+ }
+
+ return 0;
+}
+
+int createFimc(s5p_fimc_t *fimc)
+{
+ struct v4l2_capability cap;
+ struct v4l2_format fmt;
+ struct v4l2_control vc;
+
+ #define PP_DEVICE_DEV_NAME "/dev/video1"
+
+ /* open device file */
+ if(fimc->dev_fd < 0) {
+ fimc->dev_fd = open(PP_DEVICE_DEV_NAME, O_RDWR);
+
+ if (fimc->dev_fd < 0) {
+ LOGE("%s::Post processor open error (%d)", __func__, errno);
+ goto err;
+ }
+ }
+
+ /* check capability */
+ if (ioctl(fimc->dev_fd, VIDIOC_QUERYCAP, &cap) < 0) {
+ LOGE("VIDIOC_QUERYCAP failed");
+ goto err;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
+ LOGE("%d has no streaming support", fimc->dev_fd);
+ goto err;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
+ LOGE("%d is no video output", fimc->dev_fd);
+ goto err;
+ }
+
+ /*
+ * malloc fimc_outinfo structure
+ */
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (ioctl(fimc->dev_fd, VIDIOC_G_FMT, &fmt) < 0) {
+ LOGE("%s::Error in video VIDIOC_G_FMT", __func__);
+ goto err;
+ }
+
+ vc.id = V4L2_CID_FIMC_VERSION;
+ vc.value = 0;
+
+ if (ioctl(fimc->dev_fd, VIDIOC_G_CTRL, &vc) < 0) {
+ LOGE("%s::Error in video VIDIOC_G_CTRL", __func__);
+ goto err;
+ }
+ fimc->hw_ver = vc.value;
+
+ return 0;
+
+err:
+ if (0 <= fimc->dev_fd)
+ close(fimc->dev_fd);
+ fimc->dev_fd = -1;
+
+ return -1;
+}
+
+int destroyFimc(s5p_fimc_t *fimc)
+{
+ if (fimc->out_buf.virt_addr != NULL) {
+ fimc->out_buf.virt_addr = NULL;
+ fimc->out_buf.length = 0;
+ }
+
+ /* close */
+ if (0 <= fimc->dev_fd)
+ close(fimc->dev_fd);
+ fimc->dev_fd = -1;
+
+ return 0;
+}
+
+int runFimc(struct hwc_context_t *ctx,
+ struct sec_img *src_img,
+ struct sec_rect *src_rect,
+ struct sec_img *dst_img,
+ struct sec_rect *dst_rect,
+ unsigned int *phyAddr,
+ uint32_t transform)
+{
+ s5p_fimc_t *fimc = &ctx->fimc;
+ unsigned int dst_phys_addr = 0;
+ int32_t src_color_space;
+ int32_t dst_color_space;
+
+ /* 1 : source address and size */
+
+ if(0 > get_src_phys_addr(ctx, src_img, phyAddr))
+ return -1;
+
+ /* 2 : destination address and size */
+ if(0 == (dst_phys_addr = get_dst_phys_addr(ctx, dst_img)))
+ return -2;
+
+ /* check whether fimc supports the src format */
+ if (0 > (src_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(src_img->format)))
+ return -3;
+
+ if (0 > (dst_color_space = HAL_PIXEL_FORMAT_2_V4L2_PIX(dst_img->format)))
+ return -4;
+
+ if(runcFimcCore(ctx, src_img, src_rect, (uint32_t)src_color_space,
+ dst_phys_addr, dst_img, dst_rect, (uint32_t)dst_color_space, transform) < 0)
+ return -5;
+
+ return 0;
+}
diff --git a/libhwcomposer/SecHWCUtils.h b/libhwcomposer/SecHWCUtils.h
new file mode 100644
index 0000000..21d6598
--- /dev/null
+++ b/libhwcomposer/SecHWCUtils.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ *
+ * @author Rama, Meka(v.meka@samsung.com)
+ Sangwoo, Park(sw5771.park@samsung.com)
+ Jamie, Oh (jung-min.oh@samsung.com)
+ * @date 2011-07-28
+ *
+ */
+
+#ifndef ANDROID_SEC_HWC_UTILS_H_
+#define ANDROID_SEC_HWC_UTILS_H_
+#include
+#include
+#include
+#include
+#include
+#include
+#include "linux/fb.h"
+#include
+
+#include
+#include
+#include
+
+#include "s5p_fimc.h"
+#include "sec_lcd.h"
+#include "sec_format.h"
+#include "sec_utils.h"
+#include "hal_public.h"
+
+#define GRALLOC_USAGE_PHYS_CONTIG GRALLOC_USAGE_PRIVATE_1
+
+#define NUM_OF_WIN (1)
+#define NUM_OF_WIN_BUF (3)
+#define NUM_OF_MEM_OBJ (1)
+#define MAX_NUM_PLANES (3)
+
+#define MAX_RESIZING_RATIO_LIMIT (63)
+
+struct sec_rect {
+ uint32_t x;
+ uint32_t y;
+ uint32_t w;
+ uint32_t h;
+};
+
+struct sec_img {
+ uint32_t w;
+ uint32_t h;
+ uint32_t format;
+ uint32_t base;
+ uint32_t offset;
+ int mem_id;
+ int mem_type;
+};
+
+inline int SEC_MIN(int x, int y) {
+ return ((x < y) ? x : y);
+}
+
+inline int SEC_MAX(int x, int y) {
+ return ((x > y) ? x : y);
+}
+
+struct hwc_win_info_t {
+ int fd;
+ int size;
+ sec_rect rect_info;
+ uint32_t addr[NUM_OF_WIN_BUF];
+ int buf_index;
+ int power_state;
+ int blending;
+ int layer_index;
+ uint32_t layer_prev_buf;
+ int set_win_flag;
+ int status;
+ int vsync;
+
+ struct fb_fix_screeninfo fix_info;
+ struct fb_var_screeninfo var_info;
+ struct fb_var_screeninfo lcd_info;
+};
+
+enum {
+ HWC_WIN_FREE = 0,
+ HWC_WIN_RESERVED,
+};
+
+enum {
+ HWC_UNKNOWN_MEM_TYPE = 0,
+ HWC_PHYS_MEM_TYPE,
+ HWC_VIRT_MEM_TYPE,
+};
+
+struct hwc_context_t {
+ hwc_composer_device_t device;
+
+ /* our private state goes below here */
+ struct hwc_win_info_t win[NUM_OF_WIN];
+ struct fb_var_screeninfo lcd_info;
+ s5p_fimc_t fimc;
+ unsigned int num_of_fb_layer;
+ unsigned int num_of_hwc_layer;
+ unsigned int num_of_fb_layer_prev;
+};
+
+int window_open(struct hwc_win_info_t *win, int id);
+int window_close(struct hwc_win_info_t *win);
+int window_set_pos(struct hwc_win_info_t *win);
+int window_get_info(struct hwc_win_info_t *win);
+int window_pan_display(struct hwc_win_info_t *win);
+int window_show(struct hwc_win_info_t *win);
+int window_hide(struct hwc_win_info_t *win);
+int window_get_global_lcd_info(struct fb_var_screeninfo *lcd_info);
+
+int createFimc(s5p_fimc_t *fimc);
+int destroyFimc(s5p_fimc_t *fimc);
+int runFimc(struct hwc_context_t *ctx,
+ struct sec_img *src_img, struct sec_rect *src_rect,
+ struct sec_img *dst_img, struct sec_rect *dst_rect,
+ unsigned int *phyAddr,
+ uint32_t transform);
+#endif /* ANDROID_SEC_HWC_UTILS_H_*/
+
diff --git a/liblights/Android.mk b/liblights/Android.mk
new file mode 100644
index 0000000..bf55cbe
--- /dev/null
+++ b/liblights/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+# HAL module implemenation, not prelinked and stored in
+# hw/..so
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := lights.c
+
+LOCAL_MODULE_TAGS:= optional
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+
+LOCAL_SHARED_LIBRARIES := liblog
+
+LOCAL_MODULE := lights.s5pc110
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/liblights/NOTICE b/liblights/NOTICE
new file mode 100644
index 0000000..68c1616
--- /dev/null
+++ b/liblights/NOTICE
@@ -0,0 +1,192 @@
+(Modified by Michael Richter in 2010.)
+
+ Copyright (c) 2008, The Android Open Source Project
+ Copyright (C) 2010 Michael Richter (alias neldar)
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/liblights/lights.c b/liblights/lights.c
new file mode 100644
index 0000000..965c97f
--- /dev/null
+++ b/liblights/lights.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2011 Dominik Behr
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "lights"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+#include
+#include
+
+#include
+
+static pthread_once_t g_init = PTHREAD_ONCE_INIT;
+static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
+
+char const*const BUTTON_FILE = "/sys/class/leds/button-backlight/brightness";
+
+char const*const LCD_BACKLIGHT_FILE = "/sys/class/backlight/s5p_bl/brightness";
+
+char const*const NOTIFICATION_FILE = "/sys/class/misc/backlightnotification/notification_led";
+
+/**
+ * Aux method, write int to file
+ */
+static int write_int (const char* path, int value) {
+ int fd;
+ static int already_warned = 0;
+
+ fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ if (already_warned == 0) {
+ LOGE("write_int failed to open %s\n", path);
+ already_warned = 1;
+ }
+ return -errno;
+ }
+
+ char buffer[20];
+ int bytes = snprintf(buffer, sizeof(buffer), "%d\n",value);
+ int written = write (fd, buffer, bytes);
+ close (fd);
+
+ return written == -1 ? -errno : 0;
+
+}
+
+void init_globals (void) {
+ pthread_mutex_init (&g_lock, NULL);
+}
+
+static int is_lit (struct light_state_t const* state) {
+ return state->color & 0x00ffffff;
+}
+
+static int set_light_buttons (struct light_device_t* dev,
+ struct light_state_t const* state) {
+ int err = 0;
+ int on = is_lit (state);
+ pthread_mutex_lock (&g_lock);
+ err = write_int (BUTTON_FILE, on?255:0);
+ pthread_mutex_unlock (&g_lock);
+
+ return 0;
+}
+
+static int rgb_to_brightness(struct light_state_t const* state)
+{
+ int color = state->color & 0x00ffffff;
+ return ((77*((color>>16)&0x00ff))
+ + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
+}
+
+static int set_light_backlight(struct light_device_t* dev,
+ struct light_state_t const* state) {
+ int err = 0;
+ int brightness = rgb_to_brightness(state);
+ LOGV("%s brightness=%d color=0x%08x",
+ __func__,brightness, state->color);
+ pthread_mutex_lock(&g_lock);
+ err = write_int(LCD_BACKLIGHT_FILE, brightness);
+ // if LCD backlight is on then button backlight should be on too
+ // Samsung has some annoying code that turns on buttons light only when touchscreen is pressed
+ // and it turns off automatically afterwards, leaving user hunting for buttons in the dark
+ {
+ int on = is_lit (state);
+ err = write_int (BUTTON_FILE, on?255:0);
+ }
+ pthread_mutex_unlock(&g_lock);
+ return err;
+}
+
+static int
+set_light_notifications(struct light_device_t* dev,
+ struct light_state_t const* state)
+{
+ int err = 0;
+ int on = is_lit(state);
+ LOGV("%s color=%08x flashMode=%d flashOnMS=%d flashOffMS=%d\n", __func__,
+ state->color, state->flashMode, state->flashOnMS, state->flashOffMS);
+ pthread_mutex_lock(&g_lock);
+ err = write_int(NOTIFICATION_FILE, on?1:0);
+ pthread_mutex_unlock(&g_lock);
+ return err;
+}
+
+static int close_lights (struct light_device_t *dev) {
+ if (dev)
+ free (dev);
+
+ return 0;
+}
+
+static int open_lights (const struct hw_module_t* module, char const* name,
+ struct hw_device_t** device) {
+ int (*set_light)(struct light_device_t* dev,
+ struct light_state_t const* state);
+
+ if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {
+ set_light = set_light_backlight;
+ }
+ else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
+ set_light = set_light_buttons;
+ }
+ else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
+ set_light = set_light_notifications;
+ }
+ else {
+ return -EINVAL;
+ }
+
+ pthread_once (&g_init, init_globals);
+ struct light_device_t *dev = malloc (sizeof (struct light_device_t));
+ memset (dev,0,sizeof(*dev));
+
+ dev->common.tag = HARDWARE_DEVICE_TAG;
+ dev->common.version = 0;
+ dev->common.module = (struct hw_module_t*)module;
+ dev->common.close = (int (*)(struct hw_device_t*))close_lights;
+ dev->set_light = set_light;
+
+ *device = (struct hw_device_t*) dev;
+ return 0;
+
+}
+
+static struct hw_module_methods_t lights_module_methods = {
+ .open = open_lights,
+};
+
+
+const struct hw_module_t HAL_MODULE_INFO_SYM = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 1,
+ .version_minor = 0,
+ .id = LIGHTS_HARDWARE_MODULE_ID,
+ .name = "GT-P1000 lights module",
+ .author = "Dominik Behr",
+ .methods = &lights_module_methods,
+};
diff --git a/libs3cjpeg/Android.mk b/libs3cjpeg/Android.mk
new file mode 100644
index 0000000..7b1618f
--- /dev/null
+++ b/libs3cjpeg/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
+
+LOCAL_SRC_FILES:= \
+ JpegEncoder.cpp
+
+LOCAL_SHARED_LIBRARIES:= liblog
+LOCAL_SHARED_LIBRARIES+= libdl
+
+LOCAL_MODULE:= libs3cjpeg
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/libs3cjpeg/Exif.h b/libs3cjpeg/Exif.h
new file mode 100644
index 0000000..96e11dd
--- /dev/null
+++ b/libs3cjpeg/Exif.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright Samsung Electronics Co.,LTD.
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_EXIF_H
+#define ANDROID_HARDWARE_EXIF_H
+
+#include
+
+#define EXIF_LOG2(x) (log((double)(x)) / log(2.0))
+#define APEX_FNUM_TO_APERTURE(x) ((int)(EXIF_LOG2((double)(x)) * 2 + 0.5))
+#define APEX_EXPOSURE_TO_SHUTTER(x) ((x) >= 1 ? \
+ (int)(-(EXIF_LOG2((double)(x)) + 0.5)) : \
+ (int)(-(EXIF_LOG2((double)(x)) - 0.5)))
+#define APEX_ISO_TO_FILMSENSITIVITY(x) ((int)(EXIF_LOG2((x) / 3.125) + 0.5))
+
+#define NUM_SIZE 2
+#define IFD_SIZE 12
+#define OFFSET_SIZE 4
+
+#define NUM_0TH_IFD_TIFF 10
+#define NUM_0TH_IFD_EXIF 22
+#define NUM_0TH_IFD_GPS 10
+#define NUM_1TH_IFD_TIFF 9
+
+/* Type */
+#define EXIF_TYPE_BYTE 1
+#define EXIF_TYPE_ASCII 2
+#define EXIF_TYPE_SHORT 3
+#define EXIF_TYPE_LONG 4
+#define EXIF_TYPE_RATIONAL 5
+#define EXIF_TYPE_UNDEFINED 7
+#define EXIF_TYPE_SLONG 9
+#define EXIF_TYPE_SRATIONAL 10
+
+#define EXIF_FILE_SIZE 28800
+
+/* 0th IFD TIFF Tags */
+#define EXIF_TAG_IMAGE_WIDTH 0x0100
+#define EXIF_TAG_IMAGE_HEIGHT 0x0101
+#define EXIF_TAG_MAKE 0x010f
+#define EXIF_TAG_MODEL 0x0110
+#define EXIF_TAG_ORIENTATION 0x0112
+#define EXIF_TAG_SOFTWARE 0x0131
+#define EXIF_TAG_DATE_TIME 0x0132
+#define EXIF_TAG_YCBCR_POSITIONING 0x0213
+#define EXIF_TAG_EXIF_IFD_POINTER 0x8769
+#define EXIF_TAG_GPS_IFD_POINTER 0x8825
+
+/* 0th IFD Exif Private Tags */
+#define EXIF_TAG_EXPOSURE_TIME 0x829A
+#define EXIF_TAG_FNUMBER 0x829D
+#define EXIF_TAG_EXPOSURE_PROGRAM 0x8822
+#define EXIF_TAG_ISO_SPEED_RATING 0x8827
+#define EXIF_TAG_EXIF_VERSION 0x9000
+#define EXIF_TAG_DATE_TIME_ORG 0x9003
+#define EXIF_TAG_DATE_TIME_DIGITIZE 0x9004
+#define EXIF_TAG_SHUTTER_SPEED 0x9201
+#define EXIF_TAG_APERTURE 0x9202
+#define EXIF_TAG_BRIGHTNESS 0x9203
+#define EXIF_TAG_EXPOSURE_BIAS 0x9204
+#define EXIF_TAG_MAX_APERTURE 0x9205
+#define EXIF_TAG_METERING_MODE 0x9207
+#define EXIF_TAG_FLASH 0x9209
+#define EXIF_TAG_FOCAL_LENGTH 0x920A
+#define EXIF_TAG_USER_COMMENT 0x9286
+#define EXIF_TAG_COLOR_SPACE 0xA001
+#define EXIF_TAG_PIXEL_X_DIMENSION 0xA002
+#define EXIF_TAG_PIXEL_Y_DIMENSION 0xA003
+#define EXIF_TAG_EXPOSURE_MODE 0xA402
+#define EXIF_TAG_WHITE_BALANCE 0xA403
+#define EXIF_TAG_SCENCE_CAPTURE_TYPE 0xA406
+
+/* 0th IFD GPS Info Tags */
+#define EXIF_TAG_GPS_VERSION_ID 0x0000
+#define EXIF_TAG_GPS_LATITUDE_REF 0x0001
+#define EXIF_TAG_GPS_LATITUDE 0x0002
+#define EXIF_TAG_GPS_LONGITUDE_REF 0x0003
+#define EXIF_TAG_GPS_LONGITUDE 0x0004
+#define EXIF_TAG_GPS_ALTITUDE_REF 0x0005
+#define EXIF_TAG_GPS_ALTITUDE 0x0006
+#define EXIF_TAG_GPS_TIMESTAMP 0x0007
+#define EXIF_TAG_GPS_PROCESSING_METHOD 0x001B
+#define EXIF_TAG_GPS_DATESTAMP 0x001D
+
+/* 1th IFD TIFF Tags */
+#define EXIF_TAG_COMPRESSION_SCHEME 0x0103
+#define EXIF_TAG_X_RESOLUTION 0x011A
+#define EXIF_TAG_Y_RESOLUTION 0x011B
+#define EXIF_TAG_RESOLUTION_UNIT 0x0128
+#define EXIF_TAG_JPEG_INTERCHANGE_FORMAT 0x0201
+#define EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LEN 0x0202
+
+
+typedef enum {
+ EXIF_ORIENTATION_UP = 1,
+ EXIF_ORIENTATION_90 = 6,
+ EXIF_ORIENTATION_180 = 3,
+ EXIF_ORIENTATION_270 = 8,
+} ExifOrientationType;
+
+typedef enum {
+ EXIF_SCENE_STANDARD,
+ EXIF_SCENE_LANDSCAPE,
+ EXIF_SCENE_PORTRAIT,
+ EXIF_SCENE_NIGHT,
+} CamExifSceneCaptureType;
+
+typedef enum {
+ EXIF_METERING_UNKNOWN,
+ EXIF_METERING_AVERAGE,
+ EXIF_METERING_CENTER,
+ EXIF_METERING_SPOT,
+ EXIF_METERING_MULTISPOT,
+ EXIF_METERING_PATTERN,
+ EXIF_METERING_PARTIAL,
+ EXIF_METERING_OTHER = 255,
+} CamExifMeteringModeType;
+
+typedef enum {
+ EXIF_EXPOSURE_AUTO,
+ EXIF_EXPOSURE_MANUAL,
+ EXIF_EXPOSURE_AUTO_BRACKET,
+} CamExifExposureModeType;
+
+typedef enum {
+ EXIF_WB_AUTO,
+ EXIF_WB_MANUAL,
+} CamExifWhiteBalanceType;
+
+/* Values */
+#define EXIF_DEF_MAKER "SAMSUNG"
+#define EXIF_DEF_MODEL "GT-I9020"
+#define EXIF_DEF_SOFTWARE "CRESPOJH2"
+#define EXIF_DEF_EXIF_VERSION "0220"
+#define EXIF_DEF_USERCOMMENTS "User comments"
+
+#define EXIF_DEF_YCBCR_POSITIONING 1 /* centered */
+#define EXIF_DEF_FNUMBER_NUM 26 /* 2.6 */
+#define EXIF_DEF_FNUMBER_DEN 10
+#define EXIF_DEF_EXPOSURE_PROGRAM 3 /* aperture priority */
+#define EXIF_DEF_FOCAL_LEN_NUM 278 /* 2.78mm */
+#define EXIF_DEF_FOCAL_LEN_DEN 100
+#define EXIF_DEF_FLASH 0 /* O: off, 1: on*/
+#define EXIF_DEF_COLOR_SPACE 1
+#define EXIF_DEF_EXPOSURE_MODE EXIF_EXPOSURE_AUTO
+#define EXIF_DEF_APEX_DEN 10
+
+#define EXIF_DEF_COMPRESSION 6
+#define EXIF_DEF_RESOLUTION_NUM 72
+#define EXIF_DEF_RESOLUTION_DEN 1
+#define EXIF_DEF_RESOLUTION_UNIT 2 /* inches */
+
+typedef struct {
+ uint32_t num;
+ uint32_t den;
+} rational_t;
+
+typedef struct {
+ int32_t num;
+ int32_t den;
+} srational_t;
+
+typedef struct {
+ bool enableGps;
+ bool enableThumb;
+
+ unsigned char maker[32];
+ unsigned char model[32];
+ unsigned char software[32];
+ unsigned char exif_version[4];
+ unsigned char date_time[20];
+ unsigned char user_comment[150];
+
+ uint32_t width;
+ uint32_t height;
+ uint32_t widthThumb;
+ uint32_t heightThumb;
+
+ uint16_t orientation;
+ uint16_t ycbcr_positioning;
+ uint16_t exposure_program;
+ uint16_t iso_speed_rating;
+ uint16_t metering_mode;
+ uint16_t flash;
+ uint16_t color_space;
+ uint16_t exposure_mode;
+ uint16_t white_balance;
+ uint16_t scene_capture_type;
+
+ rational_t exposure_time;
+ rational_t fnumber;
+ rational_t aperture;
+ rational_t max_aperture;
+ rational_t focal_length;
+
+ srational_t shutter_speed;
+ srational_t brightness;
+ srational_t exposure_bias;
+
+ unsigned char gps_latitude_ref[2];
+ unsigned char gps_longitude_ref[2];
+
+ uint8_t gps_version_id[4];
+ uint8_t gps_altitude_ref;
+
+ rational_t gps_latitude[3];
+ rational_t gps_longitude[3];
+ rational_t gps_altitude;
+ rational_t gps_timestamp[3];
+ unsigned char gps_datestamp[11];
+ unsigned char gps_processing_method[100];
+
+ rational_t x_resolution;
+ rational_t y_resolution;
+ uint16_t resolution_unit;
+ uint16_t compression_scheme;
+} exif_attribute_t;
+
+
+#endif /* ANDROID_HARDWARE_EXIF_H */
diff --git a/libs3cjpeg/JpegEncoder.cpp b/libs3cjpeg/JpegEncoder.cpp
new file mode 100644
index 0000000..1361bca
--- /dev/null
+++ b/libs3cjpeg/JpegEncoder.cpp
@@ -0,0 +1,796 @@
+/*
+ * Copyright Samsung Electronics Co.,LTD.
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * JPEG DRIVER MODULE (JpegEncoder.cpp)
+ * Author : ge.lee -- initial version
+ * Date : 03 June 2010
+ * Purpose : This file implements the JPEG encoder APIs as needed by Camera HAL
+ */
+#define LOG_TAG "JpegEncoder"
+#define MAIN_DUMP 0
+#define THUMB_DUMP 0
+
+#include
+#include
+#include
+
+#include "JpegEncoder.h"
+
+static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };
+
+namespace android {
+JpegEncoder::JpegEncoder() : available(false)
+{
+ mArgs.mmapped_addr = (char *)MAP_FAILED;
+ mArgs.enc_param = NULL;
+ mArgs.thumb_enc_param = NULL;
+
+ mDevFd = open(JPG_DRIVER_NAME, O_RDWR);
+ if (mDevFd < 0) {
+ LOGE("Failed to open the device");
+ return;
+ }
+
+ mArgs.mmapped_addr = (char *)mmap(0,
+ JPG_TOTAL_BUF_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ mDevFd,
+ 0);
+
+ if (mArgs.mmapped_addr == MAP_FAILED) {
+ LOGE("Failed to mmap");
+ return;
+ }
+
+ mArgs.enc_param = new jpg_enc_proc_param;
+ if (mArgs.enc_param == NULL) {
+ LOGE("Failed to allocate the memory for enc_param");
+ return;
+ }
+ memset(mArgs.enc_param, 0, sizeof(jpg_enc_proc_param));
+
+ mArgs.thumb_enc_param = new jpg_enc_proc_param;
+ if (mArgs.thumb_enc_param == NULL) {
+ LOGE("Failed to allocate the memory for thumb_enc_param");
+ delete mArgs.enc_param;
+ return;
+ }
+ memset(mArgs.thumb_enc_param, 0, sizeof(jpg_enc_proc_param));
+
+ mArgs.enc_param->sample_mode = JPG_420;
+ mArgs.enc_param->enc_type = JPG_MAIN;
+ mArgs.thumb_enc_param->sample_mode = JPG_420;
+ mArgs.thumb_enc_param->enc_type = JPG_THUMBNAIL;
+
+ available = true;
+}
+
+JpegEncoder::~JpegEncoder()
+{
+ if (mArgs.mmapped_addr != (char*)MAP_FAILED)
+ munmap(mArgs.mmapped_addr, JPG_TOTAL_BUF_SIZE);
+
+ delete mArgs.enc_param;
+
+ delete mArgs.thumb_enc_param;
+
+ if (mDevFd > 0)
+ close(mDevFd);
+}
+
+jpg_return_status JpegEncoder::setConfig(jpeg_conf type, int32_t value)
+{
+ if (!available)
+ return JPG_FAIL;
+
+ jpg_return_status ret = JPG_SUCCESS;
+
+ switch (type) {
+ case JPEG_SET_ENCODE_WIDTH:
+ if (value < 0 || value > MAX_JPG_WIDTH)
+ ret = JPG_FAIL;
+ else
+ mArgs.enc_param->width = value;
+ break;
+
+ case JPEG_SET_ENCODE_HEIGHT:
+ if (value < 0 || value > MAX_JPG_HEIGHT)
+ ret = JPG_FAIL;
+ else
+ mArgs.enc_param->height = value;
+ break;
+
+ case JPEG_SET_ENCODE_QUALITY:
+ if (value < JPG_QUALITY_LEVEL_1 || value > JPG_QUALITY_LEVEL_4)
+ ret = JPG_FAIL;
+ else
+ mArgs.enc_param->quality = (image_quality_type_t)value;
+ break;
+
+ case JPEG_SET_ENCODE_IN_FORMAT:
+ if (value != JPG_MODESEL_YCBCR && value != JPG_MODESEL_RGB) {
+ ret = JPG_FAIL;
+ } else {
+ mArgs.enc_param->in_format = (in_mode_t)value;
+ mArgs.thumb_enc_param->in_format = (in_mode_t)value;
+ }
+ break;
+
+ case JPEG_SET_SAMPING_MODE:
+ if (value != JPG_420 && value != JPG_422) {
+ ret = JPG_FAIL;
+ } else {
+ mArgs.enc_param->sample_mode = (sample_mode_t)value;
+ mArgs.thumb_enc_param->sample_mode = (sample_mode_t)value;
+ }
+ break;
+
+ case JPEG_SET_THUMBNAIL_WIDTH:
+ if (value < 0 || value > MAX_JPG_THUMBNAIL_WIDTH)
+ ret = JPG_FAIL;
+ else
+ mArgs.thumb_enc_param->width = value;
+ break;
+
+ case JPEG_SET_THUMBNAIL_HEIGHT:
+ if (value < 0 || value > MAX_JPG_THUMBNAIL_HEIGHT)
+ ret = JPG_FAIL;
+ else
+ mArgs.thumb_enc_param->height = value;
+ break;
+
+ default:
+ LOGE("Invalid Config type");
+ ret = ERR_UNKNOWN;
+ }
+
+ if (ret == JPG_FAIL)
+ LOGE("Invalid value(%d) for %d type", value, type);
+
+ return ret;
+}
+
+void* JpegEncoder::getInBuf(uint64_t size)
+{
+ if (!available)
+ return NULL;
+
+ if (size > JPG_FRAME_BUF_SIZE) {
+ LOGE("The buffer size requested is too large");
+ return NULL;
+ }
+ mArgs.in_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_FRMBUF, mArgs.mmapped_addr);
+ return (void *)(mArgs.in_buf);
+}
+
+void* JpegEncoder::getOutBuf(uint64_t *size)
+{
+ if (!available)
+ return NULL;
+
+ if (mArgs.enc_param->file_size <= 0) {
+ LOGE("The buffer requested doesn't have data");
+ return NULL;
+ }
+ mArgs.out_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_STRBUF, mArgs.mmapped_addr);
+ *size = mArgs.enc_param->file_size;
+ return (void *)(mArgs.out_buf);
+}
+
+void* JpegEncoder::getThumbInBuf(uint64_t size)
+{
+ if (!available)
+ return NULL;
+
+ if (size > JPG_FRAME_THUMB_BUF_SIZE) {
+ LOGE("The buffer size requested is too large");
+ return NULL;
+ }
+ mArgs.in_thumb_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_THUMB_FRMBUF, mArgs.mmapped_addr);
+ return (void *)(mArgs.in_thumb_buf);
+}
+
+void* JpegEncoder::getThumbOutBuf(uint64_t *size)
+{
+ if (!available)
+ return NULL;
+
+ if (mArgs.thumb_enc_param->file_size <= 0) {
+ LOGE("The buffer requested doesn't have data");
+ return NULL;
+ }
+ mArgs.out_thumb_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_THUMB_STRBUF, mArgs.mmapped_addr);
+ *size = mArgs.thumb_enc_param->file_size;
+ return (void *)(mArgs.out_thumb_buf);
+}
+
+jpg_return_status JpegEncoder::encode(unsigned int *size, exif_attribute_t *exifInfo)
+{
+ if (!available)
+ return JPG_FAIL;
+
+ LOGD("encode E");
+
+ jpg_return_status ret = JPG_FAIL;
+ unsigned char *exifOut = NULL;
+ jpg_enc_proc_param *param = mArgs.enc_param;
+
+ ret = checkMcu(param->sample_mode, param->width, param->height, false);
+ if (ret != JPG_SUCCESS)
+ return ret;
+
+ param->enc_type = JPG_MAIN;
+ ret = (jpg_return_status)ioctl(mDevFd, IOCTL_JPG_ENCODE, &mArgs);
+ if (ret != JPG_SUCCESS) {
+ LOGE("Failed to encode main image");
+ return ret;
+ }
+
+ mArgs.out_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_STRBUF, mArgs.mmapped_addr);
+
+ if (exifInfo) {
+ unsigned int thumbLen, exifLen;
+
+ uint_t bufSize = 0;
+ if (exifInfo->enableThumb) {
+ ret = encodeThumbImg(&thumbLen);
+ if (ret != JPG_SUCCESS) {
+ LOGE("Failed to encode for thumbnail image");
+ bufSize = EXIF_FILE_SIZE;
+ exifInfo->enableThumb = false;
+ } else {
+ bufSize = EXIF_FILE_SIZE + thumbLen;
+ }
+ } else {
+ bufSize = EXIF_FILE_SIZE;
+ }
+
+ if (mArgs.enc_param->file_size + bufSize > JPG_TOTAL_BUF_SIZE)
+ return ret;
+
+ exifOut = new unsigned char[bufSize];
+ if (exifOut == NULL) {
+ LOGE("Failed to allocate for exifOut");
+ return ret;
+ }
+ memset(exifOut, 0, bufSize);
+
+ ret = makeExif (exifOut, exifInfo, &exifLen);
+ if (ret != JPG_SUCCESS) {
+ LOGE("Failed to make EXIF");
+ delete[] exifOut;
+ return ret;
+ }
+
+ memmove(&mArgs.out_buf[exifLen + 2], &mArgs.out_buf[2], param->file_size - 2);
+ memcpy(&mArgs.out_buf[2], exifOut, exifLen);
+ param->file_size += exifLen;
+ }
+
+ delete[] exifOut;
+
+ *size = param->file_size;
+
+#if MAIN_DUMP
+ FILE *fout = NULL;
+ char file_name[50] = "/data/main.jpg";
+ fout = fopen(file_name, "wb");
+ if (!fout)
+ perror(&file_name[0]);
+ size_t nwrite = fwrite(mArgs.out_buf, sizeof(char), param->file_size, fout);
+ fclose(fout);
+#endif
+
+ LOGD("encode X");
+
+ return ret;
+}
+
+jpg_return_status JpegEncoder::encodeThumbImg(unsigned int *size, bool useMain)
+{
+ if (!available)
+ return JPG_FAIL;
+
+ LOGD("encodeThumbImg E");
+
+ jpg_return_status ret = JPG_FAIL;
+ jpg_enc_proc_param *param = mArgs.thumb_enc_param;
+
+ if (useMain) {
+ mArgs.in_thumb_buf = (char *)getThumbInBuf(param->width*param->height*2);
+ if (mArgs.in_thumb_buf == NULL) {
+ LOGE("Failed to get the buffer for thumbnail");
+ return JPG_FAIL;
+ }
+
+ ret = (jpg_return_status)scaleDownYuv422(mArgs.in_buf,
+ mArgs.enc_param->width,
+ mArgs.enc_param->height,
+ mArgs.in_thumb_buf,
+ param->width,
+ param->height);
+ if (ret != JPG_SUCCESS)
+ return JPG_FAIL;
+ }
+
+ ret = checkMcu(param->sample_mode, param->width, param->height, true);
+ if (ret != JPG_SUCCESS)
+ return JPG_FAIL;
+
+ mArgs.enc_param->enc_type = JPG_THUMBNAIL;
+ ret = (jpg_return_status)ioctl(mDevFd, IOCTL_JPG_ENCODE, &mArgs);
+ if (ret != JPG_SUCCESS) {
+ LOGE("Failed to encode for thumbnail");
+ return JPG_FAIL;
+ }
+
+ mArgs.out_thumb_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_THUMB_STRBUF, mArgs.mmapped_addr);
+
+#if THUMB_DUMP
+ FILE *fout = NULL;
+ char file_name[50] = "/data/thumb.jpg";
+ fout = fopen(file_name, "wb");
+ if (!fout)
+ perror(&file_name[0]);
+ size_t nwrite = fwrite(mArgs.out_thumb_buf, sizeof(char), param->file_size, fout);
+ fclose(fout);
+#endif
+
+ LOGD("encodeThumbImg X");
+
+ return JPG_SUCCESS;
+}
+
+jpg_return_status JpegEncoder::makeExif (unsigned char *exifOut,
+ exif_attribute_t *exifInfo,
+ unsigned int *size,
+ bool useMainbufForThumb)
+{
+ if (!available)
+ return JPG_FAIL;
+
+ LOGD("makeExif E");
+
+ unsigned char *pCur, *pApp1Start, *pIfdStart, *pGpsIfdPtr, *pNextIfdOffset;
+ unsigned int tmp, LongerTagOffest = 0;
+ pApp1Start = pCur = exifOut;
+
+ //2 Exif Identifier Code & TIFF Header
+ pCur += 4; // Skip 4 Byte for APP1 marker and length
+ unsigned char ExifIdentifierCode[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
+ memcpy(pCur, ExifIdentifierCode, 6);
+ pCur += 6;
+
+ /* Byte Order - little endian, Offset of IFD - 0x00000008.H */
+ unsigned char TiffHeader[8] = { 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00 };
+ memcpy(pCur, TiffHeader, 8);
+ pIfdStart = pCur;
+ pCur += 8;
+
+ //2 0th IFD TIFF Tags
+ if (exifInfo->enableGps)
+ tmp = NUM_0TH_IFD_TIFF;
+ else
+ tmp = NUM_0TH_IFD_TIFF - 1;
+
+ memcpy(pCur, &tmp, NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += 8 + NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG,
+ 1, exifInfo->width);
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG,
+ 1, exifInfo->height);
+ writeExifIfd(&pCur, EXIF_TAG_MAKE, EXIF_TYPE_ASCII,
+ strlen((char *)exifInfo->maker) + 1, exifInfo->maker, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_MODEL, EXIF_TYPE_ASCII,
+ strlen((char *)exifInfo->model) + 1, exifInfo->model, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT,
+ 1, exifInfo->orientation);
+ writeExifIfd(&pCur, EXIF_TAG_SOFTWARE, EXIF_TYPE_ASCII,
+ strlen((char *)exifInfo->software) + 1, exifInfo->software, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_DATE_TIME, EXIF_TYPE_ASCII,
+ 20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_YCBCR_POSITIONING, EXIF_TYPE_SHORT,
+ 1, exifInfo->ycbcr_positioning);
+ writeExifIfd(&pCur, EXIF_TAG_EXIF_IFD_POINTER, EXIF_TYPE_LONG,
+ 1, LongerTagOffest);
+ if (exifInfo->enableGps) {
+ pGpsIfdPtr = pCur;
+ pCur += IFD_SIZE; // Skip a ifd size for gps IFD pointer
+ }
+
+ pNextIfdOffset = pCur; // Skip a offset size for next IFD offset
+ pCur += OFFSET_SIZE;
+
+ //2 0th IFD Exif Private Tags
+ pCur = pIfdStart + LongerTagOffest;
+
+ tmp = NUM_0TH_IFD_EXIF;
+ memcpy(pCur, &tmp , NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += NUM_SIZE + NUM_0TH_IFD_EXIF*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_TIME, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->exposure_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_FNUMBER, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->fnumber, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_PROGRAM, EXIF_TYPE_SHORT,
+ 1, exifInfo->exposure_program);
+ writeExifIfd(&pCur, EXIF_TAG_ISO_SPEED_RATING, EXIF_TYPE_SHORT,
+ 1, exifInfo->iso_speed_rating);
+ writeExifIfd(&pCur, EXIF_TAG_EXIF_VERSION, EXIF_TYPE_UNDEFINED,
+ 4, exifInfo->exif_version);
+ writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_ORG, EXIF_TYPE_ASCII,
+ 20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_DIGITIZE, EXIF_TYPE_ASCII,
+ 20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_SHUTTER_SPEED, EXIF_TYPE_SRATIONAL,
+ 1, (rational_t *)&exifInfo->shutter_speed, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_APERTURE, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->aperture, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_BRIGHTNESS, EXIF_TYPE_SRATIONAL,
+ 1, (rational_t *)&exifInfo->brightness, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_BIAS, EXIF_TYPE_SRATIONAL,
+ 1, (rational_t *)&exifInfo->exposure_bias, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_MAX_APERTURE, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->max_aperture, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_METERING_MODE, EXIF_TYPE_SHORT,
+ 1, exifInfo->metering_mode);
+ writeExifIfd(&pCur, EXIF_TAG_FLASH, EXIF_TYPE_SHORT,
+ 1, exifInfo->flash);
+ writeExifIfd(&pCur, EXIF_TAG_FOCAL_LENGTH, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->focal_length, &LongerTagOffest, pIfdStart);
+ char code[8] = { 0x00, 0x00, 0x00, 0x49, 0x49, 0x43, 0x53, 0x41 };
+ int commentsLen = strlen((char *)exifInfo->user_comment) + 1;
+ memmove(exifInfo->user_comment + sizeof(code), exifInfo->user_comment, commentsLen);
+ memcpy(exifInfo->user_comment, code, sizeof(code));
+ writeExifIfd(&pCur, EXIF_TAG_USER_COMMENT, EXIF_TYPE_UNDEFINED,
+ commentsLen + sizeof(code), exifInfo->user_comment, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_COLOR_SPACE, EXIF_TYPE_SHORT,
+ 1, exifInfo->color_space);
+ writeExifIfd(&pCur, EXIF_TAG_PIXEL_X_DIMENSION, EXIF_TYPE_LONG,
+ 1, exifInfo->width);
+ writeExifIfd(&pCur, EXIF_TAG_PIXEL_Y_DIMENSION, EXIF_TYPE_LONG,
+ 1, exifInfo->height);
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_MODE, EXIF_TYPE_LONG,
+ 1, exifInfo->exposure_mode);
+ writeExifIfd(&pCur, EXIF_TAG_WHITE_BALANCE, EXIF_TYPE_LONG,
+ 1, exifInfo->white_balance);
+ writeExifIfd(&pCur, EXIF_TAG_SCENCE_CAPTURE_TYPE, EXIF_TYPE_LONG,
+ 1, exifInfo->scene_capture_type);
+ tmp = 0;
+ memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
+ pCur += OFFSET_SIZE;
+
+ //2 0th IFD GPS Info Tags
+ if (exifInfo->enableGps) {
+ writeExifIfd(&pGpsIfdPtr, EXIF_TAG_GPS_IFD_POINTER, EXIF_TYPE_LONG,
+ 1, LongerTagOffest); // GPS IFD pointer skipped on 0th IFD
+
+ pCur = pIfdStart + LongerTagOffest;
+
+ if (exifInfo->gps_processing_method[0] == 0) {
+ // don't create GPS_PROCESSING_METHOD tag if there isn't any
+ tmp = NUM_0TH_IFD_GPS - 1;
+ } else {
+ tmp = NUM_0TH_IFD_GPS;
+ }
+ memcpy(pCur, &tmp, NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_GPS_VERSION_ID, EXIF_TYPE_BYTE,
+ 4, exifInfo->gps_version_id);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE_REF, EXIF_TYPE_ASCII,
+ 2, exifInfo->gps_latitude_ref);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE, EXIF_TYPE_RATIONAL,
+ 3, exifInfo->gps_latitude, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE_REF, EXIF_TYPE_ASCII,
+ 2, exifInfo->gps_longitude_ref);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE, EXIF_TYPE_RATIONAL,
+ 3, exifInfo->gps_longitude, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE_REF, EXIF_TYPE_BYTE,
+ 1, exifInfo->gps_altitude_ref);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->gps_altitude, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_TIMESTAMP, EXIF_TYPE_RATIONAL,
+ 3, exifInfo->gps_timestamp, &LongerTagOffest, pIfdStart);
+ tmp = strlen((char*)exifInfo->gps_processing_method);
+ if (tmp > 0) {
+ if (tmp > 100) {
+ tmp = 100;
+ }
+ unsigned char tmp_buf[100+sizeof(ExifAsciiPrefix)];
+ memcpy(tmp_buf, ExifAsciiPrefix, sizeof(ExifAsciiPrefix));
+ memcpy(&tmp_buf[sizeof(ExifAsciiPrefix)], exifInfo->gps_processing_method, tmp);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_PROCESSING_METHOD, EXIF_TYPE_UNDEFINED,
+ tmp+sizeof(ExifAsciiPrefix), tmp_buf, &LongerTagOffest, pIfdStart);
+ }
+ writeExifIfd(&pCur, EXIF_TAG_GPS_DATESTAMP, EXIF_TYPE_ASCII,
+ 11, exifInfo->gps_datestamp, &LongerTagOffest, pIfdStart);
+ tmp = 0;
+ memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
+ pCur += OFFSET_SIZE;
+ }
+
+ //2 1th IFD TIFF Tags
+ char *thumbBuf;
+ int thumbSize;
+
+ if (useMainbufForThumb) {
+ thumbBuf = mArgs.out_buf;
+ thumbSize = mArgs.enc_param->file_size;
+ } else {
+ thumbBuf = mArgs.out_thumb_buf;
+ thumbSize = mArgs.thumb_enc_param->file_size;
+ }
+
+ if (exifInfo->enableThumb && (thumbBuf != NULL) && (thumbSize > 0)) {
+ tmp = LongerTagOffest;
+ memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD
+
+ pCur = pIfdStart + LongerTagOffest;
+
+ tmp = NUM_1TH_IFD_TIFF;
+ memcpy(pCur, &tmp, NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += NUM_SIZE + NUM_1TH_IFD_TIFF*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG,
+ 1, exifInfo->widthThumb);
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG,
+ 1, exifInfo->heightThumb);
+ writeExifIfd(&pCur, EXIF_TAG_COMPRESSION_SCHEME, EXIF_TYPE_SHORT,
+ 1, exifInfo->compression_scheme);
+ writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT,
+ 1, exifInfo->orientation);
+ writeExifIfd(&pCur, EXIF_TAG_X_RESOLUTION, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->x_resolution, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_Y_RESOLUTION, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->y_resolution, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_RESOLUTION_UNIT, EXIF_TYPE_SHORT,
+ 1, exifInfo->resolution_unit);
+ writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT, EXIF_TYPE_LONG,
+ 1, LongerTagOffest);
+ writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LEN, EXIF_TYPE_LONG,
+ 1, thumbSize);
+
+ tmp = 0;
+ memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
+ pCur += OFFSET_SIZE;
+
+ memcpy(pIfdStart + LongerTagOffest,
+ thumbBuf, thumbSize);
+ LongerTagOffest += thumbSize;
+ } else {
+ tmp = 0;
+ memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD
+ }
+
+ unsigned char App1Marker[2] = { 0xff, 0xe1 };
+ memcpy(pApp1Start, App1Marker, 2);
+ pApp1Start += 2;
+
+ *size = 10 + LongerTagOffest;
+ tmp = *size - 2; // APP1 Maker isn't counted
+ unsigned char size_mm[2] = {(tmp >> 8) & 0xFF, tmp & 0xFF};
+ memcpy(pApp1Start, size_mm, 2);
+
+ LOGD("makeExif X");
+
+ return JPG_SUCCESS;
+}
+
+jpg_return_status JpegEncoder::checkMcu(sample_mode_t sampleMode,
+ uint32_t width, uint32_t height, bool isThumb)
+{
+ if (!available)
+ return JPG_FAIL;
+
+ uint32_t expectedWidth = width;
+ uint32_t expectedHeight = height;
+
+ switch (sampleMode){
+ case JPG_422:
+ if (width % 16 != 0)
+ expectedWidth = width + 16 - (width % 16);
+ if (height % 8 != 0)
+ expectedHeight = height + 8 - (height % 8);
+ break;
+
+ case JPG_420:
+ if (width % 16 != 0)
+ expectedWidth = width + 16 - (width % 16);
+ if (height % 16 != 0)
+ expectedHeight = height + 16 - (height % 16);
+ break;
+
+ default:
+ LOGE("Invaild sample mode");
+ return JPG_FAIL;
+ }
+
+ if (expectedWidth == width && expectedHeight == height)
+ return JPG_SUCCESS;
+
+ LOGW("The image is not matched for MCU");
+
+ uint32_t size = width*height * 2;
+ char *srcBuf, *dstBuf;
+
+ if ((srcBuf = new char[size]) == NULL) {
+ LOGE("Failed to allocate for srcBuf");
+ return JPG_FAIL;
+ }
+
+ if (!isThumb)
+ dstBuf = mArgs.in_buf;
+ else
+ dstBuf = mArgs.in_thumb_buf;
+
+ memcpy(srcBuf, dstBuf, size);
+ bool ret = pad(srcBuf, width, height, dstBuf, expectedWidth, expectedHeight);
+
+ delete[] srcBuf;
+
+ return JPG_SUCCESS;
+}
+
+bool JpegEncoder::pad(char *srcBuf, uint32_t srcWidth, uint32_t srcHight,
+ char *dstBuf, uint32_t dstWidth, uint32_t dstHight)
+{
+ if (!available)
+ return false;
+
+ if (srcBuf == NULL || dstBuf == NULL) {
+ LOGE("srcBuf or dstBuf is NULL");
+ return false;
+ }
+
+ int padW = dstWidth - srcWidth;
+ int padH = dstHight - srcHight;
+
+ if ((int)(dstWidth - srcWidth) < 0 ||
+ (int)(dstHight - srcHight) < 0) {
+ LOGE("dstSize is smaller than srcSize");
+ return false;
+ }
+ memset(dstBuf, 0, dstWidth*dstHight * 2);
+
+ for (uint32_t i = 0; i < srcHight; i++)
+ memcpy(dstBuf + i * dstWidth * 2, srcBuf + i * srcWidth * 2, srcWidth * 2);
+
+ return true;
+}
+
+bool JpegEncoder::scaleDownYuv422(char *srcBuf, uint32_t srcWidth, uint32_t srcHight,
+ char *dstBuf, uint32_t dstWidth, uint32_t dstHight)
+{
+ if (!available)
+ return false;
+
+ int32_t step_x, step_y;
+ int32_t iXsrc, iXdst;
+ int32_t x, y, src_y_start_pos, dst_pos, src_pos;
+
+ if (dstWidth % 2 != 0 || dstHight % 2 != 0){
+ LOGE("scale_down_yuv422: invalid width, height for scaling");
+ return false;
+ }
+
+ step_x = srcWidth / dstWidth;
+ step_y = srcHight / dstHight;
+
+ dst_pos = 0;
+ for (uint32_t y = 0; y < dstHight; y++) {
+ src_y_start_pos = (y * step_y * (srcWidth * 2));
+
+ for (uint32_t x = 0; x < dstWidth; x += 2) {
+ src_pos = src_y_start_pos + (x * (step_x * 2));
+
+ dstBuf[dst_pos++] = srcBuf[src_pos ];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 1];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 2];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 3];
+ }
+ }
+
+ return true;
+}
+
+inline void JpegEncoder::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ uint32_t value)
+{
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, &value, 4);
+ *pCur += 4;
+}
+
+inline void JpegEncoder::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue)
+{
+ char buf[4] = { 0,};
+
+ memcpy(buf, pValue, count);
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, buf, 4);
+ *pCur += 4;
+}
+
+
+inline void JpegEncoder::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue,
+ unsigned int *offset,
+ unsigned char *start)
+{
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, offset, 4);
+ *pCur += 4;
+ memcpy(start + *offset, pValue, count);
+ *offset += count;
+}
+
+inline void JpegEncoder::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ rational_t *pValue,
+ unsigned int *offset,
+ unsigned char *start)
+{
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, offset, 4);
+ *pCur += 4;
+ memcpy(start + *offset, pValue, 8 * count);
+ *offset += 8 * count;
+}
+
+};
diff --git a/libs3cjpeg/JpegEncoder.h b/libs3cjpeg/JpegEncoder.h
new file mode 100644
index 0000000..b95b1b1
--- /dev/null
+++ b/libs3cjpeg/JpegEncoder.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright Samsung Electronics Co.,LTD.
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * JPEG DRIVER MODULE (JpegEncoder.h)
+ * Author : ge.lee -- initial version
+ * Date : 03 June 2010
+ * Purpose : This file implements the JPEG encoder APIs as needed by Camera HAL
+ */
+#ifndef __JPG_API_H__
+#define __JPG_API_H__
+
+#include
+#include
+
+#include "Exif.h"
+
+namespace android {
+#define MAX_JPG_WIDTH 800
+#define MAX_JPG_HEIGHT 480
+#define MAX_JPG_RESOLUTION (MAX_JPG_WIDTH * MAX_JPG_HEIGHT)
+
+#define MAX_JPG_THUMBNAIL_WIDTH 320
+#define MAX_JPG_THUMBNAIL_HEIGHT 240
+#define MAX_JPG_THUMBNAIL_RESOLUTION (MAX_JPG_THUMBNAIL_WIDTH * \
+ MAX_JPG_THUMBNAIL_HEIGHT)
+
+#define MAX_RGB_WIDTH 800
+#define MAX_RGB_HEIGHT 480
+#define MAX_RGB_RESOLUTION (MAX_RGB_WIDTH * MAX_RGB_HEIGHT)
+
+/*******************************************************************************/
+/* define JPG & image memory */
+/* memory area is 4k(PAGE_SIZE) aligned because of VirtualCopyEx() */
+#define JPG_STREAM_BUF_SIZE \
+ (MAX_JPG_RESOLUTION / PAGE_SIZE + 1) * PAGE_SIZE
+#define JPG_STREAM_THUMB_BUF_SIZE \
+ (MAX_JPG_THUMBNAIL_RESOLUTION / PAGE_SIZE + 1) * PAGE_SIZE
+#define JPG_FRAME_BUF_SIZE \
+ ((MAX_JPG_RESOLUTION * 3) / PAGE_SIZE + 1) * PAGE_SIZE
+#define JPG_FRAME_THUMB_BUF_SIZE \
+ ((MAX_JPG_THUMBNAIL_RESOLUTION * 3) / PAGE_SIZE + 1) * PAGE_SIZE
+#define JPG_RGB_BUF_SIZE \
+ ((MAX_RGB_RESOLUTION * 4) / PAGE_SIZE + 1) * PAGE_SIZE
+
+#define JPG_TOTAL_BUF_SIZE (JPG_STREAM_BUF_SIZE + \
+ JPG_STREAM_THUMB_BUF_SIZE + \
+ JPG_FRAME_BUF_SIZE + \
+ JPG_FRAME_THUMB_BUF_SIZE + \
+ JPG_RGB_BUF_SIZE)
+
+#define JPG_MAIN_START 0x00
+#define JPG_THUMB_START JPG_STREAM_BUF_SIZE
+#define IMG_MAIN_START (JPG_STREAM_BUF_SIZE + JPG_STREAM_THUMB_BUF_SIZE)
+#define IMG_THUMB_START (IMG_MAIN_START + JPG_FRAME_BUF_SIZE)
+/*******************************************************************************/
+
+#define JPG_DRIVER_NAME "/dev/s3c-jpg"
+
+#define JPEG_IOCTL_MAGIC 'J'
+#define IOCTL_JPG_DECODE _IO(JPEG_IOCTL_MAGIC, 1)
+#define IOCTL_JPG_ENCODE _IO(JPEG_IOCTL_MAGIC, 2)
+#define IOCTL_JPG_GET_STRBUF _IO(JPEG_IOCTL_MAGIC, 3)
+#define IOCTL_JPG_GET_FRMBUF _IO(JPEG_IOCTL_MAGIC, 4)
+#define IOCTL_JPG_GET_THUMB_STRBUF _IO(JPEG_IOCTL_MAGIC, 5)
+#define IOCTL_JPG_GET_THUMB_FRMBUF _IO(JPEG_IOCTL_MAGIC, 6)
+#define IOCTL_JPG_GET_PHY_FRMBUF _IO(JPEG_IOCTL_MAGIC, 7)
+#define IOCTL_JPG_GET_PHY_THUMB_FRMBUF _IO(JPEG_IOCTL_MAGIC, 8)
+
+typedef enum {
+ JPEG_SET_ENCODE_WIDTH,
+ JPEG_SET_ENCODE_HEIGHT,
+ JPEG_SET_ENCODE_QUALITY,
+ JPEG_SET_ENCODE_IN_FORMAT,
+ JPEG_SET_SAMPING_MODE,
+ JPEG_SET_THUMBNAIL_WIDTH,
+ JPEG_SET_THUMBNAIL_HEIGHT
+} jpeg_conf;
+
+typedef enum {
+ JPG_FAIL,
+ JPG_SUCCESS,
+ OK_HD_PARSING,
+ ERR_HD_PARSING,
+ OK_ENC_OR_DEC,
+ ERR_ENC_OR_DEC,
+ ERR_UNKNOWN
+} jpg_return_status;
+
+typedef enum {
+ JPG_RGB16,
+ JPG_YCBYCR,
+ JPG_TYPE_UNKNOWN
+} image_type_t;
+
+typedef enum {
+ JPG_444,
+ JPG_422,
+ JPG_420,
+ JPG_400,
+ RESERVED1,
+ RESERVED2,
+ JPG_411,
+ JPG_SAMPLE_UNKNOWN
+} sample_mode_t;
+
+typedef enum {
+ YCBCR_422,
+ YCBCR_420,
+ YCBCR_SAMPLE_UNKNOWN
+} out_mode_t;
+
+typedef enum {
+ JPG_MODESEL_YCBCR = 1,
+ JPG_MODESEL_RGB,
+ JPG_MODESEL_UNKNOWN
+} in_mode_t;
+
+typedef enum {
+ JPG_MAIN,
+ JPG_THUMBNAIL
+} encode_type_t;
+
+typedef enum {
+ JPG_QUALITY_LEVEL_1, /* high */
+ JPG_QUALITY_LEVEL_2,
+ JPG_QUALITY_LEVEL_3,
+ JPG_QUALITY_LEVEL_4 /* low */
+} image_quality_type_t;
+
+typedef struct {
+ sample_mode_t sample_mode;
+ encode_type_t dec_type;
+ out_mode_t out_format;
+ uint32_t width;
+ uint32_t height;
+ uint32_t data_size;
+ uint32_t file_size;
+} jpg_dec_proc_param;
+
+typedef struct {
+ sample_mode_t sample_mode;
+ encode_type_t enc_type;
+ in_mode_t in_format;
+ image_quality_type_t quality;
+ uint32_t width;
+ uint32_t height;
+ uint32_t data_size;
+ uint32_t file_size;
+ uint32_t set_framebuf;
+} jpg_enc_proc_param;
+
+typedef struct {
+ char *in_buf;
+ char *phy_in_buf;
+ int in_buf_size;
+ char *out_buf;
+ char *phy_out_buf;
+ int out_buf_size;
+ char *in_thumb_buf;
+ char *phy_in_thumb_buf;
+ int in_thumb_buf_size;
+ char *out_thumb_buf;
+ char *phy_out_thumb_buf;
+ int out_thumb_buf_size;
+ char *mmapped_addr;
+ jpg_dec_proc_param *dec_param;
+ jpg_enc_proc_param *enc_param;
+ jpg_enc_proc_param *thumb_enc_param;
+} jpg_args;
+
+class JpegEncoder {
+public:
+ JpegEncoder();
+ virtual ~JpegEncoder();
+
+ int openHardware();
+ jpg_return_status setConfig(jpeg_conf type, int32_t value);
+ void *getInBuf(uint64_t size);
+ void *getOutBuf(uint64_t *size);
+ void *getThumbInBuf(uint64_t size);
+ void *getThumbOutBuf(uint64_t *size);
+ jpg_return_status encode(unsigned int *size, exif_attribute_t *exifInfo);
+ jpg_return_status encodeThumbImg(unsigned int *size, bool useMain = true);
+ jpg_return_status makeExif(unsigned char *exifOut,
+ exif_attribute_t *exifIn,
+ unsigned int *size,
+ bool useMainbufForThumb = false);
+
+private:
+ jpg_return_status checkMcu(sample_mode_t sampleMode, uint32_t width, uint32_t height, bool isThumb);
+ bool pad(char *srcBuf, uint32_t srcWidth, uint32_t srcHight,
+ char *dstBuf, uint32_t dstWidth, uint32_t dstHight);
+ bool scaleDownYuv422(char *srcBuf, uint32_t srcWidth, uint32_t srcHight,
+ char *dstBuf, uint32_t dstWidth, uint32_t dstHight);
+
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ uint32_t value);
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue);
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ rational_t *pValue,
+ unsigned int *offset,
+ unsigned char *start);
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue,
+ unsigned int *offset,
+ unsigned char *start);
+ int mDevFd;
+ jpg_args mArgs;
+
+ bool available;
+
+};
+};
+#endif /* __JPG_API_H__ */
diff --git a/libstagefrighthw/Android.mk b/libstagefrighthw/Android.mk
new file mode 100644
index 0000000..af3de3b
--- /dev/null
+++ b/libstagefrighthw/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SEC_OMX_Plugin.cpp
+
+LOCAL_CFLAGS += $(PV_CFLAGS_MINUS_VISIBILITY)
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/base/include/media/stagefright/openmax \
+ $(LOCAL_PATH)/../include \
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libutils \
+ libcutils \
+ libui \
+ libdl \
+
+LOCAL_MODULE := libstagefrighthw
+
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/libstagefrighthw/SEC_OMX_Plugin.cpp b/libstagefrighthw/SEC_OMX_Plugin.cpp
new file mode 100644
index 0000000..c78999c
--- /dev/null
+++ b/libstagefrighthw/SEC_OMX_Plugin.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SEC_OMX_Plugin.h"
+
+#include
+
+#include
+#include
+
+namespace android {
+
+OMXPluginBase *createOMXPlugin() {
+ return new SECOMXPlugin;
+}
+
+SECOMXPlugin::SECOMXPlugin()
+ : mLibHandle(dlopen("libSEC_OMX_Core.s5pc110.so", RTLD_NOW)),
+ mInit(NULL),
+ mDeinit(NULL),
+ mComponentNameEnum(NULL),
+ mGetHandle(NULL),
+ mFreeHandle(NULL),
+ mGetRolesOfComponentHandle(NULL) {
+ if (mLibHandle != NULL) {
+ mInit = (InitFunc)dlsym(mLibHandle, "SEC_OMX_Init");
+ mDeinit = (DeinitFunc)dlsym(mLibHandle, "SEC_OMX_DeInit");
+
+ mComponentNameEnum =
+ (ComponentNameEnumFunc)dlsym(mLibHandle, "SEC_OMX_ComponentNameEnum");
+
+ mGetHandle = (GetHandleFunc)dlsym(mLibHandle, "SEC_OMX_GetHandle");
+ mFreeHandle = (FreeHandleFunc)dlsym(mLibHandle, "SEC_OMX_FreeHandle");
+
+ mGetRolesOfComponentHandle =
+ (GetRolesOfComponentFunc)dlsym(
+ mLibHandle, "SEC_OMX_GetRolesOfComponent");
+
+ (*mInit)();
+
+ }
+}
+
+SECOMXPlugin::~SECOMXPlugin() {
+ if (mLibHandle != NULL) {
+ (*mDeinit)();
+
+ dlclose(mLibHandle);
+ mLibHandle = NULL;
+ }
+}
+
+OMX_ERRORTYPE SECOMXPlugin::makeComponentInstance(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component) {
+ if (mLibHandle == NULL) {
+ return OMX_ErrorUndefined;
+ }
+
+ return (*mGetHandle)(
+ reinterpret_cast(component),
+ const_cast(name),
+ appData, const_cast(callbacks));
+}
+
+OMX_ERRORTYPE SECOMXPlugin::destroyComponentInstance(
+ OMX_COMPONENTTYPE *component) {
+ if (mLibHandle == NULL) {
+ return OMX_ErrorUndefined;
+ }
+
+ return (*mFreeHandle)(reinterpret_cast(component));
+}
+
+OMX_ERRORTYPE SECOMXPlugin::enumerateComponents(
+ OMX_STRING name,
+ size_t size,
+ OMX_U32 index) {
+ if (mLibHandle == NULL) {
+ return OMX_ErrorUndefined;
+ }
+
+ return (*mComponentNameEnum)(name, size, index);
+}
+
+OMX_ERRORTYPE SECOMXPlugin::getRolesOfComponent(
+ const char *name,
+ Vector *roles) {
+ roles->clear();
+
+ if (mLibHandle == NULL) {
+ return OMX_ErrorUndefined;
+ }
+
+ OMX_U32 numRoles;
+ OMX_ERRORTYPE err = (*mGetRolesOfComponentHandle)(
+ const_cast(name), &numRoles, NULL);
+
+ if (err != OMX_ErrorNone) {
+ return err;
+ }
+
+ if (numRoles > 0) {
+ OMX_U8 **array = new OMX_U8 *[numRoles];
+ for (OMX_U32 i = 0; i < numRoles; ++i) {
+ array[i] = new OMX_U8[OMX_MAX_STRINGNAME_SIZE];
+ }
+
+ OMX_U32 numRoles2;
+ err = (*mGetRolesOfComponentHandle)(
+ const_cast(name), &numRoles2, array);
+
+ CHECK_EQ(err, OMX_ErrorNone);
+ CHECK_EQ(numRoles, numRoles2);
+
+ for (OMX_U32 i = 0; i < numRoles; ++i) {
+ String8 s((const char *)array[i]);
+ roles->push(s);
+
+ delete[] array[i];
+ array[i] = NULL;
+ }
+
+ delete[] array;
+ array = NULL;
+ }
+
+ return OMX_ErrorNone;
+}
+
+} // namespace android
+
diff --git a/libstagefrighthw/SEC_OMX_Plugin.h b/libstagefrighthw/SEC_OMX_Plugin.h
new file mode 100644
index 0000000..6df2d31
--- /dev/null
+++ b/libstagefrighthw/SEC_OMX_Plugin.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SEC_OMX_PLUGIN
+
+#define SEC_OMX_PLUGIN
+
+#include
+
+namespace android {
+
+struct SECOMXPlugin : public OMXPluginBase {
+ SECOMXPlugin();
+ virtual ~SECOMXPlugin();
+
+ virtual OMX_ERRORTYPE makeComponentInstance(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+ virtual OMX_ERRORTYPE destroyComponentInstance(
+ OMX_COMPONENTTYPE *component);
+
+ virtual OMX_ERRORTYPE enumerateComponents(
+ OMX_STRING name,
+ size_t size,
+ OMX_U32 index);
+
+ virtual OMX_ERRORTYPE getRolesOfComponent(
+ const char *name,
+ Vector *roles);
+
+private:
+ void *mLibHandle;
+
+ typedef OMX_ERRORTYPE (*InitFunc)();
+ typedef OMX_ERRORTYPE (*DeinitFunc)();
+ typedef OMX_ERRORTYPE (*ComponentNameEnumFunc)(
+ OMX_STRING, OMX_U32, OMX_U32);
+
+ typedef OMX_ERRORTYPE (*GetHandleFunc)(
+ OMX_HANDLETYPE *, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE *);
+
+ typedef OMX_ERRORTYPE (*FreeHandleFunc)(OMX_HANDLETYPE *);
+
+ typedef OMX_ERRORTYPE (*GetRolesOfComponentFunc)(
+ OMX_STRING, OMX_U32 *, OMX_U8 **);
+
+ InitFunc mInit;
+ DeinitFunc mDeinit;
+ ComponentNameEnumFunc mComponentNameEnum;
+ GetHandleFunc mGetHandle;
+ FreeHandleFunc mFreeHandle;
+ GetRolesOfComponentFunc mGetRolesOfComponentHandle;
+
+ SECOMXPlugin(const SECOMXPlugin &);
+ SECOMXPlugin &operator=(const SECOMXPlugin &);
+};
+
+} // namespace android
+
+#endif // SEC_OMX_PLUGIN
diff --git a/lpm.rc b/lpm.rc
new file mode 100755
index 0000000..0585939
--- /dev/null
+++ b/lpm.rc
@@ -0,0 +1,63 @@
+on early-init
+ start ueventd
+
+on init
+
+# GyuTae FIX : we should not use system partition!!!!!
+# export PATH /sbin:/bin
+
+ export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
+ export LD_LIBRARY_PATH /vendor/lib:/system/lib
+ export ANDROID_ROOT /system
+ export ANDROID_DATA /data
+ export EXTERNAL_STORAGE /sdcard
+
+ symlink /system/etc /etc
+
+ mkdir /sdcard
+ mkdir /system
+ mkdir /data
+ mkdir /cache
+ mkdir /tmp
+ mkdir /mnt 0775 root root
+ #mount /tmp /tmp tmpfs
+
+on early-fs
+
+
+on fs
+ mount tmpfs tmpfs /tmp
+ mount yaffs2 mtd@system /system
+
+on boot
+
+ ifup lo
+ hostname localhost
+ domainname localdomain
+
+ class_start default
+
+service ueventd /sbin/ueventd
+ critical
+
+service console /system/bin/sh
+ console
+
+# adbd is controlled by the persist.service.adb.enable system property
+service adbd /sbin/adbd
+ disabled
+
+service playlpm /system/bin/playlpm
+ user root
+ oneshot
+
+service lpmkey /system/bin/charging_mode
+ user root
+ oneshot
+
+on property:persist.service.adb.enable=1
+ start adbd
+
+on property:persist.service.adb.enable=0
+ stop adbd
+
diff --git a/mkshbootimg.py b/mkshbootimg.py
new file mode 100755
index 0000000..dcc8294
--- /dev/null
+++ b/mkshbootimg.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+import sys, os
+
+def copydata(outfile, infile):
+ while 1:
+ data = infile.read(512)
+ if (data):
+ outfile.write(data)
+ else:
+ break
+
+def alignoffset(outfile):
+ offset = outfile.tell()
+ outfile.seek((offset + 511) & ~511)
+ return outfile.tell()
+
+def appendimage(outfile, infile):
+ offset = alignoffset(outfile)
+ copydata(outfile, infile)
+ length = alignoffset(outfile) - offset
+ assert (offset % 512 == 0)
+ assert (length % 512 == 0)
+ return (offset/512, length/512)
+
+if len(sys.argv) < 4:
+ print "Usage:", sys.argv[0], "output kernel boot [recovery]"
+ sys.exit(1)
+
+outfile = open(sys.argv[1], 'wb')
+kernel = open(sys.argv[2], 'r')
+boot = open(sys.argv[3], 'r')
+recovery = None
+if (len(sys.argv) == 5):
+ recovery = open(sys.argv[4], 'r')
+offset_table = "\n\nBOOT_IMAGE_OFFSETS\n"
+copydata(outfile, kernel)
+table_loc = alignoffset(outfile)
+outfile.write('\x00' * 512)
+offset_table += "boot_offset=%d;boot_len=%d;" % appendimage(outfile, boot)
+if recovery:
+ offset_table += "recovery_offset=%d;recovery_len=%d;" % appendimage(outfile, recovery)
+offset_table += "\n\n"
+outfile.seek(table_loc)
+outfile.write(offset_table)
+outfile.flush()
+os.fsync(outfile.fileno())
+outfile.close()
diff --git a/overlay/frameworks/base/core/res/res/values-large/config.xml b/overlay/frameworks/base/core/res/res/values-large/config.xml
new file mode 100644
index 0000000..27d1d32
--- /dev/null
+++ b/overlay/frameworks/base/core/res/res/values-large/config.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+ 1
+
diff --git a/overlay/frameworks/base/core/res/res/values-sw600dp/config.xml b/overlay/frameworks/base/core/res/res/values-sw600dp/config.xml
new file mode 100644
index 0000000..e83ea7f
--- /dev/null
+++ b/overlay/frameworks/base/core/res/res/values-sw600dp/config.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ 1
+ 2
+
diff --git a/overlay/frameworks/base/core/res/res/values/arrays.xml b/overlay/frameworks/base/core/res/res/values/arrays.xml
new file mode 100644
index 0000000..5b65ae4
--- /dev/null
+++ b/overlay/frameworks/base/core/res/res/values/arrays.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+ - @string/reboot_reboot
+ - @string/reboot_recovery
+
+
+
+
+
+ - recovery
+
+
+
diff --git a/overlay/frameworks/base/core/res/res/values/config.xml b/overlay/frameworks/base/core/res/res/values/config.xml
new file mode 100644
index 0000000..16900dc
--- /dev/null
+++ b/overlay/frameworks/base/core/res/res/values/config.xml
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - "wifi,1,1,1,-1,true"
+ - "mobile,0,0,0,-1,true"
+ - "mobile_mms,2,0,2,60000,true"
+ - "mobile_supl,3,0,2,60000,true"
+ - "mobile_dun,4,0,4,60000,true"
+ - "mobile_hipri,5,0,3,60000,true"
+
+
+
+
+ - "usb0"
+
+
+
+
+ - "wl0.1"
+
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+
+ - 10
+ - 25
+ - 50
+ - 100
+ - 150
+ - 200
+ - 700
+ - 1300
+ - 2000
+ - 3000
+ - 4000
+ - 5000
+ - 6000
+ - 7000
+ - 8000
+ - 9000
+
+
+
+
+ - 32
+ - 32
+ - 32
+ - 32
+ - 64
+ - 64
+ - 95
+ - 95
+ - 122
+ - 149
+ - 176
+ - 197
+ - 228
+ - 255
+ - 255
+ - 255
+ - 255
+
+
+
+
+ - 255
+ - 255
+ - 255
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+
+
+
+
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+
+
+
+ 10
+
+
+ true
+
+
+
+
+ true
+
+
+ com.google.android.location.NetworkLocationProvider
+
+
+ com.google.android.location.GeocodeProvider
+
+
+ ppp0
+
+
+ false
+
+
+ true
+
+
diff --git a/overlay/frameworks/base/core/res/res/xml/eri.xml b/overlay/frameworks/base/core/res/res/xml/eri.xml
new file mode 100644
index 0000000..9218f2f
--- /dev/null
+++ b/overlay/frameworks/base/core/res/res/xml/eri.xml
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/overlay/frameworks/base/core/res/res/xml/power_profile.xml b/overlay/frameworks/base/core/res/res/xml/power_profile.xml
new file mode 100644
index 0000000..630d7b4
--- /dev/null
+++ b/overlay/frameworks/base/core/res/res/xml/power_profile.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+ - 0
+ - 30
+ - 0.4
+ - 0.8
+
+ - 35690
+ - 50
+ - 0.2
+ - 0.1
+ - 0.1
+ - 74
+ - 243
+ - 200
+ - 70
+ - 30
+
+ 3
+ 2
+
+
+ 1000000
+
+
+ - 1.5
+
+
+ 20
+
+
+ - 4000
+
diff --git a/overlay/frameworks/base/core/res/res/xml/storage_list.xml b/overlay/frameworks/base/core/res/res/xml/storage_list.xml
new file mode 100644
index 0000000..0769cfa
--- /dev/null
+++ b/overlay/frameworks/base/core/res/res/xml/storage_list.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
diff --git a/overlay/frameworks/base/data/etc/platform.xml b/overlay/frameworks/base/data/etc/platform.xml
new file mode 100644
index 0000000..8a749ba
--- /dev/null
+++ b/overlay/frameworks/base/data/etc/platform.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/overlay/frameworks/base/packages/SystemUI/res/values/config.xml b/overlay/frameworks/base/packages/SystemUI/res/values/config.xml
new file mode 100644
index 0000000..4af4a5a
--- /dev/null
+++ b/overlay/frameworks/base/packages/SystemUI/res/values/config.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+ true
+
diff --git a/overlay/packages/apps/Mms/res/xml/mms_config.xml b/overlay/packages/apps/Mms/res/xml/mms_config.xml
new file mode 100644
index 0000000..3777b12
--- /dev/null
+++ b/overlay/packages/apps/Mms/res/xml/mms_config.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+ 1024000
+
+
+ 1200
+
+
+ 1600
+
+
+ http://wap.samsungmobile.com/uaprof/GT-P1000.xml
+
+
+
+ Mozilla/5.0
+
diff --git a/overlay/packages/apps/Settings/res/values/bools.xml b/overlay/packages/apps/Settings/res/values/bools.xml
new file mode 100644
index 0000000..61e1d03
--- /dev/null
+++ b/overlay/packages/apps/Settings/res/values/bools.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ false
+
diff --git a/overlay/packages/apps/Trebuchet/res/xml/default_workspace.xml b/overlay/packages/apps/Trebuchet/res/xml/default_workspace.xml
new file mode 100644
index 0000000..3a12fc3
--- /dev/null
+++ b/overlay/packages/apps/Trebuchet/res/xml/default_workspace.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/prebuilt/etc/asound.conf b/prebuilt/etc/asound.conf
new file mode 100644
index 0000000..7568874
--- /dev/null
+++ b/prebuilt/etc/asound.conf
@@ -0,0 +1,1238 @@
+# Android ALSA configuration file for the WM8994 audio.
+
+
+##################################################################################################################################
+#
+# {name "Playback Path" value 2} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+# # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+# # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+# {name "Capture MIC Path" value 1} # 0:Main Mic 1:Ear MIC 2:BT MIC
+# {name "Voice Call Path" value 1} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+# {name "Voice Call Recording" value 1} # 0:CALL_RECORDING_OFF 1:CALL_RECORDING_MAIN 2:CALL_RECORDING_SUB
+# {name "Voip Call Path" value 1} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+#
+##################################################################################################################################
+
+##
+## Mixer Devices
+##
+
+ctl.AndroidPlayback {
+ type hw
+ card 0
+}
+
+ctl.AndroidRecord {
+ type hw
+ card 0
+}
+
+
+##
+## Playback Devices
+##
+
+pcm.AndroidPlayback {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Earpiece {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 1} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 2}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headset {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 3}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headphone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 4}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Bluetooth {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 5}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Earpiece_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 1}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 2}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headset_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 3}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headphone_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 4}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Bluetooth_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 5}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_Headset_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 6}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_Headphone_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 6}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+pcm.AndroidPlayback_Speaker_LineOut_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 2}
+ {name "Playback Path" value 11}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_LineOut_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 2}
+ {name "Playback Path" value 11}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_LineOut_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 11}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+
+pcm.AndroidPlayback_Hdmi_TVOut_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 13}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_Hdmi_TVOut_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 14}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_Hdmi_TVOut_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 15}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Earpiece_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 6}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 10}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headset_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 8}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Bluetooth_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 5}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_Headset_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 10}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_Headphone_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Playback Path" value 10}
+ # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT 6:SPK_HP 7:RING_SPK
+ # 8:RING_HP 9:RING_HP_NO_MIC 10:RING_SPK_HP 11:EXTRA_DOCK_SPEAKER
+ # 12:TV_OUT 13:HDMI_TV_OUT 14:HDMI_SPK 15:HDMI_DUAL
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Earpiece_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 1} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 2} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headset_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 3} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headphone_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 4} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Bluetooth_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 5} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_Headset_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 3} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+
+#
+# FMRadio
+#
+pcm.AndroidPlayback_Speaker_fmradio {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "FM Radio Path" value 1} # 0:OFF 1:SPK 2:HP 3:SPK_MIX 4:HP_MIX
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headset_fmradio {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "FM Radio Path" value 2} # 0:OFF 1:SPK 2:HP 3:SPK_MIX 4:HP_MIX
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_Headset_fmradio {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "FM Radio Path" value 5} # 0:OFF 1:SPK 2:HP 3:SPK_MIX 4:HP_MIX 5:DUAL MIX
+ ]
+ }
+}
+#
+# FM Radio + AP Play
+#
+pcm.AndroidPlayback_Speaker_dualinput {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "FM Radio Path" value 3} # 0:OFF 1:SPK 2:HP 3:SPK_MIX 4:HP_MIX
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headset_dualinput {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "FM Radio Path" value 4} # 0:OFF 1:SPK 2:HP 3:SPK_MIX 4:HP_MIX
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_Headset_dualinput {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "FM Radio Path" value 5} # 0:OFF 1:SPK 2:HP 3:SPK_MIX 4:HP_MIX 5:SPK_HP_MIX
+ ]
+ }
+}
+
+#
+# Video Call - Output stream
+#
+pcm.AndroidPlayback_Earpiece_videocall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 1
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 1} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_videocall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 1
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 2} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headset_videocall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 1
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 3} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headphone_videocall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 1
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 4} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Bluetooth_videocall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 1
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Path" value 5} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+
+##
+## Capture device
+##
+
+pcm.AndroidRecord {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "Capture MIC Path" value 0} # 0:Main Mic 1:Ear Mic 2:BT Mic 3:OFF
+ ]
+ }
+}
+
+pcm.AndroidRecord_Microphone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "Capture MIC Path" value 0} # 0:Main Mic 1:Ear Mic 2:BT Mic 3:OFF
+ ]
+ }
+}
+
+pcm.AndroidRecord_Earpiece_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "Capture MIC Path" value 0} # 0:Main Mic 1:Ear Mic 2:BT Mic 3:OFF
+ ]
+ }
+}
+
+pcm.AndroidRecord_Speaker_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "Capture MIC Path" value 0} # 0:Main Mic 1:Sub MIC
+ ]
+ }
+}
+
+pcm.AndroidRecord_Headset_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "Capture MIC Path" value 1} # 0:Main Mic 1:Ear Mic 2:BT Mic 3:OFF
+ ]
+ }
+}
+
+pcm.AndroidRecord_Bluetooth_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "Capture MIC Path" value 2} # 0:Main Mic 1:Ear Mic 2:BT Mic 3:OFF
+ ]
+ }
+}
+
+pcm.AndroidRecord_Speaker_Headset_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "Capture MIC Path" value 0} # 0:Main Mic 1:Ear Mic 2:BT Mic 3:OFF
+ ]
+ }
+}
+
+pcm.AndroidRecord_Speaker_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "Capture MIC Path" value 0} # 0:Main Mic 1:Ear Mic 2:BT Mic 3:OFF
+ ]
+ }
+}
+
+pcm.AndroidRecord_Headset_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "Capture MIC Path" value 1} # 0:Main Mic 1:Ear Mic 2:BT Mic 3:OFF
+ ]
+ }
+}
+
+pcm.AndroidRecord_Headphone_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "Capture MIC Path" value 0} # 0:Main Mic 1:Ear Mic 2:BT Mic 3:OFF
+ ]
+ }
+}
+
+pcm.AndroidRecord_Speaker_Headset_ringtone {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "Capture MIC Path" value 0} # 0:Main Mic 1:Ear Mic 2:BT Mic 3:OFF
+ ]
+ }
+}
+
+pcm.AndroidRecord_Earpiece_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Recording" value 1} # 0:CALL_RECORDING_OFF 1:CALL_RECORDING_MAIN 2:CALL_RECORDING_SUB
+ ]
+ }
+}
+
+pcm.AndroidRecord_Speaker_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Recording" value 1} # 0:CALL_RECORDING_OFF 1:CALL_RECORDING_MAIN 2:CALL_RECORDING_SUB
+ ]
+ }
+}
+
+pcm.AndroidRecord_Headset_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Recording" value 2} # 0:CALL_RECORDING_OFF 1:CALL_RECORDING_MAIN 2:CALL_RECORDING_SUB
+ ]
+ }
+}
+
+pcm.AndroidRecord_Headphone_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Recording" value 1} # 0:CALL_RECORDING_OFF 1:CALL_RECORDING_MAIN 2:CALL_RECORDING_SUB
+ ]
+ }
+}
+
+pcm.AndroidRecord_Bluetooth_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Recording" value 0} # 0:CALL_RECORDING_OFF 1:CALL_RECORDING_MAIN 2:CALL_RECORDING_SUB
+ ]
+ }
+}
+
+pcm.AndroidRecord_Speaker_Headset_incall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "Voice Call Recording" value 0} # 0:CALL_RECORDING_OFF 1:CALL_RECORDING_MAIN 2:CALL_RECORDING_SUB
+ ]
+ }
+}
+
+#
+# Video Call - Input stream
+#
+pcm.AndroidRecord_Earpiece_videocall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 1
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ # Already called codec path by Video call outputstream
+ ]
+ }
+}
+
+pcm.AndroidRecord_Speaker_videocall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 1
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ # Already called codec path by Video call outputstream
+ ]
+ }
+}
+
+pcm.AndroidRecord_Headset_videocall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 1
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ # Already called codec path by Video call outputstream
+ ]
+ }
+}
+
+pcm.AndroidRecord_Headphone_videocall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 1
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ # Already called codec path by Video call outputstream
+ ]
+ }
+}
+
+pcm.AndroidRecord_Bluetooth_videocall {
+ type hooks
+ slave.pcm {
+ type hw
+ card 1
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ # Already called codec path by Video call outputstream
+ #{name "Voice Call Path" value 5} # 0:OFF 1:RCV 2:SPK 3:HP3P 4:HP4P 5:BT
+ ]
+ }
+}
+
+
+#
+# ATV - Input stream (LTN_ATV)
+#
+pcm.AndroidRecord_Atv_normal {
+ type hooks
+ slave.pcm {
+ type hw
+ card 2
+ device 0 # Must be of type "digital audio capture"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ ]
+ }
+}
+
+
+## FEATURE_SEC_KOREA_MM_AUDIO
+##
+## Playback VOIP Call Devices
+##
+
+pcm.AndroidPlayback_Earpiece_voip {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "VoIP Call Path" value 1} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Speaker_voip {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "VoIP Call Path" value 2} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headset_voip {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "VoIP Call Path" value 3} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Headphone_voip {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ # Enable audio output from the DSP
+ {name "VoIP Call Path" value 4} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
+pcm.AndroidPlayback_Bluetooth_voip {
+ type hooks
+ slave.pcm {
+ type hw
+ card 0
+ device 0 # Must be of type "digital audio playback"
+ }
+ hooks.0 {
+ type ctl_elems
+ hook_args [
+ {name "VoIP Call Path" value 5} # 0:OFF 1:RCV 2:SPK 3:HP 4:HP_NO_MIC 5:BT
+ ]
+ }
+}
+
diff --git a/prebuilt/etc/bluetooth/main.conf b/prebuilt/etc/bluetooth/main.conf
new file mode 100644
index 0000000..3989580
--- /dev/null
+++ b/prebuilt/etc/bluetooth/main.conf
@@ -0,0 +1,66 @@
+[General]
+
+# List of plugins that should not be loaded on bluetoothd startup
+#DisablePlugins = network,input
+
+# Default adaper name
+# %h - substituted for hostname
+# %d - substituted for adapter id
+# %b - substituted for ro.product.brand
+# %m - substituted for ro.product.model
+# %n - substituted for ro.product.name
+Name = %m
+
+# Default device class. Only the major and minor device class bits are
+# considered.
+# Local device class
+# 0x400000 - Service class: Telephony
+# 0x000200 - Major class: Phone
+# 0x00000C - Minor class: Smart phone
+Class = 0x40020C
+
+# How long to stay in discoverable mode before going back to non-discoverable
+# The value is in seconds. Default is 180, i.e. 3 minutes.
+# 0 = disable timer, i.e. stay discoverable forever
+DiscoverableTimeout = 120
+
+# How long to stay in pairable mode before going back to non-discoverable
+# The value is in seconds. Default is 0.
+# 0 = disable timer, i.e. stay pairable forever
+PairableTimeout = 0
+
+# Use some other page timeout than the controller default one
+# which is 16384 (10 seconds).
+PageTimeout = 8192
+
+# Discover scheduler interval used in Adapter.DiscoverDevices
+# The value is in seconds. Defaults is 0 to use controller scheduler.
+DiscoverSchedulerInterval = 0
+
+# What value should be assumed for the adapter Powered property when
+# SetProperty(Powered, ...) hasn't been called yet. Defaults to true
+InitiallyPowered = true
+
+# Remember the previously stored Powered state when initializing adapters
+RememberPowered = true
+
+# Use vendor, product and version information for DID profile support.
+# The values are separated by ":" and VID, PID and version.
+DeviceID = android:generic:1.5
+
+# Do reverse service discovery for previously unknown devices that connect to
+# us. This option is really only needed for qualification since the BITE tester
+# doesn't like us doing reverse SDP for some test cases (though there could in
+# theory be other useful purposes for this too). Defaults to true.
+ReverseServiceDiscovery = true
+
+# Enable name resolving after inquiry. Set it to 'false' if you don't need
+# remote devices name and want shorter discovery cycle. Defaults to 'true'.
+NameResolving = true
+
+# The link policy for connections. By default it's set to 15(0x000f) which is
+# a bitwise OR of role switch(0x0001), hold mode(0x0002), sniff mode(0x0004)
+# and park state(0x0008) are all enabled. However, some devices have
+# connection stability issue or fail to setup SCO when the link is in park
+# state, which requires park state bit cleared.
+DefaultLinkPolicy = 7
diff --git a/prebuilt/etc/media_profiles.xml b/prebuilt/etc/media_profiles.xml
new file mode 100644
index 0000000..7fd5a2b
--- /dev/null
+++ b/prebuilt/etc/media_profiles.xml
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/prebuilt/etc/vold.fstab b/prebuilt/etc/vold.fstab
new file mode 100644
index 0000000..d677118
--- /dev/null
+++ b/prebuilt/etc/vold.fstab
@@ -0,0 +1,14 @@
+## Vold 2.0 Generic fstab
+## - San Mehat (san@android.com)
+##
+
+#######################
+## Regular device mount
+##
+## Format: dev_mount
+## label - Label for the volume
+## mount_point - Where the volume will be mounted
+## part - Partition # (1 based), or 'auto' for first usable partition.
+## - List of sysfs paths to source devices
+######################
+dev_mount sdcard /mnt/sdcard auto /devices/platform/s3c-sdhci.2/mmc_host/mmc1
diff --git a/prebuilt/lib/egl/egl.cfg b/prebuilt/lib/egl/egl.cfg
new file mode 100755
index 0000000..3e1a8c6
--- /dev/null
+++ b/prebuilt/lib/egl/egl.cfg
@@ -0,0 +1 @@
+0 1 POWERVR_SGX540_120
diff --git a/prebuilt/usr/idc/AT42QT602240_Touchscreen.idc b/prebuilt/usr/idc/AT42QT602240_Touchscreen.idc
new file mode 100644
index 0000000..67c1cd8
--- /dev/null
+++ b/prebuilt/usr/idc/AT42QT602240_Touchscreen.idc
@@ -0,0 +1,77 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Input Device Calibration File for the ace touch screen.
+#
+# These calibration values are derived from empirical measurements
+# and may not be appropriate for use with other touch screens.
+# Refer to the input device calibration documentation for more details.
+#
+
+# Touch Size
+touch.touchSize.calibration = pressure
+
+# Tool Size
+# Driver reports tool size as a linear width measurement summed over
+# all contact points.
+#
+# Raw width field measures approx. 1 unit per millimeter
+# of tool size on the surface where a raw width of 1 corresponds
+# to about 17mm of physical size. Given that the display resolution
+# is 10px per mm we obtain a scale factor of 10 pixels / unit and
+# a bias of 160 pixels. In addition, the raw width represents a
+# sum of all contact area so we note this fact in the calibration.
+touch.toolSize.calibration = linear
+touch.toolSize.linearScale = 10
+touch.toolSize.linearBias = 160
+touch.toolSize.isSummed = 1
+
+# Pressure
+# Driver reports signal strength as pressure.
+#
+# A normal thumb touch while touching the back of the device
+# typically registers about 100 signal strength units although
+# this value is highly variable and is sensitive to contact area,
+# manner of contact and environmental conditions. We set the
+# scale so that a normal touch with good signal strength will be
+# reported as having a pressure somewhere in the vicinity of 1.0,
+# a featherlight touch will be below 1.0 and a heavy or large touch
+# will be above 1.0. We don't expect these values to be accurate.
+touch.pressure.calibration = amplitude
+touch.pressure.source = default
+touch.pressure.scale = 0.01
+
+# Size
+#touch.size.calibration = normalized
+touch.size.calibration = area
+
+# Orientation
+touch.orientation.calibration = none
+
+# Set Gesture Mode to disable pointer
+#touch.gestureMode = spots
+
+# Set DeviceType
+touch.deviceType = touchScreen
+
+# Set size of surfaces
+touch.surfaceWidth = 1024px
+touch.surfaceHeight = 600px
+
+# Set orientation awareness
+touch.orientationAware = 1
+
+
+
diff --git a/prebuilt/usr/keylayout/AT42QT602240_Touchscreen.kl b/prebuilt/usr/keylayout/AT42QT602240_Touchscreen.kl
new file mode 100644
index 0000000..0599d55
--- /dev/null
+++ b/prebuilt/usr/keylayout/AT42QT602240_Touchscreen.kl
@@ -0,0 +1,4 @@
+key 139 MENU WAKE_DROPPED VIRTUAL
+key 102 HOME WAKE_DROPPED VIRTUAL
+key 158 BACK WAKE_DROPPED VIRTUAL
+key 217 SEARCH WAKE_DROPPED VIRTUAL
diff --git a/prebuilt/usr/keylayout/p1_keyboard.kl b/prebuilt/usr/keylayout/p1_keyboard.kl
new file mode 100644
index 0000000..f50c95a
--- /dev/null
+++ b/prebuilt/usr/keylayout/p1_keyboard.kl
@@ -0,0 +1,92 @@
+key 152 LOCK WAKE
+key 359 DIGITALFRAME
+key 224 BRIGHTNESS_DOWN
+key 225 BRIGHTNESS_UP
+key 150 EXPLORER
+key 139 MENU WAKE_DROPPED
+key 102 HOME WAKE
+key 158 BACK WAKE_DROPPED
+key 217 SEARCH WAKE_DROPPED
+key 391 MUSIC
+key 393 VIDEO
+key 207 MEDIA_PLAY_PAUSE
+key 168 MEDIA_REWIND
+key 208 MEDIA_FAST_FORWARD
+key 163 MEDIA_NEXT
+key 165 MEDIA_PREVIOUS
+key 113 MUTE
+key 115 VOLUME_UP
+key 114 VOLUME_DOWN
+
+key 41 GRAVE
+key 2 1
+key 3 2
+key 4 3
+key 5 4
+key 6 5
+key 7 6
+key 8 7
+key 9 8
+key 10 9
+key 11 0
+key 12 MINUS
+key 13 EQUALS
+key 14 DEL
+
+key 15 TAB
+key 16 Q
+key 17 W
+key 18 E
+key 19 R
+key 20 T
+key 21 Y
+key 22 U
+key 23 I
+key 24 O
+key 25 P
+key 26 LEFT_BRACKET
+key 27 RIGHT_BRACKET
+key 43 BACKSLASH
+
+key 58 CAPSLOCK
+key 30 A
+key 31 S
+key 32 D
+key 33 F
+key 34 G
+key 35 H
+key 36 J
+key 37 K
+key 38 L
+key 39 SEMICOLON
+key 40 APOSTROPHE
+key 523 POUND
+key 28 ENTER
+
+key 42 SHIFT_LEFT
+key 44 Z
+key 45 X
+key 46 C
+key 47 V
+key 48 B
+key 49 N
+key 50 M
+key 51 COMMA
+key 52 PERIOD
+key 53 SLASH
+key 54 SHIFT_RIGHT
+
+key 183 SIP_ON_OFF
+key 184 UMLAUT
+key 185 LANG
+key 186 VOICESEARCH
+key 57 SPACE
+key 187 SIP_SETTING
+key 188 CUSTOM
+key 189 TASKMANAGER
+
+key 108 DPAD_DOWN WAKE_DROPPED
+key 103 DPAD_UP WAKE_DROPPED
+key 105 DPAD_LEFT WAKE_DROPPED
+key 106 DPAD_RIGHT WAKE_DROPPED
+
diff --git a/prebuilt/usr/keylayout/sec_jack.kl b/prebuilt/usr/keylayout/sec_jack.kl
new file mode 100755
index 0000000..575da0b
--- /dev/null
+++ b/prebuilt/usr/keylayout/sec_jack.kl
@@ -0,0 +1,2 @@
+key 248 HEADSETHOOK WAKE
+
diff --git a/recovery.rc b/recovery.rc
new file mode 100755
index 0000000..96dfff2
--- /dev/null
+++ b/recovery.rc
@@ -0,0 +1,69 @@
+import /usb.rc
+on early-init
+ start ueventd
+
+on init
+ export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
+ export LD_LIBRARY_PATH /vendor/lib:/system/lib
+ export ANDROID_ROOT /system
+ export ANDROID_DATA /data
+ export EXTERNAL_STORAGE /sdcard
+
+ symlink /system/etc /etc
+
+ mkdir /sdcard
+ mkdir /system
+ mkdir /data
+ mkdir /cache
+ mkdir /tmp
+ mkdir /mnt 0775 root root
+
+ # This may have been created by the recovery system with odd permissions
+ chown system system /cache/recovery
+ chmod 0770 /cache/recovery
+
+on early-fs
+
+on fs
+ mount tmpfs tmpfs /tmp
+
+on post-fs
+
+ write /proc/sys/kernel/panic_on_oops 1
+ write /proc/sys/kernel/hung_task_timeout_secs 0
+ write /proc/cpu/alignment 4
+ write /proc/sys/kernel/sched_latency_ns 10000000
+ write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000
+ write /proc/sys/kernel/sched_compat_yield 1
+ write /proc/sys/kernel/sched_child_runs_first 0
+
+on boot
+
+ ifup lo
+ hostname localhost
+ domainname localdomain
+
+ class_start default
+
+service ueventd /sbin/ueventd
+ critical
+
+service console /sbin/sh
+ console
+
+service recovery /sbin/recovery
+ console
+ oneshot
+
+service adbd /sbin/adbd recovery
+ disabled
+
+on property:persist.service.adb.enable=1
+ start adbd
+
+on property:persist.service.adb.enable=0
+ stop adbd
+
+on property:ro.debuggable=1
+ start adbd
+
diff --git a/recovery/graphics.c b/recovery/graphics.c
new file mode 100644
index 0000000..87e4e29
--- /dev/null
+++ b/recovery/graphics.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+#ifndef BOARD_LDPI_RECOVERY
+ #include "font_10x18.h"
+#else
+ #include "font_7x16.h"
+#endif
+
+#include "minui.h"
+
+typedef struct {
+ GGLSurface texture;
+ unsigned cwidth;
+ unsigned cheight;
+ unsigned ascent;
+} GRFont;
+
+static GRFont *gr_font = 0;
+static GGLContext *gr_context = 0;
+static GGLSurface gr_font_texture;
+static GGLSurface gr_framebuffer[2];
+static GGLSurface gr_mem_surface;
+static unsigned gr_active_fb = 0;
+
+static int gr_fb_fd = -1;
+static int gr_vt_fd = -1;
+
+static struct fb_var_screeninfo vi;
+
+static int get_framebuffer(GGLSurface *fb)
+{
+ int fd;
+ struct fb_fix_screeninfo fi;
+ void *bits;
+
+ fd = open("/dev/graphics/fb0", O_RDWR);
+ if (fd < 0) {
+ perror("cannot open fb0");
+ return -1;
+ }
+
+ if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
+ perror("failed to get fb0 info");
+ close(fd);
+ return -1;
+ }
+
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
+ perror("failed to get fb0 info");
+ close(fd);
+ return -1;
+ }
+
+ bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (bits == MAP_FAILED) {
+ perror("failed to mmap framebuffer");
+ close(fd);
+ return -1;
+ }
+
+ fb->version = sizeof(*fb);
+ fb->width = vi.xres;
+ fb->height = vi.yres;
+#ifdef BOARD_HAS_JANKY_BACKBUFFER
+ fb->stride = fi.line_length/2;
+#else
+ fb->stride = vi.xres;
+#endif
+ fb->data = bits;
+ fb->format = GGL_PIXEL_FORMAT_RGB_565;
+ memset(fb->data, 0, vi.yres * vi.xres * 2);
+
+ fb++;
+
+ fb->version = sizeof(*fb);
+ fb->width = vi.xres;
+ fb->height = vi.yres;
+#ifdef BOARD_HAS_JANKY_BACKBUFFER
+ fb->stride = fi.line_length/2;
+ fb->data = (void*) (((unsigned) bits) + vi.yres * fi.line_length);
+#else
+ fb->stride = vi.xres;
+ fb->data = (void*) (((unsigned) bits) + vi.yres * vi.xres * 2);
+#endif
+ fb->format = GGL_PIXEL_FORMAT_RGB_565;
+ memset(fb->data, 0, vi.yres * vi.xres * 2);
+
+ return fd;
+}
+
+static void get_memory_surface(GGLSurface* ms) {
+ ms->version = sizeof(*ms);
+ ms->width = vi.xres;
+ ms->height = vi.yres;
+ ms->stride = vi.xres;
+ ms->data = malloc(vi.xres * vi.yres * 2);
+ ms->format = GGL_PIXEL_FORMAT_RGB_565;
+}
+
+static void set_active_framebuffer(unsigned n)
+{
+ if (n > 1) return;
+ vi.yres_virtual = vi.yres * 2;
+ vi.yoffset = n * vi.yres;
+ vi.bits_per_pixel = 16;
+ if (ioctl(gr_fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
+ perror("active fb swap failed");
+ }
+}
+
+void gr_flip(void)
+{
+ GGLContext *gl = gr_context;
+
+ /* swap front and back buffers */
+ gr_active_fb = (gr_active_fb + 1) & 1;
+
+#ifdef BOARD_HAS_FLIPPED_SCREEN
+ /* flip buffer 180 degrees for devices with physicaly inverted screens */
+ unsigned int i;
+ for (i = 1; i < (vi.xres * vi.yres); i++) {
+ unsigned short tmp = gr_mem_surface.data[i];
+ gr_mem_surface.data[i] = gr_mem_surface.data[(vi.xres * vi.yres * 2) - i];
+ gr_mem_surface.data[(vi.xres * vi.yres * 2) - i] = tmp;
+ }
+#endif
+
+ /* copy data from the in-memory surface to the buffer we're about
+ * to make active. */
+ memcpy(gr_framebuffer[gr_active_fb].data, gr_mem_surface.data,
+ vi.xres * vi.yres * 2);
+
+ /* inform the display driver */
+ set_active_framebuffer(gr_active_fb);
+}
+
+void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+{
+ GGLContext *gl = gr_context;
+ GGLint color[4];
+ color[0] = ((r << 8) | r) + 1;
+ color[1] = ((g << 8) | g) + 1;
+ color[2] = ((b << 8) | b) + 1;
+ color[3] = ((a << 8) | a) + 1;
+ gl->color4xv(gl, color);
+}
+
+int gr_measure(const char *s)
+{
+ return gr_font->cwidth * strlen(s);
+}
+
+void gr_font_size(int *x, int *y)
+{
+ *x = gr_font->cwidth;
+ *y = gr_font->cheight;
+}
+
+int gr_text(int x, int y, const char *s)
+{
+ GGLContext *gl = gr_context;
+ GRFont *font = gr_font;
+ unsigned off;
+
+ y -= font->ascent;
+
+ gl->bindTexture(gl, &font->texture);
+ gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
+ gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
+ gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
+ gl->enable(gl, GGL_TEXTURE_2D);
+
+ while((off = *s++)) {
+ off -= 32;
+ if (off < 96) {
+ gl->texCoord2i(gl, (off * font->cwidth) - x, 0 - y);
+ gl->recti(gl, x, y, x + font->cwidth, y + font->cheight);
+ }
+ x += font->cwidth;
+ }
+
+ return x;
+}
+
+void gr_fill(int x, int y, int w, int h)
+{
+ GGLContext *gl = gr_context;
+ gl->disable(gl, GGL_TEXTURE_2D);
+ gl->recti(gl, x, y, w, h);
+}
+
+void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) {
+ if (gr_context == NULL) {
+ return;
+ }
+ GGLContext *gl = gr_context;
+
+ gl->bindTexture(gl, (GGLSurface*) source);
+ gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
+ gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
+ gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
+ gl->enable(gl, GGL_TEXTURE_2D);
+ gl->texCoord2i(gl, sx - dx, sy - dy);
+ gl->recti(gl, dx, dy, dx + w, dy + h);
+}
+
+unsigned int gr_get_width(gr_surface surface) {
+ if (surface == NULL) {
+ return 0;
+ }
+ return ((GGLSurface*) surface)->width;
+}
+
+unsigned int gr_get_height(gr_surface surface) {
+ if (surface == NULL) {
+ return 0;
+ }
+ return ((GGLSurface*) surface)->height;
+}
+
+static void gr_init_font(void)
+{
+ GGLSurface *ftex;
+ unsigned char *bits, *rle;
+ unsigned char *in, data;
+
+ gr_font = calloc(sizeof(*gr_font), 1);
+ ftex = &gr_font->texture;
+
+ bits = malloc(font.width * font.height);
+
+ ftex->version = sizeof(*ftex);
+ ftex->width = font.width;
+ ftex->height = font.height;
+ ftex->stride = font.width;
+ ftex->data = (void*) bits;
+ ftex->format = GGL_PIXEL_FORMAT_A_8;
+
+ in = font.rundata;
+ while((data = *in++)) {
+ memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f);
+ bits += (data & 0x7f);
+ }
+
+ gr_font->cwidth = font.cwidth;
+ gr_font->cheight = font.cheight;
+ gr_font->ascent = font.cheight - 2;
+}
+
+int gr_init(void)
+{
+ gglInit(&gr_context);
+ GGLContext *gl = gr_context;
+
+ gr_init_font();
+ gr_vt_fd = open("/dev/tty0", O_RDWR | O_SYNC);
+ if (gr_vt_fd < 0) {
+ // This is non-fatal; post-Cupcake kernels don't have tty0.
+ perror("can't open /dev/tty0");
+ } else if (ioctl(gr_vt_fd, KDSETMODE, (void*) KD_GRAPHICS)) {
+ // However, if we do open tty0, we expect the ioctl to work.
+ perror("failed KDSETMODE to KD_GRAPHICS on tty0");
+ gr_exit();
+ return -1;
+ }
+
+ gr_fb_fd = get_framebuffer(gr_framebuffer);
+ if (gr_fb_fd < 0) {
+ gr_exit();
+ return -1;
+ }
+
+ get_memory_surface(&gr_mem_surface);
+
+ fprintf(stderr, "framebuffer: fd %d (%d x %d)\n",
+ gr_fb_fd, gr_framebuffer[0].width, gr_framebuffer[0].height);
+
+ /* start with 0 as front (displayed) and 1 as back (drawing) */
+ gr_active_fb = 0;
+ set_active_framebuffer(0);
+ gl->colorBuffer(gl, &gr_mem_surface);
+
+ gl->activeTexture(gl, 0);
+ gl->enable(gl, GGL_BLEND);
+ gl->blendFunc(gl, GGL_SRC_ALPHA, GGL_ONE_MINUS_SRC_ALPHA);
+
+ return 0;
+}
+
+void gr_exit(void)
+{
+ close(gr_fb_fd);
+ gr_fb_fd = -1;
+
+ free(gr_mem_surface.data);
+
+ ioctl(gr_vt_fd, KDSETMODE, (void*) KD_TEXT);
+ close(gr_vt_fd);
+ gr_vt_fd = -1;
+}
+
+int gr_fb_width(void)
+{
+ return gr_framebuffer[0].width;
+}
+
+int gr_fb_height(void)
+{
+ return gr_framebuffer[0].height;
+}
+
+gr_pixel *gr_fb_data(void)
+{
+ return (unsigned short *) gr_mem_surface.data;
+}
+
+void gr_fb_blank(bool blank)
+{
+ int ret;
+
+ ret = ioctl(gr_fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
+ if (ret < 0)
+ perror("ioctl(): blank");
+}
diff --git a/releasetools/p1_common.py b/releasetools/p1_common.py
new file mode 100644
index 0000000..93f1b8e
--- /dev/null
+++ b/releasetools/p1_common.py
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os, sys
+
+LOCAL_DIR = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
+RELEASETOOLS_DIR = os.path.abspath(os.path.join(LOCAL_DIR, '../../../build/tools/releasetools'))
+
+# Add releasetools directory to python path
+sys.path.append(RELEASETOOLS_DIR)
+
+from common import *
+
+def load_module_from_file(module_name, filename):
+ import imp
+ f = open(filename, 'r')
+ module = imp.load_module(module_name, f, filename, ('', 'U', 1))
+ f.close()
+ return module
diff --git a/releasetools/p1_edify_generator.py b/releasetools/p1_edify_generator.py
new file mode 100644
index 0000000..3261b44
--- /dev/null
+++ b/releasetools/p1_edify_generator.py
@@ -0,0 +1,71 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os, sys
+
+LOCAL_DIR = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
+RELEASETOOLS_DIR = os.path.abspath(os.path.join(LOCAL_DIR, '../../../build/tools/releasetools'))
+VENDOR_SAMSUNG_DIR = os.path.abspath(os.path.join(LOCAL_DIR, '../../../vendor/samsung'))
+
+import edify_generator
+
+class EdifyGenerator(edify_generator.EdifyGenerator):
+ def AssertDevice(self, device):
+ edify_generator.EdifyGenerator.AssertDevice(self, device)
+ self.script.append('show_progress(0.15, 5);');
+ self.script.append(
+ ('package_extract_file("modem.bin", "/tmp/modem.bin");\n'
+ 'set_perm(0, 0, 0777, "/tmp/modem.bin");'))
+ self.script.append(
+ ('package_extract_file("updater.sh", "/tmp/updater.sh");\n'
+ 'set_perm(0, 0, 0777, "/tmp/updater.sh");'))
+ self.script.append(
+ ('package_extract_file("make_ext4fs", "/tmp/make_ext4fs");\n'
+ 'set_perm(0, 0, 0777, "/tmp/make_ext4fs");'))
+ self.script.append(
+ ('package_extract_file("busybox", "/tmp/busybox");\n'
+ 'set_perm(0, 0, 0777, "/tmp/busybox");'))
+ self.script.append(
+ ('package_extract_file("flash_image", "/tmp/flash_image");\n'
+ 'set_perm(0, 0, 0777, "/tmp/flash_image");'))
+ self.script.append(
+ ('package_extract_file("erase_image", "/tmp/erase_image");\n'
+ 'set_perm(0, 0, 0777, "/tmp/erase_image");'))
+ self.script.append(
+ ('package_extract_file("bml_over_mtd", "/tmp/bml_over_mtd");\n'
+ 'set_perm(0, 0, 0777, "/tmp/bml_over_mtd");'))
+ self.script.append(
+ ('package_extract_file("bml_over_mtd.sh", "/tmp/bml_over_mtd.sh");\n'
+ 'set_perm(0, 0, 0777, "/tmp/bml_over_mtd.sh");'))
+
+ self.script.append('package_extract_file("boot.img", "/tmp/boot.img");')
+ self.script.append('assert(run_program("/tmp/updater.sh") == 0);')
+
+ def RunBackup(self, command):
+ edify_generator.EdifyGenerator.RunBackup(self, command)
+
+ def WriteBMLoverMTD(self, partition, partition_start_block, reservoirpartition, reservoir_start_block, image):
+ """Write the given package file into the given partition."""
+
+ args = {'partition': partition, 'partition_start_block': partition_start_block, 'reservoirpartition': reservoirpartition, 'reservoir_start_block': reservoir_start_block, 'image': image}
+
+ self.script.append(
+ ('assert(run_program("/tmp/erase_image", "%(partition)s"));') % args)
+
+ self.script.append(
+ ('assert(package_extract_file("%(image)s", "/tmp/%(partition)s.img"),\n'
+ ' run_program("/tmp/bml_over_mtd.sh", "%(partition)s", "%(partition_start_block)s", "%(reservoirpartition)s", "%(reservoir_start_block)s", "/tmp/%(partition)s.img"),\n'
+ ' delete("/tmp/%(partition)s.img"));') % args)
+
diff --git a/releasetools/p1_img_from_target_files b/releasetools/p1_img_from_target_files
new file mode 100755
index 0000000..590b265
--- /dev/null
+++ b/releasetools/p1_img_from_target_files
@@ -0,0 +1,187 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Given a target-files zipfile, produces an image zipfile suitable for
+use with 'fastboot update'.
+
+Usage: img_from_target_files [flags] input_target_files output_image_zip
+
+ -b (--board_config)
+ Deprecated.
+
+"""
+
+import sys
+
+if sys.hexversion < 0x02040000:
+ print >> sys.stderr, "Python 2.4 or newer is required."
+ sys.exit(1)
+
+import errno
+import os
+import re
+import shutil
+import subprocess
+import tempfile
+import zipfile
+
+# missing in Python 2.4 and before
+if not hasattr(os, "SEEK_SET"):
+ os.SEEK_SET = 0
+
+import p1_common as common
+
+OPTIONS = common.OPTIONS
+
+def AddUserdata(output_zip):
+ """Create an empty userdata image and store it in output_zip."""
+
+ print "creating userdata.img..."
+
+ # The name of the directory it is making an image out of matters to
+ # mkyaffs2image. So we create a temp dir, and within it we create an
+ # empty dir named "data", and build the image from that.
+ temp_dir = tempfile.mkdtemp()
+ user_dir = os.path.join(temp_dir, "data")
+ os.mkdir(user_dir)
+ img = tempfile.NamedTemporaryFile()
+
+ build_command = []
+ if OPTIONS.info_dict["fstab"]["/data"].fs_type.startswith("ext"):
+ build_command = ["mkuserimg.sh",
+ user_dir, img.name,
+ OPTIONS.info_dict["fstab"]["/data"].fs_type, "data"]
+ if "userdata_size" in OPTIONS.info_dict:
+ build_command.append(str(OPTIONS.info_dict["userdata_size"]))
+ else:
+ build_command = ["mkyaffs2image", "-f"]
+ extra = OPTIONS.info_dict.get("mkyaffs2_extra_flags", None)
+ if extra:
+ build_command.extend(extra.split())
+ build_command.append(user_dir)
+ build_command.append(img.name)
+
+ p = common.Run(build_command)
+ p.communicate()
+ assert p.returncode == 0, "build userdata.img image failed"
+
+ common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict)
+ output_zip.write(img.name, "userdata.img")
+ img.close()
+ os.rmdir(user_dir)
+ os.rmdir(temp_dir)
+
+
+def AddSystem(output_zip):
+ """Turn the contents of SYSTEM into a system image and store it in
+ output_zip."""
+
+ print "creating system.img..."
+
+ img = tempfile.NamedTemporaryFile()
+
+ # The name of the directory it is making an image out of matters to
+ # mkyaffs2image. It wants "system" but we have a directory named
+ # "SYSTEM", so create a symlink.
+ try:
+ os.symlink(os.path.join(OPTIONS.input_tmp, "SYSTEM"),
+ os.path.join(OPTIONS.input_tmp, "system"))
+ except OSError, e:
+ # bogus error on my mac version?
+ # File "./build/tools/releasetools/img_from_target_files", line 86, in AddSystem
+ # os.path.join(OPTIONS.input_tmp, "system"))
+ # OSError: [Errno 17] File exists
+ if (e.errno == errno.EEXIST):
+ pass
+
+ build_command = []
+ if OPTIONS.info_dict["fstab"]["/system"].fs_type.startswith("ext"):
+ build_command = ["mkuserimg.sh",
+ os.path.join(OPTIONS.input_tmp, "system"), img.name,
+ OPTIONS.info_dict["fstab"]["/system"].fs_type, "system"]
+ if "system_size" in OPTIONS.info_dict:
+ build_command.append(str(OPTIONS.info_dict["system_size"]))
+ else:
+ build_command = ["mkyaffs2image", "-f"]
+ extra = OPTIONS.info_dict.get("mkyaffs2_extra_flags", None)
+ if extra:
+ build_command.extend(extra.split())
+ build_command.append(os.path.join(OPTIONS.input_tmp, "system"))
+ build_command.append(img.name)
+
+ p = common.Run(build_command)
+ p.communicate()
+ assert p.returncode == 0, "build system.img image failed"
+
+ img.seek(os.SEEK_SET, 0)
+ data = img.read()
+ img.close()
+
+ common.CheckSize(data, "system.img", OPTIONS.info_dict)
+ common.ZipWriteStr(output_zip, "system.img", data)
+
+
+def CopyInfo(output_zip):
+ """Copy the android-info.txt file from the input to the output."""
+ output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"),
+ "android-info.txt")
+
+
+def main(argv):
+
+ def option_handler(o, a):
+ if o in ("-b", "--board_config"):
+ pass # deprecated
+ else:
+ return False
+ return True
+
+ args = common.ParseOptions(argv, __doc__,
+ extra_opts="b:",
+ extra_long_opts=["board_config="],
+ extra_option_handler=option_handler)
+
+ if len(args) != 2:
+ common.Usage(__doc__)
+ sys.exit(1)
+
+ OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0])
+ OPTIONS.info_dict = common.LoadInfoDict(input_zip)
+
+ output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED)
+
+ common.AddBoot(output_zip, OPTIONS.info_dict)
+ common.AddRecovery(output_zip, OPTIONS.info_dict)
+ AddSystem(output_zip)
+ AddUserdata(output_zip)
+ CopyInfo(output_zip)
+
+ print "cleaning up..."
+ output_zip.close()
+ shutil.rmtree(OPTIONS.input_tmp)
+
+ print "done."
+
+
+if __name__ == '__main__':
+ try:
+ main(sys.argv[1:])
+ except common.ExternalError, e:
+ print
+ print " ERROR: %s" % (e,)
+ print
+ sys.exit(1)
diff --git a/releasetools/p1_ota_from_target_files b/releasetools/p1_ota_from_target_files
new file mode 100755
index 0000000..f1e2457
--- /dev/null
+++ b/releasetools/p1_ota_from_target_files
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import os
+import p1_common as common
+
+LOCAL_DIR = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
+RELEASETOOLS_DIR = os.path.abspath(os.path.join(LOCAL_DIR, '../../../build/tools/releasetools'))
+TARGET_DIR = os.getenv('OUT')
+UTILITIES_DIR = os.path.join(TARGET_DIR, 'utilities')
+
+# Add releasetools directory to python path
+sys.path.append(RELEASETOOLS_DIR)
+
+# Import the existing file so we just have to rewrite the modules we need.
+# This is a nasty hack as the filename doesn't end in .py, but it works
+filename = os.path.join(RELEASETOOLS_DIR, "ota_from_target_files")
+ota_from_target_files = common.load_module_from_file('ota_from_target_files', filename)
+
+from ota_from_target_files import *
+import p1_edify_generator as edify_generator
+
+__doc__ = ota_from_target_files.__doc__
+
+def CopyBootFiles(input_zip, output_zip):
+ output_zip.write(os.path.join(TARGET_DIR, "boot.img"),"boot.img")
+
+def CopyBMLoverMTD(output_zip):
+ """Copy the bml_over_mtd utility and script to the output."""
+ output_zip.write(os.path.join(TARGET_DIR, "modem.bin"),"modem.bin")
+ output_zip.write(os.path.join(UTILITIES_DIR, "make_ext4fs"),"make_ext4fs")
+ output_zip.write(os.path.join(UTILITIES_DIR, "busybox"),"busybox")
+ output_zip.write(os.path.join(UTILITIES_DIR, "flash_image"),"flash_image")
+ output_zip.write(os.path.join(UTILITIES_DIR, "erase_image"),"erase_image")
+ output_zip.write(os.path.join(UTILITIES_DIR, "bml_over_mtd"),"bml_over_mtd")
+ output_zip.write(os.path.join(LOCAL_DIR, "bml_over_mtd.sh"),"bml_over_mtd.sh")
+ output_zip.write(os.path.join(TARGET_DIR, "updater.sh"),"updater.sh")
+
+def WriteFullOTAPackage(input_zip, output_zip):
+ # TODO: how to determine this? We don't know what version it will
+ # be installed on top of. For now, we expect the API just won't
+ # change very often.
+ script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict)
+
+ metadata = {"post-build": GetBuildProp("ro.build.fingerprint", input_zip),
+ "pre-device": GetBuildProp("ro.product.device", input_zip),
+ "post-timestamp": GetBuildProp("ro.build.date.utc", input_zip),
+ }
+
+ device_specific = common.DeviceSpecificParams(
+ input_zip=input_zip,
+ input_version=OPTIONS.info_dict["recovery_api_version"],
+ output_zip=output_zip,
+ script=script,
+ input_tmp=OPTIONS.input_tmp,
+ metadata=metadata,
+ info_dict=OPTIONS.info_dict)
+
+# if not OPTIONS.omit_prereq:
+# ts = GetBuildProp("ro.build.date.utc", input_zip)
+# script.AssertOlderBuild(ts)
+
+ # script.ShowProgress(0.15, 5) in device-specific assert as I could not get it to show up before it in here
+
+ AppendAssertions(script, input_zip)
+ device_specific.FullOTA_Assertions()
+
+ if OPTIONS.backuptool:
+ script.RunBackup("backup")
+
+ if OPTIONS.wipe_user_data:
+ script.FormatPartition("/data")
+
+ script.FormatPartition("/system")
+ script.Mount("/system")
+ script.ShowProgress(0.7, 30);
+ script.UnpackPackageDir("recovery", "/system")
+ script.UnpackPackageDir("system", "/system")
+
+ (symlinks, retouch_files) = CopySystemFiles(input_zip, output_zip)
+ script.MakeSymlinks(symlinks)
+
+ if OPTIONS.aslr_mode:
+ script.RetouchBinaries(retouch_files)
+ else:
+ script.UndoRetouchBinaries(retouch_files)
+
+ Item.GetMetadata(input_zip)
+ script.ShowProgress(0.15, 5)
+ Item.Get("system").SetPermissions(script)
+
+ CopyBootFiles(input_zip, output_zip)
+ CopyBMLoverMTD(output_zip)
+
+ device_specific.FullOTA_InstallEnd()
+
+ if OPTIONS.extra_script is not None:
+ script.AppendExtra(OPTIONS.extra_script)
+
+ script.UnmountAll()
+ script.AddToZip(input_zip, output_zip)
+ WriteMetadata(metadata, output_zip)
+ota_from_target_files.WriteFullOTAPackage = WriteFullOTAPackage
+
+
+def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
+ print "Incremental OTA Packages are not support on the Samsung Galaxy S at this time"
+ sys.exit(1)
+ota_from_target_files.WriteIncrementalOTAPackage = WriteIncrementalOTAPackage
+
+
+if __name__ == '__main__':
+ try:
+ main(sys.argv[1:])
+ except common.ExternalError, e:
+ print
+ print " ERROR: %s" % (e,)
+ print
+ sys.exit(1)
diff --git a/sec_mm/Android.mk b/sec_mm/Android.mk
new file mode 100644
index 0000000..16298da
--- /dev/null
+++ b/sec_mm/Android.mk
@@ -0,0 +1,5 @@
+WITH_SEC_OMX := true
+
+ifeq ($(WITH_SEC_OMX), true)
+ include $(all-subdir-makefiles)
+endif
diff --git a/sec_mm/sec_omx/Android.mk b/sec_mm/sec_omx/Android.mk
new file mode 100644
index 0000000..cbae428
--- /dev/null
+++ b/sec_mm/sec_omx/Android.mk
@@ -0,0 +1,22 @@
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+SEC_OMX_TOP := $(LOCAL_PATH)
+SEC_CODECS := $(SEC_OMX_TOP)/sec_codecs/
+
+SEC_OMX_INC := $(SEC_OMX_TOP)/sec_omx_include/
+SEC_OMX_COMPONENT := $(SEC_OMX_TOP)/sec_omx_component
+
+include $(SEC_OMX_TOP)/sec_osal/Android.mk
+include $(SEC_OMX_TOP)/sec_omx_core/Android.mk
+
+include $(SEC_CODECS)/Android.mk
+include $(SEC_OMX_COMPONENT)/common/Android.mk
+include $(SEC_OMX_COMPONENT)/video/dec/Android.mk
+include $(SEC_OMX_COMPONENT)/video/dec/h264dec/Android.mk
+include $(SEC_OMX_COMPONENT)/video/dec/mpeg4dec/Android.mk
+include $(SEC_OMX_COMPONENT)/video/enc/Android.mk
+include $(SEC_OMX_COMPONENT)/video/enc/h264enc/Android.mk
+include $(SEC_OMX_COMPONENT)/video/enc/mpeg4enc/Android.mk
diff --git a/sec_mm/sec_omx/sec_codecs/Android.mk b/sec_mm/sec_omx/sec_codecs/Android.mk
new file mode 100644
index 0000000..3c163a4
--- /dev/null
+++ b/sec_mm/sec_omx/sec_codecs/Android.mk
@@ -0,0 +1,7 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+include $(SEC_CODECS)/video/mfc_c110/dec/Android.mk
+include $(SEC_CODECS)/video/mfc_c110/enc/Android.mk
+include $(SEC_CODECS)/video/mfc_c110/csc/Android.mk
\ No newline at end of file
diff --git a/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/Android.mk b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/Android.mk
new file mode 100644
index 0000000..8b570aa
--- /dev/null
+++ b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/Android.mk
@@ -0,0 +1,36 @@
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+ifeq ($(ARCH_ARM_HAVE_NEON),true)
+LOCAL_SRC_FILES := \
+ csc_yuv420_nv12t_y_neon.s \
+ csc_yuv420_nv12t_uv_neon.s \
+ csc_nv12t_yuv420_y_neon.s \
+ csc_nv12t_yuv420_uv_neon.s \
+ csc_interleave_memcpy.s \
+ csc_deinterleave_memcpy.s
+
+else
+LOCAL_SRC_FILES := \
+ color_space_convertor.c
+
+endif
+
+LOCAL_MODULE := libseccsc.s5pc110
+
+LOCAL_CFLAGS :=
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_SHARED_LIBRARIES := liblog
+
+LOCAL_C_INCLUDES := \
+ $(SEC_CODECS)/video/mfc_c110/include
+
+include $(BUILD_STATIC_LIBRARY)
+
diff --git a/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/color_space_convertor.c b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/color_space_convertor.c
new file mode 100644
index 0000000..c1ac638
--- /dev/null
+++ b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/color_space_convertor.c
@@ -0,0 +1,1092 @@
+/*
+ *
+ * Copyright 2011 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file color_space_convertor.c
+ * @brief SEC_OMX specific define
+ * @author ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ * 2011.7.01 : Create
+ */
+
+#include "stdlib.h"
+#include "color_space_convertor.h"
+
+#define TILED_SIZE 64*32
+
+/*
+ * De-interleaves src to dest1, dest2
+ *
+ * @param dest1
+ * Address of de-interleaved data[out]
+ *
+ * @param dest2
+ * Address of de-interleaved data[out]
+ *
+ * @param src
+ * Address of interleaved data[in]
+ *
+ * @param src_size
+ * Size of interleaved data[in]
+ */
+void csc_deinterleave_memcpy(char *dest1, char *dest2, char *src, int src_size)
+{
+ int i = 0;
+ for(i=0; i= 1024) {
+ for (i=0; i>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+2;
+ tiled_offset = tiled_offset<<11;
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*2;
+ tiled_offset3 = tiled_offset+2048*3;
+ temp2 = 8;
+ } else {
+ temp2 = ((yuv420_height+31)>>5)<<5;
+ /* even fomula: x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ if ((i+32)= 512) {
+ for (i=0; i>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+2;
+ temp1 = aligned_x_size>>5;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*2;
+ tiled_offset3 = tiled_offset+2048*3;
+ temp2 = 8;
+ } else {
+ temp2 = ((yuv420_height+31)>>5)<<5;
+ /* even fomula: x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ if ((i+32)>5;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*6;
+ tiled_offset3 = tiled_offset+2048*7;
+ temp2 = 8;
+ } else {
+ temp1 = aligned_x_size>>6;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*2;
+ tiled_offset3 = tiled_offset+2048*3;
+ temp2 = 4;
+ }
+ }
+ temp1 = i&0x1F;
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i), nv12t_src+tiled_offset+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i)+64*1, nv12t_src+tiled_offset1+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i)+64*2, nv12t_src+tiled_offset2+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i)+64*3, nv12t_src+tiled_offset3+64*(temp1), 64);
+
+ tiled_offset = tiled_offset+temp2*2048;
+ tiled_offset1 = tiled_offset1+temp2*2048;
+ tiled_offset2 = tiled_offset2+temp2*2048;
+ tiled_offset3 = tiled_offset3+temp2*2048;
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i)+64*4, nv12t_src+tiled_offset+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i)+64*5, nv12t_src+tiled_offset1+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i)+64*6, nv12t_src+tiled_offset2+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i)+64*7, nv12t_src+tiled_offset3+64*(temp1), 64);
+ }
+ aligned_x_size = aligned_x_size+512;
+ }
+
+ if ((yuv420_width-aligned_x_size) >= 256) {
+ for (i=0; i>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+2;
+ temp1 = aligned_x_size>>5;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*2;
+ tiled_offset3 = tiled_offset+2048*3;
+ } else {
+ temp2 = ((yuv420_height+31)>>5)<<5;
+ /* even fomula: x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ if ((i+32)>5;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*6;
+ tiled_offset3 = tiled_offset+2048*7;
+ } else {
+ temp1 = aligned_x_size>>6;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*2;
+ tiled_offset3 = tiled_offset+2048*3;
+ }
+ }
+ temp1 = i&0x1F;
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i), nv12t_src+tiled_offset+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i)+64*1, nv12t_src+tiled_offset1+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i)+64*2, nv12t_src+tiled_offset2+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i)+64*3, nv12t_src+tiled_offset3+64*(temp1), 64);
+ }
+ aligned_x_size = aligned_x_size+256;
+ }
+
+ if ((yuv420_width-aligned_x_size) >= 128) {
+ for (i=0; i>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+2;
+ temp1 = aligned_x_size>>5;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ tiled_offset1 = tiled_offset+2048*1;
+ } else {
+ temp2 = ((yuv420_height+31)>>5)<<5;
+ /* even fomula: x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ if ((i+32)>5;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ } else {
+ temp1 = aligned_x_size>>6;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ }
+ }
+ temp1 = i&0x1F;
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i), nv12t_src+tiled_offset+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i)+64, nv12t_src+tiled_offset1+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i+1), nv12t_src+tiled_offset+64*(temp1+1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i+1)+64, nv12t_src+tiled_offset1+64*(temp1+1), 64);
+ }
+ aligned_x_size = aligned_x_size+128;
+ }
+
+ if ((yuv420_width-aligned_x_size) >= 64) {
+ for (i=0; i>6;
+ tiled_y_index = i>>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset+2;
+ temp1 = (tiled_x_index>>2)<<2;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ } else {
+ temp2 = ((yuv420_height+31)>>5)<<5;
+ if ((i+32)>2)<<2+x_block_num*y */
+ temp1 = tiled_x_index+2;
+ temp1 = (temp1>>2)<<2;
+ tiled_offset = tiled_x_index+temp1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ } else {
+ /* even2 fomula: x+x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset<<11;
+ }
+ }
+
+ temp1 = i&0x1F;
+ temp2 = aligned_x_size&0x3F;
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i), nv12t_src+tiled_offset+temp2+64*(temp1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i+1), nv12t_src+tiled_offset+temp2+64*(temp1+1), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i+2), nv12t_src+tiled_offset+temp2+64*(temp1+2), 64);
+ memcpy(yuv420_dest+aligned_x_size+yuv420_width*(i+3), nv12t_src+tiled_offset+temp2+64*(temp1+3), 64);
+ }
+ aligned_x_size = aligned_x_size+64;
+ }
+
+ if (yuv420_width != aligned_x_size) {
+ for (i=0; i>6;
+ tiled_y_index = i>>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset+2;
+ temp1 = (tiled_x_index>>2)<<2;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ } else {
+ temp2 = ((yuv420_height+31)>>5)<<5;
+ if ((i+32)>2)<<2+x_block_num*y */
+ temp1 = tiled_x_index+2;
+ temp1 = (temp1>>2)<<2;
+ tiled_offset = tiled_x_index+temp1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ } else {
+ /* even2 fomula: x+x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset<<11;
+ }
+ }
+
+ temp1 = i&0x1F;
+ temp2 = j&0x3F;
+ memcpy(yuv420_dest+j+yuv420_width*(i), nv12t_src+tiled_offset+temp2+64*(temp1), 4);
+ memcpy(yuv420_dest+j+yuv420_width*(i+1), nv12t_src+tiled_offset+temp2+64*(temp1+1), 4);
+ memcpy(yuv420_dest+j+yuv420_width*(i+2), nv12t_src+tiled_offset+temp2+64*(temp1+2), 4);
+ memcpy(yuv420_dest+j+yuv420_width*(i+3), nv12t_src+tiled_offset+temp2+64*(temp1+3), 4);
+ }
+ }
+ }
+}
+
+/*
+ * Converts and Deinterleaves tiled data to linear
+ * 1. UV of NV12T to UV of YUV420P
+ *
+ * @param yuv420_u_dest
+ * U plane address of YUV420P[out]
+ *
+ * @param yuv420_v_dest
+ * V plane address of YUV420P[out]
+ *
+ * @param nv12t_src
+ * UV plane address of NV12T[in]
+ *
+ * @param yuv420_width
+ * Width of YUV420[in]
+ *
+ * @param yuv420_uv_height
+ * Height/2 of YUV420[in]
+ */
+void csc_tiled_to_linear_deinterleave(char *yuv420_u_dest, char *yuv420_v_dest, char *nv12t_uv_src, int yuv420_width, int yuv420_uv_height)
+{
+ unsigned int i, j;
+ unsigned int tiled_x_index = 0, tiled_y_index = 0;
+ unsigned int aligned_x_size = 0;
+ unsigned int tiled_offset = 0, tiled_offset1 = 0, tiled_offset2 = 0, tiled_offset3 = 0;
+ unsigned int temp1 = 0, temp2 = 0;
+
+ if (yuv420_width >= 1024) {
+ for (i=0; i>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+2;
+ tiled_offset = tiled_offset<<11;
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*2;
+ tiled_offset3 = tiled_offset+2048*3;
+ temp2 = 8;
+ } else {
+ temp2 = ((yuv420_uv_height+31)>>5)<<5;
+ /* even fomula: x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ if ((i+32)= 512) {
+ for (i=0; i>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+2;
+ temp1 = aligned_x_size>>5;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*2;
+ tiled_offset3 = tiled_offset+2048*3;
+ temp2 = 8;
+ } else {
+ temp2 = ((yuv420_uv_height+31)>>5)<<5;
+ /* even fomula: x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ if ((i+32)>5;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*6;
+ tiled_offset3 = tiled_offset+2048*7;
+ temp2 = 8;
+ } else {
+ temp1 = aligned_x_size>>6;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*2;
+ tiled_offset3 = tiled_offset+2048*3;
+ temp2 = 4;
+ }
+ }
+ temp1 = i&0x1F;
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i), yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i), nv12t_uv_src+tiled_offset+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i)+32*1, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i)+32*1, nv12t_uv_src+tiled_offset1+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i)+32*2, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i)+32*2, nv12t_uv_src+tiled_offset2+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i)+32*3, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i)+32*3, nv12t_uv_src+tiled_offset3+64*(temp1), 64);
+
+ tiled_offset = tiled_offset+temp2*2048;
+ tiled_offset1 = tiled_offset1+temp2*2048;
+ tiled_offset2 = tiled_offset2+temp2*2048;
+ tiled_offset3 = tiled_offset3+temp2*2048;
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i)+32*4, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i)+32*4, nv12t_uv_src+tiled_offset+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i)+32*5, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i)+32*5, nv12t_uv_src+tiled_offset1+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i)+32*6, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i)+32*6, nv12t_uv_src+tiled_offset2+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i)+32*7, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i)+32*7, nv12t_uv_src+tiled_offset3+64*(temp1), 64);
+ }
+ aligned_x_size = aligned_x_size+512;
+ }
+
+ if ((yuv420_width-aligned_x_size) >= 256) {
+ for (i=0; i>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+2;
+ temp1 = aligned_x_size>>5;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*2;
+ tiled_offset3 = tiled_offset+2048*3;
+ } else {
+ temp2 = ((yuv420_uv_height+31)>>5)<<5;
+ /* even fomula: x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ if ((i+32)>5;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*6;
+ tiled_offset3 = tiled_offset+2048*7;
+ } else {
+ temp1 = aligned_x_size>>6;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ tiled_offset2 = tiled_offset+2048*2;
+ tiled_offset3 = tiled_offset+2048*3;
+ }
+ }
+ temp1 = i&0x1F;
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i), yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i), nv12t_uv_src+tiled_offset+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i)+32*1, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i)+32*1, nv12t_uv_src+tiled_offset1+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i)+32*2, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i)+32*2, nv12t_uv_src+tiled_offset2+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i)+32*3, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i)+32*3, nv12t_uv_src+tiled_offset3+64*(temp1), 64);
+ }
+ aligned_x_size = aligned_x_size+256;
+ }
+
+ if ((yuv420_width-aligned_x_size) >= 128) {
+ for (i=0; i>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+2;
+ temp1 = aligned_x_size>>5;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ tiled_offset1 = tiled_offset+2048*1;
+ } else {
+ temp2 = ((yuv420_uv_height+31)>>5)<<5;
+ /* even fomula: x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ if ((i+32)>5;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ } else {
+ temp1 = aligned_x_size>>6;
+ tiled_offset = tiled_offset+(temp1<<11);
+ tiled_offset1 = tiled_offset+2048*1;
+ }
+ }
+ temp1 = i&0x1F;
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i), yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i), nv12t_uv_src+tiled_offset+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i)+32*1, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i)+32*1, nv12t_uv_src+tiled_offset1+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i+1), yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i+1), nv12t_uv_src+tiled_offset+64*(temp1+1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i+1)+32*1, yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i+1)+32*1, nv12t_uv_src+tiled_offset1+64*(temp1+1), 64);
+ }
+ aligned_x_size = aligned_x_size+128;
+ }
+
+ if ((yuv420_width-aligned_x_size) >= 64) {
+ for (i=0; i>6;
+ tiled_y_index = i>>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset+2;
+ temp1 = (tiled_x_index>>2)<<2;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ } else {
+ temp2 = ((yuv420_uv_height+31)>>5)<<5;
+ if ((i+32)>2)<<2+x_block_num*y */
+ temp1 = tiled_x_index+2;
+ temp1 = (temp1>>2)<<2;
+ tiled_offset = tiled_x_index+temp1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ } else {
+ /* even2 fomula: x+x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset<<11;
+ }
+ }
+ temp1 = i&0x1F;
+ temp2 = aligned_x_size&0x3F;
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i), yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i), nv12t_uv_src+tiled_offset+64*(temp1), 64);
+ csc_deinterleave_memcpy(yuv420_u_dest+aligned_x_size/2+yuv420_width/2*(i+1), yuv420_v_dest+aligned_x_size/2+yuv420_width/2*(i+1), nv12t_uv_src+tiled_offset+64*(temp1+1), 64);
+ }
+ aligned_x_size = aligned_x_size+64;
+ }
+
+ if (yuv420_width != aligned_x_size) {
+ for (i=0; i>6;
+ tiled_y_index = i>>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset+2;
+ temp1 = (tiled_x_index>>2)<<2;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ } else {
+ temp2 = ((yuv420_uv_height+31)>>5)<<5;
+ if ((i+32)>2)<<2+x_block_num*y */
+ temp1 = tiled_x_index+2;
+ temp1 = (temp1>>2)<<2;
+ tiled_offset = tiled_x_index+temp1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ } else {
+ /* even2 fomula: x+x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset<<11;
+ }
+ }
+ temp1 = i&0x1F;
+ temp2 = j&0x3F;
+ csc_deinterleave_memcpy(yuv420_u_dest+j/2+yuv420_width/2*(i), yuv420_v_dest+j/2+yuv420_width/2*(i), nv12t_uv_src+tiled_offset+temp2+64*(temp1), 4);
+ csc_deinterleave_memcpy(yuv420_u_dest+j/2+yuv420_width/2*(i+1), yuv420_v_dest+j/2+yuv420_width/2*(i+1), nv12t_uv_src+tiled_offset+temp2+64*(temp1+1), 4);
+ }
+ }
+ }
+}
+
+/*
+ * Converts linear data to tiled.
+ * 1. Y of YUV420P to Y of NV12T
+ * 2. Y of YUV420S to Y of NV12T
+ * 3. UV of YUV420S to UV of NV12T
+ *
+ * @param nv12t_dest
+ * Y or UV plane address of NV12T[out]
+ *
+ * @param yuv420_src
+ * Y or UV plane address of YUV420P(S)[in]
+ *
+ * @param yuv420_width
+ * Width of YUV420[in]
+ *
+ * @param yuv420_height
+ * Y: Height of YUV420, UV: Height/2 of YUV420[in]
+ */
+void csc_linear_to_tiled(char *nv12t_dest, char *yuv420_src, int yuv420_width, int yuv420_height)
+{
+ unsigned int i, j;
+ unsigned int tiled_x_index = 0, tiled_y_index = 0;
+ unsigned int aligned_x_size = 0, aligned_y_size = 0;
+ unsigned int tiled_offset = 0;
+ unsigned int temp1 = 0, temp2 = 0;
+
+ aligned_y_size = (yuv420_height>>5)<<5;
+ aligned_x_size = (yuv420_width>>6)<<6;
+
+ for (i=0; i>6;
+ tiled_y_index = i>>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset+2;
+ temp1 = (tiled_x_index>>2)<<2;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ } else {
+ temp2 = ((yuv420_height+31)>>5)<<5;
+ if ((i+32)>2)<<2+x_block_num*y */
+ temp1 = tiled_x_index+2;
+ temp1 = (temp1>>2)<<2;
+ tiled_offset = tiled_x_index+temp1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ } else {
+ /* even2 fomula: x+x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset<<11;
+ }
+ }
+
+ memcpy(nv12t_dest+tiled_offset, yuv420_src+j+yuv420_width*(i), 64);
+ memcpy(nv12t_dest+tiled_offset+64*1, yuv420_src+j+yuv420_width*(i+1), 64);
+ memcpy(nv12t_dest+tiled_offset+64*2, yuv420_src+j+yuv420_width*(i+2), 64);
+ memcpy(nv12t_dest+tiled_offset+64*3, yuv420_src+j+yuv420_width*(i+3), 64);
+ memcpy(nv12t_dest+tiled_offset+64*4, yuv420_src+j+yuv420_width*(i+4), 64);
+ memcpy(nv12t_dest+tiled_offset+64*5, yuv420_src+j+yuv420_width*(i+5), 64);
+ memcpy(nv12t_dest+tiled_offset+64*6, yuv420_src+j+yuv420_width*(i+6), 64);
+ memcpy(nv12t_dest+tiled_offset+64*7, yuv420_src+j+yuv420_width*(i+7), 64);
+ memcpy(nv12t_dest+tiled_offset+64*8, yuv420_src+j+yuv420_width*(i+8), 64);
+ memcpy(nv12t_dest+tiled_offset+64*9, yuv420_src+j+yuv420_width*(i+9), 64);
+ memcpy(nv12t_dest+tiled_offset+64*10, yuv420_src+j+yuv420_width*(i+10), 64);
+ memcpy(nv12t_dest+tiled_offset+64*11, yuv420_src+j+yuv420_width*(i+11), 64);
+ memcpy(nv12t_dest+tiled_offset+64*12, yuv420_src+j+yuv420_width*(i+12), 64);
+ memcpy(nv12t_dest+tiled_offset+64*13, yuv420_src+j+yuv420_width*(i+13), 64);
+ memcpy(nv12t_dest+tiled_offset+64*14, yuv420_src+j+yuv420_width*(i+14), 64);
+ memcpy(nv12t_dest+tiled_offset+64*15, yuv420_src+j+yuv420_width*(i+15), 64);
+ memcpy(nv12t_dest+tiled_offset+64*16, yuv420_src+j+yuv420_width*(i+16), 64);
+ memcpy(nv12t_dest+tiled_offset+64*17, yuv420_src+j+yuv420_width*(i+17), 64);
+ memcpy(nv12t_dest+tiled_offset+64*18, yuv420_src+j+yuv420_width*(i+18), 64);
+ memcpy(nv12t_dest+tiled_offset+64*19, yuv420_src+j+yuv420_width*(i+19), 64);
+ memcpy(nv12t_dest+tiled_offset+64*20, yuv420_src+j+yuv420_width*(i+20), 64);
+ memcpy(nv12t_dest+tiled_offset+64*21, yuv420_src+j+yuv420_width*(i+21), 64);
+ memcpy(nv12t_dest+tiled_offset+64*22, yuv420_src+j+yuv420_width*(i+22), 64);
+ memcpy(nv12t_dest+tiled_offset+64*23, yuv420_src+j+yuv420_width*(i+23), 64);
+ memcpy(nv12t_dest+tiled_offset+64*24, yuv420_src+j+yuv420_width*(i+24), 64);
+ memcpy(nv12t_dest+tiled_offset+64*25, yuv420_src+j+yuv420_width*(i+25), 64);
+ memcpy(nv12t_dest+tiled_offset+64*26, yuv420_src+j+yuv420_width*(i+26), 64);
+ memcpy(nv12t_dest+tiled_offset+64*27, yuv420_src+j+yuv420_width*(i+27), 64);
+ memcpy(nv12t_dest+tiled_offset+64*28, yuv420_src+j+yuv420_width*(i+28), 64);
+ memcpy(nv12t_dest+tiled_offset+64*29, yuv420_src+j+yuv420_width*(i+29), 64);
+ memcpy(nv12t_dest+tiled_offset+64*30, yuv420_src+j+yuv420_width*(i+30), 64);
+ memcpy(nv12t_dest+tiled_offset+64*31, yuv420_src+j+yuv420_width*(i+31), 64);
+ }
+ }
+
+ for (i=aligned_y_size; i>6;
+ tiled_y_index = i>>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset+2;
+ temp1 = (tiled_x_index>>2)<<2;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ } else {
+ temp2 = ((yuv420_height+31)>>5)<<5;
+ if ((i+32)>2)<<2+x_block_num*y */
+ temp1 = tiled_x_index+2;
+ temp1 = (temp1>>2)<<2;
+ tiled_offset = tiled_x_index+temp1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ } else {
+ /* even2 fomula: x+x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset<<11;
+ }
+ }
+
+ temp1 = i&0x1F;
+ memcpy(nv12t_dest+tiled_offset+64*(temp1), yuv420_src+j+yuv420_width*(i), 64);
+ memcpy(nv12t_dest+tiled_offset+64*(temp1+1), yuv420_src+j+yuv420_width*(i+1), 64);
+ memcpy(nv12t_dest+tiled_offset+64*(temp1+2), yuv420_src+j+yuv420_width*(i+2), 64);
+ memcpy(nv12t_dest+tiled_offset+64*(temp1+3), yuv420_src+j+yuv420_width*(i+3), 64);
+ }
+ }
+
+ for (i=0; i>6;
+ tiled_y_index = i>>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset+2;
+ temp1 = (tiled_x_index>>2)<<2;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ } else {
+ temp2 = ((yuv420_height+31)>>5)<<5;
+ if ((i+32)>2)<<2+x_block_num*y */
+ temp1 = tiled_x_index+2;
+ temp1 = (temp1>>2)<<2;
+ tiled_offset = tiled_x_index+temp1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ } else {
+ /* even2 fomula: x+x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset<<11;
+ }
+ }
+
+ temp1 = i&0x1F;
+ temp2 = j&0x3F;
+ memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1), yuv420_src+j+yuv420_width*(i), 4);
+ memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1+1), yuv420_src+j+yuv420_width*(i+1), 4);
+ memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1+2), yuv420_src+j+yuv420_width*(i+2), 4);
+ memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1+3), yuv420_src+j+yuv420_width*(i+3), 4);
+ }
+ }
+}
+
+/*
+ * Converts and Interleaves linear to tiled
+ * 1. UV of YUV420P to UV of NV12T
+ *
+ * @param nv12t_uv_dest
+ * UV plane address of NV12T[out]
+ *
+ * @param yuv420p_u_src
+ * U plane address of YUV420P[in]
+ *
+ * @param yuv420p_v_src
+ * V plane address of YUV420P[in]
+ *
+ * @param yuv420_width
+ * Width of YUV420[in]
+ *
+ * @param yuv420_uv_height
+ * Height/2 of YUV420[in]
+ */
+void csc_linear_to_tiled_interleave(char *nv12t_uv_dest, char *yuv420p_u_src, char *yuv420p_v_src, int yuv420_width, int yuv420_uv_height)
+{
+ unsigned int i, j;
+ unsigned int tiled_x_index = 0, tiled_y_index = 0;
+ unsigned int aligned_x_size = 0, aligned_y_size = 0;
+ unsigned int tiled_offset = 0;
+ unsigned int temp1 = 0, temp2 = 0;
+
+ aligned_y_size = (yuv420_uv_height>>5)<<5;
+ aligned_x_size = ((yuv420_width)>>6)<<6;
+
+ for (i=0; i>6;
+ tiled_y_index = i>>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset+2;
+ temp1 = (tiled_x_index>>2)<<2;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ } else {
+ temp2 = ((yuv420_uv_height+31)>>5)<<5;
+ if ((i+32)>2)<<2+x_block_num*y */
+ temp1 = tiled_x_index+2;
+ temp1 = (temp1>>2)<<2;
+ tiled_offset = tiled_x_index+temp1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ } else {
+ /* even2 fomula: x+x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset<<11;
+ }
+ }
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset, yuv420p_u_src+j/2+yuv420_width/2*(i), yuv420p_v_src+j/2+yuv420_width/2*(i), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*1, yuv420p_u_src+j/2+yuv420_width/2*(i+1), yuv420p_v_src+j/2+yuv420_width/2*(i+1), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*2, yuv420p_u_src+j/2+yuv420_width/2*(i+2), yuv420p_v_src+j/2+yuv420_width/2*(i+2), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*3, yuv420p_u_src+j/2+yuv420_width/2*(i+3), yuv420p_v_src+j/2+yuv420_width/2*(i+3), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*4, yuv420p_u_src+j/2+yuv420_width/2*(i+4), yuv420p_v_src+j/2+yuv420_width/2*(i+4), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*5, yuv420p_u_src+j/2+yuv420_width/2*(i+5), yuv420p_v_src+j/2+yuv420_width/2*(i+5), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*6, yuv420p_u_src+j/2+yuv420_width/2*(i+6), yuv420p_v_src+j/2+yuv420_width/2*(i+6), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*7, yuv420p_u_src+j/2+yuv420_width/2*(i+7), yuv420p_v_src+j/2+yuv420_width/2*(i+7), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*8, yuv420p_u_src+j/2+yuv420_width/2*(i+8), yuv420p_v_src+j/2+yuv420_width/2*(i+8), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*9, yuv420p_u_src+j/2+yuv420_width/2*(i+9), yuv420p_v_src+j/2+yuv420_width/2*(i+9), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*10, yuv420p_u_src+j/2+yuv420_width/2*(i+10), yuv420p_v_src+j/2+yuv420_width/2*(i+10), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*11, yuv420p_u_src+j/2+yuv420_width/2*(i+11), yuv420p_v_src+j/2+yuv420_width/2*(i+11), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*12, yuv420p_u_src+j/2+yuv420_width/2*(i+12), yuv420p_v_src+j/2+yuv420_width/2*(i+12), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*13, yuv420p_u_src+j/2+yuv420_width/2*(i+13), yuv420p_v_src+j/2+yuv420_width/2*(i+13), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*14, yuv420p_u_src+j/2+yuv420_width/2*(i+14), yuv420p_v_src+j/2+yuv420_width/2*(i+14), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*15, yuv420p_u_src+j/2+yuv420_width/2*(i+15), yuv420p_v_src+j/2+yuv420_width/2*(i+15), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*16, yuv420p_u_src+j/2+yuv420_width/2*(i+16), yuv420p_v_src+j/2+yuv420_width/2*(i+16), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*17, yuv420p_u_src+j/2+yuv420_width/2*(i+17), yuv420p_v_src+j/2+yuv420_width/2*(i+17), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*18, yuv420p_u_src+j/2+yuv420_width/2*(i+18), yuv420p_v_src+j/2+yuv420_width/2*(i+18), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*19, yuv420p_u_src+j/2+yuv420_width/2*(i+19), yuv420p_v_src+j/2+yuv420_width/2*(i+19), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*20, yuv420p_u_src+j/2+yuv420_width/2*(i+20), yuv420p_v_src+j/2+yuv420_width/2*(i+20), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*21, yuv420p_u_src+j/2+yuv420_width/2*(i+21), yuv420p_v_src+j/2+yuv420_width/2*(i+21), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*22, yuv420p_u_src+j/2+yuv420_width/2*(i+22), yuv420p_v_src+j/2+yuv420_width/2*(i+22), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*23, yuv420p_u_src+j/2+yuv420_width/2*(i+23), yuv420p_v_src+j/2+yuv420_width/2*(i+23), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*24, yuv420p_u_src+j/2+yuv420_width/2*(i+24), yuv420p_v_src+j/2+yuv420_width/2*(i+24), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*25, yuv420p_u_src+j/2+yuv420_width/2*(i+25), yuv420p_v_src+j/2+yuv420_width/2*(i+25), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*26, yuv420p_u_src+j/2+yuv420_width/2*(i+26), yuv420p_v_src+j/2+yuv420_width/2*(i+26), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*27, yuv420p_u_src+j/2+yuv420_width/2*(i+27), yuv420p_v_src+j/2+yuv420_width/2*(i+27), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*28, yuv420p_u_src+j/2+yuv420_width/2*(i+28), yuv420p_v_src+j/2+yuv420_width/2*(i+28), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*29, yuv420p_u_src+j/2+yuv420_width/2*(i+29), yuv420p_v_src+j/2+yuv420_width/2*(i+29), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*30, yuv420p_u_src+j/2+yuv420_width/2*(i+30), yuv420p_v_src+j/2+yuv420_width/2*(i+30), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*31, yuv420p_u_src+j/2+yuv420_width/2*(i+31), yuv420p_v_src+j/2+yuv420_width/2*(i+31), 32);
+ }
+ }
+
+ for (i=aligned_y_size; i>6;
+ tiled_y_index = i>>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset+2;
+ temp1 = (tiled_x_index>>2)<<2;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ } else {
+ temp2 = ((yuv420_uv_height+31)>>5)<<5;
+ if ((i+32)>2)<<2+x_block_num*y */
+ temp1 = tiled_x_index+2;
+ temp1 = (temp1>>2)<<2;
+ tiled_offset = tiled_x_index+temp1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ } else {
+ /* even2 fomula: x+x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset<<11;
+ }
+ }
+ temp1 = i&0x1F;
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*(temp1), yuv420p_u_src+j/2+yuv420_width/2*(i), yuv420p_v_src+j/2+yuv420_width/2*(i), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*(temp1+1), yuv420p_u_src+j/2+yuv420_width/2*(i+1), yuv420p_v_src+j/2+yuv420_width/2*(i+1), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*(temp1+2), yuv420p_u_src+j/2+yuv420_width/2*(i+2), yuv420p_v_src+j/2+yuv420_width/2*(i+2), 32);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*(temp1+3), yuv420p_u_src+j/2+yuv420_width/2*(i+3), yuv420p_v_src+j/2+yuv420_width/2*(i+3), 32);
+ }
+ }
+
+ for (i=0; i>6;
+ tiled_y_index = i>>5;
+ if (tiled_y_index & 0x1) {
+ /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
+ tiled_offset = tiled_y_index-1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset+2;
+ temp1 = (tiled_x_index>>2)<<2;
+ tiled_offset = tiled_offset+temp1;
+ tiled_offset = tiled_offset<<11;
+ } else {
+ temp2 = ((yuv420_uv_height+31)>>5)<<5;
+ if ((i+32)>2)<<2+x_block_num*y */
+ temp1 = tiled_x_index+2;
+ temp1 = (temp1>>2)<<2;
+ tiled_offset = tiled_x_index+temp1;
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset<<11;
+ } else {
+ /* even2 fomula: x+x_block_num*y */
+ temp1 = ((yuv420_width+127)>>7)<<7;
+ tiled_offset = tiled_y_index*(temp1>>6);
+ tiled_offset = tiled_offset+tiled_x_index;
+ tiled_offset = tiled_offset<<11;
+ }
+ }
+ temp1 = i&0x1F;
+ temp2 = j&0x3F;
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+temp2+64*(temp1), yuv420p_u_src+j/2+yuv420_width/2*(i), yuv420p_v_src+j/2+yuv420_width/2*(i), 2);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+temp2+64*(temp1+1), yuv420p_u_src+j/2+yuv420_width/2*(i+1), yuv420p_v_src+j/2+yuv420_width/2*(i+1), 2);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+temp2+64*(temp1+2), yuv420p_u_src+j/2+yuv420_width/2*(i+2), yuv420p_v_src+j/2+yuv420_width/2*(i+2), 2);
+ csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+temp2+64*(temp1+3), yuv420p_u_src+j/2+yuv420_width/2*(i+3), yuv420p_v_src+j/2+yuv420_width/2*(i+3), 2);
+ }
+ }
+}
+
diff --git a/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_deinterleave_memcpy.s b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_deinterleave_memcpy.s
new file mode 100644
index 0000000..5b55080
--- /dev/null
+++ b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_deinterleave_memcpy.s
@@ -0,0 +1,128 @@
+/*
+ *
+ * Copyright 2011 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file csc_deinterleave_memcpy.s
+ * @brief SEC_OMX specific define
+ * @author ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ * 2011.7.01 : Create
+ */
+ .arch armv7-a
+ .text
+ .global csc_deinterleave_memcpy
+ .type csc_deinterleave_memcpy, %function
+csc_deinterleave_memcpy:
+ .fnstart
+
+ @r0 dest1
+ @r1 dest2
+ @r2 src
+ @r3 src_size
+ @r4 i
+ @r5 temp1
+ @r6 temp2
+ @r7 temp3
+
+ stmfd sp!, {r4-r12,r14} @ backup registers
+
+ mov r4, #0
+ cmp r3, #256
+ blt LINEAR_SIZE_128
+
+ bic r5, r3, #0xFF
+LINEAR_SIZE_256_LOOP:
+ pld [r2, #64]
+ vld2.8 {q0, q1}, [r2]!
+ pld [r2, #64]
+ vld2.8 {q2, q3}, [r2]!
+ pld [r2, #64]
+ vld2.8 {q4, q5}, [r2]!
+ pld [r2, #64]
+ vld2.8 {q6, q7}, [r2]!
+ pld [r2, #64]
+ vld2.8 {q8, q9}, [r2]!
+ pld [r2, #64]
+ vld2.8 {q10, q11}, [r2]!
+ vld2.8 {q12, q13}, [r2]!
+ vld2.8 {q14, q15}, [r2]!
+
+ vst1.8 {q0}, [r0]!
+ vst1.8 {q2}, [r0]!
+ vst1.8 {q4}, [r0]!
+ vst1.8 {q6}, [r0]!
+ vst1.8 {q8}, [r0]!
+ vst1.8 {q10}, [r0]!
+ vst1.8 {q12}, [r0]!
+ vst1.8 {q14}, [r0]!
+
+ vst1.8 {q1}, [r1]!
+ vst1.8 {q3}, [r1]!
+ vst1.8 {q5}, [r1]!
+ vst1.8 {q7}, [r1]!
+ vst1.8 {q9}, [r1]!
+ vst1.8 {q11}, [r1]!
+ vst1.8 {q13}, [r1]!
+ vst1.8 {q15}, [r1]!
+
+ add r4, #256
+ cmp r4, r5
+ blt LINEAR_SIZE_256_LOOP
+
+LINEAR_SIZE_128:
+ sub r5, r3, r4
+ cmp r5, #64
+ blt LINEAR_SIZE_4
+ pld [r2, #64]
+ vld2.8 {q0, q1}, [r2]!
+ pld [r2, #64]
+ vld2.8 {q2, q3}, [r2]!
+ vld2.8 {q4, q5}, [r2]!
+ vld2.8 {q6, q7}, [r2]!
+
+ vst1.8 {q0}, [r0]!
+ vst1.8 {q4}, [r0]!
+ vst1.8 {q2}, [r0]!
+ vst1.8 {q6}, [r0]!
+
+ vst1.8 {q1}, [r1]!
+ vst1.8 {q3}, [r1]!
+ vst1.8 {q5}, [r1]!
+ vst1.8 {q7}, [r1]!
+
+ add r4, #128
+
+LINEAR_SIZE_4:
+ ldrb r6, [r2], #1
+ ldrb r7, [r2], #1
+ ldrb r8, [r2], #1
+ ldrb r9, [r2], #1
+
+ strb r6, [r0], #1
+ strb r8, [r0], #1
+ strb r7, [r1], #1
+ strb r9, [r1], #1
+
+ add r4, #4
+ cmp r4, r3
+ blt LINEAR_SIZE_4
+
+RESTORE_REG:
+ ldmfd sp!, {r4-r12,r15} @ restore registers
+ .fnend
+
diff --git a/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_interleave_memcpy.s b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_interleave_memcpy.s
new file mode 100644
index 0000000..54f4436
--- /dev/null
+++ b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_interleave_memcpy.s
@@ -0,0 +1,133 @@
+/*
+ *
+ * Copyright 2011 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file csc_interleave_memcpy.s
+ * @brief SEC_OMX specific define
+ * @author ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ * 2011.7.01 : Create
+ */
+ .arch armv7-a
+ .text
+ .global csc_interleave_memcpy
+ .type csc_interleave_memcpy, %function
+csc_interleave_memcpy:
+ .fnstart
+
+ @r0 dest
+ @r1 src1
+ @r2 src2
+ @r3 src_size
+ @r4 i
+ @r5 temp1
+ @r6 temp2
+ @r7 temp3
+ @r8 temp2
+ @r9 temp3
+
+ stmfd sp!, {r4-r12,r14} @ backup registers
+
+ mov r4, #0
+ cmp r3, #128
+ blt LINEAR_SIZE_64
+
+ bic r5, r3, #0x2F
+LINEAR_SIZE_128_LOOP:
+ pld [r1, #64]
+ vld1.8 {q0}, [r1]!
+ vld1.8 {q2}, [r1]!
+ vld1.8 {q4}, [r1]!
+ vld1.8 {q6}, [r1]!
+ pld [r2]
+ vld1.8 {q8}, [r1]!
+ vld1.8 {q10}, [r1]!
+ vld1.8 {q12}, [r1]!
+ vld1.8 {q14}, [r1]!
+ pld [r2, #64]
+ vld1.8 {q1}, [r2]!
+ vld1.8 {q3}, [r2]!
+ vld1.8 {q5}, [r2]!
+ vld1.8 {q7}, [r2]!
+ vld1.8 {q9}, [r2]!
+ vld1.8 {q11}, [r2]!
+ vld1.8 {q13}, [r2]!
+ vld1.8 {q15}, [r2]!
+
+ vst2.8 {q0, q1}, [r0]!
+ vst2.8 {q2, q3}, [r0]!
+ vst2.8 {q4, q5}, [r0]!
+ vst2.8 {q6, q7}, [r0]!
+ vst2.8 {q8, q9}, [r0]!
+ vst2.8 {q10, q11}, [r0]!
+ pld [r1]
+ vst2.8 {q12, q13}, [r0]!
+ vst2.8 {q14, q15}, [r0]!
+
+ add r4, #128
+ cmp r4, r5
+ blt LINEAR_SIZE_128_LOOP
+
+LINEAR_SIZE_64:
+ sub r5, r3, r4
+ cmp r5, #64
+ blt LINEAR_SIZE_2
+LINEAR_SIZE_64_LOOP:
+ pld [r2]
+ vld1.8 {q0}, [r1]!
+ vld1.8 {q2}, [r1]!
+ vld1.8 {q4}, [r1]!
+ vld1.8 {q6}, [r1]!
+ vld1.8 {q1}, [r2]!
+ vld1.8 {q3}, [r2]!
+ vld1.8 {q5}, [r2]!
+ vld1.8 {q7}, [r2]!
+
+ vst2.8 {q0, q1}, [r0]!
+ vst2.8 {q2, q3}, [r0]!
+ pld [r1]
+ vst2.8 {q4, q5}, [r0]!
+ vst2.8 {q6, q7}, [r0]!
+
+ add r4, #64
+ cmp r4, r3
+ blt LINEAR_SIZE_64_LOOP
+
+LINEAR_SIZE_2:
+ sub r5, r3, r4
+ cmp r5, #2
+ blt RESTORE_REG
+LINEAR_SIZE_2_LOOP:
+ ldrb r6, [r1], #1
+ ldrb r7, [r2], #1
+ ldrb r8, [r1], #1
+ ldrb r9, [r2], #1
+
+ strb r6, [r0], #1
+ strb r7, [r0], #1
+ strb r8, [r0], #1
+ strb r9, [r0], #1
+
+ add r4, #2
+ cmp r4, r3
+ blt LINEAR_SIZE_2_LOOP
+
+RESTORE_REG:
+ ldmfd sp!, {r4-r12,r15} @ restore registers
+ .fnend
+
diff --git a/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_nv12t_yuv420_uv_neon.s b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_nv12t_yuv420_uv_neon.s
new file mode 100644
index 0000000..08e359c
--- /dev/null
+++ b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_nv12t_yuv420_uv_neon.s
@@ -0,0 +1,768 @@
+/*
+ *
+ * Copyright 2011 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file csc_nv12t_yuv420_uv_neon.s
+ * @brief SEC_OMX specific define
+ * @author ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ * 2011.7.01 : Create
+ */
+
+/*
+ * Converts and Deinterleaves tiled data to linear
+ * 1. UV of NV12T to UV of YUV420P
+ *
+ * @param yuv420_u_dest
+ * U plane address of YUV420P[out]
+ *
+ * @param yuv420_v_dest
+ * V plane address of YUV420P[out]
+ *
+ * @param nv12t_src
+ * UV plane address of NV12T[in]
+ *
+ * @param yuv420_width
+ * Width of YUV420[in]
+ *
+ * @param yuv420_uv_height
+ * Height/2 of YUV420[in]
+ */
+
+ .arch armv7-a
+ .text
+ .global csc_tiled_to_linear_deinterleave
+ .type csc_tiled_to_linear_deinterleave, %function
+csc_tiled_to_linear_deinterleave:
+ .fnstart
+
+ @r0 linear_u_dest
+ @r1 linear_v_dest
+ @r2 tiled_uv_src
+ @r3 linear_x_size
+ @r4 linear_y_size
+ @r5 j
+ @r6 i
+ @r7 tiled_addr
+ @r8 linear_addr
+ @r9 aligned_x_size
+ @r10 temp1
+ @r11 temp2
+ @r12 temp3
+ @r14 temp4
+
+ stmfd sp!, {r4-r12,r14} @ backup registers
+
+ ldr r4, [sp, #40] @ load linear_y_size to r4
+
+ mov r9, #0
+
+LINEAR_X_SIZE_1024:
+ cmp r3, #1024
+ blt LINEAR_X_SIZE_512
+
+ mov r6, #0
+LINEAR_X_SIZE_1024_LOOP:
+ mov r7, #0 @ tiled_offset = 0@
+ mov r5, r6, asr #5 @ tiled_y_index = i>>5@
+ and r10, r5, #0x1
+ cmp r10, #0x1
+ bne LINEAR_X_SIZE_1024_LOOP_EVEN
+LINEAR_X_SIZE_1024_LOOP_ODD:
+ sub r7, r5, #1 @ tiled_offset = tiled_y_index-1@
+ add r10, r3, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6)@
+ mul r7, r7, r10
+ mov r5, #8
+ mov r5, r5, lsl #11
+ sub r5, r5, #32
+ add r7, r7, #2 @ tiled_offset = tiled_offset+2@
+ mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11@
+ add r11, r7, #2048
+ add r12, r7, #4096
+ add r14, r7, #6144
+ b LINEAR_X_SIZE_1024_LOOP_MEMCPY
+
+LINEAR_X_SIZE_1024_LOOP_EVEN:
+ add r11, r4, #31 @ temp2 = ((linear_y_size+31)>>5)<<5@
+ bic r11, r11, #0x1F
+ add r10, r3, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_y_index*(temp1>>6)@
+ mul r7, r5, r10
+ add r12, r6, #32
+ cmp r12, r11
+ mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11@
+ add r11, r7, #2048
+ movlt r5, #8
+ addlt r12, r7, #12288
+ addlt r14, r7, #14336
+ movge r5, #4
+ addge r12, r7, #2048
+ addge r14, r7, #2048
+ mov r5, r5, lsl #11
+ sub r5, r5, #32
+
+LINEAR_X_SIZE_1024_LOOP_MEMCPY:
+ and r10, r6, #0x1F
+ mov r10, r10, lsl #6
+ add r10, r2, r10
+
+ add r7, r7, r10 @ tiled_addr = tiled_src+64*(temp1)
+ add r11, r11, r10 @ tiled_addr1 = tiled_src+64*(temp1)
+ pld [r11]
+ vld2.8 {q0, q1}, [r7]!
+ pld [r11, #32]
+ add r12, r12, r10 @ tiled_addr2 = tiled_src+64*(temp1)
+ vld2.8 {q2, q3}, [r7], r5
+ pld [r12]
+ vld2.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ add r14, r14, r10 @ tiled_addr3 = tiled_src+64*(temp1)
+ vld2.8 {q6, q7}, [r11], r5
+ pld [r14]
+ vld2.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ mov r10, r3, asr #1
+ vld2.8 {q10, q11}, [r12], r5
+ mul r10, r10, r6
+ vld2.8 {q12, q13}, [r14]!
+ vld2.8 {q14, q15}, [r14], r5
+
+ add r8, r0, r10
+ vst1.8 {q0}, [r8]!
+ vst1.8 {q2}, [r8]!
+ vst1.8 {q4}, [r8]!
+ vst1.8 {q6}, [r8]!
+ vst1.8 {q8}, [r8]!
+ vst1.8 {q10}, [r8]!
+ vst1.8 {q12}, [r8]!
+ vst1.8 {q14}, [r8]!
+
+ add r10, r1, r10
+ vst1.8 {q1}, [r10]!
+ vst1.8 {q3}, [r10]!
+ vst1.8 {q5}, [r10]!
+ vst1.8 {q7}, [r10]!
+ vst1.8 {q9}, [r10]!
+ vst1.8 {q11}, [r10]!
+ pld [r7]
+ vst1.8 {q13}, [r10]!
+ pld [r7, #32]
+ vst1.8 {q15}, [r10]!
+
+ pld [r11]
+ vld2.8 {q0, q1}, [r7]!
+ pld [r11, #32]
+ vld2.8 {q2, q3}, [r7], r5
+ pld [r12]
+ vld2.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ vld2.8 {q6, q7}, [r11], r5
+ pld [r14]
+ vld2.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ vld2.8 {q10, q11}, [r12], r5
+ vld2.8 {q12, q13}, [r14]!
+ vld2.8 {q14, q15}, [r14], r5
+
+ vst1.8 {q0}, [r8]!
+ vst1.8 {q2}, [r8]!
+ vst1.8 {q4}, [r8]!
+ vst1.8 {q6}, [r8]!
+ vst1.8 {q8}, [r8]!
+ vst1.8 {q10}, [r8]!
+ vst1.8 {q12}, [r8]!
+ vst1.8 {q14}, [r8]!
+
+ vst1.8 {q1}, [r10]!
+ vst1.8 {q3}, [r10]!
+ vst1.8 {q5}, [r10]!
+ vst1.8 {q7}, [r10]!
+ vst1.8 {q9}, [r10]!
+ vst1.8 {q11}, [r10]!
+ pld [r7]
+ vst1.8 {q13}, [r10]!
+ pld [r7, #32]
+ vst1.8 {q15}, [r10]!
+
+ pld [r11]
+ vld2.8 {q0, q1}, [r7]!
+ pld [r11, #32]
+ vld2.8 {q2, q3}, [r7], r5
+ pld [r12]
+ vld2.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ vld2.8 {q6, q7}, [r11], r5
+ pld [r14]
+ vld2.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ vld2.8 {q10, q11}, [r12], r5
+ vld2.8 {q12, q13}, [r14]!
+ vld2.8 {q14, q15}, [r14], r5
+
+ vst1.8 {q0}, [r8]!
+ vst1.8 {q2}, [r8]!
+ vst1.8 {q4}, [r8]!
+ vst1.8 {q6}, [r8]!
+ vst1.8 {q8}, [r8]!
+ vst1.8 {q10}, [r8]!
+ vst1.8 {q12}, [r8]!
+ vst1.8 {q14}, [r8]!
+
+ vst1.8 {q1}, [r10]!
+ vst1.8 {q3}, [r10]!
+ vst1.8 {q5}, [r10]!
+ vst1.8 {q7}, [r10]!
+ vst1.8 {q9}, [r10]!
+ vst1.8 {q11}, [r10]!
+ pld [r7]
+ vst1.8 {q13}, [r10]!
+ pld [r7, #32]
+ vst1.8 {q15}, [r10]!
+
+ pld [r11]
+ vld2.8 {q0, q1}, [r7]!
+ pld [r11, #32]
+ vld2.8 {q2, q3}, [r7]
+ pld [r12]
+ vld2.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ vld2.8 {q6, q7}, [r11]
+ pld [r14]
+ vld2.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ vld2.8 {q10, q11}, [r12]
+ vld2.8 {q12, q13}, [r14]!
+ vld2.8 {q14, q15}, [r14]
+
+ vst1.8 {q0}, [r8]!
+ vst1.8 {q2}, [r8]!
+ vst1.8 {q4}, [r8]!
+ vst1.8 {q6}, [r8]!
+ vst1.8 {q8}, [r8]!
+ vst1.8 {q10}, [r8]!
+ vst1.8 {q12}, [r8]!
+ vst1.8 {q14}, [r8]!
+
+ vst1.8 {q1}, [r10]!
+ vst1.8 {q3}, [r10]!
+ vst1.8 {q5}, [r10]!
+ vst1.8 {q7}, [r10]!
+ vst1.8 {q9}, [r10]!
+ vst1.8 {q11}, [r10]!
+ add r6, #1
+ vst1.8 {q13}, [r10]!
+ cmp r6, r4
+ vst1.8 {q15}, [r10]!
+
+ blt LINEAR_X_SIZE_1024_LOOP
+
+ mov r9, #1024
+
+LINEAR_X_SIZE_512:
+ sub r10, r3, r9
+ cmp r10, #512
+ blt LINEAR_X_SIZE_256
+
+ mov r6, #0
+LINEAR_X_SIZE_512_LOOP:
+ mov r7, #0 @ tiled_offset = 0@
+ mov r5, r6, asr #5 @ tiled_y_index = i>>5@
+ and r10, r5, #0x1
+ cmp r10, #0x1
+ bne LINEAR_X_SIZE_512_LOOP_EVEN
+LINEAR_X_SIZE_512_LOOP_ODD:
+ sub r7, r5, #1 @ tiled_offset = tiled_y_index-1@
+ add r10, r3, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6)@
+ mul r7, r7, r10
+ mov r5, #8
+ mov r5, r5, lsl #11
+ add r7, r7, #2 @ tiled_offset = tiled_offset+2@
+ mov r10, r9, asr #5
+ add r7, r7, r10
+ mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11@
+ add r11, r7, #2048
+ add r12, r7, #4096
+ add r14, r7, #6144
+ sub r5, r5, #32
+ b LINEAR_X_SIZE_512_LOOP_MEMCPY
+
+LINEAR_X_SIZE_512_LOOP_EVEN:
+ add r11, r4, #31 @ temp2 = ((linear_y_size+31)>>5)<<5@
+ bic r11, r11, #0x1F
+ add r10, r3, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_y_index*(temp1>>6)@
+ mul r7, r5, r10
+ add r12, r6, #32
+ cmp r12, r11
+ mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11@
+ movlt r5, #8
+ movlt r10, r9, asr #5
+ movge r10, r9, asr #6
+ add r7, r7, r10, lsl #11
+ add r11, r7, #2048
+ addlt r12, r7, #12288
+ addlt r14, r7, #14336
+ movge r5, #4
+ addge r12, r7, #4096
+ addge r14, r7, #6144
+ mov r5, r5, lsl #11
+ sub r5, r5, #32
+
+LINEAR_X_SIZE_512_LOOP_MEMCPY:
+ and r10, r6, #0x1F
+ mov r10, r10, lsl #6
+ add r10, r2, r10
+
+ add r7, r7, r10 @ tiled_addr = tiled_src+64*(temp1)
+ add r11, r11, r10 @ tiled_addr1 = tiled_src+64*(temp1)
+ pld [r11]
+ vld2.8 {q0, q1}, [r7]!
+ pld [r11, #32]
+ add r12, r12, r10 @ tiled_addr2 = tiled_src+64*(temp1)
+ vld2.8 {q2, q3}, [r7], r5
+ pld [r12]
+ vld2.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ add r14, r14, r10 @ tiled_addr3 = tiled_src+64*(temp1)
+ vld2.8 {q6, q7}, [r11], r5
+ pld [r14]
+ mov r10, r3, asr #1
+ vld2.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ mul r10, r10, r6
+ vld2.8 {q10, q11}, [r12], r5
+ add r8, r0, r10
+ vld2.8 {q12, q13}, [r14]!
+ add r8, r8, r9, asr #1
+ vld2.8 {q14, q15}, [r14], r5
+
+ vst1.8 {q0}, [r8]!
+ vst1.8 {q2}, [r8]!
+ vst1.8 {q4}, [r8]!
+ vst1.8 {q6}, [r8]!
+ vst1.8 {q8}, [r8]!
+ vst1.8 {q10}, [r8]!
+ vst1.8 {q12}, [r8]!
+ add r10, r1, r10
+ vst1.8 {q14}, [r8]!
+
+ add r10, r10, r9, asr #1
+ vst1.8 {q1}, [r10]!
+ vst1.8 {q3}, [r10]!
+ vst1.8 {q5}, [r10]!
+ vst1.8 {q7}, [r10]!
+ vst1.8 {q9}, [r10]!
+ vst1.8 {q11}, [r10]!
+ pld [r7]
+ vst1.8 {q13}, [r10]!
+ pld [r7, #32]
+ vst1.8 {q15}, [r10]!
+
+ pld [r11]
+ vld2.8 {q0, q1}, [r7]!
+ pld [r11, #32]
+ vld2.8 {q2, q3}, [r7]
+ pld [r12]
+ vld2.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ vld2.8 {q6, q7}, [r11]
+ pld [r14]
+ vld2.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ vld2.8 {q10, q11}, [r12]
+ vld2.8 {q12, q13}, [r14]!
+ vld2.8 {q14, q15}, [r14]
+
+ vst1.8 {q0}, [r8]!
+ vst1.8 {q2}, [r8]!
+ vst1.8 {q4}, [r8]!
+ vst1.8 {q6}, [r8]!
+ vst1.8 {q8}, [r8]!
+ vst1.8 {q10}, [r8]!
+ vst1.8 {q12}, [r8]!
+ vst1.8 {q14}, [r8]!
+
+ vst1.8 {q1}, [r10]!
+ vst1.8 {q3}, [r10]!
+ vst1.8 {q5}, [r10]!
+ vst1.8 {q7}, [r10]!
+ vst1.8 {q9}, [r10]!
+ vst1.8 {q11}, [r10]!
+ add r6, #1
+ vst1.8 {q13}, [r10]!
+ cmp r6, r4
+ vst1.8 {q15}, [r10]!
+
+ blt LINEAR_X_SIZE_512_LOOP
+
+ add r9, r9, #512
+
+LINEAR_X_SIZE_256:
+ sub r10, r3, r9
+ cmp r10, #256
+ blt LINEAR_X_SIZE_128
+
+ mov r6, #0
+LINEAR_X_SIZE_256_LOOP:
+ mov r7, #0 @ tiled_offset = 0@
+ mov r5, r6, asr #5 @ tiled_y_index = i>>5@
+ and r10, r5, #0x1
+ cmp r10, #0x1
+ bne LINEAR_X_SIZE_256_LOOP_EVEN
+LINEAR_X_SIZE_256_LOOP_ODD:
+ sub r7, r5, #1 @ tiled_offset = tiled_y_index-1@
+ add r10, r3, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6)@
+ mul r7, r7, r10
+ add r7, r7, #2 @ tiled_offset = tiled_offset+2@
+ mov r10, r9, asr #5
+ add r7, r7, r10
+ mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11@
+ add r11, r7, #2048
+ add r12, r7, #4096
+ add r14, r7, #6144
+ b LINEAR_X_SIZE_256_LOOP_MEMCPY
+
+LINEAR_X_SIZE_256_LOOP_EVEN:
+ add r11, r4, #31 @ temp2 = ((linear_y_size+31)>>5)<<5@
+ bic r11, r11, #0x1F
+ add r10, r3, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_y_index*(temp1>>6)@
+ mul r7, r5, r10
+ mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11@
+ add r12, r6, #32
+ cmp r12, r11
+ movlt r10, r9, asr #5
+ addlt r7, r7, r10, lsl #11
+ addlt r11, r7, #2048
+ addlt r12, r7, #12288
+ addlt r14, r7, #14336
+ movge r10, r9, asr #6
+ addge r7, r7, r10, lsl #11
+ addge r11, r7, #2048
+ addge r12, r7, #4096
+ addge r14, r7, #6144
+
+LINEAR_X_SIZE_256_LOOP_MEMCPY:
+ and r10, r6, #0x1F
+ mov r10, r10, lsl #6
+ add r10, r2, r10
+
+ add r7, r7, r10 @ tiled_addr = tiled_src+64*(temp1)
+ add r11, r11, r10 @ tiled_addr1 = tiled_src+64*(temp1)
+ pld [r11]
+ vld2.8 {q0, q1}, [r7]!
+ pld [r11, #32]
+ add r12, r12, r10 @ tiled_addr2 = tiled_src+64*(temp1)
+ vld2.8 {q2, q3}, [r7]
+ pld [r12]
+ vld2.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ add r14, r14, r10 @ tiled_addr3 = tiled_src+64*(temp1)
+ vld2.8 {q6, q7}, [r11]
+ pld [r14]
+ vld2.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ mov r10, r3, asr #1
+ vld2.8 {q10, q11}, [r12]
+ mul r10, r10, r6
+ vld2.8 {q12, q13}, [r14]!
+ add r8, r0, r10
+ vld2.8 {q14, q15}, [r14]
+
+ add r8, r8, r9, asr #1
+ vst1.8 {q0}, [r8]!
+ vst1.8 {q2}, [r8]!
+ vst1.8 {q4}, [r8]!
+ vst1.8 {q6}, [r8]!
+ vst1.8 {q8}, [r8]!
+ vst1.8 {q10}, [r8]!
+ vst1.8 {q12}, [r8]!
+ add r10, r1, r10
+ vst1.8 {q14}, [r8]!
+
+ add r10, r10, r9, asr #1
+ vst1.8 {q1}, [r10]!
+ vst1.8 {q3}, [r10]!
+ vst1.8 {q5}, [r10]!
+ vst1.8 {q7}, [r10]!
+ vst1.8 {q9}, [r10]!
+ vst1.8 {q11}, [r10]!
+ add r6, #1
+ vst1.8 {q13}, [r10]!
+ cmp r6, r4
+ vst1.8 {q15}, [r10]!
+ blt LINEAR_X_SIZE_256_LOOP
+
+ add r9, r9, #256
+
+LINEAR_X_SIZE_128:
+ sub r10, r3, r9
+ cmp r10, #128
+ blt LINEAR_X_SIZE_64
+
+ mov r6, #0
+LINEAR_X_SIZE_128_LOOP:
+ mov r7, #0 @ tiled_offset = 0@
+ mov r5, r6, asr #5 @ tiled_y_index = i>>5@
+ and r10, r5, #0x1
+ cmp r10, #0x1
+ bne LINEAR_X_SIZE_128_LOOP_EVEN
+LINEAR_X_SIZE_128_LOOP_ODD:
+ sub r7, r5, #1 @ tiled_offset = tiled_y_index-1@
+ add r10, r3, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6)@
+ mul r7, r7, r10
+ add r7, r7, #2 @ tiled_offset = tiled_offset+2@
+ mov r10, r9, asr #5
+ add r7, r7, r10
+ mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11@
+ add r11, r7, #2048
+ b LINEAR_X_SIZE_128_LOOP_MEMCPY
+
+LINEAR_X_SIZE_128_LOOP_EVEN:
+ add r11, r4, #31 @ temp2 = ((linear_y_size+31)>>5)<<5@
+ bic r11, r11, #0x1F
+ add r10, r3, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_y_index*(temp1>>6)@
+ mul r7, r5, r10
+ mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11@
+ add r12, r6, #32
+ cmp r12, r11
+ movlt r10, r9, asr #5
+ movge r10, r9, asr #6
+ add r7, r7, r10, lsl #11
+ add r11, r7, #2048
+
+LINEAR_X_SIZE_128_LOOP_MEMCPY:
+ and r10, r6, #0x1F
+ mov r10, r10, lsl #6
+ add r10, r2, r10
+
+ add r7, r7, r10 @ tiled_addr = tiled_src+64*(temp1)
+ add r11, r11, r10 @ tiled_addr1 = tiled_src+64*(temp1)
+ pld [r11]
+ vld2.8 {q0, q1}, [r7]!
+ pld [r11, #32]
+ vld2.8 {q2, q3}, [r7]!
+ pld [r7]
+ vld2.8 {q4, q5}, [r11]!
+ mov r10, r3, asr #1
+ pld [r7, #32]
+ vld2.8 {q6, q7}, [r11]!
+ mul r10, r10, r6
+ pld [r11]
+ vld2.8 {q8, q9}, [r7]!
+ add r10, r10, r9, asr #1
+ pld [r11, #32]
+ vld2.8 {q10, q11}, [r7]!
+ add r8, r0, r10
+ vld2.8 {q12, q13}, [r11]!
+ mov r14, r3, asr #1
+ vld2.8 {q14, q15}, [r11]!
+
+ sub r14, r14, #48
+ vst1.8 {q0}, [r8]!
+ vst1.8 {q2}, [r8]!
+ vst1.8 {q4}, [r8]!
+ vst1.8 {q6}, [r8], r14
+ vst1.8 {q8}, [r8]!
+ vst1.8 {q10}, [r8]!
+ vst1.8 {q12}, [r8]!
+ vst1.8 {q14}, [r8]!
+
+ add r10, r1, r10
+ vst1.8 {q1}, [r10]!
+ vst1.8 {q3}, [r10]!
+ vst1.8 {q5}, [r10]!
+ vst1.8 {q7}, [r10], r14
+ vst1.8 {q9}, [r10]!
+ vst1.8 {q11}, [r10]!
+ add r6, #2
+ vst1.8 {q13}, [r10]!
+ cmp r6, r4
+ vst1.8 {q15}, [r10]!
+
+ blt LINEAR_X_SIZE_128_LOOP
+
+ add r9, r9, #128
+
+LINEAR_X_SIZE_64:
+ sub r10, r3, r9
+ cmp r10, #64
+ blt LINEAR_X_SIZE_4
+
+ mov r5, r9
+ mov r6, #0
+
+LINEAR_X_SIZE_64_LOOP:
+ bl GET_TILED_OFFSET
+
+LINEAR_X_SIZE_64_LOOP_MEMCPY:
+ and r10, r6, #0x1F
+ mov r14, r3, asr #1
+ mov r10, r10, lsl #6
+ sub r14, r14, #16
+ add r10, r2, r10
+
+ add r7, r7, r10 @ tiled_addr = tiled_src+64*(temp1)
+ pld [r7, #64]
+ vld2.8 {q0, q1}, [r7]!
+ mov r10, r3, asr #1
+ pld [r7, #64]
+ vld2.8 {q2, q3}, [r7]!
+ mul r10, r10, r6
+ vld2.8 {q4, q5}, [r7]!
+ add r10, r10, r9, asr #1
+ vld2.8 {q6, q7}, [r7]!
+ add r8, r0, r10
+
+ vst1.8 {q0}, [r8]!
+ vst1.8 {q2}, [r8], r14
+ vst1.8 {q4}, [r8]!
+ vst1.8 {q6}, [r8], r14
+
+ add r10, r1, r10
+ vst1.8 {q1}, [r10]!
+ vst1.8 {q3}, [r10], r14
+ add r6, #2
+ vst1.8 {q5}, [r10]!
+ cmp r6, r4
+ vst1.8 {q7}, [r10], r14
+
+ blt LINEAR_X_SIZE_64_LOOP
+
+ add r9, r9, #64
+
+LINEAR_X_SIZE_4:
+ cmp r9, r3
+ beq RESTORE_REG
+
+ mov r6, #0 @ i = 0
+LINEAR_Y_SIZE_4_LOOP:
+
+ mov r5, r9 @ j = aligned_x_size
+LINEAR_X_SIZE_4_LOOP:
+
+ bl GET_TILED_OFFSET
+
+ mov r11, r3, asr #1 @ temp1 = linear_x_size/2
+ mul r11, r11, r6 @ temp1 = temp1*(i)
+ add r11, r11, r5, asr #1 @ temp1 = temp1+j/2
+ mov r12, r3, asr #1 @ temp2 = linear_x_size/2
+ sub r12, r12, #1 @ temp2 = linear_x_size-1
+
+ add r8, r0, r11 @ linear_addr = linear_dest_u+temp1
+ add r11, r1, r11 @ temp1 = linear_dest_v+temp1
+ add r7, r2, r7 @ tiled_addr = tiled_src+tiled_addr
+ and r14, r6, #0x1F @ temp3 = i&0x1F@
+ mov r14, r14, lsl #6 @ temp3 = temp3*64
+ add r7, r7, r14 @ tiled_addr = tiled_addr+temp3
+ and r14, r5, #0x3F @ temp3 = j&0x3F
+ add r7, r7, r14 @ tiled_addr = tiled_addr+temp3
+
+ ldrh r10, [r7], #2
+ ldrh r14, [r7], #62
+ strb r10, [r8], #1
+ mov r10, r10, asr #8
+ strb r10, [r11], #1
+ strb r14, [r8], r12
+ mov r14, r14, asr #8
+ strb r14, [r11], r12
+
+ ldrh r10, [r7], #2
+ ldrh r14, [r7], #62
+ strb r10, [r8], #1
+ mov r10, r10, asr #8
+ strb r10, [r11], #1
+ strb r14, [r8], r12
+ mov r14, r14, asr #8
+ strb r14, [r11], r12
+
+ add r5, r5, #4 @ j = j+4
+ cmp r5, r3 @ j>5
+ mov r11, r5, asr #6 @ temp1 = j>>6
+
+ and r14, r12, #0x1 @ if (temp2 & 0x1)
+ cmp r14, #0x1
+ bne GET_TILED_OFFSET_EVEN_FORMULA_1
+
+GET_TILED_OFFSET_ODD_FORMULA:
+ sub r7, r12, #1 @ tiled_addr = temp2-1
+ add r14, r3, #127 @ temp3 = linear_x_size+127
+ bic r14, r14, #0x7F @ temp3 = (temp3 >>7)<<7
+ mov r14, r14, asr #6 @ temp3 = temp3>>6
+ mul r7, r7, r14 @ tiled_addr = tiled_addr*temp3
+ add r7, r7, r11 @ tiled_addr = tiled_addr+temp1
+ add r7, r7, #2 @ tiled_addr = tiled_addr+2
+ bic r14, r11, #0x3 @ temp3 = (temp1>>2)<<2
+ add r7, r7, r14 @ tiled_addr = tiled_addr+temp3
+ mov r7, r7, lsl #11 @ tiled_addr = tiled_addr<<11
+ b GET_TILED_OFFSET_RETURN
+
+GET_TILED_OFFSET_EVEN_FORMULA_1:
+ add r14, r4, #31 @ temp3 = linear_y_size+31
+ bic r14, r14, #0x1F @ temp3 = (temp3>>5)<<5
+ sub r14, r14, #32 @ temp3 = temp3 - 32
+ cmp r6, r14 @ if (i<(temp3-32)) {
+ bge GET_TILED_OFFSET_EVEN_FORMULA_2
+ add r14, r11, #2 @ temp3 = temp1+2
+ bic r14, r14, #3 @ temp3 = (temp3>>2)<<2
+ add r7, r11, r14 @ tiled_addr = temp1+temp3
+ add r14, r3, #127 @ temp3 = linear_x_size+127
+ bic r14, r14, #0x7F @ temp3 = (temp3>>7)<<7
+ mov r14, r14, asr #6 @ temp3 = temp3>>6
+ mul r12, r12, r14 @ tiled_y_index = tiled_y_index*temp3
+ add r7, r7, r12 @ tiled_addr = tiled_addr+tiled_y_index
+ mov r7, r7, lsl #11 @
+ b GET_TILED_OFFSET_RETURN
+
+GET_TILED_OFFSET_EVEN_FORMULA_2:
+ add r14, r3, #127 @ temp3 = linear_x_size+127
+ bic r14, r14, #0x7F @ temp3 = (temp3>>7)<<7
+ mov r14, r14, asr #6 @ temp3 = temp3>>6
+ mul r7, r12, r14 @ tiled_addr = temp2*temp3
+ add r7, r7, r11 @ tiled_addr = tiled_addr+temp3
+ mov r7, r7, lsl #11 @ tiled_addr = tiled_addr<<11@
+
+GET_TILED_OFFSET_RETURN:
+ ldmfd sp!, {r15} @ restore registers
+ .fnend
diff --git a/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_nv12t_yuv420_y_neon.s b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_nv12t_yuv420_y_neon.s
new file mode 100644
index 0000000..d71ee17
--- /dev/null
+++ b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_nv12t_yuv420_y_neon.s
@@ -0,0 +1,680 @@
+/*
+ *
+ * Copyright 2011 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file csc_nv12t_yuv420_y_neon.s
+ * @brief SEC_OMX specific define
+ * @author ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ * 2011.7.01 : Create
+ */
+
+/*
+ * Converts tiled data to linear.
+ * 1. Y of NV12T to Y of YUV420P
+ * 2. Y of NV12T to Y of YUV420S
+ * 3. UV of NV12T to UV of YUV420S
+ *
+ * @param yuv420_dest
+ * Y or UV plane address of YUV420[out]
+ *
+ * @param nv12t_src
+ * Y or UV plane address of NV12T[in]
+ *
+ * @param yuv420_width
+ * Width of YUV420[in]
+ *
+ * @param yuv420_height
+ * Y: Height of YUV420, UV: Height/2 of YUV420[in]
+ */
+
+ .arch armv7-a
+ .text
+ .global csc_tiled_to_linear
+ .type csc_tiled_to_linear, %function
+csc_tiled_to_linear:
+ .fnstart
+
+ @r0 linear_dest
+ @r1 tiled_src
+ @r2 linear_x_size
+ @r3 linear_y_size
+ @r4 j
+ @r5 i
+ @r6 tiled_addr
+ @r7 linear_addr
+ @r8 aligned_x_size
+ @r9 aligned_y_size
+ @r10 temp1
+ @r11 temp2
+ @r12 temp3
+ @r14 temp4
+
+ stmfd sp!, {r4-r12,r14} @ backup registers
+
+ mov r8, #0
+ cmp r2, #1024
+ blt LINEAR_X_SIZE_512
+
+LINEAR_X_SIZE_1024:
+
+ mov r5, #0
+LINEAR_X_SIZE_1024_LOOP:
+ mov r6, #0 @ tiled_offset = 0@
+ mov r4, r5, asr #5 @ tiled_y_index = i>>5@
+ and r10, r4, #0x1
+ cmp r10, #0x1
+ bne LINEAR_X_SIZE_1024_LOOP_EVEN
+LINEAR_X_SIZE_1024_LOOP_ODD:
+ sub r6, r4, #1 @ tiled_offset = tiled_y_index-1@
+ add r10, r2, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6)@
+ mul r6, r6, r10
+ mov r4, #8
+ mov r4, r4, lsl #11
+ sub r4, r4, #32
+ add r6, r6, #2 @ tiled_offset = tiled_offset+2@
+ mov r6, r6, lsl #11 @ tiled_offset = tiled_offset<<11@
+ add r11, r6, #2048
+ add r12, r6, #4096
+ add r14, r6, #6144
+ b LINEAR_X_SIZE_1024_LOOP_MEMCPY
+
+LINEAR_X_SIZE_1024_LOOP_EVEN:
+ add r11, r3, #31 @ temp2 = ((linear_y_size+31)>>5)<<5@
+ bic r11, r11, #0x1F
+ add r10, r2, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_y_index*(temp1>>6)@
+ mul r6, r4, r10
+ add r12, r5, #32
+ cmp r12, r11
+ mov r6, r6, lsl #11 @ tiled_offset = tiled_offset<<11@
+ add r11, r6, #2048
+ movlt r4, #8
+ addlt r12, r6, #12288
+ addlt r14, r6, #14336
+ movge r4, #4
+ addge r12, r6, #4096
+ addge r14, r6, #6144
+ mov r4, r4, lsl #11
+ sub r4, r4, #32
+
+LINEAR_X_SIZE_1024_LOOP_MEMCPY:
+ and r10, r5, #0x1F
+ mov r10, r10, lsl #6
+ add r10, r1, r10
+
+ add r6, r6, r10 @ tiled_addr = tiled_src+64*(temp1)
+ add r11, r11, r10 @ tiled_addr1 = tiled_src+64*(temp1)
+ pld [r11]
+ vld1.8 {q0, q1}, [r6]!
+ pld [r11, #32]
+ add r12, r12, r10 @ tiled_addr2 = tiled_src+64*(temp1)
+ vld1.8 {q2, q3}, [r6], r4
+ pld [r12]
+ vld1.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ add r14, r14, r10 @ tiled_addr3 = tiled_src+64*(temp1)
+ vld1.8 {q6, q7}, [r11], r4
+ pld [r14]
+ vld1.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ mul r7, r2, r5
+ vld1.8 {q10, q11}, [r12], r4
+ add r7, r7, r0
+ vld1.8 {q12, q13}, [r14]!
+ vld1.8 {q14, q15}, [r14], r4
+
+ vst1.8 {q0, q1}, [r7]!
+ vst1.8 {q2, q3}, [r7]!
+ vst1.8 {q4, q5}, [r7]!
+ vst1.8 {q6, q7}, [r7]!
+ vst1.8 {q8, q9}, [r7]!
+ vst1.8 {q10, q11}, [r7]!
+ pld [r6]
+ vst1.8 {q12, q13}, [r7]!
+ pld [r6, #32]
+ vst1.8 {q14, q15}, [r7]!
+
+ pld [r11]
+ vld1.8 {q0, q1}, [r6]!
+ pld [r11, #32]
+ vld1.8 {q2, q3}, [r6], r4
+
+ pld [r12]
+ vld1.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ vld1.8 {q6, q7}, [r11], r4
+ pld [r14]
+ vld1.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ vld1.8 {q10, q11}, [r12], r4
+ vld1.8 {q12, q13}, [r14]!
+ vld1.8 {q14, q15}, [r14], r4
+
+ vst1.8 {q0, q1}, [r7]!
+ vst1.8 {q2, q3}, [r7]!
+ vst1.8 {q4, q5}, [r7]!
+ vst1.8 {q6, q7}, [r7]!
+ vst1.8 {q8, q9}, [r7]!
+ vst1.8 {q10, q11}, [r7]!
+ pld [r6]
+ vst1.8 {q12, q13}, [r7]!
+ pld [r6, #32]
+ vst1.8 {q14, q15}, [r7]!
+
+ pld [r11]
+ vld1.8 {q0, q1}, [r6]!
+ pld [r11, #32]
+ vld1.8 {q2, q3}, [r6], r4
+ pld [r12]
+ vld1.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ vld1.8 {q6, q7}, [r11], r4
+ pld [r14]
+ vld1.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ vld1.8 {q10, q11}, [r12], r4
+ vld1.8 {q12, q13}, [r14]!
+ vld1.8 {q14, q15}, [r14], r4
+
+ vst1.8 {q0, q1}, [r7]!
+ vst1.8 {q2, q3}, [r7]!
+ vst1.8 {q4, q5}, [r7]!
+ vst1.8 {q6, q7}, [r7]!
+ vst1.8 {q8, q9}, [r7]!
+ vst1.8 {q10, q11}, [r7]!
+ pld [r6]
+ vst1.8 {q12, q13}, [r7]!
+ pld [r6, #32]
+ vst1.8 {q14, q15}, [r7]!
+
+ pld [r11]
+ vld1.8 {q0, q1}, [r6]!
+ pld [r11, #32]
+ vld1.8 {q2, q3}, [r6]
+ pld [r12]
+ vld1.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ vld1.8 {q6, q7}, [r11]
+ pld [r14]
+ vld1.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ vld1.8 {q10, q11}, [r12]
+ vld1.8 {q12, q13}, [r14]!
+ vld1.8 {q14, q15}, [r14]
+
+ vst1.8 {q0, q1}, [r7]!
+ vst1.8 {q2, q3}, [r7]!
+ vst1.8 {q4, q5}, [r7]!
+ vst1.8 {q6, q7}, [r7]!
+ vst1.8 {q8, q9}, [r7]!
+ vst1.8 {q10, q11}, [r7]!
+ add r5, #1
+ vst1.8 {q12, q13}, [r7]!
+ cmp r5, r3
+ vst1.8 {q14, q15}, [r7]!
+
+ blt LINEAR_X_SIZE_1024_LOOP
+
+ mov r8, #1024
+
+LINEAR_X_SIZE_512:
+
+ sub r14, r2, r8
+ cmp r14, #512
+ blt LINEAR_X_SIZE_256
+
+ mov r5, #0
+LINEAR_X_SIZE_512_LOOP:
+ mov r6, #0
+ mov r4, r5, asr #5 @ tiled_y_index = i>>5
+ and r10, r4, #0x1
+ cmp r10, #0x1
+ bne LINEAR_X_SIZE_512_LOOP_EVEN
+
+LINEAR_X_SIZE_512_LOOP_ODD:
+ sub r6, r4, #1
+ add r10, r2, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6)@
+ mul r6, r6, r10
+ mov r4, #8
+ mov r4, r4, lsl #11
+ sub r4, r4, #32
+ add r6, r6, #2 @ tiled_offset = tiled_offset+2@
+ mov r10, r8, asr #5 @ temp1 = aligned_x_size>>5@
+ add r6, r6, r10 @ tiled_offset = tiled_offset+temp1@
+ mov r6, r6, lsl #11
+ add r11, r6, #2048
+ add r12, r6, #4096
+ add r14, r6, #6144
+ b LINEAR_X_SIZE_512_LOOP_MEMCPY
+
+LINEAR_X_SIZE_512_LOOP_EVEN:
+ add r11, r3, #31 @ temp2 = ((linear_y_size+31)>>5)<<5@
+ bic r11, r11, #0x1F
+ add r10, r2, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_y_index*(temp1>>6)@
+ mul r6, r4, r10
+ add r12, r5, #32
+ cmp r12, r11
+ mov r6, r6, lsl #11 @ tiled_offset = tiled_offset<<11@
+ movlt r4, #8
+ movlt r10, r8, asr #5 @ temp1 = aligned_x_size>>5@
+ movge r10, r8, asr #6 @ temp1 = aligned_x_size>>6@
+ add r6, r6, r10, lsl #11 @ tiled_offset = tiled_offset+(temp1<<11)@
+ add r11, r6, #2048
+ addlt r12, r6, #12288
+ addlt r14, r6, #14336
+ movge r4, #4
+ addge r12, r6, #4096
+ addge r14, r6, #6144
+ mov r4, r4, lsl #11
+ sub r4, r4, #32
+
+LINEAR_X_SIZE_512_LOOP_MEMCPY:
+ and r10, r5, #0x1F
+ mov r10, r10, lsl #6
+ add r10, r1, r10
+
+ add r6, r6, r10 @ tiled_addr = tiled_src+64*(temp1)
+ add r11, r11, r10 @ tiled_addr1 = tiled_src+64*(temp1)
+ pld [r11]
+ vld1.8 {q0, q1}, [r6]!
+ pld [r11, #32]
+ add r12, r12, r10 @ tiled_addr2 = tiled_src+64*(temp1)
+ vld1.8 {q2, q3}, [r6], r4
+ pld [r12]
+ vld1.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ add r14, r14, r10 @ tiled_addr3 = tiled_src+64*(temp1)
+ vld1.8 {q6, q7}, [r11], r4
+ pld [r14]
+ vld1.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ mul r7, r2, r5
+ vld1.8 {q10, q11}, [r12], r4
+ add r7, r7, r8
+ vld1.8 {q12, q13}, [r14]!
+ vld1.8 {q14, q15}, [r14], r4
+
+ add r7, r7, r0
+ vst1.8 {q0, q1}, [r7]!
+ vst1.8 {q2, q3}, [r7]!
+ vst1.8 {q4, q5}, [r7]!
+ vst1.8 {q6, q7}, [r7]!
+ vst1.8 {q8, q9}, [r7]!
+ vst1.8 {q10, q11}, [r7]!
+ pld [r6]
+ vst1.8 {q12, q13}, [r7]!
+ pld [r6, #32]
+ vst1.8 {q14, q15}, [r7]!
+
+ pld [r11]
+ vld1.8 {q0, q1}, [r6]!
+ pld [r11, #32]
+ vld1.8 {q2, q3}, [r6], r4
+ pld [r12]
+ vld1.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ vld1.8 {q6, q7}, [r11], r4
+ pld [r14]
+ vld1.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ vld1.8 {q10, q11}, [r12], r4
+ vld1.8 {q12, q13}, [r14]!
+ vld1.8 {q14, q15}, [r14], r4
+
+ vst1.8 {q0, q1}, [r7]!
+ vst1.8 {q2, q3}, [r7]!
+ vst1.8 {q4, q5}, [r7]!
+ vst1.8 {q6, q7}, [r7]!
+ vst1.8 {q8, q9}, [r7]!
+ vst1.8 {q10, q11}, [r7]!
+ add r5, #1
+ vst1.8 {q12, q13}, [r7]!
+ cmp r5, r3
+ vst1.8 {q14, q15}, [r7]!
+
+ blt LINEAR_X_SIZE_512_LOOP
+
+ add r8, r8, #512
+
+LINEAR_X_SIZE_256:
+
+ sub r14, r2, r8
+ cmp r14, #256
+ blt LINEAR_X_SIZE_128
+
+ mov r5, #0
+LINEAR_X_SIZE_256_LOOP:
+ mov r6, #0
+ mov r4, r5, asr #5 @ tiled_y_index = i>>5
+ and r10, r4, #0x1
+ cmp r10, #0x1
+ bne LINEAR_X_SIZE_256_LOOP_EVEN
+
+LINEAR_X_SIZE_256_LOOP_ODD:
+ sub r6, r4, #1
+ add r10, r2, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6)@
+ mul r6, r6, r10
+ add r6, r6, #2 @ tiled_offset = tiled_offset+2@
+ mov r10, r8, asr #5 @ temp1 = aligned_x_size>>5@
+ add r6, r6, r10 @ tiled_offset = tiled_offset+temp1@
+ mov r6, r6, lsl #11
+ add r11, r6, #2048
+ add r12, r6, #4096
+ add r14, r6, #6144
+ b LINEAR_X_SIZE_256_LOOP_MEMCPY
+
+LINEAR_X_SIZE_256_LOOP_EVEN:
+ add r11, r3, #31 @ temp2 = ((linear_y_size+31)>>5)<<5@
+ bic r11, r11, #0x1F
+ add r10, r2, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_y_index*(temp1>>6)@
+ mul r6, r4, r10
+ mov r6, r6, lsl #11 @ tiled_offset = tiled_offset<<11@
+ add r12, r5, #32
+ cmp r12, r11
+ movlt r10, r8, asr #5 @ temp1 = aligned_x_size>>5@
+ movge r10, r8, asr #6 @ temp1 = aligned_x_size>>6@
+ add r6, r6, r10, lsl #11 @ tiled_offset = tiled_offset+(temp1<<11)@
+ add r11, r6, #2048
+ addlt r12, r6, #12288
+ addlt r14, r6, #14336
+ addge r12, r6, #4096
+ addge r14, r6, #6144
+
+LINEAR_X_SIZE_256_LOOP_MEMCPY:
+ and r10, r5, #0x1F
+ mov r10, r10, lsl #6
+ add r10, r1, r10
+
+ add r6, r6, r10 @ tiled_addr = tiled_src+64*(temp1)
+ add r11, r11, r10 @ tiled_addr1 = tiled_src+64*(temp1)
+ pld [r11]
+ vld1.8 {q0, q1}, [r6]!
+ pld [r11, #32]
+ add r12, r12, r10 @ tiled_addr2 = tiled_src+64*(temp1)
+ vld1.8 {q2, q3}, [r6]
+ pld [r12]
+ vld1.8 {q4, q5}, [r11]!
+ pld [r12, #32]
+ add r14, r14, r10 @ tiled_addr3 = tiled_src+64*(temp1)
+ vld1.8 {q6, q7}, [r11]
+ pld [r14]
+ mul r7, r2, r5
+ vld1.8 {q8, q9}, [r12]!
+ pld [r14, #32]
+ add r7, r7, r8
+ vld1.8 {q10, q11}, [r12]
+ add r7, r7, r0
+ vld1.8 {q12, q13}, [r14]!
+ vld1.8 {q14, q15}, [r14]
+
+ vst1.8 {q0, q1}, [r7]!
+ vst1.8 {q2, q3}, [r7]!
+ vst1.8 {q4, q5}, [r7]!
+ vst1.8 {q6, q7}, [r7]!
+ vst1.8 {q8, q9}, [r7]!
+ vst1.8 {q10, q11}, [r7]!
+ add r5, #1
+ vst1.8 {q12, q13}, [r7]!
+ cmp r5, r3
+ vst1.8 {q14, q15}, [r7]!
+
+ blt LINEAR_X_SIZE_256_LOOP
+
+ add r8, r8, #256
+
+LINEAR_X_SIZE_128:
+
+ sub r14, r2, r8
+ cmp r14, #128
+ blt LINEAR_X_SIZE_64
+
+ mov r5, #0
+LINEAR_X_SIZE_128_LOOP:
+ mov r6, #0
+ mov r4, r5, asr #5 @ tiled_y_index = i>>5
+ and r10, r4, #0x1
+ cmp r10, #0x1
+ bne LINEAR_X_SIZE_128_LOOP_EVEN
+
+LINEAR_X_SIZE_128_LOOP_ODD:
+ sub r6, r4, #1
+ add r10, r2, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6)@
+ mul r6, r6, r10
+ add r6, r6, #2 @ tiled_offset = tiled_offset+2@
+ mov r10, r8, asr #5 @ temp1 = aligned_x_size>>5@
+ add r6, r6, r10 @ tiled_offset = tiled_offset+temp1@
+ mov r6, r6, lsl #11
+ add r11, r6, #2048
+ b LINEAR_X_SIZE_128_LOOP_MEMCPY
+
+LINEAR_X_SIZE_128_LOOP_EVEN:
+ add r11, r3, #31 @ temp2 = ((linear_y_size+31)>>5)<<5@
+ bic r11, r11, #0x1F
+ add r10, r2, #127 @ temp1 = ((linear_x_size+127)>>7)<<7@
+ bic r10, #0x7F
+ mov r10, r10, asr #6 @ tiled_offset = tiled_y_index*(temp1>>6)@
+ mul r6, r4, r10
+ mov r6, r6, lsl #11 @ tiled_offset = tiled_offset<<11@
+ add r12, r5, #32
+ cmp r12, r11
+ movlt r10, r8, asr #5 @ temp1 = aligned_x_size>>5@
+ movge r10, r8, asr #6 @ temp1 = aligned_x_size>>6@
+ add r6, r6, r10, lsl #11 @ tiled_offset = tiled_offset+(temp1<<11)@
+ add r11, r6, #2048
+
+LINEAR_X_SIZE_128_LOOP_MEMCPY:
+ and r10, r5, #0x1F
+ mov r10, r10, lsl #6
+ add r10, r1, r10
+
+ add r6, r6, r10 @ tiled_addr = tiled_src+64*(temp1)
+ add r11, r11, r10 @ tiled_addr1 = tiled_src+64*(temp1)
+ pld [r6, #64]
+ vld1.8 {q0, q1}, [r6]!
+ pld [r6, #64]
+ vld1.8 {q2, q3}, [r6]!
+ mul r7, r2, r5
+ pld [r11]
+ vld1.8 {q4, q5}, [r6]!
+ add r7, r7, r8
+ pld [r11, #32]
+ vld1.8 {q6, q7}, [r6]
+ add r7, r7, r0
+ pld [r11, #64]
+ vld1.8 {q8, q9}, [r11]!
+ pld [r11, #64]
+ vld1.8 {q10, q11}, [r11]!
+ vld1.8 {q12, q13}, [r11]!
+ vld1.8 {q14, q15}, [r11]
+
+ sub r9, r2, #96
+ vst1.8 {q0, q1}, [r7]!
+ vst1.8 {q2, q3}, [r7]!
+ vst1.8 {q8, q9}, [r7]!
+ vst1.8 {q10, q11}, [r7], r9
+ vst1.8 {q4, q5}, [r7]!
+ vst1.8 {q6, q7}, [r7]!
+ add r5, #2
+ vst1.8 {q12, q13}, [r7]!
+ cmp r5, r3
+ vst1.8 {q14, q15}, [r7]
+
+ blt LINEAR_X_SIZE_128_LOOP
+
+ add r8, r8, #128
+
+LINEAR_X_SIZE_64:
+
+ sub r14, r2, r8
+ cmp r14, #64
+ blt LINEAR_X_SIZE_4
+
+ mov r5, #0
+ mov r4, r8
+
+LINEAR_X_SIZE_64_LOOP:
+
+ bl GET_TILED_OFFSET
+
+ add r6, r1, r6 @ tiled_addr = tiled_src+tiled_addr
+ and r11, r5, #0x1F @ temp2 = i&0x1F
+ mov r11, r11, lsl #6 @ temp2 = 64*temp2
+ add r6, r6, r11 @ tiled_addr = tiled_addr+temp2
+
+ pld [r6, #64]
+ vld1.8 {q0, q1}, [r6]! @ store {tiled_addr}
+ mul r10, r2, r5 @ temp1 = linear_x_size*(i)
+ pld [r6, #64]
+ vld1.8 {q2, q3}, [r6]!
+ pld [r6, #64]
+ vld1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*1}
+ pld [r6, #64]
+ vld1.8 {q6, q7}, [r6]!
+ pld [r6, #64]
+ vld1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*2}
+ pld [r6, #64]
+ vld1.8 {q10, q11}, [r6]!
+ add r7, r0, r4 @ linear_addr = linear_dest+j
+ vld1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*3}
+ add r7, r7, r10 @ linear_addr = linear_addr+temp1
+ vld1.8 {q14, q15}, [r6]!
+ sub r10, r2, #32 @ temp1 = linear_x_size-32
+
+ vst1.8 {q0, q1}, [r7]! @ load {linear_src, 64}
+ vst1.8 {q2, q3}, [r7], r10
+ vst1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*1, 64}
+ vst1.8 {q6, q7}, [r7], r10
+ vst1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*2, 64}
+ vst1.8 {q10, q11}, [r7], r10
+ add r5, #4
+ vst1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*3, 64}
+ cmp r5, r3
+ vst1.8 {q14, q15}, [r7], r10
+
+ blt LINEAR_X_SIZE_64_LOOP
+
+ add r8, r8, #64
+
+LINEAR_X_SIZE_4:
+ cmp r8, r2
+ beq RESTORE_REG
+
+ mov r5, #0 @ i = 0
+LINEAR_Y_SIZE_4_LOOP:
+
+ mov r4, r8 @ j = aligned_x_size
+LINEAR_X_SIZE_4_LOOP:
+
+ bl GET_TILED_OFFSET
+
+ and r10, r5, #0x1F @ temp1 = i&0x1F
+ and r11, r4, #0x3F @ temp2 = j&0x3F
+
+ add r6, r6, r1
+ add r6, r6, r11
+ add r6, r6, r10, lsl #6
+
+ ldr r10, [r6], #64
+ add r7, r0, r4
+ ldr r11, [r6], #64
+ mul r9, r2, r5
+ ldr r12, [r6], #64
+ add r7, r7, r9
+ ldr r14, [r6], #64
+
+ str r10, [r7], r2
+ str r11, [r7], r2
+ str r12, [r7], r2
+ str r14, [r7], r2
+
+ add r4, r4, #4 @ j = j+4
+ cmp r4, r2 @ j>5
+ mov r10, r4, asr #6 @ temp1 = j>>6
+
+ and r12, r11, #0x1 @ if (temp2 & 0x1)
+ cmp r12, #0x1
+ bne GET_TILED_OFFSET_EVEN_FORMULA_1
+
+GET_TILED_OFFSET_ODD_FORMULA:
+ sub r6, r11, #1 @ tiled_addr = temp2-1
+ add r12, r2, #127 @ temp3 = linear_x_size+127
+ bic r12, r12, #0x7F @ temp3 = (temp3 >>7)<<7
+ mov r12, r12, asr #6 @ temp3 = temp3>>6
+ mul r6, r6, r12 @ tiled_addr = tiled_addr*temp3
+ add r6, r6, r10 @ tiled_addr = tiled_addr+temp1
+ add r6, r6, #2 @ tiled_addr = tiled_addr+2
+ bic r12, r10, #0x3 @ temp3 = (temp1>>2)<<2
+ add r6, r6, r12 @ tiled_addr = tiled_addr+temp3
+ mov r6, r6, lsl #11 @ tiled_addr = tiled_addr<<11
+ b GET_TILED_OFFSET_RETURN
+
+GET_TILED_OFFSET_EVEN_FORMULA_1:
+ add r12, r3, #31 @ temp3 = linear_y_size+31
+ bic r12, r12, #0x1F @ temp3 = (temp3>>5)<<5
+ sub r12, r12, #32 @ temp3 = temp3 - 32
+ cmp r5, r12 @ if (i<(temp3-32)) {
+ bge GET_TILED_OFFSET_EVEN_FORMULA_2
+ add r12, r10, #2 @ temp3 = temp1+2
+ bic r12, r12, #3 @ temp3 = (temp3>>2)<<2
+ add r6, r10, r12 @ tiled_addr = temp1+temp3
+ add r12, r2, #127 @ temp3 = linear_x_size+127
+ bic r12, r12, #0x7F @ temp3 = (temp3>>7)<<7
+ mov r12, r12, asr #6 @ temp3 = temp3>>6
+ mul r11, r11, r12 @ tiled_y_index = tiled_y_index*temp3
+ add r6, r6, r11 @ tiled_addr = tiled_addr+tiled_y_index
+ mov r6, r6, lsl #11 @
+ b GET_TILED_OFFSET_RETURN
+
+GET_TILED_OFFSET_EVEN_FORMULA_2:
+ add r12, r2, #127 @ temp3 = linear_x_size+127
+ bic r12, r12, #0x7F @ temp3 = (temp3>>7)<<7
+ mov r12, r12, asr #6 @ temp3 = temp3>>6
+ mul r6, r11, r12 @ tiled_addr = temp2*temp3
+ add r6, r6, r10 @ tiled_addr = tiled_addr+temp3
+ mov r6, r6, lsl #11 @ tiled_addr = tiled_addr<<11@
+
+GET_TILED_OFFSET_RETURN:
+ mov pc, lr
+ .fnend
+
diff --git a/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_yuv420_nv12t_uv_neon.s b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_yuv420_nv12t_uv_neon.s
new file mode 100644
index 0000000..dd2c879
--- /dev/null
+++ b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_yuv420_nv12t_uv_neon.s
@@ -0,0 +1,573 @@
+/*
+ *
+ * Copyright 2011 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file csc_yuv420_nv12t_uv_neon.s
+ * @brief SEC_OMX specific define
+ * @author ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ * 2011.7.01 : Create
+ */
+
+/*
+ * Converts and Interleaves linear to tiled
+ * 1. UV of YUV420P to UV of NV12T
+ *
+ * @param nv12t_uv_dest
+ * UV plane address of NV12T[out]
+ *
+ * @param yuv420p_u_src
+ * U plane address of YUV420P[in]
+ *
+ * @param yuv420p_v_src
+ * V plane address of YUV420P[in]
+ *
+ * @param yuv420_width
+ * Width of YUV420[in]
+ *
+ * @param yuv420_uv_height
+ * Height/2 of YUV420[in]
+ */
+
+ .arch armv7-a
+ .text
+ .global csc_linear_to_tiled_interleave
+ .type csc_linear_to_tiled_interleave, %function
+csc_linear_to_tiled_interleave:
+ .fnstart
+
+ @r0 tiled_dest
+ @r1 linear_src_u
+ @r2 linear_src_v
+ @r3 linear_x_size
+ @r4 linear_y_size
+ @r5 j
+ @r6 i
+ @r7 tiled_addr
+ @r8 linear_addr
+ @r9 aligned_x_size
+ @r10 aligned_y_size
+ @r11 temp1
+ @r12 temp2
+ @r14 temp3
+
+ stmfd sp!, {r4-r12,r14} @ backup registers
+
+ ldr r4, [sp, #40] @ load linear_y_size to r4
+
+ bic r10, r4, #0x1F @ aligned_y_size = (linear_y_size>>5)<<5
+ bic r9, r3, #0x3F @ aligned_x_size = (linear_x_size>>6)<<6
+
+ mov r6, #0 @ i = 0
+LOOP_ALIGNED_Y_SIZE:
+
+ mov r5, #0 @ j = 0
+LOOP_ALIGNED_X_SIZE:
+
+ bl GET_TILED_OFFSET
+
+ mov r11, r3, asr #1 @ temp1 = linear_x_size/2
+ mul r11, r11, r6 @ temp1 = temp1*(i)
+ add r11, r11, r5, asr #1 @ temp1 = temp1+j/2
+ mov r12, r3, asr #1 @ temp2 = linear_x_size/2
+ sub r12, r12, #16 @ temp2 = linear_x_size-16
+
+ add r8, r1, r11 @ linear_addr = linear_src_u+temp1
+ add r11, r2, r11 @ temp1 = linear_src_v+temp1
+ add r7, r0, r7 @ tiled_addr = tiled_dest+tiled_addr
+
+ pld [r8, r3]
+ vld1.8 {q0}, [r8]!
+ vld1.8 {q2}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q1}, [r11]!
+ vld1.8 {q3}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q4}, [r8]!
+ vld1.8 {q6}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q5}, [r11]!
+ vld1.8 {q7}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q8}, [r8]!
+ vld1.8 {q10}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q9}, [r11]!
+ vld1.8 {q11}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q12}, [r8]!
+ vld1.8 {q14}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q13}, [r11]!
+ vld1.8 {q15}, [r11], r12
+
+ vst2.8 {q0, q1}, [r7]!
+ vst2.8 {q2, q3}, [r7]!
+ vst2.8 {q4, q5}, [r7]!
+ vst2.8 {q6, q7}, [r7]!
+ vst2.8 {q8, q9}, [r7]!
+ vst2.8 {q10, q11}, [r7]!
+ vst2.8 {q12, q13}, [r7]!
+ vst2.8 {q14, q15}, [r7]!
+
+ pld [r8, r3]
+ vld1.8 {q0}, [r8]!
+ vld1.8 {q2}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q1}, [r11]!
+ vld1.8 {q3}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q4}, [r8]!
+ vld1.8 {q6}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q5}, [r11]!
+ vld1.8 {q7}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q8}, [r8]!
+ vld1.8 {q10}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q9}, [r11]!
+ vld1.8 {q11}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q12}, [r8]!
+ vld1.8 {q14}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q13}, [r11]!
+ vld1.8 {q15}, [r11], r12
+
+ vst2.8 {q0, q1}, [r7]!
+ vst2.8 {q2, q3}, [r7]!
+ vst2.8 {q4, q5}, [r7]!
+ vst2.8 {q6, q7}, [r7]!
+ vst2.8 {q8, q9}, [r7]!
+ vst2.8 {q10, q11}, [r7]!
+ vst2.8 {q12, q13}, [r7]!
+ vst2.8 {q14, q15}, [r7]!
+
+ pld [r8, r3]
+ vld1.8 {q0}, [r8]!
+ vld1.8 {q2}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q1}, [r11]!
+ vld1.8 {q3}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q4}, [r8]!
+ vld1.8 {q6}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q5}, [r11]!
+ vld1.8 {q7}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q8}, [r8]!
+ vld1.8 {q10}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q9}, [r11]!
+ vld1.8 {q11}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q12}, [r8]!
+ vld1.8 {q14}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q13}, [r11]!
+ vld1.8 {q15}, [r11], r12
+
+ vst2.8 {q0, q1}, [r7]!
+ vst2.8 {q2, q3}, [r7]!
+ vst2.8 {q4, q5}, [r7]!
+ vst2.8 {q6, q7}, [r7]!
+ vst2.8 {q8, q9}, [r7]!
+ vst2.8 {q10, q11}, [r7]!
+ vst2.8 {q12, q13}, [r7]!
+ vst2.8 {q14, q15}, [r7]!
+
+ pld [r8, r3]
+ vld1.8 {q0}, [r8]!
+ vld1.8 {q2}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q1}, [r11]!
+ vld1.8 {q3}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q4}, [r8]!
+ vld1.8 {q6}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q5}, [r11]!
+ vld1.8 {q7}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q8}, [r8]!
+ vld1.8 {q10}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q9}, [r11]!
+ vld1.8 {q11}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q12}, [r8]!
+ vld1.8 {q14}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q13}, [r11]!
+ vld1.8 {q15}, [r11], r12
+
+ vst2.8 {q0, q1}, [r7]!
+ vst2.8 {q2, q3}, [r7]!
+ vst2.8 {q4, q5}, [r7]!
+ vst2.8 {q6, q7}, [r7]!
+ vst2.8 {q8, q9}, [r7]!
+ vst2.8 {q10, q11}, [r7]!
+ vst2.8 {q12, q13}, [r7]!
+ vst2.8 {q14, q15}, [r7]!
+
+ pld [r8, r3]
+ vld1.8 {q0}, [r8]!
+ vld1.8 {q2}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q1}, [r11]!
+ vld1.8 {q3}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q4}, [r8]!
+ vld1.8 {q6}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q5}, [r11]!
+ vld1.8 {q7}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q8}, [r8]!
+ vld1.8 {q10}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q9}, [r11]!
+ vld1.8 {q11}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q12}, [r8]!
+ vld1.8 {q14}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q13}, [r11]!
+ vld1.8 {q15}, [r11], r12
+
+ vst2.8 {q0, q1}, [r7]!
+ vst2.8 {q2, q3}, [r7]!
+ vst2.8 {q4, q5}, [r7]!
+ vst2.8 {q6, q7}, [r7]!
+ vst2.8 {q8, q9}, [r7]!
+ vst2.8 {q10, q11}, [r7]!
+ vst2.8 {q12, q13}, [r7]!
+ vst2.8 {q14, q15}, [r7]!
+
+ pld [r8, r3]
+ vld1.8 {q0}, [r8]!
+ vld1.8 {q2}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q1}, [r11]!
+ vld1.8 {q3}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q4}, [r8]!
+ vld1.8 {q6}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q5}, [r11]!
+ vld1.8 {q7}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q8}, [r8]!
+ vld1.8 {q10}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q9}, [r11]!
+ vld1.8 {q11}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q12}, [r8]!
+ vld1.8 {q14}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q13}, [r11]!
+ vld1.8 {q15}, [r11], r12
+
+ vst2.8 {q0, q1}, [r7]!
+ vst2.8 {q2, q3}, [r7]!
+ vst2.8 {q4, q5}, [r7]!
+ vst2.8 {q6, q7}, [r7]!
+ vst2.8 {q8, q9}, [r7]!
+ vst2.8 {q10, q11}, [r7]!
+ vst2.8 {q12, q13}, [r7]!
+ vst2.8 {q14, q15}, [r7]!
+
+ pld [r8, r3]
+ vld1.8 {q0}, [r8]!
+ vld1.8 {q2}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q1}, [r11]!
+ vld1.8 {q3}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q4}, [r8]!
+ vld1.8 {q6}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q5}, [r11]!
+ vld1.8 {q7}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q8}, [r8]!
+ vld1.8 {q10}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q9}, [r11]!
+ vld1.8 {q11}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q12}, [r8]!
+ vld1.8 {q14}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q13}, [r11]!
+ vld1.8 {q15}, [r11], r12
+
+ vst2.8 {q0, q1}, [r7]!
+ vst2.8 {q2, q3}, [r7]!
+ vst2.8 {q4, q5}, [r7]!
+ vst2.8 {q6, q7}, [r7]!
+ vst2.8 {q8, q9}, [r7]!
+ vst2.8 {q10, q11}, [r7]!
+ vst2.8 {q12, q13}, [r7]!
+ vst2.8 {q14, q15}, [r7]!
+
+ pld [r8, r3]
+ vld1.8 {q0}, [r8]!
+ vld1.8 {q2}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q1}, [r11]!
+ vld1.8 {q3}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q4}, [r8]!
+ vld1.8 {q6}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q5}, [r11]!
+ vld1.8 {q7}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q8}, [r8]!
+ vld1.8 {q10}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q9}, [r11]!
+ vld1.8 {q11}, [r11], r12
+ pld [r8, r3]
+ vld1.8 {q12}, [r8]!
+ vld1.8 {q14}, [r8], r12
+ pld [r11, r3]
+ vld1.8 {q13}, [r11]!
+ vld1.8 {q15}, [r11], r12
+
+ vst2.8 {q0, q1}, [r7]!
+ vst2.8 {q2, q3}, [r7]!
+ vst2.8 {q4, q5}, [r7]!
+ vst2.8 {q6, q7}, [r7]!
+ vst2.8 {q8, q9}, [r7]!
+ vst2.8 {q10, q11}, [r7]!
+ vst2.8 {q12, q13}, [r7]!
+ vst2.8 {q14, q15}, [r7]!
+
+ add r5, r5, #64 @ j = j+64
+ cmp r5, r9 @ j>5
+ mov r11, r5, asr #6 @ temp1 = j>>6
+
+ and r14, r12, #0x1 @ if (temp2 & 0x1)
+ cmp r14, #0x1
+ bne GET_TILED_OFFSET_EVEN_FORMULA_1
+
+GET_TILED_OFFSET_ODD_FORMULA:
+ sub r7, r12, #1 @ tiled_addr = temp2-1
+ add r14, r3, #127 @ temp3 = linear_x_size+127
+ bic r14, r14, #0x7F @ temp3 = (temp3 >>7)<<7
+ mov r14, r14, asr #6 @ temp3 = temp3>>6
+ mul r7, r7, r14 @ tiled_addr = tiled_addr*temp3
+ add r7, r7, r11 @ tiled_addr = tiled_addr+temp1
+ add r7, r7, #2 @ tiled_addr = tiled_addr+2
+ bic r14, r11, #0x3 @ temp3 = (temp1>>2)<<2
+ add r7, r7, r14 @ tiled_addr = tiled_addr+temp3
+ mov r7, r7, lsl #11 @ tiled_addr = tiled_addr<<11
+ b GET_TILED_OFFSET_RETURN
+
+GET_TILED_OFFSET_EVEN_FORMULA_1:
+ add r14, r4, #31 @ temp3 = linear_y_size+31
+ bic r14, r14, #0x1F @ temp3 = (temp3>>5)<<5
+ sub r14, r14, #32 @ temp3 = temp3 - 32
+ cmp r6, r14 @ if (i<(temp3-32)) {
+ bge GET_TILED_OFFSET_EVEN_FORMULA_2
+ add r14, r11, #2 @ temp3 = temp1+2
+ bic r14, r14, #3 @ temp3 = (temp3>>2)<<2
+ add r7, r11, r14 @ tiled_addr = temp1+temp3
+ add r14, r3, #127 @ temp3 = linear_x_size+127
+ bic r14, r14, #0x7F @ temp3 = (temp3>>7)<<7
+ mov r14, r14, asr #6 @ temp3 = temp3>>6
+ mul r12, r12, r14 @ tiled_y_index = tiled_y_index*temp3
+ add r7, r7, r12 @ tiled_addr = tiled_addr+tiled_y_index
+ mov r7, r7, lsl #11 @
+ b GET_TILED_OFFSET_RETURN
+
+GET_TILED_OFFSET_EVEN_FORMULA_2:
+ add r14, r3, #127 @ temp3 = linear_x_size+127
+ bic r14, r14, #0x7F @ temp3 = (temp3>>7)<<7
+ mov r14, r14, asr #6 @ temp3 = temp3>>6
+ mul r7, r12, r14 @ tiled_addr = temp2*temp3
+ add r7, r7, r11 @ tiled_addr = tiled_addr+temp3
+ mov r7, r7, lsl #11 @ tiled_addr = tiled_addr<<11@
+
+GET_TILED_OFFSET_RETURN:
+ ldmfd sp!, {r15} @ restore registers
+ .fnend
+
diff --git a/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_yuv420_nv12t_y_neon.s b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_yuv420_nv12t_y_neon.s
new file mode 100644
index 0000000..3f8932a
--- /dev/null
+++ b/sec_mm/sec_omx/sec_codecs/video/mfc_c110/csc/csc_yuv420_nv12t_y_neon.s
@@ -0,0 +1,451 @@
+/*
+ *
+ * Copyright 2011 Samsung Electronics S.LSI Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * @file csc_yuv420_nv12t_y_neon.s
+ * @brief SEC_OMX specific define
+ * @author ShinWon Lee (shinwon.lee@samsung.com)
+ * @version 1.0
+ * @history
+ * 2011.7.01 : Create
+ */
+
+/*
+ * Converts linear data to tiled.
+ * 1. Y of YUV420P to Y of NV12T
+ * 2. Y of YUV420S to Y of NV12T
+ * 3. UV of YUV420S to UV of NV12T
+ *
+ * @param nv12t_dest
+ * Y or UV plane address of NV12T[out]
+ *
+ * @param yuv420_src
+ * Y or UV plane address of YUV420P(S)[in]
+ *
+ * @param yuv420_width
+ * Width of YUV420[in]
+ *
+ * @param yuv420_height
+ * Y: Height of YUV420, UV: Height/2 of YUV420[in]
+ */
+
+ .arch armv7-a
+ .text
+ .global csc_linear_to_tiled
+ .type csc_linear_to_tiled, %function
+csc_linear_to_tiled:
+ .fnstart
+
+ @r0 tiled_dest
+ @r1 linear_src
+ @r2 linear_x_size
+ @r3 linear_y_size
+ @r4 j
+ @r5 i
+ @r6 nn(tiled_addr)
+ @r7 mm(linear_addr)
+ @r8 aligned_x_size
+ @r9 aligned_y_size
+ @r10 temp1
+ @r11 temp2
+ @r12 temp3
+ @r14 temp4
+
+ stmfd sp!, {r4-r12,r14} @ backup registers
+
+ bic r9, r3, #0x1F @ aligned_y_size = (linear_y_size>>5)<<5
+ bic r8, r2, #0x3F @ aligned_x_size = (linear_x_size>>6)<<6
+
+ mov r5, #0 @ i = 0
+LOOP_ALIGNED_Y_SIZE:
+
+ mov r4, #0 @ j = 0
+LOOP_ALIGNED_X_SIZE:
+
+ bl GET_TILED_OFFSET
+
+ mul r10, r2, r5 @ temp1 = linear_x_size*(i)
+ add r7, r1, r4 @ linear_addr = linear_src+j
+ add r7, r7, r10 @ linear_addr = linear_addr+temp1
+ sub r10, r2, #32
+
+ pld [r7, r2, lsl #1]
+ vld1.8 {q0, q1}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q2, q3}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q4, q5}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q6, q7}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q8, q9}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q10, q11}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q12, q13}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q14, q15}, [r7], r10
+
+ add r6, r0, r6 @ tiled_addr = tiled_dest+tiled_addr
+
+ vst1.8 {q0, q1}, [r6]!
+ vst1.8 {q2, q3}, [r6]!
+ vst1.8 {q4, q5}, [r6]!
+ vst1.8 {q6, q7}, [r6]!
+ vst1.8 {q8, q9}, [r6]!
+ vst1.8 {q10, q11}, [r6]!
+ vst1.8 {q12, q13}, [r6]!
+ vst1.8 {q14, q15}, [r6]!
+
+ pld [r7, r2, lsl #1]
+ vld1.8 {q0, q1}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q2, q3}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q4, q5}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q6, q7}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q8, q9}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q10, q11}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q12, q13}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q14, q15}, [r7], r10
+
+ vst1.8 {q0, q1}, [r6]!
+ vst1.8 {q2, q3}, [r6]!
+ vst1.8 {q4, q5}, [r6]!
+ vst1.8 {q6, q7}, [r6]!
+ vst1.8 {q8, q9}, [r6]!
+ vst1.8 {q10, q11}, [r6]!
+ vst1.8 {q12, q13}, [r6]!
+ vst1.8 {q14, q15}, [r6]!
+
+ pld [r7, r2, lsl #1]
+ vld1.8 {q0, q1}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q2, q3}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q4, q5}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q6, q7}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q8, q9}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q10, q11}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q12, q13}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q14, q15}, [r7], r10
+
+ vst1.8 {q0, q1}, [r6]!
+ vst1.8 {q2, q3}, [r6]!
+ vst1.8 {q4, q5}, [r6]!
+ vst1.8 {q6, q7}, [r6]!
+ vst1.8 {q8, q9}, [r6]!
+ vst1.8 {q10, q11}, [r6]!
+ vst1.8 {q12, q13}, [r6]!
+ vst1.8 {q14, q15}, [r6]!
+
+ pld [r7, r2, lsl #1]
+ vld1.8 {q0, q1}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q2, q3}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q4, q5}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q6, q7}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q8, q9}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q10, q11}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q12, q13}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q14, q15}, [r7], r10
+
+ vst1.8 {q0, q1}, [r6]!
+ vst1.8 {q2, q3}, [r6]!
+ vst1.8 {q4, q5}, [r6]!
+ vst1.8 {q6, q7}, [r6]!
+ vst1.8 {q8, q9}, [r6]!
+ vst1.8 {q10, q11}, [r6]!
+ vst1.8 {q12, q13}, [r6]!
+ vst1.8 {q14, q15}, [r6]!
+
+ pld [r7, r2, lsl #1]
+ vld1.8 {q0, q1}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q2, q3}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q4, q5}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q6, q7}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q8, q9}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q10, q11}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q12, q13}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q14, q15}, [r7], r10
+
+ vst1.8 {q0, q1}, [r6]!
+ vst1.8 {q2, q3}, [r6]!
+ vst1.8 {q4, q5}, [r6]!
+ vst1.8 {q6, q7}, [r6]!
+ vst1.8 {q8, q9}, [r6]!
+ vst1.8 {q10, q11}, [r6]!
+ vst1.8 {q12, q13}, [r6]!
+ vst1.8 {q14, q15}, [r6]!
+
+ pld [r7, r2, lsl #1]
+ vld1.8 {q0, q1}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q2, q3}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q4, q5}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q6, q7}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q8, q9}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q10, q11}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q12, q13}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q14, q15}, [r7], r10
+
+ vst1.8 {q0, q1}, [r6]!
+ vst1.8 {q2, q3}, [r6]!
+ vst1.8 {q4, q5}, [r6]!
+ vst1.8 {q6, q7}, [r6]!
+ vst1.8 {q8, q9}, [r6]!
+ vst1.8 {q10, q11}, [r6]!
+ vst1.8 {q12, q13}, [r6]!
+ vst1.8 {q14, q15}, [r6]!
+
+ pld [r7, r2, lsl #1]
+ vld1.8 {q0, q1}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q2, q3}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q4, q5}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q6, q7}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q8, q9}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q10, q11}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q12, q13}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q14, q15}, [r7], r10
+
+ vst1.8 {q0, q1}, [r6]!
+ vst1.8 {q2, q3}, [r6]!
+ vst1.8 {q4, q5}, [r6]!
+ vst1.8 {q6, q7}, [r6]!
+ vst1.8 {q8, q9}, [r6]!
+ vst1.8 {q10, q11}, [r6]!
+ vst1.8 {q12, q13}, [r6]!
+ vst1.8 {q14, q15}, [r6]!
+
+ pld [r7, r2, lsl #1]
+ vld1.8 {q0, q1}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q2, q3}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q4, q5}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q6, q7}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q8, q9}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q10, q11}, [r7], r10
+ pld [r7, r2, lsl #1]
+ vld1.8 {q12, q13}, [r7]!
+ pld [r7, r2, lsl #1]
+ vld1.8 {q14, q15}, [r7], r10
+
+ vst1.8 {q0, q1}, [r6]!
+ vst1.8 {q2, q3}, [r6]!
+ vst1.8 {q4, q5}, [r6]!
+ vst1.8 {q6, q7}, [r6]!
+ vst1.8 {q8, q9}, [r6]!
+ vst1.8 {q10, q11}, [r6]!
+ vst1.8 {q12, q13}, [r6]!
+ vst1.8 {q14, q15}, [r6]!
+
+ add r4, r4, #64 @ j = j+64
+ cmp r4, r8 @ j