Skip to content

Commit

Permalink
[IMX] probe & push all resolutions we can use
Browse files Browse the repository at this point in the history
      beside standard(S), try also DVI(U), VESA(V)

 - try in order S -> U -> V
 - don't add modes with resolution & refresh we alredy have
 - S are preferred (over other types with same XxYxR) because
   they come from EDID(CEA) and do pass requirements
   for proper hdmi audio out

 (this superseeds sam's PR and was rediscussed with
  fritsch on IRC.)
  • Loading branch information
mk01 authored and fritsch committed May 1, 2015
1 parent e914e64 commit 4533885
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 5 deletions.
98 changes: 93 additions & 5 deletions xbmc/windowing/egl/EGLNativeTypeIMX.cpp
Expand Up @@ -39,6 +39,7 @@
CEGLNativeTypeIMX::CEGLNativeTypeIMX()
: m_display(NULL)
, m_window(NULL)
, m_sar(0)
{
}

Expand Down Expand Up @@ -126,6 +127,7 @@ void CEGLNativeTypeIMX::Initialize()

close(fd);

m_sar = GetMonitorSAR();
return;
}

Expand Down Expand Up @@ -262,24 +264,47 @@ bool CEGLNativeTypeIMX::SetNativeResolution(const RESOLUTION_INFO &res)
return true;
}

bool CEGLNativeTypeIMX::FindMatchingResolution(const RESOLUTION_INFO &res, const std::vector<RESOLUTION_INFO> &resolutions)
{
for (int i = 0; i < (int)resolutions.size(); i++)
{
if(resolutions[i].iScreenWidth == res.iScreenWidth &&
resolutions[i].iScreenHeight == res.iScreenHeight &&
resolutions[i].fRefreshRate == res.fRefreshRate &&
(resolutions[i].dwFlags & D3DPRESENTFLAG_MODEMASK) == (res.dwFlags & D3DPRESENTFLAG_MODEMASK))
{
return true;
}
}
return false;
}

bool CEGLNativeTypeIMX::ProbeResolutions(std::vector<RESOLUTION_INFO> &resolutions)
{
if (m_readonly)
return false;

std::string valstr;
SysfsUtils::GetString("/sys/class/graphics/fb0/modes", valstr);
std::vector<std::string> probe_str;
probe_str = StringUtils::Split(valstr, "\n");
std::vector<std::string> probe_str = StringUtils::Split(valstr, "\n");

// lexical order puts the modes list into our preferred
// order and by later filtering through FindMatchingResolution()
// we make sure we read _all_ S modes, following U and V modes
// while list will hold unique resolutions only
std::sort(probe_str.begin(), probe_str.end());

resolutions.clear();
RESOLUTION_INFO res;
for (size_t i = 0; i < probe_str.size(); i++)
{
if(!StringUtils::StartsWith(probe_str[i], "S:"))
if(!StringUtils::StartsWith(probe_str[i], "S:") && !StringUtils::StartsWith(probe_str[i], "U:") &&
!StringUtils::StartsWith(probe_str[i], "V:"))
continue;

if(ModeToResolution(probe_str[i], &res))
resolutions.push_back(res);
if(!FindMatchingResolution(res, resolutions))
resolutions.push_back(res);
}
return resolutions.size() > 0;
}
Expand All @@ -300,6 +325,68 @@ bool CEGLNativeTypeIMX::ShowWindow(bool show)
return false;
}

