PageRenderTime 78ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/exynos4/hal/libhdmi/libhdmiservice/SecTVOutService.cpp

https://bitbucket.org/cyanogenmod/android_hardware_samsung
C++ | 387 lines | 298 code | 62 blank | 27 comment | 69 complexity | d8722715bf26268530804c739f01abf9 MD5 | raw file
  1. /*
  2. **
  3. ** Copyright 2008, The Android Open Source Project
  4. ** Copyright 2010, Samsung Electronics Co. LTD
  5. **
  6. ** Licensed under the Apache License, Version 2.0 (the "License");
  7. ** you may not use this file except in compliance with the License.
  8. ** You may obtain a copy of the License at
  9. **
  10. ** http://www.apache.org/licenses/LICENSE-2.0
  11. **
  12. ** Unless required by applicable law or agreed to in writing, software
  13. ** distributed under the License is distributed on an "AS IS" BASIS,
  14. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. ** See the License for the specific language governing permissions and
  16. ** limitations under the License.
  17. */
  18. /*
  19. **
  20. ** @author Taikyung, Yu(taikyung.yu@samsung.com)
  21. ** @date 2011-07-06
  22. */
  23. #define LOG_TAG "SecTVOutService"
  24. #include <binder/IServiceManager.h>
  25. #include <utils/RefBase.h>
  26. #include <binder/IInterface.h>
  27. #include <binder/Parcel.h>
  28. #include <utils/Log.h>
  29. #include "SecTVOutService.h"
  30. #include <linux/fb.h>
  31. namespace android {
  32. #define DEFAULT_LCD_WIDTH 800
  33. #define DEFAULT_LCD_HEIGHT 480
  34. #define DIRECT_VIDEO_RENDERING (1)
  35. #define DIRECT_UI_RENDERING (0)
  36. enum {
  37. SET_HDMI_STATUS = IBinder::FIRST_CALL_TRANSACTION,
  38. SET_HDMI_MODE,
  39. SET_HDMI_RESOLUTION,
  40. SET_HDMI_HDCP,
  41. SET_HDMI_ROTATE,
  42. SET_HDMI_HWCLAYER,
  43. BLIT_2_HDMI
  44. };
  45. int SecTVOutService::HdmiFlushThread()
  46. {
  47. while (!mExitHdmiFlushThread) {
  48. nsecs_t timeout = -1;
  49. sp<MessageBase> msg = mHdmiEventQueue.waitMessage(timeout);
  50. }
  51. return 0;
  52. }
  53. int SecTVOutService::instantiate()
  54. {
  55. ALOGD("SecTVOutService instantiate");
  56. int r = defaultServiceManager()->addService(String16( "SecTVOutService"), new SecTVOutService ());
  57. ALOGD("SecTVOutService r=%d", r);
  58. return r;
  59. }
  60. SecTVOutService::SecTVOutService () {
  61. ALOGV("SecTVOutService created");
  62. mHdmiCableInserted = false;
  63. #ifdef SUPPORT_G2D_UI_MODE
  64. mUILayerMode = SecHdmi::HDMI_LAYER_GRAPHIC_1;
  65. #else
  66. mUILayerMode = SecHdmi::HDMI_LAYER_VIDEO;
  67. #endif
  68. mHwcLayer = 0;
  69. mExitHdmiFlushThread = false;
  70. setLCDsize();
  71. if (mSecHdmi.create(mLCD_width, mLCD_height) == false)
  72. ALOGE("%s::mSecHdmi.create() fail", __func__);
  73. else
  74. setHdmiStatus(1);
  75. mHdmiFlushThread = new HDMIFlushThread(this);
  76. }
  77. void SecTVOutService::setLCDsize(void) {
  78. char const * const device_template[] = {
  79. "/dev/graphics/fb%u",
  80. "/dev/fb%u",
  81. 0 };
  82. int fd = -1;
  83. int i = 0;
  84. char name[64];
  85. while ((fd==-1) && device_template[i]) {
  86. snprintf(name, 64, device_template[i], 0);
  87. fd = open(name, O_RDWR, 0);
  88. i++;
  89. }
  90. if (fd > 0) {
  91. struct fb_var_screeninfo info;
  92. if (ioctl(fd, FBIOGET_VSCREENINFO, &info) != -1) {
  93. mLCD_width = info.xres;
  94. mLCD_height = info.yres;
  95. } else {
  96. mLCD_width = DEFAULT_LCD_WIDTH;
  97. mLCD_height = DEFAULT_LCD_HEIGHT;
  98. }
  99. close(fd);
  100. }
  101. return;
  102. }
  103. SecTVOutService::~SecTVOutService () {
  104. ALOGV ("SecTVOutService destroyed");
  105. if (mHdmiFlushThread != NULL) {
  106. mHdmiFlushThread->requestExit();
  107. mExitHdmiFlushThread = true;
  108. mHdmiFlushThread->requestExitAndWait();
  109. mHdmiFlushThread.clear();
  110. }
  111. }
  112. status_t SecTVOutService::onTransact(uint32_t code, const Parcel & data, Parcel * reply, uint32_t flags)
  113. {
  114. switch (code) {
  115. case SET_HDMI_STATUS: {
  116. int status = data.readInt32();
  117. setHdmiStatus(status);
  118. } break;
  119. case SET_HDMI_MODE: {
  120. int mode = data.readInt32();
  121. setHdmiMode(mode);
  122. } break;
  123. case SET_HDMI_RESOLUTION: {
  124. int resolution = data.readInt32();
  125. setHdmiResolution(resolution);
  126. } break;
  127. case SET_HDMI_HDCP: {
  128. int enHdcp = data.readInt32();
  129. setHdmiHdcp(enHdcp);
  130. } break;
  131. case SET_HDMI_ROTATE: {
  132. int rotVal = data.readInt32();
  133. int hwcLayer = data.readInt32();
  134. setHdmiRotate(rotVal, hwcLayer);
  135. } break;
  136. case SET_HDMI_HWCLAYER: {
  137. int hwcLayer = data.readInt32();
  138. setHdmiHwcLayer((uint32_t)hwcLayer);
  139. } break;
  140. case BLIT_2_HDMI: {
  141. uint32_t w = data.readInt32();
  142. uint32_t h = data.readInt32();
  143. uint32_t colorFormat = data.readInt32();
  144. uint32_t physYAddr = data.readInt32();
  145. uint32_t physCbAddr = data.readInt32();
  146. uint32_t physCrAddr = data.readInt32();
  147. uint32_t dstX = data.readInt32();
  148. uint32_t dstY = data.readInt32();
  149. uint32_t hdmiLayer = data.readInt32();
  150. uint32_t num_of_hwc_layer = data.readInt32();
  151. blit2Hdmi(w, h, colorFormat, physYAddr, physCbAddr, physCrAddr, dstX, dstY, hdmiLayer, num_of_hwc_layer);
  152. } break;
  153. default :
  154. ALOGE ( "onTransact::default");
  155. return BBinder::onTransact (code, data, reply, flags);
  156. }
  157. return NO_ERROR;
  158. }
  159. void SecTVOutService::setHdmiStatus(uint32_t status)
  160. {
  161. ALOGD("%s HDMI cable status = %d", __func__, status);
  162. {
  163. Mutex::Autolock _l(mLock);
  164. bool hdmiCableInserted = (bool)status;
  165. if (mHdmiCableInserted == hdmiCableInserted)
  166. return;
  167. if (hdmiCableInserted == true) {
  168. if (mSecHdmi.connect() == false) {
  169. ALOGE("%s::mSecHdmi.connect() fail", __func__);
  170. hdmiCableInserted = false;
  171. }
  172. } else {
  173. if (mSecHdmi.disconnect() == false)
  174. ALOGE("%s::mSecHdmi.disconnect() fail", __func__);
  175. }
  176. mHdmiCableInserted = hdmiCableInserted;
  177. }
  178. if (hdmiCableInserted() == true)
  179. this->blit2Hdmi(mLCD_width, mLCD_height, HAL_PIXEL_FORMAT_BGRA_8888, 0, 0, 0, 0, 0, HDMI_MODE_UI, 0);
  180. }
  181. void SecTVOutService::setHdmiMode(uint32_t mode)
  182. {
  183. ALOGD("%s TV mode = %d", __func__, mode);
  184. Mutex::Autolock _l(mLock);
  185. if ((hdmiCableInserted() == true) && (mSecHdmi.setHdmiOutputMode(mode)) == false) {
  186. ALOGE("%s::mSecHdmi.setHdmiOutputMode() fail", __func__);
  187. return;
  188. }
  189. }
  190. void SecTVOutService::setHdmiResolution(uint32_t resolution)
  191. {
  192. //ALOGD("%s TV resolution = %d", __func__, resolution);
  193. Mutex::Autolock _l(mLock);
  194. if ((hdmiCableInserted() == true) && (mSecHdmi.setHdmiResolution(resolution)) == false) {
  195. ALOGE("%s::mSecHdmi.setHdmiResolution() fail", __func__);
  196. return;
  197. }
  198. }
  199. void SecTVOutService::setHdmiHdcp(uint32_t hdcp_en)
  200. {
  201. ALOGD("%s TV HDCP = %d", __func__, hdcp_en);
  202. Mutex::Autolock _l(mLock);
  203. if ((hdmiCableInserted() == true) && (mSecHdmi.setHdcpMode(hdcp_en)) == false) {
  204. ALOGE("%s::mSecHdmi.setHdcpMode() fail", __func__);
  205. return;
  206. }
  207. }
  208. void SecTVOutService::setHdmiRotate(uint32_t rotVal, uint32_t hwcLayer)
  209. {
  210. //ALOGD("%s TV ROTATE = %d", __func__, rotVal);
  211. Mutex::Autolock _l(mLock);
  212. if ((hdmiCableInserted() == true) && (mSecHdmi.setUIRotation(rotVal, hwcLayer)) == false) {
  213. ALOGE("%s::mSecHdmi.setUIRotation() fail", __func__);
  214. return;
  215. }
  216. }
  217. void SecTVOutService::setHdmiHwcLayer(uint32_t hwcLayer)
  218. {
  219. //ALOGD("%s TV HWCLAYER = %d", __func__, hwcLayer);
  220. Mutex::Autolock _l(mLock);
  221. mHwcLayer = hwcLayer;
  222. return;
  223. }
  224. void SecTVOutService::blit2Hdmi(uint32_t w, uint32_t h, uint32_t colorFormat,
  225. uint32_t pPhyYAddr, uint32_t pPhyCbAddr, uint32_t pPhyCrAddr,
  226. uint32_t dstX, uint32_t dstY,
  227. uint32_t hdmiMode,
  228. uint32_t num_of_hwc_layer)
  229. {
  230. Mutex::Autolock _l(mLock);
  231. if (hdmiCableInserted() == false)
  232. return;
  233. int hdmiLayer = SecHdmi::HDMI_LAYER_VIDEO;
  234. #if defined(CHECK_UI_TIME) || defined(CHECK_VIDEO_TIME)
  235. nsecs_t start, end;
  236. #endif
  237. sp<MessageBase> msg;
  238. switch (hdmiMode) {
  239. case HDMI_MODE_UI :
  240. if (mHwcLayer >= 2)
  241. hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_0;
  242. else if (mHwcLayer == 1)
  243. hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_1;
  244. else
  245. #ifdef SUPPORT_G2D_UI_MODE
  246. hdmiLayer = SecHdmi::HDMI_LAYER_GRAPHIC_1;
  247. #else
  248. hdmiLayer = SecHdmi::HDMI_LAYER_VIDEO;
  249. #endif
  250. #ifdef SUPPORT_G2D_UI_MODE
  251. if (mHwcLayer == 0) {
  252. if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_VIDEO) == false)
  253. ALOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_VIDEO);
  254. if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_GRAPHIC_0) == false)
  255. ALOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_GRAPHIC_0);
  256. }
  257. #endif
  258. if (mUILayerMode != hdmiLayer) {
  259. if (mSecHdmi.clear(mUILayerMode) == false)
  260. ALOGE("%s::mSecHdmi.clear(%d) fail", __func__, mUILayerMode);
  261. }
  262. mUILayerMode = hdmiLayer;
  263. #if !defined(BOARD_USES_HDMI_SUBTITLES)
  264. if (mHwcLayer == 0)
  265. #endif
  266. #if (DIRECT_UI_RENDERING == 1)
  267. {
  268. #ifdef CHECK_UI_TIME
  269. start = systemTime();
  270. #endif
  271. if (mSecHdmi.flush(w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, dstX, dstY,
  272. mUILayerMode, mHwcLayer) == false)
  273. ALOGE("%s::mSecHdmi.flush() on HDMI_MODE_UI fail", __func__);
  274. #ifdef CHECK_UI_TIME
  275. end = systemTime();
  276. ALOGD("[UI] mSecHdmi.flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start)));
  277. #endif
  278. }
  279. #else
  280. {
  281. msg = new SecHdmiEventMsg(&mSecHdmi, w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr,
  282. dstX, dstY, mUILayerMode, mHwcLayer, HDMI_MODE_UI);
  283. /* post to HdmiEventQueue */
  284. mHdmiEventQueue.postMessage(msg, 0, 0);
  285. }
  286. #endif
  287. break;
  288. case HDMI_MODE_VIDEO :
  289. #if !defined(BOARD_USES_HDMI_SUBTITLES)
  290. #ifdef SUPPORT_G2D_UI_MODE
  291. if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_GRAPHIC_0) == false)
  292. ALOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_GRAPHIC_0);
  293. if (mSecHdmi.clear(SecHdmi::HDMI_LAYER_GRAPHIC_1) == false)
  294. ALOGE("%s::mSecHdmi.clear(%d) fail", __func__, SecHdmi::HDMI_LAYER_GRAPHIC_1);
  295. #endif
  296. #endif
  297. #if (DIRECT_VIDEO_RENDERING == 1)
  298. #ifdef CHECK_VIDEO_TIME
  299. start = systemTime();
  300. #endif
  301. if (mSecHdmi.flush(w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr, dstX, dstY,
  302. SecHdmi::HDMI_LAYER_VIDEO, mHwcLayer) == false)
  303. ALOGE("%s::mSecHdmi.flush() on HDMI_MODE_VIDEO fail", __func__);
  304. #ifdef CHECK_VIDEO_TIME
  305. end = systemTime();
  306. ALOGD("[Video] mSecHdmi.flush[end-start] = %ld ms", long(ns2ms(end)) - long(ns2ms(start)));
  307. #endif
  308. #else
  309. msg = new SecHdmiEventMsg(&mSecHdmi, w, h, colorFormat, pPhyYAddr, pPhyCbAddr, pPhyCrAddr,
  310. dstX, dstY, SecHdmi::HDMI_LAYER_VIDEO, mHwcLayer, HDMI_MODE_VIDEO);
  311. /* post to HdmiEventQueue */
  312. mHdmiEventQueue.postMessage(msg, 0, 0);
  313. #endif
  314. break;
  315. default:
  316. ALOGE("unmatched HDMI_MODE : %d", hdmiMode);
  317. break;
  318. }
  319. return;
  320. }
  321. bool SecTVOutService::hdmiCableInserted(void)
  322. {
  323. return mHdmiCableInserted;
  324. }
  325. }