diff --git a/ddcci-backlight/ddcci-backlight.c b/ddcci-backlight/ddcci-backlight.c index 7a98522..e518bfc 100644 --- a/ddcci-backlight/ddcci-backlight.c +++ b/ddcci-backlight/ddcci-backlight.c @@ -29,6 +29,12 @@ #define DDCCI_MONITOR_BACKLIGHT 0x13 #define DDCCI_MONITOR_BL_WHITE 0x6B +#define DDCCI_BL_MUX_MAX_DEVICES 8 + +static struct backlight_device *ddcci_bl_global_control = NULL; +static struct backlight_device *ddcci_bl_mux_devices[DDCCI_BL_MUX_MAX_DEVICES] = {NULL}; +static int ddcci_bl_mux_device_count = 0; + static bool convenience_symlink = true; struct ddcci_monitor_drv_data { @@ -101,13 +107,21 @@ static int ddcci_backlight_update_status(struct backlight_device *bl) struct ddcci_monitor_drv_data *drv_data = bl_get_data(bl); int brightness = bl->props.brightness; int ret; + int i; - if (bl->props.power != FB_BLANK_UNBLANK || - bl->props.state & BL_CORE_FBBLANK) - brightness = 0; + if (drv_data == NULL) { + for (i = 0; i < ddcci_bl_mux_device_count; ++i) { + ddcci_bl_mux_devices[i]->props.brightness = bl->props.brightness; + ddcci_backlight_update_status(ddcci_bl_mux_devices[i]); + } + } else { + if (bl->props.power != FB_BLANK_UNBLANK || + bl->props.state & BL_CORE_FBBLANK) + brightness = 0; - ret = ddcci_monitor_writectrl(drv_data->device, drv_data->used_vcp, - brightness); + ret = ddcci_monitor_writectrl(drv_data->device, drv_data->used_vcp, + brightness); + } if (ret > 0) ret = 0; return ret; @@ -119,6 +133,10 @@ static int ddcci_backlight_get_brightness(struct backlight_device *bl) int ret; struct ddcci_monitor_drv_data *drv_data = bl_get_data(bl); + if (drv_data == NULL) { + return bl->props.brightness; + } + ret = ddcci_monitor_readctrl(drv_data->device, drv_data->used_vcp, &value, &maxval); if (ret < 0) @@ -277,6 +295,7 @@ static int ddcci_monitor_probe(struct ddcci_device *dev, { struct ddcci_monitor_drv_data *drv_data; struct backlight_properties props; + struct backlight_properties cprops; struct backlight_device *bl = NULL; int ret = 0; bool support_luminance, support_bl_white; @@ -369,6 +388,27 @@ static int ddcci_monitor_probe(struct ddcci_device *dev, ddcci_backlight_create_symlink(dev); } + if (ddcci_bl_global_control == NULL) { + printk(KERN_INFO "ddcci-backlight: registering global controller with brightness=%d, max_brightness=%d\n", + brightness, max_brightness); + cprops.type = BACKLIGHT_FIRMWARE; + cprops.max_brightness = max_brightness; + cprops.brightness = brightness; + ddcci_bl_global_control = devm_backlight_device_register(&dev->dev, "0000-ddcci_backlight_global_control", + &dev->dev, NULL, + &ddcci_backlight_ops, &cprops); + }; + + if(ddcci_bl_mux_device_count < DDCCI_BL_MUX_MAX_DEVICES) { + dev_info(&dev->dev, "registering backlight device %s as mux slave #%d", + dev_name(&dev->dev), ddcci_bl_mux_device_count); + ddcci_bl_mux_devices[ddcci_bl_mux_device_count] = bl; + dev_info(&dev->dev, "registered mux slave #%d successfully", ddcci_bl_mux_device_count); + ++ddcci_bl_mux_device_count; + } else { + dev_info(&dev->dev, "new backlight device added, but mux slave array is at max capacity. global control will not work for this device."); + } + goto end; err_free: devm_kfree(&dev->dev, drv_data); @@ -378,8 +418,27 @@ end: static int ddcci_monitor_remove(struct ddcci_device *dev) { + int i,j; + dev_dbg(&dev->dev, "removing device\n"); ddcci_backlight_remove_symlink(dev); + + for (i = 0; i < ddcci_bl_mux_device_count; ++i) { + struct backlight_device *bl = ddcci_bl_mux_devices[i]; + printk(KERN_INFO "ddcci-backlight: scan for remove global device %d from control array\n", i); + if (dev == (struct ddcci_device*) bl_get_data(bl)) { + printk(KERN_INFO "ddcci-backlight: removing global device %d from control array\n", i); + ddcci_bl_mux_devices[i] = NULL; + for (j = i+1; j < ddcci_bl_mux_device_count; ++j) { + if(ddcci_bl_mux_devices[j] != NULL) { + printk(KERN_INFO "ddcci-backlight: adjusting global devices %d -> %d\n", j, j-1); + ddcci_bl_mux_devices[j-1] = ddcci_bl_mux_devices[j]; + } + } + --ddcci_bl_mux_device_count; + } + } + return 0; }