View | Details | Raw Unified | Return to bug 41652
Collapse All | Expand All

(-)file_not_specified_in_diff (-595 / +3320 lines)
Line  Link Here
0
-- a/drivers/acpi/video_detect.c
0
++ b/drivers/acpi/video_detect.c
Lines 45-50 ACPI_MODULE_NAME("video"); Link Here
45
static long acpi_video_support;
45
static long acpi_video_support;
46
static bool acpi_video_caps_checked;
46
static bool acpi_video_caps_checked;
47
47
48
static const struct dmi_system_id vendor_dmi_table[] = {
49
	{
50
		.ident = "Sony Vaio S1",
51
		.matches = {
52
				DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
53
				DMI_MATCH(DMI_PRODUCT_NAME, "VPCS1"),
54
		},
55
	},
56
	{
57
		.ident = "Sony Vaio TT",
58
		.matches = {
59
				DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
60
				DMI_MATCH(DMI_PRODUCT_NAME, "VGN-TT"),
61
		},
62
	},
63
	{ }
64
};
65
48
static acpi_status
66
static acpi_status
49
acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
67
acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
50
			  void **retyurn_value)
68
			  void **retyurn_value)
Lines 163-168 long acpi_video_get_capabilities(acpi_ha Link Here
163
		 *		ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
181
		 *		ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
164
		 *}
182
		 *}
165
		 */
183
		 */
184
		if (dmi_check_system(vendor_dmi_table))
185
			acpi_video_support |= ACPI_VIDEO_BACKLIGHT_DMI_VENDOR;
186
166
	} else {
187
	} else {
167
		status = acpi_bus_get_device(graphics_handle, &tmp_dev);
188
		status = acpi_bus_get_device(graphics_handle, &tmp_dev);
168
		if (ACPI_FAILURE(status)) {
189
		if (ACPI_FAILURE(status)) {
169
190
170
-- a/drivers/platform/x86/sony-laptop.c
191
++ b/drivers/platform/x86/sony-laptop.c
Lines 3-8 Link Here
3
 *
3
 *
4
 * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
4
 * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
5
 * Copyright (C) 2007-2009 Mattia Dongili <malattia@linux.it>
5
 * Copyright (C) 2007-2009 Mattia Dongili <malattia@linux.it>
6
 * Copyright (C) 2011 Marco Chiappero <marco@absence.it>
7
 * Copyright (C) 2011 Javier Achirica <jachirica@gmail.com>
6
 *
8
 *
7
 * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
9
 * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
8
 * which are copyrighted by their respective authors.
10
 * which are copyrighted by their respective authors.
Lines 63-69 Link Here
63
#include <linux/slab.h>
65
#include <linux/slab.h>
64
#include <acpi/acpi_drivers.h>
66
#include <acpi/acpi_drivers.h>
65
#include <acpi/acpi_bus.h>
67
#include <acpi/acpi_bus.h>
66
#include <asm/uaccess.h>
68
#include <linux/uaccess.h>
67
#include <linux/sonypi.h>
69
#include <linux/sonypi.h>
68
#include <linux/sony-laptop.h>
70
#include <linux/sony-laptop.h>
69
#include <linux/rfkill.h>
71
#include <linux/rfkill.h>
Lines 127-133 MODULE_PARM_DESC(minor, Link Here
127
		 "default is -1 (automatic)");
129
		 "default is -1 (automatic)");
128
#endif
130
#endif
129
131
130
static int kbd_backlight;	/* = 1 */
132
static int kbd_backlight;	/* = 0 */
131
module_param(kbd_backlight, int, 0444);
133
module_param(kbd_backlight, int, 0444);
132
MODULE_PARM_DESC(kbd_backlight,
134
MODULE_PARM_DESC(kbd_backlight,
133
		 "set this to 0 to disable keyboard backlight, "
135
		 "set this to 0 to disable keyboard backlight, "
Lines 140-159 MODULE_PARM_DESC(kbd_backlight_timeout, Link Here
140
		 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
142
		 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
141
		 "(default: 0)");
143
		 "(default: 0)");
142
144
143
static void sony_nc_kbd_backlight_resume(void);
145
static int force_shock_notifications;	/* = 0 */
146
module_param(force_shock_notifications, int, 0);
147
MODULE_PARM_DESC(force_shock_notifications,
148
		"set this to 1 to force the generation of shock protection "
149
		"events, even though the notebook do not support head "
150
		"unloading for the installed drive drive");
144
151
145
enum sony_nc_rfkill {
146
	SONY_WIFI,
147
	SONY_BLUETOOTH,
148
	SONY_WWAN,
149
	SONY_WIMAX,
150
	N_SONY_RFKILL,
151
};
152
153
static int sony_rfkill_handle;
154
static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
155
static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
156
static void sony_nc_rfkill_update(void);
157
152
158
/*********** Input Devices ***********/
153
/*********** Input Devices ***********/
159
154
Lines 253-259 static int sony_laptop_input_index[] = { Link Here
253
	57,	/* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
248
	57,	/* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
254
	-1,	/* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
249
	-1,	/* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
255
	58,	/* 72 SONYPI_EVENT_MEDIA_PRESSED */
250
	58,	/* 72 SONYPI_EVENT_MEDIA_PRESSED */
256
	59,	/* 72 SONYPI_EVENT_VENDOR_PRESSED */
251
	59,	/* 73 SONYPI_EVENT_VENDOR_PRESSED */
257
};
252
};
258
253
259
static int sony_laptop_input_keycode_map[] = {
254
static int sony_laptop_input_keycode_map[] = {
Lines 377-383 static void sony_laptop_report_input_eve Link Here
377
372
378
	default:
373
	default:
379
		if (event >= ARRAY_SIZE(sony_laptop_input_index)) {
374
		if (event >= ARRAY_SIZE(sony_laptop_input_index)) {
380
			dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
375
			dprintk("sony_laptop_report_input_event, "
376
				"event not known: %d\n", event);
381
			break;
377
			break;
382
		}
378
		}
383
		if (sony_laptop_input_index[event] != -1) {
379
		if (sony_laptop_input_index[event] != -1) {
Lines 565-576 static int sony_pf_add(void) Link Here
565
561
566
	return 0;
562
	return 0;
567
563
568
      out_platform_alloced:
564
out_platform_alloced:
569
	platform_device_put(sony_pf_device);
565
	platform_device_put(sony_pf_device);
570
	sony_pf_device = NULL;
566
	sony_pf_device = NULL;
571
      out_platform_registered:
567
out_platform_registered:
572
	platform_driver_unregister(&sony_pf_driver);
568
	platform_driver_unregister(&sony_pf_driver);
573
      out:
569
out:
574
	atomic_dec(&sony_pf_users);
570
	atomic_dec(&sony_pf_users);
575
	return ret;
571
	return ret;
576
}
572
}
Lines 664-670 static struct sony_nc_value sony_nc_valu Link Here
664
	SNC_HANDLE(brightness_default, snc_brightness_def_get,
660
	SNC_HANDLE(brightness_default, snc_brightness_def_get,
665
			snc_brightness_def_set, brightness_default_validate, 0),
661
			snc_brightness_def_set, brightness_default_validate, 0),
666
	SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0),
662
	SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0),
667
	SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
663
	SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set,
664
			boolean_validate, 0),
668
	SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set,
665
	SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set,
669
			boolean_validate, 0),
666
			boolean_validate, 0),
670
	SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
667
	SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
Lines 684-695 static struct sony_nc_value sony_nc_valu Link Here
684
};
681
};
685
682
686
static acpi_handle sony_nc_acpi_handle;
683
static acpi_handle sony_nc_acpi_handle;
687
static struct acpi_device *sony_nc_acpi_device = NULL;
684
static struct acpi_device *sony_nc_acpi_device;
688
685
689
/*
686
/*
690
 * acpi_evaluate_object wrappers
687
 * acpi_evaluate_object wrappers
691
 */
688
 */
692
static int acpi_callgetfunc(acpi_handle handle, char *name, int *result)
689
static int acpi_callgetfunc(acpi_handle handle, char *name,
690
				unsigned int *result)
693
{
691
{
694
	struct acpi_buffer output;
692
	struct acpi_buffer output;
695
	union acpi_object out_obj;
693
	union acpi_object out_obj;
Lines 709-716 static int acpi_callgetfunc(acpi_handle Link Here
709
	return -1;
707
	return -1;
710
}
708
}
711
709
712
static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
710
static int acpi_callsetfunc(acpi_handle handle, char *name, u32 value,
713
			    int *result)
711
				unsigned int *result)
