Home | History | Annotate | Download | only in power
      1 /*
      2  * Copyright (c) 2015, The Linux Foundation. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  * *    * Redistributions of source code must retain the above copyright
      8  *       notice, this list of conditions and the following disclaimer.
      9  *     * Redistributions in binary form must reproduce the above
     10  *       copyright notice, this list of conditions and the following
     11  *       disclaimer in the documentation and/or other materials provided
     12  *       with the distribution.
     13  *     * Neither the name of The Linux Foundation nor the names of its
     14  *       contributors may be used to endorse or promote products derived
     15  *       from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 #define LOG_NDEBUG 1
     30 
     31 #include <errno.h>
     32 #include <string.h>
     33 #include <sys/types.h>
     34 #include <sys/stat.h>
     35 #include <fcntl.h>
     36 #include <dlfcn.h>
     37 #include <stdlib.h>
     38 
     39 #define LOG_TAG "QCOM PowerHAL"
     40 #include <utils/Log.h>
     41 #include <hardware/hardware.h>
     42 #include <hardware/power.h>
     43 
     44 #include "utils.h"
     45 #include "metadata-defs.h"
     46 #include "hint-data.h"
     47 #include "performance.h"
     48 #include "power-common.h"
     49 
     50 static int display_hint_sent;
     51 int launch_handle = -1;
     52 int launch_mode;
     53 
     54 #ifdef EXTRA_POWERHAL_HINTS
     55 static int process_cam_preview_hint(void *metadata)
     56 {
     57     char governor[80];
     58     struct cam_preview_metadata_t cam_preview_metadata;
     59 
     60     if (get_scaling_governor(governor, sizeof(governor)) == -1) {
     61         ALOGE("Can't obtain scaling governor.");
     62 
     63         return HINT_NONE;
     64     }
     65 
     66     /* Initialize encode metadata struct fields */
     67     memset(&cam_preview_metadata, 0, sizeof(struct cam_preview_metadata_t));
     68     cam_preview_metadata.state = -1;
     69     cam_preview_metadata.hint_id = CAM_PREVIEW_HINT_ID;
     70 
     71     if (metadata) {
     72         if (parse_cam_preview_metadata((char *)metadata, &cam_preview_metadata) ==
     73             -1) {
     74             ALOGE("Error occurred while parsing metadata.");
     75             return HINT_NONE;
     76         }
     77     } else {
     78         return HINT_NONE;
     79     }
     80 
     81     if (cam_preview_metadata.state == 1) {
     82         if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
     83                 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
     84             /* sched and cpufreq params
     85              * above_hispeed_delay for LVT - 40ms
     86              * go hispeed load for LVT - 95
     87              * hispeed freq for LVT - 556 MHz
     88              * target load for LVT - 90
     89              * above hispeed delay for sLVT - 40ms
     90              * go hispeed load for sLVT - 95
     91              * hispeed freq for sLVT - 556 MHz
     92              * target load for sLVT - 90
     93              * bus DCVS set to V2 config:
     94              *  low power ceil mpbs - 2500
     95              *  low power io percent - 50
     96              */
     97             int resource_values[] = {0x41400000, 0x4, 0x41410000, 0x5F, 0x41414000, 0x22C,
     98                 0x41420000, 0x5A, 0x41400100, 0x4, 0x41410100, 0x5F, 0x41414100, 0x22C,
     99                 0x41420100, 0x5A, 0x41810000, 0x9C4, 0x41814000, 0x32};
    100 
    101             perform_hint_action(cam_preview_metadata.hint_id,
    102                     resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
    103             ALOGI("Cam Preview hint start");
    104             return HINT_HANDLED;
    105         } else if ((strncmp(governor, SCHED_GOVERNOR, strlen(SCHED_GOVERNOR)) == 0) &&
    106                 (strlen(governor) == strlen(SCHED_GOVERNOR))) {
    107             /*
    108              * lower bus BW to save power
    109              *   0x41810000: low power ceil mpbs = 2500
    110              *   0x41814000: low power io percent = 50
    111              */
    112             int resource_values[] = {0x41810000, 0x9C4, 0x41814000, 0x32};
    113 
    114             perform_hint_action(
    115                 cam_preview_metadata.hint_id, resource_values,
    116                 sizeof(resource_values) / sizeof(resource_values[0]));
    117             ALOGI("Cam Preview hint start");
    118             return HINT_HANDLED;
    119         }
    120     } else if (cam_preview_metadata.state == 0) {
    121         if (((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
    122                 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) ||
    123             ((strncmp(governor, SCHED_GOVERNOR, strlen(SCHED_GOVERNOR)) == 0) &&
    124                 (strlen(governor) == strlen(SCHED_GOVERNOR)))) {
    125             undo_hint_action(cam_preview_metadata.hint_id);
    126             ALOGI("Cam Preview hint stop");
    127             return HINT_HANDLED;
    128         }
    129     }
    130     return HINT_NONE;
    131 }
    132 #endif
    133 
    134 static int process_boost(int boost_handle, int duration)
    135 {
    136     char governor[80];
    137     int eas_launch_resources[] = {0x40804000, 0xFFF, 0x40804100, 0xFFF,
    138                                          0x40800000, 0xFFF, 0x40800100, 0xFFF,
    139                                          0x41800000, 140,   0x40400000, 0x1};
    140     int hmp_launch_resources[] = {0x40C00000, 0x1,   0x40804000, 0xFFF,
    141                                          0x40804100, 0xFFF, 0x40800000, 0xFFF,
    142                                          0x40800100, 0xFFF, 0x41800000, 140,
    143                                          0x40400000, 0x1};
    144     int* launch_resources;
    145     size_t launch_resources_size;
    146 
    147     if (get_scaling_governor(governor, sizeof(governor)) == -1) {
    148         ALOGE("Can't obtain scaling governor.");
    149         return -1;
    150     }
    151     if (strncmp(governor, SCHED_GOVERNOR, strlen(SCHED_GOVERNOR)) == 0) {
    152         launch_resources = eas_launch_resources;
    153         launch_resources_size = sizeof(eas_launch_resources) / sizeof(eas_launch_resources[0]);
    154     } else if (strncmp(governor, INTERACTIVE_GOVERNOR,
    155                        strlen(INTERACTIVE_GOVERNOR)) == 0) { /*HMP boost*/
    156         launch_resources = hmp_launch_resources;
    157         launch_resources_size = sizeof(hmp_launch_resources) / sizeof(hmp_launch_resources[0]);
    158     } else {
    159         ALOGE("Unsupported governor.");
    160         return -1;
    161     }
    162     boost_handle = interaction_with_handle(
    163         boost_handle, duration, launch_resources_size, launch_resources);
    164     return boost_handle;
    165 }
    166 
    167 static int process_video_encode_hint(void *metadata)
    168 {
    169     char governor[80];
    170     struct video_encode_metadata_t video_encode_metadata;
    171     static int boost_handle = -1;
    172 
    173     if (get_scaling_governor(governor, sizeof(governor)) == -1) {
    174         ALOGE("Can't obtain scaling governor.");
    175 
    176         return HINT_NONE;
    177     }
    178 
    179     /* Initialize encode metadata struct fields */
    180     memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
    181     video_encode_metadata.state = -1;
    182     video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
    183 
    184     if (metadata) {
    185         if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) ==
    186             -1) {
    187             ALOGE("Error occurred while parsing metadata.");
    188             return HINT_NONE;
    189         }
    190     } else {
    191         return HINT_NONE;
    192     }
    193 
    194     if (video_encode_metadata.state == 1) {
    195         int duration = 2000; // boosts 2s for starting encoding
    196         boost_handle = process_boost(boost_handle, duration);
    197         ALOGV("LAUNCH ENCODER-ON: %d MS", duration);
    198         if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
    199                 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
    200             /* 1. cpufreq params
    201              *    -above_hispeed_delay for LVT - 40ms
    202              *    -go hispeed load for LVT - 95
    203              *    -hispeed freq for LVT - 556 MHz
    204              *    -target load for LVT - 90
    205              *    -above hispeed delay for sLVT - 40ms
    206              *    -go hispeed load for sLVT - 95
    207              *    -hispeed freq for sLVT - 806 MHz
    208              *    -target load for sLVT - 90
    209              * 2. bus DCVS set to V2 config:
    210              *    -low power ceil mpbs - 2500
    211              *    -low power io percent - 50
    212              * 3. hysteresis optimization
    213              *    -bus dcvs hysteresis tuning
    214              *    -sample_ms of 10 ms
    215              *    -disable ignore_hispeed_notif
    216              *    -sLVT hispeed freq to 806MHz
    217              */
    218             int resource_values[] = {
    219                 0x41810000, 0x9C4, 0x41814000, 0x32, 0x4180C000, 0x0, 0x41820000, 0xA,
    220                 0x41438100, 0x1,  0x41438000, 0x1 };
    221 
    222             perform_hint_action(video_encode_metadata.hint_id,
    223                     resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
    224             ALOGV("Video Encode hint start");
    225             return HINT_HANDLED;
    226         } else if ((strncmp(governor, SCHED_GOVERNOR, strlen(SCHED_GOVERNOR)) == 0) &&
    227                 (strlen(governor) == strlen(SCHED_GOVERNOR))) {
    228 
    229             /* 1. bus DCVS set to V2 config:
    230              *    0x41810000: low power ceil mpbs - 2500
    231              *    0x41814000: low power io percent - 50
    232              * 2. hysteresis optimization
    233              *    0x4180C000: bus dcvs hysteresis tuning
    234              *    0x41820000: sample_ms of 10 ms
    235              */
    236             int resource_values[] = {0x41810000, 0x9C4, 0x41814000, 0x32,
    237                                      0x4180C000, 0x0,   0x41820000, 0xA};
    238 
    239             perform_hint_action(video_encode_metadata.hint_id,
    240                     resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
    241             ALOGV("Video Encode hint start");
    242             return HINT_HANDLED;
    243         }
    244     } else if (video_encode_metadata.state == 0) {
    245         // boost handle is intentionally not released, release_request(boost_handle);
    246         if (((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
    247                 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) ||
    248             ((strncmp(governor, SCHED_GOVERNOR, strlen(SCHED_GOVERNOR)) == 0) &&
    249                 (strlen(governor) == strlen(SCHED_GOVERNOR)))) {
    250             undo_hint_action(video_encode_metadata.hint_id);
    251             ALOGV("Video Encode hint stop");
    252             return HINT_HANDLED;
    253         }
    254     }
    255     return HINT_NONE;
    256 }
    257 
    258 static int process_activity_launch_hint(void *data)
    259 {
    260     // boost will timeout in 5s
    261     int duration = 5000;
    262     if (sustained_performance_mode || vr_mode) {
    263         return HINT_HANDLED;
    264     }
    265 
    266     ALOGV("LAUNCH HINT: %s", data ? "ON" : "OFF");
    267     if (data && launch_mode == 0) {
    268         launch_handle = process_boost(launch_handle, duration);
    269         if (launch_handle > 0) {
    270             launch_mode = 1;
    271             ALOGV("Activity launch hint handled");
    272             return HINT_HANDLED;
    273         } else {
    274             return HINT_NONE;
    275         }
    276     } else if (data == NULL  && launch_mode == 1) {
    277         release_request(launch_handle);
    278         launch_mode = 0;
    279         return HINT_HANDLED;
    280     }
    281     return HINT_NONE;
    282 }
    283 
    284 int power_hint_override(struct power_module *module, power_hint_t hint, void *data)
    285 {
    286     int ret_val = HINT_NONE;
    287     switch(hint) {
    288 #ifdef EXTRA_POWERHAL_HINTS
    289         case POWER_HINT_CAM_PREVIEW:
    290             ret_val = process_cam_preview_hint(data);
    291             break;
    292 #endif
    293         case POWER_HINT_VIDEO_ENCODE:
    294             ret_val = process_video_encode_hint(data);
    295             break;
    296         case POWER_HINT_LAUNCH:
    297             ret_val = process_activity_launch_hint(data);
    298             break;
    299         default:
    300             break;
    301     }
    302     return ret_val;
    303 }
    304 
    305 int set_interactive_override(struct power_module *module, int on)
    306 {
    307     return HINT_HANDLED; /* Don't excecute this code path, not in use */
    308     char governor[80];
    309 
    310     if (get_scaling_governor(governor, sizeof(governor)) == -1) {
    311         ALOGE("Can't obtain scaling governor.");
    312 
    313         return HINT_NONE;
    314     }
    315 
    316     if (!on) {
    317         /* Display off */
    318         if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
    319             (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
    320             int resource_values[] = {}; /* dummy node */
    321             if (!display_hint_sent) {
    322                 perform_hint_action(DISPLAY_STATE_HINT_ID,
    323                 resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
    324                 display_hint_sent = 1;
    325                 ALOGV("Display Off hint start");
    326                 return HINT_HANDLED;
    327             }
    328         }
    329     } else {
    330         /* Display on */
    331         if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
    332             (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
    333             undo_hint_action(DISPLAY_STATE_HINT_ID);
    334             display_hint_sent = 0;
    335             ALOGV("Display Off hint stop");
    336             return HINT_HANDLED;
    337         }
    338     }
    339     return HINT_NONE;
    340 }
    341