MTK PQ调试之Gamma和色温调试

2 篇文章 3 订阅

导文,在手机屏幕调试过程中,经常会遇到屏的ECN器件存在色温差异问题,举个栗子:一供和二供屏在纯白颜色界面有着很明显的色温差异。那么有的同仁可能会疑问,为什么不让两个ECN器件保持同样的色温标准呢?答案是目前行业中,很少有哪家模组厂能够保证模组的一致性非常好,且固定色温偏差在一个很小的范围内;另外,不同的模组厂之间的物料也会有差异,所以很常见的就是不同模组厂出货的屏幕色温会存在差异,更甚至有同一批次的模组有些色温的差异会达到500-1000K。这个时候,从软件层面来优化这种类似问题的需求便应势而生了,PictureQuality(简称 :PQ),便是软件调试接口,是一个提高图像质量的一个新功能,为用户提高一个良好的使用体验。

调试Gamma和色温,需要分2步走,第一步是需要把效果调试好,第二部是把调试好的参数导出,合入到项目工程中去,并做好屏幕的识别处理。

第一步:获取到MTK的PQ调试工具——MiraVision_Tuning_Kit

工具的下载路径在MTK的online网址上可以找到,这里附上链接:mtk工具下载路径:

在里面可以通过搜索找到MiraVision_Tuning_Kit,建议下载前先查看下右边的ReleaseNote看下平台是不支持调试工具

向MTK提供申请下载工具,然后等到MTK回复下载工具的ID,然后点开链接去下载即可

建议拿到工具后优先看下工具中自带的调试指导文档,新手必看教程:

第二步:准备调试机器的调试环境

主要有以下注意事项:

1、调试机器的软件版本必须是userdebug版本,并且需要在开发者模式中打开ADB调试功能
2、在手机拨号盘上输入MTK的调试暗码:*#*#3646633#*#*(可能不同的第三方开发商会修改成自己的暗码,例如我这边就是*#*#9646633#*#*),进入EngineerMode,左右滑动到Log and Debugging 菜单栏目下点击 ATCI,点击 Always enable ATCI。
3、安装工具中自带的MTK驱动文件。(建议用Windows系统电脑来进行调试,因为虚拟机有时候不好使)
4、调试机器用usb与电脑链接,然后在打开调试工具前先跑一下工具中自带的脚本Before_Tuning.bat
5、双击打开调试工具MiravisionTuningKit.exe

另外还有一些注意事项需要提前准备,就是需要手动关闭AAL /PQ/CABC和自动调节亮度功能,因为有这些功能开启的情况下会影响采集RAWData,把这些影响背光和色彩的特殊功能关闭了,MTK这边才能采集到调试机器比较干净的色彩数据。

做完以上准备工作之后,下一步就是采集Gamma的RAWData了,在调试工具中其实自带了一份Gamma RAWData的表格模板,我们先要通过色彩分析仪例如CA210/CA310/CA410来测量机器的Gamma数据,这里有一点非常重要:R/G/B/W四种颜色的Gamma都需要采集 ,否则会影响调试效果!按照常见的测试方法,我们通常以白色Gamma曲线作为评估一块屏幕的Gamma是否OK,但是严格意义上应该以R/G/B/W四种颜色的全部Gamma曲线来评估。在调PQ的时候如果漏掉了其中任何一个颜色的Gamma数据,调试出来的效果都是非常差的。

至于测量步阶,以个人工作需要为准,如果采用步阶4,那就是每4个灰阶测一次灰阶亮度,这样0~255灰阶就会有65组数据。这里步阶越小,采集到的数据就会更详细,花的时间就会多一些。分别把R/G/B/W四颜色Gamma曲线测量出来后将X/Y/Z三列数据填到调试工具自带的模板表格中去。

第三步:进入调试工具开始调试

进入调试工具界面会要求选择对应的芯片平台、软件平台和MTK设备端口号,按照调试机器的匹配类型去选择好,然后点击后面的感叹号就会开始连接手机了,

连接成功了后感叹号就会有个绿色的护身符,然后把优先把CE Config和CCORR的使能开关勾选掉

先调试色温