714
{
712
{
715
	struct acpi_object_list params;
713
	struct acpi_object_list params;
716
	union acpi_object in_obj;
714
	union acpi_object in_obj;
Lines 730-736 static int acpi_callsetfunc(acpi_handle Link Here
730
	if (status == AE_OK) {
728
	if (status == AE_OK) {
731
		if (result != NULL) {
729
		if (result != NULL) {
732
			if (out_obj.type != ACPI_TYPE_INTEGER) {
730
			if (out_obj.type != ACPI_TYPE_INTEGER) {
733
				pr_warn("acpi_evaluate_object bad return type\n");
731
				pr_warn("acpi_evaluate_object bad "
732
					"return type\n");
734
				return -1;
733
				return -1;
735
			}
734
			}
736
			*result = out_obj.integer.value;
735
			*result = out_obj.integer.value;
Lines 743-748 static int acpi_callsetfunc(acpi_handle Link Here
743
	return -1;
742
	return -1;
744
}
743
}
745
744
745
static int acpi_callsetfunc_buffer(acpi_handle handle, u64 value,
746
					u8 array[], unsigned int size)
747
{
748
	u8 buffer[sizeof(value)];
749
	int length = -1;
750
	struct acpi_object_list params;
751
	union acpi_object in_obj;
752
	union acpi_object *values;
753
	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
754
	acpi_status status;
755
756
	if (!array || !size)
757
		return length;
758
759
	/* use a buffer type as parameter to overcome any 32 bits ACPI limit */
760
	memcpy(buffer, &value, sizeof(buffer));
761
762
	params.count = 1;
763
	params.pointer = &in_obj;
764
	in_obj.type = ACPI_TYPE_BUFFER;
765
	in_obj.buffer.length = sizeof(buffer);
766
	in_obj.buffer.pointer = buffer;
767
768
	/* since SN06 is the only known method returning a buffer we
769
	 * can hard code it, it is not necessary to have a parameter
770
	 */
771
	status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
772
			&output);
773
	values = (union acpi_object *) output.pointer;
774
	if (ACPI_FAILURE(status) || !values) {
775
		dprintk("acpi_evaluate_object failed\n");
776
		goto error;
777
	}
778
779
	/* some buggy DSDTs return integer when the output does
780
	   not execede the 4 bytes size
781
	*/
782
	if (values->type == ACPI_TYPE_BUFFER) {
783
		if (values->buffer.length <= 0)
784
			goto error;
785
786
		length = size > values->buffer.length ?
787
			values->buffer.length : size;
788
789
		memcpy(array, values->buffer.pointer, length);
790
	} else if (values->type == ACPI_TYPE_INTEGER) {
791
		u32 result = values->integer.value;
792
		if (size < 4)
793
			goto error;
794
795
		length = 0;
796
		while (length != 4) {
797
			array[length] = result & 0xff;
798
			result >>= 8;
799
			length++;
800
		}
801
	} else {
802
		pr_err("Invalid return object 0x%.2x\n", values->type);
803
		goto error;
804
	}
805
806
error:
807
	kfree(output.pointer);
808
	return length;
809
}
810
746
struct sony_nc_handles {
811
struct sony_nc_handles {
747
	u16 cap[0x10];
812
	u16 cap[0x10];
748
	struct device_attribute devattr;
813
	struct device_attribute devattr;
Lines 767-774 static ssize_t sony_nc_handles_show(stru Link Here
767
832
768
static int sony_nc_handles_setup(struct platform_device *pd)
833
static int sony_nc_handles_setup(struct platform_device *pd)
769
{
834
{
770
	int i;
835
	unsigned int i, result;
771
	int result;
772
836
773
	handles = kzalloc(sizeof(*handles), GFP_KERNEL);
837
	handles = kzalloc(sizeof(*handles), GFP_KERNEL);
774
	if (!handles)
838
	if (!handles)
Lines 811-822 static int sony_nc_handles_cleanup(struc Link Here
811
	return 0;
875
	return 0;
812
}
876
}
813
877
814
static int sony_find_snc_handle(int handle)
878
static int sony_find_snc_handle(unsigned int handle)
815
{
879
{
816
	int i;
880
	int i;
817
881
818
	/* not initialized yet, return early */
882
	/* not initialized yet or invalid handle, return early */
819
	if (!handles)
883
	if (!handles || !handle)
820
		return -1;
884
		return -1;
821
885
822
	for (i = 0; i < 0x10; i++) {
886
	for (i = 0; i < 0x10; i++) {
Lines 830-836 static int sony_find_snc_handle(int hand Link Here
830
	return -1;
894
	return -1;
831
}
895
}
832
896
833
static int sony_call_snc_handle(int handle, int argument, int *result)
897
/* call command method SN07, accepts a 32 bit integer, returns a integer */
898
static int sony_call_snc_handle(unsigned int handle, unsigned int argument,
899
				unsigned int *result)
834
{
900
{
835
	int ret = 0;
901
	int ret = 0;
836
	int offset = sony_find_snc_handle(handle);
902
	int offset = sony_find_snc_handle(handle);
Lines 838-843 static int sony_call_snc_handle(int hand Link Here
838
	if (offset < 0)
904
	if (offset < 0)
839
		return -1;
905
		return -1;
840
906
907
	/* max 32 bit wide argument, for wider input use SN06 */
841
	ret = acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
908
	ret = acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
842
			result);
909
			result);
843
	dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", offset | argument,
910
	dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", offset | argument,
Lines 845-850 static int sony_call_snc_handle(int hand Link Here
845
	return ret;
912
	return ret;
846
}
913
}
847
914
915
/* call command method SN06, accepts a wide input buffer, returns a buffer */
916
static int sony_call_snc_handle_buffer(unsigned int handle, u64 argument,
917
					u8 result[], unsigned int size)
918
{
919
	int ret = 0;
920
	int offset = sony_find_snc_handle(handle);
921
922
	if (offset < 0)
923
		return -1;
924
925
	ret = acpi_callsetfunc_buffer(sony_nc_acpi_handle,
926
			offset | argument, result, size);
927
	dprintk("called SN06 with 0x%.4llx (%u bytes read)\n",
928
			offset | argument, ret);
929
930
	return ret;
931
}
932
848
/*
933
/*
849
 * sony_nc_values input/output validate functions
934
 * sony_nc_values input/output validate functions
850
 */
935
 */
Lines 857-867 static int sony_call_snc_handle(int hand Link Here
857
static int brightness_default_validate(const int direction, const int value)
942
static int brightness_default_validate(const int direction, const int value)
858
{
943
{
859
	switch (direction) {
944
	switch (direction) {
860
		case SNC_VALIDATE_OUT:
945
	case SNC_VALIDATE_OUT:
861
			return value - 1;
946
		return value - 1;
862
		case SNC_VALIDATE_IN:
947
	case SNC_VALIDATE_IN:
863
			if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
948
		if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
864
				return value + 1;
949
			return value + 1;
865
	}
950
	}
866
	return -EINVAL;
951
	return -EINVAL;
867
}
952
}
Lines 883-892 static int boolean_validate(const int di Link Here
883
/*
968
/*
884
 * Sysfs show/store common to all sony_nc_values
969
 * Sysfs show/store common to all sony_nc_values
885
 */
970
 */
886
static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr,
971
static ssize_t sony_nc_sysfs_show(struct device *dev,
887
			      char *buffer)
972
					struct device_attribute *attr,
973
					char *buffer)
888
{
974
{
889
	int value;
975
	unsigned int value;
890
	struct sony_nc_value *item =
976
	struct sony_nc_value *item =
891
	    container_of(attr, struct sony_nc_value, devattr);
977
	    container_of(attr, struct sony_nc_value, devattr);
892
978
Lines 906-912 static ssize_t sony_nc_sysfs_store(struc Link Here
906
			       struct device_attribute *attr,
992
			       struct device_attribute *attr,
907
			       const char *buffer, size_t count)
993
			       const char *buffer, size_t count)
908
{
994
{
909
	int value;
995
	unsigned long value;
910
	struct sony_nc_value *item =
996
	struct sony_nc_value *item =
911
	    container_of(attr, struct sony_nc_value, devattr);
997
	    container_of(attr, struct sony_nc_value, devattr);
912
998
Lines 916-922 static ssize_t sony_nc_sysfs_store(struc Link Here
916
	if (count > 31)
1002
	if (count > 31)
917
		return -EINVAL;
1003
		return -EINVAL;
918
1004
919
	value = simple_strtoul(buffer, NULL, 10);
1005
	if (strict_strtoul(buffer, 10, &value))
1006
		return -EINVAL;
920
1007
921
	if (item->validate)
1008
	if (item->validate)
922
		value = item->validate(SNC_VALIDATE_IN, value);
1009
		value = item->validate(SNC_VALIDATE_IN, value);
Lines 924-999 static ssize_t sony_nc_sysfs_store(struc Link Here
924
	if (value < 0)
1011
	if (value < 0)
925
		return value;
1012
		return value;
926
1013
927
	if (acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, value, NULL) < 0)
1014
	if (acpi_callsetfunc(sony_nc_acpi_handle,
1015
				*item->acpiset, value, NULL) < 0)
928
		return -EIO;
1016
		return -EIO;
929
	item->value = value;
1017
	item->value = value;
930
	item->valid = 1;
1018
	item->valid = 1;
931
	return count;
1019
	return count;
932
}
1020
}
933
1021
934
935
/*
936
 * Backlight device
937
 */
938
struct sony_backlight_props {
939
	struct backlight_device *dev;
940
	int			handle;
941
	u8			offset;
942
	u8			maxlvl;
943
};
944
struct sony_backlight_props sony_bl_props;
945
946
static int sony_backlight_update_status(struct backlight_device *bd)
947
{
948
	return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
949
				bd->props.brightness + 1, NULL);
950
}
951
952
static int sony_backlight_get_brightness(struct backlight_device *bd)
953
{
954
	int value;
955
956
	if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value))
957
		return 0;
958
	/* brightness levels are 1-based, while backlight ones are 0-based */
959
	return value - 1;
960
}
961
962
static int sony_nc_get_brightness_ng(struct backlight_device *bd)
963
{
964
	int result;
965
	struct sony_backlight_props *sdev =
966
		(struct sony_backlight_props *)bl_get_data(bd);
967
968
	sony_call_snc_handle(sdev->handle, 0x0200, &result);
969
970
	return (result & 0xff) - sdev->offset;
971
}
972
973
static int sony_nc_update_status_ng(struct backlight_device *bd)
974
{
975
	int value, result;
976
	struct sony_backlight_props *sdev =
977
		(struct sony_backlight_props *)bl_get_data(bd);
978
979
	value = bd->props.brightness + sdev->offset;
980
	if (sony_call_snc_handle(sdev->handle, 0x0100 | (value << 16), &result))
981
		return -EIO;
982
983
	return value;
984
}
985
986
static const struct backlight_ops sony_backlight_ops = {
987
	.options = BL_CORE_SUSPENDRESUME,
988
	.update_status = sony_backlight_update_status,
989
	.get_brightness = sony_backlight_get_brightness,
990
};
991
static const struct backlight_ops sony_backlight_ng_ops = {
992
	.options = BL_CORE_SUSPENDRESUME,
993
	.update_status = sony_nc_update_status_ng,
994
	.get_brightness = sony_nc_get_brightness_ng,
995
};
996
997
/*
1022
/*
998
 * New SNC-only Vaios event mapping to driver known keys
1023
 * New SNC-only Vaios event mapping to driver known keys
999
 */
1024
 */
Lines 1003-1012 struct sony_nc_event { Link Here
1003
};
1028
};
1004
1029
1005
static struct sony_nc_event sony_100_events[] = {
1030
static struct sony_nc_event sony_100_events[] = {
1006
	{ 0x90, SONYPI_EVENT_PKEY_P1 },
1007
	{ 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED },
1008
	{ 0x91, SONYPI_EVENT_PKEY_P2 },
1009
	{ 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED },
1010
	{ 0x81, SONYPI_EVENT_FNKEY_F1 },
1031
	{ 0x81, SONYPI_EVENT_FNKEY_F1 },
1011
	{ 0x01, SONYPI_EVENT_FNKEY_RELEASED },
1032
	{ 0x01, SONYPI_EVENT_FNKEY_RELEASED },
1012
	{ 0x82, SONYPI_EVENT_FNKEY_F2 },
1033
	{ 0x82, SONYPI_EVENT_FNKEY_F2 },
Lines 1021-1032 static struct sony_nc_event sony_100_eve Link Here
1021
	{ 0x06, SONYPI_EVENT_FNKEY_RELEASED },
1042
	{ 0x06, SONYPI_EVENT_FNKEY_RELEASED },
1022
	{ 0x87, SONYPI_EVENT_FNKEY_F7 },
1043
	{ 0x87, SONYPI_EVENT_FNKEY_F7 },
1023
	{ 0x07, SONYPI_EVENT_FNKEY_RELEASED },
1044
	{ 0x07, SONYPI_EVENT_FNKEY_RELEASED },
1045
	{ 0x88, SONYPI_EVENT_FNKEY_F8 },
1046
	{ 0x08, SONYPI_EVENT_FNKEY_RELEASED },
1024
	{ 0x89, SONYPI_EVENT_FNKEY_F9 },
1047
	{ 0x89, SONYPI_EVENT_FNKEY_F9 },
1025
	{ 0x09, SONYPI_EVENT_FNKEY_RELEASED },
1048
	{ 0x09, SONYPI_EVENT_FNKEY_RELEASED },
1026
	{ 0x8A, SONYPI_EVENT_FNKEY_F10 },
1049
	{ 0x8A, SONYPI_EVENT_FNKEY_F10 },
1027
	{ 0x0A, SONYPI_EVENT_FNKEY_RELEASED },
1050
	{ 0x0A, SONYPI_EVENT_FNKEY_RELEASED },
1051
	{ 0x8B, SONYPI_EVENT_FNKEY_F11 },
1052
	{ 0x0B, SONYPI_EVENT_FNKEY_RELEASED },
1028
	{ 0x8C, SONYPI_EVENT_FNKEY_F12 },
1053
	{ 0x8C, SONYPI_EVENT_FNKEY_F12 },
1029
	{ 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
1054
	{ 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
1055
	{ 0x90, SONYPI_EVENT_PKEY_P1 },
1056
	{ 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED },
1057
	{ 0x91, SONYPI_EVENT_PKEY_P2 },
1058
	{ 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED },
1030
	{ 0x9d, SONYPI_EVENT_ZOOM_PRESSED },
1059
	{ 0x9d, SONYPI_EVENT_ZOOM_PRESSED },
1031
	{ 0x1d, SONYPI_EVENT_ANYBUTTON_RELEASED },
1060
	{ 0x1d, SONYPI_EVENT_ANYBUTTON_RELEASED },
1032
	{ 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
1061
	{ 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
Lines 1061-1218 static struct sony_nc_event sony_127_eve Link Here
1061
};
1090
};
1062
1091
1063
/*
1092
/*
1064
 * ACPI callbacks
1093
 * ACPI device
1065
 */
1094
 */
1066
static void sony_nc_notify(struct acpi_device *device, u32 event)
1095
static int sony_nc_function_setup(unsigned int handle)
1067
{
1096
{
1068
	u32 ev = event;
1097
	unsigned int result;
1069
1070
	if (ev >= 0x90) {
1071
		/* New-style event */
1072
		int result;
1073
		int key_handle = 0;
1074
		ev -= 0x90;
1075
1076
		if (sony_find_snc_handle(0x100) == ev)
1077
			key_handle = 0x100;
1078
		if (sony_find_snc_handle(0x127) == ev)
1079
			key_handle = 0x127;
1080
1081
		if (key_handle) {
1082
			struct sony_nc_event *key_event;
1083
1084
			if (sony_call_snc_handle(key_handle, 0x200, &result)) {
1085
				dprintk("sony_nc_notify, unable to decode"
1086
					" event 0x%.2x 0x%.2x\n", key_handle,
1087
					ev);
1088
				/* restore the original event */
1089
				ev = event;
1090
			} else {
1091
				ev = result & 0xFF;
1092
1098
1093
				if (key_handle == 0x100)
1099
	if (handle == 0x0102)
1094
					key_event = sony_100_events;
1100
		sony_call_snc_handle(0x0102, 0x100, &result);
1095
				else
1101
	else
1096
					key_event = sony_127_events;
1102
		sony_call_snc_handle(handle, 0, &result);
1097
1098
				for (; key_event->data; key_event++) {
1099
					if (key_event->data == ev) {
1100
						ev = key_event->event;
1101
						break;
1102
					}
1103
				}
1104
1105
				if (!key_event->data)
1106
					pr_info("Unknown event: 0x%x 0x%x\n",
1107
						key_handle, ev);
1108
				else
1109
					sony_laptop_report_input_event(ev);
1110
			}
1111
		} else if (sony_find_snc_handle(sony_rfkill_handle) == ev) {
1112
			sony_nc_rfkill_update();
1113
			return;
1114
		}
1115
	} else
1116
		sony_laptop_report_input_event(ev);
1117
1103
1118
	dprintk("sony_nc_notify, event: 0x%.2x\n", ev);
1104
	return 0;
1119
	acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev);
1120
}
1105
}
1121
1106
1122
static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
1107
static int sony_nc_hotkeys_decode(unsigned int handle)
1123
				      void *context, void **return_value)
1124
{
1108
{
1125
	struct acpi_device_info *info;
1109
	int ret = -EINVAL;
1110
	unsigned int result = 0;
1111
	struct sony_nc_event *key_event;
1112
1113
	if (sony_call_snc_handle(handle, 0x200, &result)) {
1114
		dprintk("sony_nc_hotkeys_decode,"
1115
				" unable to retrieve the hotkey\n");
1116
	} else {
1117
		result &= 0xff;
1126
1118
1127
	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
1119
		if (handle == 0x100)
1128
		pr_warn("method: name: %4.4s, args %X\n",
1120
			key_event = sony_100_events;
1129
			(char *)&info->name, info->param_count);
1121
		else
1122
			key_event = sony_127_events;
1130
1123
1131
		kfree(info);
1124
		for (; key_event->data; key_event++) {
1125
			if (key_event->data == result) {
1126
				ret = key_event->event;
1127
				break;
1128
			}
1129
		}
1130
1131
		if (!key_event->data)
1132
			pr_info("Unknown hotkey 0x%.2x (handle 0x%.2x)\n",
1133
							result, handle);
1134
		else
1135
			dprintk("sony_nc_hotkeys_decode, hotkey 0x%.2x decoded "
1136
					"to event 0x%.2x\n", result, ret);
1132
	}
1137
	}
1133
1138
1134
	return AE_OK;
1139
	return ret;
1135
}
1140
}
1136
1141
1137
/*
1142
enum sony_nc_rfkill {
1138
 * ACPI device
1143
	SONY_WIFI,
1139
 */
1144
	SONY_BLUETOOTH,
1140
static int sony_nc_function_setup(struct acpi_device *device)
1145
	SONY_WWAN,
1141
{
1146
	SONY_WIMAX,
1142
	int result;
1147
	N_SONY_RFKILL,
1143
1148
};
1144
	/* Enable all events */
1149
struct sony_rfkill_data {
1145
	acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result);
1150
	struct rfkill *devices[N_SONY_RFKILL];
1146
1151
	const unsigned int address[N_SONY_RFKILL];
1147
	/* Setup hotkeys */
1152
	unsigned int handle;
1148
	sony_call_snc_handle(0x0100, 0, &result);
1153
};
1149
	sony_call_snc_handle(0x0101, 0, &result);
1154
static struct sony_rfkill_data sony_rfkill = {
1150
	sony_call_snc_handle(0x0102, 0x100, &result);
1155
	{NULL}, {0x300, 0x500, 0x700, 0x900}, 0};
1151
	sony_call_snc_handle(0x0127, 0, &result);
1152
1153
	return 0;
1154
}
1155
1156
1156
static int sony_nc_resume(struct acpi_device *device)
1157
static int sony_nc_rfkill_update_wwan(void)
1157
{
1158
{
1158
	struct sony_nc_value *item;
1159
	unsigned int result, cmd;
1159
	acpi_handle handle;
1160
	bool battery;
1161
	bool swblock;
1160
1162
1161
	for (item = sony_nc_values; item->name; item++) {
1163
	if (sony_call_snc_handle(sony_rfkill.handle, 0x0200, &result))
1162
		int ret;
1164
		return -EIO;
1165
	battery = !!(result & 0x2);
1163
1166
1164
		if (!item->valid)
1167
	/* retrieve the device block state */
1165
			continue;
1168
	if (sony_call_snc_handle(sony_rfkill.handle,
1166
		ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
1169
				sony_rfkill.address[SONY_WWAN], &result))
1167
				       item->value, NULL);
1170
		return -EIO;
1168
		if (ret < 0) {
1171
	swblock = !(result & 0x02);
1169
			pr_err("%s: %d\n", __func__, ret);
1170
			break;
1171
		}
1172
	}
1173
1172
1174
	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
1173
	if (battery && !swblock) {
1175
					 &handle))) {
1174
		/* set the power state according with swblock */
1176
		if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
1175
		cmd = 0xff0000;
1177
			dprintk("ECON Method failed\n");
1176
	} else if (!battery && !swblock) {
1177
		swblock = true;
1178
		cmd = 0x20000;
1179
	} else {
1180
		return 0;
1178
	}
1181
	}
1179
1182
1180
	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1183
	cmd |= sony_rfkill.address[SONY_WWAN] + 0x100;
1181
					 &handle))) {
1182
		dprintk("Doing SNC setup\n");
1183
		sony_nc_function_setup(device);
1184
	}
1185
1184
1186
	/* re-read rfkill state */
1185
	/* set the power state */
1187
	sony_nc_rfkill_update();
1186
	sony_call_snc_handle(sony_rfkill.handle, cmd, &result);
1188
1187
1189
	/* restore kbd backlight states */
1188
	/* update the rfkill sw state */
1190
	sony_nc_kbd_backlight_resume();
1189
	rfkill_set_sw_state(sony_rfkill.devices[SONY_WWAN], swblock);
1191
1190
1192
	return 0;
1191
	return 0;
1193
}
1192
}
1194
1193
1194
static int sony_nc_get_rfkill_hwblock(void)
1195
{
1196
	unsigned int result;
1197
1198
	if (sony_call_snc_handle(sony_rfkill.handle, 0x200, &result))
1199
		return -1;
1200
1201
	return result & 0x1;
1202
}
1203
1195
static void sony_nc_rfkill_cleanup(void)
1204
static void sony_nc_rfkill_cleanup(void)
1196
{
1205
{
1197
	int i;
1206
	int i;
1198
1207
1199
	for (i = 0; i < N_SONY_RFKILL; i++) {
1208
	for (i = 0; i < N_SONY_RFKILL; i++) {
1200
		if (sony_rfkill_devices[i]) {
1209
		if (sony_rfkill.devices[i]) {
1201
			rfkill_unregister(sony_rfkill_devices[i]);
1210
			rfkill_unregister(sony_rfkill.devices[i]);
1202
			rfkill_destroy(sony_rfkill_devices[i]);
1211
			rfkill_destroy(sony_rfkill.devices[i]);
1203
		}
1212
		}
1204
	}
1213
	}
1205
}
1214
}
1206
1215
1207
static int sony_nc_rfkill_set(void *data, bool blocked)
1216
static int sony_nc_rfkill_set(void *data, bool blocked)
1208
{
1217
{
1209
	int result;
1218
	unsigned int result, argument = sony_rfkill.address[(long) data];
1210
	int argument = sony_rfkill_address[(long) data] + 0x100;
1219
1220
	/* wwan state change not allowed when the battery is not present */
1221
	sony_call_snc_handle(sony_rfkill.handle, 0x0200, &result);
1222
	if (((long) data == SONY_WWAN) && !(result & 0x2)) {
1223
		if (!blocked) {
1224
			/* notify user space: the battery must be present */
1225
			acpi_bus_generate_proc_event(sony_nc_acpi_device,
1226
				       2, 2);
1227
			acpi_bus_generate_netlink_event(
1228
					sony_nc_acpi_device->pnp.device_class,
1229
					dev_name(&sony_nc_acpi_device->dev),
1230
					2, 2);
1231
		}
1232
1233
		return -1;
1234
	}
1211
1235
1236
	/* do not force an already set state */
1237
	sony_call_snc_handle(sony_rfkill.handle, argument, &result);
1238
	if ((result & 0x1) == !blocked)
1239
		return 0;
1240
1241
	argument += 0x100;
1212
	if (!blocked)
1242
	if (!blocked)
1213
		argument |= 0xff0000;
1243
		argument |= 0xff0000;
1214
1244
1215
	return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1245
	return sony_call_snc_handle(sony_rfkill.handle, argument, &result);
1216
}
1246
}
1217
1247
1218
static const struct rfkill_ops sony_rfkill_ops = {
1248
static const struct rfkill_ops sony_rfkill_ops = {
Lines 1226-1233 static int sony_nc_setup_rfkill(struct a Link Here
1226
	struct rfkill *rfk;
1256
	struct rfkill *rfk;
1227
	enum rfkill_type type;
1257
	enum rfkill_type type;
1228
	const char *name;
1258
	const char *name;
1229
	int result;
1259
	unsigned int result;
1230
	bool hwblock;
1260
	bool hwblock, swblock, wwblock;
1231
1261
1232
	switch (nc_type) {
1262
	switch (nc_type) {
1233
	case SONY_WIFI:
1263
	case SONY_WIFI:
Lines 1255-1262 static int sony_nc_setup_rfkill(struct a Link Here
1255
	if (!rfk)
1285
	if (!rfk)
1256
		return -ENOMEM;
1286
		return -ENOMEM;
1257
1287
1258
	sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
1288
	sony_call_snc_handle(sony_rfkill.handle, 0x200, &result);
1259
	hwblock = !(result & 0x1);
1289
	hwblock = !(result & 0x1);
1290
	wwblock = !(result & 0x2);
1291
1292
	result = 0;
1293
	sony_call_snc_handle(sony_rfkill.handle, sony_rfkill.address[nc_type],
1294
				&result);
1295
	swblock = !(result & 0x2);
1296
1297
	/* hard block the WWAN module if no battery is present */
1298
	if ((nc_type == SONY_WWAN) && wwblock)
1299
		swblock = true;
1300
1301
	rfkill_init_sw_state(rfk, swblock);
1260
	rfkill_set_hw_state(rfk, hwblock);
1302
	rfkill_set_hw_state(rfk, hwblock);
1261
1303
1262
	err = rfkill_register(rfk);
1304
	err = rfkill_register(rfk);
Lines 1264-1675 static int sony_nc_setup_rfkill(struct a Link Here
1264
		rfkill_destroy(rfk);
1306
		rfkill_destroy(rfk);
1265
		return err;
1307
		return err;
1266
	}
1308
	}
1267
	sony_rfkill_devices[nc_type] = rfk;
1309
	sony_rfkill.devices[nc_type] = rfk;
1268
	return err;
1310
	return err;
1269
}
1311
}
1270
1312
1271
static void sony_nc_rfkill_update(void)
1313
static void sony_nc_rfkill_update(void)
1272
{
1314
{
1273
	enum sony_nc_rfkill i;
1315
	enum sony_nc_rfkill i;
1274
	int result;
1316
	unsigned int result;
1275
	bool hwblock;
1317
	bool hwblock, swblock, wwblock;
1276
1318
1277
	sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
1319
	sony_call_snc_handle(sony_rfkill.handle, 0x200, &result);
1278
	hwblock = !(result & 0x1);
1320
	hwblock = !(result & 0x1);
1321
	wwblock = !(result & 0x2);
1279
1322
1280
	for (i = 0; i < N_SONY_RFKILL; i++) {
1323
	for (i = 0; i < N_SONY_RFKILL; i++) {
1281
		int argument = sony_rfkill_address[i];
1324
		unsigned int argument = sony_rfkill.address[i];
1282
1325
1283
		if (!sony_rfkill_devices[i])
1326
		if (!sony_rfkill.devices[i])
1284
			continue;
1327
			continue;
1285
1328
1286
		if (hwblock) {
1329
		sony_call_snc_handle(sony_rfkill.handle, argument, &result);
1287
			if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) {
1330
		/* block wwan when no battery is present */
1288
				/* we already know we're blocked */
1331
		if ((i == SONY_WWAN) && wwblock)
1289
			}
1332
			swblock = true;
1290
			continue;
1333
		else
1291
		}
1334
			swblock = !(result & 0x2);
1292
1335
1293
		sony_call_snc_handle(sony_rfkill_handle, argument, &result);
1336
		rfkill_set_states(sony_rfkill.devices[i],
1294
		rfkill_set_states(sony_rfkill_devices[i],
1337
				  swblock, hwblock);
1295
				  !(result & 0xf), false);
1296
	}
1338
	}
1297
}
1339
}
1298
1340
1299
static void sony_nc_rfkill_setup(struct acpi_device *device)
1341
static int sony_nc_rfkill_setup(struct acpi_device *device, unsigned int handle)
1300
{
1342
{
1301
	int offset;
1343
#define	RFKILL_BUFF_SIZE 8
1302
	u8 dev_code, i;
1344
	u8 dev_code, i, buff[RFKILL_BUFF_SIZE] = { 0 };
1303
	acpi_status status;
1304
	struct acpi_object_list params;
1305
	union acpi_object in_obj;
1306
	union acpi_object *device_enum;
1307
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1308
1345
1309
	offset = sony_find_snc_handle(0x124);
1346
	sony_rfkill.handle = handle;
1310
	if (offset == -1) {
1311
		offset = sony_find_snc_handle(0x135);
1312
		if (offset == -1)
1313
			return;
1314
		else
1315
			sony_rfkill_handle = 0x135;
1316
	} else
1317
		sony_rfkill_handle = 0x124;
1318
	dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle);
1319
1347
1320
	/* need to read the whole buffer returned by the acpi call to SN06
1348
	/* need to read the whole buffer returned by the acpi call to SN06
1321
	 * here otherwise we may miss some features
1349
	 * here otherwise we may miss some features
1322
	 */
1350
	 */
1323
	params.count = 1;
1351
	if (sony_call_snc_handle_buffer(sony_rfkill.handle, 0x000,
1324
	params.pointer = &in_obj;
1352
					buff, RFKILL_BUFF_SIZE) < 0)
1325
	in_obj.type = ACPI_TYPE_INTEGER;
1353
		return -EIO;
1326
	in_obj.integer.value = offset;
1327
	status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
1328
			&buffer);
1329
	if (ACPI_FAILURE(status)) {
1330
		dprintk("Radio device enumeration failed\n");
1331
		return;
1332
	}
1333
1334
	device_enum = (union acpi_object *) buffer.pointer;
1335
	if (!device_enum) {
1336
		pr_err("No SN06 return object\n");
1337
		goto out_no_enum;
1338
	}
1339
	if (device_enum->type != ACPI_TYPE_BUFFER) {
1340
		pr_err("Invalid SN06 return object 0x%.2x\n",
1341
		       device_enum->type);
1342
		goto out_no_enum;
1343
	}
1344
1354
1345
	/* the buffer is filled with magic numbers describing the devices
1355
	/* the buffer is filled with magic numbers describing the devices
1346
	 * available, 0xff terminates the enumeration
1356
	 * available, 0xff terminates the enumeration
1347
	 */
1357
	 */
1348
	for (i = 0; i < device_enum->buffer.length; i++) {
1358
	for (i = 0; i < RFKILL_BUFF_SIZE; i++) {
1349
1359
1350
		dev_code = *(device_enum->buffer.pointer + i);
1360
		dev_code = buff[i];
1351
		if (dev_code == 0xff)
1361
		if (dev_code == 0xff)
1352
			break;
1362
			break;
1353
1363
1364
		/*
1365
		   known codes:
1366
1367
		   0x00	WLAN
1368
		   0x10 BLUETOOTH
1369
		   0x20 WWAN GPRS-EDGE
1370
		   0x21 WWAN HSDPA
1371
		   0x22 WWAN EV-DO
1372
		   0x23 WWAN GPS
1373
		   0x25	Gobi WWAN no GPS
1374
		   0x26 Gobi WWAN + GPS
1375
		   0x28	Gobi WWAN no GPS
1376
		   0x29 Gobi WWAN + GPS
1377
		   0x50	Gobi WWAN no GPS
1378
		   0x51 Gobi WWAN + GPS
1379
		   0x30	WIMAX
1380
		   0x70 no SIM card slot
1381
		   0x71 SIM card slot
1382
		*/
1354
		dprintk("Radio devices, looking at 0x%.2x\n", dev_code);
1383
		dprintk("Radio devices, looking at 0x%.2x\n", dev_code);
1355
1384
1356
		if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI])
1385
		if (dev_code == 0 && !sony_rfkill.devices[SONY_WIFI])
1357
			sony_nc_setup_rfkill(device, SONY_WIFI);
1386
			sony_nc_setup_rfkill(device, SONY_WIFI);
1358
1387
1359
		if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
1388
		if (dev_code == 0x10 && !sony_rfkill.devices[SONY_BLUETOOTH])
1360
			sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1389
			sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1361
1390
1362
		if ((0xf0 & dev_code) == 0x20 &&
1391
		if (((0xf0 & dev_code) == 0x20 || (0xf0 & dev_code) == 0x50) &&
1363
				!sony_rfkill_devices[SONY_WWAN])
1392
				!sony_rfkill.devices[SONY_WWAN])
1364
			sony_nc_setup_rfkill(device, SONY_WWAN);
1393
			sony_nc_setup_rfkill(device, SONY_WWAN);
1365
1394
1366
		if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
1395
		if (dev_code == 0x30 && !sony_rfkill.devices[SONY_WIMAX])
1367
			sony_nc_setup_rfkill(device, SONY_WIMAX);
1396
			sony_nc_setup_rfkill(device, SONY_WIMAX);
1397
	}
1398
1399
	return 0;
1400
}
1401
1402
/*	ALS controlled backlight feature	*/
1403
/* generic ALS data and interface */
1404
#define ALS_TABLE_SIZE	25
1405
1406
struct als_device_ops {
1407
	int (*init)(const u8 defaults[]);
1408
	int (*exit)(void);
1409
	int (*event_handler)(void);
1410
	int (*set_power)(unsigned int);
1411
	int (*get_power)(unsigned int *);
1412
	int (*get_lux)(unsigned int *, unsigned int *);
1413
	int (*get_kelvin)(unsigned int *);
1414
};
1415
1416
static struct  sony_als_device {
1417
	unsigned int handle;
1418
1419
	unsigned int power;
1420
	unsigned int managed;
1421
1422
	unsigned int levels_num;
1423
	u8 *levels;
1424
	unsigned int defaults_num;
1425
	u8 *defaults;
1426
	u8 parameters[ALS_TABLE_SIZE];
1427
1428
	/* common device operations */
1429
	const struct als_device_ops *ops;
1430
1431
	/* basic ALS sys interface */
1432
	unsigned int attrs_num;
1433
	struct device_attribute attrs[7];
1434
} *sony_als;
1435
1436
/*
1437
	model specific ALS data and controls
1438
	TAOS TSL256x device data
1439
*/
1440
#define LUX_SHIFT_BITS		16	/* for non-floating point math */
1441
/* scale 100000 multiplied fractional coefficients rounding the values */
1442
#define SCALE(u)	((((((u64) u) << LUX_SHIFT_BITS) / 10000) + 5) / 10)
1443
1444
#define TSL256X_REG_CTRL	0x00
1445
#define TSL256X_REG_TIMING	0x01
1446
#define TSL256X_REG_TLOW	0x02
1447
#define TSL256X_REG_THIGH	0x04
1448
#define TSL256X_REG_INT		0x06
1449
#define TSL256X_REG_ID		0x0a
1450
#define TSL256X_REG_DATA0	0x0c
1451
#define TSL256X_REG_DATA1	0x0e
1452
1453
#define TSL256X_POWER_ON	0x03
1454
#define TSL256X_POWER_OFF	0x00
1455
1456
#define TSL256X_POWER_MASK	0x03
1457
#define TSL256X_INT_MASK	0x10
1458
1459
struct tsl256x_coeff {
1460
	u32 ratio;
1461
	u32 ch0;
1462
	u32 ch1;
1463
	u32 ka;
1464
	s32 kb;
1465
};
1466
1467
struct tsl256x_data {
1468
	unsigned int gaintime;
1469
	unsigned int periods;
1470
	u8 *defaults;
1471
	struct tsl256x_coeff const *coeff_table;
1472
};
1473
static struct tsl256x_data *tsl256x_handle;
1474
1475
static const struct tsl256x_coeff tsl256x_coeff_fn[] = {
1476
	{
1477
		.ratio	= SCALE(12500),	/* 0.125 * 2^LUX_SHIFT_BITS  */
1478
		.ch0	= SCALE(3040),	/* 0.0304 * 2^LUX_SHIFT_BITS */
1479
		.ch1	= SCALE(2720),	/* 0.0272 * 2^LUX_SHIFT_BITS */
1480
		.ka	= SCALE(313550000),
1481
		.kb	= -10651,
1482
	}, {
1483
		.ratio	= SCALE(25000),	/* 0.250 * 2^LUX_SHIFT_BITS  */
1484
		.ch0	= SCALE(3250),	/* 0.0325 * 2^LUX_SHIFT_BITS */
1485
		.ch1	= SCALE(4400),	/* 0.0440 * 2^LUX_SHIFT_BITS */
1486
		.ka	= SCALE(203390000),
1487
		.kb	= -2341,
1488
	}, {
1489
		.ratio	= SCALE(37500),	/* 0.375 * 2^LUX_SHIFT_BITS  */
1490
		.ch0	= SCALE(3510),	/* 0.0351 * 2^LUX_SHIFT_BITS */
1491
		.ch1	= SCALE(5440),	/* 0.0544 * 2^LUX_SHIFT_BITS */
1492
		.ka	= SCALE(152180000),
1493
		.kb	= 157,
1494
	}, {
1495
		.ratio	= SCALE(50000),	/* 0.50 * 2^LUX_SHIFT_BITS   */
1496
		.ch0	= SCALE(3810),	/* 0.0381 * 2^LUX_SHIFT_BITS */
1497
		.ch1	= SCALE(6240),	/* 0.0624 * 2^LUX_SHIFT_BITS */
1498
		.ka	= SCALE(163580000),
1499
		.kb	= -145,
1500
	}, {
1501
		.ratio	= SCALE(61000),	/* 0.61 * 2^LUX_SHIFT_BITS   */
1502
		.ch0	= SCALE(2240),	/* 0.0224 * 2^LUX_SHIFT_BITS */
1503
		.ch1	= SCALE(3100),	/* 0.0310 * 2^LUX_SHIFT_BITS */
1504
		.ka	= SCALE(180800000),
1505
		.kb	= -495,
1506
	}, {
1507
		.ratio	= SCALE(80000),	/* 0.80 * 2^LUX_SHIFT_BITS   */
1508
		.ch0	= SCALE(1280),	/* 0.0128 * 2^LUX_SHIFT_BITS */
1509
		.ch1	= SCALE(1530),	/* 0.0153 * 2^LUX_SHIFT_BITS */
1510
		.ka	= SCALE(197340000),
1511
		.kb	= -765
1512
	}, {
1513
		.ratio	= SCALE(130000),/* 1.3 * 2^LUX_SHIFT_BITS     */
1514
		.ch0	= SCALE(146),	/* 0.00146 * 2^LUX_SHIFT_BITS */
1515
		.ch1	= SCALE(112),	/* 0.00112 * 2^LUX_SHIFT_BITS */
1516
		.ka	= SCALE(182900000),
1517
		.kb	= -608,
1518
	}, {
1519
		.ratio	= UINT_MAX,	/* for higher ratios */
1520
		.ch0	= 0,
1521
		.ch1	= 0,
1522
		.ka	= 0,
1523
		.kb	= 830,
1524
	}
1525
};
1526
1527
static const struct tsl256x_coeff tsl256x_coeff_cs[] = {
1528
	{
1529
		.ratio  = SCALE(13000),	/* 0.130 * 2^LUX_SHIFT_BITS  */
1530
		.ch0    = SCALE(3150),	/* 0.0315 * 2^LUX_SHIFT_BITS */
1531
		.ch1    = SCALE(2620),	/* 0.0262 * 2^LUX_SHIFT_BITS */
1532
		.ka	= SCALE(300370000),
1533
		.kb	= -9587,
1534
	}, {
1535
		.ratio  = SCALE(26000),	/* 0.260 * 2^LUX_SHIFT_BITS  */
1536
		.ch0    = SCALE(3370),	/* 0.0337 * 2^LUX_SHIFT_BITS */
1537
		.ch1    = SCALE(4300),	/* 0.0430 * 2^LUX_SHIFT_BITS */
1538
		.ka	= SCALE(194270000),
1539
		.kb	= -1824,
1540
	}, {
1541
		.ratio  = SCALE(39000),	/* 0.390 * 2^LUX_SHIFT_BITS  */
1542
		.ch0    = SCALE(3630),	/* 0.0363 * 2^LUX_SHIFT_BITS */
1543
		.ch1    = SCALE(5290),	/* 0.0529 * 2^LUX_SHIFT_BITS */
1544
		.ka	= SCALE(152520000),
1545
		.kb	= 145,
1546
	}, {
1547
		.ratio  = SCALE(52000),	/* 0.520 * 2^LUX_SHIFT_BITS  */
1548
		.ch0    = SCALE(3920),	/* 0.0392 * 2^LUX_SHIFT_BITS */
1549
		.ch1    = SCALE(6050),	/* 0.0605 * 2^LUX_SHIFT_BITS */
1550
		.ka	= SCALE(165960000),
1551
		.kb	= -200,
1552
	}, {
1553
		.ratio  = SCALE(65000),	/* 0.650 * 2^LUX_SHIFT_BITS  */
1554
		.ch0    = SCALE(2290),	/* 0.0229 * 2^LUX_SHIFT_BITS */
1555
		.ch1    = SCALE(2910),	/* 0.0291 * 2^LUX_SHIFT_BITS */
1556
		.ka	= SCALE(184800000),
1557
		.kb	= -566,
1558
	}, {
1559
		.ratio  = SCALE(80000),	/* 0.800 * 2^LUX_SHIFT_BITS  */
1560
		.ch0    = SCALE(1570),	/* 0.0157 * 2^LUX_SHIFT_BITS */
1561
		.ch1    = SCALE(1800),	/* 0.0180 * 2^LUX_SHIFT_BITS */
1562
		.ka	= SCALE(199220000),
1563
		.kb	= -791,
1564
	}, {
1565
		.ratio  = SCALE(130000),/* 0.130 * 2^LUX_SHIFT_BITS  */
1566
		.ch0    = SCALE(338),	/* 0.00338 * 2^LUX_SHIFT_BITS */
1567
		.ch1    = SCALE(260),	/* 0.00260 * 2^LUX_SHIFT_BITS */
1568
		.ka	= SCALE(182900000),
1569
		.kb	= -608,
1570
	}, {
1571
		.ratio  = UINT_MAX,	/* for higher ratios */
1572
		.ch0    = 0,
1573
		.ch1    = 0,
1574
		.ka	= 0,
1575
		.kb	= 830,
1576
	}
1577
};
1578
1579
/*	TAOS helper & control functions		*/
1580
static inline int tsl256x_exec_writebyte(unsigned int reg,
1581
						unsigned int const *value)
1582
{
1583
	unsigned int result;
1584
1585
	return (sony_call_snc_handle(sony_als->handle, (*value << 0x18) |
1586
		(reg << 0x10) | 0x800500, &result) || !(result & 0x01))
1587
		? -EIO : 0;
1588
}
1589
1590
static inline int tsl256x_exec_writeword(unsigned int reg,
1591
						unsigned int const *value)
1592
{
1593
	u8 result[1];
1594
	u64 arg = *value;
1595
1596
	/* using sony_call_snc_handle_buffer due to possible input overflows */
1597
	return ((sony_call_snc_handle_buffer(sony_als->handle, (arg << 0x18) |
1598
				(reg << 0x10) | 0xA00700, result, 1) < 0) ||
1599
				!(result[0] & 0x01)) ? -EIO : 0;
1600
}
1601
1602
static inline int tsl256x_exec_readbyte(unsigned int reg, unsigned int *result)
1603
{
1604
	if (sony_call_snc_handle(sony_als->handle, (reg << 0x10)
1605
		| 0x800400, result) || !(*result & 0x01))
1606
		return -EIO;
1607
	*result = (*result >> 0x08) & 0xFF;
1608
1609
	return 0;
1610
}
1611
1612
static inline int tsl256x_exec_readword(unsigned int reg, unsigned int *result)
1613
{
1614
	if (sony_call_snc_handle(sony_als->handle, (reg << 0x10)
1615
		| 0xA00600, result) || !(*result & 0x01))
1616
		return -EIO;
1617
	*result = (*result >> 0x08) & 0xFFFF;
1618
1619
	return 0;
1620
}
1621
1622
static int tsl256x_interrupt_ctrls(unsigned int *interrupt,
1623
					unsigned int *periods)
1624
{
1625
	unsigned int value, result;
1626
1627
	/* if no interrupt parameter, retrieve interrupt status */
1628
	if (!interrupt) {
1629
		if (tsl256x_exec_readbyte(TSL256X_REG_INT, &result))
1630
			return -EIO;
1631
1632
		value = (result & TSL256X_INT_MASK);
1633
	} else {
1634
		value = *interrupt << 0x04;
1635
	}
1636
1637
	/* if no periods provided use the last one set */
1638
	value |= (periods ? *periods : tsl256x_handle->periods);
1639
1640
	if (tsl256x_exec_writebyte(TSL256X_REG_INT, &value))
1641
		return -EIO;
1642
1643
	if (periods)
1644
		tsl256x_handle->periods = *periods;
1645
1646
	return 0;
1647
}
1648
1649
static int tsl256x_setup(void)
1650
{
1651
	unsigned int interr = 1, zero = 0;
1652
1653
	/*
1654
	 *   reset the threshold settings to trigger an event as soon
1655
	 *   as the event goes on, forcing a backlight adaptation to
1656
	 *   the current lighting conditions
1657
	 */
1658
	tsl256x_exec_writeword(TSL256X_REG_TLOW, &zero);
1659
	tsl256x_exec_writeword(TSL256X_REG_THIGH, &zero);
1660
1661
	/* set gain and time */
1662
	if (tsl256x_exec_writebyte(TSL256X_REG_TIMING,
1663
				&tsl256x_handle->gaintime))
1664
		return -EIO;
1665
1666
	/* restore persistence value and enable the interrupt generation */
1667
	if (tsl256x_interrupt_ctrls(&interr, &tsl256x_handle->periods))
1668
		return -EIO;
1669
1670
	return 0;
1671
}
1672
1673
static int tsl256x_set_power(unsigned int status)
1674
{
1675
	int ret;
1676
1677
	if (status) {
1678
		ret = tsl256x_setup();
1679
		if (ret)
1680
			return ret;
1681
	}
1682
1683
	status = status ? TSL256X_POWER_ON : TSL256X_POWER_OFF;
1684
	ret = tsl256x_exec_writebyte(TSL256X_REG_CTRL, &status);
1685
1686
	return ret;
1687
}
1688
1689
static int tsl256x_get_power(unsigned int *status)
1690
{
1691
	if (tsl256x_exec_readbyte(TSL256X_REG_CTRL, status))
1692
		return -EIO;
1693
1694
	*status = ((*status & TSL256X_POWER_MASK) == TSL256X_POWER_ON) ? 1 : 0;
1695
1696
	return 0;
1697
}
1698
1699
static int tsl256x_get_raw_data(unsigned int *ch0, unsigned int *ch1)
1700
{
1701
	if (!ch0)
1702
		return -1;
1703
1704
	if (tsl256x_exec_readword(TSL256X_REG_DATA0, ch0))
1705
		return -EIO;
1706
1707
	if (ch1) {
1708
		if (tsl256x_exec_readword(TSL256X_REG_DATA1, ch1))
1709
			return -EIO;
1710
	}
1711
1712
	return 0;
1713
}
1714
1715
static int tsl256x_set_thresholds(const unsigned int *ch0)
1716
{
1717
	unsigned int tlow, thigh;
1718
1719
	tlow = (*ch0 * tsl256x_handle->defaults[0]) / 100;
1720
	thigh = ((*ch0 * tsl256x_handle->defaults[1]) / 100) + 1;
1721
1722
	if (thigh > 0xffff)
1723
		thigh = 0xffff;
1724
1725
	if (tsl256x_exec_writeword(TSL256X_REG_TLOW, &tlow) ||
1726
		tsl256x_exec_writeword(TSL256X_REG_THIGH, &thigh))
1727
		return -EIO;
1728
1729
	return 0;
1730
}
1731
1732
#define MAX_LUX 1500
1733
static void tsl256x_calculate_lux(const u32 ch0, const u32 ch1,
1734
				unsigned int *integ, unsigned int *fract)
1735
{
1736
	/* the raw output from the sensor is just a "count" value, as
1737
	   it is the result of the integration of the analog sensor
1738
	   signal, the counts-to-lux curve (and its approximation can
1739
	   be found on the datasheet.
1740
	*/
1741
	const struct tsl256x_coeff *coeff = tsl256x_handle->coeff_table;
1742
	u32 ratio, temp, integer, fractional;
1743
1744
	if (ch0 >= 65535 || ch1 >= 65535)
1745
		goto saturation;
1746
1747
	/* STEP 1: ratio calculation, for ch0 & ch1 coeff selection */
1748
1749
	/* protect against division by 0 */
1750
	ratio = ch0 ? ((ch1 << (LUX_SHIFT_BITS + 1)) / ch0) : UINT_MAX;
1751
	/* round the ratio value */
1752
	ratio = ratio == UINT_MAX ? ratio : (ratio + 1) >> 1;
1753
1754
	/* coeff selection rule */
1755
	while (coeff->ratio < ratio)
1756
		coeff++;
1757
1758
	/* STEP 2: lux calculation formula using the right coeffcients */
1759
	temp = (ch0 * coeff->ch0) - (ch1 * coeff->ch1);
1760
	/* the sensor is placed under a plastic or glass cover which filters
1761
	   a certain ammount of light (depending on that particular material).
1762
	   To have an accurate reading, we need to compensate for this loss,
1763
	   multiplying for compensation parameter, taken from the DSDT.
1764
	*/
1765
	temp *= tsl256x_handle->defaults[3] / 10;
1766
1767
	/* STEP 3: separate integer and fractional part */
1768
	/* remove the integer part and multiply for the 10^N, N decimals  */
1769
	fractional = (temp % (1 << LUX_SHIFT_BITS)) * 100; /* two decimals */
1770
	/* scale down the value */
1771
	fractional >>= LUX_SHIFT_BITS;
1772
1773
	/* strip off fractional portion to obtain the integer part */
1774
	integer = temp >> LUX_SHIFT_BITS;
1775
1776
	if (integer > MAX_LUX)
1777
		goto saturation;
1778
1779
	*integ = integer;
1780
	*fract = fractional;
1781
1782
	return;
1783
1784
saturation:
1785
	*integ = MAX_LUX;
1786
	*fract = 0;
1787
}
1788
1789
static void tsl256x_calculate_kelvin(const u32 *ch0, const u32 *ch1,
1790
					unsigned int *temperature)
1791
{
1792
	const struct tsl256x_coeff *coeff = tsl256x_handle->coeff_table;
1793
	u32 ratio;
1794
1795
	/* protect against division by 0 */
1796
	ratio = *ch0 ? ((*ch1 << (LUX_SHIFT_BITS + 1)) / *ch0) : UINT_MAX;
1797
	/* round the ratio value */
1798
	ratio = (ratio + 1) >> 1;
1799
1800
	/* coeff selection rule */
1801
	while (coeff->ratio < ratio)
1802
		coeff++;
1803
1804
	*temperature = ratio ? coeff->ka / ratio + coeff->kb : 0;
1805
}
1806
1807
static int tsl256x_get_lux(unsigned int *integ, unsigned int *fract)
1808
{
1809
	int ret = 0;
1810
	unsigned int ch0, ch1;
1811
1812
	if (!integ || !fract)
1813
		return -1;
1814
1815
	ret = tsl256x_get_raw_data(&ch0, &ch1);
1816
	if (!ret)
1817
		tsl256x_calculate_lux(ch0, ch1, integ, fract);
1818
1819
	return ret;
1820
}
1821
1822
static int tsl256x_get_kelvin(unsigned int *temperature)
1823
{
1824
	int ret = -1;
1825
	unsigned int ch0, ch1;
1826
1827
	if (!temperature)
1828
		return ret;
1829
1830
	ret = tsl256x_get_raw_data(&ch0, &ch1);
1831
	if (!ret)
1832
		tsl256x_calculate_kelvin(&ch0, &ch1, temperature);
1833
1834
	return ret;
1835
}
1836
1837
static int tsl256x_get_id(char *model, unsigned int *id, bool *cs)
1838
{
1839
	int ret;
1840
	unsigned int result;
1841
	char *name = NULL;
1842
	bool unknown = false;
1843
	bool type_cs = false;
1844
1845
	ret = tsl256x_exec_readbyte(TSL256X_REG_ID, &result);
1846
	if (ret)
1847
		return ret;
1848
1849
	switch ((result >> 0x04) & 0x0F) {
1850
	case 5:
1851
		name = "TAOS TSL2561";
1852
		break;
1853
	case 4:
1854
		name = "TAOS TSL2560";
1855
		break;
1856
	case 3:
1857
		name = "TAOS TSL2563";
1858
		break;
1859
	case 2:
1860
		name = "TAOS TSL2562";
1861
		break;
1862
	case 1:
1863
		type_cs = true;
1864
		name = "TAOS TSL2561CS";
1865
		break;
1866
	case 0:
1867
		type_cs = true;
1868
		name = "TAOS TSL2560CS";
1869
		break;
1870
	default:
1871
		unknown = true;
1872
		break;
1873
	}
1874
1875
	if (id)
1876
		*id = result;
1877
	if (cs)
1878
		*cs = type_cs;
1879
	if (model && name)
1880
		strcpy(model, name);
1881
1882
	return unknown;
1883
}
1884
1885
static int tsl256x_event_handler(void)
1886
{
1887
	unsigned int ch0, interr = 1;
1888
1889
	/* wait for the EC to clear the interrupt */
1890
/*      schedule_timeout_interruptible(msecs_to_jiffies(100));	*/
1891
	/* ...or force the interrupt clear immediately */
1892
	sony_call_snc_handle(sony_als->handle, 0x04C60500, &interr);
1893
1894
	/* read the raw data */
1895
	tsl256x_get_raw_data(&ch0, NULL);
1896
1897
	/* set the thresholds */
1898
	tsl256x_set_thresholds(&ch0);
1899
1900
	/* enable interrupt */
1901
	tsl256x_interrupt_ctrls(&interr, NULL);
1902
1903
	return 0;
1904
}
1905
1906
static int tsl256x_init(const u8 defaults[])
1907
{
1908
	unsigned int id;
1909
	int ret = 0;
1910
	bool cs; /* if CS package choose CS coefficients */
1911
	char model[64];
1912
1913
	/* detect the device */
1914
	ret = tsl256x_get_id(model, &id, &cs);
1915
	if (ret < 0)
1916
		return ret;
1917
	if (ret) {
1918
		dprintk("unsupported ALS found (unknown model "
1919
			"number %u rev. %u\n", id >> 4, id & 0x0F);
1920
		return ret;
1921
	} else {
1922
		dprintk("found ALS model number %u rev. %u (%s)\n",
1923
				id >> 4, id & 0x0F, model);
1924
	}
1925
1926
	tsl256x_handle = kzalloc(sizeof(struct tsl256x_data), GFP_KERNEL);
1927
	if (!tsl256x_handle)
1928
		return -ENOMEM;
1929
1930
	tsl256x_handle->defaults = kzalloc(sizeof(u8) * 4, GFP_KERNEL);
1931
	if (!tsl256x_handle->defaults) {
1932
		kfree(tsl256x_handle);
1933
		return -ENOMEM;
1934
	}
1935
1936
	/* populate the device data */
1937
	tsl256x_handle->defaults[0] = defaults[3];  /* low threshold % */
1938
	tsl256x_handle->defaults[1] = defaults[4];  /* high threshold % */
1939
	tsl256x_handle->defaults[2] = defaults[9];  /* sensor interrupt rate */
1940
	tsl256x_handle->defaults[3] = defaults[10]; /* light compensat. rate */
1941
	tsl256x_handle->gaintime = 0x12;
1942
	tsl256x_handle->periods = defaults[9];
1943
	tsl256x_handle->coeff_table = cs ? tsl256x_coeff_cs : tsl256x_coeff_fn;
1944
1945
	ret = tsl256x_setup();
1946
1947
	return ret;
1948
}
1949
1950
static int tsl256x_exit(void)
1951
{
1952
	unsigned int interr = 0, periods = tsl256x_handle->defaults[2];
1953
1954
	/* disable the interrupt generation, restore defaults */
1955
	tsl256x_interrupt_ctrls(&interr, &periods);
1956
1957
	tsl256x_handle->coeff_table = NULL;
1958
	kfree(tsl256x_handle->defaults);
1959
	tsl256x_handle->defaults = NULL;
1960
	kfree(tsl256x_handle);
1961
1962
	return 0;
1963
}
1964
1965
/* TAOS TSL256x specific ops */
1966
static const struct als_device_ops tsl256x_ops = {
1967
	.init = tsl256x_init,
1968
	.exit = tsl256x_exit,
1969
	.event_handler = tsl256x_event_handler,
1970
	.set_power = tsl256x_set_power,
1971
	.get_power = tsl256x_get_power,
1972
	.get_lux = tsl256x_get_lux,
1973
	.get_kelvin = tsl256x_get_kelvin,
1974
};
1975
1976
/* unknown ALS sensors controlled by the EC present on newer Vaios */
1977
static inline int ngals_get_raw_data(unsigned int *data)
1978
{
1979
	if (sony_call_snc_handle(sony_als->handle, 0x1000, data))
1980
		return -EIO;
1981
1982
	return 0;
1983
}
1984
1985
static int ngals_get_lux(unsigned int *integ, unsigned int *fract)
1986
{
1987
	unsigned int data;
1988
1989
	if (sony_call_snc_handle(sony_als->handle, 0x1000, &data))
1990
		return -EIO;
1991
1992
	/* if we have a valid lux data */
1993
	if (!!(data & 0xff0000) == 0x01) {
1994
		*integ = 0xffff & data;
1995
		*fract = 0;
1996
	} else {
1997
		return -1;
1998
	}
1999
2000
	return 0;
2001
}
2002
2003
static const struct als_device_ops ngals_ops = {
2004
	.init = NULL,
2005
	.exit = NULL,
2006
	.event_handler = NULL,
2007
	.set_power = NULL,
2008
	.get_power = NULL,
2009
	.get_lux = ngals_get_lux,
2010
	.get_kelvin = NULL,
2011
};
2012
2013
/*	ALS common data and functions	*/
2014
static int sony_nc_als_event_handler(void)
2015
{
2016
	/* call the device handler */
2017
	if (sony_als->ops->event_handler)
2018
		sony_als->ops->event_handler();
2019
2020
	return 0;
2021
}
2022
2023
static int sony_nc_als_power_set(unsigned int status)
2024
{
2025
	if (!sony_als->ops->set_power)
2026
		return -EPERM;
2027
2028
	if (sony_als->ops->set_power(status))
2029
		return -EIO;
2030
2031
	sony_als->power = status;
2032
2033
	return 0;
2034
}
2035
2036
static int sony_nc_als_managed_set(unsigned int status)
2037
{
2038
	int ret = 0;
2039
	unsigned int result, cmd;
2040
	static bool was_on;
2041
2042
	/*  turn on/off the event notification
2043
	 *  (and enable als_backlight writes)
2044
	 */
2045
	cmd = sony_als->handle == 0x0143 ? 0x2200 : 0x0900;
2046
	if (sony_call_snc_handle(sony_als->handle,
2047
		(status << 0x10) | cmd, &result))
2048
		return -EIO;
2049
2050
	sony_als->managed = status;
2051
2052
	/* turn on the ALS; this will also enable the interrupt generation */
2053
	if (status) /* store the power state else check the previous state */
2054
		was_on = sony_als->power;
2055
	else if (was_on)
2056
		return 0;
2057
2058
	ret = sony_nc_als_power_set(status);
2059
	if (ret == -EPERM) /* new models do not allow power control */
2060
		ret = 0;
2061
2062
	return ret;
2063
}
2064
2065
static unsigned int level;
2066
static int sony_nc_als_get_brightness(struct backlight_device *bd)
2067
{
2068
	if (bd->props.brightness != level)
2069
		dprintk("bd->props.brightness != level\n");
2070
2071
	return level;
2072
}
2073
2074
static int sony_nc_als_update_status(struct backlight_device *bd)
2075
{
2076
	unsigned int value, result;
2077
2078
	if (sony_als->managed) {
2079
		if (bd->props.brightness != level) {
2080
			char *env[2] = { "ALS=2", NULL};
2081
			kobject_uevent_env(&sony_nc_acpi_device->dev.kobj,
2082
						KOBJ_CHANGE, env);
2083
2084
			dprintk("generating ALS event 3 (reason: 2)\n");
2085
			acpi_bus_generate_proc_event(sony_nc_acpi_device,
2086
					3, 2);
2087
			acpi_bus_generate_netlink_event(
2088
					sony_nc_acpi_device->pnp.device_class,
2089
					dev_name(&sony_nc_acpi_device->dev),
2090
					3, 2);
2091
		}
2092
	} else {
2093
		unsigned int cmd;
2094
2095
		value = sony_als->levels[bd->props.brightness];
2096
		cmd = sony_als->handle == 0x0143 ? 0x3000 : 0x0100;
2097
		if (sony_call_snc_handle(sony_als->handle,
2098
					(value << 0x10) | cmd, &result))
2099
			return -EIO;
2100
	}
2101
2102
	level = bd->props.brightness;
2103
2104
	return level;
2105
}
2106
2107
/*	ALS sys interface	*/
2108
static ssize_t sony_nc_als_power_show(struct device *dev,
2109
		struct device_attribute *attr, char *buffer)
2110
{
2111
	ssize_t count = 0;
2112
	int status;
2113
2114
	if (!sony_als->ops->get_power)
2115
		return -EPERM;
2116
2117
	if (sony_als->ops->get_power(&status))
2118
		return -EIO;
2119
2120
	count = snprintf(buffer, PAGE_SIZE, "%d\n", status);
2121
2122
	return count;
2123
}
2124
2125
static ssize_t sony_nc_als_power_store(struct device *dev,
2126
		struct device_attribute *attr,
2127
		const char *buffer, size_t count)
2128
{
2129
	int ret;
2130
	unsigned long value;
2131
2132
	if (count > 31)
2133
		return -EINVAL;
2134
2135
	if (strict_strtoul(buffer, 10, &value) || value > 1)
2136
		return -EINVAL;
2137
2138
	/* no action if already set */
2139
	if (value == sony_als->power)
2140
		return count;
2141
2142
	ret = sony_nc_als_power_set(value);
2143
	if (ret)
2144
		return ret;
2145
2146
	return count;
2147
}
2148
2149
static ssize_t sony_nc_als_managed_show(struct device *dev,
2150
		struct device_attribute *attr, char *buffer)
2151
{
2152
	ssize_t count = 0;
2153
	unsigned int status, cmd;
2154
2155
	cmd = sony_als->handle == 0x0143 ? 0x2100 : 0x0A00;
2156
	if (sony_call_snc_handle(sony_als->handle, cmd, &status))
2157
		return -EIO;
2158
2159
	count = snprintf(buffer, PAGE_SIZE, "%d\n", status & 0x01);
2160
2161
	return count;
2162
}
2163
2164
static ssize_t sony_nc_als_managed_store(struct device *dev,
2165
		struct device_attribute *attr,
2166
		const char *buffer, size_t count)
2167
{
2168
	unsigned long value;
2169
2170
	if (count > 31)
2171
		return -EINVAL;
2172
2173
	if (strict_strtoul(buffer, 10, &value) || value > 1)
2174
		return -EINVAL;
2175
2176
	if (sony_als->managed != value) {
2177
		int ret = sony_nc_als_managed_set(value);
2178
		if (ret)
2179
			return ret;
2180
	}
2181
2182
	return count;
2183
}
2184
2185
static ssize_t sony_nc_als_lux_show(struct device *dev,
2186
		struct device_attribute *attr, char *buffer)
2187
{
2188
	ssize_t count = 0;
2189
	unsigned int integ = 0, fract = 0;
2190
2191
	if (sony_als->power)
2192
		/* sony_als->ops->get_lux is mandatory, no check */
2193
		sony_als->ops->get_lux(&integ, &fract);
2194
2195
	count = snprintf(buffer, PAGE_SIZE, "%u.%.2u\n", integ, fract);
2196
2197
	return count;
2198
}
2199
2200
static ssize_t sony_nc_als_parameters_show(struct device *dev,
2201
		struct device_attribute *attr, char *buffer)
2202
{
2203
	ssize_t count = 0;
2204
	unsigned int i, num;
2205
	u8 *list;
2206
2207
	if (!strcmp(attr->attr.name, "als_defaults")) {
2208
		list = sony_als->defaults;
2209
		num = sony_als->defaults_num;
2210
	} else { /* als_backlight_levels */
2211
		list = sony_als->levels;
2212
		num = sony_als->levels_num;
2213
	}
2214
2215
	for (i = 0; i < num; i++)
2216
		count += snprintf(buffer + count, PAGE_SIZE - count,
2217
				"0x%.2x ", list[i]);
2218
2219
	count += snprintf(buffer + count, PAGE_SIZE - count, "\n");
2220
2221
	return count;
2222
}
2223
2224
static ssize_t sony_nc_als_backlight_show(struct device *dev,
2225
		struct device_attribute *attr, char *buffer)
2226
{
2227
	ssize_t count = 0;
2228
	unsigned int result, cmd;
2229
2230
	cmd = sony_als->handle == 0x0143 ? 0x3100 : 0x0200;
2231
	if (sony_call_snc_handle(sony_als->handle, cmd, &result))
2232
		return -EIO;
2233
2234
	count = snprintf(buffer, PAGE_SIZE, "%d\n", result & 0xff);
2235
2236
	return count;
2237
}
2238
2239
static ssize_t sony_nc_als_backlight_store(struct device *dev,
2240
		struct device_attribute *attr,
2241
		const char *buffer, size_t count)
2242
{
2243
	unsigned long value;
2244
	unsigned int result, cmd, max = sony_als->levels_num - 1;
2245
2246
	if (count > 31)
2247
		return -EINVAL;
2248
2249
	if (strict_strtoul(buffer, 10, &value))
2250
		return -EINVAL;
2251
2252
	if (!sony_als->managed)
2253
		return -EPERM;
2254
2255
	/* verify that the provided value falls inside the model
2256
	   specific backlight range */
2257
	if ((value < sony_als->levels[0])
2258
			|| (value > sony_als->levels[max]))
2259
		return -EINVAL;
2260
2261
	cmd = sony_als->handle == 0x0143 ? 0x3000 : 0x0100;
2262
	if (sony_call_snc_handle(sony_als->handle, (value << 0x10) | cmd,
2263
				&result))
2264
		return -EIO;
2265
2266
	return count;
2267
}
2268
2269
static ssize_t sony_nc_als_kelvin_show(struct device *dev,
2270
		struct device_attribute *attr, char *buffer)
2271
{
2272
	ssize_t count = 0;
2273
	unsigned int kelvin = 0;
2274
2275
	if (sony_als->ops->get_kelvin && sony_als->power)
2276
		sony_als->ops->get_kelvin(&kelvin);
2277
2278
	count = snprintf(buffer, PAGE_SIZE, "%d\n", kelvin);
2279
2280
	return count;
2281
}
2282
2283
/*	ALS attach/detach functions	*/
2284
static int sony_nc_als_setup(struct platform_device *pd, unsigned int handle)
2285
{
2286
	int i = 0;
2287
2288
	/* check the device presence */
2289
	if (handle == 0x0137) {
2290
		unsigned int result;
2291
2292
		if (sony_call_snc_handle(handle, 0xB00, &result))
2293
			return -EIO;
2294
2295
		if (!(result & 0x01)) {
2296
			pr_info("no ALS present\n");
2297
			return 0;
2298
		}
2299
	}
2300
2301
	sony_als = kzalloc(sizeof(struct sony_als_device), GFP_KERNEL);
2302
	if (!sony_als)
2303
		return -ENOMEM;
2304
2305
	/* set model specific data */
2306
	/* if handle 0x012f or 0x0137 use tsl256x_ops, else new als controls */
2307
	if (handle == 0x0143) {
2308
		sony_als->ops = &ngals_ops;
2309
		sony_als->levels_num = 16;
2310
		sony_als->defaults_num = 9;
2311
	} else {
2312
		sony_als->ops = &tsl256x_ops;
2313
		sony_als->levels_num = 9;
2314
		sony_als->defaults_num = 13;
2315
	}
2316
	/* backlight levels are the first levels_num values, the remaining
2317
	   defaults_num values are default settings for als regulation
2318
	*/
2319
	sony_als->levels = sony_als->parameters;
2320
	sony_als->defaults = sony_als->parameters + sony_als->levels_num;
2321
2322
	sony_als->handle = handle;
2323
2324
	/* get power state */
2325
	if (sony_als->ops->get_power) {
2326
		if (sony_als->ops->get_power(&sony_als->power))
2327
			pr_warn("unable to retrieve the power status\n");
2328
	}
2329
2330
	/* set managed to 0, userspace daemon should enable it */
2331
	sony_nc_als_managed_set(0);
2332
2333
	/* get ALS parameters */
2334
	if (sony_call_snc_handle_buffer(sony_als->handle, 0x0000,
2335
		sony_als->parameters, ALS_TABLE_SIZE) < 0)
2336
		goto nosensor;
2337
2338
	/* initial device configuration */
2339
	if (sony_als->ops->init)
2340
		if (sony_als->ops->init(sony_als->defaults)) {
2341
			pr_warn("ALS setup failed\n");
2342
			goto nosensor;
2343
		}
2344
2345
	/* set up the sys interface */
2346
2347
	/* notifications and backlight enable control file */
2348
	sysfs_attr_init(&sony_als->attrs[0].attr);
2349
	sony_als->attrs[0].attr.name = "als_managed";
2350
	sony_als->attrs[0].attr.mode = S_IRUGO | S_IWUSR;
2351
	sony_als->attrs[0].show = sony_nc_als_managed_show;
2352
	sony_als->attrs[0].store = sony_nc_als_managed_store;
2353
	/* lux equivalent value */
2354
	sysfs_attr_init(&sony_als->attrs[1].attr);
2355
	sony_als->attrs[1].attr.name = "als_lux";
2356
	sony_als->attrs[1].attr.mode = S_IRUGO;
2357
	sony_als->attrs[1].show = sony_nc_als_lux_show;
2358
	/* ALS default parameters */
2359
	sysfs_attr_init(&sony_als->attrs[2].attr);
2360
	sony_als->attrs[2].attr.name = "als_defaults";
2361
	sony_als->attrs[2].attr.mode = S_IRUGO;
2362
	sony_als->attrs[2].show = sony_nc_als_parameters_show;
2363
	/* ALS default backlight levels */
2364
	sysfs_attr_init(&sony_als->attrs[3].attr);
2365
	sony_als->attrs[3].attr.name = "als_backlight_levels";
2366
	sony_als->attrs[3].attr.mode = S_IRUGO;
2367
	sony_als->attrs[3].show = sony_nc_als_parameters_show;
2368
	/* als backlight control */
2369
	sysfs_attr_init(&sony_als->attrs[4].attr);
2370
	sony_als->attrs[4].attr.name = "als_backlight";
2371
	sony_als->attrs[4].attr.mode = S_IRUGO | S_IWUSR;
2372
	sony_als->attrs[4].show = sony_nc_als_backlight_show;
2373
	sony_als->attrs[4].store = sony_nc_als_backlight_store;
2374
2375
	sony_als->attrs_num = 5;
2376
	/* end mandatory sys interface */
2377
2378
	if (sony_als->ops->get_power || sony_als->ops->set_power) {
2379
		int i = sony_als->attrs_num++;
2380
2381
		/* als power control */
2382
		sysfs_attr_init(&sony_als->attrs[i].attr);
2383
		sony_als->attrs[i].attr.name = "als_power";
2384
		sony_als->attrs[i].attr.mode = S_IRUGO | S_IWUSR;
2385
		sony_als->attrs[i].show = sony_nc_als_power_show;
2386
		sony_als->attrs[i].store = sony_nc_als_power_store;
2387
	}
2388
2389
	if (sony_als->ops->get_kelvin) {
2390
		int i = sony_als->attrs_num++;
2391
2392
		/* light temperature */
2393
		sysfs_attr_init(&sony_als->attrs[i].attr);
2394
		sony_als->attrs[i].attr.name = "als_kelvin";
2395
		sony_als->attrs[i].attr.mode = S_IRUGO;
2396
		sony_als->attrs[i].show = sony_nc_als_kelvin_show;
2397
	}
2398
2399
	/* everything or nothing, otherwise unable to control the ALS */
2400
	for (; i < sony_als->attrs_num; i++) {
2401
		if (device_create_file(&pd->dev, &sony_als->attrs[i]))
2402
			goto attrserror;
2403
	}
2404
2405
	return 0;
2406
2407
attrserror:
2408
	for (; i > 0; i--)
2409
		device_remove_file(&pd->dev, &sony_als->attrs[i]);
2410
nosensor:
2411
	kfree(sony_als);
2412
	sony_als = NULL;
2413
2414
	return -1;
2415
}
2416
2417
static void sony_nc_als_resume(void)
2418
{
2419
	if (sony_als->managed) /* it restores the power state too */
2420
		sony_nc_als_managed_set(1);
2421
	else if (sony_als->power)
2422
		sony_nc_als_power_set(1);
2423
}
2424
2425
static int sony_nc_als_cleanup(struct platform_device *pd)
2426
{
2427
	if (sony_als) {
2428
		int i;
2429
2430
		for (i = 0; i < sony_als->attrs_num; i++)
2431
			device_remove_file(&pd->dev, &sony_als->attrs[i]);
2432
2433
		/* disable the events notification */
2434
		if (sony_als->managed)
2435
			if (sony_nc_als_managed_set(0))
2436
				pr_info("ALS notifications disable failed\n");
2437
2438
		if (sony_als->power)
2439
			if (sony_nc_als_power_set(0))
2440
				pr_info("ALS power off failed\n");
2441
2442
		if (sony_als->ops->exit)
2443
			if (sony_als->ops->exit())
2444
				pr_info("ALS device cleaning failed\n");
2445
2446
		kfree(sony_als);
2447
		sony_als = NULL;
2448
	}
2449
2450
	return 0;
2451
}
2452
/*	end ALS code	*/
2453
2454
/* Keyboard backlight feature */
2455
static struct sony_kbdbl_data {
2456
	unsigned int handle;
2457
	unsigned int base;
2458
	unsigned int mode;
2459
	unsigned int timeout;
2460
	struct device_attribute mode_attr;
2461
	struct device_attribute timeout_attr;
2462
} *sony_kbdbl;
2463
2464
static int __sony_nc_kbd_backlight_mode_set(u8 value)
2465
{
2466
	unsigned int result;
2467
2468
	if (value > 1)
2469
		return -EINVAL;
2470
2471
	if (sony_call_snc_handle(sony_kbdbl->handle, (value << 0x10) |
2472
				(sony_kbdbl->base), &result))
2473
		return -EIO;
2474
2475
	sony_kbdbl->mode = value;
2476
2477
	/* Try to turn the light on/off immediately */
2478
	sony_call_snc_handle(sony_kbdbl->handle, (value << 0x10) |
2479
				(sony_kbdbl->base + 0x100), &result);
2480
2481
	return 0;
2482
}
2483
2484
static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev,
2485
		struct device_attribute *attr,
2486
		const char *buffer, size_t count)
2487
{
2488
	int ret = 0;
2489
	unsigned long value;
2490
2491
	if (count > 31)
2492
		return -EINVAL;
2493
2494
	if (strict_strtoul(buffer, 10, &value))
2495
		return -EINVAL;
2496
2497
	ret = __sony_nc_kbd_backlight_mode_set(value);
2498
	if (ret < 0)
2499
		return ret;
2500
2501
	return count;
2502
}
2503
2504
static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev,
2505
		struct device_attribute *attr, char *buffer)
2506
{
2507
	ssize_t count = 0;
2508
2509
	count = snprintf(buffer, PAGE_SIZE, "%d\n", sony_kbdbl->mode);
2510
2511
	return count;
2512
}
2513
2514
static int __sony_nc_kbd_backlight_timeout_set(u8 value)
2515
{
2516
	unsigned int result;
2517
2518
	if (value > 3)
2519
		return -EINVAL;
2520
2521
	if (sony_call_snc_handle(sony_kbdbl->handle, (value << 0x10) |
2522
				(sony_kbdbl->base + 0x200), &result))
2523
		return -EIO;
2524
2525
	sony_kbdbl->timeout = value;
2526
2527
	return 0;
2528
}
2529
2530
static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev,
2531
		struct device_attribute *attr,
2532
		const char *buffer, size_t count)
