1/* Copyright (c) 2014, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30#define LOG_TAG "audio_hw_pm" 31/*#define LOG_NDEBUG 0*/ 32 33#include "pm.h" 34#include <cutils/log.h> 35 36static s_audio_subsys audio_ss; 37 38int audio_extn_pm_vote(void) 39{ 40 int err, intfd, ret; 41 FILE *fd; 42 enum pm_event subsys_state; 43 char halPropVal[PROPERTY_VALUE_MAX]; 44 bool prop_unload_image = false; 45 bool pm_reg = false; 46 bool pm_supp = false; 47 48 platform_get_subsys_image_name((char *)&audio_ss.img_name); 49 ALOGD("%s: register with peripheral manager for %s",__func__, audio_ss.img_name); 50 ret = pm_client_register(audio_extn_pm_event_notifier, 51 &audio_ss, 52 audio_ss.img_name, 53 PM_CLIENT_NAME, 54 &subsys_state, 55 &audio_ss.pm_handle); 56 if (ret == PM_RET_SUCCESS) { 57 pm_reg = true; 58 pm_supp = true; 59 ALOGV("%s: registered with peripheral manager for %s", 60 __func__, audio_ss.img_name); 61 } else if (ret == PM_RET_UNSUPPORTED) { 62 pm_reg = true; 63 pm_supp = false; 64 ALOGV("%s: peripheral mgr unsupported for %s", 65 __func__, audio_ss.img_name); 66 return ret; 67 } else { 68 return ret; 69 } 70 if (pm_supp == true && 71 pm_reg == true) { 72 ALOGD("%s: Voting for subsystem power up", __func__); 73 pm_client_connect(audio_ss.pm_handle); 74 75 if (property_get("sys.audio.init", halPropVal, NULL)) { 76 prop_unload_image = !(strncmp("false", halPropVal, sizeof("false"))); 77 } 78 /* 79 * adsp-loader loads modem/adsp image at boot up to play boot tone, 80 * before peripheral manager service is up. Once PM is up, vote to PM 81 * and unload the image to give control to PM to load/unload image 82 */ 83 if (prop_unload_image) { 84 intfd = open(BOOT_IMG_SYSFS_PATH, O_WRONLY); 85 if (intfd == -1) { 86 ALOGE("failed to open fd in write mode, %d", errno); 87 } else { 88 ALOGD("%s: write to sysfs to unload image", __func__); 89 err = write(intfd, UNLOAD_IMAGE, 1); 90 close(intfd); 91 property_set("sys.audio.init", "true"); 92 } 93 } 94 } 95 return 0; 96} 97 98void audio_extn_pm_unvote(void) 99{ 100 ALOGD("%s", __func__); 101 if (audio_ss.pm_handle) { 102 pm_client_disconnect(audio_ss.pm_handle); 103 pm_client_unregister(audio_ss.pm_handle); 104 } 105} 106 107void audio_extn_pm_set_parameters(struct str_parms *parms) 108{ 109 int ret; 110 char value[32]; 111 112 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DEV_SHUTDOWN, value, sizeof(value)); 113 if (ret >= 0) { 114 if (strstr(value, "true")) { 115 ALOGD("Device shutdown notification received, unregister with PM"); 116 audio_extn_pm_unvote(); 117 } 118 } 119} 120 121void audio_extn_pm_event_notifier(void *client_data, enum pm_event event) 122{ 123 pm_client_event_acknowledge(audio_ss.pm_handle, event); 124 125 /* Closing and re-opening of session is done based on snd card status given 126 * by AudioDaemon during SS offline/online (legacy code). Just return for now. 127 */ 128 switch (event) { 129 case EVENT_PERIPH_GOING_OFFLINE: 130 ALOGV("%s: %s is going offline", __func__, audio_ss.img_name); 131 break; 132 133 case EVENT_PERIPH_IS_OFFLINE: 134 ALOGV("%s: %s is offline", __func__, audio_ss.img_name); 135 break; 136 137 case EVENT_PERIPH_GOING_ONLINE: 138 ALOGV("%s: %s is going online", __func__, audio_ss.img_name); 139 break; 140 141 case EVENT_PERIPH_IS_ONLINE: 142 ALOGV("%s: %s is online", __func__, audio_ss.img_name); 143 break; 144 145 default: 146 ALOGV("%s: invalid event received from PM", __func__); 147 break; 148 } 149} 150