2 * Copyright (C) 2011-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "EGLNativeTypeAmlogic.h"
22 #include "guilib/gui3d.h"
23 #include "utils/AMLUtils.h"
24 #include "utils/StringUtils.h"
28 #include <sys/ioctl.h>
31 CEGLNativeTypeAmlogic::CEGLNativeTypeAmlogic()
33 const char *env_framebuffer = getenv("FRAMEBUFFER");
35 // default to framebuffer 0
36 m_framebuffer_name = "fb0";
39 std::string framebuffer(env_framebuffer);
40 std::string::size_type start = framebuffer.find("fb");
41 m_framebuffer_name = framebuffer.substr(start);
43 m_nativeWindow = NULL;
46 CEGLNativeTypeAmlogic::~CEGLNativeTypeAmlogic()
50 bool CEGLNativeTypeAmlogic::CheckCompatibility()
53 std::string modalias = "/sys/class/graphics/" + m_framebuffer_name + "/device/modalias";
55 aml_get_sysfs_str(modalias.c_str(), name, 255);
56 CStdString strName = name;
58 if (strName == "platform:mesonfb")
63 void CEGLNativeTypeAmlogic::Initialize()
66 aml_cpufreq_min(true);
67 aml_cpufreq_max(true);
70 void CEGLNativeTypeAmlogic::Destroy()
72 aml_cpufreq_min(false);
73 aml_cpufreq_max(false);
77 bool CEGLNativeTypeAmlogic::CreateNativeDisplay()
79 m_nativeDisplay = EGL_DEFAULT_DISPLAY;
83 bool CEGLNativeTypeAmlogic::CreateNativeWindow()
85 #if defined(_FBDEV_WINDOW_H_)
86 fbdev_window *nativeWindow = new fbdev_window;
90 nativeWindow->width = 1280;
91 nativeWindow->height = 720;
92 m_nativeWindow = nativeWindow;
99 bool CEGLNativeTypeAmlogic::GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const
103 *nativeDisplay = (XBNativeDisplayType*) &m_nativeDisplay;
107 bool CEGLNativeTypeAmlogic::GetNativeWindow(XBNativeWindowType **nativeWindow) const
111 *nativeWindow = (XBNativeWindowType*) &m_nativeWindow;
115 bool CEGLNativeTypeAmlogic::DestroyNativeDisplay()
120 bool CEGLNativeTypeAmlogic::DestroyNativeWindow()
122 #if defined(_FBDEV_WINDOW_H_)
123 delete (fbdev_window*)m_nativeWindow, m_nativeWindow = NULL;
128 bool CEGLNativeTypeAmlogic::GetNativeResolution(RESOLUTION_INFO *res) const
130 char mode[256] = {0};
131 aml_get_sysfs_str("/sys/class/display/mode", mode, 255);
132 return ModeToResolution(mode, res);
135 bool CEGLNativeTypeAmlogic::SetNativeResolution(const RESOLUTION_INFO &res)
137 switch((int)(0.5 + res.fRefreshRate))
141 switch(res.iScreenWidth)
145 SetDisplayResolution("720p");
148 if (res.dwFlags & D3DPRESENTFLAG_INTERLACED)
149 SetDisplayResolution("1080i");
151 SetDisplayResolution("1080p");
156 switch(res.iScreenWidth)
160 SetDisplayResolution("720p50hz");
163 if (res.dwFlags & D3DPRESENTFLAG_INTERLACED)
164 SetDisplayResolution("1080i50hz");
166 SetDisplayResolution("1080p50hz");
171 SetDisplayResolution("1080p30hz");
174 SetDisplayResolution("1080p24hz");
181 bool CEGLNativeTypeAmlogic::ProbeResolutions(std::vector<RESOLUTION_INFO> &resolutions)
183 char valstr[256] = {0};
184 aml_get_sysfs_str("/sys/class/amhdmitx/amhdmitx0/disp_cap", valstr, 255);
185 std::vector<CStdString> probe_str;
186 StringUtils::SplitString(valstr, "\n", probe_str);
190 for (size_t i = 0; i < probe_str.size(); i++)
192 if(ModeToResolution(probe_str[i].c_str(), &res))
193 resolutions.push_back(res);
195 return resolutions.size() > 0;
199 bool CEGLNativeTypeAmlogic::GetPreferredResolution(RESOLUTION_INFO *res) const
201 // check display/mode, it gets defaulted at boot
202 if (!GetNativeResolution(res))
204 // punt to 720p if we get nothing
205 ModeToResolution("720p", res);
211 bool CEGLNativeTypeAmlogic::ShowWindow(bool show)
213 std::string blank_framebuffer = "/sys/class/graphics/" + m_framebuffer_name + "/blank";
214 aml_set_sysfs_int(blank_framebuffer.c_str(), show ? 0 : 1);
218 bool CEGLNativeTypeAmlogic::SetDisplayResolution(const char *resolution)
220 CStdString modestr = resolution;
221 // switch display resolution
222 aml_set_sysfs_str("/sys/class/display/mode", modestr.c_str());
224 // setup gui freescale depending on display resolution
226 if (StringUtils::StartsWith(modestr, "1080"))
234 bool CEGLNativeTypeAmlogic::ModeToResolution(const char *mode, RESOLUTION_INFO *res) const
245 CStdString fromMode = mode;
247 // strips, for example, 720p* to 720p
248 // the * indicate the 'native' mode of the display
249 if (fromMode.Right(1) == "*")
250 fromMode = fromMode.Left(std::max(0, (int)fromMode.size() - 1));
252 if (fromMode.Equals("720p"))
256 res->iScreenWidth = 1280;
257 res->iScreenHeight= 720;
258 res->fRefreshRate = 60;
259 res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
261 else if (fromMode.Equals("720p50hz"))
265 res->iScreenWidth = 1280;
266 res->iScreenHeight= 720;
267 res->fRefreshRate = 50;
268 res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
270 else if (fromMode.Equals("1080p"))
274 res->iScreenWidth = 1920;
275 res->iScreenHeight= 1080;
276 res->fRefreshRate = 60;
277 res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
279 else if (fromMode.Equals("1080p24hz"))
283 res->iScreenWidth = 1920;
284 res->iScreenHeight= 1080;
285 res->fRefreshRate = 24;
286 res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
288 else if (fromMode.Equals("1080p30hz"))
292 res->iScreenWidth = 1920;
293 res->iScreenHeight= 1080;
294 res->fRefreshRate = 30;
295 res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
297 else if (fromMode.Equals("1080p50hz"))
301 res->iScreenWidth = 1920;
302 res->iScreenHeight= 1080;
303 res->fRefreshRate = 50;
304 res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
306 else if (fromMode.Equals("1080i"))
310 res->iScreenWidth = 1920;
311 res->iScreenHeight= 1080;
312 res->fRefreshRate = 60;
313 res->dwFlags = D3DPRESENTFLAG_INTERLACED;
315 else if (fromMode.Equals("1080i50hz"))
319 res->iScreenWidth = 1920;
320 res->iScreenHeight= 1080;
321 res->fRefreshRate = 50;
322 res->dwFlags = D3DPRESENTFLAG_INTERLACED;
331 res->bFullScreen = true;
332 res->iSubtitles = (int)(0.965 * res->iHeight);
333 res->fPixelRatio = 1.0f;
334 res->strMode.Format("%dx%d @ %.2f%s - Full Screen", res->iScreenWidth, res->iScreenHeight, res->fRefreshRate,
335 res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : "");
337 return res->iWidth > 0 && res->iHeight> 0;
340 void CEGLNativeTypeAmlogic::EnableFreeScale()
342 // enable OSD free scale using frame buffer size of 720p
343 aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0);
344 aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0);
345 aml_set_sysfs_int("/sys/class/graphics/fb0/scale_width", 1280);
346 aml_set_sysfs_int("/sys/class/graphics/fb0/scale_height", 720);
347 aml_set_sysfs_int("/sys/class/graphics/fb1/scale_width", 1280);
348 aml_set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720);
350 // enable video free scale (scaling to 1920x1080 with frame buffer size 1280x720)
351 aml_set_sysfs_int("/sys/class/ppmgr/ppscaler", 0);
352 aml_set_sysfs_int("/sys/class/video/disable_video", 1);
353 aml_set_sysfs_int("/sys/class/ppmgr/ppscaler", 1);
354 aml_set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1919 1079 0");
355 aml_set_sysfs_str("/sys/class/ppmgr/disp", "1280 720");
357 aml_set_sysfs_int("/sys/class/graphics/fb0/scale_width", 1280);
358 aml_set_sysfs_int("/sys/class/graphics/fb0/scale_height", 720);
359 aml_set_sysfs_int("/sys/class/graphics/fb1/scale_width", 1280);
360 aml_set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720);
362 aml_set_sysfs_int("/sys/class/video/disable_video", 2);
363 aml_set_sysfs_str("/sys/class/display/axis", "0 0 1279 719 0 0 0 0");
364 aml_set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1279 719 1");
366 aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 1);
367 aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 1);
368 aml_set_sysfs_str("/sys/class/graphics/fb0/free_scale_axis", "0 0 1279 719");
371 void CEGLNativeTypeAmlogic::DisableFreeScale()
373 // turn off frame buffer freescale
374 aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0);
375 aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0);
376 aml_set_sysfs_str("/sys/class/graphics/fb0/free_scale_axis", "0 0 1279 719");
378 aml_set_sysfs_int("/sys/class/ppmgr/ppscaler", 0);
379 aml_set_sysfs_int("/sys/class/video/disable_video", 0);
380 // now default video display to off
381 aml_set_sysfs_int("/sys/class/video/disable_video", 1);
383 // revert display axis
385 std::string framebuffer = "/dev/" + m_framebuffer_name;
387 if ((fd0 = open(framebuffer.c_str(), O_RDWR)) >= 0)
389 struct fb_var_screeninfo vinfo;
390 if (ioctl(fd0, FBIOGET_VSCREENINFO, &vinfo) == 0)
392 char daxis_str[255] = {0};
393 sprintf(daxis_str, "%d %d %d %d 0 0 0 0", 0, 0, vinfo.xres-1, vinfo.yres-1);
394 aml_set_sysfs_str("/sys/class/display/axis", daxis_str);