2533
{
2534
	int ret = 0;
2535
	unsigned long value;
2536
2537
	if (count > 31)
2538
		return -EINVAL;
2539
2540
	if (strict_strtoul(buffer, 10, &value))
2541
		return -EINVAL;
2542
2543
	ret = __sony_nc_kbd_backlight_timeout_set(value);
2544
	if (ret < 0)
2545
		return ret;
2546
2547
	return count;
2548
}
2549
2550
static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev,
2551
		struct device_attribute *attr, char *buffer)
2552
{
2553
	ssize_t count = 0;
2554
2555
	count = snprintf(buffer, PAGE_SIZE, "%d\n", sony_kbdbl->timeout);
2556
2557
	return count;
2558
}
2559
2560
static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
2561
					unsigned int handle)
2562
{
2563
	unsigned int result, base_cmd;
2564
	bool found = false;
2565
2566
	/* verify the kbd backlight presence, some models do not have it */
2567
	if (handle == 0x0137) {
2568
		if (sony_call_snc_handle(handle, 0x0B00, &result))
2569
			return -EIO;
2570
2571
		found = !!(result & 0x02);
2572
		base_cmd = 0x0C00;
2573
	} else {
2574
		if (sony_call_snc_handle(handle, 0x0100, &result))
2575
			return -EIO;
2576
2577
		found = result & 0x01;
2578
		base_cmd = 0x4000;
2579
	}
2580
2581
	if (!found) {
2582
		dprintk("no backlight keyboard found\n");
2583
		return 0;
2584
	}
2585
2586
	sony_kbdbl = kzalloc(sizeof(*sony_kbdbl), GFP_KERNEL);
2587
	if (!sony_kbdbl)
2588
		return -ENOMEM;
2589
2590
	sysfs_attr_init(&sony_kbdbl->mode_attr.attr);
2591
	sony_kbdbl->mode_attr.attr.name = "kbd_backlight";
2592
	sony_kbdbl->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
2593
	sony_kbdbl->mode_attr.show = sony_nc_kbd_backlight_mode_show;
2594
	sony_kbdbl->mode_attr.store = sony_nc_kbd_backlight_mode_store;
2595
2596
	sysfs_attr_init(&sony_kbdbl->timeout_attr.attr);
2597
	sony_kbdbl->timeout_attr.attr.name = "kbd_backlight_timeout";
2598
	sony_kbdbl->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
2599
	sony_kbdbl->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
2600
	sony_kbdbl->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
2601
2602
	if (device_create_file(&pd->dev, &sony_kbdbl->mode_attr))
2603
		goto outkzalloc;
2604
2605
	if (device_create_file(&pd->dev, &sony_kbdbl->timeout_attr))
2606
		goto outmode;
2607
2608
	sony_kbdbl->handle = handle;
2609
	sony_kbdbl->base = base_cmd;
2610
2611
	__sony_nc_kbd_backlight_mode_set(kbd_backlight);
2612
	__sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
2613
2614
	return 0;
2615
2616
outmode:
2617
	device_remove_file(&pd->dev, &sony_kbdbl->mode_attr);
2618
outkzalloc:
2619
	kfree(sony_kbdbl);
2620
	sony_kbdbl = NULL;
2621
	return -1;
2622
}
2623
2624
static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
2625
{
2626
	if (sony_kbdbl) {
2627
		unsigned int result;
2628
2629
		device_remove_file(&pd->dev, &sony_kbdbl->mode_attr);
2630
		device_remove_file(&pd->dev, &sony_kbdbl->timeout_attr);
2631
2632
		/* restore the default hw behaviour */
2633
		sony_call_snc_handle(sony_kbdbl->handle,
2634
				sony_kbdbl->base | 0x10000, &result);
2635
		sony_call_snc_handle(sony_kbdbl->handle,
2636
				sony_kbdbl->base + 0x200, &result);
2637
2638
		kfree(sony_kbdbl);
2639
		sony_kbdbl = NULL;
2640
	}
2641
	return 0;
2642
}
2643
2644
static void sony_nc_kbd_backlight_resume(void)
2645
{
2646
	unsigned int result;
2647
2648
	if (!sony_kbdbl)
2649
		return;
2650
2651
	if (sony_kbdbl->mode == 0)
2652
		sony_call_snc_handle(sony_kbdbl->handle,
2653
				sony_kbdbl->base, &result);
2654
2655
	if (sony_kbdbl->timeout != 0)
2656
		sony_call_snc_handle(sony_kbdbl->handle,
2657
				(sony_kbdbl->base + 0x200) |
2658
				(sony_kbdbl->timeout << 0x10), &result);
2659
}
2660
2661
/*	GSensor, HDD Shock Protection	*/
2662
enum axis {
2663
	X_AXIS = 4,	/* frontal  */
2664
	Y_AXIS,		/* lateral  */
2665
	Z_AXIS		/* vertical */
2666
};
2667
2668
static struct sony_gsensor_device {
2669
	unsigned int handle;
2670
	unsigned int attrs_num;
2671
	struct device_attribute *attrs;
2672
} *sony_gsensor;
2673
2674
/* the EC uses pin #11 of the SATA power connector to command the
2675
   immediate idle feature; however some drives do not implement it
2676
   and pin #11 is NC. Let's verify, otherwise no automatic
2677
   protection is possible by the hardware
2678
*/
2679
static int sony_nc_gsensor_support_get(unsigned int *support)
2680
{
2681
	unsigned int result;
2682
2683
	if (sony_call_snc_handle(sony_gsensor->handle, 0x0200, &result))
2684
		return -EIO;
2685
2686
	*support = sony_gsensor->handle == 0x0134
2687
			? !!(result & 0x20)
2688
			: !!(result & 0x01);
2689
2690
	return 0;
2691
}
2692
2693
static int sony_nc_gsensor_status_set(int value)
2694
{
2695
	unsigned int result, capable, reg, arg;
2696
	bool update = false;
2697
2698
	if (sony_nc_gsensor_support_get(&capable))
2699
		return -EIO;
2700
2701
	if (!capable)
2702
		pr_warn("hardware protection not available, the HDD"
2703
			       " do not support this feature\n");
2704
2705
	/* do not return immediately even though there is no HW
2706
	 * capability, userspace can thus receive the shock
2707
	 * notifications and call the ATA7 immediate idle command to
2708
	 * unload the heads. Just return after enabling notifications
2709
	*/
2710
	reg = sony_gsensor->handle == 0x0134 ?
2711
		(!value << 0x08) : (value << 0x10);
2712
2713
	if (sony_call_snc_handle(sony_gsensor->handle, reg, &result))
2714
		return -EIO;
2715
2716
	if (!capable)
2717
		return 0;
2718
2719
	/* if the requested protection setting is different
2720
	   from the current one
2721
	*/
2722
	reg = sony_gsensor->handle == 0x0134 ? 0x0200 : 0x0400;
2723
	if (sony_call_snc_handle(sony_gsensor->handle, reg, &result))
2724
		return -EIO;
2725
2726
	if (sony_gsensor->handle == 0x0134) {
2727
		if (!!(result & 0x04) != value) {
2728
			arg = (result & 0x1B) | (value << 0x02);
2729
			update = true;
2730
		}
2731
	} else {
2732
		if ((result & 0x01) != value) {
2733
			arg = value;
2734
			update = true;
2735
		}
2736
	}
2737
2738
	if (update && sony_call_snc_handle(sony_gsensor->handle,
2739
			(arg << 0x10) | 0x0300, &result))
2740
		return -EIO;
2741
2742
	return 0;
2743
}
2744
2745
static int sony_nc_gsensor_axis_get(enum axis name)
2746
{
2747
	unsigned int result;
2748
2749
	if (sony_call_snc_handle(sony_gsensor->handle, name << 0x08, &result))
2750
		return -EIO;
2751
2752
	return result;
2753
}
2754
2755
/*			G sensor sys interface			*/
2756
static ssize_t sony_nc_gsensor_type_show(struct device *dev,
2757
		struct device_attribute *attr, char *buffer)