点击主菜单上面的parttern Gen,接着选择Pattern Gen,然后选择Gen by AAL,再勾选上下面的pattern Gen,就可以手动调试了.

调试色温的时候,可以先点一下右边的W,屏幕会变成纯白色,然后可以适当调一下Red/Green/Blue三种颜色的灰阶数,每调一次就借助色彩分析仪来测一下色温是否满足需求。通常情况下Green灰阶对最大亮度的影响最大,如果降低太多也许会使得最大亮度降很多,这里举个例子,假如我测量R/G/B的灰阶数分别为245/255/255的时候,测量出来色温达到我的需求后,我便把R/G/B的灰阶数记下来。

然后调试Gamma

调试gamma步骤如下:

1、点击上面菜单栏的Gamma按钮
2、RawData这里选择Gamma曲线的步阶,这个步阶一定需要和你前面步骤测R/G/B/W颜色Gamma Raw Data的步阶保持一样
3、点击Import Raw Data按钮,文件选择前面填好的GammaRawData.xlsx
4、把后面的R/G/B/W的选框全都勾选上,一定要勾选上啊!!😂😂😂别问为什么
5、填一下下面的R/G/B灰阶数,填前面满足色温的灰阶参数
6、Gamma Value选择你的目标Gamma曲线
7、在最下面Para Gen and output里面点击Para Gen,调试工具就会根据你前面导入的GammaRawData数据来调试出与目标Gamma曲线相符合的Gamma参数,当然,关于目标色温的也会一块合进去。
8、左边Hardware下把Enable Gamm选框勾选上,然后点一下Write按钮就可以将调试好的Gamma和色温参数写到手机中生效,约几十帧的时间就会生效(但是亮灭屏后擦除恢复),写入到手机中后就可以立马用色彩分析仪测量一下,看看Gamma曲线和色温是否达到你的期望值,这里建议考虑到模组的一致性问题,选择适合的参数
9、点击最下面的.tbl Output按钮,就可以将此次调试的参数导出。

来看一下调试前后的对比

调试前的Gamma曲线图:

调试后的Gamma曲线图:

效果是显而易见的,然后前后色温也会改变,建议测色温前保持亮屏热机5~10分钟后再测

接下来一看看前面调试好参数导出来后像什么样子,这里面会包含R/G/B各自的参数

第四部:将调试好的参数合入到工程中去

相关文件代码的路径也许会因为不同平台存在差异,我这里以mt6765的代码做讲解

客制化参数文件

文件路径:alps\vendor\mediatek\proprietary\custom\mt6765\hal\pq\cust_gamma.cpp

里面有一个名叫‘cust_gamma 指针数组,其中0~14共有15组参数,每组里面都有R/G/B的参数,如下图:

我们将调试好的参数放到这其中一个数组中即可,例如Gamma0当中,但是需要注意放对位置,不要把R颜色的参数放到G颜色参数的位置去了😂

PQ文件配置文件

PQ相关的主要流程在这个PictureQuality.cpp这个文件夹内,可能有2个文件区分legacy和fusion

路径在:alps\vendor\mediatek\proprietary\hardware\pq\v2.0\lib\service

上面提到的配置客制化参数的位置,其默认是用的第8组数据,也就是cust_gamma [7],代码中定义如下:

// The index of default gamma table #define GAMMA_INDEX_DEFAULT 7

主要的流程如下:

在bool PictureQuality::threadLoop()中初始化,调用loadGammaEntryTable()

#ifdef MTK_DISP_GAMMA_SUPPORT
        if (mDispPQPropertyValue[DISP_GAMMA_SUPPORT])
            loadGammaEntryTable();
#endif  

在loadGammaEntryTable()中主要是去获取客制化gamma的参数,并开辟内存空间

