Description:
                Maximum brightness for <backlight>.
 Users:         HAL
+
+What:          /sys/class/backlight/<backlight>/type
+Date:          September 2010
+KernelVersion: 2.6.37
+Contact:       Matthew Garrett <mjg@redhat.com>
+Description:
+               The type of interface controlled by <backlight>.
+               "firmware": The driver uses a standard firmware interface
+               "platform": The driver uses a platform-specific interface
+               "raw": The driver controls hardware registers directly
+
+               In the general case, when multiple backlight
+               interfaces are available for a single device, firmware
+               control should be preferred to platform control should
+               be preferred to raw control. Using a firmware
+               interface reduces the probability of confusion with
+               the hardware and the OS independently updating the
+               backlight state. Platform interfaces are mostly a
+               holdover from pre-standardisation of firmware
+               interfaces.
 
                count++;
 
                memset(&props, 0, sizeof(struct backlight_properties));
+               props.type = BACKLIGHT_FIRMWARE;
                props.max_brightness = device->brightness->count - 3;
                device->backlight = backlight_device_register(name, NULL, device,
                                                              &acpi_backlight_ops,
 
                return 0;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = 31;
        bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
                                       &nv40_bl_ops, &props);
                return 0;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = 1025;
        bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
                                       &nv50_bl_ops, &props);
 
        }
 
        memset(&props, 0, sizeof(props));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = 0xff;
        bdev = backlight_device_register(dev_name(dev), dev, data,
                        &picolcd_blops, &props);
 
        snprintf(name, sizeof(name), "pmubl");
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
        bd = backlight_device_register(name, NULL, NULL, &pmu_backlight_data,
                                       &props);
 
        struct backlight_device *bd;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = max_brightness;
        bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
                                       &props);
 
 
        memset(&props, 0, sizeof(struct backlight_properties));
        props.max_brightness = 15;