2758
{
2759
	ssize_t count = 0;
2760
	unsigned int result;
2761
2762
	if (sony_call_snc_handle(sony_gsensor->handle, 0x0200, &result))
2763
		return -EIO;
2764
2765
	count = snprintf(buffer, PAGE_SIZE, "%d\n", (result >> 0x03) & 0x03);
2766
2767
	return count;
2768
}
2769
2770
static ssize_t sony_nc_gsensor_type_store(struct device *dev,
2771
		struct device_attribute *attr,
2772
		const char *buffer, size_t count)
2773
{
2774
	/*
2775
	 *  axis out type control file:
2776
	 *  0: raw values, 1: acc values 2: threshold values
2777
	 */
2778
	unsigned int result;
2779
	unsigned long value;
2780
2781
	/* sanity checks and conversion */
2782
	if (count > 31 || strict_strtoul(buffer, 10, &value) || value > 2)
2783
		return -EINVAL;
2784
2785
	value <<= 0x03;
2786
2787
	/* retrieve the current state / settings */
2788
	if (sony_call_snc_handle(sony_gsensor->handle, 0x0200, &result))
2789
		return -EIO;
2790
2791
	if ((result & 0x18) != value) {
2792
		/* the last 3 bits need to be preserved */
2793
		value |= (result & 0x07);
2794
2795
		if (sony_call_snc_handle(sony_gsensor->handle,
2796
				(value << 0x10) | 0x0300, &result))
2797
				return -EIO;
2798
	}
2799
2800
	return count;
2801
}
2802
2803
static ssize_t sony_nc_gsensor_axis_show(struct device *dev,
2804
		struct device_attribute *attr, char *buffer)
