void FMRadioSeek(const hal::FMRadioSeekDirection& aDirection) { struct v4l2_hw_freq_seek seek = {0}; seek.type = V4L2_TUNER_RADIO; seek.seek_upward = aDirection == hal::FMRadioSeekDirection::FM_RADIO_SEEK_DIRECTION_UP; /* ICS and older don't have the spacing field */ #if ANDROID_VERSION == 15 seek.reserved[0] = sRadioSettings.spaceType() * 1000; #else seek.spacing = sRadioSettings.spaceType() * 1000; #endif int rc = ioctl(sRadioFD, VIDIOC_S_HW_FREQ_SEEK, &seek); if (sMsmFMMode && rc >= 0) return; NS_DispatchToMainThread(new RadioUpdate(hal::FM_RADIO_OPERATION_SEEK, rc < 0 ? hal::FM_RADIO_OPERATION_STATUS_FAIL : hal::FM_RADIO_OPERATION_STATUS_SUCCESS)); if (rc < 0) { HAL_LOG("Could not initiate hardware seek"); return; } NS_DispatchToMainThread(new RadioUpdate(hal::FM_RADIO_OPERATION_TUNE, hal::FM_RADIO_OPERATION_STATUS_SUCCESS)); }
/* Runs on the radio thread */ static void initTavaruaRadio(hal::FMRadioSettings &aInfo) { mozilla::ScopedClose fd(sRadioFD); char version[64]; int rc; snprintf(version, sizeof(version), "%d", sTavaruaVersion); property_set("hw.fm.version", version); /* Set the mode for soc downloader */ property_set("hw.fm.mode", "normal"); /* start fm_dl service */ property_set("ctl.start", "fm_dl"); /* * Fix bug 800263. Wait until the FM radio chips initialization is done * then set other properties, or the system will hang and reboot. This * work around is from codeaurora * (git://codeaurora.org/platform/frameworks/base.git). */ for (int i = 0; i < 4; ++i) { sleep(1); char value[PROPERTY_VALUE_MAX]; property_get("hw.fm.init", value, "0"); if (!strcmp(value, "1")) { break; } } rc = setControl(V4L2_CID_PRIVATE_TAVARUA_STATE, FM_RECV); if (rc < 0) { HAL_LOG(("Unable to turn on radio |%s|", strerror(errno))); return; } int preEmphasis = aInfo.preEmphasis() <= 50; rc = setControl(V4L2_CID_PRIVATE_TAVARUA_EMPHASIS, preEmphasis); if (rc) { HAL_LOG(("Unable to configure preemphasis")); return; } rc = setControl(V4L2_CID_PRIVATE_TAVARUA_RDS_STD, 0); if (rc) { HAL_LOG(("Unable to configure RDS")); return; } int spacing; switch (aInfo.spaceType()) { case 50: spacing = FM_CH_SPACE_50KHZ; break; case 100: spacing = FM_CH_SPACE_100KHZ; break; case 200: spacing = FM_CH_SPACE_200KHZ; break; default: HAL_LOG(("Unsupported space value - %d", aInfo.spaceType())); return; } rc = setControl(V4L2_CID_PRIVATE_TAVARUA_SPACING, spacing); if (rc) { HAL_LOG(("Unable to configure spacing")); return; } /* * Frequency conversions * * HAL uses units of 1k for frequencies * V4L2 uses units of 62.5kHz * Multiplying by (10000 / 625) converts from HAL units to V4L2. */ struct v4l2_tuner tuner = {0}; tuner.rangelow = (aInfo.lowerLimit() * 10000) / 625; tuner.rangehigh = (aInfo.upperLimit() * 10000) / 625; rc = ioctl(fd, VIDIOC_S_TUNER, &tuner); if (rc < 0) { HAL_LOG(("Unable to adjust band limits")); return; } rc = setControl(V4L2_CID_PRIVATE_TAVARUA_REGION, TAVARUA_REGION_OTHER); if (rc < 0) { HAL_LOG(("Unable to configure region")); return; } // Some devices do not support analog audio routing. This should be // indicated by the 'ro.moz.fm.noAnalog' property at build time. char propval[PROPERTY_VALUE_MAX]; property_get("ro.moz.fm.noAnalog", propval, ""); bool noAnalog = !strcmp(propval, "true"); rc = setControl(V4L2_CID_PRIVATE_TAVARUA_SET_AUDIO_PATH, noAnalog ? FM_DIGITAL_PATH : FM_ANALOG_PATH); if (rc < 0) { HAL_LOG(("Unable to set audio path")); return; } if (!noAnalog) { /* Set the mode for soc downloader */ property_set("hw.fm.mode", "config_dac"); /* Use analog mode FM */ property_set("hw.fm.isAnalog", "true"); /* start fm_dl service */ property_set("ctl.start", "fm_dl"); for (int i = 0; i < 4; ++i) { sleep(1); char value[PROPERTY_VALUE_MAX]; property_get("hw.fm.init", value, "0"); if (!strcmp(value, "1")) { break; } } } fd.forget(); sRadioEnabled = true; }