^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * AS3711 PMIC backlight driver, using DCDC Step Up Converters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2012 Renesas Electronics Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/backlight.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mfd/as3711.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) enum as3711_bl_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) AS3711_BL_SU1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) AS3711_BL_SU2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct as3711_bl_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) bool powered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) enum as3711_bl_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct backlight_device *bl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct as3711_bl_supply {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct as3711_bl_data su1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct as3711_bl_data su2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) const struct as3711_bl_pdata *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct as3711 *as3711;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static struct as3711_bl_supply *to_supply(struct as3711_bl_data *su)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) switch (su->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) case AS3711_BL_SU1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return container_of(su, struct as3711_bl_supply, su1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case AS3711_BL_SU2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return container_of(su, struct as3711_bl_supply, su2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static int as3711_set_brightness_auto_i(struct as3711_bl_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned int brightness)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct as3711_bl_supply *supply = to_supply(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct as3711 *as3711 = supply->as3711;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) const struct as3711_bl_pdata *pdata = supply->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* Only all equal current values are supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (pdata->su2_auto_curr1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ret = regmap_write(as3711->regmap, AS3711_CURR1_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (!ret && pdata->su2_auto_curr2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ret = regmap_write(as3711->regmap, AS3711_CURR2_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (!ret && pdata->su2_auto_curr3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ret = regmap_write(as3711->regmap, AS3711_CURR3_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static int as3711_set_brightness_v(struct as3711 *as3711,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned int brightness,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (brightness > 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return regmap_update_bits(as3711->regmap, reg, 0xf0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) brightness << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static int as3711_bl_su2_reset(struct as3711_bl_supply *supply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct as3711 *as3711 = supply->as3711;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) 3, supply->pdata->su2_fbprot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ret = regmap_update_bits(as3711->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) AS3711_STEPUP_CONTROL_2, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) ret = regmap_update_bits(as3711->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) AS3711_STEPUP_CONTROL_2, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Someone with less fragile or less expensive hardware could try to simplify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * the brightness adjustment procedure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int as3711_bl_update_status(struct backlight_device *bl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct as3711_bl_data *data = bl_get_data(bl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct as3711_bl_supply *supply = to_supply(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct as3711 *as3711 = supply->as3711;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) brightness = backlight_get_brightness(bl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (data->type == AS3711_BL_SU1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ret = as3711_set_brightness_v(as3711, brightness,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) AS3711_STEPUP_CONTROL_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) const struct as3711_bl_pdata *pdata = supply->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) switch (pdata->su2_feedback) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case AS3711_SU2_VOLTAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ret = as3711_set_brightness_v(as3711, brightness,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) AS3711_STEPUP_CONTROL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) case AS3711_SU2_CURR_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ret = as3711_set_brightness_auto_i(data, brightness / 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (brightness) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ret = as3711_bl_su2_reset(supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) udelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ret = as3711_set_brightness_auto_i(data, brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ret = regmap_update_bits(as3711->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) AS3711_STEPUP_CONTROL_2, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Manual one current feedback pin below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) case AS3711_SU2_CURR1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ret = regmap_write(as3711->regmap, AS3711_CURR1_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) case AS3711_SU2_CURR2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ret = regmap_write(as3711->regmap, AS3711_CURR2_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) case AS3711_SU2_CURR3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ret = regmap_write(as3711->regmap, AS3711_CURR3_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) data->brightness = brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int as3711_bl_get_brightness(struct backlight_device *bl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct as3711_bl_data *data = bl_get_data(bl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return data->brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static const struct backlight_ops as3711_bl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .update_status = as3711_bl_update_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .get_brightness = as3711_bl_get_brightness,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static int as3711_bl_init_su2(struct as3711_bl_supply *supply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct as3711 *as3711 = supply->as3711;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) const struct as3711_bl_pdata *pdata = supply->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) u8 ctl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) dev_dbg(as3711->dev, "%s(): use %u\n", __func__, pdata->su2_feedback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* Turn SU2 off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ret = regmap_write(as3711->regmap, AS3711_STEPUP_CONTROL_2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) switch (pdata->su2_feedback) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) case AS3711_SU2_VOLTAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) case AS3711_SU2_CURR1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ctl = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) case AS3711_SU2_CURR2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ctl = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) case AS3711_SU2_CURR3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ctl = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) case AS3711_SU2_CURR_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (pdata->su2_auto_curr1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ctl = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (pdata->su2_auto_curr2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ctl |= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (pdata->su2_auto_curr3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ctl |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ret = regmap_write(as3711->regmap, AS3711_CURR_CONTROL, ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static int as3711_bl_register(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) unsigned int max_brightness, struct as3711_bl_data *su)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct backlight_properties props = {.type = BACKLIGHT_RAW,};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct backlight_device *bl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* max tuning I = 31uA for voltage- and 38250uA for current-feedback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) props.max_brightness = max_brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) bl = devm_backlight_device_register(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) su->type == AS3711_BL_SU1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) "as3711-su1" : "as3711-su2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) &pdev->dev, su,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) &as3711_bl_ops, &props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (IS_ERR(bl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) dev_err(&pdev->dev, "failed to register backlight\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return PTR_ERR(bl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) bl->props.brightness = props.max_brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) backlight_update_status(bl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) su->bl = bl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static int as3711_backlight_parse_dt(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct as3711_bl_pdata *pdata = dev_get_platdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct device_node *bl, *fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) bl = of_get_child_by_name(dev->parent->of_node, "backlight");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!bl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) dev_dbg(dev, "backlight node not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) fb = of_parse_phandle(bl, "su1-dev", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (fb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) of_node_put(fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) pdata->su1_fb = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) ret = of_property_read_u32(bl, "su1-max-uA", &pdata->su1_max_uA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (pdata->su1_max_uA <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) goto err_put_bl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) fb = of_parse_phandle(bl, "su2-dev", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (fb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) of_node_put(fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) pdata->su2_fb = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ret = of_property_read_u32(bl, "su2-max-uA", &pdata->su2_max_uA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (pdata->su2_max_uA <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) goto err_put_bl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (of_find_property(bl, "su2-feedback-voltage", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) pdata->su2_feedback = AS3711_SU2_VOLTAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (of_find_property(bl, "su2-feedback-curr1", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) pdata->su2_feedback = AS3711_SU2_CURR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (of_find_property(bl, "su2-feedback-curr2", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) pdata->su2_feedback = AS3711_SU2_CURR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (of_find_property(bl, "su2-feedback-curr3", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) pdata->su2_feedback = AS3711_SU2_CURR3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (of_find_property(bl, "su2-feedback-curr-auto", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) pdata->su2_feedback = AS3711_SU2_CURR_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (count != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) goto err_put_bl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (of_find_property(bl, "su2-fbprot-lx-sd4", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) pdata->su2_fbprot = AS3711_SU2_LX_SD4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (of_find_property(bl, "su2-fbprot-gpio2", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) pdata->su2_fbprot = AS3711_SU2_GPIO2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (of_find_property(bl, "su2-fbprot-gpio3", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) pdata->su2_fbprot = AS3711_SU2_GPIO3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (of_find_property(bl, "su2-fbprot-gpio4", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) pdata->su2_fbprot = AS3711_SU2_GPIO4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (count != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) goto err_put_bl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (of_find_property(bl, "su2-auto-curr1", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) pdata->su2_auto_curr1 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (of_find_property(bl, "su2-auto-curr2", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) pdata->su2_auto_curr2 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (of_find_property(bl, "su2-auto-curr3", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) pdata->su2_auto_curr3 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * At least one su2-auto-curr* must be specified iff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * AS3711_SU2_CURR_AUTO is used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (!count ^ (pdata->su2_feedback != AS3711_SU2_CURR_AUTO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) goto err_put_bl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) of_node_put(bl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) err_put_bl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) of_node_put(bl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static int as3711_backlight_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct as3711_bl_pdata *pdata = dev_get_platdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct as3711_bl_supply *supply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct as3711_bl_data *su;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) unsigned int max_brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) dev_err(&pdev->dev, "No platform data, exiting...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (pdev->dev.parent->of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) ret = as3711_backlight_parse_dt(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) dev_err(&pdev->dev, "DT parsing failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (!pdata->su1_fb && !pdata->su2_fb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) dev_err(&pdev->dev, "No framebuffer specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * Due to possible hardware damage I chose to block all modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * unsupported on my hardware. Anyone, wishing to use any of those modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * will have to first review the code, then activate and test it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (pdata->su1_fb ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) pdata->su2_fbprot != AS3711_SU2_GPIO4 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) pdata->su2_feedback != AS3711_SU2_CURR_AUTO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) dev_warn(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) "Attention! An untested mode has been chosen!\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) "Please, review the code, enable, test, and report success:-)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) supply = devm_kzalloc(&pdev->dev, sizeof(*supply), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (!supply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) supply->as3711 = as3711;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) supply->pdata = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (pdata->su1_fb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) su = &supply->su1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) su->type = AS3711_BL_SU1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) max_brightness = min(pdata->su1_max_uA, 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) ret = as3711_bl_register(pdev, max_brightness, su);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (pdata->su2_fb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) su = &supply->su2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) su->type = AS3711_BL_SU2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) switch (pdata->su2_fbprot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) case AS3711_SU2_GPIO2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) case AS3711_SU2_GPIO3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) case AS3711_SU2_GPIO4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) case AS3711_SU2_LX_SD4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) switch (pdata->su2_feedback) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) case AS3711_SU2_VOLTAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) max_brightness = min(pdata->su2_max_uA, 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) case AS3711_SU2_CURR1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) case AS3711_SU2_CURR2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) case AS3711_SU2_CURR3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) case AS3711_SU2_CURR_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) max_brightness = min(pdata->su2_max_uA / 150, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ret = as3711_bl_init_su2(supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ret = as3711_bl_register(pdev, max_brightness, su);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) platform_set_drvdata(pdev, supply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static struct platform_driver as3711_backlight_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .name = "as3711-backlight",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) .probe = as3711_backlight_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) module_platform_driver(as3711_backlight_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) MODULE_DESCRIPTION("Backlight Driver for AS3711 PMICs");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) MODULE_ALIAS("platform:as3711-backlight");