119119 * - v0.1 start from toshiba_acpi driver written by John Belmonte
120120 */
121121
122- #include <linux/kernel.h>
123- #include <linux/module.h>
124- #include <linux/init.h>
125- #include <linux/types.h>
122+ #include <linux/acpi.h>
126123#include <linux/backlight.h>
124+ #include <linux/bits.h>
127125#include <linux/ctype.h>
128- #include <linux/seq_file.h>
129- #include <linux/uaccess.h>
130- #include <linux/slab.h>
131- #include <linux/acpi.h>
126+ #include <linux/i8042.h>
127+ #include <linux/init.h>
132128#include <linux/input.h>
133129#include <linux/input/sparse-keymap.h>
130+ #include <linux/kernel.h>
131+ #include <linux/module.h>
134132#include <linux/platform_device.h>
135-
133+ #include <linux/seq_file.h>
134+ #include <linux/serio.h>
135+ #include <linux/slab.h>
136+ #include <linux/types.h>
137+ #include <linux/uaccess.h>
138+ #include <acpi/video.h>
136139
137140MODULE_AUTHOR ("Hiroshi Miura <miura@da-cha.org>" );
138141MODULE_AUTHOR ("David Bronaugh <dbronaugh@linuxboxen.org>" );
@@ -222,6 +225,17 @@ static const struct key_entry panasonic_keymap[] = {
222225 { KE_KEY , 8 , { KEY_PROG1 } }, /* Change CPU boost */
223226 { KE_KEY , 9 , { KEY_BATTERY } },
224227 { KE_KEY , 10 , { KEY_SUSPEND } },
228+ { KE_KEY , 21 , { KEY_MACRO1 } },
229+ { KE_KEY , 22 , { KEY_MACRO2 } },
230+ { KE_KEY , 24 , { KEY_MACRO3 } },
231+ { KE_KEY , 25 , { KEY_MACRO4 } },
232+ { KE_KEY , 34 , { KEY_MACRO5 } },
233+ { KE_KEY , 35 , { KEY_MACRO6 } },
234+ { KE_KEY , 36 , { KEY_MACRO7 } },
235+ { KE_KEY , 37 , { KEY_MACRO8 } },
236+ { KE_KEY , 41 , { KEY_MACRO9 } },
237+ { KE_KEY , 42 , { KEY_MACRO10 } },
238+ { KE_KEY , 43 , { KEY_MACRO11 } },
225239 { KE_END , 0 }
226240};
227241
@@ -241,6 +255,42 @@ struct pcc_acpi {
241255 struct platform_device * platform ;
242256};
243257
258+ /*
259+ * On some Panasonic models the volume up / down / mute keys send duplicate
260+ * keypress events over the PS/2 kbd interface, filter these out.
261+ */
262+ static bool panasonic_i8042_filter (unsigned char data , unsigned char str ,
263+ struct serio * port )
264+ {
265+ static bool extended ;
266+
267+ if (str & I8042_STR_AUXDATA )
268+ return false;
269+
270+ if (data == 0xe0 ) {
271+ extended = true;
272+ return true;
273+ } else if (extended ) {
274+ extended = false;
275+
276+ switch (data & 0x7f ) {
277+ case 0x20 : /* e0 20 / e0 a0, Volume Mute press / release */
278+ case 0x2e : /* e0 2e / e0 ae, Volume Down press / release */
279+ case 0x30 : /* e0 30 / e0 b0, Volume Up press / release */
280+ return true;
281+ default :
282+ /*
283+ * Report the previously filtered e0 before continuing
284+ * with the next non-filtered byte.
285+ */
286+ serio_interrupt (port , 0xe0 , 0 );
287+ return false;
288+ }
289+ }
290+
291+ return false;
292+ }
293+
244294/* method access functions */
245295static int acpi_pcc_write_sset (struct pcc_acpi * pcc , int func , int val )
246296{
@@ -299,7 +349,8 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc)
299349 }
300350
301351 if (pcc -> num_sifr < hkey -> package .count ) {
302- pr_err ("SQTY reports bad SINF length\n" );
352+ pr_err ("SQTY reports bad SINF length SQTY: %lu SINF-pkg-count: %u\n" ,
353+ pcc -> num_sifr , hkey -> package .count );
303354 status = AE_ERROR ;
304355 goto end ;
305356 }
@@ -470,7 +521,7 @@ static ssize_t numbatt_show(struct device *dev, struct device_attribute *attr,
470521 if (!acpi_pcc_retrieve_biosdata (pcc ))
471522 return - EIO ;
472523
473- return snprintf (buf , PAGE_SIZE , "%u\n" , pcc -> sinf [SINF_NUM_BATTERIES ]);
524+ return sysfs_emit (buf , "%u\n" , pcc -> sinf [SINF_NUM_BATTERIES ]);
474525}
475526
476527static ssize_t lcdtype_show (struct device * dev , struct device_attribute * attr ,
@@ -482,7 +533,7 @@ static ssize_t lcdtype_show(struct device *dev, struct device_attribute *attr,
482533 if (!acpi_pcc_retrieve_biosdata (pcc ))
483534 return - EIO ;
484535
485- return snprintf (buf , PAGE_SIZE , "%u\n" , pcc -> sinf [SINF_LCD_TYPE ]);
536+ return sysfs_emit (buf , "%u\n" , pcc -> sinf [SINF_LCD_TYPE ]);
486537}
487538
488539static ssize_t mute_show (struct device * dev , struct device_attribute * attr ,
@@ -494,7 +545,7 @@ static ssize_t mute_show(struct device *dev, struct device_attribute *attr,
494545 if (!acpi_pcc_retrieve_biosdata (pcc ))
495546 return - EIO ;
496547
497- return snprintf (buf , PAGE_SIZE , "%u\n" , pcc -> sinf [SINF_MUTE ]);
548+ return sysfs_emit (buf , "%u\n" , pcc -> sinf [SINF_MUTE ]);
498549}
499550
500551static ssize_t mute_store (struct device * dev , struct device_attribute * attr ,
@@ -524,7 +575,7 @@ static ssize_t sticky_key_show(struct device *dev, struct device_attribute *attr
524575 if (!acpi_pcc_retrieve_biosdata (pcc ))
525576 return - EIO ;
526577
527- return snprintf (buf , PAGE_SIZE , "%u\n" , pcc -> sticky_key );
578+ return sysfs_emit (buf , "%u\n" , pcc -> sticky_key );
528579}
529580
530581static ssize_t sticky_key_store (struct device * dev , struct device_attribute * attr ,
@@ -566,7 +617,7 @@ static ssize_t eco_mode_show(struct device *dev, struct device_attribute *attr,
566617 result = - EIO ;
567618 break ;
568619 }
569- return snprintf (buf , PAGE_SIZE , "%u\n" , result );
620+ return sysfs_emit (buf , "%u\n" , result );
570621}
571622
572623static ssize_t eco_mode_store (struct device * dev , struct device_attribute * attr ,
@@ -625,7 +676,7 @@ static ssize_t ac_brightness_show(struct device *dev, struct device_attribute *a
625676 if (!acpi_pcc_retrieve_biosdata (pcc ))
626677 return - EIO ;
627678
628- return snprintf (buf , PAGE_SIZE , "%u\n" , pcc -> sinf [SINF_AC_CUR_BRIGHT ]);
679+ return sysfs_emit (buf , "%u\n" , pcc -> sinf [SINF_AC_CUR_BRIGHT ]);
629680}
630681
631682static ssize_t ac_brightness_store (struct device * dev , struct device_attribute * attr ,
@@ -655,7 +706,7 @@ static ssize_t dc_brightness_show(struct device *dev, struct device_attribute *a
655706 if (!acpi_pcc_retrieve_biosdata (pcc ))
656707 return - EIO ;
657708
658- return snprintf (buf , PAGE_SIZE , "%u\n" , pcc -> sinf [SINF_DC_CUR_BRIGHT ]);
709+ return sysfs_emit (buf , "%u\n" , pcc -> sinf [SINF_DC_CUR_BRIGHT ]);
659710}
660711
661712static ssize_t dc_brightness_store (struct device * dev , struct device_attribute * attr ,
@@ -685,7 +736,7 @@ static ssize_t current_brightness_show(struct device *dev, struct device_attribu
685736 if (!acpi_pcc_retrieve_biosdata (pcc ))
686737 return - EIO ;
687738
688- return snprintf (buf , PAGE_SIZE , "%u\n" , pcc -> sinf [SINF_CUR_BRIGHT ]);
739+ return sysfs_emit (buf , "%u\n" , pcc -> sinf [SINF_CUR_BRIGHT ]);
689740}
690741
691742static ssize_t current_brightness_store (struct device * dev , struct device_attribute * attr ,
@@ -710,7 +761,7 @@ static ssize_t current_brightness_store(struct device *dev, struct device_attrib
710761static ssize_t cdpower_show (struct device * dev , struct device_attribute * attr ,
711762 char * buf )
712763{
713- return snprintf (buf , PAGE_SIZE , "%d\n" , get_optd_power_state ());
764+ return sysfs_emit (buf , "%d\n" , get_optd_power_state ());
714765}
715766
716767static ssize_t cdpower_store (struct device * dev , struct device_attribute * attr ,
@@ -735,6 +786,24 @@ static DEVICE_ATTR_RW(dc_brightness);
735786static DEVICE_ATTR_RW (current_brightness );
736787static DEVICE_ATTR_RW (cdpower );
737788
789+ static umode_t pcc_sysfs_is_visible (struct kobject * kobj , struct attribute * attr , int idx )
790+ {
791+ struct device * dev = kobj_to_dev (kobj );
792+ struct acpi_device * acpi = to_acpi_device (dev );
793+ struct pcc_acpi * pcc = acpi_driver_data (acpi );
794+
795+ if (attr == & dev_attr_mute .attr )
796+ return (pcc -> num_sifr > SINF_MUTE ) ? attr -> mode : 0 ;
797+
798+ if (attr == & dev_attr_eco_mode .attr )
799+ return (pcc -> num_sifr > SINF_ECO_MODE ) ? attr -> mode : 0 ;
800+
801+ if (attr == & dev_attr_current_brightness .attr )
802+ return (pcc -> num_sifr > SINF_CUR_BRIGHT ) ? attr -> mode : 0 ;
803+
804+ return attr -> mode ;
805+ }
806+
738807static struct attribute * pcc_sysfs_entries [] = {
739808 & dev_attr_numbatt .attr ,
740809 & dev_attr_lcdtype .attr ,
@@ -749,8 +818,9 @@ static struct attribute *pcc_sysfs_entries[] = {
749818};
750819
751820static const struct attribute_group pcc_attr_group = {
752- .name = NULL , /* put in device directory */
753- .attrs = pcc_sysfs_entries ,
821+ .name = NULL , /* put in device directory */
822+ .attrs = pcc_sysfs_entries ,
823+ .is_visible = pcc_sysfs_is_visible ,
754824};
755825
756826
@@ -762,6 +832,8 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
762832 struct input_dev * hotk_input_dev = pcc -> input_dev ;
763833 int rc ;
764834 unsigned long long result ;
835+ unsigned int key ;
836+ unsigned int updown ;
765837
766838 rc = acpi_evaluate_integer (pcc -> handle , METHOD_HKEY_QUERY ,
767839 NULL , & result );
@@ -770,20 +842,27 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
770842 return ;
771843 }
772844
845+ key = result & GENMASK (6 , 0 );
846+ updown = result & BIT (7 ); /* 0x80 == key down; 0x00 = key up */
847+
773848 /* hack: some firmware sends no key down for sleep / hibernate */
774- if (( result & 0xf ) == 0x7 || ( result & 0xf ) == 0xa ) {
775- if (result & 0x80 )
849+ if (key == 7 || key == 10 ) {
850+ if (updown )
776851 sleep_keydown_seen = 1 ;
777852 if (!sleep_keydown_seen )
778853 sparse_keymap_report_event (hotk_input_dev ,
779- result & 0xf , 0x80 , false);
854+ key , 0x80 , false);
780855 }
781856
782- if ((result & 0xf ) == 0x7 || (result & 0xf ) == 0x9 || (result & 0xf ) == 0xa ) {
783- if (!sparse_keymap_report_event (hotk_input_dev ,
784- result & 0xf , result & 0x80 , false))
785- pr_err ("Unknown hotkey event: 0x%04llx\n" , result );
786- }
857+ /*
858+ * Don't report brightness key-presses if they are also reported
859+ * by the ACPI video bus.
860+ */
861+ if ((key == 1 || key == 2 ) && acpi_video_handles_brightness_key_presses ())
862+ return ;
863+
864+ if (!sparse_keymap_report_event (hotk_input_dev , key , updown , false))
865+ pr_err ("Unknown hotkey event: 0x%04llx\n" , result );
787866}
788867
789868static void acpi_pcc_hotkey_notify (struct acpi_device * device , u32 event )
@@ -894,12 +973,15 @@ static int acpi_pcc_hotkey_resume(struct device *dev)
894973 if (!pcc )
895974 return - EINVAL ;
896975
897- acpi_pcc_write_sset (pcc , SINF_MUTE , pcc -> mute );
898- acpi_pcc_write_sset (pcc , SINF_ECO_MODE , pcc -> eco_mode );
976+ if (pcc -> num_sifr > SINF_MUTE )
977+ acpi_pcc_write_sset (pcc , SINF_MUTE , pcc -> mute );
978+ if (pcc -> num_sifr > SINF_ECO_MODE )
979+ acpi_pcc_write_sset (pcc , SINF_ECO_MODE , pcc -> eco_mode );
899980 acpi_pcc_write_sset (pcc , SINF_STICKY_KEY , pcc -> sticky_key );
900981 acpi_pcc_write_sset (pcc , SINF_AC_CUR_BRIGHT , pcc -> ac_brightness );
901982 acpi_pcc_write_sset (pcc , SINF_DC_CUR_BRIGHT , pcc -> dc_brightness );
902- acpi_pcc_write_sset (pcc , SINF_CUR_BRIGHT , pcc -> current_brightness );
983+ if (pcc -> num_sifr > SINF_CUR_BRIGHT )
984+ acpi_pcc_write_sset (pcc , SINF_CUR_BRIGHT , pcc -> current_brightness );
903985
904986 return 0 ;
905987}
@@ -916,11 +998,21 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
916998
917999 num_sifr = acpi_pcc_get_sqty (device );
9181000
919- if (num_sifr < 0 || num_sifr > 255 ) {
920- pr_err ("num_sifr out of range" );
1001+ /*
1002+ * pcc->sinf is expected to at least have the AC+DC brightness entries.
1003+ * Accesses to higher SINF entries are checked against num_sifr.
1004+ */
1005+ if (num_sifr <= SINF_DC_CUR_BRIGHT || num_sifr > 255 ) {
1006+ pr_err ("num_sifr %d out of range %d - 255\n" , num_sifr , SINF_DC_CUR_BRIGHT + 1 );
9211007 return - ENODEV ;
9221008 }
9231009
1010+ /*
1011+ * Some DSDT-s have an off-by-one bug where the SINF package count is
1012+ * one higher than the SQTY reported value, allocate 1 entry extra.
1013+ */
1014+ num_sifr ++ ;
1015+
9241016 pcc = kzalloc (sizeof (struct pcc_acpi ), GFP_KERNEL );
9251017 if (!pcc ) {
9261018 pr_err ("Couldn't allocate mem for pcc" );
@@ -951,29 +1043,36 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
9511043 pr_err ("Couldn't retrieve BIOS data\n" );
9521044 goto out_input ;
9531045 }
954- /* initialize backlight */
955- memset (& props , 0 , sizeof (struct backlight_properties ));
956- props .type = BACKLIGHT_PLATFORM ;
957- props .max_brightness = pcc -> sinf [SINF_AC_MAX_BRIGHT ];
958- pcc -> backlight = backlight_device_register ("panasonic" , NULL , pcc ,
959- & pcc_backlight_ops , & props );
960- if (IS_ERR (pcc -> backlight )) {
961- result = PTR_ERR (pcc -> backlight );
962- goto out_input ;
963- }
9641046
965- /* read the initial brightness setting from the hardware */
966- pcc -> backlight -> props .brightness = pcc -> sinf [SINF_AC_CUR_BRIGHT ];
1047+ if (acpi_video_get_backlight_type () == acpi_backlight_vendor ) {
1048+ /* initialize backlight */
1049+ memset (& props , 0 , sizeof (struct backlight_properties ));
1050+ props .type = BACKLIGHT_PLATFORM ;
1051+ props .max_brightness = pcc -> sinf [SINF_AC_MAX_BRIGHT ];
1052+
1053+ pcc -> backlight = backlight_device_register ("panasonic" , NULL , pcc ,
1054+ & pcc_backlight_ops , & props );
1055+ if (IS_ERR (pcc -> backlight )) {
1056+ result = PTR_ERR (pcc -> backlight );
1057+ goto out_input ;
1058+ }
1059+
1060+ /* read the initial brightness setting from the hardware */
1061+ pcc -> backlight -> props .brightness = pcc -> sinf [SINF_AC_CUR_BRIGHT ];
1062+ }
9671063
9681064 /* Reset initial sticky key mode since the hardware register state is not consistent */
9691065 acpi_pcc_write_sset (pcc , SINF_STICKY_KEY , 0 );
9701066 pcc -> sticky_key = 0 ;
9711067
972- pcc -> eco_mode = pcc -> sinf [SINF_ECO_MODE ];
973- pcc -> mute = pcc -> sinf [SINF_MUTE ];
9741068 pcc -> ac_brightness = pcc -> sinf [SINF_AC_CUR_BRIGHT ];
9751069 pcc -> dc_brightness = pcc -> sinf [SINF_DC_CUR_BRIGHT ];
976- pcc -> current_brightness = pcc -> sinf [SINF_CUR_BRIGHT ];
1070+ if (pcc -> num_sifr > SINF_MUTE )
1071+ pcc -> mute = pcc -> sinf [SINF_MUTE ];
1072+ if (pcc -> num_sifr > SINF_ECO_MODE )
1073+ pcc -> eco_mode = pcc -> sinf [SINF_ECO_MODE ];
1074+ if (pcc -> num_sifr > SINF_CUR_BRIGHT )
1075+ pcc -> current_brightness = pcc -> sinf [SINF_CUR_BRIGHT ];
9771076
9781077 /* add sysfs attributes */
9791078 result = sysfs_create_group (& device -> dev .kobj , & pcc_attr_group );
@@ -983,7 +1082,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
9831082 /* optical drive initialization */
9841083 if (ACPI_SUCCESS (check_optd_present ())) {
9851084 pcc -> platform = platform_device_register_simple ("panasonic" ,
986- -1 , NULL , 0 );
1085+ PLATFORM_DEVID_NONE , NULL , 0 );
9871086 if (IS_ERR (pcc -> platform )) {
9881087 result = PTR_ERR (pcc -> platform );
9891088 goto out_backlight ;
@@ -997,6 +1096,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
9971096 pcc -> platform = NULL ;
9981097 }
9991098
1099+ i8042_install_filter (panasonic_i8042_filter );
10001100 return 0 ;
10011101
10021102out_platform :
@@ -1020,6 +1120,8 @@ static void acpi_pcc_hotkey_remove(struct acpi_device *device)
10201120 if (!device || !pcc )
10211121 return ;
10221122
1123+ i8042_remove_filter (panasonic_i8042_filter );
1124+
10231125 if (pcc -> platform ) {
10241126 device_remove_file (& pcc -> platform -> dev , & dev_attr_cdpower );
10251127 platform_device_unregister (pcc -> platform );
0 commit comments