2805
{
2806
	ssize_t count = 0;
2807
	unsigned int result;
2808
	enum axis arg;
2809
2810
	/* file being read for axis selection */
2811
	if (!strcmp(attr->attr.name, "gsensor_xval"))
2812
		arg = X_AXIS;
2813
	else if (!strcmp(attr->attr.name, "gsensor_yval"))
2814
		arg = Y_AXIS;
2815
	else if (!strcmp(attr->attr.name, "gsensor_zval"))
2816
		arg = Z_AXIS;
2817
	else
2818
		return count;
2819
2820
	result = sony_nc_gsensor_axis_get(arg);
2821
	if (result < 0)
2822
		return -EIO;
2823
2824
	count = snprintf(buffer, PAGE_SIZE, "%d\n", result);
2825
2826
	return count;
2827
}
2828
2829
static ssize_t sony_nc_gsensor_status_show(struct device *dev,
2830
		struct device_attribute *attr, char *buffer)
2831
{
2832
	ssize_t count = 0;
2833
	unsigned int result;
2834
2835
	if (sony_gsensor->handle == 0x0134) {
2836
		if (sony_call_snc_handle(sony_gsensor->handle, 0x0200,
2837
					&result))
2838
			return -EIO;
2839
2840
		result = !!(result & 0x04);
2841
	} else {
2842
		if (sony_call_snc_handle(sony_gsensor->handle, 0x0400,
2843
					&result))
2844
			return -EIO;
2845
2846
		result &= 0x01;
2847
	}
2848
2849
	count = snprintf(buffer, PAGE_SIZE, "%d\n", result);
2850
2851
	return count;
2852
}
2853
2854
static ssize_t sony_nc_gsensor_status_store(struct device *dev,
2855
		struct device_attribute *attr,
2856
		const char *buffer, size_t count)
2857
{
2858
	int ret;
2859
	unsigned long value;
2860
2861
	if (count > 31)
2862
		return -EINVAL;
2863
	if (strict_strtoul(buffer, 10, &value) || value > 1)
2864
		return -EINVAL;
2865
2866
	ret = sony_nc_gsensor_status_set(value);
2867
	if (ret)
2868
		return ret;
2869
2870
	return count;
2871
}
2872
2873
static ssize_t sony_nc_gsensor_sensitivity_show(struct device *dev,
2874
		struct device_attribute *attr, char *buffer)
2875
{
2876
	ssize_t count = 0;
2877
	unsigned int result;
2878
2879
	if (sony_call_snc_handle(sony_gsensor->handle, 0x0200, &result))
2880
		return -EINVAL;
2881
2882
	count = snprintf(buffer, PAGE_SIZE, "%d\n", result & 0x03);
2883
	return count;
2884
}
2885
2886
static ssize_t sony_nc_gsensor_sensitivity_store(struct device *dev,
2887
		struct device_attribute *attr,
2888
		const char *buffer, size_t count)
2889
{
2890
	unsigned int result;
2891
	unsigned long value;
2892
2893
	if (count > 31)
2894
		return -EINVAL;
2895
	if (strict_strtoul(buffer, 10, &value) || value > 2)
2896
		return -EINVAL;
2897
2898
	/* retrieve the other parameters to be stored as well */
2899
	if (sony_call_snc_handle(sony_gsensor->handle, 0x0200, &result))
2900
		return -EIO;
2901
	value |= (result & 0x1C); /* preserve only the needed bits */
2902
2903
	if (sony_call_snc_handle(sony_gsensor->handle, (value << 0x10)
2904
		| 0x0300, &result))
2905
		return -EIO;
2906
2907
	return count;
2908
}
2909
2910
static int sony_nc_gsensor_setup(struct platform_device *pd,
2911
					unsigned int handle)
2912
{
2913
	int i, enable, support;
2914
2915
	sony_gsensor = kzalloc(sizeof(struct sony_gsensor_device), GFP_KERNEL);
2916
	if (!sony_gsensor)
2917
		return -ENOMEM;
2918
2919
	sony_gsensor->handle = handle;
2920
	sony_gsensor->attrs_num = handle == 0x0134 ? 6 : 1;
2921
2922
	sony_gsensor->attrs = kzalloc(sizeof(struct device_attribute)
2923
				* sony_gsensor->attrs_num, GFP_KERNEL);
2924
	if (!sony_gsensor->attrs)
2925
		goto memerror;
2926
2927
	/* check the storing device support */
2928
	if (sony_nc_gsensor_support_get(&support))
2929
		return -EIO;
2930
2931
	/* enable the HDD protection and notification by default
2932
	   when hardware driven protection is possible */
2933
	enable = support ? 1 : force_shock_notifications;
2934
	if (sony_nc_gsensor_status_set(enable))
2935
		if (enable)
2936
			pr_warn("failed to enable the HDD shock protection\n");
2937
2938
	/* activation control	*/
2939
	sysfs_attr_init(&sony_gsensor->attrs[0].attr);
2940
	sony_gsensor->attrs[0].attr.name = "gsensor_protection";
2941
	sony_gsensor->attrs[0].attr.mode = S_IRUGO | S_IWUSR;
2942
	sony_gsensor->attrs[0].show = sony_nc_gsensor_status_show;
2943
	sony_gsensor->attrs[0].store = sony_nc_gsensor_status_store;
2944
2945
	if (sony_gsensor->attrs_num > 1) {
2946
		/* sensitivity selection */
2947
		sysfs_attr_init(&sony_gsensor->attrs[1].attr);
2948
		sony_gsensor->attrs[1].attr.name = "gsensor_sensitivity";
2949
		sony_gsensor->attrs[1].attr.mode = S_IRUGO | S_IWUSR;
2950
		sony_gsensor->attrs[1].show = sony_nc_gsensor_sensitivity_show;
2951
		sony_gsensor->attrs[1].store =
2952
					sony_nc_gsensor_sensitivity_store;
2953
		/* x/y/z output selection */
2954
		sysfs_attr_init(&sony_gsensor->attrs[2].attr);
2955
		sony_gsensor->attrs[2].attr.name = "gsensor_val_type";
2956
		sony_gsensor->attrs[2].attr.mode = S_IRUGO | S_IWUSR;
2957
		sony_gsensor->attrs[2].show = sony_nc_gsensor_type_show;
2958
		sony_gsensor->attrs[2].store = sony_nc_gsensor_type_store;
2959
2960
		sysfs_attr_init(&sony_gsensor->attrs[3].attr);
2961
		sony_gsensor->attrs[3].attr.name = "gsensor_xval";
2962
		sony_gsensor->attrs[3].attr.mode = S_IRUGO;
2963
		sony_gsensor->attrs[3].show = sony_nc_gsensor_axis_show;
2964
2965
		sysfs_attr_init(&sony_gsensor->attrs[4].attr);
2966
		sony_gsensor->attrs[4].attr.name = "gsensor_yval";
2967
		sony_gsensor->attrs[4].attr.mode = S_IRUGO;
2968
		sony_gsensor->attrs[4].show = sony_nc_gsensor_axis_show;
2969
2970
		sysfs_attr_init(&sony_gsensor->attrs[5].attr);
2971
		sony_gsensor->attrs[5].attr.name = "gsensor_zval";
2972
		sony_gsensor->attrs[5].attr.mode = S_IRUGO;
2973
		sony_gsensor->attrs[5].show = sony_nc_gsensor_axis_show;
2974
	}
2975
2976
	for (i = 0; i < sony_gsensor->attrs_num; i++) {
2977
		if (device_create_file(&pd->dev, &sony_gsensor->attrs[i]))
2978
			goto attrserror;
2979
	}
2980
2981
	return 0;
2982
2983
attrserror:
2984
	for (; i > 0; i--)
2985
		device_remove_file(&pd->dev, &sony_gsensor->attrs[i]);
2986
2987
	kfree(sony_gsensor->attrs);
2988
memerror:
2989
	kfree(sony_gsensor);
2990
	sony_gsensor = NULL;
2991
2992
	return -1;
2993
}
2994
2995
static int sony_nc_gsensor_cleanup(struct platform_device *pd)
2996
{
2997
	if (sony_gsensor) {
2998
		unsigned int i, result, reg;
2999
3000
		for (i = 0; i < sony_gsensor->attrs_num; i++)
3001
			device_remove_file(&pd->dev, &sony_gsensor->attrs[i]);
3002
3003
		/* disable the event generation,
3004
		 * preserve any other setting
3005
		 */
3006
		reg = sony_gsensor->handle == 0x0134 ? 0x0100 : 0x0000;
3007
3008
		sony_call_snc_handle(sony_gsensor->handle, reg, &result);
3009
3010
		kfree(sony_gsensor->attrs);
3011
		kfree(sony_gsensor);
3012
		sony_gsensor = NULL;
3013
	}
3014
3015
	return 0;
3016
}
3017
/*			end G sensor code			*/
3018
3019
static struct sony_battcare_data {
3020
	unsigned int handle;
3021
	struct device_attribute attrs[2];
3022
} *sony_battcare;
3023
3024
static ssize_t sony_nc_battery_care_limit_store(struct device *dev,
3025
		struct device_attribute *attr,
3026
		const char *buffer, size_t count)
3027
{
3028
	unsigned int result, cmd;
3029
	unsigned long value;
3030
3031
	if (count > 31)
3032
		return -EINVAL;
3033
	if (strict_strtoul(buffer, 10, &value))
3034
		return -EINVAL;
3035
3036
	/*  limit values (2 bits):
3037
	 *  00 - none
3038
	 *  01 - 80%
3039
	 *  10 - 50%
3040
	 *  11 - 100%
3041
	 *
3042
	 *  bit 0: 0 disable BCL, 1 enable BCL
3043
	 *  bit 1: 1 tell to store the battery limit (see bits 6,7) too
3044
	 *  bits 2,3: reserved
3045
	 *  bits 4,5: store the limit into the EC
3046
	 *  bits 6,7: store the limit into the battery
3047
	 */
3048
3049
	/*
3050
	 * handle 0x0115 should allow storing on battery too;
3051
	 * handle 0x0136 same as 0x0115 + health status;
3052
	 * handle 0x013f, same as 0x0136 but no storing on the battery
3053
	 *
3054
	 * Store only inside the EC for now, regardless the handle number
3055
	 */
3056
	switch (value) {
3057
	case 0:	/* disable */
3058
		cmd = 0x00;
3059
		break;
3060
	case 1: /* enable, 80% charge limit */
3061
		cmd = 0x11;
3062
		break;
3063
	case 2: /* enable, 50% charge limit */
3064
		cmd = 0x21;
3065
		break;
3066
	default:
3067
		return -EINVAL;
3068
	}
3069
3070
	if (sony_call_snc_handle(sony_battcare->handle, (cmd << 0x10) | 0x0100,
3071
				&result))
3072
		return -EIO;
3073
3074
	return count;
3075
}
3076
3077
static ssize_t sony_nc_battery_care_limit_show(struct device *dev,
3078
		struct device_attribute *attr, char *buffer)
3079
{
3080
	ssize_t count = 0;
3081
	unsigned int result, status;
3082
3083
	if (sony_call_snc_handle(sony_battcare->handle, 0x0000, &result))
3084
		return -EIO;
3085
3086
	/* if disabled 0, else take the limit bits */
3087
	status = !(result & 0x01) ? 0 : ((result & 0x30) >> 0x04);
3088
3089
	count = snprintf(buffer, PAGE_SIZE, "%d\n", status);
3090
	return count;
3091
}
3092
3093
static ssize_t sony_nc_battery_care_health_show(struct device *dev,
3094
		struct device_attribute *attr, char *buffer)
3095
{
3096
	ssize_t count = 0;
3097
	unsigned int health;
3098
3099
	if (sony_call_snc_handle(sony_battcare->handle, 0x0200, &health))
3100
		return -EIO;
3101
3102
	count = snprintf(buffer, PAGE_SIZE, "%d\n", health & 0xff);
3103
3104
	return count;
3105
}
3106
3107
static int sony_nc_battery_care_setup(struct platform_device *pd,
3108
					unsigned int handle)
3109
{
3110
	sony_battcare = kzalloc(sizeof(struct sony_battcare_data), GFP_KERNEL);
3111
	if (!sony_battcare)
3112
		return -ENOMEM;
3113
3114
	sony_battcare->handle = handle;
3115
3116
	sysfs_attr_init(&sony_battcare->attrs[0].attr);
3117
	sony_battcare->attrs[0].attr.name = "battery_care_limiter";
3118
	sony_battcare->attrs[0].attr.mode = S_IRUGO | S_IWUSR;
3119
	sony_battcare->attrs[0].show = sony_nc_battery_care_limit_show;
3120
	sony_battcare->attrs[0].store = sony_nc_battery_care_limit_store;
3121
3122
	if (device_create_file(&pd->dev, &sony_battcare->attrs[0]))
3123
		goto outkzalloc;
3124
3125
	if (handle == 0x0115) /* no health indication */
3126
		return 0;
3127
3128
	sysfs_attr_init(&sony_battcare->attrs[1].attr);
3129
	sony_battcare->attrs[1].attr.name = "battery_care_health";
3130
	sony_battcare->attrs[1].attr.mode = S_IRUGO;
3131
	sony_battcare->attrs[1].show = sony_nc_battery_care_health_show;
3132
3133
	if (device_create_file(&pd->dev, &sony_battcare->attrs[1]))
3134
		goto outlimiter;
3135
3136
	return 0;
3137
3138
outlimiter:
3139
	device_remove_file(&pd->dev, &sony_battcare->attrs[0]);
3140
outkzalloc:
3141
	kfree(sony_battcare);
3142
	sony_battcare = NULL;
3143
3144
	return -1;
3145
}
3146
3147
static int sony_nc_battery_care_cleanup(struct platform_device *pd)
3148
{
3149
	if (sony_battcare) {
3150
		device_remove_file(&pd->dev, &sony_battcare->attrs[0]);
3151
		if (sony_battcare->handle != 0x0115)
3152
			device_remove_file(&pd->dev, &sony_battcare->attrs[1]);
3153
3154
		kfree(sony_battcare);
3155
		sony_battcare = NULL;
3156
	}
3157
3158
	return 0;
3159
}
3160
3161
static struct sony_thermal_data {
3162
	unsigned int mode;
3163
	unsigned int profiles;
3164
	struct device_attribute mode_attr;
3165
	struct device_attribute profiles_attr;
3166
} *sony_thermal;
3167
3168
static int sony_nc_thermal_mode_set(unsigned int profile)
3169
{
3170
	unsigned int cmd, result;
3171
3172
	/* to avoid the 1 value hole when only 2 profiles are available */
3173
	switch (profile) {
3174
	case 1: /* performance */
3175
		cmd = 2;
3176
		break;
3177
	case 2: /* silent */
3178
		cmd = 1;
3179
		break;
3180
	default: /* balanced */
3181
		cmd = 0;
3182
		break;
3183
	}
3184
3185
	if (sony_call_snc_handle(0x0122, cmd << 0x10 | 0x0200, &result))
3186
		return -EIO;
3187
3188
	sony_thermal->mode = profile;
3189
3190
	return 0;
3191
}
3192
3193
static int sony_nc_thermal_mode_get(unsigned int *profile)
3194
{
3195
	unsigned int result;
3196
3197
	if (sony_call_snc_handle(0x0122, 0x0100, &result))
3198
		return -EIO;
3199
3200
	/* to avoid the 1 value hole when only 2 profiles are available */
3201
	switch (result & 0xff) {
3202
	case 2: /* performance */
3203
		*profile = 1;
3204
		break;
3205
	case 1: /* silent */
3206
		*profile = 2;
3207
		break;
3208
	default: /* balanced */
3209
		*profile = 0;
3210
		break;
3211
	}
3212
3213
	return 0;
3214
}
3215
3216
static ssize_t sony_nc_thermal_profiles_show(struct device *dev,
3217
		struct device_attribute *attr, char *buffer)
3218
{
3219
	return snprintf(buffer, PAGE_SIZE, "%u\n", sony_thermal->profiles);
3220
}
3221
3222
static ssize_t sony_nc_thermal_mode_store(struct device *dev,
3223
		struct device_attribute *attr,
3224
		const char *buffer, size_t count)
3225
{
3226
	unsigned long value;
3227
3228
	if (count > 31)
3229
		return -EINVAL;
3230
	if (strict_strtoul(buffer, 10, &value) ||
3231
		value > (sony_thermal->profiles - 1))
3232
		return -EINVAL;
3233
3234
	if (sony_nc_thermal_mode_set(value))
3235
		return -EIO;
3236
3237
	return count;
3238
}
3239
3240
static ssize_t sony_nc_thermal_mode_show(struct device *dev,
3241
		struct device_attribute *attr, char *buffer)
