0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/kernel.h>
0010 #include <linux/init.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/backlight.h>
0013 #include <linux/dmi.h>
0014 #include <linux/acpi.h>
0015
0016 #define SAMSUNGQ10_BL_MAX_INTENSITY 7
0017
0018 static acpi_handle ec_handle;
0019
0020 static bool force;
0021 module_param(force, bool, 0);
0022 MODULE_PARM_DESC(force,
0023 "Disable the DMI check and force the driver to be loaded");
0024
0025 static int samsungq10_bl_set_intensity(struct backlight_device *bd)
0026 {
0027
0028 acpi_status status;
0029 int i;
0030
0031 for (i = 0; i < SAMSUNGQ10_BL_MAX_INTENSITY; i++) {
0032 status = acpi_evaluate_object(ec_handle, "_Q63", NULL, NULL);
0033 if (ACPI_FAILURE(status))
0034 return -EIO;
0035 }
0036 for (i = 0; i < bd->props.brightness; i++) {
0037 status = acpi_evaluate_object(ec_handle, "_Q64", NULL, NULL);
0038 if (ACPI_FAILURE(status))
0039 return -EIO;
0040 }
0041
0042 return 0;
0043 }
0044
0045 static const struct backlight_ops samsungq10_bl_ops = {
0046 .update_status = samsungq10_bl_set_intensity,
0047 };
0048
0049 static int samsungq10_probe(struct platform_device *pdev)
0050 {
0051
0052 struct backlight_properties props;
0053 struct backlight_device *bd;
0054
0055 memset(&props, 0, sizeof(struct backlight_properties));
0056 props.type = BACKLIGHT_PLATFORM;
0057 props.max_brightness = SAMSUNGQ10_BL_MAX_INTENSITY;
0058 bd = backlight_device_register("samsung", &pdev->dev, NULL,
0059 &samsungq10_bl_ops, &props);
0060 if (IS_ERR(bd))
0061 return PTR_ERR(bd);
0062
0063 platform_set_drvdata(pdev, bd);
0064
0065 return 0;
0066 }
0067
0068 static int samsungq10_remove(struct platform_device *pdev)
0069 {
0070
0071 struct backlight_device *bd = platform_get_drvdata(pdev);
0072
0073 backlight_device_unregister(bd);
0074
0075 return 0;
0076 }
0077
0078 static struct platform_driver samsungq10_driver = {
0079 .driver = {
0080 .name = KBUILD_MODNAME,
0081 },
0082 .probe = samsungq10_probe,
0083 .remove = samsungq10_remove,
0084 };
0085
0086 static struct platform_device *samsungq10_device;
0087
0088 static int __init dmi_check_callback(const struct dmi_system_id *id)
0089 {
0090 printk(KERN_INFO KBUILD_MODNAME ": found model '%s'\n", id->ident);
0091 return 1;
0092 }
0093
0094 static const struct dmi_system_id samsungq10_dmi_table[] __initconst = {
0095 {
0096 .ident = "Samsung Q10",
0097 .matches = {
0098 DMI_MATCH(DMI_SYS_VENDOR, "Samsung"),
0099 DMI_MATCH(DMI_PRODUCT_NAME, "SQ10"),
0100 },
0101 .callback = dmi_check_callback,
0102 },
0103 {
0104 .ident = "Samsung Q20",
0105 .matches = {
0106 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
0107 DMI_MATCH(DMI_PRODUCT_NAME, "SENS Q20"),
0108 },
0109 .callback = dmi_check_callback,
0110 },
0111 {
0112 .ident = "Samsung Q25",
0113 .matches = {
0114 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
0115 DMI_MATCH(DMI_PRODUCT_NAME, "NQ25"),
0116 },
0117 .callback = dmi_check_callback,
0118 },
0119 {
0120 .ident = "Dell Latitude X200",
0121 .matches = {
0122 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
0123 DMI_MATCH(DMI_PRODUCT_NAME, "X200"),
0124 },
0125 .callback = dmi_check_callback,
0126 },
0127 { },
0128 };
0129 MODULE_DEVICE_TABLE(dmi, samsungq10_dmi_table);
0130
0131 static int __init samsungq10_init(void)
0132 {
0133 if (!force && !dmi_check_system(samsungq10_dmi_table))
0134 return -ENODEV;
0135
0136 ec_handle = ec_get_handle();
0137
0138 if (!ec_handle)
0139 return -ENODEV;
0140
0141 samsungq10_device = platform_create_bundle(&samsungq10_driver,
0142 samsungq10_probe,
0143 NULL, 0, NULL, 0);
0144
0145 return PTR_ERR_OR_ZERO(samsungq10_device);
0146 }
0147
0148 static void __exit samsungq10_exit(void)
0149 {
0150 platform_device_unregister(samsungq10_device);
0151 platform_driver_unregister(&samsungq10_driver);
0152 }
0153
0154 module_init(samsungq10_init);
0155 module_exit(samsungq10_exit);
0156
0157 MODULE_AUTHOR("Frederick van der Wyck <fvanderwyck@gmail.com>");
0158 MODULE_DESCRIPTION("Samsung Q10 Driver");
0159 MODULE_LICENSE("GPL");