forked from Minki/linux
Merge branch 'next' into for-linus
Prepare first set of updates for 3.8 merge window.
This commit is contained in:
commit
022573c275
@ -0,0 +1,46 @@
|
||||
* GPIO driven matrix keypad device tree bindings
|
||||
|
||||
GPIO driven matrix keypad is used to interface a SoC with a matrix keypad.
|
||||
The matrix keypad supports multiple row and column lines, a key can be
|
||||
placed at each intersection of a unique row and a unique column. The matrix
|
||||
keypad can sense a key-press and key-release by means of GPIO lines and
|
||||
report the event using GPIO interrupts to the cpu.
|
||||
|
||||
Required Properties:
|
||||
- compatible: Should be "gpio-matrix-keypad"
|
||||
- row-gpios: List of gpios used as row lines. The gpio specifier
|
||||
for this property depends on the gpio controller to
|
||||
which these row lines are connected.
|
||||
- col-gpios: List of gpios used as column lines. The gpio specifier
|
||||
for this property depends on the gpio controller to
|
||||
which these column lines are connected.
|
||||
- linux,keymap: The definition can be found at
|
||||
bindings/input/matrix-keymap.txt
|
||||
|
||||
Optional Properties:
|
||||
- linux,no-autorepeat: do no enable autorepeat feature.
|
||||
- linux,wakeup: use any event on keypad as wakeup event.
|
||||
- debounce-delay-ms: debounce interval in milliseconds
|
||||
- col-scan-delay-us: delay, measured in microseconds, that is needed
|
||||
before we can scan keypad after activating column gpio
|
||||
|
||||
Example:
|
||||
matrix-keypad {
|
||||
compatible = "gpio-matrix-keypad";
|
||||
debounce-delay-ms = <5>;
|
||||
col-scan-delay-us = <2>;
|
||||
|
||||
row-gpios = <&gpio2 25 0
|
||||
&gpio2 26 0
|
||||
&gpio2 27 0>;
|
||||
|
||||
col-gpios = <&gpio2 21 0
|
||||
&gpio2 22 0>;
|
||||
|
||||
linux,keymap = <0x0000008B
|
||||
0x0100009E
|
||||
0x02000069
|
||||
0x0001006A
|
||||
0x0101001C
|
||||
0x0201006C>;
|
||||
};
|
7
Documentation/devicetree/bindings/input/pwm-beeper.txt
Normal file
7
Documentation/devicetree/bindings/input/pwm-beeper.txt
Normal file
@ -0,0 +1,7 @@
|
||||
* PWM beeper device tree bindings
|
||||
|
||||
Registers a PWM device as beeper.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "pwm-beeper"
|
||||
- pwms: phandle to the physical PWM device
|
39
Documentation/devicetree/bindings/input/stmpe-keypad.txt
Normal file
39
Documentation/devicetree/bindings/input/stmpe-keypad.txt
Normal file
@ -0,0 +1,39 @@
|
||||
* STMPE Keypad
|
||||
|
||||
Required properties:
|
||||
- compatible : "st,stmpe-keypad"
|
||||
- linux,keymap : See ./matrix-keymap.txt
|
||||
|
||||
Optional properties:
|
||||
- debounce-interval : Debouncing interval time in milliseconds
|
||||
- st,scan-count : Scanning cycles elapsed before key data is updated
|
||||
- st,no-autorepeat : If specified device will not autorepeat
|
||||
|
||||
Example:
|
||||
|
||||
stmpe_keypad {
|
||||
compatible = "st,stmpe-keypad";
|
||||
|
||||
debounce-interval = <64>;
|
||||
st,scan-count = <8>;
|
||||
st,no-autorepeat;
|
||||
|
||||
linux,keymap = <0x205006b
|
||||
0x4010074
|
||||
0x3050072
|
||||
0x1030004
|
||||
0x502006a
|
||||
0x500000a
|
||||
0x5008b
|
||||
0x706001c
|
||||
0x405000b
|
||||
0x6070003
|
||||
0x3040067
|
||||
0x303006c
|
||||
0x60400e7
|
||||
0x602009e
|
||||
0x4020073
|
||||
0x5050002
|
||||
0x4030069
|
||||
0x3020008>;
|
||||
};
|
@ -0,0 +1,8 @@
|
||||
|
||||
Required properties:
|
||||
- compatible: "ti,tca8418"
|
||||
- reg: the I2C address
|
||||
- interrupts: IRQ line number, should trigger on falling edge
|
||||
- keypad,num-rows: The number of rows
|
||||
- keypad,num-columns: The number of columns
|
||||
- linux,keymap: Keys definitions, see keypad-matrix.
|
@ -0,0 +1,34 @@
|
||||
* MELFAS MMS114 touchscreen controller
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "melfas,mms114"
|
||||
- reg: I2C address of the chip
|
||||
- interrupts: interrupt to which the chip is connected
|
||||
- x-size: horizontal resolution of touchscreen
|
||||
- y-size: vertical resolution of touchscreen
|
||||
|
||||
Optional properties:
|
||||
- contact-threshold:
|
||||
- moving-threshold:
|
||||
- x-invert: invert X axis
|
||||
- y-invert: invert Y axis
|
||||
|
||||
Example:
|
||||
|
||||
i2c@00000000 {
|
||||
/* ... */
|
||||
|
||||
touchscreen@48 {
|
||||
compatible = "melfas,mms114";
|
||||
reg = <0x48>;
|
||||
interrupts = <39 0>;
|
||||
x-size = <720>;
|
||||
y-size = <1280>;
|
||||
contact-threshold = <10>;
|
||||
moving-threshold = <10>;
|
||||
x-invert;
|
||||
y-invert;
|
||||
};
|
||||
|
||||
/* ... */
|
||||
};
|
@ -0,0 +1,43 @@
|
||||
STMPE Touchscreen
|
||||
----------------
|
||||
|
||||
Required properties:
|
||||
- compatible: "st,stmpe-ts"
|
||||
|
||||
Optional properties:
|
||||
- st,sample-time: ADC converstion time in number of clock. (0 -> 36 clocks, 1 ->
|
||||
44 clocks, 2 -> 56 clocks, 3 -> 64 clocks, 4 -> 80 clocks, 5 -> 96 clocks, 6
|
||||
-> 144 clocks), recommended is 4.
|
||||
- st,mod-12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC)
|
||||
- st,ref-sel: ADC reference source (0 -> internal reference, 1 -> external
|
||||
reference)
|
||||
- st,adc-freq: ADC Clock speed (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz)
|
||||
- st,ave-ctrl: Sample average control (0 -> 1 sample, 1 -> 2 samples, 2 -> 4
|
||||
samples, 3 -> 8 samples)
|
||||
- st,touch-det-delay: Touch detect interrupt delay (0 -> 10 us, 1 -> 50 us, 2 ->
|
||||
100 us, 3 -> 500 us, 4-> 1 ms, 5 -> 5 ms, 6 -> 10 ms, 7 -> 50 ms) recommended
|
||||
is 3
|
||||
- st,settling: Panel driver settling time (0 -> 10 us, 1 -> 100 us, 2 -> 500 us, 3
|
||||
-> 1 ms, 4 -> 5 ms, 5 -> 10 ms, 6 for 50 ms, 7 -> 100 ms) recommended is 2
|
||||
- st,fraction-z: Length of the fractional part in z (fraction-z ([0..7]) = Count of
|
||||
the fractional part) recommended is 7
|
||||
- st,i-drive: current limit value of the touchscreen drivers (0 -> 20 mA typical 35
|
||||
mA max, 1 -> 50 mA typical 80 mA max)
|
||||
|
||||
Node name must be stmpe_touchscreen and should be child node of stmpe node to
|
||||
which it belongs.
|
||||
|
||||
Example:
|
||||
|
||||
stmpe_touchscreen {
|
||||
compatible = "st,stmpe-ts";
|
||||
st,sample-time = <4>;
|
||||
st,mod-12b = <1>;
|
||||
st,ref-sel = <0>;
|
||||
st,adc-freq = <1>;
|
||||
st,ave-ctrl = <1>;
|
||||
st,touch-det-delay = <2>;
|
||||
st,settling = <2>;
|
||||
st,fraction-z = <7>;
|
||||
st,i-drive = <1>;
|
||||
};
|
@ -10,7 +10,7 @@ Supported chips:
|
||||
BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors
|
||||
(not yet published)
|
||||
|
||||
Author: Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
@ -503,7 +503,7 @@ F: include/linux/altera_uart.h
|
||||
F: include/linux/altera_jtaguart.h
|
||||
|
||||
AMD FAM15H PROCESSOR POWER MONITORING DRIVER
|
||||
M: Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
M: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/fam15h_power
|
||||
@ -2507,6 +2507,7 @@ M: Joonyoung Shim <jy0922.shim@samsung.com>
|
||||
M: Seung-Woo Kim <sw0312.kim@samsung.com>
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
|
||||
S: Supported
|
||||
F: drivers/gpu/drm/exynos
|
||||
F: include/drm/exynos*
|
||||
@ -5647,7 +5648,7 @@ S: Maintained
|
||||
F: drivers/pinctrl/spear/
|
||||
|
||||
PKTCDVD DRIVER
|
||||
M: Peter Osterlund <petero2@telia.com>
|
||||
M: Jiri Kosina <jkosina@suse.cz>
|
||||
S: Maintained
|
||||
F: drivers/block/pktcdvd.c
|
||||
F: include/linux/pktcdvd.h
|
||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
VERSION = 3
|
||||
PATCHLEVEL = 7
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc3
|
||||
EXTRAVERSION = -rc4
|
||||
NAME = Terrified Chipmunk
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -112,17 +112,6 @@ static void __init mipid_dev_init(void)
|
||||
omapfb_set_lcd_config(&nokia770_lcd_config);
|
||||
}
|
||||
|
||||
static void __init ads7846_dev_init(void)
|
||||
{
|
||||
if (gpio_request(ADS7846_PENDOWN_GPIO, "ADS7846 pendown") < 0)
|
||||
printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
|
||||
}
|
||||
|
||||
static int ads7846_get_pendown_state(void)
|
||||
{
|
||||
return !gpio_get_value(ADS7846_PENDOWN_GPIO);
|
||||
}
|
||||
|
||||
static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = {
|
||||
.x_max = 0x0fff,
|
||||
.y_max = 0x0fff,
|
||||
@ -131,7 +120,7 @@ static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata =
|
||||
.debounce_max = 10,
|
||||
.debounce_tol = 3,
|
||||
.debounce_rep = 1,
|
||||
.get_pendown_state = ads7846_get_pendown_state,
|
||||
.gpio_pendown = ADS7846_PENDOWN_GPIO,
|
||||
};
|
||||
|
||||
static struct spi_board_info nokia770_spi_board_info[] __initdata = {
|
||||
@ -241,7 +230,6 @@ static void __init omap_nokia770_init(void)
|
||||
omap_serial_init();
|
||||
omap_register_i2c_bus(1, 100, NULL, 0);
|
||||
hwa742_dev_init();
|
||||
ads7846_dev_init();
|
||||
mipid_dev_init();
|
||||
omap1_usb_init(&nokia770_usb_config);
|
||||
nokia770_mmc_init();
|
||||
|
@ -77,9 +77,6 @@ static struct i2c_board_info __initdata mop500_i2c0_devices_stuib[] = {
|
||||
* BU21013 ROHM touchscreen interface on the STUIBs
|
||||
*/
|
||||
|
||||
/* tracks number of bu21013 devices being enabled */
|
||||
static int bu21013_devices;
|
||||
|
||||
#define TOUCH_GPIO_PIN 84
|
||||
|
||||
#define TOUCH_XMAX 384
|
||||
@ -88,85 +85,8 @@ static int bu21013_devices;
|
||||
#define PRCMU_CLOCK_OCR 0x1CC
|
||||
#define TSC_EXT_CLOCK_9_6MHZ 0x840000
|
||||
|
||||
/**
|
||||
* bu21013_gpio_board_init : configures the touch panel.
|
||||
* @reset_pin: reset pin number
|
||||
* This function can be used to configures
|
||||
* the voltage and reset the touch panel controller.
|
||||
*/
|
||||
static int bu21013_gpio_board_init(int reset_pin)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
bu21013_devices++;
|
||||
if (bu21013_devices == 1) {
|
||||
retval = gpio_request(reset_pin, "touchp_reset");
|
||||
if (retval) {
|
||||
printk(KERN_ERR "Unable to request gpio reset_pin");
|
||||
return retval;
|
||||
}
|
||||
retval = gpio_direction_output(reset_pin, 1);
|
||||
if (retval < 0) {
|
||||
printk(KERN_ERR "%s: gpio direction failed\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* bu21013_gpio_board_exit : deconfigures the touch panel controller
|
||||
* @reset_pin: reset pin number
|
||||
* This function can be used to deconfigures the chip selection
|
||||
* for touch panel controller.
|
||||
*/
|
||||
static int bu21013_gpio_board_exit(int reset_pin)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (bu21013_devices == 1) {
|
||||
retval = gpio_direction_output(reset_pin, 0);
|
||||
if (retval < 0) {
|
||||
printk(KERN_ERR "%s: gpio direction failed\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
gpio_set_value(reset_pin, 0);
|
||||
}
|
||||
bu21013_devices--;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* bu21013_read_pin_val : get the interrupt pin value
|
||||
* This function can be used to get the interrupt pin value for touch panel
|
||||
* controller.
|
||||
*/
|
||||
static int bu21013_read_pin_val(void)
|
||||
{
|
||||
return gpio_get_value(TOUCH_GPIO_PIN);
|
||||
}
|
||||
|
||||
static struct bu21013_platform_device tsc_plat_device = {
|
||||
.cs_en = bu21013_gpio_board_init,
|
||||
.cs_dis = bu21013_gpio_board_exit,
|
||||
.irq_read_val = bu21013_read_pin_val,
|
||||
.irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN),
|
||||
.touch_x_max = TOUCH_XMAX,
|
||||
.touch_y_max = TOUCH_YMAX,
|
||||
.ext_clk = false,
|
||||
.x_flip = false,
|
||||
.y_flip = true,
|
||||
};
|
||||
|
||||
static struct bu21013_platform_device tsc_plat2_device = {
|
||||
.cs_en = bu21013_gpio_board_init,
|
||||
.cs_dis = bu21013_gpio_board_exit,
|
||||
.irq_read_val = bu21013_read_pin_val,
|
||||
.irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN),
|
||||
.touch_pin = TOUCH_GPIO_PIN,
|
||||
.touch_x_max = TOUCH_XMAX,
|
||||
.touch_y_max = TOUCH_YMAX,
|
||||
.ext_clk = false,
|
||||
@ -181,21 +101,16 @@ static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = {
|
||||
},
|
||||
{
|
||||
I2C_BOARD_INFO("bu21013_tp", 0x5D),
|
||||
.platform_data = &tsc_plat2_device,
|
||||
.platform_data = &tsc_plat_device,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
void __init mop500_stuib_init(void)
|
||||
{
|
||||
if (machine_is_hrefv60()) {
|
||||
if (machine_is_hrefv60())
|
||||
tsc_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
|
||||
tsc_plat2_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
|
||||
} else {
|
||||
else
|
||||
tsc_plat_device.cs_pin = GPIO_BU21013_CS;
|
||||
tsc_plat2_device.cs_pin = GPIO_BU21013_CS;
|
||||
|
||||
}
|
||||
|
||||
mop500_uib_i2c_add(0, mop500_i2c0_devices_stuib,
|
||||
ARRAY_SIZE(mop500_i2c0_devices_stuib));
|
||||
|
@ -48,20 +48,16 @@
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/opcodes-virt.h>
|
||||
#include <xen/interface/xen.h>
|
||||
|
||||
|
||||
/* HVC 0xEA1 */
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
#define xen_hvc .word 0xf7e08ea1
|
||||
#else
|
||||
#define xen_hvc .word 0xe140ea71
|
||||
#endif
|
||||
#define XEN_IMM 0xEA1
|
||||
|
||||
#define HYPERCALL_SIMPLE(hypercall) \
|
||||
ENTRY(HYPERVISOR_##hypercall) \
|
||||
mov r12, #__HYPERVISOR_##hypercall; \
|
||||
xen_hvc; \
|
||||
__HVC(XEN_IMM); \
|
||||
mov pc, lr; \
|
||||
ENDPROC(HYPERVISOR_##hypercall)
|
||||
|
||||
@ -76,7 +72,7 @@ ENTRY(HYPERVISOR_##hypercall) \
|
||||
stmdb sp!, {r4} \
|
||||
ldr r4, [sp, #4] \
|
||||
mov r12, #__HYPERVISOR_##hypercall; \
|
||||
xen_hvc \
|
||||
__HVC(XEN_IMM); \
|
||||
ldm sp!, {r4} \
|
||||
mov pc, lr \
|
||||
ENDPROC(HYPERVISOR_##hypercall)
|
||||
@ -100,7 +96,7 @@ ENTRY(privcmd_call)
|
||||
mov r2, r3
|
||||
ldr r3, [sp, #8]
|
||||
ldr r4, [sp, #4]
|
||||
xen_hvc
|
||||
__HVC(XEN_IMM)
|
||||
ldm sp!, {r4}
|
||||
mov pc, lr
|
||||
ENDPROC(privcmd_call);
|
||||
|
@ -13,6 +13,7 @@ config FRV
|
||||
select GENERIC_CPU_DEVICES
|
||||
select ARCH_WANT_IPC_PARSE_VERSION
|
||||
select GENERIC_KERNEL_THREAD
|
||||
select GENERIC_KERNEL_EXECVE
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
|
@ -17,6 +17,8 @@ PARAMS_PHYS = 0x0207c000
|
||||
INITRD_PHYS = 0x02180000
|
||||
INITRD_VIRT = 0x02180000
|
||||
|
||||
OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment
|
||||
|
||||
#
|
||||
# If you don't define ZRELADDR above,
|
||||
# then it defaults to ZTEXTADDR
|
||||
@ -32,18 +34,18 @@ Image: $(obj)/Image
|
||||
targets: $(obj)/Image
|
||||
|
||||
$(obj)/Image: vmlinux FORCE
|
||||
$(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@
|
||||
|
||||
#$(obj)/Image: $(CONFIGURE) $(SYSTEM)
|
||||
# $(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@
|
||||
# $(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@
|
||||
|
||||
bzImage: zImage
|
||||
|
||||
zImage: $(CONFIGURE) compressed/$(LINUX)
|
||||
$(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@
|
||||
|
||||
bootpImage: bootp/bootp
|
||||
$(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@
|
||||
|
||||
compressed/$(LINUX): $(LINUX) dep
|
||||
@$(MAKE) -C compressed $(LINUX)
|
||||
|
@ -30,7 +30,6 @@
|
||||
#define __ARCH_WANT_SYS_RT_SIGACTION
|
||||
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||
#define __ARCH_WANT_SYS_EXECVE
|
||||
#define __ARCH_WANT_KERNEL_EXECVE
|
||||
|
||||
/*
|
||||
* "Conditional" syscalls
|
||||
|
@ -869,11 +869,6 @@ ret_from_kernel_thread:
|
||||
call schedule_tail
|
||||
calll.p @(gr21,gr0)
|
||||
or gr20,gr20,gr8
|
||||
bra sys_exit
|
||||
|
||||
.globl ret_from_kernel_execve
|
||||
ret_from_kernel_execve:
|
||||
ori gr28,0,sp
|
||||
bra __syscall_exit
|
||||
|
||||
###################################################################################################
|
||||
@ -1080,27 +1075,10 @@ __entry_return_from_kernel_interrupt:
|
||||
subicc gr5,#0,gr0,icc0
|
||||
beq icc0,#0,__entry_return_direct
|
||||
|
||||
__entry_preempt_need_resched:
|
||||
ldi @(gr15,#TI_FLAGS),gr4
|
||||
andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0
|
||||
beq icc0,#1,__entry_return_direct
|
||||
|
||||
setlos #PREEMPT_ACTIVE,gr5
|
||||
sti gr5,@(gr15,#TI_FLAGS)
|
||||
|
||||
andi gr23,#~PSR_PIL,gr23
|
||||
movgs gr23,psr
|
||||
|
||||
call schedule
|
||||
sti gr0,@(gr15,#TI_PRE_COUNT)
|
||||
|
||||
movsg psr,gr23
|
||||
ori gr23,#PSR_PIL_14,gr23
|
||||
movgs gr23,psr
|
||||
bra __entry_preempt_need_resched
|
||||
#else
|
||||
bra __entry_return_direct
|
||||
subcc gr0,gr0,gr0,icc2 /* set Z and clear C */
|
||||
call preempt_schedule_irq
|
||||
#endif
|
||||
bra __entry_return_direct
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
@ -181,6 +181,9 @@ int copy_thread(unsigned long clone_flags,
|
||||
childregs = (struct pt_regs *)
|
||||
(task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
|
||||
|
||||
/* set up the userspace frame (the only place that the USP is stored) */
|
||||
*childregs = *__kernel_frame0_ptr;
|
||||
|
||||
p->set_child_tid = p->clear_child_tid = NULL;
|
||||
|
||||
p->thread.frame = childregs;
|
||||
@ -191,10 +194,8 @@ int copy_thread(unsigned long clone_flags,
|
||||
p->thread.frame0 = childregs;
|
||||
|
||||
if (unlikely(!regs)) {
|
||||
memset(childregs, 0, sizeof(struct pt_regs));
|
||||
childregs->gr9 = usp; /* function */
|
||||
childregs->gr8 = arg;
|
||||
childregs->psr = PSR_S;
|
||||
p->thread.pc = (unsigned long) ret_from_kernel_thread;
|
||||
save_user_regs(p->thread.user);
|
||||
return 0;
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/pci.h>
|
||||
|
@ -33,7 +33,6 @@
|
||||
#ifndef _ASM_X86_XEN_HYPERVISOR_H
|
||||
#define _ASM_X86_XEN_HYPERVISOR_H
|
||||
|
||||
/* arch/i386/kernel/setup.c */
|
||||
extern struct shared_info *HYPERVISOR_shared_info;
|
||||
extern struct start_info *xen_start_info;
|
||||
|
||||
|
@ -3779,7 +3779,7 @@ static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
|
||||
{
|
||||
struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0];
|
||||
|
||||
memcpy(vcpu->run->mmio.data, frag->data, frag->len);
|
||||
memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len));
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
@ -3832,18 +3832,11 @@ mmio:
|
||||
bytes -= handled;
|
||||
val += handled;
|
||||
|
||||
while (bytes) {
|
||||
unsigned now = min(bytes, 8U);
|
||||
|
||||
frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
|
||||
frag->gpa = gpa;
|
||||
frag->data = val;
|
||||
frag->len = now;
|
||||
|
||||
gpa += now;
|
||||
val += now;
|
||||
bytes -= now;
|
||||
}
|
||||
WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS);
|
||||
frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
|
||||
frag->gpa = gpa;
|
||||
frag->data = val;
|
||||
frag->len = bytes;
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
@ -3890,7 +3883,7 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
|
||||
vcpu->mmio_needed = 1;
|
||||
vcpu->mmio_cur_fragment = 0;
|
||||
|
||||
vcpu->run->mmio.len = vcpu->mmio_fragments[0].len;
|
||||
vcpu->run->mmio.len = min(8u, vcpu->mmio_fragments[0].len);
|
||||
vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write;
|
||||
vcpu->run->exit_reason = KVM_EXIT_MMIO;
|
||||
vcpu->run->mmio.phys_addr = gpa;
|
||||
@ -5522,28 +5515,44 @@ static int complete_emulated_pio(struct kvm_vcpu *vcpu)
|
||||
*
|
||||
* read:
|
||||
* for each fragment
|
||||
* write gpa, len
|
||||
* exit
|
||||
* copy data
|
||||
* for each mmio piece in the fragment
|
||||
* write gpa, len
|
||||
* exit
|
||||
* copy data
|
||||
* execute insn
|
||||
*
|
||||
* write:
|
||||
* for each fragment
|
||||
* write gpa, len
|
||||
* copy data
|
||||
* exit
|
||||
* for each mmio piece in the fragment
|
||||
* write gpa, len
|
||||
* copy data
|
||||
* exit
|
||||
*/
|
||||
static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_run *run = vcpu->run;
|
||||
struct kvm_mmio_fragment *frag;
|
||||
unsigned len;
|
||||
|
||||
BUG_ON(!vcpu->mmio_needed);
|
||||
|
||||
/* Complete previous fragment */
|
||||
frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++];
|
||||
frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment];
|
||||
len = min(8u, frag->len);
|
||||
if (!vcpu->mmio_is_write)
|
||||
memcpy(frag->data, run->mmio.data, frag->len);
|
||||
memcpy(frag->data, run->mmio.data, len);
|
||||
|
||||
if (frag->len <= 8) {
|
||||
/* Switch to the next fragment. */
|
||||
frag++;
|
||||
vcpu->mmio_cur_fragment++;
|
||||
} else {
|
||||
/* Go forward to the next mmio piece. */
|
||||
frag->data += len;
|
||||
frag->gpa += len;
|
||||
frag->len -= len;
|
||||
}
|
||||
|
||||
if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
|
||||
vcpu->mmio_needed = 0;
|
||||
if (vcpu->mmio_is_write)
|
||||
@ -5551,13 +5560,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
|
||||
vcpu->mmio_read_completed = 1;
|
||||
return complete_emulated_io(vcpu);
|
||||
}
|
||||
/* Initiate next fragment */
|
||||
++frag;
|
||||
|
||||
run->exit_reason = KVM_EXIT_MMIO;
|
||||
run->mmio.phys_addr = frag->gpa;
|
||||
if (vcpu->mmio_is_write)
|
||||
memcpy(run->mmio.data, frag->data, frag->len);
|
||||
run->mmio.len = frag->len;
|
||||
memcpy(run->mmio.data, frag->data, min(8u, frag->len));
|
||||
run->mmio.len = min(8u, frag->len);
|
||||
run->mmio.is_write = vcpu->mmio_is_write;
|
||||
vcpu->arch.complete_userspace_io = complete_emulated_mmio;
|
||||
return 0;
|
||||
|
@ -1288,6 +1288,25 @@ unsigned long xen_read_cr2_direct(void)
|
||||
return this_cpu_read(xen_vcpu_info.arch.cr2);
|
||||
}
|
||||
|
||||
void xen_flush_tlb_all(void)
|
||||
{
|
||||
struct mmuext_op *op;
|
||||
struct multicall_space mcs;
|
||||
|
||||
trace_xen_mmu_flush_tlb_all(0);
|
||||
|
||||
preempt_disable();
|
||||
|
||||
mcs = xen_mc_entry(sizeof(*op));
|
||||
|
||||
op = mcs.args;
|
||||
op->cmd = MMUEXT_TLB_FLUSH_ALL;
|
||||
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
|
||||
|
||||
xen_mc_issue(PARAVIRT_LAZY_MMU);
|
||||
|
||||
preempt_enable();
|
||||
}
|
||||
static void xen_flush_tlb(void)
|
||||
{
|
||||
struct mmuext_op *op;
|
||||
@ -2518,7 +2537,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
|
||||
err = 0;
|
||||
out:
|
||||
|
||||
flush_tlb_all();
|
||||
xen_flush_tlb_all();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ config XTENSA
|
||||
select GENERIC_CPU_DEVICES
|
||||
select MODULES_USE_ELF_RELA
|
||||
select GENERIC_PCI_IOMAP
|
||||
select GENERIC_KERNEL_THREAD
|
||||
select GENERIC_KERNEL_EXECVE
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
help
|
||||
Xtensa processors are 32-bit RISC machines designed by Tensilica
|
||||
|
@ -62,6 +62,10 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
|
||||
static inline void iounmap(volatile void __iomem *addr)
|
||||
{
|
||||
}
|
||||
|
||||
#define virt_to_bus virt_to_phys
|
||||
#define bus_to_virt phys_to_virt
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
/*
|
||||
|
@ -152,6 +152,7 @@ struct thread_struct {
|
||||
|
||||
/* Clearing a0 terminates the backtrace. */
|
||||
#define start_thread(regs, new_pc, new_sp) \
|
||||
memset(regs, 0, sizeof(*regs)); \
|
||||
regs->pc = new_pc; \
|
||||
regs->ps = USER_PS_VALUE; \
|
||||
regs->areg[1] = new_sp; \
|
||||
@ -168,9 +169,6 @@ struct mm_struct;
|
||||
/* Free all resources held by a thread. */
|
||||
#define release_thread(thread) do { } while(0)
|
||||
|
||||
/* Create a kernel thread without removing it from tasklists */
|
||||
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
|
||||
|
||||
/* Copy and release all segment info associated with a VM */
|
||||
#define copy_segments(p, mm) do { } while(0)
|
||||
#define release_segments(mm) do { } while(0)
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
struct pt_regs;
|
||||
struct sigaction;
|
||||
asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
|
||||
asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*);
|
||||
asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
|
||||
asmlinkage long xtensa_ptrace(long, long, long, long);
|
||||
asmlinkage long xtensa_sigreturn(struct pt_regs*);
|
||||
|
@ -1,16 +1,9 @@
|
||||
/*
|
||||
* include/asm-xtensa/unistd.h
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2001 - 2005 Tensilica Inc.
|
||||
*/
|
||||
#ifndef _XTENSA_UNISTD_H
|
||||
#define _XTENSA_UNISTD_H
|
||||
|
||||
#define __ARCH_WANT_SYS_EXECVE
|
||||
#include <uapi/asm/unistd.h>
|
||||
|
||||
|
||||
/*
|
||||
* "Conditional" syscalls
|
||||
*
|
||||
@ -37,3 +30,5 @@
|
||||
#define __IGNORE_mmap /* use mmap2 */
|
||||
#define __IGNORE_vfork /* use clone */
|
||||
#define __IGNORE_fadvise64 /* use fadvise64_64 */
|
||||
|
||||
#endif /* _XTENSA_UNISTD_H */
|
||||
|
@ -1,14 +1,4 @@
|
||||
/*
|
||||
* include/asm-xtensa/unistd.h
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2001 - 2012 Tensilica Inc.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_XTENSA_UNISTD_H
|
||||
#if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL)
|
||||
#define _UAPI_XTENSA_UNISTD_H
|
||||
|
||||
#ifndef __SYSCALL
|
||||
@ -272,7 +262,7 @@ __SYSCALL(115, sys_sendmmsg, 4)
|
||||
#define __NR_clone 116
|
||||
__SYSCALL(116, xtensa_clone, 5)
|
||||
#define __NR_execve 117
|
||||
__SYSCALL(117, xtensa_execve, 3)
|
||||
__SYSCALL(117, sys_execve, 3)
|
||||
#define __NR_exit 118
|
||||
__SYSCALL(118, sys_exit, 1)
|
||||
#define __NR_exit_group 119
|
||||
@ -759,4 +749,6 @@ __SYSCALL(331, sys_kcmp, 5)
|
||||
|
||||
#define SYS_XTENSA_COUNT 5 /* count */
|
||||
|
||||
#undef __SYSCALL
|
||||
|
||||
#endif /* _UAPI_XTENSA_UNISTD_H */
|
||||
|
@ -1832,50 +1832,6 @@ ENTRY(system_call)
|
||||
retw
|
||||
|
||||
|
||||
/*
|
||||
* Create a kernel thread
|
||||
*
|
||||
* int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
|
||||
* a2 a2 a3 a4
|
||||
*/
|
||||
|
||||
ENTRY(kernel_thread)
|
||||
entry a1, 16
|
||||
|
||||
mov a5, a2 # preserve fn over syscall
|
||||
mov a7, a3 # preserve args over syscall
|
||||
|
||||
movi a3, _CLONE_VM | _CLONE_UNTRACED
|
||||
movi a2, __NR_clone
|
||||
or a6, a4, a3 # arg0: flags
|
||||
mov a3, a1 # arg1: sp
|
||||
syscall
|
||||
|
||||
beq a3, a1, 1f # branch if parent
|
||||
mov a6, a7 # args
|
||||
callx4 a5 # fn(args)
|
||||
|
||||
movi a2, __NR_exit
|
||||
syscall # return value of fn(args) still in a6
|
||||
|
||||
1: retw
|
||||
|
||||
/*
|
||||
* Do a system call from kernel instead of calling sys_execve, so we end up
|
||||
* with proper pt_regs.
|
||||
*
|
||||
* int kernel_execve(const char *fname, char *const argv[], charg *const envp[])
|
||||
* a2 a2 a3 a4
|
||||
*/
|
||||
|
||||
ENTRY(kernel_execve)
|
||||
entry a1, 16
|
||||
mov a6, a2 # arg0 is in a6
|
||||
movi a2, __NR_execve
|
||||
syscall
|
||||
|
||||
retw
|
||||
|
||||
/*
|
||||
* Task switch.
|
||||
*
|
||||
@ -1958,3 +1914,16 @@ ENTRY(ret_from_fork)
|
||||
|
||||
j common_exception_return
|
||||
|
||||
/*
|
||||
* Kernel thread creation helper
|
||||
* On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg
|
||||
* left from _switch_to: a6 = prev
|
||||
*/
|
||||
ENTRY(ret_from_kernel_thread)
|
||||
|
||||
call4 schedule_tail
|
||||
mov a6, a3
|
||||
callx4 a2
|
||||
j common_exception_return
|
||||
|
||||
ENDPROC(ret_from_kernel_thread)
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <asm/regs.h>
|
||||
|
||||
extern void ret_from_fork(void);
|
||||
extern void ret_from_kernel_thread(void);
|
||||
|
||||
struct task_struct *current_set[NR_CPUS] = {&init_task, };
|
||||
|
||||
@ -158,18 +159,30 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
|
||||
/*
|
||||
* Copy thread.
|
||||
*
|
||||
* There are two modes in which this function is called:
|
||||
* 1) Userspace thread creation,
|
||||
* regs != NULL, usp_thread_fn is userspace stack pointer.
|
||||
* It is expected to copy parent regs (in case CLONE_VM is not set
|
||||
* in the clone_flags) and set up passed usp in the childregs.
|
||||
* 2) Kernel thread creation,
|
||||
* regs == NULL, usp_thread_fn is the function to run in the new thread
|
||||
* and thread_fn_arg is its parameter.
|
||||
* childregs are not used for the kernel threads.
|
||||
*
|
||||
* The stack layout for the new thread looks like this:
|
||||
*
|
||||
* +------------------------+ <- sp in childregs (= tos)
|
||||
* +------------------------+
|
||||
* | childregs |
|
||||
* +------------------------+ <- thread.sp = sp in dummy-frame
|
||||
* | dummy-frame | (saved in dummy-frame spill-area)
|
||||
* +------------------------+
|
||||
*
|
||||
* We create a dummy frame to return to ret_from_fork:
|
||||
* a0 points to ret_from_fork (simulating a call4)
|
||||
* We create a dummy frame to return to either ret_from_fork or
|
||||
* ret_from_kernel_thread:
|
||||
* a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4)
|
||||
* sp points to itself (thread.sp)
|
||||
* a2, a3 are unused.
|
||||
* a2, a3 are unused for userspace threads,
|
||||
* a2 points to thread_fn, a3 holds thread_fn arg for kernel threads.
|
||||
*
|
||||
* Note: This is a pristine frame, so we don't need any spill region on top of
|
||||
* childregs.
|
||||
@ -185,43 +198,63 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
|
||||
* involved. Much simpler to just not copy those live frames across.
|
||||
*/
|
||||
|
||||
int copy_thread(unsigned long clone_flags, unsigned long usp,
|
||||
unsigned long unused,
|
||||
struct task_struct * p, struct pt_regs * regs)
|
||||
int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
|
||||
unsigned long thread_fn_arg,
|
||||
struct task_struct *p, struct pt_regs *unused)
|
||||
{
|
||||
struct pt_regs *childregs;
|
||||
unsigned long tos;
|
||||
int user_mode = user_mode(regs);
|
||||
struct pt_regs *childregs = task_pt_regs(p);
|
||||
|
||||
#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
|
||||
struct thread_info *ti;
|
||||
#endif
|
||||
|
||||
/* Set up new TSS. */
|
||||
tos = (unsigned long)task_stack_page(p) + THREAD_SIZE;
|
||||
if (user_mode)
|
||||
childregs = (struct pt_regs*)(tos - PT_USER_SIZE);
|
||||
else
|
||||
childregs = (struct pt_regs*)tos - 1;
|
||||
|
||||
/* This does not copy all the regs. In a bout of brilliance or madness,
|
||||
ARs beyond a0-a15 exist past the end of the struct. */
|
||||
*childregs = *regs;
|
||||
|
||||
/* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
|
||||
*((int*)childregs - 3) = (unsigned long)childregs;
|
||||
*((int*)childregs - 4) = 0;
|
||||
|
||||
childregs->areg[2] = 0;
|
||||
p->set_child_tid = p->clear_child_tid = NULL;
|
||||
p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1);
|
||||
p->thread.sp = (unsigned long)childregs;
|
||||
|
||||
if (user_mode(regs)) {
|
||||
if (!(p->flags & PF_KTHREAD)) {
|
||||
struct pt_regs *regs = current_pt_regs();
|
||||
unsigned long usp = usp_thread_fn ?
|
||||
usp_thread_fn : regs->areg[1];
|
||||
|
||||
p->thread.ra = MAKE_RA_FOR_CALL(
|
||||
(unsigned long)ret_from_fork, 0x1);
|
||||
|
||||
/* This does not copy all the regs.
|
||||
* In a bout of brilliance or madness,
|
||||
* ARs beyond a0-a15 exist past the end of the struct.
|
||||
*/
|
||||
*childregs = *regs;
|
||||
childregs->areg[1] = usp;
|
||||
childregs->areg[2] = 0;
|
||||
|
||||
/* When sharing memory with the parent thread, the child
|
||||
usually starts on a pristine stack, so we have to reset
|
||||
windowbase, windowstart and wmask.
|
||||
(Note that such a new thread is required to always create
|
||||
an initial call4 frame)
|
||||
The exception is vfork, where the new thread continues to
|
||||
run on the parent's stack until it calls execve. This could
|
||||
be a call8 or call12, which requires a legal stack frame
|
||||
of the previous caller for the overflow handlers to work.
|
||||
(Note that it's always legal to overflow live registers).
|
||||
In this case, ensure to spill at least the stack pointer
|
||||
of that frame. */
|
||||
|
||||
if (clone_flags & CLONE_VM) {
|
||||
childregs->wmask = 1; /* can't share live windows */
|
||||
/* check that caller window is live and same stack */
|
||||
int len = childregs->wmask & ~0xf;
|
||||
if (regs->areg[1] == usp && len != 0) {
|
||||
int callinc = (regs->areg[0] >> 30) & 3;
|
||||
int caller_ars = XCHAL_NUM_AREGS - callinc * 4;
|
||||
put_user(regs->areg[caller_ars+1],
|
||||
(unsigned __user*)(usp - 12));
|
||||
}
|
||||
childregs->wmask = 1;
|
||||
childregs->windowstart = 1;
|
||||
childregs->windowbase = 0;
|
||||
} else {
|
||||
int len = childregs->wmask & ~0xf;
|
||||
memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
|
||||
@ -230,11 +263,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
|
||||
// FIXME: we need to set THREADPTR in thread_info...
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
childregs->areg[2] = childregs->areg[6];
|
||||
|
||||
} else {
|
||||
/* In kernel space, we start a new thread with a new stack. */
|
||||
childregs->wmask = 1;
|
||||
childregs->areg[1] = tos;
|
||||
p->thread.ra = MAKE_RA_FOR_CALL(
|
||||
(unsigned long)ret_from_kernel_thread, 1);
|
||||
|
||||
/* pass parameters to ret_from_kernel_thread:
|
||||
* a2 = thread_fn, a3 = thread_fn arg
|
||||
*/
|
||||
*((int *)childregs - 1) = thread_fn_arg;
|
||||
*((int *)childregs - 2) = usp_thread_fn;
|
||||
|
||||
/* Childregs are only used when we're going to userspace
|
||||
* in which case start_thread will set them up.
|
||||
*/
|
||||
}
|
||||
|
||||
#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
|
||||
@ -330,32 +371,5 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
|
||||
void __user *child_tid, long a5,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if (!newsp)
|
||||
newsp = regs->areg[1];
|
||||
return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
|
||||
}
|
||||
|
||||
/*
|
||||
* xtensa_execve() executes a new program.
|
||||
*/
|
||||
|
||||
asmlinkage
|
||||
long xtensa_execve(const char __user *name,
|
||||
const char __user *const __user *argv,
|
||||
const char __user *const __user *envp,
|
||||
long a3, long a4, long a5,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
long error;
|
||||
struct filename *filename;
|
||||
|
||||
filename = getname(name);
|
||||
error = PTR_ERR(filename);
|
||||
if (IS_ERR(filename))
|
||||
goto out;
|
||||
error = do_execve(filename->name, argv, envp, regs);
|
||||
putname(filename);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -32,10 +32,8 @@ typedef void (*syscall_t)(void);
|
||||
syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
|
||||
[0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall,
|
||||
|
||||
#undef __SYSCALL
|
||||
#define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol,
|
||||
#undef __KERNEL_SYSCALLS__
|
||||
#include <asm/unistd.h>
|
||||
#include <uapi/asm/unistd.h>
|
||||
};
|
||||
|
||||
asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
|
||||
@ -49,7 +47,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
|
||||
return (long)ret;
|
||||
}
|
||||
|
||||
asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len)
|
||||
asmlinkage long xtensa_fadvise64_64(int fd, int advice,
|
||||
unsigned long long offset, unsigned long long len)
|
||||
{
|
||||
return sys_fadvise64_64(fd, offset, len, advice);
|
||||
}
|
||||
|
@ -43,7 +43,6 @@ EXPORT_SYMBOL(__strncpy_user);
|
||||
EXPORT_SYMBOL(clear_page);
|
||||
EXPORT_SYMBOL(copy_page);
|
||||
|
||||
EXPORT_SYMBOL(kernel_thread);
|
||||
EXPORT_SYMBOL(empty_zero_page);
|
||||
|
||||
/*
|
||||
|
@ -89,7 +89,7 @@ config BLK_DEV_INTEGRITY
|
||||
|
||||
config BLK_DEV_THROTTLING
|
||||
bool "Block layer bio throttling support"
|
||||
depends on BLK_CGROUP=y && EXPERIMENTAL
|
||||
depends on BLK_CGROUP=y
|
||||
default n
|
||||
---help---
|
||||
Block layer bio throttling support. It can be used to limit
|
||||
|
@ -285,6 +285,13 @@ static void blkg_destroy_all(struct request_queue *q)
|
||||
blkg_destroy(blkg);
|
||||
spin_unlock(&blkcg->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* root blkg is destroyed. Just clear the pointer since
|
||||
* root_rl does not take reference on root blkg.
|
||||
*/
|
||||
q->root_blkg = NULL;
|
||||
q->root_rl.blkg = NULL;
|
||||
}
|
||||
|
||||
static void blkg_rcu_free(struct rcu_head *rcu_head)
|
||||
@ -326,6 +333,9 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl,
|
||||
*/
|
||||
if (rl == &q->root_rl) {
|
||||
ent = &q->blkg_list;
|
||||
/* There are no more block groups, hence no request lists */
|
||||
if (list_empty(ent))
|
||||
return NULL;
|
||||
} else {
|
||||
blkg = container_of(rl, struct blkcg_gq, rl);
|
||||
ent = &blkg->q_node;
|
||||
|
@ -2868,7 +2868,8 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b)
|
||||
struct request *rqa = container_of(a, struct request, queuelist);
|
||||
struct request *rqb = container_of(b, struct request, queuelist);
|
||||
|
||||
return !(rqa->q <= rqb->q);
|
||||
return !(rqa->q < rqb->q ||
|
||||
(rqa->q == rqb->q && blk_rq_pos(rqa) < blk_rq_pos(rqb)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1345,12 +1345,15 @@ static int
|
||||
acpi_video_bus_get_devices(struct acpi_video_bus *video,
|
||||
struct acpi_device *device)
|
||||
{
|
||||
int status;
|
||||
int status = 0;
|
||||
struct acpi_device *dev;
|
||||
|
||||
status = acpi_video_device_enumerate(video);
|
||||
if (status)
|
||||
return status;
|
||||
/*
|
||||
* There are systems where video module known to work fine regardless
|
||||
* of broken _DOD and ignoring returned value here doesn't cause
|
||||
* any issues later.
|
||||
*/
|
||||
acpi_video_device_enumerate(video);
|
||||
|
||||
list_for_each_entry(dev, &device->children, node) {
|
||||
|
||||
|
@ -131,6 +131,7 @@ config BLK_CPQ_DA
|
||||
config BLK_CPQ_CISS_DA
|
||||
tristate "Compaq Smart Array 5xxx support"
|
||||
depends on PCI
|
||||
select CHECK_SIGNATURE
|
||||
help
|
||||
This is the driver for Compaq Smart Array 5xxx controllers.
|
||||
Everyone using these boards should say Y here.
|
||||
@ -166,8 +167,8 @@ config BLK_DEV_DAC960
|
||||
module will be called DAC960.
|
||||
|
||||
config BLK_DEV_UMEM
|
||||
tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)"
|
||||
depends on PCI && EXPERIMENTAL
|
||||
tristate "Micro Memory MM5415 Battery Backed RAM support"
|
||||
depends on PCI
|
||||
---help---
|
||||
Saying Y here will include support for the MM5415 family of
|
||||
battery backed (Non-volatile) RAM cards.
|
||||
@ -430,8 +431,8 @@ config CDROM_PKTCDVD_BUFFERS
|
||||
a disc is opened for writing.
|
||||
|
||||
config CDROM_PKTCDVD_WCACHE
|
||||
bool "Enable write caching (EXPERIMENTAL)"
|
||||
depends on CDROM_PKTCDVD && EXPERIMENTAL
|
||||
bool "Enable write caching"
|
||||
depends on CDROM_PKTCDVD
|
||||
help
|
||||
If enabled, write caching will be set for the CD-R/W device. For now
|
||||
this option is dangerous unless the CD-RW media is known good, as we
|
||||
@ -508,8 +509,8 @@ config XEN_BLKDEV_BACKEND
|
||||
|
||||
|
||||
config VIRTIO_BLK
|
||||
tristate "Virtio block driver (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && VIRTIO
|
||||
tristate "Virtio block driver"
|
||||
depends on VIRTIO
|
||||
---help---
|
||||
This is the virtual block driver for virtio. It can be used with
|
||||
lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
|
||||
@ -528,7 +529,7 @@ config BLK_DEV_HD
|
||||
|
||||
config BLK_DEV_RBD
|
||||
tristate "Rados block device (RBD)"
|
||||
depends on INET && EXPERIMENTAL && BLOCK
|
||||
depends on INET && BLOCK
|
||||
select CEPH_LIB
|
||||
select LIBCRC32C
|
||||
select CRYPTO_AES
|
||||
|
@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev)
|
||||
return;
|
||||
}
|
||||
/* write all data in the battery backed cache to disk */
|
||||
memset(flush_buf, 0, 4);
|
||||
return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf,
|
||||
4, 0, CTLR_LUNID, TYPE_CMD);
|
||||
kfree(flush_buf);
|
||||
|
@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = {
|
||||
|
||||
static struct platform_device floppy_device[N_DRIVE];
|
||||
|
||||
static bool floppy_available(int drive)
|
||||
{
|
||||
if (!(allowed_drive_mask & (1 << drive)))
|
||||
return false;
|
||||
if (fdc_state[FDC(drive)].version == FDC_NONE)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct kobject *floppy_find(dev_t dev, int *part, void *data)
|
||||
{
|
||||
int drive = (*part & 3) | ((*part & 0x80) >> 5);
|
||||
if (drive >= N_DRIVE ||
|
||||
!(allowed_drive_mask & (1 << drive)) ||
|
||||
fdc_state[FDC(drive)].version == FDC_NONE)
|
||||
if (drive >= N_DRIVE || !floppy_available(drive))
|
||||
return NULL;
|
||||
if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
|
||||
return NULL;
|
||||
@ -4124,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
|
||||
|
||||
static int __init do_floppy_init(void)
|
||||
{
|
||||
int i, unit, drive;
|
||||
int err, dr;
|
||||
int i, unit, drive, err;
|
||||
|
||||
set_debugt();
|
||||
interruptjiffies = resultjiffies = jiffies;
|
||||
@ -4137,34 +4143,32 @@ static int __init do_floppy_init(void)
|
||||
|
||||
raw_cmd = NULL;
|
||||
|
||||
for (dr = 0; dr < N_DRIVE; dr++) {
|
||||
disks[dr] = alloc_disk(1);
|
||||
if (!disks[dr]) {
|
||||
floppy_wq = alloc_ordered_workqueue("floppy", 0);
|
||||
if (!floppy_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
for (drive = 0; drive < N_DRIVE; drive++) {
|
||||
disks[drive] = alloc_disk(1);
|
||||
if (!disks[drive]) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_disk;
|
||||
}
|
||||
|
||||
floppy_wq = alloc_ordered_workqueue("floppy", 0);
|
||||
if (!floppy_wq) {
|
||||
disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock);
|
||||
if (!disks[drive]->queue) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_disk;
|
||||
}
|
||||
|
||||
disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
|
||||
if (!disks[dr]->queue) {
|
||||
err = -ENOMEM;
|
||||
goto out_destroy_workq;
|
||||
}
|
||||
blk_queue_max_hw_sectors(disks[drive]->queue, 64);
|
||||
disks[drive]->major = FLOPPY_MAJOR;
|
||||
disks[drive]->first_minor = TOMINOR(drive);
|
||||
disks[drive]->fops = &floppy_fops;
|
||||
sprintf(disks[drive]->disk_name, "fd%d", drive);
|
||||
|
||||
blk_queue_max_hw_sectors(disks[dr]->queue, 64);
|
||||
disks[dr]->major = FLOPPY_MAJOR;
|
||||
disks[dr]->first_minor = TOMINOR(dr);
|
||||
disks[dr]->fops = &floppy_fops;
|
||||
sprintf(disks[dr]->disk_name, "fd%d", dr);
|
||||
|
||||
init_timer(&motor_off_timer[dr]);
|
||||
motor_off_timer[dr].data = dr;
|
||||
motor_off_timer[dr].function = motor_off_callback;
|
||||
init_timer(&motor_off_timer[drive]);
|
||||
motor_off_timer[drive].data = drive;
|
||||
motor_off_timer[drive].function = motor_off_callback;
|
||||
}
|
||||
|
||||
err = register_blkdev(FLOPPY_MAJOR, "fd");
|
||||
@ -4282,9 +4286,7 @@ static int __init do_floppy_init(void)
|
||||
}
|
||||
|
||||
for (drive = 0; drive < N_DRIVE; drive++) {
|
||||
if (!(allowed_drive_mask & (1 << drive)))
|
||||
continue;
|
||||
if (fdc_state[FDC(drive)].version == FDC_NONE)
|
||||
if (!floppy_available(drive))
|
||||
continue;
|
||||
|
||||
floppy_device[drive].name = floppy_device_name;
|
||||
@ -4293,7 +4295,7 @@ static int __init do_floppy_init(void)
|
||||
|
||||
err = platform_device_register(&floppy_device[drive]);
|
||||
if (err)
|
||||
goto out_release_dma;
|
||||
goto out_remove_drives;
|
||||
|
||||
err = device_create_file(&floppy_device[drive].dev,
|
||||
&dev_attr_cmos);
|
||||
@ -4311,29 +4313,34 @@ static int __init do_floppy_init(void)
|
||||
|
||||
out_unreg_platform_dev:
|
||||
platform_device_unregister(&floppy_device[drive]);
|
||||
out_remove_drives:
|
||||
while (drive--) {
|
||||
if (floppy_available(drive)) {
|
||||
del_gendisk(disks[drive]);
|
||||
device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
|
||||
platform_device_unregister(&floppy_device[drive]);
|
||||
}
|
||||
}
|
||||
out_release_dma:
|
||||
if (atomic_read(&usage_count))
|
||||
floppy_release_irq_and_dma();
|
||||
out_unreg_region:
|
||||
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
|
||||
platform_driver_unregister(&floppy_driver);
|
||||
out_destroy_workq:
|
||||
destroy_workqueue(floppy_wq);
|
||||
out_unreg_blkdev:
|
||||
unregister_blkdev(FLOPPY_MAJOR, "fd");
|
||||
out_put_disk:
|
||||
while (dr--) {
|
||||
del_timer_sync(&motor_off_timer[dr]);
|
||||
if (disks[dr]->queue) {
|
||||
blk_cleanup_queue(disks[dr]->queue);
|
||||
/*
|
||||
* put_disk() is not paired with add_disk() and
|
||||
* will put queue reference one extra time. fix it.
|
||||
*/
|
||||
disks[dr]->queue = NULL;
|
||||
for (drive = 0; drive < N_DRIVE; drive++) {
|
||||
if (!disks[drive])
|
||||
break;
|
||||
if (disks[drive]->queue) {
|
||||
del_timer_sync(&motor_off_timer[drive]);
|
||||
blk_cleanup_queue(disks[drive]->queue);
|
||||
disks[drive]->queue = NULL;
|
||||
}
|
||||
put_disk(disks[dr]);
|
||||
put_disk(disks[drive]);
|
||||
}
|
||||
destroy_workqueue(floppy_wq);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -4551,8 +4558,7 @@ static void __exit floppy_module_exit(void)
|
||||
for (drive = 0; drive < N_DRIVE; drive++) {
|
||||
del_timer_sync(&motor_off_timer[drive]);
|
||||
|
||||
if ((allowed_drive_mask & (1 << drive)) &&
|
||||
fdc_state[FDC(drive)].version != FDC_NONE) {
|
||||
if (floppy_available(drive)) {
|
||||
del_gendisk(disks[drive]);
|
||||
device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
|
||||
platform_device_unregister(&floppy_device[drive]);
|
||||
|
@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo)
|
||||
if (lo->lo_state != Lo_bound)
|
||||
return -ENXIO;
|
||||
|
||||
if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */
|
||||
return -EBUSY;
|
||||
/*
|
||||
* If we've explicitly asked to tear down the loop device,
|
||||
* and it has an elevated reference count, set it for auto-teardown when
|
||||
* the last reference goes away. This stops $!~#$@ udev from
|
||||
* preventing teardown because it decided that it needs to run blkid on
|
||||
* the loopback device whenever they appear. xfstests is notorious for
|
||||
* failing tests because blkid via udev races with a losetup
|
||||
* <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
|
||||
* command to fail with EBUSY.
|
||||
*/
|
||||
if (lo->lo_refcnt > 1) {
|
||||
lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
|
||||
mutex_unlock(&lo->lo_ctl_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (filp == NULL)
|
||||
return -EINVAL;
|
||||
|
@ -2035,8 +2035,9 @@ static unsigned int implicit_sector(unsigned char command,
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
|
||||
static void mtip_set_timeout(struct driver_data *dd,
|
||||
struct host_to_dev_fis *fis,
|
||||
unsigned int *timeout, u8 erasemode)
|
||||
{
|
||||
switch (fis->command) {
|
||||
case ATA_CMD_DOWNLOAD_MICRO:
|
||||
@ -2044,7 +2045,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
|
||||
break;
|
||||
case ATA_CMD_SEC_ERASE_UNIT:
|
||||
case 0xFC:
|
||||
*timeout = 240000; /* 4 minutes */
|
||||
if (erasemode)
|
||||
*timeout = ((*(dd->port->identify + 90) * 2) * 60000);
|
||||
else
|
||||
*timeout = ((*(dd->port->identify + 89) * 2) * 60000);
|
||||
break;
|
||||
case ATA_CMD_STANDBYNOW1:
|
||||
*timeout = 120000; /* 2 minutes */
|
||||
@ -2087,6 +2091,7 @@ static int exec_drive_taskfile(struct driver_data *dd,
|
||||
unsigned int transfer_size;
|
||||
unsigned long task_file_data;
|
||||
int intotal = outtotal + req_task->out_size;
|
||||
int erasemode = 0;
|
||||
|
||||
taskout = req_task->out_size;
|
||||
taskin = req_task->in_size;
|
||||
@ -2212,7 +2217,13 @@ static int exec_drive_taskfile(struct driver_data *dd,
|
||||
fis.lba_hi,
|
||||
fis.device);
|
||||
|
||||
mtip_set_timeout(&fis, &timeout);
|
||||
/* check for erase mode support during secure erase.*/
|
||||
if ((fis.command == ATA_CMD_SEC_ERASE_UNIT)
|
||||
&& (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
|
||||
erasemode = 1;
|
||||
}
|
||||
|
||||
mtip_set_timeout(dd, &fis, &timeout, erasemode);
|
||||
|
||||
/* Determine the correct transfer size.*/
|
||||
if (force_single_sector)
|
||||
|
@ -33,6 +33,9 @@
|
||||
/* offset of Device Control register in PCIe extended capabilites space */
|
||||
#define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48
|
||||
|
||||
/* check for erase mode support during secure erase */
|
||||
#define MTIP_SEC_ERASE_MODE 0x3
|
||||
|
||||
/* # of times to retry timed out/failed IOs */
|
||||
#define MTIP_MAX_RETRIES 2
|
||||
|
||||
|
@ -158,8 +158,8 @@ struct xen_vbd {
|
||||
struct block_device *bdev;
|
||||
/* Cached size parameter. */
|
||||
sector_t size;
|
||||
bool flush_support;
|
||||
bool discard_secure;
|
||||
unsigned int flush_support:1;
|
||||
unsigned int discard_secure:1;
|
||||
};
|
||||
|
||||
struct backend_info;
|
||||
|
@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
|
||||
{
|
||||
struct xen_blkif *blkif;
|
||||
|
||||
blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL);
|
||||
blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);
|
||||
if (!blkif)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memset(blkif, 0, sizeof(*blkif));
|
||||
blkif->domid = domid;
|
||||
spin_lock_init(&blkif->blk_ring_lock);
|
||||
atomic_set(&blkif->refcnt, 1);
|
||||
@ -196,7 +195,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
|
||||
}
|
||||
}
|
||||
|
||||
void xen_blkif_free(struct xen_blkif *blkif)
|
||||
static void xen_blkif_free(struct xen_blkif *blkif)
|
||||
{
|
||||
if (!atomic_dec_and_test(&blkif->refcnt))
|
||||
BUG();
|
||||
@ -257,7 +256,7 @@ static struct attribute_group xen_vbdstat_group = {
|
||||
VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
|
||||
VBD_SHOW(mode, "%s\n", be->mode);
|
||||
|
||||
int xenvbd_sysfs_addif(struct xenbus_device *dev)
|
||||
static int xenvbd_sysfs_addif(struct xenbus_device *dev)
|
||||
{
|
||||
int error;
|
||||
|
||||
@ -281,7 +280,7 @@ fail1: device_remove_file(&dev->dev, &dev_attr_physical_device);
|
||||
return error;
|
||||
}
|
||||
|
||||
void xenvbd_sysfs_delif(struct xenbus_device *dev)
|
||||
static void xenvbd_sysfs_delif(struct xenbus_device *dev)
|
||||
{
|
||||
sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);
|
||||
device_remove_file(&dev->dev, &dev_attr_mode);
|
||||
|
@ -5,7 +5,7 @@
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Maintainer:
|
||||
* Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
* Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
*
|
||||
* Based on the powernow-k7.c module written by Dave Jones.
|
||||
* (C) 2003 Dave Jones on behalf of SuSE Labs
|
||||
|
@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
|
||||
}
|
||||
|
||||
chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
|
||||
chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
|
||||
chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL);
|
||||
if (!chip->buffer) {
|
||||
ret = -ENOMEM;
|
||||
goto exit_destroy;
|
||||
|
@ -244,6 +244,8 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mvebu_gpio_set(chip, pin, value);
|
||||
|
||||
spin_lock_irqsave(&mvchip->lock, flags);
|
||||
u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
|
||||
u &= ~(1 << pin);
|
||||
@ -644,7 +646,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
|
||||
ct->handler = handle_edge_irq;
|
||||
ct->chip.name = mvchip->chip.label;
|
||||
|
||||
irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE,
|
||||
irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
|
||||
IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
|
||||
|
||||
/* Setup irq domain on top of the generic chip. */
|
||||
|
@ -251,6 +251,40 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _clear_gpio_debounce - clear debounce settings for a gpio
|
||||
* @bank: the gpio bank we're acting upon
|
||||
* @gpio: the gpio number on this @gpio
|
||||
*
|
||||
* If a gpio is using debounce, then clear the debounce enable bit and if
|
||||
* this is the only gpio in this bank using debounce, then clear the debounce
|
||||
* time too. The debounce clock will also be disabled when calling this function
|
||||
* if this is the only gpio in the bank using debounce.
|
||||
*/
|
||||
static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
|
||||
{
|
||||
u32 gpio_bit = GPIO_BIT(bank, gpio);
|
||||
|
||||
if (!bank->dbck_flag)
|
||||
return;
|
||||
|
||||
if (!(bank->dbck_enable_mask & gpio_bit))
|
||||
return;
|
||||
|
||||
bank->dbck_enable_mask &= ~gpio_bit;
|
||||
bank->context.debounce_en &= ~gpio_bit;
|
||||
__raw_writel(bank->context.debounce_en,
|
||||
bank->base + bank->regs->debounce_en);
|
||||
|
||||
if (!bank->dbck_enable_mask) {
|
||||
bank->context.debounce = 0;
|
||||
__raw_writel(bank->context.debounce, bank->base +
|
||||
bank->regs->debounce);
|
||||
clk_disable(bank->dbck);
|
||||
bank->dbck_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
|
||||
unsigned trigger)
|
||||
{
|
||||
@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
|
||||
_set_gpio_irqenable(bank, gpio, 0);
|
||||
_clear_gpio_irqstatus(bank, gpio);
|
||||
_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
|
||||
_clear_gpio_debounce(bank, gpio);
|
||||
}
|
||||
|
||||
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
|
||||
|
@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tgpio->lock, flags);
|
||||
tgpio->last_ier &= ~(1 << offset);
|
||||
tgpio->last_ier &= ~(1UL << offset);
|
||||
iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
|
||||
spin_unlock_irqrestore(&tgpio->lock, flags);
|
||||
}
|
||||
@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tgpio->lock, flags);
|
||||
tgpio->last_ier |= 1 << offset;
|
||||
tgpio->last_ier |= 1UL << offset;
|
||||
iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
|
||||
spin_unlock_irqrestore(&tgpio->lock, flags);
|
||||
}
|
||||
|
@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class,
|
||||
*/
|
||||
|
||||
status = gpio_request(gpio, "sysfs");
|
||||
if (status < 0)
|
||||
if (status < 0) {
|
||||
if (status == -EPROBE_DEFER)
|
||||
status = -ENODEV;
|
||||
goto done;
|
||||
|
||||
}
|
||||
status = gpio_export(gpio, true);
|
||||
if (status < 0)
|
||||
gpio_free(gpio);
|
||||
@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label)
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
if (!gpio_is_valid(gpio))
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
status = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
desc = &gpio_desc[gpio];
|
||||
chip = desc->chip;
|
||||
if (chip == NULL)
|
||||
|
@ -1,6 +1,6 @@
|
||||
config DRM_EXYNOS
|
||||
tristate "DRM Support for Samsung SoC EXYNOS Series"
|
||||
depends on DRM && PLAT_SAMSUNG
|
||||
depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
|
||||
select DRM_KMS_HELPER
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
|
@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
|
||||
exynos_connector->encoder_id = encoder->base.id;
|
||||
exynos_connector->manager = manager;
|
||||
exynos_connector->dpms = DRM_MODE_DPMS_OFF;
|
||||
connector->dpms = DRM_MODE_DPMS_OFF;
|
||||
connector->encoder = encoder;
|
||||
|
||||
err = drm_mode_connector_attach_encoder(connector, encoder);
|
||||
|
@ -43,12 +43,14 @@
|
||||
* @manager: specific encoder has its own manager to control a hardware
|
||||
* appropriately and we can access a hardware drawing on this manager.
|
||||
* @dpms: store the encoder dpms value.
|
||||
* @updated: indicate whether overlay data updating is needed or not.
|
||||
*/
|
||||
struct exynos_drm_encoder {
|
||||
struct drm_crtc *old_crtc;
|
||||
struct drm_encoder drm_encoder;
|
||||
struct exynos_drm_manager *manager;
|
||||
int dpms;
|
||||
int dpms;
|
||||
bool updated;
|
||||
};
|
||||
|
||||
static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
|
||||
@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
if (manager_ops && manager_ops->apply)
|
||||
manager_ops->apply(manager->dev);
|
||||
if (!exynos_encoder->updated)
|
||||
manager_ops->apply(manager->dev);
|
||||
|
||||
exynos_drm_connector_power(encoder, mode);
|
||||
exynos_encoder->dpms = mode;
|
||||
break;
|
||||
@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
exynos_drm_connector_power(encoder, mode);
|
||||
exynos_encoder->dpms = mode;
|
||||
exynos_encoder->updated = false;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unspecified mode %d\n", mode);
|
||||
@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
|
||||
|
||||
static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
|
||||
{
|
||||
struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
|
||||
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
|
||||
struct exynos_drm_manager *manager = exynos_encoder->manager;
|
||||
struct exynos_drm_manager_ops *manager_ops = manager->ops;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (manager_ops && manager_ops->commit)
|
||||
manager_ops->commit(manager->dev);
|
||||
|
||||
/*
|
||||
* this will avoid one issue that overlay data is updated to
|
||||
* real hardware two times.
|
||||
* And this variable will be used to check if the data was
|
||||
* already updated or not by exynos_drm_encoder_dpms function.
|
||||
*/
|
||||
exynos_encoder->updated = true;
|
||||
}
|
||||
|
||||
static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
|
||||
@ -400,19 +414,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
|
||||
if (manager_ops && manager_ops->dpms)
|
||||
manager_ops->dpms(manager->dev, mode);
|
||||
|
||||
/*
|
||||
* set current mode to new one so that data aren't updated into
|
||||
* registers by drm_helper_connector_dpms two times.
|
||||
*
|
||||
* in case that drm_crtc_helper_set_mode() is called,
|
||||
* overlay_ops->commit() and manager_ops->commit() callbacks
|
||||
* can be called two times, first at drm_crtc_helper_set_mode()
|
||||
* and second at drm_helper_connector_dpms().
|
||||
* so with this setting, when drm_helper_connector_dpms() is called
|
||||
* encoder->funcs->dpms() will be ignored.
|
||||
*/
|
||||
exynos_encoder->dpms = mode;
|
||||
|
||||
/*
|
||||
* if this condition is ok then it means that the crtc is already
|
||||
* detached from encoder and last function for detaching is properly
|
||||
|
@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
|
||||
const struct of_device_id *match;
|
||||
match = of_match_node(of_match_ptr(mixer_match_types),
|
||||
pdev->dev.of_node);
|
||||
drv = match->data;
|
||||
drv = (struct mixer_drv_data *)match->data;
|
||||
} else {
|
||||
drv = (struct mixer_drv_data *)
|
||||
platform_get_device_id(pdev)->driver_data;
|
||||
|
@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
goto put_gmch;
|
||||
}
|
||||
|
||||
i915_kick_out_firmware_fb(dev_priv);
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
i915_kick_out_firmware_fb(dev_priv);
|
||||
|
||||
pci_set_master(dev->pdev);
|
||||
|
||||
|
@ -729,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)
|
||||
|
||||
crt->base.type = INTEL_OUTPUT_ANALOG;
|
||||
crt->base.cloneable = true;
|
||||
if (IS_HASWELL(dev))
|
||||
if (IS_HASWELL(dev) || IS_I830(dev))
|
||||
crt->base.crtc_mask = (1 << 0);
|
||||
else
|
||||
crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
|
||||
|
@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay)
|
||||
intel_ring_emit(ring, flip_addr);
|
||||
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
/* turn overlay off */
|
||||
intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
||||
intel_ring_emit(ring, flip_addr);
|
||||
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
if (IS_I830(dev)) {
|
||||
/* Workaround: Don't disable the overlay fully, since otherwise
|
||||
* it dies on the next OVERLAY_ON cmd. */
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
} else {
|
||||
intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
||||
intel_ring_emit(ring, flip_addr);
|
||||
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
}
|
||||
intel_ring_advance(ring);
|
||||
|
||||
return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
|
||||
|
@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = _intel_panel_get_max_backlight(dev);
|
||||
if (props.max_brightness == 0) {
|
||||
DRM_ERROR("Failed to get maximum backlight value\n");
|
||||
DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_priv->backlight =
|
||||
|
@ -894,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
|
||||
unsigned if_index, uint8_t tx_rate,
|
||||
uint8_t *data, unsigned length)
|
||||
{
|
||||
uint8_t set_buf_index[2] = { if_index, 0 };
|
||||
uint8_t hbuf_size, tmp[8];
|
||||
int i;
|
||||
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_INDEX,
|
||||
set_buf_index, 2))
|
||||
return false;
|
||||
|
||||
if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
|
||||
&hbuf_size, 1))
|
||||
return false;
|
||||
|
||||
/* Buffer size is 0 based, hooray! */
|
||||
hbuf_size++;
|
||||
|
||||
DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
|
||||
if_index, length, hbuf_size);
|
||||
|
||||
for (i = 0; i < hbuf_size; i += 8) {
|
||||
memset(tmp, 0, 8);
|
||||
if (i < length)
|
||||
memcpy(tmp, data + i, min_t(unsigned, 8, length - i));
|
||||
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_DATA,
|
||||
tmp, 8))
|
||||
return false;
|
||||
}
|
||||
|
||||
return intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_TXRATE,
|
||||
&tx_rate, 1);
|
||||
}
|
||||
|
||||
static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
|
||||
{
|
||||
struct dip_infoframe avi_if = {
|
||||
@ -901,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
|
||||
.ver = DIP_VERSION_AVI,
|
||||
.len = DIP_LEN_AVI,
|
||||
};
|
||||
uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
|
||||
uint8_t set_buf_index[2] = { 1, 0 };
|
||||
uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
|
||||
uint64_t *data = (uint64_t *)sdvo_data;
|
||||
unsigned i;
|
||||
|
||||
intel_dip_infoframe_csum(&avi_if);
|
||||
|
||||
@ -915,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
|
||||
sdvo_data[3] = avi_if.checksum;
|
||||
memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
|
||||
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_INDEX,
|
||||
set_buf_index, 2))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < sizeof(sdvo_data); i += 8) {
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_DATA,
|
||||
data, 8))
|
||||
return false;
|
||||
data++;
|
||||
}
|
||||
|
||||
return intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_TXRATE,
|
||||
&tx_rate, 1);
|
||||
return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
|
||||
SDVO_HBUF_TX_VSYNC,
|
||||
sdvo_data, sizeof(sdvo_data));
|
||||
}
|
||||
|
||||
static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
|
||||
|
@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {
|
||||
#define SDVO_CMD_SET_AUDIO_STAT 0x91
|
||||
#define SDVO_CMD_GET_AUDIO_STAT 0x92
|
||||
#define SDVO_CMD_SET_HBUF_INDEX 0x93
|
||||
#define SDVO_HBUF_INDEX_ELD 0
|
||||
#define SDVO_HBUF_INDEX_AVI_IF 1
|
||||
#define SDVO_CMD_GET_HBUF_INDEX 0x94
|
||||
#define SDVO_CMD_GET_HBUF_INFO 0x95
|
||||
#define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96
|
||||
|
@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
|
||||
node = kzalloc(sizeof(*node), GFP_KERNEL);
|
||||
if (!node)
|
||||
return -ENOMEM;
|
||||
node->offset = roundup(offset, mm->block_size);
|
||||
node->length = rounddown(offset + length, mm->block_size) - node->offset;
|
||||
|
||||
if (length) {
|
||||
node->offset = roundup(offset, mm->block_size);
|
||||
node->length = rounddown(offset + length, mm->block_size);
|
||||
node->length -= node->offset;
|
||||
}
|
||||
|
||||
list_add_tail(&node->nl_entry, &mm->nodes);
|
||||
list_add_tail(&node->fl_entry, &mm->free);
|
||||
mm->heap_nodes++;
|
||||
mm->heap_size += length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ struct nouveau_mm {
|
||||
|
||||
u32 block_size;
|
||||
int heap_nodes;
|
||||
u32 heap_size;
|
||||
};
|
||||
|
||||
int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
|
||||
|
@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
((priv->base.ram.size & 0x000000ff) << 32);
|
||||
|
||||
tags = nv_rd32(priv, 0x100320);
|
||||
if (tags) {
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nv_debug(priv, "%d compression tags\n", tags);
|
||||
}
|
||||
nv_debug(priv, "%d compression tags\n", tags);
|
||||
|
||||
size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
|
||||
switch (device->chipset) {
|
||||
|
@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||
case DCB_I2C_NVIO_BIT:
|
||||
port->drive = info.drive & 0x0f;
|
||||
if (device->card_type < NV_D0) {
|
||||
if (info.drive >= ARRAY_SIZE(nv50_i2c_port))
|
||||
if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
|
||||
break;
|
||||
port->drive = nv50_i2c_port[port->drive];
|
||||
port->sense = port->drive;
|
||||
|
@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nouveau_disp *pdisp = nouveau_disp(drm->device);
|
||||
struct nouveau_display *disp;
|
||||
u32 pclass = dev->pdev->class >> 8;
|
||||
int ret, gen;
|
||||
|
||||
disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
|
||||
@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)
|
||||
drm_kms_helper_poll_init(dev);
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
|
||||
if (nv_device(drm->device)->card_type < NV_50)
|
||||
ret = nv04_display_create(dev);
|
||||
else
|
||||
if (nv_device(drm->device)->card_type < NV_D0)
|
||||
ret = nv50_display_create(dev);
|
||||
else
|
||||
ret = nvd0_display_create(dev);
|
||||
if (ret)
|
||||
goto disp_create_err;
|
||||
|
||||
if (dev->mode_config.num_crtc) {
|
||||
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
|
||||
if (nouveau_modeset == 1 ||
|
||||
(nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
|
||||
if (nv_device(drm->device)->card_type < NV_50)
|
||||
ret = nv04_display_create(dev);
|
||||
else
|
||||
if (nv_device(drm->device)->card_type < NV_D0)
|
||||
ret = nv50_display_create(dev);
|
||||
else
|
||||
ret = nvd0_display_create(dev);
|
||||
if (ret)
|
||||
goto vblank_err;
|
||||
goto disp_create_err;
|
||||
|
||||
if (dev->mode_config.num_crtc) {
|
||||
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
|
||||
if (ret)
|
||||
goto vblank_err;
|
||||
}
|
||||
|
||||
nouveau_backlight_init(dev);
|
||||
}
|
||||
|
||||
nouveau_backlight_init(dev);
|
||||
return 0;
|
||||
|
||||
vblank_err:
|
||||
@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)
|
||||
nouveau_backlight_exit(dev);
|
||||
drm_vblank_cleanup(dev);
|
||||
|
||||
disp->dtor(dev);
|
||||
if (disp->dtor)
|
||||
disp->dtor(dev);
|
||||
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
drm_mode_config_cleanup(dev);
|
||||
|
@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
|
||||
static int nouveau_noaccel = 0;
|
||||
module_param_named(noaccel, nouveau_noaccel, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(modeset, "enable driver");
|
||||
static int nouveau_modeset = -1;
|
||||
MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
|
||||
"0 = disabled, 1 = enabled, 2 = headless)");
|
||||
int nouveau_modeset = -1;
|
||||
module_param_named(modeset, nouveau_modeset, int, 0400);
|
||||
|
||||
static struct drm_driver driver;
|
||||
@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev)
|
||||
|
||||
nouveau_pm_fini(dev);
|
||||
|
||||
nouveau_display_fini(dev);
|
||||
if (dev->mode_config.num_crtc)
|
||||
nouveau_display_fini(dev);
|
||||
nouveau_display_destroy(dev);
|
||||
|
||||
nouveau_irq_fini(dev);
|
||||
@ -403,13 +405,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
|
||||
pm_state.event == PM_EVENT_PRETHAW)
|
||||
return 0;
|
||||
|
||||
NV_INFO(drm, "suspending fbcon...\n");
|
||||
nouveau_fbcon_set_suspend(dev, 1);
|
||||
if (dev->mode_config.num_crtc) {
|
||||
NV_INFO(drm, "suspending fbcon...\n");
|
||||
nouveau_fbcon_set_suspend(dev, 1);
|
||||
|
||||
NV_INFO(drm, "suspending display...\n");
|
||||
ret = nouveau_display_suspend(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
NV_INFO(drm, "suspending display...\n");
|
||||
ret = nouveau_display_suspend(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
NV_INFO(drm, "evicting buffers...\n");
|
||||
ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
|
||||
@ -445,8 +449,10 @@ fail_client:
|
||||
nouveau_client_init(&cli->base);
|
||||
}
|
||||
|
||||
NV_INFO(drm, "resuming display...\n");
|
||||
nouveau_display_resume(dev);
|
||||
if (dev->mode_config.num_crtc) {
|
||||
NV_INFO(drm, "resuming display...\n");
|
||||
nouveau_display_resume(dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev)
|
||||
nouveau_irq_postinstall(dev);
|
||||
nouveau_pm_resume(dev);
|
||||
|
||||
NV_INFO(drm, "resuming display...\n");
|
||||
nouveau_display_resume(dev);
|
||||
if (dev->mode_config.num_crtc) {
|
||||
NV_INFO(drm, "resuming display...\n");
|
||||
nouveau_display_resume(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -662,9 +670,7 @@ nouveau_drm_init(void)
|
||||
#ifdef CONFIG_VGA_CONSOLE
|
||||
if (vgacon_text_force())
|
||||
nouveau_modeset = 0;
|
||||
else
|
||||
#endif
|
||||
nouveau_modeset = 1;
|
||||
}
|
||||
|
||||
if (!nouveau_modeset)
|
||||
|
@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);
|
||||
nv_info((cli), fmt, ##args); \
|
||||
} while (0)
|
||||
|
||||
extern int nouveau_modeset;
|
||||
|
||||
#endif
|
||||
|
@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
|
||||
|
||||
nv_subdev(pmc)->intr(nv_subdev(pmc));
|
||||
|
||||
if (device->card_type >= NV_D0) {
|
||||
if (nv_rd32(device, 0x000100) & 0x04000000)
|
||||
nvd0_display_intr(dev);
|
||||
} else
|
||||
if (device->card_type >= NV_50) {
|
||||
if (nv_rd32(device, 0x000100) & 0x04000000)
|
||||
nv50_display_intr(dev);
|
||||
if (dev->mode_config.num_crtc) {
|
||||
if (device->card_type >= NV_D0) {
|
||||
if (nv_rd32(device, 0x000100) & 0x04000000)
|
||||
nvd0_display_intr(dev);
|
||||
} else
|
||||
if (device->card_type >= NV_50) {
|
||||
if (nv_rd32(device, 0x000100) & 0x04000000)
|
||||
nv50_display_intr(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -220,7 +220,7 @@ out:
|
||||
NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
|
||||
|
||||
if (blue == 0x18) {
|
||||
NV_INFO(drm, "Load detected on head A\n");
|
||||
NV_DEBUG(drm, "Load detected on head A\n");
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
|
||||
|
||||
if (nv17_dac_sample_load(encoder) &
|
||||
NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
|
||||
NV_INFO(drm, "Load detected on output %c\n",
|
||||
'@' + ffs(dcb->or));
|
||||
NV_DEBUG(drm, "Load detected on output %c\n",
|
||||
'@' + ffs(dcb->or));
|
||||
return connector_status_connected;
|
||||
} else {
|
||||
return connector_status_disconnected;
|
||||
@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)
|
||||
|
||||
helper->dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
|
||||
NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
|
||||
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
|
||||
nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
|
||||
NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
|
||||
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
|
||||
nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
|
||||
}
|
||||
|
||||
void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
|
||||
@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
|
||||
return;
|
||||
nv_encoder->last_dpms = mode;
|
||||
|
||||
NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
|
||||
nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
|
||||
}
|
||||
|
@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
|
||||
|
||||
helper->dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
|
||||
NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
|
||||
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
|
||||
nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
|
||||
NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
|
||||
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
|
||||
nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
|
||||
}
|
||||
|
||||
static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
|
||||
@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
|
||||
return;
|
||||
nv_encoder->last_dpms = mode;
|
||||
|
||||
NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
|
||||
if (was_powersaving && is_powersaving_dpms(mode))
|
||||
return;
|
||||
@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
|
||||
return;
|
||||
nv_encoder->last_dpms = mode;
|
||||
|
||||
NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
|
||||
nv04_dfp_update_backlight(encoder, mode);
|
||||
nv04_dfp_update_fp_control(encoder, mode);
|
||||
|
@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
|
||||
struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
|
||||
uint8_t crtc1A;
|
||||
|
||||
NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
|
||||
state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK);
|
||||
|
||||
@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
|
||||
|
||||
helper->dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
|
||||
NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
|
||||
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index,
|
||||
'@' + ffs(nv_encoder->dcb->or));
|
||||
NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
|
||||
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
|
||||
}
|
||||
|
||||
static void nv04_tv_destroy(struct drm_encoder *encoder)
|
||||
|
@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,
|
||||
/* macro tile width & height */
|
||||
palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
|
||||
halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
|
||||
mtileb = (palign / 8) * (halign / 8) * tileb;;
|
||||
mtileb = (palign / 8) * (halign / 8) * tileb;
|
||||
mtile_pr = surf->nbx / palign;
|
||||
mtile_ps = (mtile_pr * surf->nby) / halign;
|
||||
surf->layer_size = mtile_ps * mtileb * slice_pt;
|
||||
|
@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
|
||||
}
|
||||
|
||||
/**
|
||||
* radeon_atpx_switchto - switch to the requested GPU
|
||||
* radeon_atpx_power_state - power down/up the requested GPU
|
||||
*
|
||||
* @id: GPU to switch to
|
||||
* @id: GPU to power down/up
|
||||
* @state: requested power state (0 = off, 1 = on)
|
||||
*
|
||||
* Execute the necessary ATPX function to power down/up the discrete GPU
|
||||
|
@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
||||
struct drm_mode_object *obj;
|
||||
int i;
|
||||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
bool dret = false;
|
||||
bool dret = false, broken_edid = false;
|
||||
|
||||
if (!force && radeon_check_hpd_status_unchanged(connector))
|
||||
return connector->status;
|
||||
@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
||||
ret = connector_status_disconnected;
|
||||
DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
|
||||
radeon_connector->ddc_bus = NULL;
|
||||
} else {
|
||||
ret = connector_status_connected;
|
||||
broken_edid = true; /* defer use_digital to later */
|
||||
}
|
||||
} else {
|
||||
radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
|
||||
@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
||||
|
||||
encoder_funcs = encoder->helper_private;
|
||||
if (encoder_funcs->detect) {
|
||||
if (ret != connector_status_connected) {
|
||||
ret = encoder_funcs->detect(encoder, connector);
|
||||
if (ret == connector_status_connected) {
|
||||
radeon_connector->use_digital = false;
|
||||
if (!broken_edid) {
|
||||
if (ret != connector_status_connected) {
|
||||
/* deal with analog monitors without DDC */
|
||||
ret = encoder_funcs->detect(encoder, connector);
|
||||
if (ret == connector_status_connected) {
|
||||
radeon_connector->use_digital = false;
|
||||
}
|
||||
if (ret != connector_status_disconnected)
|
||||
radeon_connector->detected_by_load = true;
|
||||
}
|
||||
if (ret != connector_status_disconnected)
|
||||
radeon_connector->detected_by_load = true;
|
||||
} else {
|
||||
enum drm_connector_status lret;
|
||||
/* assume digital unless load detected otherwise */
|
||||
radeon_connector->use_digital = true;
|
||||
lret = encoder_funcs->detect(encoder, connector);
|
||||
DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret);
|
||||
if (lret == connector_status_connected)
|
||||
radeon_connector->use_digital = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t crtc_ext_cntl = 0;
|
||||
uint32_t mask;
|
||||
|
||||
if (radeon_crtc->crtc_id)
|
||||
@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
RADEON_CRTC_VSYNC_DIS |
|
||||
RADEON_CRTC_HSYNC_DIS);
|
||||
|
||||
/*
|
||||
* On all dual CRTC GPUs this bit controls the CRTC of the primary DAC.
|
||||
* Therefore it is set in the DAC DMPS function.
|
||||
* This is different for GPU's with a single CRTC but a primary and a
|
||||
* TV DAC: here it controls the single CRTC no matter where it is
|
||||
* routed. Therefore we set it here.
|
||||
*/
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC)
|
||||
crtc_ext_cntl = RADEON_CRTC_CRT_ON;
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
radeon_crtc->enabled = true;
|
||||
@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
else {
|
||||
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
|
||||
RADEON_CRTC_DISP_REQ_EN_B));
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));
|
||||
}
|
||||
drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
|
||||
radeon_crtc_load_lut(crtc);
|
||||
@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
else {
|
||||
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
|
||||
RADEON_CRTC_DISP_REQ_EN_B));
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));
|
||||
}
|
||||
radeon_crtc->enabled = false;
|
||||
/* adjust pm to dpms changes AFTER disabling crtcs */
|
||||
|
@ -537,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
|
||||
break;
|
||||
}
|
||||
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
|
||||
/* handled in radeon_crtc_dpms() */
|
||||
if (!(rdev->flags & RADEON_SINGLE_CRTC))
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
|
||||
WREG32(RADEON_DAC_CNTL, dac_cntl);
|
||||
WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
|
||||
|
||||
@ -662,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
|
||||
|
||||
if (ASIC_IS_R300(rdev))
|
||||
tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
|
||||
else if (ASIC_IS_RV100(rdev))
|
||||
tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
|
||||
else
|
||||
tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
|
||||
|
||||
@ -671,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
|
||||
tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
|
||||
WREG32(RADEON_DAC_CNTL, tmp);
|
||||
|
||||
tmp = dac_macro_cntl;
|
||||
tmp &= ~(RADEON_DAC_PDWN_R |
|
||||
RADEON_DAC_PDWN_G |
|
||||
RADEON_DAC_PDWN_B);
|
||||
@ -1092,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
|
||||
} else {
|
||||
if (is_tv)
|
||||
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
|
||||
else
|
||||
/* handled in radeon_crtc_dpms() */
|
||||
else if (!(rdev->flags & RADEON_SINGLE_CRTC))
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
}
|
||||
@ -1416,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
|
||||
return found;
|
||||
}
|
||||
|
||||
static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
|
||||
uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
|
||||
uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
|
||||
uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
|
||||
uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
|
||||
bool found = false;
|
||||
int i;
|
||||
|
||||
/* save the regs we need */
|
||||
gpio_monid = RREG32(RADEON_GPIO_MONID);
|
||||
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
|
||||
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A);
|
||||
disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B);
|
||||
disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C);
|
||||
disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D);
|
||||
disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E);
|
||||
disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F);
|
||||
crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP);
|
||||
crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP);
|
||||
crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID);
|
||||
crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID);
|
||||
|
||||
tmp = RREG32(RADEON_GPIO_MONID);
|
||||
tmp &= ~RADEON_GPIO_A_0;
|
||||
WREG32(RADEON_GPIO_MONID, tmp);
|
||||
|
||||
WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON |
|
||||
RADEON_FP2_PANEL_FORMAT |
|
||||
R200_FP2_SOURCE_SEL_TRANS_UNIT |
|
||||
RADEON_FP2_DVO_EN |
|
||||
R200_FP2_DVO_RATE_SEL_SDR));
|
||||
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX |
|
||||
RADEON_DISP_TRANS_MATRIX_GRAPHICS));
|
||||
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN |
|
||||
RADEON_CRTC2_DISP_REQ_EN_B));
|
||||
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
|
||||
|
||||
WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
|
||||
WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
|
||||
WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
|
||||
WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
|
||||
|
||||
for (i = 0; i < 200; i++) {
|
||||
tmp = RREG32(RADEON_GPIO_MONID);
|
||||
if (tmp & RADEON_GPIO_Y_0)
|
||||
found = true;
|
||||
|
||||
if (found)
|
||||
break;
|
||||
|
||||
if (!drm_can_sleep())
|
||||
mdelay(1);
|
||||
else
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
/* restore the regs we used */
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
|
||||
WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
|
||||
WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
|
||||
WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
|
||||
WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
|
||||
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
|
||||
WREG32(RADEON_GPIO_MONID, gpio_monid);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
|
||||
uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
|
||||
uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
|
||||
uint32_t gpiopad_a = 0, pixclks_cntl, tmp;
|
||||
uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;
|
||||
enum drm_connector_status found = connector_status_disconnected;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
@ -1459,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
/* R200 uses an external DAC for secondary DAC */
|
||||
if (rdev->family == CHIP_R200) {
|
||||
if (radeon_legacy_ext_dac_detect(encoder, connector))
|
||||
found = connector_status_connected;
|
||||
return found;
|
||||
}
|
||||
|
||||
/* save the regs we need */
|
||||
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
|
||||
gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0;
|
||||
disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0;
|
||||
disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG);
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC) {
|
||||
crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
|
||||
} else {
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
gpiopad_a = RREG32(RADEON_GPIOPAD_A);
|
||||
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
|
||||
} else {
|
||||
disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
|
||||
}
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
}
|
||||
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
|
||||
dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
|
||||
dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
|
||||
@ -1473,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
|
||||
| RADEON_PIX2CLK_DAC_ALWAYS_ONb);
|
||||
WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
|
||||
|
||||
if (ASIC_IS_R300(rdev))
|
||||
WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
|
||||
|
||||
tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
|
||||
tmp |= RADEON_CRTC2_CRT2_ON |
|
||||
(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
|
||||
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
|
||||
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC) {
|
||||
tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, tmp);
|
||||
} else {
|
||||
tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
|
||||
WREG32(RADEON_DISP_HW_DEBUG, tmp);
|
||||
tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
|
||||
tmp |= RADEON_CRTC2_CRT2_ON |
|
||||
(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
|
||||
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
|
||||
tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
|
||||
} else {
|
||||
tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
|
||||
WREG32(RADEON_DISP_HW_DEBUG, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
tmp = RADEON_TV_DAC_NBLANK |
|
||||
@ -1530,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
|
||||
WREG32(RADEON_DAC_CNTL2, dac_cntl2);
|
||||
WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
|
||||
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC) {
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
|
||||
} else {
|
||||
WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
|
||||
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
|
||||
} else {
|
||||
WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
|
||||
}
|
||||
}
|
||||
|
||||
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
|
||||
|
||||
return found;
|
||||
|
@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev,
|
||||
|
||||
int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
|
||||
const char *front, char **urb_buf_ptr,
|
||||
u32 byte_offset, u32 byte_width,
|
||||
u32 byte_offset, u32 device_byte_offset, u32 byte_width,
|
||||
int *ident_ptr, int *sent_ptr);
|
||||
|
||||
int udl_dumb_create(struct drm_file *file_priv,
|
||||
|
@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,
|
||||
list_for_each_entry(cur, &fbdefio->pagelist, lru) {
|
||||
|
||||
if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8),
|
||||
&urb, (char *) info->fix.smem_start,
|
||||
&cmd, cur->index << PAGE_SHIFT,
|
||||
PAGE_SIZE, &bytes_identical, &bytes_sent))
|
||||
&urb, (char *) info->fix.smem_start,
|
||||
&cmd, cur->index << PAGE_SHIFT,
|
||||
cur->index << PAGE_SHIFT,
|
||||
PAGE_SIZE, &bytes_identical, &bytes_sent))
|
||||
goto error;
|
||||
bytes_rendered += PAGE_SIZE;
|
||||
}
|
||||
@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
|
||||
for (i = y; i < y + height ; i++) {
|
||||
const int line_offset = fb->base.pitches[0] * i;
|
||||
const int byte_offset = line_offset + (x * bpp);
|
||||
|
||||
const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
|
||||
if (udl_render_hline(dev, bpp, &urb,
|
||||
(char *) fb->obj->vmapping,
|
||||
&cmd, byte_offset, width * bpp,
|
||||
&cmd, byte_offset, dev_byte_offset,
|
||||
width * bpp,
|
||||
&bytes_identical, &bytes_sent))
|
||||
goto error;
|
||||
}
|
||||
|
@ -213,11 +213,12 @@ static void udl_compress_hline16(
|
||||
*/
|
||||
int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
|
||||
const char *front, char **urb_buf_ptr,
|
||||
u32 byte_offset, u32 byte_width,
|
||||
u32 byte_offset, u32 device_byte_offset,
|
||||
u32 byte_width,
|
||||
int *ident_ptr, int *sent_ptr)
|
||||
{
|
||||
const u8 *line_start, *line_end, *next_pixel;
|
||||
u32 base16 = 0 + (byte_offset / bpp) * 2;
|
||||
u32 base16 = 0 + (device_byte_offset / bpp) * 2;
|
||||
struct urb *urb = *urb_ptr;
|
||||
u8 *cmd = *urb_buf_ptr;
|
||||
u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
|
||||
|
@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = {
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
|
||||
|
@ -1532,6 +1532,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
|
||||
@ -2139,6 +2142,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
|
||||
{ }
|
||||
|
@ -118,6 +118,9 @@
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b
|
||||
|
@ -28,22 +28,30 @@
|
||||
#define MS_RDESC 0x08
|
||||
#define MS_NOGET 0x10
|
||||
#define MS_DUPLICATE_USAGES 0x20
|
||||
#define MS_RDESC_3K 0x40
|
||||
|
||||
/*
|
||||
* Microsoft Wireless Desktop Receiver (Model 1028) has
|
||||
* 'Usage Min/Max' where it ought to have 'Physical Min/Max'
|
||||
*/
|
||||
static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
unsigned int *rsize)
|
||||
{
|
||||
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
|
||||
|
||||
/*
|
||||
* Microsoft Wireless Desktop Receiver (Model 1028) has
|
||||
* 'Usage Min/Max' where it ought to have 'Physical Min/Max'
|
||||
*/
|
||||
if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
|
||||
rdesc[559] == 0x29) {
|
||||
hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
|
||||
rdesc[557] = 0x35;
|
||||
rdesc[559] = 0x45;
|
||||
}
|
||||
/* the same as above (s/usage/physical/) */
|
||||
if ((quirks & MS_RDESC_3K) && *rsize == 106 &&
|
||||
!memcmp((char []){ 0x19, 0x00, 0x29, 0xff },
|
||||
&rdesc[94], 4)) {
|
||||
rdesc[94] = 0x35;
|
||||
rdesc[96] = 0x45;
|
||||
}
|
||||
return rdesc;
|
||||
}
|
||||
|
||||
@ -192,7 +200,7 @@ static const struct hid_device_id ms_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
|
||||
.driver_data = MS_PRESENTER },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K),
|
||||
.driver_data = MS_ERGONOMY },
|
||||
.driver_data = MS_ERGONOMY | MS_RDESC_3K },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
|
||||
.driver_data = MS_NOGET },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
|
||||
|
@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = {
|
||||
},
|
||||
{ .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
|
||||
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
|
||||
MT_QUIRK_SLOT_IS_CONTACTNUMBER,
|
||||
.maxcontacts = 10
|
||||
MT_QUIRK_SLOT_IS_CONTACTNUMBER
|
||||
},
|
||||
|
||||
{ .name = MT_CLS_FLATFROG,
|
||||
@ -421,11 +420,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
* contact max are global to the report */
|
||||
td->last_field_index = field->index;
|
||||
return -1;
|
||||
}
|
||||
case HID_DG_TOUCH:
|
||||
/* Legacy devices use TIPSWITCH and not TOUCH.
|
||||
* Let's just ignore this field. */
|
||||
return -1;
|
||||
}
|
||||
/* let hid-input decide for the others */
|
||||
return 0;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* fam15h_power.c - AMD Family 15h processor power monitoring
|
||||
*
|
||||
* Copyright (c) 2011 Advanced Micro Devices, Inc.
|
||||
* Author: Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
* Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
*
|
||||
*
|
||||
* This driver is free software; you can redistribute it and/or
|
||||
@ -28,7 +28,7 @@
|
||||
#include <asm/processor.h>
|
||||
|
||||
MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor");
|
||||
MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>");
|
||||
MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* D18F3 */
|
||||
|
@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = {
|
||||
.driver = {
|
||||
.name = "gpio-fan",
|
||||
.pm = GPIO_FAN_PM,
|
||||
#ifdef CONFIG_OF_GPIO
|
||||
.of_match_table = of_match_ptr(of_gpio_fan_match),
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
|
||||
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
|
||||
obj-$(CONFIG_I2C_MUX) += i2c-mux.o
|
||||
obj-y += algos/ busses/ muxes/
|
||||
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
|
||||
|
||||
ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
|
||||
CFLAGS_i2c-core.o := -Wno-deprecated-declarations
|
||||
|
@ -81,7 +81,6 @@ config I2C_I801
|
||||
tristate "Intel 82801 (ICH/PCH)"
|
||||
depends on PCI
|
||||
select CHECK_SIGNATURE if X86 && DMI
|
||||
select GPIOLIB if I2C_MUX
|
||||
help
|
||||
If you say yes to this option, support will be included for the Intel
|
||||
801 family of mainboard I2C interfaces. Specifically, the following
|
||||
|
@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
|
||||
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
|
||||
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
|
||||
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
|
||||
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
|
||||
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
|
||||
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
|
||||
|
||||
|
@ -82,7 +82,8 @@
|
||||
#include <linux/wait.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
|
||||
#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
|
||||
defined CONFIG_DMI
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c-mux-gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -192,7 +193,8 @@ struct i801_priv {
|
||||
int len;
|
||||
u8 *data;
|
||||
|
||||
#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
|
||||
#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
|
||||
defined CONFIG_DMI
|
||||
const struct i801_mux_config *mux_drvdata;
|
||||
struct platform_device *mux_pdev;
|
||||
#endif
|
||||
@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {}
|
||||
static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
|
||||
#endif /* CONFIG_X86 && CONFIG_DMI */
|
||||
|
||||
#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
|
||||
#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
|
||||
defined CONFIG_DMI
|
||||
static struct i801_mux_config i801_mux_config_asus_z8_d12 = {
|
||||
.gpio_chip = "gpio_ich",
|
||||
.values = { 0x02, 0x03 },
|
||||
@ -1059,7 +1062,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)
|
||||
|
||||
id = dmi_first_match(mux_dmi_table);
|
||||
if (id) {
|
||||
/* Remove from branch classes from trunk */
|
||||
/* Remove branch classes from trunk */
|
||||
mux_config = id->driver_data;
|
||||
for (i = 0; i < mux_config->n_values; i++)
|
||||
class &= ~mux_config->classes[i];
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Freescale MXS I2C bus driver
|
||||
*
|
||||
* Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
|
||||
* Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K.
|
||||
*
|
||||
* based on a (non-working) driver which was:
|
||||
*
|
||||
@ -35,10 +35,6 @@
|
||||
|
||||
#define DRIVER_NAME "mxs-i2c"
|
||||
|
||||
static bool use_pioqueue;
|
||||
module_param(use_pioqueue, bool, 0);
|
||||
MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
|
||||
|
||||
#define MXS_I2C_CTRL0 (0x00)
|
||||
#define MXS_I2C_CTRL0_SET (0x04)
|
||||
|
||||
@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
|
||||
MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \
|
||||
MXS_I2C_CTRL1_SLAVE_IRQ)
|
||||
|
||||
#define MXS_I2C_QUEUECTRL (0x60)
|
||||
#define MXS_I2C_QUEUECTRL_SET (0x64)
|
||||
#define MXS_I2C_QUEUECTRL_CLR (0x68)
|
||||
|
||||
#define MXS_I2C_QUEUECTRL_QUEUE_RUN 0x20
|
||||
#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE 0x04
|
||||
|
||||
#define MXS_I2C_QUEUESTAT (0x70)
|
||||
#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY 0x00002000
|
||||
#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F
|
||||
|
||||
#define MXS_I2C_QUEUECMD (0x80)
|
||||
|
||||
#define MXS_I2C_QUEUEDATA (0x90)
|
||||
|
||||
#define MXS_I2C_DATA (0xa0)
|
||||
|
||||
|
||||
#define MXS_CMD_I2C_SELECT (MXS_I2C_CTRL0_RETAIN_CLOCK | \
|
||||
MXS_I2C_CTRL0_PRE_SEND_START | \
|
||||
@ -153,7 +132,6 @@ struct mxs_i2c_dev {
|
||||
const struct mxs_i2c_speed_config *speed;
|
||||
|
||||
/* DMA support components */
|
||||
bool dma_mode;
|
||||
int dma_channel;
|
||||
struct dma_chan *dmach;
|
||||
struct mxs_dma_data dma_data;
|
||||
@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
|
||||
writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
|
||||
|
||||
writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
|
||||
if (i2c->dma_mode)
|
||||
writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_CLR);
|
||||
else
|
||||
writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_SET);
|
||||
}
|
||||
|
||||
static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len,
|
||||
int flags)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD);
|
||||
|
||||
data = (addr << 1) | I2C_SMBUS_READ;
|
||||
writel(data, i2c->regs + MXS_I2C_DATA);
|
||||
|
||||
data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags;
|
||||
writel(data, i2c->regs + MXS_I2C_QUEUECMD);
|
||||
}
|
||||
|
||||
static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c,
|
||||
u8 addr, u8 *buf, int len, int flags)
|
||||
{
|
||||
u32 data;
|
||||
int i, shifts_left;
|
||||
|
||||
data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags;
|
||||
writel(data, i2c->regs + MXS_I2C_QUEUECMD);
|
||||
|
||||
/*
|
||||
* We have to copy the slave address (u8) and buffer (arbitrary number
|
||||
* of u8) into the data register (u32). To achieve that, the u8 are put
|
||||
* into the MSBs of 'data' which is then shifted for the next u8. When
|
||||
* appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32
|
||||
* looks like this:
|
||||
*
|
||||
* 3 2 1 0
|
||||
* 10987654|32109876|54321098|76543210
|
||||
* --------+--------+--------+--------
|
||||
* buffer+2|buffer+1|buffer+0|slave_addr
|
||||
*/
|
||||
|
||||
data = ((addr << 1) | I2C_SMBUS_WRITE) << 24;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
data >>= 8;
|
||||
data |= buf[i] << 24;
|
||||
if ((i & 3) == 2)
|
||||
writel(data, i2c->regs + MXS_I2C_DATA);
|
||||
}
|
||||
|
||||
/* Write out the remaining bytes if any */
|
||||
shifts_left = 24 - (i & 3) * 8;
|
||||
if (shifts_left)
|
||||
writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the
|
||||
* rd_threshold to 1). Couldn't get this to work, though.
|
||||
*/
|
||||
static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
|
||||
|
||||
while (readl(i2c->regs + MXS_I2C_QUEUESTAT)
|
||||
& MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) {
|
||||
if (time_after(jiffies, timeout))
|
||||
return -ETIMEDOUT;
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
|
||||
{
|
||||
u32 uninitialized_var(data);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((i & 3) == 0) {
|
||||
if (mxs_i2c_wait_for_data(i2c))
|
||||
return -ETIMEDOUT;
|
||||
data = readl(i2c->regs + MXS_I2C_QUEUEDATA);
|
||||
}
|
||||
buf[i] = data & 0xff;
|
||||
data >>= 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
|
||||
@ -432,39 +317,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
init_completion(&i2c->cmd_complete);
|
||||
i2c->cmd_err = 0;
|
||||
|
||||
if (i2c->dma_mode) {
|
||||
ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
if (msg->flags & I2C_M_RD) {
|
||||
mxs_i2c_pioq_setup_read(i2c, msg->addr,
|
||||
msg->len, flags);
|
||||
} else {
|
||||
mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf,
|
||||
msg->len, flags);
|
||||
}
|
||||
|
||||
writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_SET);
|
||||
}
|
||||
ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wait_for_completion_timeout(&i2c->cmd_complete,
|
||||
msecs_to_jiffies(1000));
|
||||
if (ret == 0)
|
||||
goto timeout;
|
||||
|
||||
if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) {
|
||||
ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
|
||||
if (ret)
|
||||
goto timeout;
|
||||
}
|
||||
|
||||
if (i2c->cmd_err == -ENXIO)
|
||||
mxs_i2c_reset(i2c);
|
||||
else
|
||||
writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_CLR);
|
||||
|
||||
dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
|
||||
|
||||
@ -472,8 +335,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
|
||||
timeout:
|
||||
dev_dbg(i2c->dev, "Timeout!\n");
|
||||
if (i2c->dma_mode)
|
||||
mxs_i2c_dma_finish(i2c);
|
||||
mxs_i2c_dma_finish(i2c);
|
||||
mxs_i2c_reset(i2c);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
@ -502,7 +364,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
|
||||
{
|
||||
struct mxs_i2c_dev *i2c = dev_id;
|
||||
u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
|
||||
bool is_last_cmd;
|
||||
|
||||
if (!stat)
|
||||
return IRQ_NONE;
|
||||
@ -515,14 +376,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
|
||||
/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
|
||||
i2c->cmd_err = -EIO;
|
||||
|
||||
if (!i2c->dma_mode) {
|
||||
is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
|
||||
MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
|
||||
|
||||
if (is_last_cmd || i2c->cmd_err)
|
||||
complete(&i2c->cmd_complete);
|
||||
}
|
||||
|
||||
writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@ -555,15 +408,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
|
||||
struct device_node *node = dev->of_node;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The MXS I2C DMA mode is prefered and enabled by default.
|
||||
* The PIO mode is still supported, but should be used only
|
||||
* for debuging purposes etc.
|
||||
*/
|
||||
i2c->dma_mode = !use_pioqueue;
|
||||
if (!i2c->dma_mode)
|
||||
dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n");
|
||||
|
||||
/*
|
||||
* TODO: This is a temporary solution and should be changed
|
||||
* to use generic DMA binding later when the helpers get in.
|
||||
@ -571,8 +415,8 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
|
||||
ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
|
||||
&i2c->dma_channel);
|
||||
if (ret) {
|
||||
dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n");
|
||||
i2c->dma_mode = 0;
|
||||
dev_err(dev, "Failed to get DMA channel!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "clock-frequency", &speed);
|
||||
@ -634,15 +478,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Setup the DMA */
|
||||
if (i2c->dma_mode) {
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
i2c->dma_data.chan_irq = dmairq;
|
||||
i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
|
||||
if (!i2c->dmach) {
|
||||
dev_err(dev, "Failed to request dma\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
i2c->dma_data.chan_irq = dmairq;
|
||||
i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
|
||||
if (!i2c->dmach) {
|
||||
dev_err(dev, "Failed to request dma\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, i2c);
|
||||
|
@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
|
||||
pm_runtime_get_sync(&dev->adev->dev);
|
||||
|
||||
clk_enable(dev->clk);
|
||||
status = clk_prepare_enable(dev->clk);
|
||||
if (status) {
|
||||
dev_err(&dev->adev->dev, "can't prepare_enable clock\n");
|
||||
goto out_clk;
|
||||
}
|
||||
|
||||
status = init_hw(dev);
|
||||
if (status)
|
||||
@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
}
|
||||
|
||||
out:
|
||||
clk_disable(dev->clk);
|
||||
clk_disable_unprepare(dev->clk);
|
||||
out_clk:
|
||||
pm_runtime_put_sync(&dev->adev->dev);
|
||||
|
||||
dev->busy = false;
|
||||
|
@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
|
||||
tegra_i2c_isr, 0, pdev->name, i2c_dev);
|
||||
tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
|
||||
return ret;
|
||||
|
@ -2,7 +2,7 @@
|
||||
i2c-stub.c - I2C/SMBus chip emulator
|
||||
|
||||
Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
|
||||
Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
|
||||
Copyright (C) 2007, 2012 Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -51,8 +51,8 @@ struct stub_chip {
|
||||
static struct stub_chip *stub_chips;
|
||||
|
||||
/* Return negative errno on error. */
|
||||
static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
|
||||
char read_write, u8 command, int size, union i2c_smbus_data * data)
|
||||
static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
|
||||
char read_write, u8 command, int size, union i2c_smbus_data *data)
|
||||
{
|
||||
s32 ret;
|
||||
int i, len;
|
||||
@ -78,14 +78,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
|
||||
case I2C_SMBUS_BYTE:
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
chip->pointer = command;
|
||||
dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
|
||||
"wrote 0x%02x.\n",
|
||||
addr, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus byte - addr 0x%02x, wrote 0x%02x.\n",
|
||||
addr, command);
|
||||
} else {
|
||||
data->byte = chip->words[chip->pointer++] & 0xff;
|
||||
dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
|
||||
"read 0x%02x.\n",
|
||||
addr, data->byte);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus byte - addr 0x%02x, read 0x%02x.\n",
|
||||
addr, data->byte);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
@ -95,14 +95,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
chip->words[command] &= 0xff00;
|
||||
chip->words[command] |= data->byte;
|
||||
dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
|
||||
"wrote 0x%02x at 0x%02x.\n",
|
||||
addr, data->byte, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
|
||||
addr, data->byte, command);
|
||||
} else {
|
||||
data->byte = chip->words[command] & 0xff;
|
||||
dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
|
||||
"read 0x%02x at 0x%02x.\n",
|
||||
addr, data->byte, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus byte data - addr 0x%02x, read 0x%02x at 0x%02x.\n",
|
||||
addr, data->byte, command);
|
||||
}
|
||||
chip->pointer = command + 1;
|
||||
|
||||
@ -112,14 +112,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
chip->words[command] = data->word;
|
||||
dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
|
||||
"wrote 0x%04x at 0x%02x.\n",
|
||||
addr, data->word, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n",
|
||||
addr, data->word, command);
|
||||
} else {
|
||||
data->word = chip->words[command];
|
||||
dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
|
||||
"read 0x%04x at 0x%02x.\n",
|
||||
addr, data->word, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus word data - addr 0x%02x, read 0x%04x at 0x%02x.\n",
|
||||
addr, data->word, command);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
@ -132,17 +132,17 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
|
||||
chip->words[command + i] &= 0xff00;
|
||||
chip->words[command + i] |= data->block[1 + i];
|
||||
}
|
||||
dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
|
||||
"wrote %d bytes at 0x%02x.\n",
|
||||
addr, len, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n",
|
||||
addr, len, command);
|
||||
} else {
|
||||
for (i = 0; i < len; i++) {
|
||||
data->block[1 + i] =
|
||||
chip->words[command + i] & 0xff;
|
||||
}
|
||||
dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
|
||||
"read %d bytes at 0x%02x.\n",
|
||||
addr, len, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"i2c block data - addr 0x%02x, read %d bytes at 0x%02x.\n",
|
||||
addr, len, command);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
@ -179,25 +179,24 @@ static int __init i2c_stub_init(void)
|
||||
int i, ret;
|
||||
|
||||
if (!chip_addr[0]) {
|
||||
printk(KERN_ERR "i2c-stub: Please specify a chip address\n");
|
||||
pr_err("i2c-stub: Please specify a chip address\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
|
||||
if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {
|
||||
printk(KERN_ERR "i2c-stub: Invalid chip address "
|
||||
"0x%02x\n", chip_addr[i]);
|
||||
pr_err("i2c-stub: Invalid chip address 0x%02x\n",
|
||||
chip_addr[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n",
|
||||
chip_addr[i]);
|
||||
pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]);
|
||||
}
|
||||
|
||||
/* Allocate memory for all chips at once */
|
||||
stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
|
||||
if (!stub_chips) {
|
||||
printk(KERN_ERR "i2c-stub: Out of memory\n");
|
||||
pr_err("i2c-stub: Out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -219,4 +218,3 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(i2c_stub_init);
|
||||
module_exit(i2c_stub_exit);
|
||||
|
@ -57,7 +57,7 @@ static const struct pci_device_id emu_tbl[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, emu_tbl);
|
||||
|
||||
static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
static int emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
struct emu *emu;
|
||||
struct gameport *port;
|
||||
@ -107,7 +107,7 @@ static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id
|
||||
return error;
|
||||
}
|
||||
|
||||
static void __devexit emu_remove(struct pci_dev *pdev)
|
||||
static void emu_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct emu *emu = pci_get_drvdata(pdev);
|
||||
|
||||
@ -122,7 +122,7 @@ static struct pci_driver emu_driver = {
|
||||
.name = "Emu10k1_gameport",
|
||||
.id_table = emu_tbl,
|
||||
.probe = emu_probe,
|
||||
.remove = __devexit_p(emu_remove),
|
||||
.remove = emu_remove,
|
||||
};
|
||||
|
||||
module_pci_driver(emu_driver);
|
||||
|
@ -78,7 +78,7 @@ static int fm801_gp_open(struct gameport *gameport, int mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
|
||||
static int fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
|
||||
{
|
||||
struct fm801_gp *gp;
|
||||
struct gameport *port;
|
||||
@ -129,7 +129,7 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device
|
||||
return error;
|
||||
}
|
||||
|
||||
static void __devexit fm801_gp_remove(struct pci_dev *pci)
|
||||
static void fm801_gp_remove(struct pci_dev *pci)
|
||||
{
|
||||
struct fm801_gp *gp = pci_get_drvdata(pci);
|
||||
|
||||
@ -150,7 +150,7 @@ static struct pci_driver fm801_gp_driver = {
|
||||
.name = "FM801_gameport",
|
||||
.id_table = fm801_gp_id_table,
|
||||
.probe = fm801_gp_probe,
|
||||
.remove = __devexit_p(fm801_gp_remove),
|
||||
.remove = fm801_gp_remove,
|
||||
};
|
||||
|
||||
module_pci_driver(fm801_gp_driver);
|
||||
|
@ -194,7 +194,7 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
|
||||
if (!mt)
|
||||
return;
|
||||
|
||||
oldest = 0;
|
||||
oldest = NULL;
|
||||
oldid = mt->trkid;
|
||||
count = 0;
|
||||
|
||||
|
@ -534,8 +534,11 @@ EXPORT_SYMBOL(input_grab_device);
|
||||
static void __input_release_device(struct input_handle *handle)
|
||||
{
|
||||
struct input_dev *dev = handle->dev;
|
||||
struct input_handle *grabber;
|
||||
|
||||
if (dev->grab == handle) {
|
||||
grabber = rcu_dereference_protected(dev->grab,
|
||||
lockdep_is_held(&dev->mutex));
|
||||
if (grabber == handle) {
|
||||
rcu_assign_pointer(dev->grab, NULL);
|
||||
/* Make sure input_pass_event() notices that grab is gone */
|
||||
synchronize_rcu();
|
||||
@ -1723,7 +1726,7 @@ EXPORT_SYMBOL_GPL(input_class);
|
||||
/**
|
||||
* input_allocate_device - allocate memory for new input device
|
||||
*
|
||||
* Returns prepared struct input_dev or NULL.
|
||||
* Returns prepared struct input_dev or %NULL.
|
||||
*
|
||||
* NOTE: Use input_free_device() to free devices that have not been
|
||||
* registered; input_unregister_device() should be used for already
|
||||
@ -1750,6 +1753,70 @@ struct input_dev *input_allocate_device(void)
|
||||
}
|
||||
EXPORT_SYMBOL(input_allocate_device);
|
||||
|
||||
struct input_devres {
|
||||
struct input_dev *input;
|
||||
};
|
||||
|
||||
static int devm_input_device_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct input_devres *devres = res;
|
||||
|
||||
return devres->input == data;
|
||||
}
|
||||
|
||||
static void devm_input_device_release(struct device *dev, void *res)
|
||||
{
|
||||
struct input_devres *devres = res;
|
||||
struct input_dev *input = devres->input;
|
||||
|
||||
dev_dbg(dev, "%s: dropping reference to %s\n",
|
||||
__func__, dev_name(&input->dev));
|
||||
input_put_device(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_input_allocate_device - allocate managed input device
|
||||
* @dev: device owning the input device being created
|
||||
*
|
||||
* Returns prepared struct input_dev or %NULL.
|
||||
*
|
||||
* Managed input devices do not need to be explicitly unregistered or
|
||||
* freed as it will be done automatically when owner device unbinds from
|
||||
* its driver (or binding fails). Once managed input device is allocated,
|
||||
* it is ready to be set up and registered in the same fashion as regular
|
||||
* input device. There are no special devm_input_device_[un]register()
|
||||
* variants, regular ones work with both managed and unmanaged devices.
|
||||
*
|
||||
* NOTE: the owner device is set up as parent of input device and users
|
||||
* should not override it.
|
||||
*/
|
||||
|
||||
struct input_dev *devm_input_allocate_device(struct device *dev)
|
||||
{
|
||||
struct input_dev *input;
|
||||
struct input_devres *devres;
|
||||
|
||||
devres = devres_alloc(devm_input_device_release,
|
||||
sizeof(struct input_devres), GFP_KERNEL);
|
||||
if (!devres)
|
||||
return NULL;
|
||||
|
||||
input = input_allocate_device();
|
||||
if (!input) {
|
||||
devres_free(devres);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
input->dev.parent = dev;
|
||||
input->devres_managed = true;
|
||||
|
||||
devres->input = input;
|
||||
devres_add(dev, devres);
|
||||
|
||||
return input;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_input_allocate_device);
|
||||
|
||||
/**
|
||||
* input_free_device - free memory occupied by input_dev structure
|
||||
* @dev: input device to free
|
||||
@ -1766,8 +1833,14 @@ EXPORT_SYMBOL(input_allocate_device);
|
||||
*/
|
||||
void input_free_device(struct input_dev *dev)
|
||||
{
|
||||
if (dev)
|
||||
if (dev) {
|
||||
if (dev->devres_managed)
|
||||
WARN_ON(devres_destroy(dev->dev.parent,
|
||||
devm_input_device_release,
|
||||
devm_input_device_match,
|
||||
dev));
|
||||
input_put_device(dev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(input_free_device);
|
||||
|
||||
@ -1888,6 +1961,38 @@ static void input_cleanse_bitmasks(struct input_dev *dev)
|
||||
INPUT_CLEANSE_BITMASK(dev, SW, sw);
|
||||
}
|
||||
|
||||
static void __input_unregister_device(struct input_dev *dev)
|
||||
{
|
||||
struct input_handle *handle, *next;
|
||||
|
||||
input_disconnect_device(dev);
|
||||
|
||||
mutex_lock(&input_mutex);
|
||||
|
||||
list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
|
||||
handle->handler->disconnect(handle);
|
||||
WARN_ON(!list_empty(&dev->h_list));
|
||||
|
||||
del_timer_sync(&dev->timer);
|
||||
list_del_init(&dev->node);
|
||||
|
||||
input_wakeup_procfs_readers();
|
||||
|
||||
mutex_unlock(&input_mutex);
|
||||
|
||||
device_del(&dev->dev);
|
||||
}
|
||||
|
||||
static void devm_input_device_unregister(struct device *dev, void *res)
|
||||
{
|
||||
struct input_devres *devres = res;
|
||||
struct input_dev *input = devres->input;
|
||||
|
||||
dev_dbg(dev, "%s: unregistering device %s\n",
|
||||
__func__, dev_name(&input->dev));
|
||||
__input_unregister_device(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* input_register_device - register device with input core
|
||||
* @dev: device to be registered
|
||||
@ -1903,11 +2008,21 @@ static void input_cleanse_bitmasks(struct input_dev *dev)
|
||||
int input_register_device(struct input_dev *dev)
|
||||
{
|
||||
static atomic_t input_no = ATOMIC_INIT(0);
|
||||
struct input_devres *devres = NULL;
|
||||
struct input_handler *handler;
|
||||
unsigned int packet_size;
|
||||
const char *path;
|
||||
int error;
|
||||
|
||||
if (dev->devres_managed) {
|
||||
devres = devres_alloc(devm_input_device_unregister,
|
||||
sizeof(struct input_devres), GFP_KERNEL);
|
||||
if (!devres)
|
||||
return -ENOMEM;
|
||||
|
||||
devres->input = dev;
|
||||
}
|
||||
|
||||
/* Every input device generates EV_SYN/SYN_REPORT events. */
|
||||
__set_bit(EV_SYN, dev->evbit);
|
||||
|
||||
@ -1923,8 +2038,10 @@ int input_register_device(struct input_dev *dev)
|
||||
|
||||
dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2;
|
||||
dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL);
|
||||
if (!dev->vals)
|
||||
return -ENOMEM;
|
||||
if (!dev->vals) {
|
||||
error = -ENOMEM;
|
||||
goto err_devres_free;
|
||||
}
|
||||
|
||||
/*
|
||||
* If delay and period are pre-set by the driver, then autorepeating
|
||||
@ -1949,7 +2066,7 @@ int input_register_device(struct input_dev *dev)
|
||||
|
||||
error = device_add(&dev->dev);
|
||||
if (error)
|
||||
return error;
|
||||
goto err_free_vals;
|
||||
|
||||
path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
|
||||
pr_info("%s as %s\n",
|
||||
@ -1958,10 +2075,8 @@ int input_register_device(struct input_dev *dev)
|
||||
kfree(path);
|
||||
|
||||
error = mutex_lock_interruptible(&input_mutex);
|
||||
if (error) {
|
||||
device_del(&dev->dev);
|
||||
return error;
|
||||
}
|
||||
if (error)
|
||||
goto err_device_del;
|
||||
|
||||
list_add_tail(&dev->node, &input_dev_list);
|
||||
|
||||
@ -1972,7 +2087,21 @@ int input_register_device(struct input_dev *dev)
|
||||
|
||||
mutex_unlock(&input_mutex);
|
||||
|
||||
if (dev->devres_managed) {
|
||||
dev_dbg(dev->dev.parent, "%s: registering %s with devres.\n",
|
||||
__func__, dev_name(&dev->dev));
|
||||
devres_add(dev->dev.parent, devres);
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_device_del:
|
||||
device_del(&dev->dev);
|
||||
err_free_vals:
|
||||
kfree(dev->vals);
|
||||
dev->vals = NULL;
|
||||
err_devres_free:
|
||||
devres_free(devres);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL(input_register_device);
|
||||
|
||||
@ -1985,24 +2114,20 @@ EXPORT_SYMBOL(input_register_device);
|
||||
*/
|
||||
void input_unregister_device(struct input_dev *dev)
|
||||
{
|
||||
struct input_handle *handle, *next;
|
||||
|
||||
input_disconnect_device(dev);
|
||||
|
||||
mutex_lock(&input_mutex);
|
||||
|
||||
list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
|
||||
handle->handler->disconnect(handle);
|
||||
WARN_ON(!list_empty(&dev->h_list));
|
||||
|
||||
del_timer_sync(&dev->timer);
|
||||
list_del_init(&dev->node);
|
||||
|
||||
input_wakeup_procfs_readers();
|
||||
|
||||
mutex_unlock(&input_mutex);
|
||||
|
||||
device_unregister(&dev->dev);
|
||||
if (dev->devres_managed) {
|
||||
WARN_ON(devres_destroy(dev->dev.parent,
|
||||
devm_input_device_unregister,
|
||||
devm_input_device_match,
|
||||
dev));
|
||||
__input_unregister_device(dev);
|
||||
/*
|
||||
* We do not do input_put_device() here because it will be done
|
||||
* when 2nd devres fires up.
|
||||
*/
|
||||
} else {
|
||||
__input_unregister_device(dev);
|
||||
input_put_device(dev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(input_unregister_device);
|
||||
|
||||
|
@ -85,7 +85,10 @@ static int as5011_i2c_write(struct i2c_client *client,
|
||||
{
|
||||
uint8_t data[2] = { aregaddr, avalue };
|
||||
struct i2c_msg msg = {
|
||||
client->addr, I2C_M_IGNORE_NAK, 2, (uint8_t *)data
|
||||
.addr = client->addr,
|
||||
.flags = I2C_M_IGNORE_NAK,
|
||||
.len = 2,
|
||||
.buf = (uint8_t *)data
|
||||
};
|
||||
int error;
|
||||
|
||||
@ -98,8 +101,18 @@ static int as5011_i2c_read(struct i2c_client *client,
|
||||
{
|
||||
uint8_t data[2] = { aregaddr };
|
||||
struct i2c_msg msg_set[2] = {
|
||||
{ client->addr, I2C_M_REV_DIR_ADDR, 1, (uint8_t *)data },
|
||||
{ client->addr, I2C_M_RD | I2C_M_NOSTART, 1, (uint8_t *)data }
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = I2C_M_REV_DIR_ADDR,
|
||||
.len = 1,
|
||||
.buf = (uint8_t *)data
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = I2C_M_RD | I2C_M_NOSTART,
|
||||
.len = 1,
|
||||
.buf = (uint8_t *)data
|
||||
}
|
||||
};
|
||||
int error;
|
||||
|
||||
@ -144,7 +157,7 @@ out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __devinit as5011_configure_chip(struct as5011_device *as5011,
|
||||
static int as5011_configure_chip(struct as5011_device *as5011,
|
||||
const struct as5011_platform_data *plat_dat)
|
||||
{
|
||||
struct i2c_client *client = as5011->i2c_client;
|
||||
@ -212,8 +225,8 @@ static int __devinit as5011_configure_chip(struct as5011_device *as5011,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit as5011_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int as5011_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
const struct as5011_platform_data *plat_data;
|
||||
struct as5011_device *as5011;
|
||||
@ -328,7 +341,7 @@ err_free_mem:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __devexit as5011_remove(struct i2c_client *client)
|
||||
static int as5011_remove(struct i2c_client *client)
|
||||
{
|
||||
struct as5011_device *as5011 = i2c_get_clientdata(client);
|
||||
|
||||
@ -353,7 +366,7 @@ static struct i2c_driver as5011_driver = {
|
||||
.name = "as5011",
|
||||
},
|
||||
.probe = as5011_probe,
|
||||
.remove = __devexit_p(as5011_remove),
|
||||
.remove = as5011_remove,
|
||||
.id_table = as5011_id,
|
||||
};
|
||||
|
||||
|
@ -78,7 +78,7 @@ static void dc_pad_close(struct input_dev *dev)
|
||||
}
|
||||
|
||||
/* allow the controller to be used */
|
||||
static int __devinit probe_maple_controller(struct device *dev)
|
||||
static int probe_maple_controller(struct device *dev)
|
||||
{
|
||||
static const short btn_bit[32] = {
|
||||
BTN_C, BTN_B, BTN_A, BTN_START, -1, -1, -1, -1,
|
||||
@ -157,7 +157,7 @@ fail:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __devexit remove_maple_controller(struct device *dev)
|
||||
static int remove_maple_controller(struct device *dev)
|
||||
{
|
||||
struct maple_device *mdev = to_maple_dev(dev);
|
||||
struct dc_pad *pad = maple_get_drvdata(mdev);
|
||||
@ -175,7 +175,7 @@ static struct maple_driver dc_pad_driver = {
|
||||
.drv = {
|
||||
.name = "Dreamcast_controller",
|
||||
.probe = probe_maple_controller,
|
||||
.remove = __devexit_p(remove_maple_controller),
|
||||
.remove = remove_maple_controller,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -196,6 +196,7 @@ static void walkera0701_close(struct input_dev *dev)
|
||||
struct walkera_dev *w = input_get_drvdata(dev);
|
||||
|
||||
parport_disable_irq(w->parport);
|
||||
hrtimer_cancel(&w->timer);
|
||||
}
|
||||
|
||||
static int walkera0701_connect(struct walkera_dev *w, int parport)
|
||||
@ -224,6 +225,9 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
|
||||
if (parport_claim(w->pardevice))
|
||||
goto init_err1;
|
||||
|
||||
hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
w->timer.function = timer_handler;
|
||||
|
||||
w->input_dev = input_allocate_device();
|
||||
if (!w->input_dev)
|
||||
goto init_err2;
|
||||
@ -254,8 +258,6 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
|
||||
if (err)
|
||||
goto init_err3;
|
||||
|
||||
hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
w->timer.function = timer_handler;
|
||||
return 0;
|
||||
|
||||
init_err3:
|
||||
@ -271,7 +273,6 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
|
||||
|
||||
static void walkera0701_disconnect(struct walkera_dev *w)
|
||||
{
|
||||
hrtimer_cancel(&w->timer);
|
||||
input_unregister_device(w->input_dev);
|
||||
parport_release(w->pardevice);
|
||||
parport_unregister_device(w->pardevice);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user