14a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh/*
24a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
34a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*
44a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* Redistribution and use in source and binary forms, with or without
54a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* modification, are permitted provided that the following conditions are
64a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* met:
74a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*     * Redistributions of source code must retain the above copyright
84a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*       notice, this list of conditions and the following disclaimer.
94a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*     * Redistributions in binary form must reproduce the above
104a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*       copyright notice, this list of conditions and the following
114a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*       disclaimer in the documentation and/or other materials provided
124a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*       with the distribution.
134a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*     * Neither the name of The Linux Foundation nor the names of its
144a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*       contributors may be used to endorse or promote products derived
154a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*       from this software without specific prior written permission.
164a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*
174a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
184a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
194a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
204a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
214a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
224a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
234a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
244a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
254a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
264a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
274a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
284a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*/
294a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
304a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <ctype.h>
314a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <math.h>
324a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <fcntl.h>
334a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <inttypes.h>
344a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <sys/types.h>
354a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <sys/stat.h>
364a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <sys/resource.h>
374a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <sys/prctl.h>
384a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <linux/msm_mdp.h>
394a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <utils/constants.h>
404a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <utils/debug.h>
414a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include "hw_color_manager.h"
424a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
434a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#define __CLASS__ "HWColorManager"
444a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
454a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanhnamespace sdm {
464a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
474a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError (*HWColorManager::SetFeature[])(const PPFeatureInfo &, msmfb_mdp_pp *) = {
484a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        [kGlobalColorFeaturePcc] = &HWColorManager::SetPCC,
494a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        [kGlobalColorFeatureIgc] = &HWColorManager::SetIGC,
504a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        [kGlobalColorFeaturePgc] = &HWColorManager::SetPGC,
514a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        [kMixerColorFeatureGc] = &HWColorManager::SetMixerGC,
524a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        [kGlobalColorFeaturePaV2] = &HWColorManager::SetPAV2,
534a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        [kGlobalColorFeatureDither] = &HWColorManager::SetDither,
544a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        [kGlobalColorFeatureGamut] = &HWColorManager::SetGamut,
554a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        [kGlobalColorFeaturePADither] = &HWColorManager::SetPADither,
564a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh};
574a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
584a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError HWColorManager::SetPCC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
594a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError ret = kErrorNone;
604a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
614a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->op = mdp_op_pcc_cfg;
624a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.pcc_cfg_data.version = feature.feature_version_;
634a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.pcc_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
644a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.pcc_cfg_data.ops = feature.enable_flags_;
654a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.pcc_cfg_data.cfg_payload = feature.GetConfigData();
664a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DLOGV_IF(kTagQDCM, "kernel params version = %d, block = %d, flags = %d",
674a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh           kernel_params->data.pcc_cfg_data.version, kernel_params->data.pcc_cfg_data.block,
684a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh           kernel_params->data.pcc_cfg_data.ops);
694a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
704a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return ret;
714a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
724a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
734a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError HWColorManager::SetIGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
744a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError ret = kErrorNone;
754a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
764a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->op = mdp_op_lut_cfg;
774a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.lut_type = mdp_lut_igc;
784a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.igc_lut_data.block =
794a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
804a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.igc_lut_data.version = feature.feature_version_;
814a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.igc_lut_data.ops = feature.enable_flags_;
824a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.igc_lut_data.cfg_payload = feature.GetConfigData();
834a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
844a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return ret;
854a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
864a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
874a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError HWColorManager::SetPGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
884a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError ret = kErrorNone;
894a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
904a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->op = mdp_op_lut_cfg;
914a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.lut_type = mdp_lut_pgc;
924a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.pgc_lut_data.version = feature.feature_version_;
934a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.pgc_lut_data.block =
944a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
954a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.pgc_lut_data.flags = feature.enable_flags_;
964a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.pgc_lut_data.cfg_payload = feature.GetConfigData();
974a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
984a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return ret;
994a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
1004a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1014a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError HWColorManager::SetMixerGC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
1024a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError ret = kErrorNone;
1034a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1044a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->op = mdp_op_lut_cfg;
1054a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.lut_type = mdp_lut_pgc;
1064a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.pgc_lut_data.version = feature.feature_version_;
1074a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.pgc_lut_data.block =
1084a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      (MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_) | MDSS_PP_LM_CFG;
1094a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.pgc_lut_data.flags = feature.enable_flags_;
1104a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.lut_cfg_data.data.pgc_lut_data.cfg_payload = feature.GetConfigData();
1114a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return ret;
1124a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
1134a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1144a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError HWColorManager::SetPAV2(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
1154a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError ret = kErrorNone;
1164a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1174a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->op = mdp_op_pa_v2_cfg;
1184a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.pa_v2_cfg_data.version = feature.feature_version_;
1194a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.pa_v2_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
1204a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.pa_v2_cfg_data.flags = feature.enable_flags_;
1214a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.pa_v2_cfg_data.cfg_payload = feature.GetConfigData();
1224a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DLOGV_IF(kTagQDCM, "kernel params version = %d, block = %d, flags = %d",
1234a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh           kernel_params->data.pa_v2_cfg_data.version, kernel_params->data.pa_v2_cfg_data.block,
1244a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh           kernel_params->data.pa_v2_cfg_data.flags);
1254a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1264a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return ret;
1274a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
1284a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1294a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError HWColorManager::SetDither(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
1304a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError ret = kErrorNone;
1314a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1324a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->op = mdp_op_dither_cfg;
1334a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.dither_cfg_data.version = feature.feature_version_;
1344a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.dither_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
1354a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.dither_cfg_data.flags = feature.enable_flags_;
1364a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.dither_cfg_data.cfg_payload = feature.GetConfigData();
1374a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1384a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return ret;
1394a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
1404a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1414a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError HWColorManager::SetGamut(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
1424a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError ret = kErrorNone;
1434a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1444a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->op = mdp_op_gamut_cfg;
1454a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.gamut_cfg_data.version = feature.feature_version_;
1464a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.gamut_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
1474a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.gamut_cfg_data.flags = feature.enable_flags_;
1484a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.gamut_cfg_data.cfg_payload = feature.GetConfigData();
1494a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1504a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return ret;
1514a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
1524a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1534a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError HWColorManager::SetPADither(const PPFeatureInfo &feature,
1544a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                                         msmfb_mdp_pp *kernel_params) {
1554a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError ret = kErrorNone;
1564a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#ifdef PA_DITHER
1574a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->op = mdp_op_pa_dither_cfg;
1584a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.dither_cfg_data.version = feature.feature_version_;
1594a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.dither_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
1604a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.dither_cfg_data.flags = feature.enable_flags_;
1614a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  kernel_params->data.dither_cfg_data.cfg_payload = feature.GetConfigData();
1624a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#endif
1634a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return ret;
1644a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
1654a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1664a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}  // namespace sdm
167