summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-23 12:32:02 -0300
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-23 12:32:02 -0300
commitbf8ebd444cd4780af7e031c1fc1ec5a1141bc9ab (patch)
tree2a5e77951748fe427be25cb7614df1373fdd35a3
parent5d969334204ade2828ba6de4ccfa2e9ef3d4c893 (diff)
parent8cdf1a0d812974ed33868a4c74f62b8d128feff2 (diff)
downloadlinux-3.10-bf8ebd444cd4780af7e031c1fc1ec5a1141bc9ab.tar.gz
linux-3.10-bf8ebd444cd4780af7e031c1fc1ec5a1141bc9ab.tar.bz2
linux-3.10-bf8ebd444cd4780af7e031c1fc1ec5a1141bc9ab.zip
Merge remote-tracking branch 'tizen/tizen' into tizen-media-backports
* tizen/tizen: (119 commits) arm: odroid: cpufreq: Support for frequency up to 1.7 GHz cpufreq: BOOST: Adjust setting of BOOST frequency just before first valid freq s5p-mfc: fix handling for MPEG2 decoding with IOMMU arm: tizen_odroid_defconfig: enable pwm-fan driver media: s5p_mfc: Check the right pointer after allocation hwmon: pwm-fan: fix build error dts: Enable pwm in Exynos4412-odroidu3 and add pwm-fan hwmon: pwm-fan: Add pwm-fan driver odroid: disable dmabuf-sync media: s5p_mfc: remove unnecessary calling to function video_devdata() arm: tizen_odroid_defconfig: enable MAX77686 RTC driver ARM: dts: ODROID i2c improvements ARM: dts: Enable PMIC interrupts on ODROID ASoC: odroidx2_max98090: Rectify module device table name ASoC: odroidx2_max98090: Move clock settings from ops to late_probe ASoC: samsung-i2s: Maintain CDCLK settings across i2s_{shutdown/startup} usbnet: smsc95xx: add reset_resume function with reset operation usb: s3c-hsotg: break infinite loop in endpoint disable code arm: tizen_odroid_defconfig: enable LED heartbeat USB: add reset resume quirk for usb3503 ... Conflicts: arch/arm/configs/tizen_odroid_defconfig drivers/media/v4l2-core/videobuf2-core.c
-rw-r--r--.gbs.conf3
-rw-r--r--Documentation/cgroups/net_cls.txt5
-rw-r--r--Documentation/devicetree/bindings/hwmon/pwm-fan.txt12
-rw-r--r--Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt24
-rw-r--r--Documentation/devicetree/bindings/sound/samsung-i2s.txt6
-rw-r--r--Documentation/devicetree/bindings/usb/exynos-usb.txt16
-rw-r--r--Documentation/devicetree/bindings/usb/usb3503.txt8
-rw-r--r--Documentation/devicetree/bindings/video/samsung-fimd.txt43
-rw-r--r--Documentation/hwmon/pwm-fan17
-rw-r--r--arch/arm/boot/dts/exynos4.dtsi22
-rw-r--r--arch/arm/boot/dts/exynos4412-odroid-common.dtsi65
-rw-r--r--arch/arm/boot/dts/exynos4412-odroidu3.dts28
-rw-r--r--arch/arm/boot/dts/exynos4412-odroidx.dts2
-rw-r--r--arch/arm/boot/dts/exynos4412-odroidx2.dts24
-rw-r--r--arch/arm/boot/dts/exynos4412-trats2.dts22
-rw-r--r--arch/arm/configs/tizen_defconfig11
-rw-r--r--[-rwxr-xr-x]arch/arm/configs/tizen_odroid_defconfig615
-rw-r--r--arch/arm/mach-exynos/Makefile1
-rw-r--r--arch/arm/mach-exynos/odroid-reboot.c96
-rw-r--r--arch/arm/plat-samsung/dma-ops.c12
-rw-r--r--arch/arm/plat-samsung/include/plat/dma-ops.h2
-rw-r--r--drivers/clk/samsung/clk-exynos4-audss.c20
-rw-r--r--drivers/clk/samsung/clk-exynos4.c3
-rw-r--r--drivers/cpufreq/exynos-cpufreq.c41
-rw-r--r--drivers/cpufreq/exynos-cpufreq.h1
-rw-r--r--drivers/cpufreq/exynos4x12-cpufreq.c15
-rw-r--r--drivers/dma/pl330.c69
-rw-r--r--drivers/extcon/extcon-max77693.c74
-rw-r--r--drivers/gpu/drm/exynos/Kconfig1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c18
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h7
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c36
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c175
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c290
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c74
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.h3
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c19
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c2
-rw-r--r--drivers/gpu/drm/panel/Kconfig2
-rw-r--r--drivers/gpu/drm/panel/panel-s6e8aa0.c55
-rw-r--r--drivers/hwmon/Kconfig11
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/pwm-fan.c201
-rw-r--r--drivers/media/platform/s5p-mfc/regs-mfc.h3
-rwxr-xr-xdrivers/media/platform/s5p-mfc/s5p_mfc.c7
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_common.h30
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c2
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c32
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c26
-rw-r--r--drivers/mfd/max77686.c6
-rw-r--r--drivers/net/usb/smsc95xx.c14
-rw-r--r--drivers/phy/phy-exynos4x12-usb2.c122
-rw-r--r--drivers/phy/phy-samsung-usb2.h3
-rw-r--r--drivers/usb/core/quirks.c3
-rw-r--r--drivers/usb/gadget/f_fs.c259
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c20
-rw-r--r--drivers/usb/gadget/u_fs.h10
-rw-r--r--drivers/usb/gadget/udc-core.c25
-rw-r--r--drivers/usb/host/ehci-s5p.c2
-rw-r--r--drivers/usb/host/ohci-exynos.c114
-rw-r--r--drivers/usb/misc/usb3503.c94
-rw-r--r--include/drm/drm_mipi_dsi.h8
-rw-r--r--include/uapi/linux/netfilter/Kbuild1
-rw-r--r--include/uapi/linux/netfilter/xt_cgroup.h11
-rw-r--r--include/uapi/linux/usb/functionfs.h41
-rw-r--r--include/video/samsung_fimd.h3
-rw-r--r--net/netfilter/Kconfig10
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/xt_cgroup.c71
-rw-r--r--sound/soc/samsung/Kconfig7
-rw-r--r--sound/soc/samsung/Makefile4
-rw-r--r--sound/soc/samsung/dma.c296
-rw-r--r--sound/soc/samsung/dma.h1
-rw-r--r--sound/soc/samsung/i2s.c97
-rw-r--r--sound/soc/samsung/idma.c30
-rw-r--r--sound/soc/samsung/idma.h4
-rw-r--r--sound/soc/samsung/odroidx2_max98090.c182
-rw-r--r--sound/soc/samsung/trats2_wm1811.c (renamed from sound/soc/samsung/exynos4_wm1811.c)134
79 files changed, 2901 insertions, 928 deletions
diff --git a/.gbs.conf b/.gbs.conf
new file mode 100644
index 00000000000..2290232b08e
--- /dev/null
+++ b/.gbs.conf
@@ -0,0 +1,3 @@
+[general]
+upstream_branch = upstream
+upstream_tag = v${upstreamversion}
diff --git a/Documentation/cgroups/net_cls.txt b/Documentation/cgroups/net_cls.txt
index 9face6bb578..ec182346dea 100644
--- a/Documentation/cgroups/net_cls.txt
+++ b/Documentation/cgroups/net_cls.txt
@@ -6,6 +6,8 @@ tag network packets with a class identifier (classid).
The Traffic Controller (tc) can be used to assign
different priorities to packets from different cgroups.
+Also, Netfilter (iptables) can use this tag to perform
+actions on such packets.
Creating a net_cls cgroups instance creates a net_cls.classid file.
This net_cls.classid value is initialized to 0.
@@ -32,3 +34,6 @@ tc class add dev eth0 parent 10: classid 10:1 htb rate 40mbit
- creating traffic class 10:1
tc filter add dev eth0 parent 10: protocol ip prio 10 handle 1: cgroup
+
+configuring iptables, basic example:
+iptables -A OUTPUT -m cgroup ! --cgroup 0x100001 -j DROP
diff --git a/Documentation/devicetree/bindings/hwmon/pwm-fan.txt b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt
new file mode 100644
index 00000000000..610757ce449
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt
@@ -0,0 +1,12 @@
+Bindings for a fan connected to the PWM lines
+
+Required properties:
+- compatible : "pwm-fan"
+- pwms : the PWM that is used to control the PWM fan
+
+Example:
+ pwm-fan {
+ compatible = "pwm-fan";
+ status = "okay";
+ pwms = <&pwm 0 10000 0>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt b/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt
index 73a8914ea75..e4bb694398a 100644
--- a/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt
+++ b/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt
@@ -1,11 +1,24 @@
Samsung OdroidX2/U3 audio complex
Required properties:
- - compatible:
- "samsung,odroidx2-audio" - for odroidx2 board
- "samsung,odroidu3-audio" - for odroidu3 board
- - samsung,i2s-controller: the phandle of the I2S controller
- - samsung,audio-codec: the phandle of the max98090 audio codec
+ - compatible : "samsung,odroidx2-audio" - for odroidx2 board,
+ "samsung,odroidu3-audio" - for odroidu3 board
+ - samsung,model : the user-visible name of this sound complex.
+ - samsung,i2s-controller : the phandle of the I2S controller
+ - samsung,audio-codec : the phandle of the MAX98090 audio codec
+ - samsung,audio-routing : a list of the connections between audio
+ components; each entry is a pair of strings, the first being the
+ connection's sink, the second being the connection's source;
+ valid names for sources and sinks are the MAX98090's pins (as
+ documented in its binding), and the jacks on the board;
+ For Odroid X2:
+ * Headphone Jack
+ * Mic Jack
+ * DMIC
+
+ For Odroid U3:
+ * Headphone Jack
+ * Speakers
Example:
@@ -14,4 +27,3 @@ sound {
samsung,i2s-controller = <&i2s0>;
samsung,audio-codec = <&max98090>;
};
-
diff --git a/Documentation/devicetree/bindings/sound/samsung-i2s.txt b/Documentation/devicetree/bindings/sound/samsung-i2s.txt
index 3070046da2e..0cda9146303 100644
--- a/Documentation/devicetree/bindings/sound/samsung-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/samsung-i2s.txt
@@ -2,9 +2,10 @@
Required SoC Specific Properties:
-- compatible : "samsung,i2s-v5"
+- compatible: "samsung,i2s-v5"
- reg: physical base address of the controller and length of memory mapped
region.
+- interrupts: should contain I2S interrupt number.
- dmas: list of DMA controller phandle and DMA request line ordered pairs.
- dma-names: identifier string for each DMA request line in the dmas property.
These strings correspond 1:1 with the ordered pairs in dmas.
@@ -16,7 +17,7 @@ Optional SoC Specific Properties:
- samsung,supports-rstclr: This flag should be set if I2S software reset bit
control is required. When this flag is set I2S software reset bit will be
enabled or disabled based on need.
-- samsung,supports-secdai:If I2S block has a secondary FIFO and internal DMA,
+- samsung,supports-secdai: If I2S block has a secondary FIFO and internal DMA,
then this flag is enabled.
- samsung,idma-addr: Internal DMA register base address of the audio
sub system(used in secondary sound source).
@@ -40,6 +41,7 @@ Example:
i2s@03830000 {
compatible = "samsung,i2s-v5";
reg = <0x03830000 0x100>;
+ interrupts = <0 97 0>;
dmas = <&pdma0 10
&pdma0 9
&pdma0 8>;
diff --git a/Documentation/devicetree/bindings/usb/exynos-usb.txt b/Documentation/devicetree/bindings/usb/exynos-usb.txt
index b3abde73601..f7189b4cbce 100644
--- a/Documentation/devicetree/bindings/usb/exynos-usb.txt
+++ b/Documentation/devicetree/bindings/usb/exynos-usb.txt
@@ -38,6 +38,13 @@ Required properties:
- interrupts: interrupt number to the cpu.
- clocks: from common clock binding: handle to usb clock.
- clock-names: from common clock binding: Shall be "usbhost".
+ - port: if in the SoC there are OHCI phys, they should be listed here.
+ One phy per port. Each port should have following entries:
+ - reg: port number on OHCI controller, e.g
+ On Exynos5250, port 0 is USB2.0 otg phy
+ port 1 is HSIC phy0
+ port 2 is HSIC phy1
+ - phys: from the *Generic PHY* bindings, specifying phy used by port.
Example:
usb@12120000 {
@@ -47,4 +54,13 @@ Example:
clocks = <&clock 285>;
clock-names = "usbhost";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ phys = <&usb2phy 1>;
+ status = "disabled";
+ };
+
};
diff --git a/Documentation/devicetree/bindings/usb/usb3503.txt b/Documentation/devicetree/bindings/usb/usb3503.txt
index a018da4a7ad..221ac0dbc67 100644
--- a/Documentation/devicetree/bindings/usb/usb3503.txt
+++ b/Documentation/devicetree/bindings/usb/usb3503.txt
@@ -15,6 +15,14 @@ Optional properties:
- reset-gpios: Should specify GPIO for reset.
- initial-mode: Should specify initial mode.
(1 for HUB mode, 2 for STANDBY mode)
+- refclk: Clock used for driving REFCLK signal (optional, if not provided
+ the driver assumes that clock signal is always available, its
+ rate is specified by REF_SEL pins and a value from the primary
+ reference clock frequencies table is used)
+- refclk-frequency: Frequency of the REFCLK signal as defined by REF_SEL
+ pins (optional, if not provided, driver will not set rate of the
+ REFCLK signal and assume that a value from the primary reference
+ clock frequencies table is used)
Examples:
usb3503@08 {
diff --git a/Documentation/devicetree/bindings/video/samsung-fimd.txt b/Documentation/devicetree/bindings/video/samsung-fimd.txt
index 778838a0336..a67617acd07 100644
--- a/Documentation/devicetree/bindings/video/samsung-fimd.txt
+++ b/Documentation/devicetree/bindings/video/samsung-fimd.txt
@@ -39,6 +39,49 @@ Required properties:
Optional Properties:
- samsung,power-domain: a phandle to FIMD power domain node.
+- display-timings: timing settings for FIMD, as described in document [1].
+ Can be used in case timings cannot be provided otherwise
+ or to override timings provided by the panel.
+- samsung,sysreg: handle to syscon used to control the system registers
+- i80-if-timings: timing configuration for lcd i80 interface support.
+ - cs-setup: clock cycles for the active period of address signal is enabled
+ until chip select is enabled.
+ If not specified, the default value(0) will be used.
+ - wr-setup: clock cycles for the active period of CS signal is enabled until
+ write signal is enabled.
+ If not specified, the default value(0) will be used.
+ - wr-active: clock cycles for the active period of CS is enabled.
+ If not specified, the default value(1) will be used.
+ - wr-hold: clock cycles for the active period of CS is disabled until write
+ signal is disabled.
+ If not specified, the default value(0) will be used.
+
+ The parameters are defined as:
+
+ VCLK(internal) __|¯¯¯¯¯¯|_____|¯¯¯¯¯¯|_____|¯¯¯¯¯¯|_____|¯¯¯¯¯¯|_____|¯¯
+ : : : : :
+ Address Output --:<XXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XX
+ | cs-setup+1 | : : :
+ |<---------->| : : :
+ Chip Select ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|____________:____________:____________|¯¯
+ | wr-setup+1 | | wr-hold+1 |
+ |<---------->| |<---------->|
+ Write Enable ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|____________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+ | wr-active+1|
+ |<---------->|
+ Video Data ----------------------------<XXXXXXXXXXXXXXXXXXXXXXXXX>--
+
+The device node can contain 'port' child nodes according to the bindings defined
+in [2]. The following are properties specific to those nodes:
+- reg: (required) port index, can be:
+ 0 - for CAMIF0 input,
+ 1 - for CAMIF1 input,
+ 2 - for CAMIF2 input,
+ 3 - for parallel output,
+ 4 - for write-back interface
+
+[1]: Documentation/devicetree/bindings/video/display-timing.txt
+[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
Example:
diff --git a/Documentation/hwmon/pwm-fan b/Documentation/hwmon/pwm-fan
new file mode 100644
index 00000000000..18529d2e3bc
--- /dev/null
+++ b/Documentation/hwmon/pwm-fan
@@ -0,0 +1,17 @@
+Kernel driver pwm-fan
+=====================
+
+This driver enables the use of a PWM module to drive a fan. It uses the
+generic PWM interface thus it is hardware independent. It can be used on
+many SoCs, as long as the SoC supplies a PWM line driver that exposes
+the generic PWM API.
+
+Author: Kamil Debski <k.debski@samsung.com>
+
+Description
+-----------
+
+The driver implements a simple interface for driving a fan connected to
+a PWM output. It uses the generic PWM interface, thus it can be used with
+a range of SoCs. The driver exposes the fan to the user space through
+the hwmon's sysfs interface.
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 931a5ad71e7..c227dac81d9 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -522,7 +522,7 @@
interrupts = <0 37 0>, <0 38 0>, <0 39 0>, <0 40 0>, <0 41 0>;
clocks = <&clock 336>;
clock-names = "timers";
- #pwm-cells = <2>;
+ #pwm-cells = <3>;
samsung,pwm-outputs = <0>;
status = "ok";
};
@@ -538,6 +538,25 @@
status = "disabled";
};
+ ohci@12590000 {
+ compatible = "samsung,exynos4210-ohci";
+ reg = <0x12590000 0x100>;
+ interrupts = <0 70 0>;
+ clocks = <&clock 304>;
+ clock-names = "usbhost";
+ status = "disabled";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ phys = <&exynos_usbphy 1>;
+ phy-names = "host";
+ status = "disabled";
+ };
+ };
+
ehci@12580000 {
compatible = "samsung,exynos-ehci";
reg = <0x12580000 0x20000>;
@@ -572,6 +591,7 @@
i2s0: i2s@03830000 {
compatible = "samsung,i2s-v5";
reg = <0x03830000 0x100>;
+ interrupts = <0 97 0>;
clocks = <&clock_audss 0>, <&clock_audss 3>, <&clock_audss 1>,
<&clock_audss 2>, <&clock_audss 4>, <&clock_audss 2>;
clock-names = "mout_audss", "mout_i2s", "dout_srp",
diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index 16000370198..86c54dcf3a8 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -48,7 +48,7 @@
status = "okay";
};
- sound {
+ sound: sound {
compatible = "samsung,odroidx2-audio";
samsung,i2s-controller = <&i2s0>;
samsung,audio-codec = <&max98090>;
@@ -77,8 +77,10 @@
sdhci@12530000 {
bus-width = <4>;
- pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sd_cdn>;
pinctrl-names = "default";
+ cd-gpios = <&gpk2 2 0>;
+ cd-inverted;
status = "okay";
};
@@ -108,6 +110,8 @@
samsung,i2c-max-bus-freq = <100000>;
pinctrl-0 = <&i2c0_bus>;
pinctrl-names = "default";
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <400000>;
status = "okay";
usb3503: usb3503@08 {
@@ -123,6 +127,10 @@
max77686_pmic@09 {
compatible = "maxim,max77686";
+ interrupt-parent = <&gpx3>;
+ interrupts = <2 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&max77686_irq>;
reg = <0x09>;
voltage-regulators {
@@ -398,7 +406,6 @@
regulator-name = "VDD_BUCK8_2.8V";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
- regulator-always-on;
};
buck9_reg: buck@9 {
@@ -473,7 +480,7 @@
compatible = "maxim,max98090";
reg = <0x10>;
interrupt-parent = <&gpx0>;
- interrupts = <1 0>;
+ interrupts = <0 0>;
};
};
@@ -493,10 +500,10 @@
};
cpufreq {
- freq_table = <1400000 1300000 1200000 1100000 1000000
- 900000 800000 700000 600000 500000 400000 300000
- 200000>;
- boost_freq = <1500000>;
+ freq_table = <1704000 1600000 1500000 1400000 1300000 1200000
+ 1100000 1000000 900000 800000 700000 600000
+ 500000 400000 300000 200000>;
+ boost_freq = <1800000>;
vdd_arm-supply = <&buck2_reg>;
status = "okay";
};
@@ -516,6 +523,29 @@
vdd_pll-supply = <&ldo8_reg>;
status = "okay";
};
+
+ odroid_reboot {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_ndet>;
+ compatible = "hardkernel,odroid-reboot";
+ reset-gpio = <&gpk1 2 0>;
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_power_key>;
+
+ power_key {
+ interrupt-parent = <&gpx1>;
+ interrupts = <3 0>;
+ gpios = <&gpx1 3 1>;
+ linux,code = <116>;
+ label = "power key";
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
};
&pinctrl_1 {
@@ -524,6 +554,18 @@
samsung,pin-pud = <0>;
};
+ max77686_irq: max77686-irq {
+ samsung,pins = "gpx3-2";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ sd_cdn: sd_cdn {
+ samsung,pins = "gpk2-2";
+ samsung,pin-pud = <0>;
+ };
+
gpio_home_key: home_key {
samsung,pins = "gpx2-2";
samsung,pin-pud = <1>;
@@ -533,4 +575,11 @@
samsung,pins = "gpx3-7";
samsung,pin-pud = <1>;
};
+
+ emmc_ndet: emmc-ndet {
+ samsung,pins = "gpk1-2";
+ samsung,pin-pud = <0>;
+ samsung,pin-con-pdn = <1>;
+ samsung,pin-pud-pdn = <0>;
+ };
};
diff --git a/arch/arm/boot/dts/exynos4412-odroidu3.dts b/arch/arm/boot/dts/exynos4412-odroidu3.dts
index 85ac5329cca..0bafd23f113 100644
--- a/arch/arm/boot/dts/exynos4412-odroidu3.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidu3.dts
@@ -19,7 +19,7 @@
compatible = "hardkernel,odroid-u3", "samsung,exynos4412", "samsung,exynos4";
memory {
- reg = <0x40000000 0x40000000>;
+ reg = <0x40000000 0x7FF00000>;
};
leds {
@@ -31,11 +31,25 @@
linux,default-trigger = "heartbeat";
};
};
+
+ pwm: pwm@139D0000 {
+ pinctrl-0 = <&pwm0_out>;
+ pinctrl-names = "default";
+ samsung,pwm-outputs = <0>;
+ status = "okay";
+ };
+
+ pwm-fan {
+ compatible = "pwm-fan";
+ status = "okay";
+ pwms = <&pwm 0 10000 0>;
+ };
};
&usb3503 {
clock-names = "refclk";
clocks = <&clock 21>;
+ refclk-frequency = <24000000>;
};
&ehci {
@@ -46,3 +60,15 @@
status = "okay";
};
};
+
+&sound {
+ compatible = "samsung,odroidu3-audio";
+ samsung,model = "Odroid-U3";
+ samsung,audio-routing =
+ "Headphone Jack", "HPL",
+ "Headphone Jack", "HPR",
+ "Headphone Jack", "MICBIAS",
+ "IN1", "Headphone Jack",
+ "Speakers", "SPKL",
+ "Speakers", "SPKR";
+};
diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts
index 53bc8bf7798..aed770fc767 100644
--- a/arch/arm/boot/dts/exynos4412-odroidx.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidx.dts
@@ -19,7 +19,7 @@
compatible = "hardkernel,odroid-x", "samsung,exynos4412";
memory {
- reg = <0x40000000 0x40000000>;
+ reg = <0x40000000 0x3FF00000>;
};
leds {
diff --git a/arch/arm/boot/dts/exynos4412-odroidx2.dts b/arch/arm/boot/dts/exynos4412-odroidx2.dts
index 98166e5365f..c881c668bd7 100644
--- a/arch/arm/boot/dts/exynos4412-odroidx2.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidx2.dts
@@ -19,7 +19,7 @@
compatible = "hardkernel,odroid-x2", "samsung,exynos4412", "samsung,exynos4";
memory {
- reg = <0x40000000 0x40000000>;
+ reg = <0x40000000 0x7FF00000>;
};
leds {
@@ -39,20 +39,8 @@
};
gpio_keys {
- compatible = "gpio-keys";
- pinctrl-names = "default";
pinctrl-0 = <&gpio_power_key &gpio_home_key>;
- power_key {
- interrupt-parent = <&gpx1>;
- interrupts = <3 0>;
- gpios = <&gpx1 3 1>;
- linux,code = <116>;
- label = "power key";
- debounce-interval = <10>;
- gpio-key,wakeup;
- };
-
home_key {
interrupt-parent = <&gpx2>;
interrupts = <2 0>;
@@ -86,6 +74,7 @@
&usb3503 {
clock-names = "refclk";
clocks = <&usbhubxti>;
+ refclk-frequency = <26000000>;
};
&ehci {
@@ -93,3 +82,12 @@
status = "okay";
};
};
+
+&sound {
+ samsung,model = "Odroid-X2";
+ samsung,audio-routing =
+ "Headphone Jack", "HPL",
+ "Headphone Jack", "HPR",
+ "IN1", "Mic Jack",
+ "Mic Jack", "MICBIAS";
+};
diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts
index 219687ca92d..944c57469f0 100644
--- a/arch/arm/boot/dts/exynos4412-trats2.dts
+++ b/arch/arm/boot/dts/exynos4412-trats2.dts
@@ -1046,6 +1046,9 @@
vddcore-supply = <&ldo8_reg>;
vddio-supply = <&ldo10_reg>;
samsung,pll-clock-frequency = <24000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
status = "okay";
ports {
@@ -1130,10 +1133,21 @@
extcon = <&max_muic>;
};
+ ohci@12590000 {
+ status = "okay";
+ port@0 {
+ status = "okay";
+ };
+ };
+
ehci@12580000 {
status = "okay";
vusb_d-supply = <&ldo15_reg>;
vusb_a-supply = <&ldo12_reg>;
+ samsung,vbus-gpio = <&gpf0 7 0>;
+ port@0 {
+ status = "okay";
+ };
port@1 {
status = "okay";
};
@@ -1278,7 +1292,7 @@
};
sound {
- compatible = "samsung,exynos4-wm1811";
+ compatible = "samsung,trats2-wm1811";
clocks = <&clock 2>, <&clock 396>, <&clock 21>, <&clock 6>;
clock-names = "parent", "out-mux", "out", "pll" /* EPLL */;
samsung,i2s-controller = <&i2s0>;
@@ -1294,9 +1308,9 @@
};
cpufreq {
- freq_table = <1400000 1300000 1200000 1100000 1000000
- 900000 800000 700000 600000 500000 400000 300000
- 200000>;
+ freq_table = <1400000 1300000 1200000 1100000 1000000 900000
+ 800000 700000 600000 500000 400000 300000
+ 200000>;
boost_freq = <1500000>;
lab-num-of-states = <5>;
lab-ctrl-freq = < 0 0 0 1300000 1200000
diff --git a/arch/arm/configs/tizen_defconfig b/arch/arm/configs/tizen_defconfig
index 2b38f7c9f0a..701aa167549 100644
--- a/arch/arm/configs/tizen_defconfig
+++ b/arch/arm/configs/tizen_defconfig
@@ -2402,20 +2402,17 @@ CONFIG_SND_SOC=y
# CONFIG_SND_ATMEL_SOC is not set
# CONFIG_SND_DESIGNWARE_I2S is not set
CONFIG_SND_SOC_SAMSUNG=y
-CONFIG_SND_SAMSUNG_PCM=y
-CONFIG_SND_SAMSUNG_SPDIF=y
CONFIG_SND_SAMSUNG_I2S=y
-CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994=y
+# CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994 is not set
# CONFIG_SND_SAMSUNG_I2S_MASTER is not set
-CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF=y
-CONFIG_SND_SOC_SMDK_WM8994_PCM=y
+# CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF is not set
+# CONFIG_SND_SOC_SMDK_WM8994_PCM is not set
CONFIG_SND_SOC_TRATS=y
-CONFIG_SND_SOC_SAMSUNG_EXYNOS4_WM1811=y
+CONFIG_SND_SOC_SAMSUNG_TRATS2_WM1811=y
# CONFIG_SND_SOC_ODROIDX2 is not set
CONFIG_SND_SOC_I2C_AND_SPI=y
# CONFIG_SND_SOC_ALL_CODECS is not set
CONFIG_SND_SOC_WM_HUBS=y
-CONFIG_SND_SOC_SPDIF=y
CONFIG_SND_SOC_WM8994=y
CONFIG_SND_SOC_MC1N2=y
CONFIG_SND_SOC_USE_EXTERNAL_MIC_BIAS=y
diff --git a/arch/arm/configs/tizen_odroid_defconfig b/arch/arm/configs/tizen_odroid_defconfig
index 06348d21b7e..1aee7a961cd 100755..100644
--- a/arch/arm/configs/tizen_odroid_defconfig
+++ b/arch/arm/configs/tizen_odroid_defconfig
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm 3.10.33 Kernel Configuration
+# Linux/arm 3.10.39 Kernel Configuration
#
CONFIG_ARM=y
CONFIG_ARM_HAS_SG_CHAIN=y
@@ -402,8 +402,11 @@ CONFIG_SWP_EMULATE=y
# CONFIG_CPU_DCACHE_DISABLE is not set
# CONFIG_CPU_BPREDICT_DISABLE is not set
CONFIG_KUSER_HELPERS=y
+CONFIG_OUTER_CACHE=y
+CONFIG_OUTER_CACHE_SYNC=y
CONFIG_MIGHT_HAVE_CACHE_L2X0=y
-# CONFIG_CACHE_L2X0 is not set
+CONFIG_CACHE_L2X0=y
+CONFIG_CACHE_PL310=y
CONFIG_ARM_L1_CACHE_SHIFT_6=y
CONFIG_ARM_L1_CACHE_SHIFT=6
CONFIG_ARM_DMA_MEM_BUFFERABLE=y
@@ -414,13 +417,17 @@ CONFIG_MULTI_IRQ_HANDLER=y
# CONFIG_ARM_ERRATA_460075 is not set
# CONFIG_ARM_ERRATA_742230 is not set
# CONFIG_ARM_ERRATA_742231 is not set
+# CONFIG_PL310_ERRATA_588369 is not set
# CONFIG_ARM_ERRATA_643719 is not set
# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_PL310_ERRATA_727915 is not set
# CONFIG_ARM_ERRATA_743622 is not set
# CONFIG_ARM_ERRATA_751472 is not set
+# CONFIG_PL310_ERRATA_753970 is not set
# CONFIG_ARM_ERRATA_754322 is not set
# CONFIG_ARM_ERRATA_754327 is not set
# CONFIG_ARM_ERRATA_764369 is not set
+# CONFIG_PL310_ERRATA_769419 is not set
# CONFIG_ARM_ERRATA_775420 is not set
# CONFIG_ARM_ERRATA_798181 is not set
@@ -610,27 +617,36 @@ CONFIG_UNIX=y
# CONFIG_UNIX_DIAG is not set
CONFIG_XFRM=y
CONFIG_XFRM_ALGO=y
-# CONFIG_XFRM_USER is not set
+CONFIG_XFRM_USER=y
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=y
CONFIG_NET_KEY=y
# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE_DEMUX is not set
-# CONFIG_NET_IP_TUNNEL is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_NET_IPVTI is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
@@ -638,42 +654,266 @@ CONFIG_INET_LRO=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_INET_UDP_DIAG is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=y
CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+CONFIG_DEFAULT_BIC=y
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="bic"
# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=y
-# CONFIG_IPV6_PRIVACY is not set
-# CONFIG_IPV6_ROUTER_PREF is not set
-# CONFIG_IPV6_OPTIMISTIC_DAD is not set
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_IPV6_MIP6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_TUNNEL=y
+CONFIG_INET6_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
-# CONFIG_IPV6_SIT is not set
-# CONFIG_IPV6_TUNNEL is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=y
# CONFIG_IPV6_GRE is not set
-# CONFIG_IPV6_MULTIPLE_TABLES is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+# CONFIG_IPV6_SUBTREES is not set
# CONFIG_IPV6_MROUTE is not set
+CONFIG_NETLABEL=y
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
-# CONFIG_NETFILTER is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=y
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CONNTRACK_TIMEOUT is not set
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_GRE=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_BROADCAST=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+# CONFIG_NF_CONNTRACK_SNMP is not set
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_NF_NAT_PROTO_DCCP=y
+CONFIG_NF_NAT_PROTO_UDPLITE=y
+CONFIG_NF_NAT_PROTO_SCTP=y
+CONFIG_NF_NAT_AMANDA=y
+CONFIG_NF_NAT_FTP=y
+CONFIG_NF_NAT_IRC=y
+# CONFIG_NF_NAT_SIP is not set
+CONFIG_NF_NAT_TFTP=y
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+# CONFIG_NETFILTER_XT_TARGET_CT is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_HL is not set
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NETMAP=y
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+CONFIG_NETFILTER_XT_TARGET_REDIRECT=y
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+CONFIG_NETFILTER_XT_MATCH_ECN=y
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_HL=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+# CONFIG_IP_NF_MATCH_RPFILTER is not set
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT_IPV4=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_NF_NAT_PROTO_GRE=y
+CONFIG_NF_NAT_PPTP=y
+CONFIG_NF_NAT_H323=y
+CONFIG_IP_NF_MANGLE=y
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_RAW=y
+# CONFIG_IP_NF_SECURITY is not set
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+# CONFIG_IP6_NF_MATCH_AH is not set
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+# CONFIG_IP6_NF_MATCH_MH is not set
+# CONFIG_IP6_NF_MATCH_RPFILTER is not set
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_TARGET_HL is not set
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+# CONFIG_IP6_NF_SECURITY is not set
+# CONFIG_NF_NAT_IPV6 is not set
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+# CONFIG_BRIDGE_EBT_T_FILTER is not set
+# CONFIG_BRIDGE_EBT_T_NAT is not set
+# CONFIG_BRIDGE_EBT_802_3 is not set
+# CONFIG_BRIDGE_EBT_AMONG is not set
+# CONFIG_BRIDGE_EBT_ARP is not set
+# CONFIG_BRIDGE_EBT_IP is not set
+# CONFIG_BRIDGE_EBT_IP6 is not set
+# CONFIG_BRIDGE_EBT_LIMIT is not set
+# CONFIG_BRIDGE_EBT_MARK is not set
+# CONFIG_BRIDGE_EBT_PKTTYPE is not set
+# CONFIG_BRIDGE_EBT_STP is not set
+# CONFIG_BRIDGE_EBT_VLAN is not set
+# CONFIG_BRIDGE_EBT_ARPREPLY is not set
+# CONFIG_BRIDGE_EBT_DNAT is not set
+# CONFIG_BRIDGE_EBT_MARK_T is not set
+# CONFIG_BRIDGE_EBT_REDIRECT is not set
+# CONFIG_BRIDGE_EBT_SNAT is not set
+# CONFIG_BRIDGE_EBT_LOG is not set
+# CONFIG_BRIDGE_EBT_ULOG is not set
+# CONFIG_BRIDGE_EBT_NFLOG is not set
# CONFIG_IP_DCCP is not set
# CONFIG_IP_SCTP is not set
# CONFIG_RDS is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_L2TP is not set
-# CONFIG_BRIDGE is not set
+CONFIG_STP=y
+CONFIG_BRIDGE=y
+CONFIG_BRIDGE_IGMP_SNOOPING=y
CONFIG_HAVE_NET_DSA=y
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
+CONFIG_LLC=y
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
@@ -681,7 +921,67 @@ CONFIG_HAVE_NET_DSA=y
# CONFIG_LAPB is not set
# CONFIG_PHONET is not set
# CONFIG_IEEE802154 is not set
-# CONFIG_NET_SCHED is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+CONFIG_NET_SCH_HTB=y
+# CONFIG_NET_SCH_HFSC is not set
+CONFIG_NET_SCH_PRIO=y
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFB is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_QFQ is not set
+# CONFIG_NET_SCH_CODEL is not set
+# CONFIG_NET_SCH_FQ_CODEL is not set
+# CONFIG_NET_SCH_INGRESS is not set
+# CONFIG_NET_SCH_PLUG is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_CLS_CGROUP=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+# CONFIG_NET_ACT_POLICE is not set
+# CONFIG_NET_ACT_GACT is not set
+# CONFIG_NET_ACT_MIRRED is not set
+# CONFIG_NET_ACT_IPT is not set
+# CONFIG_NET_ACT_NAT is not set
+# CONFIG_NET_ACT_PEDIT is not set
+# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
+# CONFIG_NET_ACT_CSUM is not set
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
# CONFIG_DCB is not set
CONFIG_DNS_RESOLVER=y
# CONFIG_BATMAN_ADV is not set
@@ -705,6 +1005,7 @@ CONFIG_BQL=y
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_LIB80211 is not set
@@ -747,7 +1048,7 @@ CONFIG_REGMAP_SPI=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
CONFIG_DMA_SHARED_BUFFER=y
-CONFIG_DMABUF_SYNC=y
+# CONFIG_DMABUF_SYNC is not set
CONFIG_CMA=y
CONFIG_CMA_DEBUG=y
@@ -825,7 +1126,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
# CONFIG_BMP085_SPI is not set
# CONFIG_USB_SWITCH_FSA9480 is not set
# CONFIG_LATTICE_ECP3_CONFIG is not set
-# CONFIG_SLP_GLOBAL_LOCK is not set
+CONFIG_SLP_GLOBAL_LOCK=y
# CONFIG_SRAM is not set
# CONFIG_SII9234 is not set
# CONFIG_C2PORT is not set
@@ -922,6 +1223,7 @@ CONFIG_NET_CORE=y
# CONFIG_DUMMY is not set
# CONFIG_EQUALIZER is not set
CONFIG_MII=y
+# CONFIG_IFB is not set
# CONFIG_NET_TEAM is not set
# CONFIG_MACVLAN is not set
# CONFIG_VXLAN is not set
@@ -1095,6 +1397,7 @@ CONFIG_KEYBOARD_GPIO=y
# CONFIG_KEYBOARD_TCA6416 is not set
# CONFIG_KEYBOARD_TCA8418 is not set
# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
# CONFIG_KEYBOARD_LM8333 is not set
# CONFIG_KEYBOARD_MAX7359 is not set
# CONFIG_KEYBOARD_MCS is not set
@@ -1397,7 +1700,111 @@ CONFIG_DEBUG_GPIO=y
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_POWER_AVS is not set
-# CONFIG_HWMON is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7314 is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7310 is not set
+# CONFIG_SENSORS_ADT7410 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_GPIO_FAN is not set
+# CONFIG_SENSORS_HIH6130 is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_LM95234 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LM95245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+# CONFIG_SENSORS_MAX197 is not set
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_MAX6697 is not set
+# CONFIG_SENSORS_MCP3021 is not set
+# CONFIG_SENSORS_NCT6775 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+CONFIG_SENSORS_PWM_FAN=y
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
+# CONFIG_SENSORS_ADS1015 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_INA209 is not set
+# CONFIG_SENSORS_INA2XX is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_THERMAL is not set
# CONFIG_WATCHDOG is not set
CONFIG_SSB_POSSIBLE=y
@@ -1682,6 +2089,7 @@ CONFIG_VIDEO_TVEEPROM=y
#
CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
CONFIG_MEDIA_ATTACH=y
+CONFIG_VIDEO_IR_I2C=y
#
# Audio decoders, processors and mixers
@@ -1723,7 +2131,11 @@ CONFIG_MEDIA_ATTACH=y
# Sensors used on soc_camera driver
#
CONFIG_MEDIA_TUNER_TDA18271=y
+CONFIG_MEDIA_TUNER_MT2060=y
+CONFIG_MEDIA_TUNER_MT2266=y
+CONFIG_MEDIA_TUNER_XC2028=y
CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_MEDIA_TUNER_XC4000=y
CONFIG_MEDIA_TUNER_MXL5007T=y
#
@@ -1741,6 +2153,9 @@ CONFIG_MEDIA_TUNER_MXL5007T=y
#
# DVB-T (terrestrial) frontends
#
+CONFIG_DVB_DIB3000MC=y
+CONFIG_DVB_DIB7000M=y
+CONFIG_DVB_DIB7000P=y
#
# DVB-C (cable) frontends
@@ -1754,14 +2169,18 @@ CONFIG_DVB_LG2160=y
CONFIG_DVB_AU8522=y
CONFIG_DVB_AU8522_DTV=y
CONFIG_DVB_AU8522_V4L=y
+CONFIG_DVB_S5H1411=y
#
# ISDB-T (terrestrial) frontends
#
+CONFIG_DVB_DIB8000=y
#
# Digital terrestrial only tuners/PLL
#
+CONFIG_DVB_TUNER_DIB0070=y
+CONFIG_DVB_TUNER_DIB0090=y
#
# SEC control devices for DVB-S
@@ -1914,6 +2333,8 @@ CONFIG_SND_USB_AUDIO=m
# CONFIG_SND_USB_CAIAQ is not set
# CONFIG_SND_USB_6FIRE is not set
CONFIG_SND_SOC=y
+CONFIG_SND_SOC_DMAENGINE_PCM=y
+CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y
# CONFIG_SND_ATMEL_SOC is not set
# CONFIG_SND_DESIGNWARE_I2S is not set
CONFIG_SND_SOC_SAMSUNG=y
@@ -1923,7 +2344,7 @@ CONFIG_SND_SAMSUNG_I2S_MASTER=y
# CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF is not set
# CONFIG_SND_SOC_SMDK_WM8994_PCM is not set
# CONFIG_SND_SOC_TRATS is not set
-# CONFIG_SND_SOC_SAMSUNG_EXYNOS4_WM1811 is not set
+# CONFIG_SND_SOC_SAMSUNG_TRATS2_WM1811 is not set
CONFIG_SND_SOC_ODROIDX2=y
CONFIG_SND_SOC_I2C_AND_SPI=y
# CONFIG_SND_SOC_ALL_CODECS is not set
@@ -1996,7 +2417,10 @@ CONFIG_HID_MONTEREY=y
# CONFIG_HID_SMARTJOYPLUS is not set
# CONFIG_HID_TIVO is not set
# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THINGM is not set
# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_WIIMOTE is not set
# CONFIG_HID_ZEROPLUS is not set
# CONFIG_HID_ZYDACRON is not set
# CONFIG_HID_SENSOR_HUB is not set
@@ -2123,9 +2547,8 @@ CONFIG_USB_PHY=y
# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_OMAP_CONTROL_USB is not set
# CONFIG_OMAP_USB3 is not set
-CONFIG_SAMSUNG_USBPHY=y
-CONFIG_SAMSUNG_USB2PHY=y
-CONFIG_SAMSUNG_USB3PHY=y
+# CONFIG_SAMSUNG_USB2PHY is not set
+# CONFIG_SAMSUNG_USB3PHY is not set
# CONFIG_USB_GPIO_VBUS is not set
# CONFIG_USB_ISP1301 is not set
# CONFIG_USB_RCAR_PHY is not set
@@ -2150,16 +2573,12 @@ CONFIG_USB_S3C_HSOTG=y
# CONFIG_USB_NET2272 is not set
# CONFIG_USB_DUMMY_HCD is not set
CONFIG_USB_LIBCOMPOSITE=y
-CONFIG_USB_U_ETHER=y
-CONFIG_USB_F_ECM=y
-CONFIG_USB_F_SUBSET=y
-CONFIG_USB_F_RNDIS=y
+CONFIG_USB_F_ACM=y
+CONFIG_USB_U_SERIAL=y
# CONFIG_USB_CONFIGFS is not set
# CONFIG_USB_ZERO is not set
# CONFIG_USB_AUDIO is not set
-CONFIG_USB_ETH=y
-CONFIG_USB_ETH_RNDIS=y
-# CONFIG_USB_ETH_EEM is not set
+# CONFIG_USB_ETH is not set
# CONFIG_USB_G_NCM is not set
# CONFIG_USB_GADGETFS is not set
# CONFIG_USB_FUNCTIONFS is not set
@@ -2167,7 +2586,7 @@ CONFIG_USB_ETH_RNDIS=y
# CONFIG_USB_G_SERIAL is not set
# CONFIG_USB_MIDI_GADGET is not set
# CONFIG_USB_G_PRINTER is not set
-# CONFIG_USB_G_SLP is not set
+CONFIG_USB_G_SLP=y
# CONFIG_USB_CDC_COMPOSITE is not set
# CONFIG_USB_G_ACM_MS is not set
# CONFIG_USB_G_MULTI is not set
@@ -2176,7 +2595,7 @@ CONFIG_USB_ETH_RNDIS=y
# CONFIG_USB_G_WEBCAM is not set
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
-# CONFIG_MMC_UNSAFE_RESUME is not set
+CONFIG_MMC_UNSAFE_RESUME=y
# CONFIG_MMC_CLKGATE is not set
#
@@ -2205,7 +2624,51 @@ CONFIG_MMC_DW_EXYNOS=y
# CONFIG_MMC_VUB300 is not set
# CONFIG_MMC_USHC is not set
# CONFIG_MEMSTICK is not set
-# CONFIG_NEW_LEDS is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_LM3530 is not set
+# CONFIG_LEDS_LM3642 is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_LP5562 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_PCA9633 is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_PWM is not set
+# CONFIG_LEDS_REGULATOR is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_RENESAS_TPU is not set
+# CONFIG_LEDS_TCA6507 is not set
+# CONFIG_LEDS_MAX8997 is not set
+# CONFIG_LEDS_LM355x is not set
+# CONFIG_LEDS_OT200 is not set
+# CONFIG_LEDS_BLINKM is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_ONESHOT is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_CPU is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_LEDS_TRIGGER_TRANSIENT is not set
+# CONFIG_LEDS_TRIGGER_CAMERA is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=y
@@ -2233,7 +2696,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_DS3232 is not set
# CONFIG_RTC_DRV_MAX6900 is not set
# CONFIG_RTC_DRV_MAX8997 is not set
-# CONFIG_RTC_DRV_MAX77686 is not set
+CONFIG_RTC_DRV_MAX77686=y
# CONFIG_RTC_DRV_RS5C372 is not set
# CONFIG_RTC_DRV_ISL1208 is not set
# CONFIG_RTC_DRV_ISL12022 is not set
@@ -2403,7 +2866,9 @@ CONFIG_EXYNOS_IOMMU=y
# CONFIG_EXTCON is not set
# CONFIG_MEMORY is not set
# CONFIG_IIO is not set
-# CONFIG_PWM is not set
+CONFIG_PWM=y
+CONFIG_PWM_SYSFS=y
+CONFIG_PWM_SAMSUNG=y
CONFIG_IRQCHIP=y
CONFIG_ARM_GIC=y
CONFIG_GIC_NON_BANKED=y
@@ -2415,10 +2880,10 @@ CONFIG_GIC_NON_BANKED=y
#
CONFIG_GENERIC_PHY=y
# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set
+CONFIG_EXYNOS_PHY=y
CONFIG_PHY_SAMSUNG_USB2=y
CONFIG_PHY_EXYNOS4210_USB2=y
CONFIG_PHY_EXYNOS4X12_USB2=y
-CONFIG_EXYNOS_PHY=y
#
# File systems
@@ -2433,8 +2898,8 @@ CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
CONFIG_EXT4_FS=y
-# CONFIG_EXT4_FS_POSIX_ACL is not set
-# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
# CONFIG_EXT4_DEBUG is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
@@ -2453,10 +2918,11 @@ CONFIG_FILE_LOCKING=y
CONFIG_FSNOTIFY=y
CONFIG_DNOTIFY=y
CONFIG_INOTIFY_USER=y
-# CONFIG_FANOTIFY is not set
+CONFIG_FANOTIFY=y
+# CONFIG_FANOTIFY_ACCESS_PERMISSIONS is not set
# CONFIG_QUOTA is not set
# CONFIG_QUOTACTL is not set
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=y
# CONFIG_FUSE_FS is not set
CONFIG_GENERIC_ACL=y
@@ -2526,6 +2992,7 @@ CONFIG_NFS_V3=y
CONFIG_NFS_V4=y
# CONFIG_NFS_SWAP is not set
# CONFIG_NFS_V4_1 is not set
+# CONFIG_ROOT_NFS is not set
# CONFIG_NFS_USE_LEGACY_DNS is not set
CONFIG_NFS_USE_KERNEL_DNS=y
# CONFIG_NFSD is not set
@@ -2728,10 +3195,20 @@ CONFIG_KEYS=y
# CONFIG_ENCRYPTED_KEYS is not set
# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
# CONFIG_SECURITY_DMESG_RESTRICT is not set
-# CONFIG_SECURITY is not set
+CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
-CONFIG_DEFAULT_SECURITY_DAC=y
-CONFIG_DEFAULT_SECURITY=""
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+# CONFIG_SECURITY_PATH is not set
+CONFIG_SECURITY_SMACK=y
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_SECURITY_YAMA is not set
+# CONFIG_IMA is not set
+# CONFIG_EVM is not set
+CONFIG_DEFAULT_SECURITY_SMACK=y
+# CONFIG_DEFAULT_SECURITY_DAC is not set
+CONFIG_DEFAULT_SECURITY="smack"
CONFIG_CRYPTO=y
#
@@ -2739,6 +3216,7 @@ CONFIG_CRYPTO=y
#
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
@@ -2756,7 +3234,7 @@ CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
# CONFIG_CRYPTO_PCRYPT is not set
CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
-# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_AUTHENC=y
# CONFIG_CRYPTO_TEST is not set
#
@@ -2781,7 +3259,7 @@ CONFIG_CRYPTO_CBC=y
# Hash modes
#
# CONFIG_CRYPTO_CMAC is not set
-# CONFIG_CRYPTO_HMAC is not set
+CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_VMAC is not set
@@ -2792,13 +3270,13 @@ CONFIG_CRYPTO_CRC32C=y
# CONFIG_CRYPTO_CRC32 is not set
# CONFIG_CRYPTO_GHASH is not set
# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_RMD128 is not set
# CONFIG_CRYPTO_RMD160 is not set
# CONFIG_CRYPTO_RMD256 is not set
# CONFIG_CRYPTO_RMD320 is not set
-# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA1=y
# CONFIG_CRYPTO_SHA1_ARM is not set
CONFIG_CRYPTO_SHA256=y
# CONFIG_CRYPTO_SHA512 is not set
@@ -2816,7 +3294,7 @@ CONFIG_CRYPTO_AES=y
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_DES is not set
+CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_SALSA20 is not set
@@ -2828,7 +3306,7 @@ CONFIG_CRYPTO_AES=y
#
# Compression
#
-# CONFIG_CRYPTO_DEFLATE is not set
+CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
@@ -2861,9 +3339,10 @@ CONFIG_CRC32_SLICEBY8=y
# CONFIG_CRC32_SARWATE is not set
# CONFIG_CRC32_BIT is not set
# CONFIG_CRC7 is not set
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=y
# CONFIG_CRC8 is not set
CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_XZ_DEC=y
@@ -2880,6 +3359,10 @@ CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DECOMPRESS_XZ=y
CONFIG_DECOMPRESS_LZO=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=y
+CONFIG_TEXTSEARCH_BM=y
+CONFIG_TEXTSEARCH_FSM=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
CONFIG_CPU_RMAP=y
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 0b539ea1bda..9f6844cf498 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o
obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o
obj-$(CONFIG_ARCH_EXYNOS4) += sec-reboot.o
+obj-$(CONFIG_ARCH_EXYNOS4) += odroid-reboot.o
# device support
diff --git a/arch/arm/mach-exynos/odroid-reboot.c b/arch/arm/mach-exynos/odroid-reboot.c
new file mode 100644
index 00000000000..a81a5cb863a
--- /dev/null
+++ b/arch/arm/mach-exynos/odroid-reboot.c
@@ -0,0 +1,96 @@
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <asm/system.h>
+#include <mach/regs-pmu.h>
+#include <linux/gpio.h>
+#include "common.h"
+#include <linux/extcon.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+
+struct odroid_reboot_platform_data {
+ struct device *dev;
+ int power_gpio;
+};
+
+static struct odroid_reboot_platform_data *g_pdata;
+
+static void odroid_reboot(char str, const char *cmd)
+{
+ local_irq_disable();
+
+ writel(0x12345678, S5P_INFORM2); /* Don't enter lpm mode */
+ writel(0x0, S5P_INFORM4); /* Reset reboot count */
+
+ gpio_set_value(g_pdata->power_gpio, 0);
+ mdelay(150);
+ gpio_set_value(g_pdata->power_gpio, 1);
+
+ flush_cache_all();
+ outer_flush_all();
+
+ exynos4_restart(0, 0);
+
+ pr_emerg("%s: waiting for reboot\n", __func__);
+ while (1)
+ ;
+}
+
+static struct odroid_reboot_platform_data *odroid_reboot_parse_dt(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct odroid_reboot_platform_data *pdata;
+
+ pdata = devm_kzalloc(dev, sizeof(struct odroid_reboot_platform_data),
+ GFP_KERNEL);
+ if (!pdata)
+ return NULL;
+
+ pdata->power_gpio = of_get_named_gpio(np, "reset-gpio", 0);
+ if (!gpio_is_valid(pdata->power_gpio)) {
+ dev_err(dev, "invalied power-gpio\n");
+ return NULL;
+ }
+ devm_gpio_request(dev, pdata->power_gpio, "reset-gpio");
+
+ return pdata;
+}
+
+static int odroid_reboot_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+
+ if (pdev->dev.of_node)
+ g_pdata = odroid_reboot_parse_dt(dev);
+
+ if (!g_pdata) {
+ dev_err(&pdev->dev, "failed to get platform data\n");
+ return -EINVAL;
+ }
+
+ g_pdata->dev = &pdev->dev;
+
+ /* Set machine specific functions */
+ arm_pm_restart = odroid_reboot;
+
+ return 0;
+}
+
+static struct of_device_id odroid_reboot_of_match[] = {
+ { .compatible = "hardkernel,odroid-reboot", },
+ { },
+};
+
+static struct platform_driver odroid_reboot_driver = {
+ .probe = odroid_reboot_probe,
+ .driver = {
+ .name = "odroid-reboot",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(odroid_reboot_of_match),
+ }
+};
+
+module_platform_driver(odroid_reboot_driver);
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
index ec0d731b0e7..011f232f6f3 100644
--- a/arch/arm/plat-samsung/dma-ops.c
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -122,6 +122,16 @@ static inline int samsung_dmadev_flush(unsigned ch)
return dmaengine_terminate_all((struct dma_chan *)ch);
}
+static inline int samsung_dmadev_pause(unsigned ch)
+{
+ return dmaengine_pause((struct dma_chan *)ch);
+}
+
+static inline int samsung_dmadev_resume(unsigned ch)
+{
+ return dmaengine_resume((struct dma_chan *)ch);
+}
+
static struct samsung_dma_ops dmadev_ops = {
.request = samsung_dmadev_request,
.release = samsung_dmadev_release,
@@ -131,6 +141,8 @@ static struct samsung_dma_ops dmadev_ops = {
.started = NULL,
.flush = samsung_dmadev_flush,
.stop = samsung_dmadev_flush,
+ .pause = samsung_dmadev_pause,
+ .resume = samsung_dmadev_resume,
};
void *samsung_dmadev_get_ops(void)
diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h
index ce6d7634b6c..9e14fe001e2 100644
--- a/arch/arm/plat-samsung/include/plat/dma-ops.h
+++ b/arch/arm/plat-samsung/include/plat/dma-ops.h
@@ -47,6 +47,8 @@ struct samsung_dma_ops {
int (*started)(unsigned ch);
int (*flush)(unsigned ch);
int (*stop)(unsigned ch);
+ int (*pause)(unsigned ch);
+ int (*resume)(unsigned ch);
};
extern void *samsung_dmadev_get_ops(void);
diff --git a/drivers/clk/samsung/clk-exynos4-audss.c b/drivers/clk/samsung/clk-exynos4-audss.c
index 4522d000a5b..28c18d03ef9 100644
--- a/drivers/clk/samsung/clk-exynos4-audss.c
+++ b/drivers/clk/samsung/clk-exynos4-audss.c
@@ -51,22 +51,36 @@ static struct clk_onecell_data clk_data;
static void __iomem *io_base;
static struct clk *clks[AUDSS_CLK_MAX];
+#ifdef CONFIG_PM_SLEEP
+static unsigned long reg_save[][2] = {
+ { AUDSS_CLKSRC, 0 },
+ { AUDSS_CLKDIV, 0 },
+ { AUDSS_CLKGATE, 0 },
+};
+
static int samsung_audss_clk_suspend(void)
{
- /* TODO: */
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(reg_save); i++)
+ reg_save[i][1] = readl(io_base + reg_save[i][0]);
+
return 0;
}
static void samsung_audss_clk_resume(void)
{
- /* TODO: */
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(reg_save); i++)
+ writel(reg_save[i][1], io_base + reg_save[i][0]);
}
static struct syscore_ops samsung_audss_clk_syscore_ops = {
.suspend = samsung_audss_clk_suspend,
.resume = samsung_audss_clk_resume,
};
-
+#endif /* CONFIG_PM_SLEEP */
#ifdef CONFIG_OF
static struct of_device_id audss_of_match[] __initdata = {
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index a3ba9396760..e37793ededd 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1034,6 +1034,9 @@ static DEFINE_SPINLOCK(clkout_lock);
/* PLLs PMS values */
struct pll_pms pll35xx_exynos4412_pms[] = {
+ {.p = 4, .m = 300, .s = 0},
+ {.p = 3, .m = 213, .s = 0},
+ {.p = 3, .m = 200, .s = 0},
{.p = 4, .m = 250, .s = 0},
{.p = 3, .m = 175, .s = 0},
{.p = 6, .m = 325, .s = 0},
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 0ecb7c918ce..feda2e5fcdd 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -293,7 +293,7 @@ int exynos_of_parse_boost(struct exynos_dvfs_info *info,
{
struct cpufreq_frequency_table *ft = info->freq_table;
struct device_node *node = info->dev->of_node;
- unsigned int boost_freq;
+ unsigned int boost_freq, i;
if (of_property_read_u32(node, property_name, &boost_freq)) {
pr_err("%s: Property: %s not found\n", __func__,
@@ -310,10 +310,19 @@ int exynos_of_parse_boost(struct exynos_dvfs_info *info,
* frequency table is required.
*/
- ft[0].index = CPUFREQ_BOOST_FREQ;
- ft[0].frequency = boost_freq;
+ for (i = 0; ft[i].frequency != CPUFREQ_TABLE_END; i++)
+ if (ft[i].frequency != CPUFREQ_ENTRY_INVALID)
+ break;
- pr_debug("%s: BOOST frequency: %d\n", __func__, ft[0].frequency);
+ if (--i >= 0) {
+ ft[i].index = CPUFREQ_BOOST_FREQ;
+ ft[i].frequency = boost_freq;
+ } else {
+ pr_err("%s: BOOST index: %d out of range\n", __func__, i);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: BOOST frequency: %d\n", __func__, ft[i].frequency);
return 0;
}
@@ -323,8 +332,8 @@ struct cpufreq_frequency_table *exynos_of_parse_freq_table(
{
struct device_node *node = info->dev->of_node;
struct cpufreq_frequency_table *ft, *ret = NULL;
+ int len, num, i = 0, k;
struct property *pp;
- int len, num, i = 0;
u32 *of_f_tab;
if (!node)
@@ -357,29 +366,29 @@ struct cpufreq_frequency_table *exynos_of_parse_freq_table(
}
/*
- * Here + 2 is required for CPUFREQ_ENTRY_INVALID and
- * CPUFREQ_TABLE_END
+ * Here + 1 is required for CPUFREQ_TABLE_END
*
* Number of those entries must correspond to the apll_freq_4412 table
*/
- ft = kzalloc(sizeof(struct cpufreq_frequency_table) * (num + 2),
- GFP_KERNEL);
+ ft = kzalloc(sizeof(struct cpufreq_frequency_table) *
+ (info->freq_levels + 1), GFP_KERNEL);
if (!ft) {
pr_err("%s: Allocation failed\n", __func__);
goto err_of_f_tab;
}
- ft[0].index = L0;
- ft[0].frequency = CPUFREQ_ENTRY_INVALID;
+ i = info->freq_levels;
+ ft[i].index = 0;
+ ft[i].frequency = CPUFREQ_TABLE_END;
- for (i = 1; i <= num; i++) {
+ for (i--, k = num - 1; i >= 0; i--, k--) {
ft[i].index = i;
- ft[i].frequency = of_f_tab[i-1];
+ if (k < 0)
+ ft[i].frequency = CPUFREQ_ENTRY_INVALID;
+ else
+ ft[i].frequency = of_f_tab[k];
}
- ft[i].index = 0;
- ft[i].frequency = CPUFREQ_TABLE_END;
-
ret = ft;
err_of_f_tab:
diff --git a/drivers/cpufreq/exynos-cpufreq.h b/drivers/cpufreq/exynos-cpufreq.h
index cb08d2850d6..5fe15fad16f 100644
--- a/drivers/cpufreq/exynos-cpufreq.h
+++ b/drivers/cpufreq/exynos-cpufreq.h
@@ -39,6 +39,7 @@ struct exynos_dvfs_info {
unsigned int pll_safe_idx;
struct clk *cpu_clk;
unsigned int *volt_table;
+ unsigned int freq_levels;
struct cpufreq_frequency_table *freq_table;
void (*set_freq)(unsigned int, unsigned int);
bool (*need_apll_change)(unsigned int, unsigned int);
diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c b/drivers/cpufreq/exynos4x12-cpufreq.c
index e92d19be2c8..16ffbece2c5 100644
--- a/drivers/cpufreq/exynos4x12-cpufreq.c
+++ b/drivers/cpufreq/exynos4x12-cpufreq.c
@@ -27,8 +27,9 @@ static struct clk *sclk_mpll;
static struct clk *mout_apll;
static unsigned int exynos4x12_volt_table[] = {
- 1350000, 1287500, 1250000, 1187500, 1137500, 1087500, 1037500,
- 1000000, 987500, 975000, 950000, 925000, 900000, 900000
+ 1400000, 1350000, 1350000, 1300000, 1225000, 1175000,
+ 1125000, 1075000, 1037500, 1012500, 1000000, 987500,
+ 975000, 925000, 925000, 925000, 900000
};
static struct cpufreq_frequency_table exynos4x12_freq_table[] = {
@@ -83,6 +84,9 @@ static struct apll_freq apll_freq_4412[] = {
* clock divider for COPY, HPM, CORES
* PLL M, P, S
*/
+ APLL_FREQ(1800, 0, 3, 7, 0, 6, 1, 2, 0, 7, 0, 7, 300, 4, 0),
+ APLL_FREQ(1704, 0, 3, 7, 0, 6, 1, 2, 0, 7, 0, 7, 213, 3, 0),
+ APLL_FREQ(1600, 0, 3, 7, 0, 6, 1, 2, 0, 6, 0, 7, 200, 3, 0),
APLL_FREQ(1500, 0, 3, 7, 0, 6, 1, 2, 0, 6, 0, 7, 250, 4, 0),
APLL_FREQ(1400, 0, 3, 7, 0, 6, 1, 2, 0, 6, 0, 6, 175, 3, 0),
APLL_FREQ(1300, 0, 3, 7, 0, 5, 1, 2, 0, 5, 0, 6, 325, 6, 0),
@@ -186,10 +190,13 @@ int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info)
if (IS_ERR(mout_apll))
goto err_mout_apll;
- if (soc_is_exynos4212())
+ if (soc_is_exynos4212()) {
+ info->freq_levels = ARRAY_SIZE(apll_freq_4212);
apll_freq_4x12 = apll_freq_4212;
- else
+ } else {
+ info->freq_levels = ARRAY_SIZE(apll_freq_4412);
apll_freq_4x12 = apll_freq_4412;
+ }
info->mpll_freq_khz = rate;
/* 800Mhz */
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 24f8ae3f376..de1e0a1bffd 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -429,6 +429,10 @@ enum pl330_chan_op {
PL330_OP_ABORT,
/* Stop xfer and flush queue */
PL330_OP_FLUSH,
+ /* Pause xfer and halt channel */
+ PL330_OP_PAUSE,
+ /* Resume xfer and restart channel */
+ PL330_OP_RESUME,
};
struct _xfer_spec {
@@ -1235,6 +1239,49 @@ static bool _start(struct pl330_thread *thrd)
}
}
+static bool _pause(struct pl330_thread *thrd)
+{
+ void __iomem *regs = thrd->dmac->pinfo->base;
+ u8 insn[6] = {0, 0, 0, 0, 0, 0};
+
+ if (_state(thrd) == PL330_STATE_FAULT_COMPLETING)
+ UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
+
+ /* Return false if dma channel has fault */
+ if (_state(thrd) == PL330_STATE_COMPLETING ||
+ _state(thrd) == PL330_STATE_KILLING ||
+ _state(thrd) == PL330_STATE_FAULTING)
+ return false;
+
+ _emit_WFE(0, insn, thrd->ev, 1);
+
+ /* Stop generating interrupts for SEV */
+ writel(readl(regs + INTEN) & ~(1 << thrd->ev), regs + INTEN);
+
+ _execute_DBGINSN(thrd, insn, is_manager(thrd));
+
+ return true;
+}
+
+static bool _resume(struct pl330_thread *thrd)
+{
+ void __iomem *regs = thrd->dmac->pinfo->base;
+
+ if (_state(thrd) == PL330_STATE_FAULT_COMPLETING)
+ UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
+
+ /* Return false if dma channel has fault */
+ if (_state(thrd) == PL330_STATE_COMPLETING ||
+ _state(thrd) == PL330_STATE_KILLING ||
+ _state(thrd) == PL330_STATE_FAULTING)
+ return false;
+
+ /* Start generating interrupts for SEV */
+ writel(readl(regs + INTEN) | (1 << thrd->ev), regs + INTEN);
+
+ return true;
+}
+
static inline int _ldst_memtomem(unsigned dry_run, u8 buf[],
const struct _xfer_spec *pxs, int cyc)
{
@@ -1820,6 +1867,16 @@ static int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
ret = -EIO;
break;
+ case PL330_OP_PAUSE:
+ if ((active != -1) && !_pause(thrd))
+ ret = -EIO;
+ break;
+
+ case PL330_OP_RESUME:
+ if ((active != -1) && !_resume(thrd))
+ ret = -EIO;
+ break;
+
default:
ret = -EINVAL;
}
@@ -2416,6 +2473,16 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
pch->burst_len = slave_config->src_maxburst;
}
break;
+ case DMA_PAUSE:
+ spin_lock_irqsave(&pch->lock, flags);
+ pl330_chan_ctrl(pch->pl330_chid, PL330_OP_PAUSE);
+ spin_unlock_irqrestore(&pch->lock, flags);
+ break;
+ case DMA_RESUME:
+ spin_lock_irqsave(&pch->lock, flags);
+ pl330_chan_ctrl(pch->pl330_chid, PL330_OP_RESUME);
+ spin_unlock_irqrestore(&pch->lock, flags);
+ break;
default:
dev_err(pch->dmac->pif.dev, "Not supported command.\n");
return -ENXIO;
@@ -2883,7 +2950,7 @@ static int pl330_dma_device_slave_caps(struct dma_chan *dchan,
caps->src_addr_widths = PL330_DMA_BUSWIDTHS;
caps->dstn_addr_widths = PL330_DMA_BUSWIDTHS;
caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
- caps->cmd_pause = false;
+ caps->cmd_pause = true;
caps->cmd_terminate = true;
return 0;
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index f29148bcbbc..51758b83633 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -28,6 +28,7 @@
#include <linux/extcon.h>
#include <linux/regmap.h>
#include <linux/irqdomain.h>
+#include <linux/delay.h>
#define DEV_NAME "max77693-muic"
#define DELAY_MS_DEFAULT 20000 /* unit: millisecond */
@@ -600,6 +601,75 @@ static int max77693_muic_dock_button_handler(struct max77693_muic_info *info,
return 0;
}
+void max77693_otg_control(struct max77693_muic_info *info, int enable)
+{
+ static u8 chg_int_state;
+ u8 int_mask, cdetctrl1, chg_cnfg_00;
+ dev_dbg(info->dev, "%s: enable(%d)\n", __func__, enable);
+
+ if (enable) {
+ /* disable charger interrupt */
+ max77693_read_reg(info->max77693->regmap,
+ MAX77693_CHG_REG_CHG_INT_MASK, &int_mask);
+ chg_int_state = int_mask;
+ int_mask |= (1 << 4); /* disable chgin intr */
+ int_mask |= (1 << 6); /* disable chg */
+ int_mask &= ~(1 << 0); /* enable byp intr */
+ max77693_write_reg(info->max77693->regmap,
+ MAX77693_CHG_REG_CHG_INT_MASK, int_mask);
+
+ /* disable charger detection */
+ max77693_read_reg(info->max77693->regmap_muic,
+ MAX77693_MUIC_REG_CDETCTRL1, &cdetctrl1);
+ cdetctrl1 &= ~(1 << 0);
+ max77693_write_reg(info->max77693->regmap_muic,
+ MAX77693_MUIC_REG_CDETCTRL1, cdetctrl1);
+
+ /* OTG on, boost on, DIS_MUIC_CTRL=1 */
+ max77693_read_reg(info->max77693->regmap,
+ MAX77693_CHG_REG_CHG_CNFG_00, &chg_cnfg_00);
+ chg_cnfg_00 &= ~(CHG_CNFG_00_CHG_MASK
+ | CHG_CNFG_00_OTG_MASK
+ | CHG_CNFG_00_BUCK_MASK
+ | CHG_CNFG_00_BOOST_MASK
+ | CHG_CNFG_00_DIS_MUIC_CTRL_MASK);
+ chg_cnfg_00 |= (CHG_CNFG_00_OTG_MASK
+ | CHG_CNFG_00_BOOST_MASK
+ | CHG_CNFG_00_DIS_MUIC_CTRL_MASK);
+ max77693_write_reg(info->max77693->regmap,
+ MAX77693_CHG_REG_CHG_CNFG_00, chg_cnfg_00);
+ } else {
+ /* OTG off, boost off, (buck on),
+ DIS_MUIC_CTRL = 0 unless CHG_ENA = 1 */
+ max77693_read_reg(info->max77693->regmap,
+ MAX77693_CHG_REG_CHG_CNFG_00, &chg_cnfg_00);
+ chg_cnfg_00 &= ~(CHG_CNFG_00_OTG_MASK
+ | CHG_CNFG_00_BOOST_MASK
+ | CHG_CNFG_00_DIS_MUIC_CTRL_MASK);
+ chg_cnfg_00 |= CHG_CNFG_00_BUCK_MASK;
+ max77693_write_reg(info->max77693->regmap,
+ MAX77693_CHG_REG_CHG_CNFG_00, chg_cnfg_00);
+
+ msleep(50);
+
+ /* enable charger detection */
+ max77693_read_reg(info->max77693->regmap_muic,
+ MAX77693_MUIC_REG_CDETCTRL1, &cdetctrl1);
+ cdetctrl1 |= (1 << 0);
+ max77693_write_reg(info->max77693->regmap_muic,
+ MAX77693_MUIC_REG_CDETCTRL1, cdetctrl1);
+
+ /* enable charger interrupt */
+ max77693_write_reg(info->max77693->regmap,
+ MAX77693_CHG_REG_CHG_INT_MASK, chg_int_state);
+ max77693_read_reg(info->max77693->regmap,
+ MAX77693_CHG_REG_CHG_INT_MASK, &int_mask);
+ }
+
+ dev_dbg(info->dev, "%s: INT_MASK(0x%x), CDETCTRL1(0x%x), CHG_CNFG_00(0x%x)\n",
+ __func__, int_mask, cdetctrl1, chg_cnfg_00);
+}
+
static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)
{
int cable_type_gnd;
@@ -617,6 +687,7 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)
if (ret < 0)
return ret;
extcon_set_cable_state(info->edev, "USB-Host", attached);
+ max77693_otg_control(info, attached);
break;
case MAX77693_MUIC_GND_AV_CABLE_LOAD:
/* Audio Video Cable with load, PATH:AUDIO */
@@ -1250,9 +1321,6 @@ static int max77693_muic_probe(struct platform_device *pdev)
delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
}
- /* Set initial path for UART */
- max77693_muic_set_path(info, info->path_uart, true);
-
/* Check revision number of MUIC device*/
ret = max77693_read_reg(info->max77693->regmap_muic,
MAX77693_MUIC_REG_ID, &id);
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index ac10b5eedef..988309c5cc8 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -27,6 +27,7 @@ config DRM_EXYNOS_FIMD
bool "Exynos DRM FIMD"
depends on OF && DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM
select FB_MODE_HELPERS
+ select MFD_SYSCON
select VIDEOMODE_HELPERS
help
Choose this option if you want to use Exynos FIMD for DRM.
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index bc694364f19..22a8d1b8f64 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -85,8 +85,10 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
if (mode > DRM_MODE_DPMS_ON) {
/* wait for the completion of page flip. */
- wait_event(exynos_crtc->pending_flip_queue,
- atomic_read(&exynos_crtc->pending_flip) == 0);
+ if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
+ !atomic_read(&exynos_crtc->pending_flip),
+ HZ/20))
+ atomic_set(&exynos_crtc->pending_flip, 0);
drm_vblank_off(crtc->dev, exynos_crtc->pipe);
}
@@ -353,6 +355,7 @@ out_fence:
spin_lock_irq(&dev->event_lock);
drm_vblank_put(dev, exynos_crtc->pipe);
list_del(&event->base.link);
+ atomic_set(&exynos_crtc->pending_flip, 0);
spin_unlock_irq(&dev->event_lock);
mutex_unlock(&dev->struct_mutex);
@@ -611,3 +614,14 @@ void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
manager->ops->wait_for_vblank(manager);
}
}
+
+int exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
+{
+ struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+ int ret = 0;
+
+ if (manager->ops->te_handler)
+ ret = manager->ops->te_handler(manager);
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index c27b66cc5d2..eb78c16e52c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -32,4 +32,11 @@ void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos);
void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos);
void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
+/*
+ * This function calls the crtc device(manager)'s te_handler() callback
+ * to trigger to transfer video image at the tearing effect synchronization
+ * signal.
+ */
+int exynos_drm_crtc_te_handler(struct drm_crtc *crtc);
+
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index d4c7dda847c..773f8c3fdf5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -15,6 +15,8 @@
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <linux/anon_inodes.h>
+
#include <drm/exynos_drm.h>
#include "exynos_drm_drv.h"
@@ -150,6 +152,10 @@ static int exynos_drm_unload(struct drm_device *dev)
return 0;
}
+static const struct file_operations exynos_drm_gem_fops = {
+ .mmap = exynos_drm_gem_mmap_buffer,
+};
+
static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state)
{
struct drm_connector *connector;
@@ -188,6 +194,8 @@ static int exynos_drm_resume(struct drm_device *dev)
static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
{
struct drm_exynos_file_private *file_priv;
+ struct file *anon_filp;
+ int ret;
file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
if (!file_priv)
@@ -195,7 +203,29 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
file->driver_priv = file_priv;
- return exynos_drm_subdrv_open(dev, file);
+ ret = exynos_drm_subdrv_open(dev, file);
+ if (ret)
+ goto err_file_priv_free;
+
+ anon_filp = anon_inode_getfile("exynos_gem", &exynos_drm_gem_fops,
+ NULL, 0);
+ if (IS_ERR(anon_filp)) {
+ ret = PTR_ERR(anon_filp);
+ goto err_subdrv_close;
+ }
+
+ anon_filp->f_mode = FMODE_READ | FMODE_WRITE;
+ file_priv->anon_filp = anon_filp;
+
+ return ret;
+
+err_subdrv_close:
+ exynos_drm_subdrv_close(dev, file);
+
+err_file_priv_free:
+ kfree(file_priv);
+ file->driver_priv = NULL;
+ return ret;
}
static void exynos_drm_preclose(struct drm_device *dev,
@@ -207,6 +237,7 @@ static void exynos_drm_preclose(struct drm_device *dev,
static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
{
struct exynos_drm_private *private = dev->dev_private;
+ struct drm_exynos_file_private *file_priv;
struct drm_pending_vblank_event *v, *vt;
struct drm_pending_event *e, *et;
unsigned long flags;
@@ -232,6 +263,9 @@ static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
}
spin_unlock_irqrestore(&dev->event_lock, flags);
+ file_priv = file->driver_priv;
+ if (file_priv->anon_filp)
+ fput(file_priv->anon_filp);
kfree(file->driver_priv);
file->driver_priv = NULL;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index a8002cc4981..3e825229bb0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -186,6 +186,8 @@ struct exynos_drm_display {
* @win_commit: apply hardware specific overlay data to registers.
* @win_enable: enable hardware specific overlay.
* @win_disable: disable hardware specific overlay.
+ * @te_handler: trigger to transfer video image at the tearing effect
+ * synchronization signal if there is a page flip request.
*/
struct exynos_drm_manager;
struct exynos_drm_manager_ops {
@@ -207,6 +209,7 @@ struct exynos_drm_manager_ops {
void (*win_commit)(struct exynos_drm_manager *mgr, int zpos);
void (*win_enable)(struct exynos_drm_manager *mgr, int zpos);
void (*win_disable)(struct exynos_drm_manager *mgr, int zpos);
+ int (*te_handler)(struct exynos_drm_manager *mgr);
};
/*
@@ -243,6 +246,7 @@ struct exynos_drm_ipp_private {
struct drm_exynos_file_private {
struct exynos_drm_g2d_private *g2d_priv;
struct exynos_drm_ipp_private *ipp_priv;
+ struct file *anon_filp;
};
/*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 2d105ce1ee6..03efe88d29f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -17,12 +17,14 @@
#include <linux/clk.h>
#include <linux/irq.h>
+#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/regulator/consumer.h>
#include <video/mipi_display.h>
#include <video/videomode.h>
+#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
/* returns true iff both arguments logically differs */
@@ -53,9 +55,12 @@
/* FIFO memory AC characteristic register */
#define DSIM_PLLCTRL_REG 0x4c /* PLL control register */
-#define DSIM_PLLTMR_REG 0x50 /* PLL timer register */
#define DSIM_PHYACCHR_REG 0x54 /* D-PHY AC characteristic register */
#define DSIM_PHYACCHR1_REG 0x58 /* D-PHY AC characteristic register1 */
+#define DSIM_PHYCTRL_REG 0x5c
+#define DSIM_PHYTIMING_REG 0x64
+#define DSIM_PHYTIMING1_REG 0x68
+#define DSIM_PHYTIMING2_REG 0x6c
/* DSIM_STATUS */
#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
@@ -199,6 +204,24 @@
#define DSIM_PLL_M(x) ((x) << 4)
#define DSIM_PLL_S(x) ((x) << 1)
+/* DSIM_PHYCTRL */
+#define DSIM_PHYCTRL_ULPS_EXIT(x) (((x) & 0x1ff) << 0)
+
+/* DSIM_PHYTIMING */
+#define DSIM_PHYTIMING_LPX(x) ((x) << 8)
+#define DSIM_PHYTIMING_HS_EXIT(x) ((x) << 0)
+
+/* DSIM_PHYTIMING1 */
+#define DSIM_PHYTIMING1_CLK_PREPARE(x) ((x) << 24)
+#define DSIM_PHYTIMING1_CLK_ZERO(x) ((x) << 16)
+#define DSIM_PHYTIMING1_CLK_POST(x) ((x) << 8)
+#define DSIM_PHYTIMING1_CLK_TRAIL(x) ((x) << 0)
+
+/* DSIM_PHYTIMING2 */
+#define DSIM_PHYTIMING2_HS_PREPARE(x) ((x) << 16)
+#define DSIM_PHYTIMING2_HS_ZERO(x) ((x) << 8)
+#define DSIM_PHYTIMING2_HS_TRAIL(x) ((x) << 0)
+
#define DSI_MAX_BUS_WIDTH 4
#define DSI_NUM_VIRTUAL_CHANNELS 4
#define DSI_TX_FIFO_SIZE 2048
@@ -232,6 +255,12 @@ struct exynos_dsi_transfer {
#define DSIM_STATE_INITIALIZED BIT(1)
#define DSIM_STATE_CMD_LPM BIT(2)
+struct exynos_dsi_driver_data {
+ unsigned int plltmr_reg;
+
+ unsigned int has_freqband:1;
+};
+
struct exynos_dsi {
struct mipi_dsi_host dsi_host;
struct drm_connector connector;
@@ -261,11 +290,39 @@ struct exynos_dsi {
spinlock_t transfer_lock; /* protects transfer_list */
struct list_head transfer_list;
+
+ struct exynos_dsi_driver_data *driver_data;
};
#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
#define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
+static struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
+ .plltmr_reg = 0x50,
+ .has_freqband = 1,
+};
+
+static struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
+ .plltmr_reg = 0x58,
+};
+
+static struct of_device_id exynos_dsi_of_match[] = {
+ { .compatible = "samsung,exynos4210-mipi-dsi",
+ .data = &exynos4_dsi_driver_data },
+ { .compatible = "samsung,exynos5420-mipi-dsi",
+ .data = &exynos5_dsi_driver_data },
+ { }
+};
+
+static inline struct exynos_dsi_driver_data *exynos_dsi_get_driver_data(
+ struct platform_device *pdev)
+{
+ const struct of_device_id *of_id =
+ of_match_device(exynos_dsi_of_match, &pdev->dev);
+
+ return (struct exynos_dsi_driver_data *)of_id->data;
+}
+
static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi)
{
if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300)))
@@ -339,14 +396,9 @@ static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi,
static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
unsigned long freq)
{
- static const unsigned long freq_bands[] = {
- 100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ,
- 270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ,
- 510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ,
- 770 * MHZ, 870 * MHZ, 950 * MHZ,
- };
+ struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
unsigned long fin, fout;
- int timeout, band;
+ int timeout;
u8 p, s;
u16 m;
u32 reg;
@@ -367,18 +419,30 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
"failed to find PLL PMS for requested frequency\n");
return -EFAULT;
}
+ dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d)\n", fout, p, m, s);
- for (band = 0; band < ARRAY_SIZE(freq_bands); ++band)
- if (fout < freq_bands[band])
- break;
+ writel(500, dsi->reg_base + driver_data->plltmr_reg);
+
+ reg = DSIM_PLL_EN | DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s);
+
+ if (driver_data->has_freqband) {
+ static const unsigned long freq_bands[] = {
+ 100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ,
+ 270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ,
+ 510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ,
+ 770 * MHZ, 870 * MHZ, 950 * MHZ,
+ };
+ int band;
- dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d), band %d\n", fout,
- p, m, s, band);
+ for (band = 0; band < ARRAY_SIZE(freq_bands); ++band)
+ if (fout < freq_bands[band])
+ break;
- writel(500, dsi->reg_base + DSIM_PLLTMR_REG);
+ dev_dbg(dsi->dev, "band %d\n", band);
+
+ reg |= DSIM_FREQ_BAND(band);
+ }
- reg = DSIM_FREQ_BAND(band) | DSIM_PLL_EN
- | DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s);
writel(reg, dsi->reg_base + DSIM_PLLCTRL_REG);
timeout = 1000;
@@ -432,6 +496,59 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi)
return 0;
}
+static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
+{
+ struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+ u32 reg;
+
+ if (driver_data->has_freqband)
+ return;
+
+ /* B D-PHY: D-PHY Master & Slave Analog Block control */
+ reg = DSIM_PHYCTRL_ULPS_EXIT(0x0af);
+ writel(reg, dsi->reg_base + DSIM_PHYCTRL_REG);
+
+ /*
+ * T LPX: Transmitted length of any Low-Power state period
+ * T HS-EXIT: Time that the transmitter drives LP-11 following a HS
+ * burst
+ */
+ reg = DSIM_PHYTIMING_LPX(0x06) | DSIM_PHYTIMING_HS_EXIT(0x0b);
+ writel(reg, dsi->reg_base + DSIM_PHYTIMING_REG);
+
+ /*
+ * T CLK-PREPARE: Time that the transmitter drives the Clock Lane LP-00
+ * Line state immediately before the HS-0 Line state starting the
+ * HS transmission
+ * T CLK-ZERO: Time that the transmitter drives the HS-0 state prior to
+ * transmitting the Clock.
+ * T CLK_POST: Time that the transmitter continues to send HS clock
+ * after the last associated Data Lane has transitioned to LP Mode
+ * Interval is defined as the period from the end of T HS-TRAIL to
+ * the beginning of T CLK-TRAIL
+ * T CLK-TRAIL: Time that the transmitter drives the HS-0 state after
+ * the last payload clock bit of a HS transmission burst
+ */
+ reg = DSIM_PHYTIMING1_CLK_PREPARE(0x07) |
+ DSIM_PHYTIMING1_CLK_ZERO(0x27) |
+ DSIM_PHYTIMING1_CLK_POST(0x0d) |
+ DSIM_PHYTIMING1_CLK_TRAIL(0x08);
+ writel(reg, dsi->reg_base + DSIM_PHYTIMING1_REG);
+
+ /*
+ * T HS-PREPARE: Time that the transmitter drives the Data Lane LP-00
+ * Line state immediately before the HS-0 Line state starting the
+ * HS transmission
+ * T HS-ZERO: Time that the transmitter drives the HS-0 state prior to
+ * transmitting the Sync sequence.
+ * T HS-TRAIL: Time that the transmitter drives the flipped differential
+ * state after last payload data bit of a HS transmission burst
+ */
+ reg = DSIM_PHYTIMING2_HS_PREPARE(0x09) | DSIM_PHYTIMING2_HS_ZERO(0x0d) |
+ DSIM_PHYTIMING2_HS_TRAIL(0x0b);
+ writel(reg, dsi->reg_base + DSIM_PHYTIMING2_REG);
+}
+
static void exynos_dsi_disable_clock(struct exynos_dsi *dsi)
{
u32 reg;
@@ -472,8 +589,6 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
if (!(dsi->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH))
reg |= DSIM_MFLUSH_VS;
- if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
- reg |= DSIM_EOT_DISABLE;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
reg |= DSIM_SYNC_INFORM;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
@@ -490,6 +605,9 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
reg |= DSIM_HSA_MODE;
}
+ if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
+ reg |= DSIM_EOT_DISABLE;
+
switch (dsi->format) {
case MIPI_DSI_FMT_RGB888:
reg |= DSIM_MAIN_PIX_FORMAT_RGB888;
@@ -945,10 +1063,11 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id)
static int exynos_dsi_init(struct exynos_dsi *dsi)
{
- exynos_dsi_enable_clock(dsi);
exynos_dsi_reset(dsi);
enable_irq(dsi->irq);
+ exynos_dsi_enable_clock(dsi);
exynos_dsi_wait_for_reset(dsi);
+ exynos_dsi_set_phy_ctrl(dsi);
exynos_dsi_init_link(dsi);
return 0;
@@ -1031,10 +1150,22 @@ static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host,
return (ret < 0) ? ret : xfer.rx_done;
}
+static int exynos_dsi_host_te_handler(struct mipi_dsi_host *host)
+{
+ struct exynos_dsi *dsi = host_to_dsi(host);
+ struct drm_encoder *encoder = dsi->encoder;
+
+ if (!(dsi->state & DSIM_STATE_ENABLED))
+ return -EPERM;
+
+ return exynos_drm_crtc_te_handler(encoder->crtc);
+}
+
static const struct mipi_dsi_host_ops exynos_dsi_ops = {
.attach = exynos_dsi_host_attach,
.detach = exynos_dsi_host_detach,
.transfer = exynos_dsi_host_transfer,
+ .te_handler = exynos_dsi_host_te_handler,
};
static int exynos_dsi_poweron(struct exynos_dsi *dsi)
@@ -1398,6 +1529,7 @@ static int exynos_dsi_probe(struct platform_device *pdev)
dsi->dsi_host.dev = &pdev->dev;
dsi->dev = &pdev->dev;
+ dsi->driver_data = exynos_dsi_get_driver_data(pdev);
ret = exynos_dsi_parse_dt(dsi);
if (ret)
@@ -1502,11 +1634,6 @@ static const struct dev_pm_ops exynos_dsi_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(exynos_dsi_suspend, exynos_dsi_resume)
};
-static struct of_device_id exynos_dsi_of_match[] = {
- { .compatible = "samsung,exynos4210-mipi-dsi" },
- { }
-};
-
struct platform_driver dsi_driver = {
.probe = exynos_dsi_probe,
.remove = exynos_dsi_remove,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index c632757d850..2d0d94132c9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -61,6 +61,24 @@
/* color key value register for hardware window 1 ~ 4. */
#define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8))
+/* I80 / RGB trigger control register */
+#define TRIGCON 0x1A4
+#define TRGMODE_I80_RGB_ENABLE_I80 (1 << 0)
+#define SWTRGCMD_I80_RGB_ENABLE (1 << 1)
+
+/* display mode change control register except exynos4 */
+#define VIDOUT_CON 0x000
+#define VIDOUT_CON_F_I80_LDI0 (0x2 << 8)
+
+/* I80 interface control for main LDI register */
+#define I80IFCONFAx(x) (0x1B0 + (x) * 4)
+#define I80IFCONFBx(x) (0x1B8 + (x) * 4)
+#define LCD_CS_SETUP(x) ((x) << 16)
+#define LCD_WR_SETUP(x) ((x) << 12)
+#define LCD_WR_ACTIVE(x) ((x) << 8)
+#define LCD_WR_HOLD(x) ((x) << 4)
+#define I80IFEN_ENABLE (1 << 0)
+
/* FIMD has totally five hardware windows. */
#define WINDOWS_NR 5
@@ -68,12 +86,14 @@
struct fimd_driver_data {
unsigned int timing_base;
- unsigned int lcdblk_reg;
- unsigned int lcdblk_fimdbypass;
+ unsigned int lcdblk_off;
+ unsigned int lcdblk_vt_shift;
+ unsigned int lcdblk_bypass_shift;
unsigned int has_shadowcon:1;
unsigned int has_clksel:1;
unsigned int has_limited_fmt:1;
+ unsigned int has_vidoutcon:1;
};
static struct fimd_driver_data s3c64xx_fimd_driver_data = {
@@ -84,16 +104,19 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = {
static struct fimd_driver_data exynos4_fimd_driver_data = {
.timing_base = 0x0,
- .lcdblk_reg = 0x210,
- .lcdblk_fimdbypass = 1,
+ .lcdblk_off = 0x210,
+ .lcdblk_vt_shift = 10,
+ .lcdblk_bypass_shift = 1,
.has_shadowcon = 1,
};
static struct fimd_driver_data exynos5_fimd_driver_data = {
.timing_base = 0x20000,
- .lcdblk_reg = 0x210,
- .lcdblk_fimdbypass = 15,
+ .lcdblk_off = 0x214,
+ .lcdblk_vt_shift = 24,
+ .lcdblk_bypass_shift = 15,
.has_shadowcon = 1,
+ .has_vidoutcon = 1,
};
struct fimd_win_data {
@@ -118,16 +141,23 @@ struct fimd_context {
struct clk *bus_clk;
struct clk *lcd_clk;
void __iomem *regs;
- struct drm_display_mode mode;
struct regmap *sysreg;
+ struct drm_display_mode mode;
struct fimd_win_data win_data[WINDOWS_NR];
unsigned int default_win;
unsigned long irq_flags;
+ u32 vidcon0;
u32 vidcon1;
+ u32 vidout_con;
+ u32 i80ifcon;
+ bool i80_if;
bool suspended;
int pipe;
wait_queue_head_t wait_vsync_queue;
atomic_t wait_vsync_event;
+ atomic_t win_updated;
+ atomic_t triggering;
+ spinlock_t win_updated_lock;
struct exynos_drm_panel_info panel;
struct fimd_driver_data *driver_data;
@@ -248,6 +278,14 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
u32 clkdiv;
+ if (ctx->i80_if) {
+ /*
+ * The frame done interrupt should be occurred prior to the
+ * next TE signal.
+ */
+ ideal_clk *= 2;
+ }
+
/* Find the clock divider value that gets us closest to ideal_clk */
clkdiv = DIV_ROUND_UP(clk_get_rate(ctx->lcd_clk), ideal_clk);
@@ -276,12 +314,10 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
{
struct fimd_context *ctx = mgr->ctx;
struct drm_display_mode *mode = &ctx->mode;
- struct fimd_driver_data *driver_data;
+ struct fimd_driver_data *driver_data = ctx->driver_data;
+ void *timing_base = ctx->regs + driver_data->timing_base;
u32 val, clkdiv;
- int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
- int ret;
- driver_data = ctx->driver_data;
if (ctx->suspended)
return;
@@ -289,37 +325,65 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
if (mode->htotal == 0 || mode->vtotal == 0)
return;
- /* enable FIMDBYPASS bit of LCDBLK0 */
- ret = regmap_update_bits(ctx->sysreg, driver_data->lcdblk_reg,
- 0x1 << driver_data->lcdblk_fimdbypass,
- 0x1 << driver_data->lcdblk_fimdbypass);
- if (ret < 0) {
- DRM_ERROR("failed to update sysreg.\n");
- return;
- }
+ if (ctx->i80_if) {
+ val = ctx->i80ifcon | I80IFEN_ENABLE;
+ writel(val, timing_base + I80IFCONFAx(0));
- /* setup polarity values from machine code. */
- writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
+ /* disable auto frame rate */
+ writel(0, timing_base + I80IFCONFBx(0));
- /* setup vertical timing values. */
- vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
- vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
- vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
+ if (ctx->vidout_con)
+ writel(ctx->vidout_con, timing_base + VIDOUT_CON);
- val = VIDTCON0_VBPD(vbpd - 1) |
- VIDTCON0_VFPD(vfpd - 1) |
- VIDTCON0_VSPW(vsync_len - 1);
- writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
-
- /* setup horizontal timing values. */
- hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
- hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
- hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
+ /* set video type selection to I80 interface */
+ if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
+ driver_data->lcdblk_off,
+ 0x3 << driver_data->lcdblk_vt_shift,
+ 0x1 << driver_data->lcdblk_vt_shift)) {
+ DRM_ERROR("Failed to update sysreg for I80 i/f.\n");
+ return;
+ }
+ } else {
+ int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
+ u32 vidcon1;
+
+ /* setup polarity values */
+ vidcon1 = ctx->vidcon1;
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ vidcon1 |= VIDCON1_INV_VSYNC;
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ vidcon1 |= VIDCON1_INV_HSYNC;
+ writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
+
+ /* setup vertical timing values. */
+ vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+ vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
+ vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
+
+ val = VIDTCON0_VBPD(vbpd - 1) |
+ VIDTCON0_VFPD(vfpd - 1) |
+ VIDTCON0_VSPW(vsync_len - 1);
+ writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
+
+ /* setup horizontal timing values. */
+ hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+ hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
+ hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
+
+ val = VIDTCON1_HBPD(hbpd - 1) |
+ VIDTCON1_HFPD(hfpd - 1) |
+ VIDTCON1_HSPW(hsync_len - 1);
+ writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
+ }
- val = VIDTCON1_HBPD(hbpd - 1) |
- VIDTCON1_HFPD(hfpd - 1) |
- VIDTCON1_HSPW(hsync_len - 1);
- writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
+ /* set bypass selection */
+ if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
+ driver_data->lcdblk_off,
+ 0x1 << driver_data->lcdblk_bypass_shift,
+ 0x1 << driver_data->lcdblk_bypass_shift)) {
+ DRM_ERROR("Failed to update sysreg for bypass setting.\n");
+ return;
+ }
/* setup horizontal and vertical display size. */
val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
@@ -332,7 +396,8 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
* fields of register with prefix '_F' would be updated
* at vsync(same as dma start)
*/
- val = VIDCON0_ENVID | VIDCON0_ENVID_F;
+ val = ctx->vidcon0;
+ val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
if (ctx->driver_data->has_clksel)
val |= VIDCON0_CLKSEL_LCD;
@@ -657,6 +722,14 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
}
win_data->enabled = true;
+
+ if (ctx->i80_if) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&ctx->win_updated_lock, flags);
+ atomic_set(&ctx->win_updated, 1);
+ spin_unlock_irqrestore(&ctx->win_updated_lock, flags);
+ }
}
static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
@@ -846,6 +919,68 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
}
}
+static void fimd_trigger(struct device *dev)
+{
+ struct exynos_drm_manager *mgr = get_fimd_manager(dev);
+ struct fimd_context *ctx = mgr->ctx;
+ struct fimd_driver_data *driver_data = ctx->driver_data;
+ void *timing_base = ctx->regs + driver_data->timing_base;
+ u32 reg;
+
+ atomic_set(&ctx->triggering, 1);
+
+ reg = readl(ctx->regs + VIDINTCON0);
+ reg |= (VIDINTCON0_INT_ENABLE | VIDINTCON0_INT_I80IFDONE |
+ VIDINTCON0_INT_SYSMAINCON);
+ writel(reg, ctx->regs + VIDINTCON0);
+
+ reg = readl(timing_base + TRIGCON);
+ reg |= (TRGMODE_I80_RGB_ENABLE_I80 | SWTRGCMD_I80_RGB_ENABLE);
+ writel(reg, timing_base + TRIGCON);
+}
+
+static int fimd_te_handler(struct exynos_drm_manager *mgr)
+{
+ struct fimd_context *ctx = mgr->ctx;
+ unsigned long flags;
+
+ /* Checks the crtc is detached already from encoder */
+ if (ctx->pipe < 0 || !ctx->drm_dev)
+ return -EINVAL;
+
+ /*
+ * Skips to trigger if in triggering state, because multiple triggering
+ * requests can cause panel reset.
+ */
+ if (atomic_read(&ctx->triggering))
+ return 0;
+
+ spin_lock_irqsave(&ctx->win_updated_lock, flags);
+
+ /*
+ * If there is a page flip request, triggers and handles the page flip
+ * event so that current fb can be updated into panel GRAM.
+ */
+ if (atomic_read(&ctx->win_updated)) {
+ atomic_set(&ctx->win_updated, 0);
+
+ fimd_trigger(ctx->dev);
+ }
+
+ spin_unlock_irqrestore(&ctx->win_updated_lock, flags);
+
+ /* Wakes up vsync event queue */
+ if (atomic_read(&ctx->wait_vsync_event)) {
+ atomic_set(&ctx->wait_vsync_event, 0);
+ wake_up(&ctx->wait_vsync_queue);
+
+ if (!atomic_read(&ctx->triggering))
+ drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+ }
+
+ return 0;
+}
+
static struct exynos_drm_manager_ops fimd_manager_ops = {
.initialize = fimd_mgr_initialize,
.remove = fimd_mgr_remove,
@@ -859,6 +994,7 @@ static struct exynos_drm_manager_ops fimd_manager_ops = {
.win_mode_set = fimd_win_mode_set,
.win_commit = fimd_win_commit,
.win_disable = fimd_win_disable,
+ .te_handler = fimd_te_handler,
};
static struct exynos_drm_manager fimd_manager = {
@@ -869,26 +1005,40 @@ static struct exynos_drm_manager fimd_manager = {
static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
{
struct fimd_context *ctx = (struct fimd_context *)dev_id;
- u32 val;
+ u32 val, clear_bit;
val = readl(ctx->regs + VIDINTCON1);
- if (val & VIDINTCON1_INT_FRAME)
- /* VSYNC interrupt */
- writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
+ clear_bit = ctx->i80_if ? VIDINTCON1_INT_I80 : VIDINTCON1_INT_FRAME;
+ if (val & clear_bit)
+ writel(clear_bit, ctx->regs + VIDINTCON1);
/* check the crtc is detached already from encoder */
if (ctx->pipe < 0 || !ctx->drm_dev)
goto out;
- drm_handle_vblank(ctx->drm_dev, ctx->pipe);
- exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
+ if (ctx->i80_if) {
+ /* unset I80 frame done interrupt */
+ val = readl(ctx->regs + VIDINTCON0);
+ val &= ~(VIDINTCON0_INT_I80IFDONE | VIDINTCON0_INT_SYSMAINCON);
+ writel(val, ctx->regs + VIDINTCON0);
- /* set wait vsync event to zero and wake up queue. */
- if (atomic_read(&ctx->wait_vsync_event)) {
- atomic_set(&ctx->wait_vsync_event, 0);
- wake_up(&ctx->wait_vsync_queue);
+ /* exit triggering mode */
+ atomic_set(&ctx->triggering, 0);
+
+ drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+ exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
+ } else {
+ drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+ exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
+
+ /* set wait vsync event to zero and wake up queue. */
+ if (atomic_read(&ctx->wait_vsync_event)) {
+ atomic_set(&ctx->wait_vsync_event, 0);
+ wake_up(&ctx->wait_vsync_queue);
+ }
}
+
out:
return IRQ_HANDLED;
}
@@ -897,6 +1047,7 @@ static int fimd_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct fimd_context *ctx;
+ struct device_node *i80_if_timings;
struct resource *res;
int win;
int ret = -EINVAL;
@@ -910,12 +1061,49 @@ static int fimd_probe(struct platform_device *pdev)
ctx->dev = dev;
ctx->suspended = true;
+ ctx->driver_data = drm_fimd_get_driver_data(pdev);
if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
ctx->vidcon1 |= VIDCON1_INV_VDEN;
if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
ctx->vidcon1 |= VIDCON1_INV_VCLK;
+ i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings");
+ if (i80_if_timings) {
+ u32 val;
+
+ ctx->i80_if = true;
+
+ if (ctx->driver_data->has_vidoutcon)
+ ctx->vidout_con |= VIDOUT_CON_F_I80_LDI0;
+ else
+ ctx->vidcon0 |= VIDCON0_VIDOUT_I80_LDI0;
+ ctx->vidcon0 |= VIDCON0_DSI_EN;
+
+ if (of_property_read_u32(i80_if_timings, "cs-setup", &val))
+ val = 0;
+ ctx->i80ifcon = LCD_CS_SETUP(val);
+ if (of_property_read_u32(i80_if_timings, "wr-setup", &val))
+ val = 0;
+ ctx->i80ifcon |= LCD_WR_SETUP(val);
+ if (of_property_read_u32(i80_if_timings, "wr-active", &val))
+ val = 1;
+ ctx->i80ifcon |= LCD_WR_ACTIVE(val);
+ if (of_property_read_u32(i80_if_timings, "wr-hold", &val))
+ val = 0;
+ ctx->i80ifcon |= LCD_WR_HOLD(val);
+
+ spin_lock_init(&ctx->win_updated_lock);
+ }
+ of_node_put(i80_if_timings);
+
+ ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "samsung,sysreg");
+ if (IS_ERR(ctx->sysreg)) {
+ dev_warn(dev, "failed to get system register.\n");
+ ctx->sysreg = NULL;
+ }
+
ctx->bus_clk = devm_clk_get(dev, "fimd");
if (IS_ERR(ctx->bus_clk)) {
dev_err(dev, "failed to get bus clock\n");
@@ -934,7 +1122,8 @@ static int fimd_probe(struct platform_device *pdev)
if (IS_ERR(ctx->regs))
return PTR_ERR(ctx->regs);
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "vsync");
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+ ctx->i80_if ? "lcd_sys" : "vsync");
if (!res) {
dev_err(dev, "irq request failed.\n");
return -ENXIO;
@@ -952,7 +1141,6 @@ static int fimd_probe(struct platform_device *pdev)
if (IS_ERR(ctx->sysreg))
return PTR_ERR(ctx->sysreg);
- ctx->driver_data = drm_fimd_get_driver_data(pdev);
init_waitqueue_head(&ctx->wait_vsync_queue);
atomic_set(&ctx->wait_vsync_event, 0);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 55289cda85a..d88931d964d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -353,46 +353,22 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
&args->offset);
}
-static struct drm_file *exynos_drm_find_drm_file(struct drm_device *drm_dev,
- struct file *filp)
-{
- struct drm_file *file_priv;
-
- /* find current process's drm_file from filelist. */
- list_for_each_entry(file_priv, &drm_dev->filelist, lhead)
- if (file_priv->filp == filp)
- return file_priv;
-
- WARN_ON(1);
-
- return ERR_PTR(-EFAULT);
-}
-
-static int exynos_drm_gem_mmap_buffer(struct file *filp,
+int exynos_drm_gem_mmap_buffer(struct file *filp,
struct vm_area_struct *vma)
{
struct drm_gem_object *obj = filp->private_data;
struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
struct drm_device *drm_dev = obj->dev;
struct exynos_drm_gem_buf *buffer;
- struct drm_file *file_priv;
unsigned long vm_size;
int ret;
+ WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
+
vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_private_data = obj;
vma->vm_ops = drm_dev->driver->gem_vm_ops;
- /* restore it to driver's fops. */
- filp->f_op = fops_get(drm_dev->driver->fops);
-
- file_priv = exynos_drm_find_drm_file(drm_dev, filp);
- if (IS_ERR(file_priv))
- return PTR_ERR(file_priv);
-
- /* restore it to drm_file. */
- filp->private_data = file_priv;
-
update_vm_cache_attr(exynos_gem_obj, vma);
vm_size = vma->vm_end - vma->vm_start;
@@ -426,15 +402,13 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
return 0;
}
-static const struct file_operations exynos_drm_gem_fops = {
- .mmap = exynos_drm_gem_mmap_buffer,
-};
-
int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ struct drm_exynos_file_private *exynos_file_priv;
struct drm_exynos_gem_mmap *args = data;
struct drm_gem_object *obj;
+ struct file *anon_filp;
unsigned int addr;
if (!(dev->driver->driver_features & DRIVER_GEM)) {
@@ -442,47 +416,25 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
return -ENODEV;
}
+ mutex_lock(&dev->struct_mutex);
+
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (!obj) {
DRM_ERROR("failed to lookup gem object.\n");
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
- /*
- * We have to use gem object and its fops for specific mmaper,
- * but vm_mmap() can deliver only filp. So we have to change
- * filp->f_op and filp->private_data temporarily, then restore
- * again. So it is important to keep lock until restoration the
- * settings to prevent others from misuse of filp->f_op or
- * filp->private_data.
- */
- mutex_lock(&dev->struct_mutex);
-
- /*
- * Set specific mmper's fops. And it will be restored by
- * exynos_drm_gem_mmap_buffer to dev->driver->fops.
- * This is used to call specific mapper temporarily.
- */
- file_priv->filp->f_op = &exynos_drm_gem_fops;
-
- /*
- * Set gem object to private_data so that specific mmaper
- * can get the gem object. And it will be restored by
- * exynos_drm_gem_mmap_buffer to drm_file.
- */
- file_priv->filp->private_data = obj;
+ exynos_file_priv = file_priv->driver_priv;
+ anon_filp = exynos_file_priv->anon_filp;
+ anon_filp->private_data = obj;
- addr = vm_mmap(file_priv->filp, 0, args->size,
- PROT_READ | PROT_WRITE, MAP_SHARED, 0);
+ addr = vm_mmap(anon_filp, 0, args->size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, 0);
drm_gem_object_unreference(obj);
if (IS_ERR((void *)addr)) {
- /* check filp->f_op, filp->private_data are restored */
- if (file_priv->filp->f_op == &exynos_drm_gem_fops) {
- file_priv->filp->f_op = fops_get(dev->driver->fops);
- file_priv->filp->private_data = file_priv;
- }
mutex_unlock(&dev->struct_mutex);
return PTR_ERR((void *)addr);
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index 78a083302c6..d653c9cf22a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -126,6 +126,9 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+int exynos_drm_gem_mmap_buffer(struct file *filp,
+ struct vm_area_struct *vma);
+
/* map user space allocated by malloc to pages. */
int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 337e4d69a38..eabf38bc858 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1903,6 +1903,11 @@ out:
static void hdmi_dpms(struct exynos_drm_display *display, int mode)
{
+ struct hdmi_context *hdata = display->ctx;
+ struct drm_encoder *encoder = hdata->encoder;
+ struct drm_crtc *crtc = encoder->crtc;
+ struct drm_crtc_helper_funcs *funcs = NULL;
+
DRM_DEBUG_KMS("mode %d\n", mode);
switch (mode) {
@@ -1912,6 +1917,20 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode)
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
+ /*
+ * The SFRs of VP and Mixer are updated by Vertical Sync of
+ * Timing generator which is a part of HDMI so the sequence
+ * to disable TV Subsystem should be as following,
+ * VP -> Mixer -> HDMI
+ *
+ * Below codes will try to disable Mixer and VP(if used)
+ * prior to disabling HDMI.
+ */
+ if (crtc)
+ funcs = crtc->helper_private;
+ if (funcs && funcs->dpms)
+ (*funcs->dpms)(crtc, mode);
+
hdmi_poweroff(display);
break;
default:
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index cca841a1638..5c1ebbab007 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -603,7 +603,7 @@ static void vp_win_reset(struct mixer_context *ctx)
/* waiting until VP_SRESET_PROCESSING is 0 */
if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
break;
- usleep_range(10000, 12000);
+ mdelay(10);
}
WARN(tries == 0, "failed to reset Video Processor\n");
}
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 4ec874da566..a54d89b5f55 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -29,5 +29,7 @@ config DRM_PANEL_S6E8AA0
depends on OF
select DRM_MIPI_DSI
select VIDEOMODE_HELPERS
+ select BACKLIGHT_LCD_SUPPORT
+ select BACKLIGHT_CLASS_DEVICE
endmenu
diff --git a/drivers/gpu/drm/panel/panel-s6e8aa0.c b/drivers/gpu/drm/panel/panel-s6e8aa0.c
index 5782ff48f70..32b1434084c 100644
--- a/drivers/gpu/drm/panel/panel-s6e8aa0.c
+++ b/drivers/gpu/drm/panel/panel-s6e8aa0.c
@@ -19,6 +19,7 @@
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_panel.h>
+#include <linux/backlight.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
@@ -92,9 +93,12 @@ struct s6e8aa0_variant {
const s6e8aa0_gamma_table *gamma_tables;
};
+#define S6E8AA0_STATE_BIT_ENABLED 0
+
struct s6e8aa0 {
struct device *dev;
struct drm_panel panel;
+ struct backlight_device *backlight;
struct regulator_bulk_data supplies[2];
int reset_gpio;
@@ -107,6 +111,7 @@ struct s6e8aa0 {
u32 width_mm;
u32 height_mm;
+ unsigned long state;
u8 version;
u8 id;
const struct s6e8aa0_variant *variant;
@@ -891,6 +896,7 @@ static int s6e8aa0_disable(struct drm_panel *panel)
{
struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
+ clear_bit(S6E8AA0_STATE_BIT_ENABLED, &ctx->state);
s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF);
msleep(40);
@@ -914,6 +920,8 @@ static int s6e8aa0_enable(struct drm_panel *panel)
if (ret < 0)
s6e8aa0_disable(panel);
+ else
+ set_bit(S6E8AA0_STATE_BIT_ENABLED, &ctx->state);
return ret;
}
@@ -948,6 +956,49 @@ static const struct drm_panel_funcs s6e8aa0_drm_funcs = {
.get_modes = s6e8aa0_get_modes,
};
+static int s6e8aa0_get_brightness(struct backlight_device *bd)
+{
+ return bd->props.brightness;
+}
+
+static int s6e8aa0_set_brightness(struct backlight_device *bd)
+{
+ struct s6e8aa0 *ctx = bl_get_data(bd);
+
+ bd->props.power = FB_BLANK_UNBLANK;
+ if (ctx->brightness != bd->props.brightness) {
+ ctx->brightness = bd->props.brightness;
+ if (test_bit(S6E8AA0_STATE_BIT_ENABLED, &ctx->state))
+ s6e8aa0_brightness_set(ctx);
+ }
+
+ return s6e8aa0_clear_error(ctx);
+}
+
+static const struct backlight_ops s6e8aa0_backlight_ops = {
+ .get_brightness = s6e8aa0_get_brightness,
+ .update_status = s6e8aa0_set_brightness,
+};
+
+static void s6e8aa0_backlight_register(struct s6e8aa0 *ctx)
+{
+ struct backlight_properties props = {
+ .type = BACKLIGHT_RAW,
+ .brightness = ctx->brightness,
+ .max_brightness = GAMMA_LEVEL_NUM - 1
+ };
+ struct device *dev = ctx->dev;
+ struct backlight_device *bd;
+
+ bd = backlight_device_register("s6e8aa0-bl", dev, ctx,
+ &s6e8aa0_backlight_ops, &props);
+ if (IS_ERR(bd))
+ dev_err(dev, "error registering backlight device (%ld)\n",
+ PTR_ERR(bd));
+ else
+ ctx->backlight = bd;
+}
+
static int s6e8aa0_parse_dt(struct s6e8aa0 *ctx)
{
struct device *dev = ctx->dev;
@@ -1037,6 +1088,8 @@ static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
if (ret < 0)
drm_panel_remove(&ctx->panel);
+ s6e8aa0_backlight_register(ctx);
+
return ret;
}
@@ -1044,6 +1097,8 @@ static int s6e8aa0_remove(struct mipi_dsi_device *dsi)
{
struct s6e8aa0 *ctx = mipi_dsi_get_drvdata(dsi);
+ if (ctx->backlight)
+ backlight_device_unregister(ctx->backlight);
mipi_dsi_detach(dsi);
drm_panel_remove(&ctx->panel);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index df064e8cd9d..8f2bde1fbd3 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1000,6 +1000,17 @@ config SENSORS_PCF8591
source drivers/hwmon/pmbus/Kconfig
+config SENSORS_PWM_FAN
+ tristate "PWM fan"
+ depends on PWM
+ help
+ If you say yes here you get support for fans connected to PWM lines.
+ The driver uses the generic PWM interface, thus it will work on a
+ variety of SoCs.
+
+ This driver can also be built as a module. If so, the module
+ will be called pwm-fan.
+
config SENSORS_SHT15
tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
depends on GPIOLIB
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index d17d3e64f9f..fa7127e77da 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
+obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
new file mode 100644
index 00000000000..d5421c023b4
--- /dev/null
+++ b/drivers/hwmon/pwm-fan.c
@@ -0,0 +1,201 @@
+/*
+ * pwm-fan.c - Hwmon driver for fans connected to PWM lines.
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Author: Kamil Debski <k.debski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/sysfs.h>
+
+#define MAX_PWM 255
+
+struct pwm_fan_ctx {
+ struct mutex lock;
+ struct pwm_device *pwm;
+ unsigned char pwm_value;
+};
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+ unsigned long pwm, duty;
+ ssize_t ret;
+
+ if (kstrtoul(buf, 10, &pwm) || pwm > MAX_PWM)
+ return -EINVAL;
+
+ mutex_lock(&ctx->lock);
+
+ if (ctx->pwm_value == pwm)
+ goto exit_set_pwm_no_change;
+
+ if (pwm == 0) {
+ pwm_disable(ctx->pwm);
+ goto exit_set_pwm;
+ }
+
+ duty = DIV_ROUND_UP(pwm * (ctx->pwm->period - 1), MAX_PWM);
+ ret = pwm_config(ctx->pwm, duty, ctx->pwm->period);
+ if (ret)
+ goto exit_set_pwm_err;
+
+ if (ctx->pwm_value == 0) {
+ ret = pwm_enable(ctx->pwm);
+ if (ret)
+ goto exit_set_pwm_err;
+ }
+
+exit_set_pwm:
+ ctx->pwm_value = pwm;
+exit_set_pwm_no_change:
+ ret = count;
+exit_set_pwm_err:
+ mutex_unlock(&ctx->lock);
+ return ret;
+}
+
+static ssize_t show_pwm(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", ctx->pwm_value);
+}
+
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
+
+static struct attribute *pwm_fan_attributes[] = {
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group pwm_fan_group = {
+ .attrs = pwm_fan_attributes,
+};
+
+static int pwm_fan_probe(struct platform_device *pdev)
+{
+ struct device *hwmon;
+ struct pwm_fan_ctx *ctx;
+ int duty_cycle;
+ int ret;
+
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ mutex_init(&ctx->lock);
+
+ ctx->pwm = devm_of_pwm_get(&pdev->dev, pdev->dev.of_node, 0);
+ if (IS_ERR(ctx->pwm)) {
+ dev_err(&pdev->dev, "Could not get PWM\n");
+ return PTR_ERR(ctx->pwm);
+ }
+
+ dev_set_drvdata(&pdev->dev, ctx);
+ platform_set_drvdata(pdev, ctx);
+
+ /* Set duty cycle to maximum allowed */
+ duty_cycle = ctx->pwm->period - 1;
+ ctx->pwm_value = MAX_PWM;
+
+ ret = pwm_config(ctx->pwm, duty_cycle, ctx->pwm->period);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to configure PWM\n");
+ return ret;
+ }
+
+ /* Enable PWM output */
+ ret = pwm_enable(ctx->pwm);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to enable PWM\n");
+ return ret;
+ }
+
+ ret = sysfs_create_group(&pdev->dev.kobj, &pwm_fan_group);
+ if (ret)
+ return ret;
+
+ hwmon = hwmon_device_register(&pdev->dev);
+
+ if (IS_ERR(hwmon)) {
+ dev_err(&pdev->dev, "Failed to register hwmon device");
+ pwm_disable(ctx->pwm);
+ return PTR_ERR(hwmon);
+ }
+ return 0;
+}
+
+static int pwm_fan_remove(struct platform_device *pdev)
+{
+ struct pwm_fan_ctx *ctx = platform_get_drvdata(pdev);
+
+ if (ctx->pwm_value)
+ pwm_disable(ctx->pwm);
+ mutex_destroy(&ctx->lock);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pwm_fan_suspend(struct device *dev)
+{
+ struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+
+ if (ctx->pwm_value)
+ pwm_disable(ctx->pwm);
+ return 0;
+}
+
+static int pwm_fan_resume(struct device *dev)
+{
+ struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+
+ if (ctx->pwm_value)
+ return pwm_enable(ctx->pwm);
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pwm_fan_pm, pwm_fan_suspend, pwm_fan_resume);
+
+static struct of_device_id of_pwm_fan_match[] = {
+ { .compatible = "pwm-fan", },
+ {},
+};
+
+static struct platform_driver pwm_fan_driver = {
+ .probe = pwm_fan_probe,
+ .remove = pwm_fan_remove,
+ .driver = {
+ .name = "pwm-fan",
+ .pm = &pwm_fan_pm,
+ .of_match_table = of_pwm_fan_match,
+ },
+};
+
+module_platform_driver(pwm_fan_driver);
+
+MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
+MODULE_ALIAS("platform:pwm-fan");
+MODULE_DESCRIPTION("PWM FAN driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc.h b/drivers/media/platform/s5p-mfc/regs-mfc.h
index 6ccc3f8c122..882739ba895 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc.h
@@ -365,6 +365,9 @@
#define S5P_FIMV_H2R_CMD_SLEEP 5
#define S5P_FIMV_H2R_CMD_WAKEUP 6
+/* Host to RISC command options */
+#define S5P_FIMV_H2R_MPEG2_PADDING BIT(30)
+
#define S5P_FIMV_R2H_CMD_EMPTY 0
#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET 1
#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET 2
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index b1ad27b8515..0597b4d3a3f 100755
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -448,6 +448,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev,
static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
unsigned int reason, unsigned int err)
{
+ unsigned int status;
struct s5p_mfc_dev *dev;
if (ctx == NULL)
@@ -462,6 +463,10 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops, get_img_height,
dev);
+ status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
+ & S5P_FIMV_DEC_STATUS_INTERLACE_MASK;
+ ctx->interlace = status == S5P_FIMV_DEC_STATUS_INTERLACE;
+
s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx);
ctx->pb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
@@ -709,7 +714,7 @@ static int s5p_mfc_open(struct file *file)
ret = -ENOMEM;
goto err_alloc;
}
- v4l2_fh_init(&ctx->fh, video_devdata(file));
+ v4l2_fh_init(&ctx->fh, vdev);
file->private_data = &ctx->fh;
v4l2_fh_add(&ctx->fh);
ctx->dev = dev;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index ab5ba6ea297..41474aa77cd 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -559,9 +559,12 @@ struct s5p_mfc_ctx {
int img_height;
int buf_width;
int buf_height;
+ int interlace;
int luma_size;
int chroma_size;
+ int luma_size_to_report;
+ int chroma_size_to_report;
int mv_size;
unsigned long consumed_stream;
@@ -604,9 +607,6 @@ struct s5p_mfc_ctx {
struct s5p_mfc_enc_params enc_params;
size_t enc_dst_buf_size;
- size_t luma_dpb_size;
- size_t chroma_dpb_size;
- size_t me_buffer_size;
size_t tmv_buffer_size;
enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
@@ -681,4 +681,28 @@ void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
mem == V4L2_MEMORY_USERPTR || \
mem == V4L2_MEMORY_DMABUF) ? 1 : 0)
+#define INITIAL_MAPPING_VAL ERR_PTR(-EAGAIN)
+
+static inline bool mfc_is_iommu_used(struct s5p_mfc_ctx *ctx)
+{
+#ifdef CONFIG_ARM_DMA_USE_IOMMU
+ struct device *dev_iommu1 = ctx->dev->mem_dev_l;
+ struct device *dev_iommu2 = ctx->dev->mem_dev_r;
+ int iommu1_mapped, iommu2_mapped;
+
+ iommu1_mapped = dev_iommu1->archdata.mapping &&
+ dev_iommu1->archdata.mapping != INITIAL_MAPPING_VAL;
+ iommu2_mapped = dev_iommu2->archdata.mapping &&
+ dev_iommu2->archdata.mapping != INITIAL_MAPPING_VAL;
+
+ if (iommu1_mapped) {
+ /* Warn when one iommu is mapped and the second is not.
+ * This is a strange case. */
+ WARN_ON(!iommu2_mapped);
+ return true;
+ }
+#endif
+ return false;
+}
+
#endif /* S5P_MFC_COMMON_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index a428a972890..0e1830ef0f4 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -50,7 +50,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER,
&bank2_dma_addr, GFP_KERNEL);
- if (IS_ERR(dev->fw_virt_addr)) {
+ if (IS_ERR(bank2_virt)) {
mfc_err("Allocating bank2 base failed\n");
dma_free_coherent(dev->mem_dev_l, dev->fw_size,
dev->fw_virt_addr, dev->bank1);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
index 58ec7bb26eb..5d5dde07d53 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
@@ -288,30 +288,48 @@ static void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,
S5P_FIMV_DEC_BUF_ALIGN);
ctx->chroma_size = ALIGN(ctx->buf_width *
- ALIGN((ctx->img_height >> 1),
+ ALIGN((ctx->buf_height >> 1),
S5P_FIMV_NV12MT_VALIGN),
S5P_FIMV_DEC_BUF_ALIGN);
ctx->mv_size = ALIGN(ctx->buf_width *
ALIGN((ctx->buf_height >> 2),
S5P_FIMV_NV12MT_VALIGN),
S5P_FIMV_DEC_BUF_ALIGN);
+ ctx->luma_size_to_report = ctx->luma_size;
+ ctx->chroma_size_to_report = ctx->chroma_size;
} else {
guard_width =
- ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);
+ ALIGN(ctx->buf_width + 24, S5P_FIMV_NV12MT_HALIGN);
guard_height =
- ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);
+ ALIGN(ctx->buf_height + 16, S5P_FIMV_NV12MT_VALIGN);
ctx->luma_size = ALIGN(guard_width * guard_height,
S5P_FIMV_DEC_BUF_ALIGN);
guard_width =
- ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);
+ ALIGN(ctx->buf_width + 16, S5P_FIMV_NV12MT_HALIGN);
guard_height =
- ALIGN((ctx->img_height >> 1) + 4,
+ ALIGN((ctx->buf_height >> 1) + 4,
S5P_FIMV_NV12MT_VALIGN);
ctx->chroma_size = ALIGN(guard_width * guard_height,
S5P_FIMV_DEC_BUF_ALIGN);
ctx->mv_size = 0;
+
+ ctx->luma_size_to_report = ctx->luma_size;
+ ctx->chroma_size_to_report = ctx->chroma_size;
+ if (mfc_is_iommu_used(ctx)) {
+ ctx->luma_size_to_report *= 2;
+ ctx->chroma_size_to_report *= 2;
+ }
+
+ /* If interlace is deteced for MPEG2 decoding the size of the
+ * luma an chroma buffers should be doubled */
+ if (mfc_is_iommu_used(ctx) && ctx->interlace && ctx->codec_mode
+ == S5P_MFC_CODEC_MPEG2_DEC)
+ {
+ ctx->luma_size *= 2;
+ ctx->chroma_size *= 2;
+ }
}
}
@@ -496,8 +514,8 @@ static int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)
mfc_debug(2, "Not enough memory has been allocated\n");
return -ENOMEM;
}
- s5p_mfc_write_info_v5(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
- s5p_mfc_write_info_v5(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
+ s5p_mfc_write_info_v5(ctx, ctx->luma_size_to_report, ALLOC_LUMA_DPB_SIZE);
+ s5p_mfc_write_info_v5(ctx, ctx->chroma_size_to_report, ALLOC_CHROMA_DPB_SIZE);
if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC)
s5p_mfc_write_info_v5(ctx, frame_size_mv, ALLOC_MV_SIZE);
mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index 66f0d042357..11828206c52 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -80,19 +80,19 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height),
S5P_FIMV_TMV_BUFFER_ALIGN_V6);
- ctx->luma_dpb_size = ALIGN((mb_width * mb_height) *
+ ctx->luma_size = ALIGN((mb_width * mb_height) *
S5P_FIMV_LUMA_MB_TO_PIXEL_V6,
S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6);
- ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) *
+ ctx->chroma_size = ALIGN((mb_width * mb_height) *
S5P_FIMV_CHROMA_MB_TO_PIXEL_V6,
S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6);
- ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6(
+ ctx->mv_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6(
ctx->img_width, ctx->img_height,
mb_width, mb_height),
S5P_FIMV_ME_BUFFER_ALIGN_V6);
mfc_debug(2, "recon luma size: %d chroma size: %d\n",
- ctx->luma_dpb_size, ctx->chroma_dpb_size);
+ ctx->luma_size, ctx->chroma_size);
} else {
return -EINVAL;
}
@@ -161,8 +161,8 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
ctx->bank1.size =
ctx->scratch_buf_size + ctx->tmv_buffer_size +
- (ctx->pb_count * (ctx->luma_dpb_size +
- ctx->chroma_dpb_size + ctx->me_buffer_size));
+ (ctx->pb_count * (ctx->luma_size +
+ ctx->chroma_size + ctx->mv_size));
ctx->bank2.size = 0;
break;
case S5P_MFC_CODEC_MPEG4_ENC:
@@ -175,8 +175,8 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
ctx->bank1.size =
ctx->scratch_buf_size + ctx->tmv_buffer_size +
- (ctx->pb_count * (ctx->luma_dpb_size +
- ctx->chroma_dpb_size + ctx->me_buffer_size));
+ (ctx->pb_count * (ctx->luma_size +
+ ctx->chroma_size + ctx->mv_size));
ctx->bank2.size = 0;
break;
default:
@@ -492,13 +492,13 @@ static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx)
for (i = 0; i < ctx->pb_count; i++) {
WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB_V6 + (4 * i));
- buf_addr1 += ctx->luma_dpb_size;
+ buf_addr1 += ctx->luma_size;
WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB_V6 + (4 * i));
- buf_addr1 += ctx->chroma_dpb_size;
+ buf_addr1 += ctx->chroma_size;
WRITEL(buf_addr1, S5P_FIMV_E_ME_BUFFER_V6 + (4 * i));
- buf_addr1 += ctx->me_buffer_size;
- buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size +
- ctx->me_buffer_size);
+ buf_addr1 += ctx->mv_size;
+ buf_size1 -= (ctx->luma_size + ctx->chroma_size +
+ ctx->mv_size);
}
WRITEL(buf_addr1, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6);
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index 436a0c19eb1..e23ccef80e0 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -191,6 +191,9 @@ static int max77686_suspend(struct device *dev)
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
+ if (!max77686->irq)
+ return 0;
+
if (device_may_wakeup(dev))
enable_irq_wake(max77686->irq);
@@ -208,6 +211,9 @@ static int max77686_resume(struct device *dev)
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
+ if (!max77686->irq)
+ return 0;
+
if (device_may_wakeup(dev))
disable_irq_wake(max77686->irq);
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 9375b8c6410..7ce9b3fa1be 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1716,6 +1716,18 @@ static int smsc95xx_resume(struct usb_interface *intf)
return ret;
}
+static int smsc95xx_reset_resume(struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ int ret;
+
+ ret = smsc95xx_reset(dev);
+ if (ret < 0)
+ return ret;
+
+ return smsc95xx_resume(intf);
+}
+
static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
{
skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2);
@@ -2006,7 +2018,7 @@ static struct usb_driver smsc95xx_driver = {
.probe = usbnet_probe,
.suspend = smsc95xx_suspend,
.resume = smsc95xx_resume,
- .reset_resume = smsc95xx_resume,
+ .reset_resume = smsc95xx_reset_resume,
.disconnect = usbnet_disconnect,
.disable_hub_initiated_lpm = 1,
.supports_autosuspend = 1,
diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c
index 431568b5cc6..59d8dd3ff39 100644
--- a/drivers/phy/phy-exynos4x12-usb2.c
+++ b/drivers/phy/phy-exynos4x12-usb2.c
@@ -86,21 +86,23 @@
#define EXYNOS_4x12_URSTCON_OTG_HLINK BIT(1)
#define EXYNOS_4x12_URSTCON_OTG_PHYLINK BIT(2)
#define EXYNOS_4x12_URSTCON_HOST_PHY BIT(3)
+/* The following bit defines are presented in the
+ * order taken from the Exynos4412 reference manual.
+ *
+ * During experiments with the hardware and debugging
+ * it was determined that the hardware behaves contrary
+ * to the manual.
+ *
+ * The following bit values were chaned accordingly to the
+ * results of real hardware experiments.
+ */
#define EXYNOS_4x12_URSTCON_PHY1 BIT(4)
-/*
- * According to Exynos 4x12 reference manual the values for
- * EXYNOS_4x12_URSTCON_HSIC are:
- * URSTCON_HSIC0 = BIT(5)
- * URSTCON_HSIC1 = BIT(6)
- * but from experiments with real hardware the above 2 bitfields
- * seems to be swapped, so define them to match the actual
- * hardware */
-#define EXYNOS_4x12_URSTCON_HSIC1 BIT(5)
#define EXYNOS_4x12_URSTCON_HSIC0 BIT(6)
+#define EXYNOS_4x12_URSTCON_HSIC1 BIT(5)
#define EXYNOS_4x12_URSTCON_HOST_LINK_ALL BIT(7)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(8)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(10)
#define EXYNOS_4x12_URSTCON_HOST_LINK_P1 BIT(9)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P2 BIT(10)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P2 BIT(8)
/* Isolation, configured in the power management unit */
#define EXYNOS_4x12_USB_ISOL_OFFSET 0x704
@@ -196,6 +198,7 @@ static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
+ clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
}
@@ -206,42 +209,31 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
u32 phypwr = 0;
u32 rst;
u32 pwr;
- u32 mode = 0;
- u32 switch_mode = 0;
switch (inst->cfg->id) {
case EXYNOS4x12_DEVICE:
phypwr = EXYNOS_4x12_UPHYPWR_PHY0;
rstbits = EXYNOS_4x12_URSTCON_PHY0;
- mode = EXYNOS_4x12_MODE_SWITCH_DEVICE;
- switch_mode = 1;
break;
case EXYNOS4x12_HOST:
phypwr = EXYNOS_4x12_UPHYPWR_PHY1;
- rstbits = EXYNOS_4x12_URSTCON_HOST_PHY;
- mode = EXYNOS_4x12_MODE_SWITCH_HOST;
- switch_mode = 1;
+ rstbits = EXYNOS_4x12_URSTCON_HOST_PHY |
+ EXYNOS_4x12_URSTCON_PHY1 |
+ EXYNOS_4x12_URSTCON_HOST_LINK_P0;
break;
case EXYNOS4x12_HSIC0:
phypwr = EXYNOS_4x12_UPHYPWR_HSIC0;
rstbits = EXYNOS_4x12_URSTCON_HSIC0 |
- EXYNOS_4x12_URSTCON_HOST_LINK_P0 |
- EXYNOS_4x12_URSTCON_HOST_PHY;
+ EXYNOS_4x12_URSTCON_HOST_LINK_P1 ;
break;
case EXYNOS4x12_HSIC1:
phypwr = EXYNOS_4x12_UPHYPWR_HSIC1;
rstbits = EXYNOS_4x12_URSTCON_HSIC1 |
- EXYNOS_4x12_URSTCON_HOST_LINK_P1 |
- EXYNOS_4x12_URSTCON_HOST_PHY;
+ EXYNOS_4x12_URSTCON_HOST_LINK_P1;
break;
};
if (on) {
- if (switch_mode)
- regmap_update_bits(drv->reg_sys,
- EXYNOS_4x12_MODE_SWITCH_OFFSET,
- EXYNOS_4x12_MODE_SWITCH_MASK, mode);
-
pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
pwr &= ~phypwr;
writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
@@ -262,52 +254,78 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
}
}
-static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+static void exynos4x12_power_on_internal(struct samsung_usb2_phy_instance *inst)
{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- struct samsung_usb2_phy_instance *device =
- &drv->instances[EXYNOS4x12_DEVICE];
+ if (inst->int_cnt++ > 0)
+ return;
- inst->enabled++;
exynos4x12_setup_clk(inst);
- exynos4x12_phy_pwr(inst, 1);
exynos4x12_isol(inst, 0);
+ exynos4x12_phy_pwr(inst, 1);
+}
+
+static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+
+ if (inst->ext_cnt++ > 0)
+ return 0;
+
+ if (inst->cfg->id == EXYNOS4x12_HOST) {
+ regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+ EXYNOS_4x12_MODE_SWITCH_MASK,
+ EXYNOS_4x12_MODE_SWITCH_HOST);
+ exynos4x12_power_on_internal(&drv->instances[EXYNOS4x12_DEVICE]);
+ }
+
+ if (inst->cfg->id == EXYNOS4x12_DEVICE)
+ regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+ EXYNOS_4x12_MODE_SWITCH_MASK,
+ EXYNOS_4x12_MODE_SWITCH_DEVICE);
- /* Power on the device, as it is necessary for HSIC to work */
if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
- inst->cfg->id == EXYNOS4x12_HSIC1) {
- if (!device->enabled) {
- exynos4x12_phy_pwr(device, 1);
- exynos4x12_isol(device, 0);
- }
- device->enabled++;
+ inst->cfg->id == EXYNOS4x12_HSIC1) {
+ exynos4x12_power_on_internal(&drv->instances[EXYNOS4x12_DEVICE]);
+ exynos4x12_power_on_internal(&drv->instances[EXYNOS4x12_HOST]);
}
+ exynos4x12_power_on_internal(inst);
+
return 0;
}
+static void exynos4x12_power_off_internal(struct samsung_usb2_phy_instance *inst)
+{
+ if (inst->int_cnt-- > 1)
+ return;
+
+ exynos4x12_isol(inst, 1);
+ exynos4x12_phy_pwr(inst, 0);
+}
+
static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
{
struct samsung_usb2_phy_driver *drv = inst->drv;
- struct samsung_usb2_phy_instance *device =
- &drv->instances[EXYNOS4x12_DEVICE];
- inst->enabled--;
- if (inst->enabled)
+ if (inst->ext_cnt-- > 1)
return 0;
- exynos4x12_isol(inst, 1);
- exynos4x12_phy_pwr(inst, 0);
+ if (inst->cfg->id == EXYNOS4x12_DEVICE)
+ regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+ EXYNOS_4x12_MODE_SWITCH_MASK,
+ EXYNOS_4x12_MODE_SWITCH_HOST);
+
+ if (inst->cfg->id == EXYNOS4x12_HOST)
+ exynos4x12_power_off_internal(&drv->instances[EXYNOS4x12_DEVICE]);
if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
- inst->cfg->id == EXYNOS4x12_HSIC1) {
- device->enabled--;
- if (!device->enabled) {
- exynos4x12_isol(device, 1);
- exynos4x12_phy_pwr(device, 0);
- }
+ inst->cfg->id == EXYNOS4x12_HSIC1) {
+ exynos4x12_power_off_internal(&drv->instances[EXYNOS4x12_DEVICE]);
+ exynos4x12_power_off_internal(&drv->instances[EXYNOS4x12_HOST]);
}
+ exynos4x12_power_off_internal(inst);
+
return 0;
}
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
index 848744ab8f3..1cbdbf502a1 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -29,7 +29,8 @@ struct samsung_usb2_phy_instance {
const struct samsung_usb2_common_phy *cfg;
struct phy *phy;
struct samsung_usb2_phy_driver *drv;
- int enabled;
+ int int_cnt;
+ int ext_cnt;
};
struct samsung_usb2_phy_driver {
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 1053eb651b2..31f7ebf5586 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -154,6 +154,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* INTEL VALUE SSD */
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* USB3503 */
+ { USB_DEVICE(0x0424, 0x3503), .driver_info = USB_QUIRK_RESET_RESUME },
+
{ } /* terminating entry must be last */
};
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index ffc41e4bf65..20b372b5909 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -134,8 +134,8 @@ struct ffs_ep {
struct usb_ep *ep; /* P: ffs->eps_lock */
struct usb_request *req; /* P: epfile->mutex */
- /* [0]: full speed, [1]: high speed */
- struct usb_endpoint_descriptor *descs[2];
+ /* [0]: full speed, [1]: high speed, [2]: super speed */
+ struct usb_endpoint_descriptor *descs[3];
u8 num;
@@ -745,6 +745,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
*/
struct usb_gadget *gadget = epfile->ffs->gadget;
+ spin_lock_irq(&epfile->ffs->eps_lock);
+ /* In the meantime, endpoint got disabled or changed. */
+ if (epfile->ep != ep) {
+ spin_unlock_irq(&epfile->ffs->eps_lock);
+ return -ESHUTDOWN;
+ }
/*
* Controller may require buffer size to be aligned to
* maxpacketsize of an out endpoint.
@@ -752,6 +758,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
data_len = io_data->read ?
usb_ep_align_maybe(gadget, ep->ep, io_data->len) :
io_data->len;
+ spin_unlock_irq(&epfile->ffs->eps_lock);
data = kmalloc(data_len, GFP_KERNEL);
if (unlikely(!data))
@@ -802,7 +809,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
if (io_data->aio) {
req = usb_ep_alloc_request(ep->ep, GFP_KERNEL);
if (unlikely(!req))
- goto error;
+ goto error_lock;
req->buf = data;
req->length = io_data->len;
@@ -817,7 +824,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
if (unlikely(ret)) {
usb_ep_free_request(ep->ep, req);
- goto error;
+ goto error_lock;
}
ret = -EIOCBQUEUED;
@@ -843,19 +850,21 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
ret = -EINTR;
usb_ep_dequeue(ep->ep, req);
} else {
- /*
- * XXX We may end up silently droping data here.
- * Since data_len (i.e. req->length) may be bigger
- * than len (after being rounded up to maxpacketsize),
- * we may end up with more data then user space has
- * space for.
- */
- ret = ep->status;
- if (io_data->read && ret > 0 &&
- unlikely(copy_to_user(io_data->buf, data,
- min_t(size_t, ret,
- io_data->len))))
- ret = -EFAULT;
+ /*
+ * XXX We may end up silently droping data
+ * here. Since data_len (i.e. req->length) may
+ * be bigger than len (after being rounded up
+ * to maxpacketsize), we may end up with more
+ * data then user space has space for.
+ */
+ ret = ep->status;
+ if (io_data->read && ret > 0) {
+ ret = min_t(size_t, ret, io_data->len);
+
+ if (unlikely(copy_to_user(io_data->buf,
+ data, ret)))
+ ret = -EFAULT;
+ }
}
kfree(data);
}
@@ -863,6 +872,10 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
mutex_unlock(&epfile->mutex);
return ret;
+
+error_lock:
+ spin_unlock_irq(&epfile->ffs->eps_lock);
+ mutex_unlock(&epfile->mutex);
error:
kfree(data);
return ret;
@@ -915,7 +928,7 @@ ffs_epfile_open(struct inode *inode, struct file *file)
return 0;
}
-static int ffs_aio_cancel(struct kiocb *kiocb)
+static int ffs_aio_cancel(struct kiocb *kiocb, struct io_event *e)
{
struct ffs_io_data *io_data = kiocb->private;
struct ffs_epfile *epfile = kiocb->ki_filp->private_data;
@@ -1439,7 +1452,7 @@ static void ffs_data_clear(struct ffs_data *ffs)
if (ffs->epfiles)
ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count);
- kfree(ffs->raw_descs);
+ kfree(ffs->raw_descs_data);
kfree(ffs->raw_strings);
kfree(ffs->stringtabs);
}
@@ -1451,14 +1464,15 @@ static void ffs_data_reset(struct ffs_data *ffs)
ffs_data_clear(ffs);
ffs->epfiles = NULL;
+ ffs->raw_descs_data = NULL;
ffs->raw_descs = NULL;
ffs->raw_strings = NULL;
ffs->stringtabs = NULL;
ffs->raw_descs_length = 0;
- ffs->raw_fs_descs_length = 0;
ffs->fs_descs_count = 0;
ffs->hs_descs_count = 0;
+ ffs->ss_descs_count = 0;
ffs->strings_count = 0;
ffs->interfaces_count = 0;
@@ -1601,7 +1615,24 @@ static int ffs_func_eps_enable(struct ffs_function *func)
spin_lock_irqsave(&func->ffs->eps_lock, flags);
do {
struct usb_endpoint_descriptor *ds;
- ds = ep->descs[ep->descs[1] ? 1 : 0];
+ int desc_idx;
+
+ if (ffs->gadget->speed == USB_SPEED_SUPER)
+ desc_idx = 2;
+ else if (ffs->gadget->speed == USB_SPEED_HIGH)
+ desc_idx = 1;
+ else
+ desc_idx = 0;
+
+ /* fall-back to lower speed if desc missing for current speed */
+ do {
+ ds = ep->descs[desc_idx];
+ } while (!ds && --desc_idx >= 0);
+
+ if (!ds) {
+ ret = -EINVAL;
+ break;
+ }
ep->ep->driver_data = ep;
ep->ep->desc = ds;
@@ -1736,6 +1767,12 @@ static int __must_check ffs_do_desc(char *data, unsigned len,
}
break;
+ case USB_DT_SS_ENDPOINT_COMP:
+ pr_vdebug("EP SS companion descriptor\n");
+ if (length != sizeof(struct usb_ss_ep_comp_descriptor))
+ goto inv_length;
+ break;
+
case USB_DT_OTHER_SPEED_CONFIG:
case USB_DT_INTERFACE_POWER:
case USB_DT_DEBUG:
@@ -1846,60 +1883,76 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
static int __ffs_data_got_descs(struct ffs_data *ffs,
char *const _data, size_t len)
{
- unsigned fs_count, hs_count;
- int fs_len, ret = -EINVAL;
- char *data = _data;
+ char *data = _data, *raw_descs;
+ unsigned counts[3], flags;
+ int ret = -EINVAL, i;
ENTER();
- if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_DESCRIPTORS_MAGIC ||
- get_unaligned_le32(data + 4) != len))
+ if (get_unaligned_le32(data + 4) != len)
goto error;
- fs_count = get_unaligned_le32(data + 8);
- hs_count = get_unaligned_le32(data + 12);
- if (!fs_count && !hs_count)
- goto einval;
-
- data += 16;
- len -= 16;
-
- if (likely(fs_count)) {
- fs_len = ffs_do_descs(fs_count, data, len,
- __ffs_data_do_entity, ffs);
- if (unlikely(fs_len < 0)) {
- ret = fs_len;
+ switch (get_unaligned_le32(data)) {
+ case FUNCTIONFS_DESCRIPTORS_MAGIC:
+ flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC;
+ data += 8;
+ len -= 8;
+ break;
+ case FUNCTIONFS_DESCRIPTORS_MAGIC_V2:
+ flags = get_unaligned_le32(data + 8);
+ if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
+ FUNCTIONFS_HAS_HS_DESC |
+ FUNCTIONFS_HAS_SS_DESC)) {
+ ret = -ENOSYS;
goto error;
}
+ data += 12;
+ len -= 12;
+ break;
+ default:
+ goto error;
+ }
- data += fs_len;
- len -= fs_len;
- } else {
- fs_len = 0;
+ /* Read fs_count, hs_count and ss_count (if present) */
+ for (i = 0; i < 3; ++i) {
+ if (!(flags & (1 << i))) {
+ counts[i] = 0;
+ } else if (len < 4) {
+ goto error;
+ } else {
+ counts[i] = get_unaligned_le32(data);
+ data += 4;
+ len -= 4;
+ }
}
- if (likely(hs_count)) {
- ret = ffs_do_descs(hs_count, data, len,
+ /* Read descriptors */
+ raw_descs = data;
+ for (i = 0; i < 3; ++i) {
+ if (!counts[i])
+ continue;
+ ret = ffs_do_descs(counts[i], data, len,
__ffs_data_do_entity, ffs);
- if (unlikely(ret < 0))
+ if (ret < 0)
goto error;
- } else {
- ret = 0;
+ data += ret;
+ len -= ret;
}
- if (unlikely(len != ret))
- goto einval;
+ if (raw_descs == data || len) {
+ ret = -EINVAL;
+ goto error;
+ }
- ffs->raw_fs_descs_length = fs_len;
- ffs->raw_descs_length = fs_len + ret;
- ffs->raw_descs = _data;
- ffs->fs_descs_count = fs_count;
- ffs->hs_descs_count = hs_count;
+ ffs->raw_descs_data = _data;
+ ffs->raw_descs = raw_descs;
+ ffs->raw_descs_length = data - raw_descs;
+ ffs->fs_descs_count = counts[0];
+ ffs->hs_descs_count = counts[1];
+ ffs->ss_descs_count = counts[2];
return 0;
-einval:
- ret = -EINVAL;
error:
kfree(_data);
return ret;
@@ -2117,21 +2170,28 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
struct usb_endpoint_descriptor *ds = (void *)desc;
struct ffs_function *func = priv;
struct ffs_ep *ffs_ep;
-
- /*
- * If hs_descriptors is not NULL then we are reading hs
- * descriptors now
- */
- const int isHS = func->function.hs_descriptors != NULL;
- unsigned idx;
+ unsigned ep_desc_id, idx;
+ static const char *speed_names[] = { "full", "high", "super" };
if (type != FFS_DESCRIPTOR)
return 0;
- if (isHS)
+ /*
+ * If ss_descriptors is not NULL, we are reading super speed
+ * descriptors; if hs_descriptors is not NULL, we are reading high
+ * speed descriptors; otherwise, we are reading full speed
+ * descriptors.
+ */
+ if (func->function.ss_descriptors) {
+ ep_desc_id = 2;
+ func->function.ss_descriptors[(long)valuep] = desc;
+ } else if (func->function.hs_descriptors) {
+ ep_desc_id = 1;
func->function.hs_descriptors[(long)valuep] = desc;
- else
+ } else {
+ ep_desc_id = 0;
func->function.fs_descriptors[(long)valuep] = desc;
+ }
if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
return 0;
@@ -2139,13 +2199,13 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
idx = (ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) - 1;
ffs_ep = func->eps + idx;
- if (unlikely(ffs_ep->descs[isHS])) {
- pr_vdebug("two %sspeed descriptors for EP %d\n",
- isHS ? "high" : "full",
+ if (unlikely(ffs_ep->descs[ep_desc_id])) {
+ pr_err("two %sspeed descriptors for EP %d\n",
+ speed_names[ep_desc_id],
ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
return -EINVAL;
}
- ffs_ep->descs[isHS] = ds;
+ ffs_ep->descs[ep_desc_id] = ds;
ffs_dump_mem(": Original ep desc", ds, ds->bLength);
if (ffs_ep->ep) {
@@ -2289,8 +2349,10 @@ static int _ffs_func_bind(struct usb_configuration *c,
const int full = !!func->ffs->fs_descs_count;
const int high = gadget_is_dualspeed(func->gadget) &&
func->ffs->hs_descs_count;
+ const int super = gadget_is_superspeed(func->gadget) &&
+ func->ffs->ss_descs_count;
- int ret;
+ int fs_len, hs_len, ret;
/* Make it a single chunk, less management later on */
vla_group(d);
@@ -2299,15 +2361,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
full ? ffs->fs_descs_count + 1 : 0);
vla_item_with_sz(d, struct usb_descriptor_header *, hs_descs,
high ? ffs->hs_descs_count + 1 : 0);
+ vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs,
+ super ? ffs->ss_descs_count + 1 : 0);
vla_item_with_sz(d, short, inums, ffs->interfaces_count);
- vla_item_with_sz(d, char, raw_descs,
- high ? ffs->raw_descs_length : ffs->raw_fs_descs_length);
+ vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length);
char *vlabuf;
ENTER();
- /* Only high speed but not supported by gadget? */
- if (unlikely(!(full | high)))
+ /* Has descriptors only for speeds gadget does not support */
+ if (unlikely(!(full | high | super)))
return -ENOTSUPP;
/* Allocate a single chunk, less management later on */
@@ -2317,8 +2380,10 @@ static int _ffs_func_bind(struct usb_configuration *c,
/* Zero */
memset(vla_ptr(vlabuf, d, eps), 0, d_eps__sz);
- memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs + 16,
- d_raw_descs__sz);
+ /* Copy descriptors */
+ memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs,
+ ffs->raw_descs_length);
+
memset(vla_ptr(vlabuf, d, inums), 0xff, d_inums__sz);
for (ret = ffs->eps_count; ret; --ret) {
struct ffs_ep *ptr;
@@ -2340,22 +2405,38 @@ static int _ffs_func_bind(struct usb_configuration *c,
*/
if (likely(full)) {
func->function.fs_descriptors = vla_ptr(vlabuf, d, fs_descs);
- ret = ffs_do_descs(ffs->fs_descs_count,
- vla_ptr(vlabuf, d, raw_descs),
- d_raw_descs__sz,
- __ffs_func_bind_do_descs, func);
- if (unlikely(ret < 0))
+ fs_len = ffs_do_descs(ffs->fs_descs_count,
+ vla_ptr(vlabuf, d, raw_descs),
+ d_raw_descs__sz,
+ __ffs_func_bind_do_descs, func);
+ if (unlikely(fs_len < 0)) {
+ ret = fs_len;
goto error;
+ }
} else {
- ret = 0;
+ fs_len = 0;
}
if (likely(high)) {
func->function.hs_descriptors = vla_ptr(vlabuf, d, hs_descs);
- ret = ffs_do_descs(ffs->hs_descs_count,
- vla_ptr(vlabuf, d, raw_descs) + ret,
- d_raw_descs__sz - ret,
- __ffs_func_bind_do_descs, func);
+ hs_len = ffs_do_descs(ffs->hs_descs_count,
+ vla_ptr(vlabuf, d, raw_descs) + fs_len,
+ d_raw_descs__sz - fs_len,
+ __ffs_func_bind_do_descs, func);
+ if (unlikely(hs_len < 0)) {
+ ret = hs_len;
+ goto error;
+ }
+ } else {
+ hs_len = 0;
+ }
+
+ if (likely(super)) {
+ func->function.ss_descriptors = vla_ptr(vlabuf, d, ss_descs);
+ ret = ffs_do_descs(ffs->ss_descs_count,
+ vla_ptr(vlabuf, d, raw_descs) + fs_len + hs_len,
+ d_raw_descs__sz - fs_len - hs_len,
+ __ffs_func_bind_do_descs, func);
if (unlikely(ret < 0))
goto error;
}
@@ -2366,7 +2447,8 @@ static int _ffs_func_bind(struct usb_configuration *c,
* now.
*/
ret = ffs_do_descs(ffs->fs_descs_count +
- (high ? ffs->hs_descs_count : 0),
+ (high ? ffs->hs_descs_count : 0) +
+ (super ? ffs->ss_descs_count : 0),
vla_ptr(vlabuf, d, raw_descs), d_raw_descs__sz,
__ffs_func_bind_do_nums, func);
if (unlikely(ret < 0))
@@ -2713,6 +2795,7 @@ static void ffs_func_unbind(struct usb_configuration *c,
*/
func->function.fs_descriptors = NULL;
func->function.hs_descriptors = NULL;
+ func->function.ss_descriptors = NULL;
func->interfaces_nums = NULL;
ffs_event_add(ffs, FUNCTIONFS_UNBIND);
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 6e4aefe1c0c..2cd3fc394d0 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -383,6 +383,7 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
dev_err(hsotg->dev,
"%s: timeout flushing fifos (GRSTCTL=%08x)\n",
__func__, val);
+ break;
}
udelay(1);
@@ -1791,6 +1792,7 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx)
dev_err(hsotg->dev,
"%s: timeout flushing fifo (GRSTCTL=%08x)\n",
__func__, val);
+ break;
}
udelay(1);
@@ -3548,13 +3550,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
hsotg->irq = ret;
- ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0,
- dev_name(dev), hsotg);
- if (ret < 0) {
- dev_err(dev, "cannot claim IRQ\n");
- goto err_clk;
- }
-
dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
hsotg->gadget.max_speed = USB_SPEED_HIGH;
@@ -3594,6 +3589,17 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
s3c_hsotg_init(hsotg);
s3c_hsotg_hw_cfg(hsotg);
+ ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0,
+ dev_name(dev), hsotg);
+ if (ret < 0) {
+ s3c_hsotg_phy_disable(hsotg);
+ clk_disable_unprepare(hsotg->clk);
+ regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
+ hsotg->supplies);
+ dev_err(dev, "cannot claim IRQ\n");
+ goto err_clk;
+ }
+
/* hsotg->num_of_eps holds number of EPs other than ep0 */
if (hsotg->num_of_eps == 0) {
diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/u_fs.h
index c39e805025b..bf0ba375d45 100644
--- a/drivers/usb/gadget/u_fs.h
+++ b/drivers/usb/gadget/u_fs.h
@@ -206,16 +206,16 @@ struct ffs_data {
/* filled by __ffs_data_got_descs() */
/*
- * Real descriptors are 16 bytes after raw_descs (so you need
- * to skip 16 bytes (ie. ffs->raw_descs + 16) to get to the
- * first full speed descriptor). raw_descs_length and
- * raw_fs_descs_length do not have those 16 bytes added.
+ * raw_descs is what you kfree, real_descs points inside of raw_descs,
+ * where full speed, high speed and super speed descriptors start.
+ * real_descs_length is the length of all those descriptors.
*/
+ const void *raw_descs_data;
const void *raw_descs;
unsigned raw_descs_length;
- unsigned raw_fs_descs_length;
unsigned fs_descs_count;
unsigned hs_descs_count;
+ unsigned ss_descs_count;
unsigned short strings_count;
unsigned short interfaces_count;
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index bdd7336a6b4..e7ab8c98714 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -376,6 +376,8 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
udc->gadget->dev.driver = &driver->driver;
node = udc->gadget->dev.of_node;
+
+ edev = 0;
/* Check if we have an extcon associated with the UDC driver */
if (node && of_property_read_bool(node, "extcon")) {
edev = extcon_get_edev_by_phandle(&udc->gadget->dev, 0);
@@ -402,20 +404,25 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
ret = driver->bind(udc->gadget, driver);
if (ret)
goto err2;
- ret = usb_gadget_udc_start(udc->gadget, driver);
- if (ret) {
- driver->unbind(udc->gadget);
- goto err2;
- }
-
- usb_gadget_connect(udc->gadget);
if (udc->extcon_usb_dev.edev) {
- udc->enabled = 1;
+ udc->enabled = 0;
udc->cable_state = extcon_get_cable_state_(
udc->extcon_usb_dev.edev,
udc->extcon_usb_dev.cable_index);
- queue_work(udc->pwr_workqueue, &udc->pwr_work);
+ } else {
+ udc->cable_state = 1;
+ }
+
+ if (udc->cable_state) {
+ ret = usb_gadget_udc_start(udc->gadget, driver);
+ if (ret) {
+ driver->unbind(udc->gadget);
+ goto err2;
+ }
+
+ usb_gadget_connect(udc->gadget);
+ udc->enabled = 1;
}
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index cd1282443c8..8b14ac5d786 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -424,7 +424,7 @@ static int s5p_ehci_resume(struct device *dev)
/* DMA burst Enable */
writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
- ehci_resume(hcd, false);
+ ehci_resume(hcd, true);
return 0;
}
#else
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index b0b542c14e3..da063718290 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -15,9 +15,12 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/platform_data/usb-ohci-exynos.h>
+#include <linux/phy/phy.h>
#include <linux/usb/phy.h>
#include <linux/usb/samsung_usb_phy.h>
+#define PHY_NUMBER 3
+
struct exynos_ohci_hcd {
struct device *dev;
struct usb_hcd *hcd;
@@ -25,26 +28,106 @@ struct exynos_ohci_hcd {
struct usb_phy *phy;
struct usb_otg *otg;
struct exynos4_ohci_platdata *pdata;
+ struct phy *phy_g[PHY_NUMBER];
};
-static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)
+static int exynos_ohci_get_phy(struct device *dev,
+ struct exynos_ohci_hcd *exynos_ohci)
+{
+ struct device_node *child;
+ struct phy *phy;
+ int phy_number;
+ int ret = 0;
+
+ exynos_ohci->phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ if (IS_ERR(exynos_ohci->phy)) {
+ ret = PTR_ERR(exynos_ohci->phy);
+ if (ret != -ENXIO && ret != -ENODEV) {
+ dev_err(dev, "no usb2 phy configured\n");
+ return ret;
+ }
+ dev_dbg(dev, "Failed to get usb2 phy\n");
+ } else {
+ exynos_ohci->otg = exynos_ohci->phy->otg;
+ }
+
+ /*
+ * Getting generic phy:
+ * We are keeping both types of phys as a part of transiting OHCI
+ * to generic phy framework, so as to maintain backward compatibilty
+ * with old DTB.
+ * If there are existing devices using DTB files built from them,
+ * to remove the support for old bindings in this driver,
+ * we need to make sure that such devices have their DTBs
+ * updated to ones built from new DTS.
+ */
+ for_each_available_child_of_node(dev->of_node, child) {
+ ret = of_property_read_u32(child, "reg", &phy_number);
+ if (ret) {
+ dev_err(dev, "Failed to parse device tree\n");
+ of_node_put(child);
+ return ret;
+ }
+
+ if (phy_number >= PHY_NUMBER) {
+ dev_err(dev, "Invalid number of PHYs\n");
+ of_node_put(child);
+ return -EINVAL;
+ }
+
+ phy = devm_of_phy_get(dev, child, 0);
+ of_node_put(child);
+ if (IS_ERR(phy)) {
+ ret = PTR_ERR(phy);
+ if (ret != -ENOSYS && ret != -ENODEV) {
+ dev_err(dev, "no usb2 phy configured\n");
+ return ret;
+ }
+ dev_dbg(dev, "Failed to get usb2 phy\n");
+ }
+ exynos_ohci->phy_g[phy_number] = phy;
+ }
+
+ return ret;
+}
+
+static int exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)
{
struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+ int i;
+ int ret = 0;
- if (exynos_ohci->phy)
- usb_phy_init(exynos_ohci->phy);
+ if (!IS_ERR(exynos_ohci->phy))
+ return usb_phy_init(exynos_ohci->phy);
else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_init)
exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
+ else {
+ for (i = 0; ret == 0 && i < PHY_NUMBER; i++)
+ if (!IS_ERR(exynos_ohci->phy_g[i]))
+ ret = phy_power_on(exynos_ohci->phy_g[i]);
+ if (ret)
+ for (i--; i >= 0; i--)
+ if (!IS_ERR(exynos_ohci->phy_g[i]))
+ phy_power_off(exynos_ohci->phy_g[i]);
+ }
+
+ return ret;
}
static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci)
{
struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+ int i;
- if (exynos_ohci->phy)
+ if (!IS_ERR(exynos_ohci->phy))
usb_phy_shutdown(exynos_ohci->phy);
else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_exit)
exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
+ else {
+ for (i = 0; i < PHY_NUMBER; i++)
+ if (!IS_ERR(exynos_ohci->phy_g[i]))
+ phy_power_off(exynos_ohci->phy_g[i]);
+ }
}
static int ohci_exynos_reset(struct usb_hcd *hcd)
@@ -105,7 +188,6 @@ static int exynos_ohci_probe(struct platform_device *pdev)
struct usb_hcd *hcd;
struct ohci_hcd *ohci;
struct resource *res;
- struct usb_phy *phy;
int irq;
int err;
@@ -128,8 +210,8 @@ static int exynos_ohci_probe(struct platform_device *pdev)
"samsung,exynos5440-ohci"))
goto skip_phy;
- phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
- if (IS_ERR(phy)) {
+ err = exynos_ohci_get_phy(&pdev->dev, exynos_ohci);
+ if (err) {
/* Fallback to pdata */
if (!pdata) {
dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
@@ -137,9 +219,6 @@ static int exynos_ohci_probe(struct platform_device *pdev)
} else {
exynos_ohci->pdata = pdata;
}
- } else {
- exynos_ohci->phy = phy;
- exynos_ohci->otg = phy->otg;
}
skip_phy:
@@ -193,10 +272,15 @@ skip_phy:
exynos_ohci->otg->set_host(exynos_ohci->otg,
&exynos_ohci->hcd->self);
- exynos_ohci_phy_enable(exynos_ohci);
+ platform_set_drvdata(pdev, hcd);
ohci = hcd_to_ohci(hcd);
ohci_hcd_init(ohci);
+ err = exynos_ohci_phy_enable(exynos_ohci);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to enable USB phy\n");
+ goto fail_io;
+ }
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err) {
@@ -288,6 +372,7 @@ static int exynos_ohci_resume(struct device *dev)
{
struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev);
struct usb_hcd *hcd = exynos_ohci->hcd;
+ int ret;
clk_prepare_enable(exynos_ohci->clk);
@@ -295,7 +380,12 @@ static int exynos_ohci_resume(struct device *dev)
exynos_ohci->otg->set_host(exynos_ohci->otg,
&exynos_ohci->hcd->self);
- exynos_ohci_phy_enable(exynos_ohci);
+ ret = exynos_ohci_phy_enable(exynos_ohci);
+ if (ret) {
+ dev_err(dev, "Failed to enable USB phy\n");
+ clk_disable_unprepare(exynos_ohci->clk);
+ return ret;
+ }
ohci_resume(hcd, false);
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index 52cb7549b77..47cb143716a 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -149,8 +149,6 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode)
case USB3503_MODE_STANDBY:
usb3503_reset(hub, 0);
-
- hub->mode = mode;
dev_info(dev, "switched to STANDBY mode\n");
break;
@@ -187,25 +185,57 @@ static int usb3503_probe(struct usb3503 *hub)
hub->gpio_reset = pdata->gpio_reset;
hub->mode = pdata->initial_mode;
} else if (np) {
+ struct clk *clk;
hub->port_off_mask = 0;
- hub->clk = devm_clk_get(dev, "refclk");
- if (!IS_ERR(hub->clk)) {
- unsigned long rate;
+ clk = devm_clk_get(dev, "refclk");
+ if (IS_ERR(clk) && PTR_ERR(clk) != -ENOENT) {
+ dev_err(dev, "unable to request refclk (%ld)\n",
+ PTR_ERR(clk));
+ return PTR_ERR(clk);
+ }
- clk_prepare_enable(hub->clk);
- rate = clk_get_rate(hub->clk);
+ if (!IS_ERR(clk)) {
+ u32 rate = 0;
+ hub->clk = clk;
+
+ if (!of_property_read_u32(np, "refclk-frequency",
+ &rate)) {
+
+ switch (rate) {
+ case 38400000:
+ case 26000000:
+ case 19200000:
+ case 12000000:
+ hub->secondary_ref_clk = 0;
+ break;
+ case 24000000:
+ case 27000000:
+ case 25000000:
+ case 50000000:
+ hub->secondary_ref_clk = 1;
+ break;
+ default:
+ dev_err(dev,
+ "unsupported reference clock rate (%d)\n",
+ (int) rate);
+ return -EINVAL;
+ }
+ err = clk_set_rate(hub->clk, rate);
+ if (err) {
+ dev_err(dev,
+ "unable to set reference clock rate to %d\n",
+ (int) rate);
+ return err;
+ }
+ }
- if (rate == 38400000 || rate == 26000000 ||
- rate == 19200000 || rate == 12000000)
- hub->secondary_ref_clk = 0;
- else if (rate == 24000000 || rate == 27000000 ||
- rate == 25000000 || rate == 50000000)
- hub->secondary_ref_clk = 1;
- else
+ err = clk_prepare_enable(hub->clk);
+ if (err) {
dev_err(dev,
- "unsupported reference clock rate (%d)\n",
- rate);
+ "unable to enable reference clock\n");
+ return err;
+ }
}
property = of_get_property(np, "disabled-ports", &len);
@@ -315,6 +345,37 @@ static int usb3503_platform_probe(struct platform_device *pdev)
return usb3503_probe(hub);
}
+#ifdef CONFIG_PM_SLEEP
+static int usb3503_i2c_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct usb3503 *hub = i2c_get_clientdata(client);
+
+ usb3503_switch_mode(hub, USB3503_MODE_STANDBY);
+
+ if (hub->clk)
+ clk_disable_unprepare(hub->clk);
+
+ return 0;
+}
+
+static int usb3503_i2c_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct usb3503 *hub = i2c_get_clientdata(client);
+
+ if (hub->clk)
+ clk_prepare_enable(hub->clk);
+
+ usb3503_switch_mode(hub, hub->mode);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(usb3503_i2c_pm_ops, usb3503_i2c_suspend,
+ usb3503_i2c_resume);
+
static const struct i2c_device_id usb3503_id[] = {
{ USB3503_I2C_NAME, 0 },
{ }
@@ -333,6 +394,7 @@ MODULE_DEVICE_TABLE(of, usb3503_of_match);
static struct i2c_driver usb3503_i2c_driver = {
.driver = {
.name = USB3503_I2C_NAME,
+ .pm = &usb3503_i2c_pm_ops,
.of_match_table = of_match_ptr(usb3503_of_match),
},
.probe = usb3503_i2c_probe,
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 7209df15a3c..f6d4c851c5b 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -49,6 +49,13 @@ struct mipi_dsi_msg {
* @detach: detach DSI device from DSI host
* @transfer: send and/or receive DSI packet, return number of received bytes,
* or error
+ * @te_handler: call the crtc te_handler() callback from DSI host.
+ * The panel generates tearing effect synchronization signal
+ * between MCU and FB to display video images.
+ * And the display controller should trigger to transfer video
+ * image at this signal.
+ * So the panel receives the TE IRQ, then calls this handler
+ * to notify it to the display controller.
*/
struct mipi_dsi_host_ops {
int (*attach)(struct mipi_dsi_host *host,
@@ -57,6 +64,7 @@ struct mipi_dsi_host_ops {
struct mipi_dsi_device *dsi);
ssize_t (*transfer)(struct mipi_dsi_host *host,
struct mipi_dsi_msg *msg);
+ int (*te_handler)(struct mipi_dsi_host *host);
};
/**
diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild
index 41115776d76..7620b8399f7 100644
--- a/include/uapi/linux/netfilter/Kbuild
+++ b/include/uapi/linux/netfilter/Kbuild
@@ -36,6 +36,7 @@ header-y += xt_TEE.h
header-y += xt_TPROXY.h
header-y += xt_addrtype.h
header-y += xt_bpf.h
+header-y += xt_cgroup.h
header-y += xt_cluster.h
header-y += xt_comment.h
header-y += xt_connbytes.h
diff --git a/include/uapi/linux/netfilter/xt_cgroup.h b/include/uapi/linux/netfilter/xt_cgroup.h
new file mode 100644
index 00000000000..43acb7e175f
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_cgroup.h
@@ -0,0 +1,11 @@
+#ifndef _UAPI_XT_CGROUP_H
+#define _UAPI_XT_CGROUP_H
+
+#include <linux/types.h>
+
+struct xt_cgroup_info {
+ __u32 id;
+ __u32 invert;
+};
+
+#endif /* _UAPI_XT_CGROUP_H */
diff --git a/include/uapi/linux/usb/functionfs.h b/include/uapi/linux/usb/functionfs.h
index d6b01283f85..24b68c59dcf 100644
--- a/include/uapi/linux/usb/functionfs.h
+++ b/include/uapi/linux/usb/functionfs.h
@@ -10,9 +10,15 @@
enum {
FUNCTIONFS_DESCRIPTORS_MAGIC = 1,
- FUNCTIONFS_STRINGS_MAGIC = 2
+ FUNCTIONFS_STRINGS_MAGIC = 2,
+ FUNCTIONFS_DESCRIPTORS_MAGIC_V2 = 3,
};
+enum functionfs_flags {
+ FUNCTIONFS_HAS_FS_DESC = 1,
+ FUNCTIONFS_HAS_HS_DESC = 2,
+ FUNCTIONFS_HAS_SS_DESC = 4,
+};
#ifndef __KERNEL__
@@ -27,31 +33,48 @@ struct usb_endpoint_descriptor_no_audio {
__u8 bInterval;
} __attribute__((packed));
-
-/*
- * All numbers must be in little endian order.
- */
-
+/* Legacy format, deprecated as of 3.14. */
struct usb_functionfs_descs_head {
__le32 magic;
__le32 length;
__le32 fs_count;
__le32 hs_count;
-} __attribute__((packed));
+} __attribute__((packed, deprecated));
/*
* Descriptors format:
*
* | off | name | type | description |
* |-----+-----------+--------------+--------------------------------------|
- * | 0 | magic | LE32 | FUNCTIONFS_{FS,HS}_DESCRIPTORS_MAGIC |
+ * | 0 | magic | LE32 | FUNCTIONFS_DESCRIPTORS_MAGIC_V2 |
+ * | 4 | length | LE32 | length of the whole data chunk |
+ * | 8 | flags | LE32 | combination of functionfs_flags |
+ * | | fs_count | LE32 | number of full-speed descriptors |
+ * | | hs_count | LE32 | number of high-speed descriptors |
+ * | | ss_count | LE32 | number of super-speed descriptors |
+ * | | fs_descrs | Descriptor[] | list of full-speed descriptors |
+ * | | hs_descrs | Descriptor[] | list of high-speed descriptors |
+ * | | ss_descrs | Descriptor[] | list of super-speed descriptors |
+ *
+ * Depending on which flags are set, various fields may be missing in the
+ * structure. Any flags that are not recognised cause the whole block to be
+ * rejected with -ENOSYS.
+ *
+ * Legacy descriptors format:
+ *
+ * | off | name | type | description |
+ * |-----+-----------+--------------+--------------------------------------|
+ * | 0 | magic | LE32 | FUNCTIONFS_DESCRIPTORS_MAGIC |
* | 4 | length | LE32 | length of the whole data chunk |
* | 8 | fs_count | LE32 | number of full-speed descriptors |
* | 12 | hs_count | LE32 | number of high-speed descriptors |
* | 16 | fs_descrs | Descriptor[] | list of full-speed descriptors |
* | | hs_descrs | Descriptor[] | list of high-speed descriptors |
*
- * descs are just valid USB descriptors and have the following format:
+ * All numbers must be in little endian order.
+ *
+ * Descriptor[] is an array of valid USB descriptors which have the following
+ * format:
*
* | off | name | type | description |
* |-----+-----------------+------+--------------------------|
diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h
index b0393209679..eaad58b5be4 100644
--- a/include/video/samsung_fimd.h
+++ b/include/video/samsung_fimd.h
@@ -19,6 +19,7 @@
/* VIDCON0 */
#define VIDCON0 0x00
+#define VIDCON0_DSI_EN (1 << 30)
#define VIDCON0_INTERLACE (1 << 29)
#define VIDCON0_VIDOUT_MASK (0x7 << 26)
#define VIDCON0_VIDOUT_SHIFT 26
@@ -355,7 +356,7 @@
#define VIDINTCON0_INT_ENABLE (1 << 0)
#define VIDINTCON1 0x134
-#define VIDINTCON1_INT_I180 (1 << 2)
+#define VIDINTCON1_INT_I80 (1 << 2)
#define VIDINTCON1_INT_FRAME (1 << 1)
#define VIDINTCON1_INT_FIFO (1 << 0)
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 56d22cae590..1f63a3bf866 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -814,6 +814,16 @@ config NETFILTER_XT_MATCH_BPF
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_MATCH_CGROUP
+ tristate '"control group" match support'
+ depends on NETFILTER_ADVANCED
+ depends on CGROUPS
+ select CGROUP_NET_CLASSID
+ ---help---
+ Socket/process control group matching allows you to match locally
+ generated packets based on which net_cls control group processes
+ belong to.
+
config NETFILTER_XT_MATCH_CLUSTER
tristate '"cluster" match support'
depends on NF_CONNTRACK
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index a1abf87d43b..736dc1029af 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -124,6 +124,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
obj-$(CONFIG_NETFILTER_XT_MATCH_NFACCT) += xt_nfacct.o
obj-$(CONFIG_NETFILTER_XT_MATCH_OSF) += xt_osf.o
obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_CGROUP) += xt_cgroup.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
diff --git a/net/netfilter/xt_cgroup.c b/net/netfilter/xt_cgroup.c
new file mode 100644
index 00000000000..9a8e77e7f8d
--- /dev/null
+++ b/net/netfilter/xt_cgroup.c
@@ -0,0 +1,71 @@
+/*
+ * Xtables module to match the process control group.
+ *
+ * Might be used to implement individual "per-application" firewall
+ * policies in contrast to global policies based on control groups.
+ * Matching is based upon processes tagged to net_cls' classid marker.
+ *
+ * (C) 2013 Daniel Borkmann <dborkman@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/skbuff.h>
+#include <linux/module.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_cgroup.h>
+#include <net/sock.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Daniel Borkmann <dborkman@redhat.com>");
+MODULE_DESCRIPTION("Xtables: process control group matching");
+MODULE_ALIAS("ipt_cgroup");
+MODULE_ALIAS("ip6t_cgroup");
+
+static int cgroup_mt_check(const struct xt_mtchk_param *par)
+{
+ struct xt_cgroup_info *info = par->matchinfo;
+
+ if (info->invert & ~1)
+ return -EINVAL;
+
+ return info->id ? 0 : -EINVAL;
+}
+
+static bool
+cgroup_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+ const struct xt_cgroup_info *info = par->matchinfo;
+
+ if (skb->sk == NULL)
+ return false;
+
+ return (info->id == skb->sk->sk_classid) ^ info->invert;
+}
+
+static struct xt_match cgroup_mt_reg __read_mostly = {
+ .name = "cgroup",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = cgroup_mt_check,
+ .match = cgroup_mt,
+ .matchsize = sizeof(struct xt_cgroup_info),
+ .me = THIS_MODULE,
+ .hooks = (1 << NF_INET_LOCAL_OUT) |
+ (1 << NF_INET_POST_ROUTING),
+};
+
+static int __init cgroup_mt_init(void)
+{
+ return xt_register_match(&cgroup_mt_reg);
+}
+
+static void __exit cgroup_mt_exit(void)
+{
+ xt_unregister_match(&cgroup_mt_reg);
+}
+
+module_init(cgroup_mt_init);
+module_exit(cgroup_mt_exit);
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 8bbd79490b8..7f9719af275 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -3,6 +3,7 @@ config SND_SOC_SAMSUNG
depends on PLAT_SAMSUNG
select S3C64XX_DMA if ARCH_S3C64XX
select S3C2410_DMA if ARCH_S3C24XX
+ select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y or M if you want to add support for codecs attached to
the Samsung SoCs' Audio interfaces. You will also need to
@@ -233,13 +234,13 @@ config SND_SOC_LITTLEMILL
select MFD_WM8994
select SND_SOC_WM8994
-config SND_SOC_SAMSUNG_EXYNOS4_WM1811
- tristate "SoC I2S Audio support for WM1811 on Tizen Exynos4 board"
+config SND_SOC_SAMSUNG_TRATS2_WM1811
+ tristate "SoC I2S Audio support for WM1811 on Tizen Trats2 board"
depends on SND_SOC_SAMSUNG
select SND_SOC_WM8994
select SND_SAMSUNG_I2S
help
- Say Y if you want to add support for SoC audio on the Tizen Exynos4 board.
+ Say Y if you want to add support for SoC audio on the Tizen Trats2 board.
config SND_SOC_ODROIDX2
tristate "Audio support for Odroidx2"
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 8a675f18d98..da223de7557 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -44,7 +44,7 @@ snd-soc-trats-objs := trats_mc1n2.o
snd-soc-lowland-objs := lowland.o
snd-soc-littlemill-objs := littlemill.o
snd-soc-bells-objs := bells.o
-snd-soc-exynos4-wm1811-objs := exynos4_wm1811.o
+snd-soc-trats2-wm1811-objs := trats2_wm1811.o
snd-soc-odroidx2-max98090-objs := odroidx2_max98090.o
obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o
@@ -71,5 +71,5 @@ obj-$(CONFIG_SND_SOC_TRATS) += snd-soc-trats.o
obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o
obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o
obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o
-obj-$(CONFIG_SND_SOC_SAMSUNG_EXYNOS4_WM1811) += snd-soc-exynos4-wm1811.o
+obj-$(CONFIG_SND_SOC_SAMSUNG_TRATS2_WM1811) += snd-soc-trats2-wm1811.o
obj-$(CONFIG_SND_SOC_ODROIDX2) += snd-soc-odroidx2-max98090.o
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 6e2b2b4dca5..26db25da19c 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -20,6 +20,9 @@
#include <sound/soc.h>
#include <sound/pcm_params.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/dmaengine_pcm.h>
#include <asm/dma.h>
#include <mach/hardware.h>
@@ -27,14 +30,13 @@
#include "dma.h"
-#define ST_RUNNING (1<<0)
-#define ST_OPENED (1<<1)
-
static const struct snd_pcm_hardware dma_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_LE |
SNDRV_PCM_FMTBIT_U8 |
@@ -49,290 +51,77 @@ static const struct snd_pcm_hardware dma_hardware = {
.fifo_size = 32,
};
-struct runtime_data {
- spinlock_t lock;
- int state;
- unsigned int dma_loaded;
- unsigned int dma_period;
- dma_addr_t dma_start;
- dma_addr_t dma_pos;
- dma_addr_t dma_end;
- struct s3c_dma_params *params;
-};
-
-static void audio_buffdone(void *data);
-
-/* dma_enqueue
- *
- * place a dma buffer onto the queue for the dma system
- * to handle.
- */
-static void dma_enqueue(struct snd_pcm_substream *substream)
-{
- struct runtime_data *prtd = substream->runtime->private_data;
- dma_addr_t pos = prtd->dma_pos;
- unsigned int limit;
- struct samsung_dma_prep dma_info;
-
- pr_debug("Entered %s\n", __func__);
-
- limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
-
- pr_debug("%s: loaded %d, limit %d\n",
- __func__, prtd->dma_loaded, limit);
-
- dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
- dma_info.direction =
- (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
- ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
- dma_info.fp = audio_buffdone;
- dma_info.fp_param = substream;
- dma_info.period = prtd->dma_period;
- dma_info.len = prtd->dma_period*limit;
-
- if (dma_info.cap == DMA_CYCLIC) {
- dma_info.buf = pos;
- prtd->params->ops->prepare(prtd->params->ch, &dma_info);
- prtd->dma_loaded += limit;
- return;
- }
-
- while (prtd->dma_loaded < limit) {
- pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
-
- if ((pos + dma_info.period) > prtd->dma_end) {
- dma_info.period = prtd->dma_end - pos;
- pr_debug("%s: corrected dma len %ld\n",
- __func__, dma_info.period);
- }
-
- dma_info.buf = pos;
- prtd->params->ops->prepare(prtd->params->ch, &dma_info);
-
- prtd->dma_loaded++;
- pos += prtd->dma_period;
- if (pos >= prtd->dma_end)
- pos = prtd->dma_start;
- }
-
- prtd->dma_pos = pos;
-}
-
-static void audio_buffdone(void *data)
-{
- struct snd_pcm_substream *substream = data;
- struct runtime_data *prtd = substream->runtime->private_data;
-
- pr_debug("Entered %s\n", __func__);
-
- if (prtd->state & ST_RUNNING) {
- prtd->dma_pos += prtd->dma_period;
- if (prtd->dma_pos >= prtd->dma_end)
- prtd->dma_pos = prtd->dma_start;
-
- if (substream)
- snd_pcm_period_elapsed(substream);
-
- spin_lock(&prtd->lock);
- if (!samsung_dma_has_circular()) {
- prtd->dma_loaded--;
- dma_enqueue(substream);
- }
- spin_unlock(&prtd->lock);
- }
-}
-
+/* This might get called for several times by oss emulation */
static int dma_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct runtime_data *prtd = runtime->private_data;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- unsigned long totbytes = params_buffer_bytes(params);
- struct s3c_dma_params *dma =
- snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- struct samsung_dma_req req;
- struct samsung_dma_config config;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dmaengine_dai_dma_data *dma;
+ struct dma_slave_config slave_config;
+ struct dma_chan *chan;
+ int ret;
pr_debug("Entered %s\n", __func__);
+ dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
/* return if this is a bufferless transfer e.g.
* codec <--> BT codec or GSM modem -- lg FIXME */
if (!dma)
return 0;
- /* this may get called several times by oss emulation
- * with different params -HW */
- if (prtd->params == NULL) {
- /* prepare DMA */
- prtd->params = dma;
-
- pr_debug("params %p, client %p, channel %d\n", prtd->params,
- prtd->params->client, prtd->params->channel);
-
- prtd->params->ops = samsung_dma_get_ops();
-
- req.cap = (samsung_dma_has_circular() ?
- DMA_CYCLIC : DMA_SLAVE);
- req.client = prtd->params->client;
- config.direction =
- (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
- ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
- config.width = prtd->params->dma_size;
- config.fifo = prtd->params->dma_addr;
- prtd->params->ch = prtd->params->ops->request(
- prtd->params->channel, &req, rtd->cpu_dai->dev,
- prtd->params->ch_name);
- prtd->params->ops->config(prtd->params->ch, &config);
- }
-
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ runtime->dma_bytes = params_buffer_bytes(params);
- runtime->dma_bytes = totbytes;
+ chan = snd_dmaengine_pcm_get_chan(substream);
+ if (!chan)
+ return -ENODEV;
- spin_lock_irq(&prtd->lock);
- prtd->dma_loaded = 0;
- prtd->dma_period = params_period_bytes(params);
- prtd->dma_start = runtime->dma_addr;
- prtd->dma_pos = prtd->dma_start;
- prtd->dma_end = prtd->dma_start + totbytes;
- spin_unlock_irq(&prtd->lock);
+ ret = snd_dmaengine_pcm_prepare_slave_config(substream, params,
+ &slave_config);
+ if (ret)
+ return ret;
- return 0;
+ return dmaengine_slave_config(chan, &slave_config);
}
static int dma_hw_free(struct snd_pcm_substream *substream)
{
- struct runtime_data *prtd = substream->runtime->private_data;
-
pr_debug("Entered %s\n", __func__);
snd_pcm_set_runtime_buffer(substream, NULL);
- if (prtd->params) {
- prtd->params->ops->flush(prtd->params->ch);
- prtd->params->ops->release(prtd->params->ch,
- prtd->params->client);
- prtd->params = NULL;
- }
-
return 0;
}
-static int dma_prepare(struct snd_pcm_substream *substream)
-{
- struct runtime_data *prtd = substream->runtime->private_data;
- int ret = 0;
-
- pr_debug("Entered %s\n", __func__);
-
- /* return if this is a bufferless transfer e.g.
- * codec <--> BT codec or GSM modem -- lg FIXME */
- if (!prtd->params)
- return 0;
-
- /* flush the DMA channel */
- prtd->params->ops->flush(prtd->params->ch);
-
- prtd->dma_loaded = 0;
- prtd->dma_pos = prtd->dma_start;
-
- /* enqueue dma buffers */
- dma_enqueue(substream);
-
- return ret;
-}
-
-static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct runtime_data *prtd = substream->runtime->private_data;
- int ret = 0;
-
- pr_debug("Entered %s\n", __func__);
-
- spin_lock(&prtd->lock);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- prtd->state |= ST_RUNNING;
- prtd->params->ops->trigger(prtd->params->ch);
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- prtd->state &= ~ST_RUNNING;
- prtd->params->ops->stop(prtd->params->ch);
- break;
-
- default:
- ret = -EINVAL;
- break;
- }
-
- spin_unlock(&prtd->lock);
-
- return ret;
-}
-
-static snd_pcm_uframes_t
-dma_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct runtime_data *prtd = runtime->private_data;
- unsigned long res;
-
- pr_debug("Entered %s\n", __func__);
-
- res = prtd->dma_pos - prtd->dma_start;
-
- pr_debug("Pointer offset: %lu\n", res);
-
- /* we seem to be getting the odd error from the pcm library due
- * to out-of-bounds pointers. this is maybe due to the dma engine
- * not having loaded the new values for the channel before being
- * called... (todo - fix )
- */
-
- if (res >= snd_pcm_lib_buffer_bytes(substream)) {
- if (res == snd_pcm_lib_buffer_bytes(substream))
- res = 0;
- }
-
- return bytes_to_frames(substream->runtime, res);
-}
+static const char * const dma_chan_names[] = {
+ [SNDRV_PCM_STREAM_PLAYBACK] = "tx",
+ [SNDRV_PCM_STREAM_CAPTURE] = "rx",
+};
static int dma_open(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct runtime_data *prtd;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct dma_chan *chan;
pr_debug("Entered %s\n", __func__);
- snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
snd_soc_set_runtime_hwparams(substream, &dma_hardware);
- prtd = kzalloc(sizeof(struct runtime_data), GFP_KERNEL);
- if (prtd == NULL)
+ chan = kzalloc(sizeof(struct dma_chan), GFP_KERNEL);
+ if (!chan)
return -ENOMEM;
- spin_lock_init(&prtd->lock);
+ /* Request slave dma channel according to playback/capture stream */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ chan = dma_request_slave_channel(rtd->cpu_dai->dev,
+ dma_chan_names[0]);
+ else
+ chan = dma_request_slave_channel(rtd->cpu_dai->dev,
+ dma_chan_names[1]);
- runtime->private_data = prtd;
- return 0;
-}
-
-static int dma_close(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct runtime_data *prtd = runtime->private_data;
-
- pr_debug("Entered %s\n", __func__);
-
- if (!prtd)
- pr_debug("dma_close called with prtd == NULL\n");
-
- kfree(prtd);
-
- return 0;
+ return snd_dmaengine_pcm_open(substream, chan);
}
static int dma_mmap(struct snd_pcm_substream *substream,
@@ -350,13 +139,12 @@ static int dma_mmap(struct snd_pcm_substream *substream,
static struct snd_pcm_ops dma_ops = {
.open = dma_open,
- .close = dma_close,
+ .close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = dma_hw_params,
.hw_free = dma_hw_free,
- .prepare = dma_prepare,
- .trigger = dma_trigger,
- .pointer = dma_pointer,
+ .trigger = snd_dmaengine_pcm_trigger,
+ .pointer = snd_dmaengine_pcm_pointer_no_residue,
.mmap = dma_mmap,
};
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index 189a7a6d502..a4ab20ac0d1 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -16,6 +16,7 @@ struct s3c_dma_params {
struct s3c2410_dma_client *client; /* stream identifier */
int channel; /* Channel ID */
dma_addr_t dma_addr;
+ int irq;
int dma_size; /* Size of the DMA transfer */
unsigned ch;
struct samsung_dma_ops *ops;
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index b6687e30bf8..54df6db57d1 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -17,10 +17,12 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
+#include <sound/dmaengine_pcm.h>
#include <mach/dma.h>
@@ -84,9 +86,13 @@ struct i2s_dai {
#define DAI_OPENED (1 << 0) /* Dai is opened */
#define DAI_MANAGER (1 << 1) /* Dai is the manager */
unsigned mode;
+ /* CDCLK pin direction: 0 - input, 1 - output */
+ unsigned int cdclk_out:1;
/* Driver for this DAI */
struct snd_soc_dai_driver i2s_dai_drv;
/* DMA parameters */
+ struct snd_dmaengine_dai_dma_data snd_dma_playback;
+ struct snd_dmaengine_dai_dma_data snd_dma_capture;
struct s3c_dma_params dma_playback;
struct s3c_dma_params dma_capture;
struct s3c_dma_params idma_playback;
@@ -599,16 +605,19 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
break;
case 2:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- i2s->dma_playback.dma_size = 4;
+ i2s->snd_dma_playback.addr_width =
+ DMA_SLAVE_BUSWIDTH_4_BYTES;
else
- i2s->dma_capture.dma_size = 4;
+ i2s->snd_dma_capture.addr_width =
+ DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
case 1:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- i2s->dma_playback.dma_size = 2;
+ i2s->snd_dma_playback.addr_width =
+ DMA_SLAVE_BUSWIDTH_2_BYTES;
else
- i2s->dma_capture.dma_size = 2;
-
+ i2s->snd_dma_capture.addr_width =
+ DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
default:
dev_err(&i2s->pdev->dev, "%d channels not supported\n",
@@ -658,10 +667,10 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
snd_soc_dai_set_dma_data(dai, substream,
- (void *)&i2s->dma_playback);
+ (void *)&i2s->snd_dma_playback);
else
snd_soc_dai_set_dma_data(dai, substream,
- (void *)&i2s->dma_capture);
+ (void *)&i2s->snd_dma_capture);
i2s->frmclk = params_rate(params);
@@ -693,6 +702,9 @@ static int i2s_startup(struct snd_pcm_substream *substream,
spin_unlock_irqrestore(&lock, flags);
+ if (!is_opened(other) && i2s->cdclk_out)
+ i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK,
+ 0, SND_SOC_CLOCK_OUT);
return 0;
}
@@ -708,9 +720,13 @@ static void i2s_shutdown(struct snd_pcm_substream *substream,
i2s->mode &= ~DAI_OPENED;
i2s->mode &= ~DAI_MANAGER;
- if (is_opened(other))
+ if (is_opened(other)) {
other->mode |= DAI_MANAGER;
-
+ } else {
+ u32 mod = readl(i2s->addr + I2SMOD);
+ i2s->cdclk_out = !(mod & MOD_CDCLKCON);
+ other->cdclk_out = i2s->cdclk_out;
+ }
/* Reset any constraint on RFS and BFS */
i2s->rfs = 0;
i2s->bfs = 0;
@@ -940,11 +956,9 @@ static int i2s_suspend(struct snd_soc_dai *dai)
{
struct i2s_dai *i2s = to_info(dai);
- if (dai->active) {
- i2s->suspend_i2smod = readl(i2s->addr + I2SMOD);
- i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
- i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
- }
+ i2s->suspend_i2smod = readl(i2s->addr + I2SMOD);
+ i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
+ i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
return 0;
}
@@ -953,11 +967,9 @@ static int i2s_resume(struct snd_soc_dai *dai)
{
struct i2s_dai *i2s = to_info(dai);
- if (dai->active) {
- writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
- writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
- writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
- }
+ writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
+ writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
+ writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
return 0;
}
@@ -998,7 +1010,8 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
if (i2s->quirks & QUIRK_SEC_DAI)
idma_reg_addr_init(i2s->addr,
- i2s->sec_dai->idma_playback.dma_addr);
+ i2s->sec_dai->idma_playback.dma_addr,
+ i2s->sec_dai->idma_playback.irq);
probe_exit:
/* Reset any constraint on RFS and BFS */
@@ -1028,7 +1041,7 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
if (i2s->quirks & QUIRK_NEED_RSTCLR)
writel(0, i2s->addr + I2SCON);
- if (!IS_ERR(i2s->op_clk)){
+ if (!IS_ERR(i2s->op_clk)) {
clk_disable_unprepare(i2s->op_clk);
clk_put(i2s->op_clk);
}
@@ -1149,7 +1162,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data;
struct samsung_i2s *i2s_cfg = NULL;
struct resource *res;
- u32 regs_base, quirks = 0, idma_addr = 0;
+ u32 regs_base, quirks = 0, idma_addr = 0, idma_irq = 0;
struct device_node *np = pdev->dev.of_node;
enum samsung_dai_type samsung_dai_type;
int ret = 0;
@@ -1163,10 +1176,12 @@ static int samsung_i2s_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Unable to get drvdata\n");
return -EFAULT;
}
+
snd_soc_register_component(&sec_dai->pdev->dev,
&samsung_i2s_component,
&sec_dai->i2s_dai_drv, 1);
- asoc_dma_platform_register(&pdev->dev);
+ asoc_idma_platform_register(&pdev->dev);
+
return 0;
}
@@ -1218,8 +1233,15 @@ static int samsung_i2s_probe(struct platform_device *pdev)
if (of_property_read_u32(np, "samsung,idma-addr",
&idma_addr)) {
if (quirks & QUIRK_SEC_DAI) {
- dev_err(&pdev->dev, "idma address is not"\
- "specified");
+ dev_err(&pdev->dev, "idma address is not specified\n");
+ return -EINVAL;
+ }
+ }
+
+ idma_irq = irq_of_parse_and_map(np, 0);
+ if (idma_irq == NO_IRQ) {
+ if (quirks & QUIRK_SEC_DAI) {
+ dev_err(&pdev->dev, "idma irq is not specified\n");
return -EINVAL;
}
}
@@ -1238,16 +1260,14 @@ static int samsung_i2s_probe(struct platform_device *pdev)
}
regs_base = res->start;
- pri_dai->dma_playback.dma_addr = regs_base + I2STXD;
- pri_dai->dma_capture.dma_addr = regs_base + I2SRXD;
- pri_dai->dma_playback.client =
- (struct s3c2410_dma_client *)&pri_dai->dma_playback;
- pri_dai->dma_playback.ch_name = "tx";
- pri_dai->dma_capture.client =
- (struct s3c2410_dma_client *)&pri_dai->dma_capture;
- pri_dai->dma_capture.ch_name = "rx";
- pri_dai->dma_playback.dma_size = 4;
- pri_dai->dma_capture.dma_size = 4;
+ pri_dai->snd_dma_playback.addr = regs_base + I2STXD;
+ pri_dai->snd_dma_playback.addr_width =
+ DMA_SLAVE_BUSWIDTH_4_BYTES; /* Default address width */
+ pri_dai->snd_dma_playback.maxburst = 1;
+ pri_dai->snd_dma_capture.addr = regs_base + I2SRXD;
+ pri_dai->snd_dma_capture.addr_width =
+ DMA_SLAVE_BUSWIDTH_4_BYTES; /* Default address width */
+ pri_dai->snd_dma_capture.maxburst = 1;
pri_dai->base = regs_base;
pri_dai->quirks = quirks;
pri_dai->op_clk = ERR_PTR(-EINVAL);
@@ -1277,6 +1297,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
sec_dai->base = regs_base;
sec_dai->quirks = quirks;
sec_dai->idma_playback.dma_addr = idma_addr;
+ sec_dai->idma_playback.irq = idma_irq;
sec_dai->pri_dai = pri_dai;
pri_dai->sec_dai = sec_dai;
}
@@ -1322,7 +1343,11 @@ static int samsung_i2s_remove(struct platform_device *pdev)
i2s->pri_dai = NULL;
i2s->sec_dai = NULL;
- asoc_dma_platform_unregister(&pdev->dev);
+ if (other)
+ asoc_idma_platform_unregister(&pdev->dev);
+ else
+ asoc_dma_platform_unregister(&pdev->dev);
+
snd_soc_unregister_component(&pdev->dev);
return 0;
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
index 6e5fed30aa2..8c3f912fddf 100644
--- a/sound/soc/samsung/idma.c
+++ b/sound/soc/samsung/idma.c
@@ -405,11 +405,12 @@ static int idma_new(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr)
+void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr, int irq)
{
spin_lock_init(&idma.lock);
idma.regs = regs;
idma.lp_tx_addr = addr;
+ idma_irq = irq;
}
EXPORT_SYMBOL_GPL(idma_reg_addr_init);
@@ -419,32 +420,17 @@ static struct snd_soc_platform_driver asoc_idma_platform = {
.pcm_free = idma_free,
};
-static int asoc_idma_platform_probe(struct platform_device *pdev)
+int asoc_idma_platform_register(struct device *dev)
{
- idma_irq = platform_get_irq(pdev, 0);
- if (idma_irq < 0)
- return idma_irq;
-
- return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform);
+ return snd_soc_register_platform(dev, &asoc_idma_platform);
}
+EXPORT_SYMBOL_GPL(asoc_idma_platform_register);
-static int asoc_idma_platform_remove(struct platform_device *pdev)
+void asoc_idma_platform_unregister(struct device *dev)
{
- snd_soc_unregister_platform(&pdev->dev);
- return 0;
+ snd_soc_unregister_platform(dev);
}
-
-static struct platform_driver asoc_idma_driver = {
- .driver = {
- .name = "samsung-idma",
- .owner = THIS_MODULE,
- },
-
- .probe = asoc_idma_platform_probe,
- .remove = asoc_idma_platform_remove,
-};
-
-module_platform_driver(asoc_idma_driver);
+EXPORT_SYMBOL_GPL(asoc_idma_platform_unregister);
MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
MODULE_DESCRIPTION("Samsung ASoC IDMA Driver");
diff --git a/sound/soc/samsung/idma.h b/sound/soc/samsung/idma.h
index 8644946973e..b12c47f1d86 100644
--- a/sound/soc/samsung/idma.h
+++ b/sound/soc/samsung/idma.h
@@ -14,8 +14,10 @@
#ifndef __SND_SOC_SAMSUNG_IDMA_H_
#define __SND_SOC_SAMSUNG_IDMA_H_
-extern void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr);
+extern void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr, int irq);
+int asoc_idma_platform_register(struct device *dev);
+void asoc_idma_platform_unregister(struct device *dev);
/* dma_state */
#define LPAM_DMA_STOP 0
#define LPAM_DMA_START 1
diff --git a/sound/soc/samsung/odroidx2_max98090.c b/sound/soc/samsung/odroidx2_max98090.c
index 844af328835..27355a765b5 100644
--- a/sound/soc/samsung/odroidx2_max98090.c
+++ b/sound/soc/samsung/odroidx2_max98090.c
@@ -12,84 +12,134 @@
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include "i2s.h"
-#include "i2s-regs.h"
+
+struct odroidx2_drv_data {
+ const struct snd_soc_dapm_widget *dapm_widgets;
+ unsigned int num_dapm_widgets;
+
+ const struct snd_kcontrol_new *controls;
+ unsigned int num_controls;
+};
/* Config I2S CDCLK output 19.2MHZ clock to Max98090 */
#define MAX98090_MCLK 19200000
-static int odroidx2_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+static int odroidx2_late_probe(struct snd_soc_card *card)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ struct snd_soc_dai *cpu_dai = card->rtd[0].cpu_dai;
int ret;
ret = snd_soc_dai_set_sysclk(codec_dai, 0, MAX98090_MCLK,
SND_SOC_CLOCK_IN);
- if (ret < 0) {
- dev_err(codec_dai->dev,
- "Unable to switch to FLL1: %d\n", ret);
+ if (ret < 0)
return ret;
- }
-
- ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK,
- 0, MOD_OPCLK_PCLK);
- if (ret < 0) {
- dev_err(cpu_dai->dev,
- "Unable to set i2s opclk: 0x%x\n", ret);
- return ret;
- }
/* Set the cpu DAI configuration in order to use CDCLK */
- ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK,
+ return snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK,
0, SND_SOC_CLOCK_OUT);
- if (ret < 0)
- return ret;
+}
- dev_info(codec_dai->dev,
- "HiFi DAI %s params ch %d, rate %d as i2s slave\n",
- ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? \
- "playback" : "capture"),
- params_channels(params),
- params_rate(params));
+static const struct snd_soc_dapm_widget odroidx2_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_MIC("Mic Jack", NULL),
+ SND_SOC_DAPM_MIC("DMIC", NULL),
+};
- return 0;
-}
+static const struct snd_kcontrol_new odroidx2_max98090_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+ SOC_DAPM_PIN_SWITCH("Mic Jack"),
+ SOC_DAPM_PIN_SWITCH("DMIC"),
+};
+
+static const struct snd_soc_dapm_widget odroidu3_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_SPK("Speakers", NULL),
+};
-static struct snd_soc_ops odroidx2_ops = {
- .hw_params = odroidx2_hw_params,
+static const struct snd_kcontrol_new odroidu3_max98090_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+ SOC_DAPM_PIN_SWITCH("Speakers"),
};
static struct snd_soc_dai_link odroidx2_dai[] = {
{
- .name = "MAX98090",
- .stream_name = "MAX98090 PCM",
- .codec_dai_name = "HiFi",
- .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
- | SND_SOC_DAIFMT_CBM_CFM,
- .ops = &odroidx2_ops,
+ .name = "MAX98090",
+ .stream_name = "MAX98090 PCM",
+ .codec_dai_name = "HiFi",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
+ }, {
+ .name = "MAX98090 SEC",
+ .stream_name = "MAX98090 PCM SEC",
+ .codec_dai_name = "HiFi",
+ .cpu_dai_name = "samsung-i2s-sec",
+ .platform_name = "samsung-i2s-sec",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
},
};
static struct snd_soc_card odroidx2 = {
- .name = "odroidx2",
- .owner = THIS_MODULE,
- .dai_link = odroidx2_dai,
- .num_links = ARRAY_SIZE(odroidx2_dai),
+ .owner = THIS_MODULE,
+ .dai_link = odroidx2_dai,
+ .num_links = ARRAY_SIZE(odroidx2_dai),
+ .fully_routed = true,
+ .late_probe = odroidx2_late_probe,
+};
+
+struct odroidx2_drv_data odroidx2_drvdata = {
+ .dapm_widgets = odroidx2_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(odroidx2_dapm_widgets),
+ .controls = odroidx2_max98090_controls,
+ .num_controls = ARRAY_SIZE(odroidx2_max98090_controls),
};
+struct odroidx2_drv_data odroidu3_drvdata = {
+ .dapm_widgets = odroidu3_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(odroidu3_dapm_widgets),
+ .controls = odroidu3_max98090_controls,
+ .num_controls = ARRAY_SIZE(odroidu3_max98090_controls),
+};
+
+static const struct of_device_id odroidx2_audio_of_match[] = {
+ {
+ .compatible = "samsung,odroidx2-audio",
+ .data = &odroidx2_drvdata,
+ }, {
+ .compatible = "samsung,odroidu3-audio",
+ .data = &odroidu3_drvdata,
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, odroidx2_audio_of_match);
+
static int odroidx2_audio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct snd_soc_card *card = &odroidx2;
-
- if (!np)
- return -ENODEV;
+ struct odroidx2_drv_data *dd;
+ const struct of_device_id *of_id;
+ int ret;
card->dev = &pdev->dev;
- odroidx2_dai[0].codec_name = NULL;
+ of_id = of_match_node(odroidx2_audio_of_match, np);
+ dd = (struct odroidx2_drv_data *)of_id->data;
+
+ card->dapm_widgets = dd->dapm_widgets;
+ card->num_dapm_widgets = dd->num_dapm_widgets;
+ card->controls = dd->controls;
+ card->num_controls = dd->num_controls;
+
+ ret = snd_soc_of_parse_card_name(card, "samsung,model");
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
+ if (ret < 0)
+ return ret;
+
odroidx2_dai[0].codec_of_node = of_parse_phandle(np,
"samsung,audio-codec", 0);
if (!odroidx2_dai[0].codec_of_node) {
@@ -98,18 +148,33 @@ static int odroidx2_audio_probe(struct platform_device *pdev)
return -EINVAL;
}
- odroidx2_dai[0].cpu_name = NULL;
odroidx2_dai[0].cpu_of_node = of_parse_phandle(np,
"samsung,i2s-controller", 0);
if (!odroidx2_dai[0].cpu_of_node) {
dev_err(&pdev->dev,
"Property 'samsung,i2s-controller' missing or invalid\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_put_cod_n;
}
odroidx2_dai[0].platform_of_node = odroidx2_dai[0].cpu_of_node;
- return snd_soc_register_card(card);
+ /* Configure the secondary audio interface with the same codec dai */
+ odroidx2_dai[1].codec_of_node = odroidx2_dai[0].codec_of_node;
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret);
+ goto err_put_cpu_n;
+ }
+
+ return 0;
+
+err_put_cpu_n:
+ of_node_put((struct device_node *)odroidx2_dai[0].cpu_of_node);
+err_put_cod_n:
+ of_node_put((struct device_node *)odroidx2_dai[0].codec_of_node);
+ return ret;
}
static int odroidx2_audio_remove(struct platform_device *pdev)
@@ -118,25 +183,22 @@ static int odroidx2_audio_remove(struct platform_device *pdev)
snd_soc_unregister_card(card);
+ of_node_put((struct device_node *)odroidx2_dai[0].cpu_of_node);
+ of_node_put((struct device_node *)odroidx2_dai[0].codec_of_node);
+
return 0;
}
-static const struct of_device_id odroidx2_audio_of_match[] = {
- { .compatible = "samsung,odroidx2-audio", },
- { },
-};
-MODULE_DEVICE_TABLE(of, odroid_audio_of_match);
-
static struct platform_driver odroidx2_audio_driver = {
.driver = {
- .name = "odroidx2-audio",
- .owner = THIS_MODULE,
- .of_match_table = odroidx2_audio_of_match,
+ .name = "odroidx2-audio",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = odroidx2_audio_of_match,
},
- .probe = odroidx2_audio_probe,
- .remove = odroidx2_audio_remove,
+ .probe = odroidx2_audio_probe,
+ .remove = odroidx2_audio_remove,
};
-
module_platform_driver(odroidx2_audio_driver);
MODULE_AUTHOR("zhen1.chen@samsung.com");
diff --git a/sound/soc/samsung/exynos4_wm1811.c b/sound/soc/samsung/trats2_wm1811.c
index a1dbce6627c..9de4fc32119 100644
--- a/sound/soc/samsung/exynos4_wm1811.c
+++ b/sound/soc/samsung/trats2_wm1811.c
@@ -95,7 +95,7 @@ enum {
MIC_MAX
};
-enum exynos4_wm1811_gpios {
+enum trats2_wm1811_gpios {
GPIO_VPS_SOUND,
GPIO_MIC_BIAS,
GPIO_MIC_SUB_BIAS,
@@ -107,7 +107,7 @@ static struct class *audio_class;
static struct device *jack_dev;
static struct device *caps_dev;
-struct exynos_wm1811 {
+struct trats2_wm1811 {
struct snd_soc_jack jack;
struct snd_soc_codec *codec;
struct clk *codec_mclk;
@@ -154,7 +154,7 @@ static int exynos_snd_micbias(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- struct exynos_wm1811 *machine = snd_soc_card_get_drvdata(codec->card);
+ struct trats2_wm1811 *machine = snd_soc_card_get_drvdata(codec->card);
unsigned int mic;
dev_info(codec->dev, "Mic Bias: %s event is %02X", w->name, event);
@@ -236,7 +236,7 @@ static int exynos_snd_vps_switch(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- struct exynos_wm1811 *machine = snd_soc_card_get_drvdata(codec->card);
+ struct trats2_wm1811 *machine = snd_soc_card_get_drvdata(codec->card);
if (!gpio_is_valid(machine->gpio_vps_en))
return 0;
@@ -300,7 +300,7 @@ static void codec_micd_set_rate(struct snd_soc_codec *codec)
static void codec_micdet(u16 status, void *data)
{
- struct exynos_wm1811 *machine = data;
+ struct trats2_wm1811 *machine = data;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(machine->codec);
int report;
static int check_report;
@@ -461,7 +461,7 @@ static int machine_aif1_hw_params(struct snd_pcm_substream *substream,
dev_info(codec_dai->dev,
"AIF1 DAI %s params ch %d, rate %d as i2s slave\n",
- ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? \
+ ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
"playback" : "capture"),
params_channels(params),
params_rate(params));
@@ -548,7 +548,7 @@ static int machine_aif1_hw_params(struct snd_pcm_substream *substream,
psr = 1;
break;
default:
- printk(KERN_INFO "Not yet supported!\n");
+ dev_info(codec_dai->dev, "Not yet supported!\n");
return -EINVAL;
}
@@ -665,7 +665,7 @@ static int machine_aif2_hw_params(struct snd_pcm_substream *substream,
dev_info(codec_dai->dev,
"AIF2 DAI %s params ch %d, rate %d as Clock %s\n",
- ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? \
+ ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
"playback" : "capture"),
params_channels(params),
params_rate(params),
@@ -684,7 +684,7 @@ static int machine_aif3_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = rtd->codec_dai;
dev_info(codec_dai->dev, "AIF3 DAI %s params ch %d, rate %d\n",
- ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? \
+ ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
"playback" : "capture"),
params_channels(params),
params_rate(params));
@@ -827,7 +827,7 @@ static DEVICE_ATTR(select_jack, S_IRUGO | S_IWUSR | S_IWGRP,
static ssize_t audio_caps_cp_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct exynos_wm1811 *machine = dev_get_drvdata(dev);
+ struct trats2_wm1811 *machine = dev_get_drvdata(dev);
if (machine->cp_wb_support == true)
return sprintf(buf, "wb\n") + 1;
@@ -839,7 +839,7 @@ static DEVICE_ATTR(cp_caps, S_IRUGO, audio_caps_cp_show, NULL);
static ssize_t audio_caps_mic_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct exynos_wm1811 *machine = dev_get_drvdata(dev);
+ struct trats2_wm1811 *machine = dev_get_drvdata(dev);
int i, cnt = 0;
if (!machine)
@@ -858,7 +858,7 @@ static int machine_init_paiftx(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = rtd->card;
- struct exynos_wm1811 *machine = snd_soc_card_get_drvdata(card);
+ struct trats2_wm1811 *machine = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *aif1_dai = rtd->codec_dai;
struct wm8994 *wm8994 = dev_get_drvdata(codec->dev->parent);
int ret;
@@ -1023,6 +1023,51 @@ static int machine_init_paiftx(struct snd_soc_pcm_runtime *rtd)
return snd_soc_dapm_sync(&codec->dapm);
}
+static struct snd_soc_dai_driver voice_dai[] = {
+ {
+ .name = "voice-modem",
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 16000,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 16000,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ },
+ {
+ .name = "voice-bluetooth",
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 16000,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 16000,
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ },
+};
+
+static const struct snd_soc_component_driver voice_component = {
+ .name = "trats2-voice",
+};
+
static struct snd_soc_dai_link machine_dai[] = {
{
/* Primary DAI i/f */
@@ -1039,7 +1084,6 @@ static struct snd_soc_dai_link machine_dai[] = {
.stream_name = "Voice Tx/Rx",
.cpu_dai_name = "voice-modem",
.codec_dai_name = "wm8994-aif2",
- .platform_name = "snd-soc-dummy",
.codec_name = "wm8994-codec",
.ops = &machine_aif2_ops,
.ignore_suspend = 1,
@@ -1048,23 +1092,16 @@ static struct snd_soc_dai_link machine_dai[] = {
.stream_name = "BT Tx/Rx",
.cpu_dai_name = "voice-bluetooth",
.codec_dai_name = "wm8994-aif3",
- .platform_name = "snd-soc-dummy",
.codec_name = "wm8994-codec",
.ops = &machine_aif3_ops,
.ignore_suspend = 1,
}, {
/* Sec_Fifo DAI i/f */
- .cpu_dai_name = "samsung-i2s.4",
- .codec_dai_name = "wm8994-aif1",
-#ifdef CONFIG_SND_SAMSUNG_USE_IDMA
.name = "Sec_FIFO TX",
.stream_name = "Sec_Dai",
- .platform_name = "samsung-idma",
-#else
- .name = "WM1811 AIF1 Playback",
- .stream_name = "Pri_Dai Playback",
- .platform_name = "samsung-audio",
-#endif
+ .cpu_dai_name = "samsung-i2s-sec",
+ .codec_dai_name = "wm8994-aif1",
+ .platform_name = "samsung-i2s-sec",
.codec_name = "wm8994-codec",
.ops = &machine_aif1_ops,
},
@@ -1072,7 +1109,7 @@ static struct snd_soc_dai_link machine_dai[] = {
static int machine_card_suspend_post(struct snd_soc_card *card)
{
- struct exynos_wm1811 *machine = snd_soc_card_get_drvdata(card);
+ struct trats2_wm1811 *machine = snd_soc_card_get_drvdata(card);
struct snd_soc_codec *codec = card->rtd->codec;
struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
struct snd_soc_dai *aif2_dai = card->rtd[1].codec_dai;
@@ -1084,8 +1121,6 @@ static int machine_card_suspend_post(struct snd_soc_card *card)
to disable mclk1 from AP */
dev_info(codec->dev, "use mclk2 and disable fll");
-/* Disable this code until support for AIF2 interface is added. */
-#if 0
ret = snd_soc_dai_set_sysclk(aif2_dai,
WM8994_SYSCLK_MCLK2,
CODEC_CLK32K,
@@ -1098,7 +1133,7 @@ static int machine_card_suspend_post(struct snd_soc_card *card)
if (ret < 0)
dev_err(codec->dev,
"Unable to stop FLL2: %d\n", ret);
-#endif
+
ret = snd_soc_dai_set_sysclk(aif1_dai,
WM8994_SYSCLK_MCLK2,
CODEC_CLK32K,
@@ -1124,7 +1159,7 @@ static int machine_card_suspend_post(struct snd_soc_card *card)
static int machine_card_resume_pre(struct snd_soc_card *card)
{
- struct exynos_wm1811 *machine = snd_soc_card_get_drvdata(card);
+ struct trats2_wm1811 *machine = snd_soc_card_get_drvdata(card);
struct snd_soc_codec *codec = card->rtd->codec;
struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
int reg = 0;
@@ -1163,7 +1198,7 @@ static int machine_card_resume_pre(struct snd_soc_card *card)
return 0;
}
-static int exynos4_wm1811_parse_dt(struct exynos_wm1811 *machine,
+static int trats2_wm1811_parse_dt(struct trats2_wm1811 *machine,
struct device *dev)
{
struct device_node *node = dev->of_node;
@@ -1190,7 +1225,7 @@ static int exynos4_wm1811_parse_dt(struct exynos_wm1811 *machine,
continue;
}
ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW,
- mic_names[i]);
+ mic_names[i]);
if (ret) {
dev_err(dev, "%s gpio request failed\n", mic_names[i]);
continue;
@@ -1210,10 +1245,10 @@ static int exynos4_wm1811_parse_dt(struct exynos_wm1811 *machine,
return ret;
}
-static int exynos4_wm1811_probe(struct platform_device *pdev)
+static int trats2_wm1811_probe(struct platform_device *pdev)
{
struct snd_soc_dai_link *dai_link = &machine_dai[0];
- struct exynos_wm1811 *machine;
+ struct trats2_wm1811 *machine;
struct snd_soc_card *card;
struct clk *parent, *out_mux;
int ret;
@@ -1226,8 +1261,7 @@ static int exynos4_wm1811_probe(struct platform_device *pdev)
return -ENOMEM;
card->dai_link = machine_dai;
- /* FIXME: Enable all audio interfaces */
- card->num_links = 1; /* ARRAY_SIZE(machine_dai); */
+ card->num_links = ARRAY_SIZE(machine_dai);
card->suspend_post = machine_card_suspend_post;
card->resume_pre = machine_card_resume_pre;
card->dev = &pdev->dev;
@@ -1236,7 +1270,7 @@ static int exynos4_wm1811_probe(struct platform_device *pdev)
if (!machine)
return -ENOMEM;
- ret = exynos4_wm1811_parse_dt(machine, &pdev->dev);
+ ret = trats2_wm1811_parse_dt(machine, &pdev->dev);
if (ret < 0)
return ret;
@@ -1285,13 +1319,19 @@ static int exynos4_wm1811_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(card, machine);
+ /* register voice DAI */
+ ret = snd_soc_register_component(&pdev->dev, &voice_component,
+ voice_dai, ARRAY_SIZE(voice_dai));
+ if (ret)
+ return ret;
+
return snd_soc_register_card(card);
}
-static int exynos4_wm1811_remove(struct platform_device *pdev)
+static int trats2_wm1811_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
- struct exynos_wm1811 *machine = snd_soc_card_get_drvdata(card);
+ struct trats2_wm1811 *machine = snd_soc_card_get_drvdata(card);
snd_soc_unregister_card(card);
clk_put(machine->codec_mclk);
@@ -1299,28 +1339,28 @@ static int exynos4_wm1811_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id exynos4_wm1811_of_match[] = {
+static const struct of_device_id trats2_wm1811_of_match[] = {
{
- .compatible = "samsung,exynos4-wm1811",
+ .compatible = "samsung,trats2-wm1811",
},
{ /* sentinel */ },
};
-MODULE_DEVICE_TABLE(of, exynos4_wm1811_of_match);
+MODULE_DEVICE_TABLE(of, trats2_wm1811_of_match);
-static struct platform_driver exynos4_wm1811_driver = {
+static struct platform_driver trats2_wm1811_driver = {
.driver = {
- .name = "exynos4-wm1811",
- .of_match_table = exynos4_wm1811_of_match,
+ .name = "trats2-wm1811",
+ .of_match_table = trats2_wm1811_of_match,
.owner = THIS_MODULE,
.pm = &snd_soc_pm_ops,
},
- .probe = exynos4_wm1811_probe,
- .remove = exynos4_wm1811_remove,
+ .probe = trats2_wm1811_probe,
+ .remove = trats2_wm1811_remove,
};
-module_platform_driver(exynos4_wm1811_driver);
+module_platform_driver(trats2_wm1811_driver);
MODULE_AUTHOR("KwangHui Cho <kwanghui.cho@samsung.com>");
MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
-MODULE_DESCRIPTION("Exynos4+WM1811 machine ASoC driver");
+MODULE_DESCRIPTION("trats2 machine ASoC driver");
MODULE_LICENSE("GPL");