Unfortunately, the MDP support site is entirely barren of anything technical.
No, sorry, I can't. I don't have a 6P. (In fact, I don't have the older nexus 6 anymore either.).can you give some help?
hmmm...ok and thanks for the answerNo, sorry, I can't. I don't have a 6P. (In fact, I don't have the older nexus 6 anymore either.)
Take care
Gary
Try google; https://developers.google.com/android/nexus/imagesAnyone holding an unmodified Original MMB30G "lights.shamu.so"
Mine somehow got corrupted.
Thanks
That's not what I asked for.
&spmi_bus {
qcom,[email protected] {
qcom,[email protected] {
compatible = "qcom,leds-qpnp";
reg = <0xc600 0x100>;
status = "okay";
qcom,led_gpio_7 {
label = "rgb";
linux,name = "red";
qcom,mode = "pwm";
qcom,pwm-channel = <2>;
qcom,start-idx = <1>;
qcom,idx-len = <10>;
qcom,duty-pcts = [00 19 32 4B 64
64 4B 32 19 00];
qcom,lut-flags = <3>;
qcom,pause-lo = <0>;
qcom,pause-hi = <0>;
qcom,ramp-step-ms = <255>;
qcom,max-current = <12>;
qcom,default-state = "on";
qcom,turn-off-delay-ms = <500>;
qcom,id = <5>;
linux,default-trigger = "none";
qcom,pwm-us = <1000>;
qcom,use-blink; };
};
qcom,[email protected] {
compatible = "qcom,leds-qpnp";
reg = <0xc700 0x100>;
status = "okay";
qcom,led_gpio_8 {
label = "rgb";
linux,name = "green";
qcom,mode = "pwm";
qcom,pwm-channel = <3>;
qcom,start-idx = <1>;
qcom,idx-len = <10>;
qcom,duty-pcts = [00 19 32 4B 64
64 4B 32 19 00];
qcom,lut-flags = <3>;
qcom,pause-lo = <0>;
qcom,pause-hi = <0>;
qcom,ramp-step-ms = <255>;
qcom,max-current = <12>;
qcom,default-state = "on";
qcom,turn-off-delay-ms = <500>;
qcom,id = <5>;
linux,default-trigger = "none";
qcom,pwm-us = <1000>;
qcom,use-blink; };
};
qcom,[email protected] {
compatible = "qcom,leds-qpnp";
reg = <0xc800 0x100>;
status = "okay";
qcom,led_gpio_9 {
label = "rgb";
linux,name = "blue";
qcom,mode = "pwm";
qcom,pwm-channel = <4>;
qcom,start-idx = <1>;
qcom,idx-len = <10>;
qcom,duty-pcts = [00 19 32 4B 64
64 4B 32 19 00];
qcom,lut-flags = <3>;
qcom,pause-lo = <0>;
qcom,pause-hi = <0>;
qcom,ramp-step-ms = <255>;
qcom,max-current = <12>;
qcom,default-state = "on";
qcom,turn-off-delay-ms = <500>;
qcom,id = <5>;
linux,default-trigger = "none";
qcom,pwm-us = <1000>;
qcom,use-blink;
};
};
};
};
I tried out the timer trigger (which uses kernel timers to decide when to turn the LED on and off), and what I have found is that it works fine when the CPU is kept online, but doesn't seem to have the ability to wake the CPU up to do the switch. That means that once the thing starts sleeping, the blinking doesn't really work -- just when the CPU comes alive.2) qcom BLINKING is performed by LPG mode.
3) It switches between PWM and LPG mode by writing "1" into "blink".
4) I'm not sure what I'm missing, but when I do this with the above code, it just turns the light off. No blinking.
5) The PWM channels are HARD WIRED to the different GPIOs.
6) I believe that the LPGs are also hardwired to specific GPIOs.
[email protected] (gpio7) --> LPG3
[email protected] (gpio8) --> LPG4
[email protected] (gpio9) --> LPG5
Still working on it.
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (C) 2014 The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// #define LOG_NDEBUG 0
#include <cutils/log.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <hardware/lights.h>
/******************************************************************************/
static pthread_once_t g_init = PTHREAD_ONCE_INIT;
static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
static struct light_state_t g_notification;
static struct light_state_t g_battery;
static int rgb_brightness_ratio = 32;
char const*const RED_LED_FILE
= "/sys/class/leds/red/brightness";
char const*const GREEN_LED_FILE
= "/sys/class/leds/green/brightness";
char const*const BLUE_LED_FILE
= "/sys/class/leds/blue/brightness";
char const*const LCD_FILE
= "/sys/class/leds/lcd-backlight/brightness";
char const*const RED_ON_MS_FILE
= "/sys/class/leds/red/delay_on";
char const*const GREEN_ON_MS_FILE
= "/sys/class/leds/green/delay_on";
char const*const BLUE_ON_MS_FILE
= "/sys/class/leds/blue/delay_on";
char const*const RED_OFF_MS_FILE
= "/sys/class/leds/red/delay_off";
char const*const GREEN_OFF_MS_FILE
= "/sys/class/leds/green/delay_off";
char const*const BLUE_OFF_MS_FILE
= "/sys/class/leds/blue/delay_off";
char const*const RED_TRIGGER_FILE
= "/sys/class/leds/red/trigger";
char const*const GREEN_TRIGGER_FILE
= "/sys/class/leds/green/trigger";
char const*const BLUE_TRIGGER_FILE
= "/sys/class/leds/blue/trigger";
/**
* device methods
*/
void init_globals(void)
{
// init the mutex
pthread_mutex_init(&g_lock, NULL);
memset(&g_battery, 0, sizeof(g_battery));
memset(&g_notification, 0, sizeof(g_notification));
}
static int
write_int(char const* path, int value)
{
int fd;
static int already_warned = 0;
fd = open(path, O_RDWR);
if (fd >= 0) {
char buffer[20];
int bytes = sprintf(buffer, "%d\n", value);
ssize_t amt = write(fd, buffer, (size_t)bytes);
close(fd);
return amt == -1 ? -errno : 0;
} else {
if (already_warned == 0) {
ALOGE("write_int failed to open %s\n", path);
already_warned = 1;
}
return -errno;
}
}
static int
is_lit(struct light_state_t const* state)
{
return state->color & 0x00ffffff;
}
static int
rgb_to_brightness(struct light_state_t const* state)
{
int color = state->color & 0x00ffffff;
return ((77*((color>>16)&0x00ff))
+ (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
}
static int
set_light_backlight(struct light_device_t* dev,
struct light_state_t const* state)
{
int err = 0;
int brightness = rgb_to_brightness(state);
if(!dev) {
return -1;
}
pthread_mutex_lock(&g_lock);
err = write_int(LCD_FILE, brightness);
pthread_mutex_unlock(&g_lock);
return err;
}
/**
* There is a sperate gpio per led. Each with a maximum brightness of 20.
* The normal rgb values are computed on a scale up to 255 so we divide them
* by 12.75 so that varied brightness per led is spread out evenly per color.
* The led is only optimal on absolute red, green or blue, and produces artifacts
* of two different colors appearing at once when more than one is active, but
* this is very limiting so ultimately we allow the end user full control.
ABOVE DESCRIPTION IS TYPICAL CYANOGENMOD NONSENSE. They have the LED
configured in DIGITAL mode without PWM, which means it is either ON or OFF.
Varying the brightness of a digital LED is completely meaningless.
... this implementation has been altered from the CM BOGUS to match up with
a kernel that ties PWM to the digital LED GPIO pins, yielding a brightness range
of [0,255]
**/
static int
set_speaker_light_locked(struct light_device_t* dev,
struct light_state_t const* state)
{
unsigned int colorRGB = state->color;
int red = 0;
int green = 0;
int blue = 0;
red = ((colorRGB >> 16) & 0xFF) * rgb_brightness_ratio / 255;
green = ((colorRGB >> 8) & 0xFF) * rgb_brightness_ratio / 255;
blue = (colorRGB & 0xFF) * rgb_brightness_ratio / 255;
if (red < 10) red = 0;
if (blue < 10) blue = 0;
if (green < 10) green = 0;
write_int(RED_LED_FILE, red);
write_int(GREEN_LED_FILE, green);
write_int(BLUE_LED_FILE, blue);
#if 0
ALOGD("set_speaker_light_locked colorRGB=%08X, red=%d, green=%d, blue=%d\n",
colorRGB, red, green, blue);
#endif
return 0;
}
static void
handle_speaker_battery_locked(struct light_device_t* dev)
{
if (is_lit(&g_notification)) {
set_speaker_light_locked(dev, &g_notification);
} else {
set_speaker_light_locked(dev, &g_battery);
}
}
static int
set_light_notifications(struct light_device_t* dev,
struct light_state_t const* state)
{
pthread_mutex_lock(&g_lock);
g_notification = *state;
handle_speaker_battery_locked(dev);
pthread_mutex_unlock(&g_lock);
return 0;
}
static int
set_light_battery(struct light_device_t* dev,
struct light_state_t const* state)
{
pthread_mutex_lock(&g_lock);
g_battery = *state;
handle_speaker_battery_locked(dev);
pthread_mutex_unlock(&g_lock);
return 0;
}
/** Close the lights device */
static int
close_lights(struct light_device_t *dev)
{
if (dev) {
free(dev);
}
return 0;
}
/******************************************************************************/
/**
* module methods
*/
/** Open a new instance of a lights device using name */
static int open_lights(const struct hw_module_t* module, char const* name,
struct hw_device_t** device)
{
int (*set_light)(struct light_device_t* dev,
struct light_state_t const* state);
if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
set_light = set_light_backlight;
else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
set_light = set_light_notifications;
else if (0 == strcmp(LIGHT_ID_BATTERY, name))
set_light = set_light_battery;
else
return -EINVAL;
pthread_once(&g_init, init_globals);
struct light_device_t *dev = malloc(sizeof(struct light_device_t));
memset(dev, 0, sizeof(*dev));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (struct hw_module_t*)module;
dev->common.close = (int (*)(struct hw_device_t*))close_lights;
dev->set_light = set_light;
*device = (struct hw_device_t*)dev;
return 0;
}
static struct hw_module_methods_t lights_module_methods = {
.open = open_lights,
};
/*
* The lights Module
*/
struct hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = LIGHTS_HARDWARE_MODULE_ID,
.name = "shamu lights module",
.author = "Google, Inc.",
.methods = &lights_module_methods,
};
In lights.c function open_lights, comment out the 'else if' that checks for name=="LIGHT_ID_BATTERY", then compile your lights.shamu.Does anybody know of a way to have the LED enabled for notifications but disabled for charging? It's annoying to have the phone plugged in next to the bedside with a bright green LED lighting up the room.
I wonder if the blinker code was maybe not compiled into the pmic firmware? It is labeled as "special function 1", which suggests that it could be programmed differently. I've also seen references that suggest that it may be possible to program some really strange functionality into that hardware block.I think that the driver may be fubared.
Thanks for the info. My ideal situation is to have the LED "display black" (aka off) when fully charged. Some custom ROMs let you set this feature. I'm thinking about going back to stock for stability, but the LED is the one big conflict for me.In lights.c function open_lights, comment out the 'else if' that checks for name=="LIGHT_ID_BATTERY", then compile your lights.shamu.
Better option though is to apply my adjustments to the kernel to enable pwm and just turn down the brightness. The charging led is very nice to have, as long as it is subtle and isn't a death ray.
---------- Post added at 02:15 AM ---------- Previous post was at 02:11 AM ----------
I wonder if the blinker code was maybe not compiled into the pmic firmware? It is labeled as "special function 1", which suggests that it could be programmed differently. I've also seen references that suggest that it may be possible to program some really strange functionality into that hardware block.
From the sysimage, the *only* change you need is to lights.shamu.so (lights.c source).Thanks for the info. My ideal situation is to have the LED "display black" (aka off) when fully charged. Some custom ROMs let you set this feature. I'm thinking about going back to stock for stability, but the LED is the one big conflict for me.
That will need more than a change in a file. While charging led can be controlled by the kernel directly (easy), app notifications require changes in the device tree, you'll only find this in custom ROMs, or maybe using apps like lightflow (not 100% sure about the name amd not sure it'll work at all, or if so, reliably and it will likely require root)...Hi Devs,
Nice thread you have here, the LED is definitely an elephant in the room when I use the Nexus 6 rarely or let it charge overnight bedside. I have rooted it and flashed the Elite kernel. I'm running the Official Google Nougat 7.0 now. The charging LED works but not notifications. Can you suggest what lines of code to edit and on what files so the Notification LED works with any application?
Thank you and happy new year!
Love,
Syed
What driver have you modified to get /sys/class/leds/red/delay_on?I think that the driver may be fubared.