+       props.type = BACKLIGHT_PLATFORM;
 
        bd = backlight_device_register(ASUS_LAPTOP_FILE,
                                       &asus->platform_device->dev, asus,
 
        }
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = 15;
        asus_backlight_device = backlight_device_register("asus", NULL, NULL,
                                                          &asus_backlight_data,
 
                return -ENOMEM;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = 7;
        ipml->bd = backlight_device_register("cmpc_bl", &acpi->dev,
                                             acpi->handle, &cmpc_bl_ops,
 
        if (!acpi_video_backlight_support()) {
                struct backlight_properties props;
                memset(&props, 0, sizeof(struct backlight_properties));
+               props.type = BACKLIGHT_PLATFORM;
                props.max_brightness = BACKLIGHT_LEVEL_MAX;
                compalbl_device = backlight_device_register(DRIVER_NAME,
                                                            NULL, NULL,
 
        if (max_intensity) {
                struct backlight_properties props;
                memset(&props, 0, sizeof(struct backlight_properties));
+               props.type = BACKLIGHT_PLATFORM;
                props.max_brightness = max_intensity;
                dell_backlight_device = backlight_device_register("dell_backlight",
                                                                  &platform_device->dev,
 
        struct backlight_device *bd;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = 15;
        bd = backlight_device_register(EEEPC_LAPTOP_FILE,
                                       &eeepc->platform_device->dev, eeepc,
 
 
                memset(&props, 0, sizeof(struct backlight_properties));
                max_brightness = fujitsu->max_brightness;
+               props.type = BACKLIGHT_PLATFORM;
                props.max_brightness = max_brightness - 1;
                fujitsu->bl_device = backlight_device_register("fujitsu-laptop",
                                                               NULL, NULL,
 
        } else {
                struct backlight_properties props;
                memset(&props, 0, sizeof(struct backlight_properties));
+               props.type = BACKLIGHT_PLATFORM;
                props.max_brightness = MSI_LCD_LEVEL_MAX - 1;
                msibl_device = backlight_device_register("msi-laptop-bl", NULL,
                                                         NULL, &msibl_ops,
 
        if (!acpi_video_backlight_support()) {
                struct backlight_properties props;
                memset(&props, 0, sizeof(struct backlight_properties));
+               props.type = BACKLIGHT_PLATFORM;
                props.max_brightness = ARRAY_SIZE(backlight_map) - 1;
                backlight = backlight_device_register(DRV_NAME, NULL, NULL,
                                                      &msi_backlight_ops,
 
        }
        /* initialize backlight */
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = pcc->sinf[SINF_AC_MAX_BRIGHT];
        pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
                                                   &pcc_backlight_ops, &props);
 
                       "controlled by ACPI video driver\n");
        } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
                                                &handle))) {
-                                                       struct backlight_properties props;
+               struct backlight_properties props;
                memset(&props, 0, sizeof(struct backlight_properties));
+               props.type = BACKLIGHT_PLATFORM;
                props.max_brightness = SONY_MAX_BRIGHTNESS - 1;
                sony_backlight_device = backlight_device_register("sony", NULL,
                                                                  NULL,
 
                return 1;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = bright_maxlvl;
        props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
        ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME,
 
                create_toshiba_proc_entries();
        }
 
+       props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
        toshiba_backlight_device = backlight_device_register("toshiba",
                                                             &toshiba_acpi.p_dev->dev,
 
 
 static struct backlight_properties dcon_bl_props = {
        .max_brightness = 15,
+       .type = BACKLIGHT_RAW,
        .power = FB_BLANK_UNBLANK,
 };
 
 
 
        /* create a backlight device to talk to this one */
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = sabi_config->max_brightness;
        backlight_device = backlight_device_register("samsung", &sdev->dev,
                                                     NULL, &backlight_ops,
 
        snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
                atomic_inc_return(&count_displays) - 1);
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = 0xff;
        pdata->bd = backlight_device_register(bl_name, NULL, pdata,
                                              &appledisplay_bl_data, &props);
 
                return;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = 0xff;
        bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo,
                                       &atmel_lcdc_bl_ops, &props);
 
        snprintf(name, sizeof(name), "aty128bl%d", info->node);
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
        bd = backlight_device_register(name, info->dev, par, &aty128_bl_data,
                                       &props);
 
        snprintf(name, sizeof(name), "atybl%d", info->node);
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
        bd = backlight_device_register(name, info->dev, par, &aty_bl_data,
                                       &props);
 
        snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
        bd = backlight_device_register(name, rinfo->info->dev, pdata,
                                       &radeon_bl_data, &props);
 
        }
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = MAX_BRIGHTNESS;
        bl = backlight_device_register(name, &pdev->dev, data,
                                        &pm860x_backlight_ops, &props);
 
        mutex_init(&data->lock);
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = ADP5020_MAX_BRIGHTNESS;
        bl = backlight_device_register(pdev->name, data->master, data,
                                       &adp5520_bl_ops, &props);
 
        i2c_set_clientdata(client, data);
 
        memset(&props, 0, sizeof(props));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = ADP8860_MAX_BRIGHTNESS;
 
        mutex_init(&data->lock);
 
        }
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = 0xff;
        bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
                                          bl, &adx_backlight_ops, &props);
 
        }
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
        bldev = backlight_device_register("atmel-pwm-bl", &pdev->dev, pwmbl,
                                          &atmel_pwm_bl_ops, &props);
 
 #include <asm/backlight.h>
 #endif
 
+static const char const *backlight_types[] = {
+       [BACKLIGHT_RAW] = "raw",
+       [BACKLIGHT_PLATFORM] = "platform",
+       [BACKLIGHT_FIRMWARE] = "firmware",
+};
+
 #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
                           defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
 /* This callback gets called when something important happens inside a
        return rc;
 }
 
+static ssize_t backlight_show_type(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct backlight_device *bd = to_backlight_device(dev);
+
+       return sprintf(buf, "%s\n", backlight_types[bd->props.type]);
+}
+
 static ssize_t backlight_show_max_brightness(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
        __ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
                     NULL),
        __ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
+       __ATTR(type, 0444, backlight_show_type, NULL),
        __ATTR_NULL,
 };
 
        dev_set_drvdata(&new_bd->dev, devdata);
 
        /* Set default properties */
-       if (props)
+       if (props) {
                memcpy(&new_bd->props, props,
                       sizeof(struct backlight_properties));
+               if (props->type <= 0 || props->type >= BACKLIGHT_TYPE_MAX) {
+                       WARN(1, "%s: invalid backlight type", name);
+                       new_bd->props.type = BACKLIGHT_RAW;
+               }
+       } else {
+               new_bd->props.type = BACKLIGHT_RAW;
+       }
 
        rc = device_register(&new_bd->dev);
        if (rc) {
 
        lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = pdata->max_intensity;
        lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev, lcd,
                                                &corgi_bl_ops, &props);
 
        }
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        bdp = backlight_device_register("cr-backlight", &pdev->dev, NULL,
                                        &cr_backlight_ops, &props);
        if (IS_ERR(bdp)) {
 
                da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2,
                                DA9034_WLED_ISET(pdata->output_current));
 
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = max_brightness;
        bl = backlight_device_register(pdev->name, data->da903x_dev, data,
                                       &da903x_backlight_ops, &props);
 
        ep93xxbl->mmio = EP93XX_RASTER_BRIGHTNESS;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = EP93XX_MAX_BRIGHT;
        bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl,
                                       &ep93xxbl_ops, &props);
 
                name = machinfo->name;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = machinfo->max_intensity;
        bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops,
                                       &props);
 
        struct backlight_device *bd;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = HP680_MAX_INTENSITY;
        bd = backlight_device_register("hp680-bl", &pdev->dev, NULL,
                                       &hp680bl_ops, &props);
 
        struct backlight_device *bd;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = BL_MAX_BRIGHT;
        bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL,
                                       &jornada_bl_ops, &props);
 
                machinfo->limit_mask = -1;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = machinfo->max_intensity;
        kb3886_backlight_device = backlight_device_register("kb3886-bl",
                                                            &pdev->dev, NULL,
 
        local_irq_restore(flags);
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = 4;
        locomolcd_bl_device = backlight_device_register("locomo-bl",
                                                        &ldev->dev, NULL,
 
        data->current_brightness = 0;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = MAX_BRIGHTNESS;
        bl = backlight_device_register(name, &pdev->dev, data,
                                        &max8925_backlight_ops, &props);
 
                return -ENXIO;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = 15;
        mbp_backlight_device = backlight_device_register("mbp_backlight", NULL,
                                                         NULL,
 
                return -ENOMEM;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = OMAPBL_MAX_INTENSITY;
        dev = backlight_device_register("omap-bl", &pdev->dev, bl, &omapbl_ops,
                                        &props);
 
        if (!pcf_bl)
                return -ENOMEM;
 
+       bl_props.type = BACKLIGHT_RAW;
        bl_props.max_brightness = 0x3f;
        bl_props.power = FB_BLANK_UNBLANK;
 
 
        pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20);
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
        progear_backlight_device = backlight_device_register("progear-bl",
                                                             &pdev->dev, NULL,
 
                dev_dbg(&pdev->dev, "got pwm for backlight\n");
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = data->max_brightness;
        bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
                                       &pwm_backlight_ops, &props);
 
 
        bd->props.max_brightness = MAX_BRIGHTNESS;
        bd->props.brightness = MAX_BRIGHTNESS;
+       bd->props.type = BACKLIGHT_RAW;
        lcd->bd = bd;
 
        /*
 
        data->i2c = client;
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = 512 - 1;
        data->bl = backlight_device_register("tosa-bl", &client->dev, data,
                                             &bl_ops, &props);
 
        data->current_brightness = 0;
        data->isink_reg = isink_reg;
 
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = max_isel;
        bl = backlight_device_register("wm831x", &pdev->dev, data,
                                       &wm831x_backlight_ops, &props);
 
        }
 #ifndef NO_BL_SUPPORT
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = 255;
        bl_dev = backlight_device_register("bf54x-bl", NULL, NULL,
                                           &bfin_lq043fb_bl_ops, &props);
 
        }
 #ifndef NO_BL_SUPPORT
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = 255;
        bl_dev = backlight_device_register("bf52x-bl", NULL, NULL,
                                           &bfin_lq043fb_bl_ops, &props);
 
 
        memset(&props, 0, sizeof(struct backlight_properties));
        props.max_brightness = 0xff;
+       props.type = BACKLIGHT_RAW;
        writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
 
        bl = backlight_device_register("imxfb-bl", &fbi->pdev->dev, fbi,
 
        snprintf(name, sizeof(name), "nvidiabl%d", info->node);
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
        bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops,
                                       &props);
 
 
        props.fb_blank = FB_BLANK_UNBLANK;
        props.power = FB_BLANK_UNBLANK;
+       props.type = BACKLIGHT_RAW;
 
        bldev = backlight_device_register("acx565akm", &md->spi->dev,
                        md, &acx565akm_bl_ops, &props);
 
 
        memset(&props, 0, sizeof(struct backlight_properties));
        props.max_brightness = dssdev->max_backlight_level;
+       props.type = BACKLIGHT_RAW;
 
        bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev,
                        &sharp_ls_bl_ops, &props);
 
                props.max_brightness = 255;
        else
                props.max_brightness = 127;
+
+       props.type = BACKLIGHT_RAW;
        bldev = backlight_device_register("taal", &dssdev->dev, dssdev,
                                          &taal_bl_ops, &props);
        if (IS_ERR(bldev)) {
 
        snprintf(name, sizeof(name), "rivabl%d", info->node);
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
        bd = backlight_device_register(name, info->dev, par, &riva_bl_ops,
                                       &props);
 
        BACKLIGHT_UPDATE_SYSFS,
 };
 
+enum backlight_type {
+       BACKLIGHT_RAW = 1,
+       BACKLIGHT_PLATFORM,
+       BACKLIGHT_FIRMWARE,
+       BACKLIGHT_TYPE_MAX,
+};
+
 struct backlight_device;
 struct fb_info;
 
        /* FB Blanking active? (values as for power) */
        /* Due to be removed, please use (state & BL_CORE_FBBLANK) */
        int fb_blank;
+       /* Backlight type */
+       enum backlight_type type;
        /* Flags used to signal drivers of state changes */
        /* Upper 4 bits are reserved for driver internal use */
        unsigned int state;