Revert "EDP: remove old system EDP framework (pwm backlight driver)"
authorDominik Sliwa <dominik.sliwa@toradex.com>
Tue, 27 Mar 2018 13:36:25 +0000 (15:36 +0200)
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>
Wed, 28 Mar 2018 16:39:27 +0000 (18:39 +0200)
This reverts commit 08a13bacb43f206239ae0f1ccbe37325993e2b1b.

drivers/video/backlight/pwm_bl.c
include/linux/pwm_backlight.h

index 29b55621b5f42696d64c5d08fb294715c33e67d5..e4c6d27727175f96fb758834e77997567db512b2 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/slab.h>
+#include <linux/edp.h>
 
 struct pwm_bl_data {
        struct pwm_device       *pwm;
@@ -46,6 +47,8 @@ struct pwm_bl_data {
                                        int brightness);
        int                     (*check_fb)(struct device *, struct fb_info *);
        void                    (*exit)(struct device *);
+       struct edp_client *pwm_bl_edp_client;
+       int *edp_brightness_states;
 };
 
 static int pwm_backlight_set(struct backlight_device *bl, int brightness)
@@ -86,10 +89,45 @@ static int pwm_backlight_set(struct backlight_device *bl, int brightness)
        return 0;
 }
 
+static int pwm_backlight_set_with_edp(struct backlight_device *bl,
+       int brightness)
+{
+       struct pwm_bl_data *data = bl_get_data(bl);
+       unsigned int approved;
+       int ret;
+       unsigned int edp_state;
+       unsigned int i;
+       if (data->pwm_bl_edp_client) {
+               for (i = 0; i < PWM_BL_EDP_NUM_STATES; i++) {
+                       if (brightness >= data->edp_brightness_states[i])
+                               break;
+               }
+               edp_state = i;
+               ret = edp_update_client_request(data->pwm_bl_edp_client,
+                                                       edp_state, &approved);
+               if (ret) {
+                       dev_err(data->dev, "E state transition failed\n");
+                       return ret;
+               }
+               pwm_backlight_set(bl, data->edp_brightness_states[approved]);
+       } else {
+               pwm_backlight_set(bl, brightness);
+       }
+       return 0;
+}
+
 static int pwm_backlight_update_status(struct backlight_device *bl)
 {
        int brightness = bl->props.brightness;
-       return pwm_backlight_set(bl, brightness);
+       return pwm_backlight_set_with_edp(bl, brightness);
+}
+
+static void pwm_backlight_edpcb(unsigned int new_state, void *priv_data)
+{
+       struct backlight_device *bl_device =
+               (struct backlight_device *) priv_data;
+       struct pwm_bl_data *data = bl_get_data(bl_device);
+       pwm_backlight_set(bl_device, data->edp_brightness_states[new_state]);
 }
 
 static int pwm_backlight_get_brightness(struct backlight_device *bl)
@@ -192,6 +230,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        struct backlight_properties props;
        struct backlight_device *bl;
        struct pwm_bl_data *pb;
+       struct edp_manager *battery_manager = NULL;
        unsigned int max;
        int ret;
 
@@ -230,6 +269,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        pb->exit = data->exit;
        pb->dev = &pdev->dev;
        pb->pwm_gpio = data->pwm_gpio;
+       pb->edp_brightness_states = data->edp_brightness;
 
        pb->pwm = devm_pwm_get(&pdev->dev, NULL);
        if (IS_ERR(pb->pwm)) {
@@ -274,6 +314,57 @@ static int pwm_backlight_probe(struct platform_device *pdev)
                goto err_alloc;
        }
 