3242
{
3243
	ssize_t count = 0;
3244
	unsigned int profile;
3245
3246
	if (sony_nc_thermal_mode_get(&profile))
3247
		return -EIO;
3248
3249
	count = snprintf(buffer, PAGE_SIZE, "%d\n", profile);
3250
3251
	return count;
3252
}
3253
3254
static int sony_nc_thermal_setup(struct platform_device *pd)
3255
{
3256
	sony_thermal = kzalloc(sizeof(struct sony_thermal_data), GFP_KERNEL);
3257
	if (!sony_thermal)
3258
		return -ENOMEM;
3259
3260
	if (sony_call_snc_handle(0x0122, 0x0000, &sony_thermal->profiles)) {
3261
		pr_warn("unable to retrieve the available profiles\n");
3262
		goto outkzalloc;
3263
	}
3264
3265
	if (sony_nc_thermal_mode_get(&sony_thermal->mode)) {
3266
		pr_warn("unable to retrieve the current profile");
3267
		goto outkzalloc;
3268
	}
3269
3270
	sysfs_attr_init(&sony_thermal->profiles_attr.attr);
3271
	sony_thermal->profiles_attr.attr.name = "thermal_profiles";
3272
	sony_thermal->profiles_attr.attr.mode = S_IRUGO;
3273
	sony_thermal->profiles_attr.show = sony_nc_thermal_profiles_show;
3274
3275
	sysfs_attr_init(&sony_thermal->mode_attr.attr);
3276
	sony_thermal->mode_attr.attr.name = "thermal_control";
3277
	sony_thermal->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
3278
	sony_thermal->mode_attr.show = sony_nc_thermal_mode_show;
3279
	sony_thermal->mode_attr.store = sony_nc_thermal_mode_store;
3280
3281
	if (device_create_file(&pd->dev, &sony_thermal->profiles_attr))
3282
		goto outkzalloc;
3283
3284
	if (device_create_file(&pd->dev, &sony_thermal->mode_attr))
3285
		goto outprofiles;
3286
3287
	return 0;
3288
3289
outprofiles:
3290
	device_remove_file(&pd->dev, &sony_thermal->profiles_attr);
3291
outkzalloc:
3292
	kfree(sony_thermal);
3293
	sony_thermal = NULL;
3294
	return -1;
3295
}
3296
3297
static int sony_nc_thermal_cleanup(struct platform_device *pd)
3298
{
3299
	if (sony_thermal) {
3300
		device_remove_file(&pd->dev, &sony_thermal->profiles_attr);
3301
		device_remove_file(&pd->dev, &sony_thermal->mode_attr);
3302
		kfree(sony_thermal);
3303
		sony_thermal = NULL;
3304
	}
3305
3306
	return 0;
3307
}
3308
3309
static void sony_nc_thermal_resume(void)
3310
{
3311
	unsigned int status;
3312
3313
	sony_nc_thermal_mode_get(&status);
3314
3315
	if (status != sony_thermal->mode)
3316
		sony_nc_thermal_mode_set(sony_thermal->mode);
3317
}
3318
3319
static struct device_attribute *sony_lid;
3320
3321
static ssize_t sony_nc_lid_resume_store(struct device *dev,
3322
		struct device_attribute *attr,
3323
		const char *buffer, size_t count)
3324
{
3325
	unsigned int result;
3326
	unsigned long value;
3327
3328
	if (count > 31)
3329
		return -EINVAL;
3330
	if (strict_strtoul(buffer, 10, &value) || value > 3)
3331
		return -EINVAL;
3332
3333
	/* 00 <- disabled
3334
	   01 <- resume from S4
3335
	   10 <- resume from S3
3336
	   11 <- resume from S4 and S3
3337
	*/
3338
	/* we must set bit 1 and 2 (bit 0 is for S5), so shift one bit more */
3339
	if (sony_call_snc_handle(0x0119, value << 0x11 | 0x0100, &result))
3340
		return -EIO;
3341
3342
	return count;
3343
}
3344
3345
static ssize_t sony_nc_lid_resume_show(struct device *dev,
3346
		struct device_attribute *attr, char *buffer)
3347
{
3348
	ssize_t count = 0;
3349
	unsigned int result;
3350
3351
	if (sony_call_snc_handle(0x0119, 0x0000, &result))
3352
		return -EIO;
3353
3354
	count = snprintf(buffer, PAGE_SIZE, "%d\n", (result >> 1) & 0x03);
3355
3356
	return count;
3357
}
3358
3359
static int sony_nc_lid_resume_setup(struct platform_device *pd)
3360
{
3361
	sony_lid = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
3362
	if (!sony_lid)
3363
		return -ENOMEM;
3364
3365
	sysfs_attr_init(&sony_lid->attr);
3366
	sony_lid->attr.name = "lid_resume_control";
3367
	sony_lid->attr.mode = S_IRUGO | S_IWUSR;
3368
	sony_lid->show = sony_nc_lid_resume_show;
3369
	sony_lid->store = sony_nc_lid_resume_store;
3370
3371
	if (device_create_file(&pd->dev, sony_lid)) {
3372
		kfree(sony_lid);
3373
		sony_lid = NULL;
3374
		return -1;
3375
	}
3376
3377
	return 0;
3378
}
3379
3380
static int sony_nc_lid_resume_cleanup(struct platform_device *pd)
3381
{
3382
	if (sony_lid) {
3383
		device_remove_file(&pd->dev, sony_lid);
3384
		kfree(sony_lid);
3385
		sony_lid = NULL;
3386
	}
3387
3388
	return 0;
3389
}
3390
3391
static struct device_attribute *sony_hsc;
3392
3393
static ssize_t sony_nc_highspeed_charging_store(struct device *dev,
3394
		struct device_attribute *attr,
3395
		const char *buffer, size_t count)
3396
{
3397
	unsigned int result;
3398
	unsigned long value;
3399
3400
	if (count > 31)
3401
		return -EINVAL;
3402
	if (strict_strtoul(buffer, 10, &value) || value > 1)
3403
		return -EINVAL;
3404
3405
	if (sony_call_snc_handle(0x0131, value << 0x10 | 0x0200, &result))
3406
		return -EIO;
3407
3408
	return count;
3409
}
3410
3411
static ssize_t sony_nc_highspeed_charging_show(struct device *dev,
3412
		struct device_attribute *attr, char *buffer)
3413
{
3414
	ssize_t count = 0;
3415
	unsigned int result;
3416
3417
	if (sony_call_snc_handle(0x0131, 0x0100, &result))
3418
		return -EIO;
3419
3420
	count = snprintf(buffer, PAGE_SIZE, "%d\n", result & 0x01);
3421
3422
	return count;
3423
}
3424
3425
static int sony_nc_highspeed_charging_setup(struct platform_device *pd)
3426
{
3427
	unsigned int result;
3428
3429
	if (sony_call_snc_handle(0x0131, 0x0000, &result) || !(result & 0x01)) {
3430
		pr_info("no High Speed Charging capability found\n");
3431
		return 0;
3432
	}
3433
3434
	sony_hsc = kzalloc(sizeof(struct device_attribute), GFP_KERNEL);
3435
	if (!sony_hsc)
3436
		return -ENOMEM;
3437
3438
	sysfs_attr_init(&sony_hsc->attr);
3439
	sony_hsc->attr.name = "battery_highspeed_charging";
3440
	sony_hsc->attr.mode = S_IRUGO | S_IWUSR;
3441
	sony_hsc->show = sony_nc_highspeed_charging_show;
3442
	sony_hsc->store = sony_nc_highspeed_charging_store;
3443
3444
	if (device_create_file(&pd->dev, sony_hsc)) {
3445
		kfree(sony_hsc);
3446
		sony_hsc = NULL;
3447
		return -1;
3448
	}
3449
3450
	return 0;
3451
}
3452
3453
static int sony_nc_highspeed_charging_cleanup(struct platform_device *pd)
3454
{
3455
	if (sony_hsc) {
3456
		device_remove_file(&pd->dev, sony_hsc);
3457
		kfree(sony_hsc);
3458
		sony_hsc = NULL;
3459
	}
3460
3461
	return 0;
3462
}
3463
3464
static struct sony_tpad_device {
3465
	unsigned int handle;
3466
	struct device_attribute attr;
3467
} *sony_tpad;
3468
3469
static ssize_t sony_nc_touchpad_store(struct device *dev,
3470
		struct device_attribute *attr,
3471
		const char *buffer, size_t count)
3472
{
3473
	unsigned int result;
3474
	unsigned long value;
3475
3476
	if (count > 31)
3477
		return -EINVAL;
3478
	if (strict_strtoul(buffer, 10, &value) || value > 1)
3479
		return -EINVAL;
3480
3481
	/* sysfs: 0 disabled, 1 enabled; EC: 0 enabled, 1 disabled */
3482
	if (sony_call_snc_handle(sony_tpad->handle,
3483
				(!value << 0x10) | 0x100, &result))
3484
		return -EIO;
3485
3486
	return count;
3487
}
3488
3489
static ssize_t sony_nc_touchpad_show(struct device *dev,
3490
		struct device_attribute *attr, char *buffer)
3491
{
3492
	ssize_t count = 0;
3493
	unsigned int result;
3494
3495
	if (sony_call_snc_handle(sony_tpad->handle, 0x000, &result))
3496
		return -EINVAL;
3497
3498
	/* 1 tpad off, 0 tpad on */
3499
	count = snprintf(buffer, PAGE_SIZE, "%d\n", !(result & 0x01));
3500
	return count;
3501
}
3502
3503
static int sony_nc_touchpad_setup(struct platform_device *pd,
3504
					unsigned int handle)
3505
{
3506
	sony_tpad = kzalloc(sizeof(struct sony_tpad_device), GFP_KERNEL);
3507
	if (!sony_tpad)
3508
		return -ENOMEM;
3509
3510
	sony_tpad->handle = handle;
3511
3512
	sysfs_attr_init(&sony_tpad->attr.attr);
3513
	sony_tpad->attr.attr.name = "touchpad";
3514
	sony_tpad->attr.attr.mode = S_IRUGO | S_IWUSR;
3515
	sony_tpad->attr.show = sony_nc_touchpad_show;
3516
	sony_tpad->attr.store = sony_nc_touchpad_store;
3517
3518
	if (device_create_file(&pd->dev, &sony_tpad->attr)) {
3519
		kfree(sony_tpad);
3520
		sony_tpad = NULL;
3521
		return -1;
3522
	}
3523
3524
	return 0;
3525
}
3526
3527
static int sony_nc_touchpad_cleanup(struct platform_device *pd)
3528
{
3529
	if (sony_tpad) {
3530
		device_remove_file(&pd->dev, &sony_tpad->attr);
3531
		kfree(sony_tpad);
3532
		sony_tpad = NULL;
3533
	}
3534
3535
	return 0;
3536
}
3537
3538
#define SONY_FAN_HANDLE 0x0149
3539
#define FAN_SPEEDS_NUM	4	/* leave some more room */
3540
#define FAN_ATTRS_NUM	3
3541
static struct sony_fan_device {
3542
	unsigned int speeds_num;
3543
	unsigned int speeds[4];
3544
	struct device_attribute	attrs[3];
3545
} *sony_fan;
3546
3547
static ssize_t sony_nc_fan_control_store(struct device *dev,
3548
		struct device_attribute *attr,
3549
		const char *buffer, size_t count)
3550
{
3551
	unsigned int result;
3552
	unsigned long value;
3553
3554
	if (count > 31)
3555
		return -EINVAL;
3556
	if (strict_strtoul(buffer, 10, &value)
3557
		|| value > sony_fan->speeds_num)
3558
		return -EINVAL;
3559
3560
	if (sony_call_snc_handle(SONY_FAN_HANDLE,
3561
				(value << 0x10) | 0x0200, &result))
3562
		return -EIO;
3563
3564
	return count;
3565
}
3566
3567
static ssize_t sony_nc_fan_control_show(struct device *dev,
3568
		struct device_attribute *attr, char *buffer)
3569
{
3570
	ssize_t count = 0;
3571
	unsigned int result;
3572
3573
	if (sony_call_snc_handle(SONY_FAN_HANDLE, 0x0100, &result))
3574
		return -EINVAL;
3575
3576
	count = snprintf(buffer, PAGE_SIZE, "%d\n", result & 0xff);
3577
	return count;
3578
}
3579
3580
static ssize_t sony_nc_fan_profiles_show(struct device *dev,
3581
		struct device_attribute *attr, char *buffer)
3582
{
3583
	ssize_t count = 0;
3584
	unsigned int i;
3585
3586
	for (i = 0; i < sony_fan->speeds_num; i++)
3587
		count += snprintf(buffer + count, PAGE_SIZE - count,
3588
				"%.4u ", sony_fan->speeds[i] * 100);
3589
3590
	count += snprintf(buffer + count, PAGE_SIZE - count, "\n");
3591
3592
	return count;
3593
}
3594
3595
static ssize_t sony_nc_fan_speed_show(struct device *dev,
3596
		struct device_attribute *attr, char *buffer)
3597
{
3598
	ssize_t count = 0;
3599
	unsigned int result;
3600
3601
	if (sony_call_snc_handle(SONY_FAN_HANDLE, 0x0300, &result))
3602
		return -EINVAL;
3603
3604
	count = snprintf(buffer, PAGE_SIZE, "%d\n",
3605
				(result & 0xff) * 100);
3606
	return count;
3607
}
3608
3609
static int sony_nc_fan_setup(struct platform_device *pd)
3610
{
3611
	int ret;
3612
	unsigned int i, found;
3613
	u8 list[FAN_SPEEDS_NUM * 2] = { 0 };
3614
3615
	sony_fan = kzalloc(sizeof(struct sony_fan_device), GFP_KERNEL);
3616
	if (!sony_fan)
3617
		return -ENOMEM;
3618
3619
	ret = sony_call_snc_handle_buffer(SONY_FAN_HANDLE, 0x0000,
3620
					list, FAN_SPEEDS_NUM * 2);
3621
	if (ret < 0)
3622
		pr_info("unable to retrieve fan profiles table\n");
3623
3624
	for (i = 0, found = 0;
3625
		list[i] != 0 && found < FAN_SPEEDS_NUM; i += 2, found++) {
3626
3627
		sony_fan->speeds[found] = list[i+1];
3628
	}
3629
	sony_fan->speeds_num = found;
3630
3631
	sysfs_attr_init(&sony_fan->attrs[0].attr);
3632
	sony_fan->attrs[0].attr.name = "fan_speed";
3633
	sony_fan->attrs[0].attr.mode = S_IRUGO;
3634
	sony_fan->attrs[0].show = sony_nc_fan_speed_show;
3635
3636
	sysfs_attr_init(&sony_fan->attrs[1].attr);
3637
	sony_fan->attrs[1].attr.name = "fan_profiles";
3638
	sony_fan->attrs[1].attr.mode = S_IRUGO;
3639
	sony_fan->attrs[1].show = sony_nc_fan_profiles_show;
3640
3641
	sysfs_attr_init(&sony_fan->attrs[2].attr);
3642
	sony_fan->attrs[2].attr.name = "fan_control";
3643
	sony_fan->attrs[2].attr.mode = S_IRUGO | S_IWUSR;
3644
	sony_fan->attrs[2].show = sony_nc_fan_control_show;
3645
	sony_fan->attrs[2].store = sony_nc_fan_control_store;
3646
3647
	for (i = 0; i < FAN_ATTRS_NUM; i++) {
3648
		if (device_create_file(&pd->dev, &sony_fan->attrs[i]))
3649
			goto attrserror;
3650
	}
3651
3652
	return 0;
3653
3654
attrserror:
3655
	for (; i > 0; i--)
3656
		device_remove_file(&pd->dev, &sony_fan->attrs[i]);
3657
3658
	kfree(sony_fan);
3659
	sony_fan = NULL;
3660
3661
	return -1;
3662
}
3663
3664
static int sony_nc_fan_cleanup(struct platform_device *pd)
3665
{
3666
	if (sony_fan) {
3667
		int i;
3668
3669
		for (i = 0; i < FAN_ATTRS_NUM; i++)
3670
			device_remove_file(&pd->dev, &sony_fan->attrs[i]);
3671
3672
		kfree(sony_fan);
3673
		sony_fan = NULL;
3674
	}
3675
3676
	return 0;
3677
}
3678
3679
static struct sony_odd_device {
3680
	unsigned int vendor_id;
3681
	unsigned int model_id;
3682
	struct device_attribute status_attr;
3683
} *sony_odd;
3684
3685
#if 0
3686
static int sony_nc_odd_remove(void)
3687
{
3688
	/*
3689
	   0 - change the link state first?
3690
	   1 - scsi lookup searching for the optical device (scsi_device *)
3691
	   2 - call int scsi_remove_device(struct scsi_device *sdev)
3692
	*/
3693
3694
	struct scsi_device *sdev;
3695
	struct Scsi_Host *shost;
3696
	int error = -ENXIO;
3697
3698
	shost = scsi_host_lookup(host);
3699
	if (!shost)
3700
		return error;
3701
3702
	sdev = scsi_device_lookup(shost, channel, id, lun);
3703
	if (sdev) {
3704
		scsi_remove_device(sdev);
3705
		scsi_device_put(sdev);
3706
		error = 0;
3707
	}
3708
3709
	scsi_host_put(shost);
3710
3711
	return 0;
3712
}
3713
#endif
3714
3715
static ssize_t sony_nc_odd_status_store(struct device *dev,
3716
		struct device_attribute *attr,
3717
		const char *buffer, size_t count)
3718
{
3719
	unsigned int result;
3720
	unsigned long value;
3721
3722
	if (count > 31)
3723
		return -EINVAL;
3724
	if (strict_strtoul(buffer, 10, &value) || value > 1)
3725
		return -EINVAL;
3726
3727
#if 0
3728
	if (off)
3729
		sony_nc_odd_remove();
3730
3731
		/* and goes on, otherwise leave */
3732
#endif
3733
3734
	/* 0x200 turn on (sysfs: 1), 0x300 turn off (sysfs: 0) */
3735
	value = (!value << 0x08) + 0x200;
3736
3737
	/* the MSB have to be high */
3738
	if (sony_call_snc_handle(0x126, (1 << 0x10) | value, &result))
3739
		return -EIO;
3740
3741
#if 0
3742
	if (on)
3743
		/* force a bus scan? */
3744
#endif
3745
3746
	return count;
3747
}
3748
3749
static ssize_t sony_nc_odd_status_show(struct device *dev,
3750
		struct device_attribute *attr, char *buffer)
3751
{
3752
	ssize_t count = 0;
3753
	unsigned int result;
3754
3755
	if (sony_call_snc_handle(0x126, 0x100, &result))
3756
		return -EINVAL;
3757
3758
	count = snprintf(buffer, PAGE_SIZE, "%d\n", result & 0x01);
3759
	return count;
3760
}
3761
3762
static int sony_nc_odd_setup(struct platform_device *pd)
3763
{
3764
#define ODD_TAB_SIZE 32
3765
	u8 list[ODD_TAB_SIZE] = { 0 };
3766
	int ret = 0;
3767
	int found = 0;
3768
	int i = 0;
3769
	unsigned int vendor = 0;
3770
	unsigned int model = 0;
3771
	u16 word = 0;
3772
3773
	ret = sony_call_snc_handle_buffer(0x126, 0x0000, list, ODD_TAB_SIZE);
3774
	if (ret < 0) {
3775
		pr_info("unable to retrieve the odd table\n");
3776
		return -EIO;
3777
	}
3778
3779
	/* parse the table looking for optical devices */
3780
	do {
3781
		word = (list[i+1] << 8) | list[i];
3782
3783
		if (word == 1) { /* 1 DWord device data following */
3784
			vendor = (list[i+3] << 8) | list[i+2];
3785
			model = (list[i+5] << 8) | list[i+4];
3786
			found++;
3787
			i += 6;
3788
		} else {
3789
			i += 2;
3790
		}
3791
	} while (word != 0xff00);
3792
3793
	if (found)
3794
		dprintk("one optical device found, connected to: %x:%x\n",
3795
				vendor, model);
3796
	else
3797
		return 0;
3798
3799
	sony_odd = kzalloc(sizeof(*sony_odd), GFP_KERNEL);
3800
	if (!sony_odd)
3801
		return -ENOMEM;
3802
3803
	sony_odd->vendor_id = vendor;
3804
	sony_odd->model_id = model;
3805
3806
	sysfs_attr_init(&sony_odd->status_attr.attr);
3807
	sony_odd->status_attr.attr.name = "odd_power";
3808
	sony_odd->status_attr.attr.mode = S_IRUGO | S_IWUSR;
3809
	sony_odd->status_attr.show = sony_nc_odd_status_show;
3810
	sony_odd->status_attr.store = sony_nc_odd_status_store;
3811
3812
	if (device_create_file(&pd->dev, &sony_odd->status_attr)) {
3813
		kfree(sony_odd);
3814
		sony_odd = NULL;
3815
		return -1;
3816
	}
3817
3818
	return 0;
3819
}
3820
3821
static int sony_nc_odd_cleanup(struct platform_device *pd)
3822
{
3823
	if (sony_odd) {
3824
		device_remove_file(&pd->dev, &sony_odd->status_attr);
3825
		kfree(sony_odd);
3826
		sony_odd = NULL;
3827
	}
3828
3829
	return 0;
3830
}
3831
3832
/*
3833
 * Backlight device
3834
 */
3835
static struct backlight_device *sony_backlight_device;
3836
3837
static int sony_backlight_update_status(struct backlight_device *bd)
3838
{
3839
	return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
3840
				bd->props.brightness + 1, NULL);
3841
}
3842
3843
static int sony_backlight_get_brightness(struct backlight_device *bd)
3844
{
3845
	unsigned int value;
3846
3847
	if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value))
3848
		return 0;
3849
	/* brightness levels are 1-based, while backlight ones are 0-based */
3850
	return value - 1;
3851
}
3852
3853
static const struct backlight_ops sony_backlight_ops = {
3854
	.options = BL_CORE_SUSPENDRESUME,
3855
	.update_status = sony_backlight_update_status,
3856
	.get_brightness = sony_backlight_get_brightness,
3857
};
3858
static const struct backlight_ops sony_als_backlight_ops = {
3859
	.options = BL_CORE_SUSPENDRESUME,
3860
	.update_status = sony_nc_als_update_status,
3861
	.get_brightness = sony_nc_als_get_brightness,
3862
};
3863
3864
static void sony_nc_backlight_setup(void)
3865
{
3866
	acpi_handle unused;
3867
	int max_brightness = 0;
3868
	const struct backlight_ops *ops = NULL;
3869
	struct backlight_properties props;
3870
3871
	/* do not use SNC GBRT/SBRT controls along with the ALS */
3872
	if (sony_als) {
3873
		/* ALS based backlight device */
3874
		ops = &sony_als_backlight_ops;
3875
		max_brightness = sony_als->levels_num - 1;
3876
	} else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
3877
						&unused))) {
3878
		ops = &sony_backlight_ops;
3879
		max_brightness = SONY_MAX_BRIGHTNESS - 1;
3880
	} else {
3881
		return;
3882
	}
