16fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/* 26fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * Copyright (C) 2012 The Android Open Source Project 36fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * 46fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * Licensed under the Apache License, Version 2.0 (the "License"); 56fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * you may not use this file except in compliance with the License. 66fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * You may obtain a copy of the License at 76fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * 86fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * http://www.apache.org/licenses/LICENSE-2.0 96fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * 106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * Unless required by applicable law or agreed to in writing, software 116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * distributed under the License is distributed on an "AS IS" BASIS, 126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * See the License for the specific language governing permissions and 146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * limitations under the License. 153f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org */ 163f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org 173f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org#define __STDC_LIMIT_MACROS 183f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org 193f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org#define LOG_TAG "common_time" 203f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org#include <utils/Log.h> 213f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org 223f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org#include <stdint.h> 233f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org 243f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org#include <utils/Errors.h> 253f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org#include <utils/LinearTransform.h> 263f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org 273f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org#include "common_clock.h" 283f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org 293f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.orgnamespace android { 303f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org 316fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgCommonClock::CommonClock() { 326fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_slew_ = 0; 336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_valid_ = false; 343f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org 356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_.a_zero = 0; 366fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_.b_zero = 0; 376fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_.a_to_b_numer = local_to_common_freq_numer_ = 1; 386fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_.a_to_b_denom = local_to_common_freq_denom_ = 1; 396fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org duration_trans_ = cur_trans_; 406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org} 416fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 426fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgbool CommonClock::init(uint64_t local_freq) { 436fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Mutex::Autolock lock(&lock_); 446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 456fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!local_freq) 466fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return false; 476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 486fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org uint64_t numer = kCommonFreq; 496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org uint64_t denom = local_freq; 506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 516fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org LinearTransform::reduce(&numer, &denom); 526fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if ((numer > UINT32_MAX) || (denom > UINT32_MAX)) { 536fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org ALOGE("Overflow in CommonClock::init while trying to reduce %lld/%lld", 546fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org kCommonFreq, local_freq); 556fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return false; 566fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org } 573f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org 586fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_.a_to_b_numer = local_to_common_freq_numer_ = 596fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org static_cast<uint32_t>(numer); 603f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org cur_trans_.a_to_b_denom = local_to_common_freq_denom_ = 613f0af3b06425f635f3559f0bd4f53efea95fa5e2johannkoenig@chromium.org static_cast<uint32_t>(denom); 626fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org duration_trans_ = cur_trans_; 636fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 646fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return true; 656fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org} 666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 676fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgstatus_t CommonClock::localToCommon(int64_t local, int64_t *common_out) const { 686fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Mutex::Autolock lock(&lock_); 696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 706fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!cur_trans_valid_) 716fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return INVALID_OPERATION; 726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 736fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!cur_trans_.doForwardTransform(local, common_out)) 746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return INVALID_OPERATION; 756fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return OK; 776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org} 786fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 796fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgstatus_t CommonClock::commonToLocal(int64_t common, int64_t *local_out) const { 806fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Mutex::Autolock lock(&lock_); 816fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 826fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!cur_trans_valid_) 836fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return INVALID_OPERATION; 846fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 856fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (!cur_trans_.doReverseTransform(common, local_out)) 866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return INVALID_OPERATION; 876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 886fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return OK; 896fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org} 906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 916fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgint64_t CommonClock::localDurationToCommonDuration(int64_t localDur) const { 926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int64_t ret; 936fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org duration_trans_.doForwardTransform(localDur, &ret); 946fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org return ret; 956fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org} 966fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 976fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgvoid CommonClock::setBasis(int64_t local, int64_t common) { 986fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Mutex::Autolock lock(&lock_); 996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1006fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_.a_zero = local; 1016fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_.b_zero = common; 1026fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_valid_ = true; 1036fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org} 1046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgvoid CommonClock::resetBasis() { 1066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Mutex::Autolock lock(&lock_); 1076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1086fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_.a_zero = 0; 1096fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_.b_zero = 0; 1106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org cur_trans_valid_ = false; 1116fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org} 1126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1136fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgstatus_t CommonClock::setSlew(int64_t change_time, int32_t ppm) { 1146fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org Mutex::Autolock lock(&lock_); 1156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int64_t new_local_basis; 1176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org int64_t new_common_basis; 1186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org 1196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org if (cur_trans_valid_) { 1206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org new_local_basis = change_time; 121 if (!cur_trans_.doForwardTransform(change_time, &new_common_basis)) { 122 ALOGE("Overflow when attempting to set slew rate to %d", ppm); 123 return INVALID_OPERATION; 124 } 125 } else { 126 new_local_basis = 0; 127 new_common_basis = 0; 128 } 129 130 cur_slew_ = ppm; 131 uint32_t n1 = local_to_common_freq_numer_; 132 uint32_t n2 = 1000000 + cur_slew_; 133 134 uint32_t d1 = local_to_common_freq_denom_; 135 uint32_t d2 = 1000000; 136 137 // n1/d1 has already been reduced, no need to do so here. 138 LinearTransform::reduce(&n1, &d2); 139 LinearTransform::reduce(&n2, &d1); 140 LinearTransform::reduce(&n2, &d2); 141 142 cur_trans_.a_zero = new_local_basis; 143 cur_trans_.b_zero = new_common_basis; 144 cur_trans_.a_to_b_numer = n1 * n2; 145 cur_trans_.a_to_b_denom = d1 * d2; 146 147 return OK; 148} 149 150} // namespace android 151