+       if (pb->edp_brightness_states) {
+               pb->pwm_bl_edp_client = devm_kzalloc(&pdev->dev,
+                               sizeof(struct edp_client), GFP_KERNEL);
+               if (IS_ERR_OR_NULL(pb->pwm_bl_edp_client)) {
+                       dev_err(&pdev->dev, "could not allocate edp client\n");
+                       return PTR_ERR(pb->pwm_bl_edp_client);
+               }
+
+               strncpy(pb->pwm_bl_edp_client->name,
+                                               "backlight", EDP_NAME_LEN - 1);
+               pb->pwm_bl_edp_client->name[EDP_NAME_LEN - 1] = '\0';
+               pb->pwm_bl_edp_client->states = data->edp_states;
+               pb->pwm_bl_edp_client->num_states = PWM_BL_EDP_NUM_STATES;
+               pb->pwm_bl_edp_client->e0_index = PWM_BL_EDP_ZERO;
+               pb->pwm_bl_edp_client->private_data = bl;
+               pb->pwm_bl_edp_client->priority = EDP_MAX_PRIO + 2;
+               pb->pwm_bl_edp_client->throttle = pwm_backlight_edpcb;
+               pb->pwm_bl_edp_client->notify_promotion = pwm_backlight_edpcb;
+
+               battery_manager = edp_get_manager("battery");
+               if (!battery_manager) {
+                       dev_err(&pdev->dev, "unable to get edp manager\n");
+                       goto err_edp_init;
+               } else {
+                       ret = edp_register_client(battery_manager,
+                                               pb->pwm_bl_edp_client);
+                       if (ret) {
+                               dev_err(&pdev->dev, "unable to register edp client\n");
+                               goto err_edp_init;
+                       } else {
+                               ret = edp_update_client_request(
+                                               pb->pwm_bl_edp_client,
+                                                       PWM_BL_EDP_ZERO, NULL);
+                               if (ret) {
+                                       dev_err(&pdev->dev,
+                                               "unable to set E0 EDP state\n");
+                                       edp_unregister_client(
+                                               pb->pwm_bl_edp_client);
+                                       goto err_edp_init;
+                               }
+                               goto success_edp_init;
+                       }
+               }
+err_edp_init:
+               devm_kfree(&pdev->dev, pb->pwm_bl_edp_client);
+               pb->pwm_bl_edp_client = NULL;
+success_edp_init:;
+       } else {
+               dev_info(&pdev->dev, "edp manager not supported\n");
+       }
+
        if (data->dft_brightness > data->max_brightness) {
                dev_warn(&pdev->dev,
                         "invalid default brightness level: %u, using %u\n",
@@ -314,7 +405,7 @@ static int pwm_backlight_suspend(struct device *dev)
 {
        struct backlight_device *bl = dev_get_drvdata(dev);
 
-       return pwm_backlight_set(bl, 0);
+       return pwm_backlight_set_with_edp(bl, 0);
 }
 
 static int pwm_backlight_resume(struct device *dev)
index bf19167960febd614cf79d8415e29bf107c6ce35..c4d55510c7bdda555a4d96e1c2bcfb13a2371ee4 100644 (file)
 
 #include <linux/backlight.h>
 
+enum pwm_bl_edp_states {
+       PWM_BL_EDP_NEG_3,
+       PWM_BL_EDP_NEG_2,
+       PWM_BL_EDP_NEG_1,
+       PWM_BL_EDP_ZERO,
+       PWM_BL_EDP_1,
+       PWM_BL_EDP_2,
+       PWM_BL_EDP_3,
+       PWM_BL_EDP_4,
+       PWM_BL_EDP_5,
+       PWM_BL_EDP_6,
+       PWM_BL_EDP_NUM_STATES,
+};
+
+#define PWM_BL_EDP_BRIGHTNESS_UNIT     25
+
 struct platform_pwm_backlight_data {
        int pwm_id;
        unsigned int max_brightness;
@@ -31,6 +47,8 @@ struct platform_pwm_backlight_data {
        void (*notify_after)(struct device *dev, int brightness);
        void (*exit)(struct device *dev);
        int (*check_fb)(struct device *dev, struct fb_info *info);
+       unsigned int *edp_states;
+       unsigned int *edp_brightness;
 };
 
 #endif