3883
3884
	memset(&props, 0, sizeof(struct backlight_properties));
3885
	props.type = BACKLIGHT_PLATFORM;
3886
	props.max_brightness = max_brightness;
3887
	sony_backlight_device = backlight_device_register("sony", NULL, NULL,
3888
								ops, &props);
3889
3890
	if (IS_ERR(sony_backlight_device)) {
3891
		pr_warn("unable to register backlight device\n");
3892
		sony_backlight_device = NULL;
3893
	} else {
3894
		sony_backlight_device->props.brightness =
3895
			ops->get_brightness(sony_backlight_device);
3896
	}
3897
}
3898
3899
static void sony_nc_backlight_cleanup(void)
3900
{
3901
	if (sony_backlight_device)
3902
		backlight_device_unregister(sony_backlight_device);
3903
}
3904
3905
static void sony_nc_tests_resume(void)
3906
{
3907
	return;
3908
}
3909
3910
/* place here some unknown handles, we might want to see some output */
3911
static void sony_nc_tests_setup(void)
3912
{
3913
	int ret;
3914
	unsigned int result;
3915
3916
	result = 0;
3917
	ret = sony_call_snc_handle(0x114, 0x000, &result);
3918
	if (!ret)
3919
		pr_info("handle 0x114 returned: %x\n", result & 0xff);
3920
3921
	result = 0;
3922
	ret = sony_call_snc_handle(0x139, 0x0000, &result);
3923
	if (!ret)
3924
		pr_info("handle 0x139+00 returned: %x\n", result & 0xffff);
3925
3926
	result = 0;
3927
	ret = sony_call_snc_handle(0x139, 0x0100, &result);
3928
	if (!ret)
3929
		pr_info("handle 0x139+01 returned: %x\n", result & 0xffff);
3930
3931
	return;
3932
}
3933
3934
static void sony_nc_snc_setup_handles(struct platform_device *pd)
3935
{
3936
	unsigned int i;
3937
3938
	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
3939
		int ret = 0;
3940
		int unsigned handle = handles->cap[i];
3941
3942
		if (!handle)
3943
			continue;
3944
3945
		dprintk("looking at handle 0x%.4x\n", handle);
3946
3947
		switch (handle) {
3948
		case 0x0100:
3949
		case 0x0127:
3950
		case 0x0101:
3951
		case 0x0102:
3952
			ret = sony_nc_function_setup(handle);
3953
			break;
3954
		case 0x0105:
3955
		case 0x0148: /* same as 0x0105 + Fn-F1 combo */
3956
			ret = sony_nc_touchpad_setup(pd, handle);
3957
			break;
3958
		case 0x0115:
3959
		case 0x0136:
3960
		case 0x013f:
3961
			ret = sony_nc_battery_care_setup(pd, handle);
3962
			break;
3963
		case 0x0119:
3964
			ret = sony_nc_lid_resume_setup(pd);
3965
			break;
3966
		case 0x0122:
3967
			ret = sony_nc_thermal_setup(pd);
3968
			break;
3969
		case 0x0126:
3970
			ret = sony_nc_odd_setup(pd);
3971
			break;
3972
		case 0x0137:
3973
		case 0x0143:
3974
			ret = sony_nc_kbd_backlight_setup(pd, handle);
3975
		case 0x012f: /* no keyboard backlight */
3976
			ret = sony_nc_als_setup(pd, handle);
3977
			break;
3978
		case 0x0131:
3979
			ret = sony_nc_highspeed_charging_setup(pd);
3980
			break;
3981
		case 0x0134:
3982
		case 0x0147:
3983
			ret = sony_nc_gsensor_setup(pd, handle);
3984
			break;
3985
		case 0x0149:
3986
			ret = sony_nc_fan_setup(pd);
3987
			break;
3988
		case 0x0124:
3989
		case 0x0135:
3990
			ret = sony_nc_rfkill_setup(sony_nc_acpi_device, handle);
3991
			break;
3992
		default:
3993
			continue;
3994
		}
3995
3996
		if (ret < 0) {
3997
			pr_warn("handle 0x%.4x setup failed (ret: %i)",
3998
								handle, ret);
3999
		} else {
4000
			dprintk("handle 0x%.4x setup completed\n", handle);
4001
		}
1368
	}
4002
	}
1369
4003
1370
out_no_enum:
4004
	if (debug)
1371
	kfree(buffer.pointer);
4005
		sony_nc_tests_setup();
1372
	return;
1373
}
4006
}
1374
4007
1375
/* Keyboard backlight feature */
4008
static void sony_nc_snc_cleanup_handles(struct platform_device *pd)
1376
#define KBDBL_HANDLER	0x137
1377
#define KBDBL_PRESENT	0xB00
1378
#define	SET_MODE	0xC00
1379
#define SET_STATE	0xD00
1380
#define SET_TIMEOUT	0xE00
1381
1382
struct kbd_backlight {
1383
	int mode;
1384
	int timeout;
1385
	struct device_attribute mode_attr;
1386
	struct device_attribute timeout_attr;
1387
};
1388
1389
static struct kbd_backlight *kbdbl_handle;
1390
1391
static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
1392
{
4009
{
1393
	int result;
4010
	unsigned int i;
1394
4011
1395
	if (value > 1)
4012
	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
1396
		return -EINVAL;
1397
4013
1398
	if (sony_call_snc_handle(KBDBL_HANDLER,
4014
		int unsigned handle = handles->cap[i];
1399
				(value << 0x10) | SET_MODE, &result))
1400
		return -EIO;
1401
4015
1402
	/* Try to turn the light on/off immediately */
4016
		if (!handle)
1403
	sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE,
4017
			continue;
1404
			&result);
1405
4018
1406
	kbdbl_handle->mode = value;
4019
		dprintk("looking at handle 0x%.4x\n", handle);
1407
4020
1408
	return 0;
4021
		switch (handle) {
4022
		case 0x0105:
4023
		case 0x0148:
4024
			sony_nc_touchpad_cleanup(pd);
4025
			break;
4026
		case 0x0115:
4027
		case 0x0136:
4028
		case 0x013f:
4029
			sony_nc_battery_care_cleanup(pd);
4030
			break;
4031
		case 0x0119:
4032
			sony_nc_lid_resume_cleanup(pd);
4033
			break;
4034
		case 0x0122:
4035
			sony_nc_thermal_cleanup(pd);
4036
			break;
4037
		case 0x0126:
4038
			sony_nc_odd_cleanup(pd);
4039
			break;
4040
		case 0x0137:
4041
		case 0x0143:
4042
			sony_nc_kbd_backlight_cleanup(pd);
4043
		case 0x012f:
4044
			sony_nc_als_cleanup(pd);
4045
			break;
4046
		case 0x0131:
4047
			sony_nc_highspeed_charging_cleanup(pd);
4048
			break;
4049
		case 0x0134:
4050
		case 0x0147:
4051
			sony_nc_gsensor_cleanup(pd);
4052
			break;
4053
		case 0x0149:
4054
			sony_nc_fan_cleanup(pd);
4055
			break;
4056
		case 0x0124:
4057
		case 0x0135:
4058
			sony_nc_rfkill_cleanup();
4059
			break;
4060
		default:
4061
			continue;
4062
		}
4063
4064
		dprintk("handle 0x%.4x deconfigured\n", handle);
4065
	}
1409
}
4066
}
1410
4067
1411
static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev,
4068
static int sony_nc_snc_setup(struct platform_device *pd)
1412
		struct device_attribute *attr,
1413
		const char *buffer, size_t count)
1414
{
4069
{
1415
	int ret = 0;
4070
	unsigned int i, string[4], bitmask, result;
1416
	unsigned long value;
1417
1418
	if (count > 31)
1419
		return -EINVAL;
1420
1421
	if (strict_strtoul(buffer, 10, &value))
1422
		return -EINVAL;
1423
4071
1424
	ret = __sony_nc_kbd_backlight_mode_set(value);
4072
	for (i = 0; i < 4; i++) {
1425
	if (ret < 0)
4073
		if (acpi_callsetfunc(sony_nc_acpi_handle,
1426
		return ret;
4074
				"SN00", i, &string[i]))
4075
			return -EIO;
4076
	}
4077
	if (strncmp("SncSupported", (char *) string, 0x10)) {
4078
		pr_info("SNC device present but not supported by hardware");
4079
		return -1;
4080
	}
1427
4081
1428
	return count;
4082
	if (!acpi_callsetfunc(sony_nc_acpi_handle, "SN00", 0x04, &result)) {
1429
}
4083
		unsigned int model, i;
4084
		for (model = 0, i = 0; i < 4; i++)
4085
			model |= ((result >> (i * 8)) & 0xff) << ((3 - i) * 8);
4086
		pr_info("found Vaio model ID: %u\n", model);
4087
	}
1430
4088
1431
static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev,
4089
	/* retrieve the implemented offsets mask */
1432
		struct device_attribute *attr, char *buffer)
4090
	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN00", 0x10, &bitmask))
1433
{
4091
		return -EIO;
1434
	ssize_t count = 0;
1435
	count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode);
1436
	return count;
1437
}
1438
4092
1439
static int __sony_nc_kbd_backlight_timeout_set(u8 value)
4093
	/* retrieve the available handles, otherwise return */
1440
{
4094
	if (sony_nc_handles_setup(pd))
1441
	int result;
4095
		return -2;
1442
4096
1443
	if (value > 3)
4097
	/* setup found handles here */
1444
		return -EINVAL;
4098
	sony_nc_snc_setup_handles(pd);
1445
4099
1446
	if (sony_call_snc_handle(KBDBL_HANDLER,
4100
	/* Enable all events for the found handles, otherwise return */
1447
				(value << 0x10) | SET_TIMEOUT, &result))
4101
	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", bitmask, &result))
1448
		return -EIO;
4102
		return -EIO;
1449
4103
1450
	kbdbl_handle->timeout = value;
4104
	/* check for SN05 presence? */
1451
4105
1452
	return 0;
4106
	return 0;
1453
}
4107
}
1454
4108
1455
static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev,
4109
static int sony_nc_snc_cleanup(struct platform_device *pd)
1456
		struct device_attribute *attr,
1457
		const char *buffer, size_t count)
1458
{
4110
{
1459
	int ret = 0;
4111
	unsigned int result, bitmask;
1460
	unsigned long value;
1461
4112
1462
	if (count > 31)
4113
	/* retrieve the event enabled handles */
1463
		return -EINVAL;
4114
	acpi_callgetfunc(sony_nc_acpi_handle, "SN01", &bitmask);
1464
4115
1465
	if (strict_strtoul(buffer, 10, &value))
4116
	/* disable the event generation	for every handle */
1466
		return -EINVAL;
4117
	acpi_callsetfunc(sony_nc_acpi_handle, "SN03", bitmask, &result);
1467
4118
1468
	ret = __sony_nc_kbd_backlight_timeout_set(value);
4119
	/* cleanup handles here */
1469
	if (ret < 0)
4120
	sony_nc_snc_cleanup_handles(pd);
1470
		return ret;
1471
4121
1472
	return count;
4122
	sony_nc_handles_cleanup(pd);
1473
}
1474
4123
1475
static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev,
4124
	return 0;
1476
		struct device_attribute *attr, char *buffer)
1477
{
1478
	ssize_t count = 0;
1479
	count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout);
1480
	return count;
1481
}
4125
}
1482
4126
1483
static int sony_nc_kbd_backlight_setup(struct platform_device *pd)
4127
static int sony_nc_snc_resume(void)
1484
{
4128
{
1485
	int result;
4129
	unsigned int i, result, bitmask;
1486
4130
1487
	if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result))
4131
	/* retrieve the implemented offsets mask */
1488
		return 0;
4132
	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN00", 0x10, &bitmask))
1489
	if (!(result & 0x02))
4133
		return -EIO;
1490
		return 0;
1491
4134
1492
	kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL);
4135
	/* Enable all events, otherwise return */
1493
	if (!kbdbl_handle)
4136
	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", bitmask, &result))
1494
		return -ENOMEM;
4137
		return -EIO;
4138
4139
	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
4140
		int unsigned handle = handles->cap[i];
1495
4141
1496
	sysfs_attr_init(&kbdbl_handle->mode_attr.attr);
4142
		if (!handle)
1497
	kbdbl_handle->mode_attr.attr.name = "kbd_backlight";
4143
			continue;
1498
	kbdbl_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
1499
	kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show;
1500
	kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store;
1501
1502
	sysfs_attr_init(&kbdbl_handle->timeout_attr.attr);
1503
	kbdbl_handle->timeout_attr.attr.name = "kbd_backlight_timeout";
1504
	kbdbl_handle->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
1505
	kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
1506
	kbdbl_handle->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
1507
4144
1508
	if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr))
4145
		dprintk("looking at handle 0x%.4x\n", handle);
1509
		goto outkzalloc;
1510
4146
1511
	if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr))
4147
		switch (handle) {
1512
		goto outmode;
4148
		case 0x0100:
4149
		case 0x0127:
4150
		case 0x0101:
4151
		case 0x0102:
4152
			sony_nc_function_setup(handle);
4153
			break;
4154
		case 0x0122:
4155
			sony_nc_thermal_resume();
4156
			break;
4157
		case 0x0124:
4158
		case 0x0135:
4159
			/* re-read rfkill state */
4160
			sony_nc_rfkill_update();
4161
			break;
4162
		case 0x0137: /* kbd + als */
4163
		case 0x0143:
4164
			sony_nc_kbd_backlight_resume();
4165
		case 0x012f: /* als only */
4166
			sony_nc_als_resume();
4167
			break;
4168
		default:
4169
			continue;
4170
		}
1513
4171
1514
	__sony_nc_kbd_backlight_mode_set(kbd_backlight);
4172
		dprintk("handle 0x%.4x updated\n", handle);
1515
	__sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
4173
	}
1516
4174
1517
	return 0;
4175
	if (debug)
4176
		sony_nc_tests_resume();
1518
4177
1519
outmode:
4178
	return 0;
1520
	device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
1521
outkzalloc:
1522
	kfree(kbdbl_handle);
1523
	kbdbl_handle = NULL;
1524
	return -1;
1525
}
4179
}
1526
4180
1527
static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
4181
/*
4182
 * ACPI callbacks
4183
 */
4184
static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
4185
				      void *context, void **return_value)
1528
{
4186
{
1529
	if (kbdbl_handle) {
4187
	struct acpi_device_info *info;
1530
		int result;
1531
1532
		device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
1533
		device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr);
1534
4188
1535
		/* restore the default hw behaviour */
4189
	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
1536
		sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result);
4190
		pr_warn("method: name: %4.4s, args %X\n",
1537
		sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result);
4191
			(char *)&info->name, info->param_count);
1538
4192
1539
		kfree(kbdbl_handle);
4193
		kfree(info);
1540
	}
4194
	}
1541
	return 0;
4195
4196
	return AE_OK;
1542
}
4197
}
1543
4198
1544
static void sony_nc_kbd_backlight_resume(void)
4199
#define EV_HOTKEYS	1
4200
#define EV_RFKILL	2
4201
#define EV_ALS		3
4202
#define EV_GSENSOR	4
4203
#define	EV_HGFX		5
4204
static void sony_nc_notify(struct acpi_device *device, u32 event)
1545
{
4205
{
1546
	int ignore = 0;
4206
	u8 ev = 0;
4207
	int value = 0;
4208
	char *env[2] = { NULL };
1547
4209
1548
	if (!kbdbl_handle)
4210
	dprintk("sony_nc_notify, event: 0x%.2x\n", event);
1549
		return;
1550
4211
1551
	if (kbdbl_handle->mode == 0)
4212
	/* handles related events */
1552
		sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore);
4213
	if (event >= 0x90) {
4214
		unsigned int result = 0, handle = 0;
4215
4216
		/* the event should corrispond to the offset of the method */
4217
		unsigned int offset = event - 0x90;
4218
4219
		handle = handles->cap[offset];
4220
		switch (handle) {
4221
		/* list of handles known for generating events */
4222
		case 0x0100:
4223
		case 0x0127:
4224
			/* hotkey event, a key has been pressed, retrieve it */
4225
			value = sony_nc_hotkeys_decode(handle);
4226
			if (value > 0) /* known event */
4227
				sony_laptop_report_input_event(value);
4228
			else /* restore the original event */
4229
			    value = event;
1553
4230
1554
	if (kbdbl_handle->timeout != 0)
4231
			ev = EV_HOTKEYS;
1555
		sony_call_snc_handle(KBDBL_HANDLER,
4232
			break;
1556
				(kbdbl_handle->timeout << 0x10) | SET_TIMEOUT,
1557
				&ignore);
1558
}
1559
4233
1560
static void sony_nc_backlight_ng_read_limits(int handle,
4234
		case 0x0143:
1561
		struct sony_backlight_props *props)
4235
			sony_call_snc_handle(handle, 0x2000, &result);
1562
{
4236
			/* event reasons are reverted */
1563
	int offset;
4237
			value = (result & 0x03) == 1 ? 2 : 1;
1564
	acpi_status status;
4238
			dprintk("sony_nc_notify, ALS event received (reason:"
1565
	u8 brlvl, i;
4239
				       " %s change)\n", value == 1 ? "light" :
1566
	u8 min = 0xff, max = 0x00;
4240
				       "backlight");
1567
	struct acpi_object_list params;
1568
	union acpi_object in_obj;
1569
	union acpi_object *lvl_enum;
1570
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1571
4241
1572
	props->handle = handle;
4242
			env[0] = (value == 1) ? "ALS=1" : "ALS=2";
1573
	props->offset = 0;
4243
			kobject_uevent_env(&device->dev.kobj, KOBJ_CHANGE, env);
1574
	props->maxlvl = 0xff;
1575
4244
1576
	offset = sony_find_snc_handle(handle);
4245
			ev = EV_ALS;
1577
	if (offset < 0)
4246
			break;
1578
		return;
1579
4247
1580
	/* try to read the boundaries from ACPI tables, if we fail the above
4248
		case 0x012f:
1581
	 * defaults should be reasonable
4249
		case 0x0137:
1582
	 */
4250
			sony_call_snc_handle(handle, 0x0800, &result);
1583
	params.count = 1;
4251
			value = result & 0x03;
1584
	params.pointer = &in_obj;
4252
			dprintk("sony_nc_notify, ALS event received (reason:"
1585
	in_obj.type = ACPI_TYPE_INTEGER;
4253
					" %s change)\n", value == 1 ? "light" :
1586
	in_obj.integer.value = offset;
4254
					"backlight");
1587
	status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
4255
			if (value == 1) /* lighting change reason */
1588
			&buffer);
4256
				sony_nc_als_event_handler();
1589
	if (ACPI_FAILURE(status))
1590
		return;
1591
4257
1592
	lvl_enum = (union acpi_object *) buffer.pointer;
4258
			env[0] = (value == 1) ? "ALS=1" : "ALS=2";
1593
	if (!lvl_enum) {
4259
			kobject_uevent_env(&device->dev.kobj, KOBJ_CHANGE, env);
1594
		pr_err("No SN06 return object.");
1595
		return;
1596
	}
1597
	if (lvl_enum->type != ACPI_TYPE_BUFFER) {
1598
		pr_err("Invalid SN06 return object 0x%.2x\n",
1599
		       lvl_enum->type);
1600
		goto out_invalid;
1601
	}
1602
4260
1603
	/* the buffer lists brightness levels available, brightness levels are
4261
			ev = EV_ALS;
1604
	 * from 0 to 8 in the array, other values are used by ALS control.
4262
			break;
1605
	 */
1606
	for (i = 0; i < 9 && i < lvl_enum->buffer.length; i++) {
1607
4263
1608
		brlvl = *(lvl_enum->buffer.pointer + i);
4264
		case 0x0124:
1609
		dprintk("Brightness level: %d\n", brlvl);
4265
		case 0x0135:
4266
			sony_call_snc_handle(handle, 0x0100, &result);
4267
			result &= 0x03;
4268
			dprintk("sony_nc_notify, RFKILL event received "
4269
					"(reason: %s)\n", result == 1 ?
4270
					"switch state changed" : "battery");
4271
4272
			if (result == 1) { /* hw swtich event */
4273
				sony_nc_rfkill_update();
4274
				value = sony_nc_get_rfkill_hwblock();
4275
			} else if (result == 2) { /* battery event */
4276
				/*  we might need to change the WWAN rfkill
4277
				    state when the battery state changes
4278
				 */
4279
				sony_nc_rfkill_update_wwan();
4280
				return;
4281
			}
1610
4282
1611
		if (!brlvl)
4283
			ev = EV_RFKILL;
1612
			break;
4284
			break;
1613
4285
1614
		if (brlvl > max)
4286
		case 0x0134:
1615
			max = brlvl;
4287
		case 0x0147:
1616
		if (brlvl < min)
4288
			ev = 4;
1617
			min = brlvl;
4289
			value = EV_GSENSOR;
1618
	}
4290
			/* hdd protection event, notify userspace */
1619
	props->offset = min;
1620
	props->maxlvl = max;
1621
	dprintk("Brightness levels: min=%d max=%d\n", props->offset,
1622
			props->maxlvl);
1623
4291
1624
out_invalid:
4292
			env[0] = "HDD_SHOCK=1";
1625
	kfree(buffer.pointer);
4293
			kobject_uevent_env(&device->dev.kobj, KOBJ_CHANGE, env);
1626
	return;
1627
}
1628
4294
1629
static void sony_nc_backlight_setup(void)
4295
			break;
1630
{
1631
	acpi_handle unused;
1632
	int max_brightness = 0;
1633
	const struct backlight_ops *ops = NULL;
1634
	struct backlight_properties props;
1635
4296
1636
	if (sony_find_snc_handle(0x12f) != -1) {
4297
		case 0x0128:
1637
		ops = &sony_backlight_ng_ops;
4298
		case 0x0146:
1638
		sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
4299
			/* Hybrid GFX switching, 1 */
1639
		max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
4300
			sony_call_snc_handle(handle, 0x0000, &result);
1640
4301
			dprintk("sony_nc_notify, Hybrid GFX event received "
1641
	} else if (sony_find_snc_handle(0x137) != -1) {
4302
					"(reason: %s)\n", (result & 0x01) ?
1642
		ops = &sony_backlight_ng_ops;
4303
					"switch position change" : "unknown");
1643
		sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
4304
1644
		max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
4305
			/* verify the switch state
4306
			   (1: discrete GFX, 0: integrated GFX)*/
4307
			result = 0;
4308
			sony_call_snc_handle(handle, 0x0100, &result);
1645
4309
1646
	} else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
4310
			/* sony_laptop_report_input_event(); */
1647
						&unused))) {
1648
		ops = &sony_backlight_ops;
1649
		max_brightness = SONY_MAX_BRIGHTNESS - 1;
1650
4311
1651
	} else