float CEGLNativeTypeIMX::GetMonitorSAR()
{
FILE *f_edid;
char *str = NULL;
unsigned char p;
size_t n;
int done = 0;

// kernels <= 3.18 use ./soc0/soc.0
// kernels > 3.18 use ./soc0/soc
f_edid = fopen("/sys/devices/soc0/soc/20e0000.hdmi_video/edid", "r");
if(!f_edid)
f_edid = fopen("/sys/devices/soc0/soc.0/20e0000.hdmi_video/edid", "r");

This comment has been minimized.

Copy link
@samnazarko

samnazarko May 7, 2015

On Vero, this is osmc@vero:/sys/devices/soc0/soc.1/20e0000.hdmi_video on LK 3.14

This comment has been minimized.

Copy link
@fritsch

fritsch May 7, 2015

Owner

Yeah - same for i4. It's a typo. It will fallback to 1.0 for pixel ratio - so won't harm for now.

ping @mk01

This comment has been minimized.

Copy link
@fritsch

fritsch May 7, 2015

Owner

Thx I opened a PR to fix that.

This comment has been minimized.

Copy link
@mk01

mk01 May 8, 2015

Author

yes, my bad


if(!f_edid)
return 0;

// we need to convert mxc_hdmi output format to binary array
// mxc_hdmi provides the EDID as space delimited 1bytes blocks
// exported as text with format specifier %x eg:
// 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0x4C 0x2D 0x7A 0x0A 0x00 0x00 0x00 0x00
//
// this translates into the inner cycle where we move pointer first
// with +2 to skip '0x',
// we sscanf actual data (eg FF) into a byte,
// we move over the FF and delimiting space with +3
//
// this parses whole 512 byte long info into internal binary array for future
// reference and use. current use is only to grab screen's physical params
// at EGL init.
while(getline(&str, &n, f_edid) > 0)
{
char *c = str;
while(*c != '\n' && done < 512)
{
c += 2;
sscanf(c, "%hhx", &p);
m_edid[done++] = p;
c += 3;
}
if (str)
free(str);
str = NULL;
}
fclose(f_edid);

// info related to 'Basic display parameters.' is at offset 0x14-0x18.
// where W is 2nd byte, H 3rd.
int cmWidth = (int)*(m_edid +EDID_STRUCT_DISPLAY +1);
int cmHeight = (int)*(m_edid +EDID_STRUCT_DISPLAY +2);
if (cmHeight > 0)
{
float t_sar = (float) cmWidth / cmHeight;
if (t_sar >= 0.33 && t_sar <= 3.0)
return t_sar;
}

// if we end up here, H/W values or final SAR are useless
// return 0 and use 1.0f as PR for all resolutions
return 0;
}

bool CEGLNativeTypeIMX::ModeToResolution(std::string mode, RESOLUTION_INFO *res) const
{
if (!res)
Expand Down Expand Up @@ -334,7 +421,8 @@ bool CEGLNativeTypeIMX::ModeToResolution(std::string mode, RESOLUTION_INFO *res)
res->iScreen = 0;
res->bFullScreen = true;
res->iSubtitles = (int)(0.965 * res->iHeight);
res->fPixelRatio = 1.0f;

res->fPixelRatio = !m_sar ? 1.0f : (float)m_sar / res->iScreenWidth * res->iScreenHeight;
res->strMode = StringUtils::Format("%dx%d @ %.2f%s - Full Screen", res->iScreenWidth, res->iScreenHeight, res->fRefreshRate,
res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : "");
res->strId = mode;
Expand Down
6 changes: 6 additions & 0 deletions xbmc/windowing/egl/EGLNativeTypeIMX.h
Expand Up @@ -22,6 +22,8 @@
#include <linux/fb.h>
#include "EGLNativeType.h"

#define EDID_STRUCT_DISPLAY 0x14

class CEGLNativeTypeIMX : public CEGLNativeType
{
public:
Expand Down Expand Up @@ -50,8 +52,12 @@ class CEGLNativeTypeIMX : public CEGLNativeType

protected:
bool m_readonly;
float m_sar;
bool ModeToResolution(std::string mode, RESOLUTION_INFO *res) const;
bool FindMatchingResolution(const RESOLUTION_INFO &res, const std::vector<RESOLUTION_INFO> &resolutions);
float GetMonitorSAR();

EGLNativeDisplayType m_display;
EGLNativeWindowType m_window;
uint8_t m_edid[512];
};

0 comments on commit 4533885

Please sign in to comment.