#ifdef MTK_DISP_GAMMA_SUPPORT
void PictureQuality::loadGammaEntryTable()
{
    // load gamma from cust lib if load factory gamma fail or factory gamma not support
    CustParameters &cust = CustParameters::getPQCust();
    gamma_entry_t* ptr = (gamma_entry_t*)cust.getSymbol("cust_gamma");
​
    if (!ptr) {
        PQ_LOGD("[PQ_SERVICE] cust_gamma is not found in libpq_cust.so\n");
    }
    else
    {
        memcpy(m_CustGamma, ptr, sizeof(gamma_entry_t) * GAMMA_LCM_MAX * GAMMA_INDEX_MAX);
        memcpy(m_NvGamma, ptr, sizeof(gamma_entry_t) * GAMMA_LCM_MAX * GAMMA_INDEX_MAX);
    }
#ifdef FACTORY_GAMMA_SUPPORT
    if (loadNvGammaTable() == NO_ERROR) {
        gamma_entry_t *entry = (m_NvGamma[0]);
        configGamma(m_PQMode, entry);
        return;
    }
#endif
    if (ptr) {
        gamma_entry_t *entry = (m_CustGamma[0]);
        configGamma(m_PQMode, entry);
    }
}
#endif
```

然后调用configGamma(int picMode, const gamma_entry_t *entry)去索引选用哪个gammaIndex,所以我们要做LCD兼容区分的时候,建议就在这里去做区分。

void PictureQuality::configGamma(int picMode, const gamma_entry_t *entry)
{
#ifdef MTK_DISP_GAMMA_SUPPORT
#if (GAMMA_LCM_MAX > 0) && (GAMMA_INDEX_MAX > 0)
    int gammaIndex = 0;
#endif
​
#if GAMMA_INDEX_MAX > 1
    // get gamma index from runtime property configuration
    char property[PROPERTY_VALUE_MAX] = {0};
gammaIndex = GAMMA_INDEX_DEFAULT;
if (picMode == PQ_PIC_MODE_USER_DEF &&
        property_get(GAMMA_INDEX_PROPERTY_NAME, property, NULL) > 0 &&
        strlen(property) > 0)
{
    gammaIndex = atoi(property);
}
​
if (gammaIndex < 0 || GAMMA_INDEX_MAX <= gammaIndex)
    gammaIndex = GAMMA_INDEX_DEFAULT;
#endif
#if (GAMMA_LCM_MAX > 0) && (GAMMA_INDEX_MAX > 0)
    PQ_LOGD("Gamma index: %d/%d", gammaIndex, GAMMA_INDEX_MAX);
    configDriverGamma(entry + gammaIndex);
#endif
#endif
}

关于屏的识别区分方案

在一个项目中不同模组厂出货的屏基本上都会存在差异,所以我们在调试PQ时务必要做好屏幕的识别区分,否则会影响另外模组的主观表现,这里简单介绍两个区分与方案:

1.通过索引lcm_index来区分

可以在上面的configGamma函数里面去调用_getLcmIndexOfGamma来获取lcm_index,理论上这个lcm_index最终是从底层获得,相关代码参考如下:

void PictureQuality::configGamma(int picMode, const gamma_entry_t *entry)
{
#ifdef MTK_DISP_GAMMA_SUPPORT
#if (GAMMA_LCM_MAX > 0) && (GAMMA_INDEX_MAX > 0)
    int gammaIndex = 0;
#endif
int lcm_index=_getLcmIndexOfGamma();//add by Shoulder.Newan for recognize
if(lcm_index == 0) //如果是一供LCM
    gammaIndex = GAMMA_INDEX_DEFAULT;//这里去配置选用cust_gamma中的哪组参数
else if(lcm_index == 1)//如果是二供
    gammaIndex = GAMMA_INDEX_DEFAULT;//这里去配置选用cust_gamma中的哪组参数
else
    gammaIndex = GAMMA_INDEX_DEFAULT;

_getLcmIndexOfGamma()函数会通过ioctl(m_drvID, DISP_IOCTL_GET_LCMINDEX, &lcmIdx);的方式去获取lcm的编号,

alps\kernel-4.19\drivers\misc\mediatek\video\mt6765\videox\mtk_disp_mgr.c

case DISP_IOCTL_GET_LCMINDEX:
        {
            return primary_display_get_lcm_index();
        }

alps\kernel-4.19\drivers\misc\mediatek\video\mt6765\videox\primary_display.c

int primary_display_get_lcm_index(void)
{
    int index = 0;
    DISPFUNC();
    if (pgc->plcm == NULL) {
        DISPERR("lcm handle is null\n");
        return 0;
    }
    index = pgc->plcm->index;
    DISPDBG("lcm index = %d\n", index);
    return index;
}

alps\kernel-4.19\drivers\misc\mediatek\video\mt6765\videox\disp_lcm.c

struct disp_lcm_handle *disp_lcm_probe
    ......
    for (i = 0; i < _lcm_count(); i++) {
                lcm_drv = lcm_driver_list[i];
                if (!strcmp(lcm_drv->name, plcm_name)) {
                    isLCMFound = true;
                    isLCMInited = true;
                    lcmindex = i;
                    break;
                }
            }
    ......      
    plcm->index = lcmindex;
2.通过识别LCM的名字来区分

建议可以去读LCM的驱动节点lcm_name去做匹配,可能有些ODM创建的驱动节点路径各不相同,这里只做举例

假如我这边的LCM的驱动节点路径是:sys/devices/platform/soc/14014300.dsi/lcm_name

#define LCM_NAME_PATH   "/sys/devices/platform/soc/14014300.dsi/lcm_name"
#define LCM_NAME_PQ1    "ili8963_hdp_dsi_vdo_120hz"
void PictureQuality::configGamma(int picMode, const gamma_entry_t *entry)
{
int ret;
int retval;
int lcm_index;
#ifdef MTK_DISP_GAMMA_SUPPORT
#if (GAMMA_LCM_MAX > 0) && (GAMMA_INDEX_MAX > 0)
    int gammaIndex = 0;
#endif
ret = open(LCM_NAME_PATH, O_RDONLY);
if (ret >= 0) {
     char buffer[20];
     retval = read(ret, buffer, sizeof(buffer));
     if (retval <= 0)
          PQ_LOGE("read lcm driver node path failed");
     else if(0 == strncmp(buffer, "LCM_NAME_PQ1", strlen("LCM_NAME_PQ1"))) {
          PQ_LOGE("We will load gamma for LCM_NAME_PQ1");
          lcm_index = 1;
     }
     close(ret);
     break;
   }
 gammaIndex = lcm_index;
......

但是这种方式的话肯定会遇上avc权限问题,需要再处理一下avc权限相关,不过也并不复杂,看avc log前先输入指令:adb shell setenforce 0 ,然后再logcat | grep avc --color ,这里就不展开说了

  • 24
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Gamma调试是一种软件调试方法,主要用于追踪和修复程序中的错误。其基本步骤如下: 1. 确定问题:首先需要明确程序中存在的问题。这可以通过观察程序的异常行为、错误提示或在特定条件下出现的错误来确定。确切地了解问题的性质和范围,将有助于后续的调试过程。 2. 制定假设:根据对问题的初步分析,制定假设来解释问题的原因。这些假设可能包括变量值错误、逻辑错误或函数调用错误等。制定假设将有助于集中精力进行具体调试活动。 3. 收集数据:为了验证假设,需要收集相关数据。这可能包括输入数据、日志文件、调用堆栈和内存转储等。这些数据将有助于更全面地分析问题,并找出错误的根源。 4. 分析数据:基于收集的数据,仔细分析每个数据点,观察数据间的关联,试图找到引发问题的具体原因。可以使用调试工具、日志分析工具或手动调试方法来深入分析数据。 5. 提出解决方案:根据对数据分析的结果,提出可能的解决方案。这可能包括修改代码、修复变量值错误或重新设计算法等。选择最佳解决方案可能需要多次尝试和迭代。 6. 实施解决方案:根据选择的解决方案,对程序进行相应的修改。这可能包括修改源代码、重新编译程序或更新配置文件等。 7. 测试修复:对修复后的程序进行测试,以验证问题是否得到解决。可以使用已知测试用例再次运行程序,并观察是否出现预期的结果。如果问题得到解决,则调试过程结束,如果问题仍然存在,则需要重新回到前面的步骤进行分析和修复。 总结起来,Gamma调试的基本步骤包括确定问题、制定假设、收集数据、分析数据、提出解决方案、实施解决方案和测试修复。这些步骤可以帮助开发人员快速定位和修复程序中的错误,提高软件质量和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值