4312
			ev = EV_HGFX;
1652
		return;
4313
			value = result & 0xff;
4314
			break;
1653
4315
1654
	memset(&props, 0, sizeof(struct backlight_properties));
4316
		default:
1655
	props.type = BACKLIGHT_PLATFORM;
4317
			value = event;
1656
	props.max_brightness = max_brightness;
4318
			dprintk("Unknowk event for handle: 0x%x\n", handle);
1657
	sony_bl_props.dev = backlight_device_register("sony", NULL,
4319
			break;
1658
						      &sony_bl_props,
4320
		}
1659
						      ops, &props);
1660
4321
1661
	if (IS_ERR(sony_bl_props.dev)) {
4322
		/* clear the event (and the event reason when present) */
1662
		pr_warn("unable to register backlight device\n");
4323
		acpi_callsetfunc(sony_nc_acpi_handle, "SN05", 1 << offset,
1663
		sony_bl_props.dev = NULL;
4324
				&result);
1664
	} else
4325
	} else {
1665
		sony_bl_props.dev->props.brightness =
4326
		ev = 1;
1666
			ops->get_brightness(sony_bl_props.dev);
4327
		sony_laptop_report_input_event(event);
1667
}
4328
	}
1668
4329
1669
static void sony_nc_backlight_cleanup(void)
4330
	acpi_bus_generate_proc_event(device, ev, value);
1670
{
4331
	acpi_bus_generate_netlink_event(device->pnp.device_class,
1671
	if (sony_bl_props.dev)
4332
					dev_name(&device->dev), ev, value);
1672
		backlight_device_unregister(sony_bl_props.dev);
1673
}
4333
}
1674
4334
1675
static int sony_nc_add(struct acpi_device *device)
4335
static int sony_nc_add(struct acpi_device *device)
Lines 1688-1694 static int sony_nc_add(struct acpi_devic Link Here
1688
4348
1689
	/* read device status */
4349
	/* read device status */
1690
	result = acpi_bus_get_status(device);
4350
	result = acpi_bus_get_status(device);
1691
	/* bail IFF the above call was successful and the device is not present */
4351
	/* bail IFF the above call was successful
4352
	   and the device is not present */
1692
	if (!result && !device->status.present) {
4353
	if (!result && !device->status.present) {
1693
		dprintk("Device not present\n");
4354
		dprintk("Device not present\n");
1694
		result = -ENODEV;
4355
		result = -ENODEV;
Lines 1719-1743 static int sony_nc_add(struct acpi_devic Link Here
1719
	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
4380
	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1720
					 &handle))) {
4381
					 &handle))) {
1721
		dprintk("Doing SNC setup\n");
4382
		dprintk("Doing SNC setup\n");
1722
		result = sony_nc_handles_setup(sony_pf_device);
4383
1723
		if (result)
4384
		if (sony_nc_snc_setup(sony_pf_device))
1724
			goto outpresent;
1725
		result = sony_nc_kbd_backlight_setup(sony_pf_device);
1726
		if (result)
1727
			goto outsnc;
4385
			goto outsnc;
1728
		sony_nc_function_setup(device);
1729
		sony_nc_rfkill_setup(device);
1730
	}
4386
	}
1731
4387
1732
	/* setup input devices and helper fifo */
4388
	/* setup input devices and helper fifo */
1733
	result = sony_laptop_setup_input(device);
4389
	result = sony_laptop_setup_input(device);
1734
	if (result) {
4390
	if (result) {
1735
		pr_err("Unable to create input devices\n");
4391
		pr_err("Unable to create input devices\n");
1736
		goto outkbdbacklight;
4392
		goto outsnc;
1737
	}
4393
	}
1738
4394
1739
	if (acpi_video_backlight_support()) {
4395
	if (acpi_video_backlight_support()) {
1740
		pr_info("brightness ignored, must be controlled by ACPI video driver\n");
4396
		pr_info("brightness ignored, must be "
4397
			"controlled by ACPI video driver\n");
1741
	} else {
4398
	} else {
1742
		sony_nc_backlight_setup();
4399
		sony_nc_backlight_setup();
1743
	}
4400
	}
Lines 1783-1807 static int sony_nc_add(struct acpi_devic Link Here
1783
4440
1784
	return 0;
4441
	return 0;
1785
4442
1786
      out_sysfs:
4443
out_sysfs:
1787
	for (item = sony_nc_values; item->name; ++item) {
4444
	for (item = sony_nc_values; item->name; ++item)
1788
		device_remove_file(&sony_pf_device->dev, &item->devattr);
4445
		device_remove_file(&sony_pf_device->dev, &item->devattr);
1789
	}
4446
1790
	sony_nc_backlight_cleanup();
4447
	sony_nc_backlight_cleanup();
1791
4448
1792
	sony_laptop_remove_input();
4449
	sony_laptop_remove_input();
1793
4450
1794
      outkbdbacklight:
4451
outsnc:
1795
	sony_nc_kbd_backlight_cleanup(sony_pf_device);
4452
	sony_nc_snc_cleanup(sony_pf_device);
1796
1797
      outsnc:
1798
	sony_nc_handles_cleanup(sony_pf_device);
1799
4453
1800
      outpresent:
4454
outpresent:
1801
	sony_pf_remove();
4455
	sony_pf_remove();
1802
4456
1803
      outwalk:
4457
outwalk:
1804
	sony_nc_rfkill_cleanup();
1805
	return result;
4458
	return result;
1806
}
4459
}
1807
4460
Lines 1813-1832 static int sony_nc_remove(struct acpi_de Link Here
1813
4466
1814
	sony_nc_acpi_device = NULL;
4467
	sony_nc_acpi_device = NULL;
1815
4468
1816
	for (item = sony_nc_values; item->name; ++item) {
4469
	for (item = sony_nc_values; item->name; ++item)
1817
		device_remove_file(&sony_pf_device->dev, &item->devattr);
4470
		device_remove_file(&sony_pf_device->dev, &item->devattr);
1818
	}
1819
4471
1820
	sony_nc_kbd_backlight_cleanup(sony_pf_device);
4472
	sony_nc_snc_cleanup(sony_pf_device);
1821
	sony_nc_handles_cleanup(sony_pf_device);
1822
	sony_pf_remove();
4473
	sony_pf_remove();
1823
	sony_laptop_remove_input();
4474
	sony_laptop_remove_input();
1824
	sony_nc_rfkill_cleanup();
1825
	dprintk(SONY_NC_DRIVER_NAME " removed.\n");
4475
	dprintk(SONY_NC_DRIVER_NAME " removed.\n");
1826
4476
1827
	return 0;
4477
	return 0;
1828
}
4478
}
1829
4479
4480
static int sony_nc_resume(struct acpi_device *device)
4481
{
4482
	struct sony_nc_value *item;
4483
	acpi_handle handle;
4484
4485
	for (item = sony_nc_values; item->name; item++) {
4486
		int ret;
4487
4488
		if (!item->valid)
4489
			continue;
4490
		ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
4491
				       item->value, NULL);
4492
		if (ret < 0) {
4493
			pr_err("%s: %d\n", __func__, ret);
4494
			break;
4495
		}
4496
	}
4497
4498
	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
4499
					 &handle))) {
4500
		if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
4501
			dprintk("ECON Method failed\n");
4502
	}
4503
4504
	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
4505
					 &handle))) {
4506
		dprintk("Doing SNC setup\n");
4507
4508
		sony_nc_snc_resume();
4509
	}
4510
4511
	/* set the last requested brightness level */
4512
	if (sony_backlight_device &&
4513
		sony_backlight_ops.update_status(sony_backlight_device) < 0)
4514
		pr_warn("unable to restore brightness level\n");
4515
4516
	return 0;
4517
}
4518
1830
static const struct acpi_device_id sony_device_ids[] = {
4519
static const struct acpi_device_id sony_device_ids[] = {
1831
	{SONY_NC_HID, 0},
4520
	{SONY_NC_HID, 0},
1832
	{SONY_PIC_HID, 0},
4521
	{SONY_PIC_HID, 0},
Lines 2165-2175 static u8 sony_pic_call3(u8 dev, u8 fn, Link Here
2165
{
4854
{
2166
	u8 v1;
4855
	u8 v1;
2167
4856
2168
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
4857
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
4858
			ITERATIONS_LONG);
2169
	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
4859
	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
2170
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
4860
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
4861
			ITERATIONS_LONG);
2171
	outb(fn, spic_dev.cur_ioport->io1.minimum);
4862
	outb(fn, spic_dev.cur_ioport->io1.minimum);
2172
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
4863
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
4864
			ITERATIONS_LONG);
2173
	outb(v, spic_dev.cur_ioport->io1.minimum);
4865
	outb(v, spic_dev.cur_ioport->io1.minimum);
2174
	v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
4866
	v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
2175
	dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n",
4867
	dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n",
Lines 2283-2301 out: Link Here
2283
/* the rest don't need a loop until not 0xff */
4975
/* the rest don't need a loop until not 0xff */
2284
#define SONYPI_CAMERA_AGC			6
4976
#define SONYPI_CAMERA_AGC			6
2285
#define SONYPI_CAMERA_AGC_MASK			0x30
4977
#define SONYPI_CAMERA_AGC_MASK			0x30
2286
#define SONYPI_CAMERA_SHUTTER_MASK 		0x7
4978
#define SONYPI_CAMERA_SHUTTER_MASK		0x7
2287
4979
2288
#define SONYPI_CAMERA_SHUTDOWN_REQUEST		7
4980
#define SONYPI_CAMERA_SHUTDOWN_REQUEST		7
2289
#define SONYPI_CAMERA_CONTROL			0x10
4981
#define SONYPI_CAMERA_CONTROL			0x10
2290
4982
2291
#define SONYPI_CAMERA_STATUS 			7
4983
#define SONYPI_CAMERA_STATUS			7
2292
#define SONYPI_CAMERA_STATUS_READY 		0x2
4984
#define SONYPI_CAMERA_STATUS_READY		0x2
2293
#define SONYPI_CAMERA_STATUS_POSITION		0x4
4985
#define SONYPI_CAMERA_STATUS_POSITION		0x4
2294
4986
2295
#define SONYPI_DIRECTION_BACKWARDS 		0x4
4987
#define SONYPI_DIRECTION_BACKWARDS		0x4
2296
4988
2297
#define SONYPI_CAMERA_REVISION 			8
4989
#define SONYPI_CAMERA_REVISION			8
2298
#define SONYPI_CAMERA_ROMVERSION 		9
4990
#define SONYPI_CAMERA_ROMVERSION		9
2299
4991
2300
static int __sony_pic_camera_ready(void)
4992
static int __sony_pic_camera_ready(void)
2301
{
4993
{
Lines 2379-2406 int sony_pic_camera_command(int command, Link Here
2379
			__sony_pic_camera_off();
5071
			__sony_pic_camera_off();
2380
		break;
5072
		break;
2381
	case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
5073
	case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
2382
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS, value),
5074
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS,
2383
				ITERATIONS_SHORT);
5075
				value),	ITERATIONS_SHORT);
2384
		break;
5076
		break;
2385
	case SONY_PIC_COMMAND_SETCAMERACONTRAST:
5077
	case SONY_PIC_COMMAND_SETCAMERACONTRAST:
2386
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value),
5078
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST,
2387
				ITERATIONS_SHORT);
5079
				value),	ITERATIONS_SHORT);
2388
		break;
5080
		break;
2389
	case SONY_PIC_COMMAND_SETCAMERAHUE:
5081
	case SONY_PIC_COMMAND_SETCAMERAHUE:
2390
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value),
5082
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value),
2391
				ITERATIONS_SHORT);
5083
				ITERATIONS_SHORT);
2392
		break;
5084
		break;
2393
	case SONY_PIC_COMMAND_SETCAMERACOLOR:
5085
	case SONY_PIC_COMMAND_SETCAMERACOLOR:
2394
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value),
5086
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR,
2395
				ITERATIONS_SHORT);
5087
				value),	ITERATIONS_SHORT);
2396
		break;
5088
		break;
2397
	case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
5089
	case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
2398
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value),
5090
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS,
2399
				ITERATIONS_SHORT);
5091
				value),	ITERATIONS_SHORT);
2400
		break;
5092
		break;
2401
	case SONY_PIC_COMMAND_SETCAMERAPICTURE:
5093
	case SONY_PIC_COMMAND_SETCAMERAPICTURE:
2402
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value),
5094
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
2403
				ITERATIONS_SHORT);
5095
				value),	ITERATIONS_SHORT);
2404
		break;
5096
		break;
2405
	case SONY_PIC_COMMAND_SETCAMERAAGC:
5097
	case SONY_PIC_COMMAND_SETCAMERAAGC:
2406
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value),
5098
		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value),
Lines 2434-2440 static ssize_t sony_pic_wwanpower_store( Link Here
2434
	if (count > 31)
5126
	if (count > 31)
2435
		return -EINVAL;
5127
		return -EINVAL;
2436
5128
2437
	value = simple_strtoul(buffer, NULL, 10);
5129
	if (strict_strtoul(buffer, 10, &value))
5130
		return -EINVAL;
5131
2438
	mutex_lock(&spic_dev.lock);
5132
	mutex_lock(&spic_dev.lock);
2439
	__sony_pic_set_wwanpower(value);
5133
	__sony_pic_set_wwanpower(value);
2440
	mutex_unlock(&spic_dev.lock);
5134
	mutex_unlock(&spic_dev.lock);
Lines 2471-2477 static ssize_t sony_pic_bluetoothpower_s Link Here
2471
	if (count > 31)
5165
	if (count > 31)
2472
		return -EINVAL;
5166
		return -EINVAL;
2473
5167
2474
	value = simple_strtoul(buffer, NULL, 10);
5168
	if (strict_strtoul(buffer, 10, &value))
5169
		return -EINVAL;
5170
2475
	mutex_lock(&spic_dev.lock);
5171
	mutex_lock(&spic_dev.lock);
2476
	__sony_pic_set_bluetoothpower(value);
5172
	__sony_pic_set_bluetoothpower(value);
2477
	mutex_unlock(&spic_dev.lock);
5173
	mutex_unlock(&spic_dev.lock);
Lines 2510-2516 static ssize_t sony_pic_fanspeed_store(s Link Here
2510
	if (count > 31)
5206
	if (count > 31)
2511
		return -EINVAL;
5207
		return -EINVAL;
2512
5208
2513
	value = simple_strtoul(buffer, NULL, 10);
5209
	if (strict_strtoul(buffer, 10, &value))
5210
		return -EINVAL;
5211
2514
	if (sony_pic_set_fanspeed(value))
5212
	if (sony_pic_set_fanspeed(value))
2515
		return -EIO;
5213
		return -EIO;
2516
5214
Lines 2659-2670 static long sonypi_misc_ioctl(struct fil Link Here
2659
	void __user *argp = (void __user *)arg;
5357
	void __user *argp = (void __user *)arg;
2660
	u8 val8;
5358
	u8 val8;
2661
	u16 val16;
5359
	u16 val16;
2662
	int value;
5360
	unsigned int value;
2663
5361
2664
	mutex_lock(&spic_dev.lock);
5362
	mutex_lock(&spic_dev.lock);
2665
	switch (cmd) {
5363
	switch (cmd) {
2666
	case SONYPI_IOCGBRT:
5364
	case SONYPI_IOCGBRT:
2667
		if (sony_bl_props.dev == NULL) {
5365
		if (sony_backlight_device == NULL) {
2668
			ret = -EIO;
5366
			ret = -EIO;
2669
			break;
5367
			break;
2670
		}
5368
		}
Lines 2677-2683 static long sonypi_misc_ioctl(struct fil Link Here
2677
				ret = -EFAULT;
5375
				ret = -EFAULT;
2678
		break;
5376
		break;
2679
	case SONYPI_IOCSBRT:
5377
	case SONYPI_IOCSBRT:
2680
		if (sony_bl_props.dev == NULL) {
5378
		if (sony_backlight_device == NULL) {
2681
			ret = -EIO;
5379
			ret = -EIO;
2682
			break;
5380
			break;
2683
		}
5381
		}
Lines 2691-2698 static long sonypi_misc_ioctl(struct fil Link Here
2691
			break;
5389
			break;
2692
		}
5390
		}
2693
		/* sync the backlight device status */
5391
		/* sync the backlight device status */
2694
		sony_bl_props.dev->props.brightness =
5392
		sony_backlight_device->props.brightness =
2695
		    sony_backlight_get_brightness(sony_bl_props.dev);
5393
		    sony_backlight_get_brightness(sony_backlight_device);
2696
		break;
5394
		break;
2697
	case SONYPI_IOCGBAT1CAP:
5395
	case SONYPI_IOCGBAT1CAP:
2698
		if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
5396
		if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
Lines 2861-2867 sony_pic_read_possible_resource(struct a Link Here
2861
	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
5559
	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
2862
		{
5560
		{
2863
			/* start IO enumeration */
5561
			/* start IO enumeration */
2864
			struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
5562
			struct sony_pic_ioport *ioport =
5563
					kzalloc(sizeof(*ioport), GFP_KERNEL);
2865
			if (!ioport)
5564
			if (!ioport)
2866
				return AE_ERROR;
5565
				return AE_ERROR;
2867
5566
Lines 2909-2915 sony_pic_read_possible_resource(struct a Link Here
2909
		{
5608
		{
2910
			struct acpi_resource_io *io = &resource->data.io;
5609
			struct acpi_resource_io *io = &resource->data.io;
2911
			struct sony_pic_ioport *ioport =
5610
			struct sony_pic_ioport *ioport =
2912
				list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
5611
				list_first_entry(&dev->ioports,
5612
						struct sony_pic_ioport, list);
2913
			if (!io) {
5613
			if (!io) {
2914
				dprintk("Blank IO resource\n");
5614
				dprintk("Blank IO resource\n");
2915
				return AE_OK;
5615
				return AE_OK;
Lines 2917-2932 sony_pic_read_possible_resource(struct a Link Here
2917
5617
2918
			if (!ioport->io1.minimum) {
5618
			if (!ioport->io1.minimum) {
2919
				memcpy(&ioport->io1, io, sizeof(*io));
5619
				memcpy(&ioport->io1, io, sizeof(*io));
2920
				dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
5620
				dprintk("IO1 at 0x%.4x (0x%.2x)\n",
5621
						ioport->io1.minimum,
2921
						ioport->io1.address_length);
5622
						ioport->io1.address_length);
2922
			}
5623
			} else if (!ioport->io2.minimum) {
2923
			else if (!ioport->io2.minimum) {
2924
				memcpy(&ioport->io2, io, sizeof(*io));
5624
				memcpy(&ioport->io2, io, sizeof(*io));
2925
				dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
5625
				dprintk("IO2 at 0x%.4x (0x%.2x)\n",
5626
						ioport->io2.minimum,
2926
						ioport->io2.address_length);
5627
						ioport->io2.address_length);
2927
			}
5628
			} else {
2928
			else {
5629
				pr_err("Unknown SPIC Type, "
2929
				pr_err("Unknown SPIC Type, more than 2 IO Ports\n");
5630
					"more than 2 IO Ports\n");
2930
				return AE_ERROR;
5631
				return AE_ERROR;
2931
			}
5632
			}
2932
			return AE_OK;
5633
			return AE_OK;
Lines 3249-3272 static int sony_pic_add(struct acpi_devi Link Here
3249
			/* Type 1 have 2 ioports */
5950
			/* Type 1 have 2 ioports */
3250
			if (io->io2.minimum) {
5951
			if (io->io2.minimum) {
3251
				if (request_region(io->io2.minimum,
5952
				if (request_region(io->io2.minimum,
3252
						io->io2.address_length,
5953
					io->io2.address_length,
3253
						"Sony Programmable I/O Device")) {
5954
					"Sony Programmable I/O Device")) {
3254
					dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
5955
					dprintk("I/O port2: 0x%.4x (0x%.4x) "
3255
							io->io2.minimum, io->io2.maximum,
5956
							"+ 0x%.2x\n",
5957
							io->io2.minimum,
5958
							io->io2.maximum,
3256
							io->io2.address_length);
5959
							io->io2.address_length);
3257
					spic_dev.cur_ioport = io;
5960
					spic_dev.cur_ioport = io;
3258
					break;
5961
					break;
3259
				}
5962
				} else {
3260
				else {
3261
					dprintk("Unable to get I/O port2: "
5963
					dprintk("Unable to get I/O port2: "
3262
							"0x%.4x (0x%.4x) + 0x%.2x\n",
5964
							"0x%.4x (0x%.4x) "
3263
							io->io2.minimum, io->io2.maximum,
5965
							"+ 0x%.2x\n",
5966
							io->io2.minimum,
5967
							io->io2.maximum,
3264
							io->io2.address_length);
5968
							io->io2.address_length);
3265
					release_region(io->io1.minimum,
5969
					release_region(io->io1.minimum,
3266
							io->io1.address_length);
5970
							io->io1.address_length);
3267
				}
5971
				}
3268
			}
5972
			} else {
3269
			else {
3270
				spic_dev.cur_ioport = io;
5973
				spic_dev.cur_ioport = io;
3271
				break;
5974
				break;
3272
			}
5975
			}
Lines 3281-3287 static int sony_pic_add(struct acpi_devi Link Here
3281
	/* request IRQ */
5984
	/* request IRQ */
3282
	list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
5985
	list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
3283
		if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
5986
		if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
3284
					IRQF_DISABLED, "sony-laptop", &spic_dev)) {
5987
				IRQF_DISABLED, "sony-laptop", &spic_dev)) {
3285
			dprintk("IRQ: %d - triggering: %d - "
5988
			dprintk("IRQ: %d - triggering: %d - "
3286
					"polarity: %d - shr: %d\n",
5989
					"polarity: %d - shr: %d\n",
3287
					irq->irq.interrupts[0],
5990
					irq->irq.interrupts[0],
Lines 3311-3317 static int sony_pic_add(struct acpi_devi Link Here
3311
	if (result)
6014
	if (result)
3312
		goto err_disable_device;
6015
		goto err_disable_device;
3313
6016
3314
	result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
6017
	result = sysfs_create_group(&sony_pf_device->dev.kobj,
6018
					&spic_attribute_group);
3315
	if (result)
6019
	if (result)
3316
		goto err_remove_pf;
6020
		goto err_remove_pf;
3317
6021

Return to bug 41652