Em Seg, 2008-09-15 às 13:18 +0200, Antonio Ospite escreveu: > Hi Richard, hi openezx friends, > > this is a proposal for the National Semiconductor LP3944[1] leds driver > (aka Funlight) chip, found in Motorola A910. The driver is generic, > modeled after leds-pca9532, but I still have some doubts about how to > handle wiring setups.
> Now the doubts I have: > Some leds can be wired with inverted logic (leds OFF for LP3944 > means that the light is ON), like in A910 LCD backlights leds, and > +enum lp3944_type { > + LP3944_LED_TYPE_NONE, > + LP3944_LED_TYPE_LED, > + /* > + LP3944_LED_TYPE_LED_INVERTED > + */ > +}; Uncomment this, and go ahead with the inverted on/off logic on kernel space. > sometimes a led needs some pre-condition to be actually ON: > * A910 has two LCD displays whose backlights are attached to > LP3944; well, when the main display is ON, the secondary one > should be turned OFF, and vice-versa. > * A910 has two flashlight modes, the flash led can be in a low > light mode, or in a flash mode. Well, two LP3944 leds (LED6 and > LED7) are attached to the same physical flashlight diode, > controlling its state according to the following scheme: > > LED6 OFF + LED7 OFF -> lights off > LED6 OFF + LED7 ON -> strong light that turns off after ~1sec > LED6 ON + LED7 OFF -> lights off (useless) > LED6 ON + LED7 ON -> low light mode This can be handled on userspace. > The question is, should we entrust such wiring-dependent logic to > user-space? To handle that in kernel space I could set also > ledX_set_brightness() callbacks via platform data, it shouldn't be too > difficult. I dont think that _set_brightness via platform_data is a good idea, we would end with a lot of duplicate code. > And, should I use backlight-class devices for backlight driving leds? Good idea. Add a .backlights array to the platform data. :) > +static struct lp3944_platform_data a910_lp3944_leds = { > + /* set two default dim modes, a fast one and a slow one. > + * they will be used when brightness == {2,3} > + */ > + .dims = { > + [0] = { > + .period = 5, > + .dutycycle = 5, > + }, > + [1] = { > + .period = 10, > + .dutycycle = 50, > + }, > + }, > + .leds = { > + [0] = { > + .name = "a910:red", > + .status = LP3944_LED_STATUS_OFF, > + .type = LP3944_LED_TYPE_LED, > + }, > + [1] = { > + .name = "a910:green", > + .status = LP3944_LED_STATUS_OFF, > + .type = LP3944_LED_TYPE_LED, > + }, > + [2] { > + .name = "a910:blue", > + .status = LP3944_LED_STATUS_OFF, > + .type = LP3944_LED_TYPE_LED, > + }, > + /* Leds 3 and 4 are displays backlights */ > + [3] = { > + .name = "a910:cli_backlight", > + .status = LP3944_LED_STATUS_ON, > + .type = LP3944_LED_TYPE_LED > + }, > + [4] = { > + .name = "a910:main_backlight", > + .status = LP3944_LED_STATUS_ON, > + .type = LP3944_LED_TYPE_LED > + }, > + [5] = { .type = LP3944_LED_TYPE_NONE }, > + [6] = { > + .name = "a910:torch", > + .status = LP3944_LED_STATUS_OFF, > + .type = LP3944_LED_TYPE_LED, > + }, > + [7] = { > + .name = "a910:flash", > + .status = LP3944_LED_STATUS_OFF, > + .type = LP3944_LED_TYPE_LED, > + }, > + }, > +}; Add .dims_size/.leds_size fields for these arrays... > + for (i = 0; i < 2; i++) { > + lp3944_dim_set_period(client, i, > pdata->dims[i].period); > + lp3944_dim_set_dutycycle(client, i, > pdata->dims[i].dutycycle); > + } > + > + for (i = 0; i < 8; i++) { And use it here instead of relying on the fixed array size. Also, make the .dims array optional and pass on the led wiring number (*_LEDx) on the .leds fields. > +static void lp3944_set_brightness(struct led_classdev *led_cdev, > + enum led_brightness value) > +{ > + struct lp3944_led *led = ldev_to_led(led_cdev); > + > + /* > + * Meaning of the value parameter: > + * 0 = led OFF > + * 1 = led ON > + * 2 = led in DIM0 mode > + * 3 = led in DIM1 mode > + */ > + if (value > 3) > + value = 3; > + pr_debug(KERN_DEBUG "%s: %d\n", led_cdev->name, value); > + lp3944_led_set(led, value); > +} You probably shouldn't abuse "brightness" to set dim modes, but if you really want to do it, the "1 = led ON" should be the default for (value>3). -- Daniel Ribeiro