From c7397b6ca0f2dad55ef4625cda093503dc38a0da Mon Sep 17 00:00:00 2001 From: =?utf8?q?Lothar=20Wa=C3=9Fmann?= Date: Thu, 19 Jun 2014 10:18:37 +0200 Subject: [PATCH] KARO: cleanup after merge of Freescale 3.10.17 stuff --- arch/arm/boot/dts/Makefile | 28 +- arch/arm/boot/dts/imx6dl.dtsi | 90 +- arch/arm/boot/dts/imx6q.dtsi | 135 +- arch/arm/boot/dts/imx6qdl-tx6.dtsi | 5 + arch/arm/boot/dts/imx6qdl.dtsi | 38 +- arch/arm/include/asm/glue-cache.h | 16 +- drivers/cpufreq/Kconfig | 29 - drivers/cpufreq/Makefile | 1 - drivers/cpufreq/cpufreq_interactive.c | 705 ---------- drivers/dma/imx-sdma.c | 4 +- drivers/gpu/drm/Makefile | 21 - drivers/hwmon/Kconfig | 14 - drivers/hwmon/Makefile | 2 - drivers/hwmon/mag3110.c | 611 --------- drivers/hwmon/mxc_mma8451.c | 598 --------- drivers/input/touchscreen/Kconfig | 21 - drivers/input/touchscreen/Makefile | 1 - drivers/input/touchscreen/egalax_ts.c | 130 +- drivers/input/touchscreen/elan_ts.c | 472 ------- drivers/leds/leds-gpio.c | 4 +- .../media/platform/mxc/output/mxc_pxp_v4l2.c | 4 +- drivers/mfd/si476x-cmd.c | 14 +- drivers/mfd/si476x-i2c.c | 19 +- drivers/mfd/si476x-prop.c | 21 - drivers/misc/sram.c | 2 +- drivers/mmc/core/mmc.c | 377 ------ drivers/mmc/host/sdhci.c | 4 +- drivers/mtd/chips/cfi_cmdset_0002.c | 4 + drivers/mtd/ubi/build.c | 2 +- drivers/mxc/vpu/mxc_vpu.c | 1139 +++++++---------- drivers/net/can/flexcan.c | 11 +- drivers/net/ethernet/freescale/fec.h | 2 - drivers/net/wireless/ath/ath6kl/sdio.c | 11 +- drivers/pci/host/pci-exynos.c | 52 - drivers/pinctrl/devicetree.c | 44 - drivers/power/Kconfig | 14 - drivers/power/Makefile | 2 - drivers/power/imx6_usb_charger.c | 294 ----- drivers/power/sabresd_battery.c | 998 --------------- drivers/spi/spi.c | 5 - drivers/thermal/imx_thermal.c | 2 +- drivers/usb/core/hub.c | 3 +- drivers/video/Kconfig | 2 + drivers/video/Makefile | 1 + drivers/video/mxc/Kconfig | 71 + drivers/video/mxc/Makefile | 9 + drivers/video/mxc/ldb.c | 1036 +++++++++++++++ drivers/video/mxc/mxc_dispdrv.c | 150 +++ drivers/video/mxc/mxc_dispdrv.h | 54 + drivers/video/mxc/mxc_ipuv3_fb.c | 16 +- include/linux/cpufreq.h | 3 - include/linux/isl29023.h | 47 - include/linux/mmc/card.h | 4 - include/linux/mmc/mmc.h | 25 - include/linux/mtd/map.h | 2 +- include/linux/mxc_vpu.h | 4 +- include/linux/mxcfb.h | 46 + include/linux/power/imx6_usb_charger.h | 80 -- include/linux/power/sabresd_battery.h | 65 - include/uapi/linux/isl29023.h | 47 - include/uapi/linux/mxcfb.h | 174 +++ sound/soc/fsl/Kconfig | 35 - sound/soc/fsl/Makefile | 6 - sound/soc/fsl/imx-cs42888.c | 367 ------ sound/soc/fsl/imx-hdmi.c | 126 -- sound/soc/fsl/imx-si476x.c | 173 --- sound/soc/soc-pcm.c | 4 +- 67 files changed, 2300 insertions(+), 6196 deletions(-) delete mode 100644 drivers/cpufreq/cpufreq_interactive.c delete mode 100755 drivers/hwmon/mag3110.c delete mode 100644 drivers/hwmon/mxc_mma8451.c delete mode 100644 drivers/input/touchscreen/elan_ts.c delete mode 100644 drivers/power/imx6_usb_charger.c delete mode 100644 drivers/power/sabresd_battery.c create mode 100644 drivers/video/mxc/Kconfig create mode 100644 drivers/video/mxc/Makefile create mode 100644 drivers/video/mxc/ldb.c create mode 100644 drivers/video/mxc/mxc_dispdrv.c create mode 100644 drivers/video/mxc/mxc_dispdrv.h delete mode 100644 include/linux/isl29023.h create mode 100644 include/linux/mxcfb.h delete mode 100644 include/linux/power/imx6_usb_charger.h delete mode 100644 include/linux/power/sabresd_battery.h delete mode 100644 include/uapi/linux/isl29023.h create mode 100644 include/uapi/linux/mxcfb.h delete mode 100644 sound/soc/fsl/imx-cs42888.c delete mode 100644 sound/soc/fsl/imx-hdmi.c delete mode 100644 sound/soc/fsl/imx-si476x.c diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index f8986980d6e9..37a4c8cb88fb 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -195,7 +195,9 @@ dtb-$(CONFIG_ARCH_MXC) += \ imx6dl-sabreauto.dtb \ imx6dl-sabrelite.dtb \ imx6dl-sabresd.dtb \ + imx6dl-tx6dl-comtft.dtb \ imx6dl-tx6u-801x.dtb \ + imx6dl-tx6u-811x.dtb \ imx6dl-wandboard.dtb \ imx6q-arm2.dtb \ imx6q-cm-fx6.dtb \ @@ -214,34 +216,16 @@ dtb-$(CONFIG_ARCH_MXC) += \ imx6q-sabrelite.dtb \ imx6q-sabresd.dtb \ imx6q-sbc6x.dtb \ - imx6q-udoo.dtb \ - imx6q-wandboard.dtb \ - imx6sl-evk.dtb \ - vf610-colibri.dtb \ - vf610-cosmic.dtb \ - vf610-twr.dtb -# imx6dl-tx6dl-comtft.dtb \ - imx6dl-tx6u-801x.dtb \ - imx6dl-tx6u-811x.dtb \ - imx6dl-wandboard.dtb \ - imx6q-arm2.dtb \ - imx6q-sabreauto.dtb \ - imx6q-sabreauto-ecspi.dtb \ - imx6q-sabreauto-flexcan1.dtb \ - imx6q-sabreauto-gpmi-weim.dtb \ - imx6q-sabrelite.dtb \ - imx6q-sabresd.dtb \ - imx6q-sabresd-hdcp.dtb \ - imx6q-sabresd-ldo.dtb \ - imx6q-sbc6x.dtb \ imx6q-tx6q-1010.dtb \ imx6q-tx6q-1010-comtft.dtb \ imx6q-tx6q-1020.dtb \ imx6q-tx6q-1020-comtft.dtb \ imx6q-tx6q-1110.dtb \ + imx6q-udoo.dtb \ + imx6q-wandboard.dtb \ imx6sl-evk.dtb \ - imx6sl-evk-csi.dtb \ - imx6sl-evk-ldo.dtb \ + vf610-colibri.dtb \ + vf610-cosmic.dtb \ vf610-twr.dtb dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \ imx23-olinuxino.dtb \ diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi index 0a9c49d69d41..8df79933a151 100644 --- a/arch/arm/boot/dts/imx6dl.dtsi +++ b/arch/arm/boot/dts/imx6dl.dtsi @@ -53,25 +53,102 @@ }; soc { + + busfreq { /* BUSFREQ */ + compatible = "fsl,imx6_busfreq"; + clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>, + <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>, <&clks 22> , <&clks 8>; + clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph", + "periph_pre", "periph_clk2", "periph_clk2_sel", "osc", "axi_sel", "pll3_pfd1_540m"; + interrupts = <0 107 0x04>, <0 112 0x4>; + interrupt-names = "irq_busfreq_0", "irq_busfreq_1"; + fsl,max_ddr_freq = <400000000>; + }; + + gpu: gpu@00130000 { + compatible = "fsl,imx6dl-gpu", "fsl,imx6q-gpu"; + reg = <0x00130000 0x4000>, <0x00134000 0x4000>, + <0x0 0x0>; + reg-names = "iobase_3d", "iobase_2d", + "phys_baseaddr"; + interrupts = <0 9 0x04>, <0 10 0x04>; + interrupt-names = "irq_3d", "irq_2d"; + clocks = <&clks 143>, <&clks 27>, + <&clks 121>, <&clks 122>, + <&clks 0>; + clock-names = "gpu2d_axi_clk", "gpu3d_axi_clk", + "gpu2d_clk", "gpu3d_clk", + "gpu3d_shader_clk"; + resets = <&src 0>, <&src 3>; + reset-names = "gpu3d", "gpu2d"; + pu-supply = <®_pu>; + }; + ocram: sram@00900000 { compatible = "mmio-sram"; - reg = <0x00900000 0x20000>; + reg = <0x00904000 0x1C000>; clocks = <&clks 142>; }; + hdmi_core: hdmi_core@00120000 { + compatible = "fsl,imx6dl-hdmi-core"; + reg = <0x00120000 0x9000>; + clocks = <&clks 124>, <&clks 123>; + clock-names = "hdmi_isfr", "hdmi_iahb"; + status = "disabled"; + }; + + hdmi_video: hdmi_video@020e0000 { + compatible = "fsl,imx6dl-hdmi-video"; + reg = <0x020e0000 0x1000>; + reg-names = "hdmi_gpr"; + interrupts = <0 115 0x04>; + clocks = <&clks 124>, <&clks 123>; + clock-names = "hdmi_isfr", "hdmi_iahb"; + status = "disabled"; + }; + + hdmi_audio: hdmi_audio@00120000 { + compatible = "fsl,imx6dl-hdmi-audio"; + clocks = <&clks 124>, <&clks 123>; + clock-names = "hdmi_isfr", "hdmi_iahb"; + dmas = <&sdma 2 22 0>; + dma-names = "tx"; + status = "disabled"; + }; + + hdmi_cec: hdmi_cec@00120000 { + compatible = "fsl,imx6dl-hdmi-cec"; + interrupts = <0 115 0x04>; + status = "disabled"; + }; + aips1: aips-bus@02000000 { + vpu@02040000 { + compatible = "fsl,imx6dl-vpu"; + iramsize = <0>; + status = "okay"; + }; + iomuxc: iomuxc@020e0000 { compatible = "fsl,imx6dl-iomuxc"; }; pxp: pxp@020f0000 { + compatible = "fsl,imx6dl-pxp-dma"; reg = <0x020f0000 0x4000>; interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks 133>; + clock-names = "pxp-axi"; + status = "disabled"; }; epdc: epdc@020f4000 { + compatible = "fsl,imx6dl-epdc"; reg = <0x020f4000 0x4000>; interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks 133>, <&clks 137>; + clock-names = "epdc_axi", "epdc_pix"; }; lcdif: lcdif@020f8000 { @@ -81,13 +158,22 @@ }; aips2: aips-bus@02100000 { + mipi_dsi: mipi@021e0000 { + compatible = "fsl,imx6dl-mipi-dsi"; + reg = <0x021e0000 0x4000>; + interrupts = <0 102 0x04>; + gpr = <&gpr>; + clocks = <&clks 138>, <&clks 204>; + clock-names = "mipi_pllref_clk", "mipi_cfg_clk"; + status = "disabled"; + }; + i2c4: i2c@021f8000 { #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c"; reg = <0x021f8000 0x4000>; interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 116>; status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index addd3f881ce2..c346a7e88217 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -14,6 +14,7 @@ / { aliases { + ipu1 = &ipu2; spi4 = &ecspi5; }; @@ -75,12 +76,77 @@ }; soc { + + busfreq { /* BUSFREQ */ + compatible = "fsl,imx6_busfreq"; + clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>, + <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>; + clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph", + "periph_pre", "periph_clk2", "periph_clk2_sel", "osc"; + interrupts = <0 107 0x04>, <0 112 0x4>, <0 113 0x4>, <0 114 0x4>; + interrupt-names = "irq_busfreq_0", "irq_busfreq_1", "irq_busfreq_2", "irq_busfreq_3"; + fsl,max_ddr_freq = <528000000>; + }; + + gpu: gpu@00130000 { + compatible = "fsl,imx6q-gpu"; + reg = <0x00130000 0x4000>, <0x00134000 0x4000>, + <0x02204000 0x4000>, <0x0 0x0>; + reg-names = "iobase_3d", "iobase_2d", + "iobase_vg", "phys_baseaddr"; + interrupts = <0 9 0x04>, <0 10 0x04>,<0 11 0x04>; + interrupt-names = "irq_3d", "irq_2d", "irq_vg"; + clocks = <&clks 26>, <&clks 143>, + <&clks 27>, <&clks 121>, + <&clks 122>, <&clks 74>; + clock-names = "gpu2d_axi_clk", "openvg_axi_clk", + "gpu3d_axi_clk", "gpu2d_clk", + "gpu3d_clk", "gpu3d_shader_clk"; + resets = <&src 0>, <&src 3>, <&src 3>; + reset-names = "gpu3d", "gpu2d", "gpuvg"; + pu-supply = <®_pu>; + }; + ocram: sram@00900000 { compatible = "mmio-sram"; - reg = <0x00900000 0x40000>; + reg = <0x00904000 0x3C000>; clocks = <&clks 142>; }; + hdmi_core: hdmi_core@00120000 { + compatible = "fsl,imx6q-hdmi-core"; + reg = <0x00120000 0x9000>; + clocks = <&clks 124>, <&clks 123>; + clock-names = "hdmi_isfr", "hdmi_iahb"; + status = "disabled"; + }; + + hdmi_video: hdmi_video@020e0000 { + compatible = "fsl,imx6q-hdmi-video"; + reg = <0x020e0000 0x1000>; + reg-names = "hdmi_gpr"; + interrupts = <0 115 0x04>; + clocks = <&clks 124>, <&clks 123>; + clock-names = "hdmi_isfr", "hdmi_iahb"; + status = "disabled"; + }; + + hdmi_audio: hdmi_audio@00120000 { + compatible = "fsl,imx6q-hdmi-audio"; + clocks = <&clks 124>, <&clks 123>; + clock-names = "hdmi_isfr", "hdmi_iahb"; + dmas = <&sdma 2 22 0>; + dma-names = "tx"; + status = "disabled"; + }; + + hdmi_cec: hdmi_cec@00120000 { + compatible = "fsl,imx6q-hdmi-cec"; + interrupts = <0 115 0x04>; + status = "disabled"; + }; + + aips-bus@02000000 { /* AIPS1 */ spba-bus@02000000 { ecspi5: ecspi@02018000 { @@ -95,44 +161,25 @@ }; }; + vpu@02040000 { + compatible = "fsl,imx6q-vpu"; + status = "okay"; + }; + iomuxc: iomuxc@020e0000 { compatible = "fsl,imx6q-iomuxc"; + }; + }; - ipu2 { - pinctrl_ipu2_1: ipu2grp-1 { - fsl,pins = < - MX6QDL_PAD_DI0_DISP_CLK__IPU2_DI0_DISP_CLK 0x10 - MX6QDL_PAD_DI0_PIN15__IPU2_DI0_PIN15 0x10 - MX6QDL_PAD_DI0_PIN2__IPU2_DI0_PIN02 0x10 - MX6QDL_PAD_DI0_PIN3__IPU2_DI0_PIN03 0x10 - MX6QDL_PAD_DI0_PIN4__IPU2_DI0_PIN04 0x80000000 - MX6QDL_PAD_DISP0_DAT0__IPU2_DISP0_DATA00 0x10 - MX6QDL_PAD_DISP0_DAT1__IPU2_DISP0_DATA01 0x10 - MX6QDL_PAD_DISP0_DAT2__IPU2_DISP0_DATA02 0x10 - MX6QDL_PAD_DISP0_DAT3__IPU2_DISP0_DATA03 0x10 - MX6QDL_PAD_DISP0_DAT4__IPU2_DISP0_DATA04 0x10 - MX6QDL_PAD_DISP0_DAT5__IPU2_DISP0_DATA05 0x10 - MX6QDL_PAD_DISP0_DAT6__IPU2_DISP0_DATA06 0x10 - MX6QDL_PAD_DISP0_DAT7__IPU2_DISP0_DATA07 0x10 - MX6QDL_PAD_DISP0_DAT8__IPU2_DISP0_DATA08 0x10 - MX6QDL_PAD_DISP0_DAT9__IPU2_DISP0_DATA09 0x10 - MX6QDL_PAD_DISP0_DAT10__IPU2_DISP0_DATA10 0x10 - MX6QDL_PAD_DISP0_DAT11__IPU2_DISP0_DATA11 0x10 - MX6QDL_PAD_DISP0_DAT12__IPU2_DISP0_DATA12 0x10 - MX6QDL_PAD_DISP0_DAT13__IPU2_DISP0_DATA13 0x10 - MX6QDL_PAD_DISP0_DAT14__IPU2_DISP0_DATA14 0x10 - MX6QDL_PAD_DISP0_DAT15__IPU2_DISP0_DATA15 0x10 - MX6QDL_PAD_DISP0_DAT16__IPU2_DISP0_DATA16 0x10 - MX6QDL_PAD_DISP0_DAT17__IPU2_DISP0_DATA17 0x10 - MX6QDL_PAD_DISP0_DAT18__IPU2_DISP0_DATA18 0x10 - MX6QDL_PAD_DISP0_DAT19__IPU2_DISP0_DATA19 0x10 - MX6QDL_PAD_DISP0_DAT20__IPU2_DISP0_DATA20 0x10 - MX6QDL_PAD_DISP0_DAT21__IPU2_DISP0_DATA21 0x10 - MX6QDL_PAD_DISP0_DAT22__IPU2_DISP0_DATA22 0x10 - MX6QDL_PAD_DISP0_DAT23__IPU2_DISP0_DATA23 0x10 - >; - }; - }; + aips-bus@02100000 { /* AIPS2 */ + mipi_dsi: mipi@021e0000 { + compatible = "fsl,imx6q-mipi-dsi"; + reg = <0x021e0000 0x4000>; + interrupts = <0 102 0x04>; + gpr = <&gpr>; + clocks = <&clks 138>, <&clks 204>; + clock-names = "mipi_pllref_clk", "mipi_cfg_clk"; + status = "disabled"; }; }; @@ -152,9 +199,14 @@ reg = <0x02800000 0x400000>; interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>, <0 7 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 133>, <&clks 134>, <&clks 137>; - clock-names = "bus", "di0", "di1"; + clocks = <&clks 133>, <&clks 134>, <&clks 137>, + <&clks 41>, <&clks 42>, + <&clks 135>, <&clks 136>; + clock-names = "bus", "di0", "di1", + "di0_sel", "di1_sel", + "ldb_di0", "ldb_di1"; resets = <&src 4>; + bypass_reset = <0>; ipu2_di0: port@2 { #address-cells = <1>; @@ -230,13 +282,6 @@ }; &ldb { - clocks = <&clks 33>, <&clks 34>, - <&clks 39>, <&clks 40>, <&clks 41>, <&clks 42>, - <&clks 135>, <&clks 136>; - clock-names = "di0_pll", "di1_pll", - "di0_sel", "di1_sel", "di2_sel", "di3_sel", - "di0", "di1"; - lvds-channel@0 { port@2 { reg = <2>; diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi index 2105c785a834..8f817c06912f 100644 --- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi +++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi @@ -179,6 +179,11 @@ mux-int-port = <1>; mux-ext-port = <5>; }; + + v4l2_out { + compatible = "fsl,mxc_v4l2_output"; + status = "okay"; + }; }; &audmux { diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 13d8db9975f6..143cd65cff08 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -26,6 +26,7 @@ gpio4 = &gpio5; gpio5 = &gpio6; gpio6 = &gpio7; + ipu0 = &ipu1; i2c0 = &i2c1; i2c1 = &i2c2; i2c2 = &i2c3; @@ -257,8 +258,14 @@ }; esai: esai@02024000 { + compatible = "fsl,imx6q-esai"; reg = <0x02024000 0x4000>; interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks 118>, <&clks 156>; + clock-names = "core", "dma"; + fsl,esai-dma-events = <24 23>; + fsl,flags = <1>; + status = "disabled"; }; ssi1: ssi@02028000 { @@ -318,8 +325,17 @@ vpu: vpu@02040000 { reg = <0x02040000 0x3c000>; + reg-names = "vpu_regs"; interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>, <0 12 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "vpu_jpu_irq", "vpu_ipi_irq"; + clocks = <&clks 168>, <&clks 140>, <&clks 142>; + clock-names = "vpu_clk", "mmdc_ch0_axi", "ocram"; + iramsize = <0x21000>; + iram = <&ocram>; + resets = <&src 1>; + pu-supply = <®_pu>; + status = "disabled"; }; aipstz@0207c000 { /* AIPSTZ1 */ @@ -673,6 +689,19 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb"; + reg = <0x020e0000 0x4000>; + clocks = <&clks 135>, <&clks 136>, + <&clks 39>, <&clks 40>, + <&clks 41>, <&clks 42>, + <&clks 184>, <&clks 185>, + <&clks 205>, <&clks 206>, + <&clks 207>, <&clks 208>; + clock-names = "ldb_di0", "ldb_di1", + "ipu1_di0_sel", "ipu1_di1_sel", + "ipu2_di0_sel", "ipu2_di1_sel", + "di0_div_3_5", "di1_div_3_5", + "di0_div_7", "di1_div_7", + "di0_div_sel", "di1_div_sel"; gpr = <&gpr>; status = "disabled"; @@ -1046,9 +1075,14 @@ reg = <0x02400000 0x400000>; interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>, <0 5 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 130>, <&clks 131>, <&clks 132>; - clock-names = "bus", "di0", "di1"; + clocks = <&clks 130>, <&clks 131>, <&clks 132>, + <&clks 39>, <&clks 40>, + <&clks 135>, <&clks 136>; + clock-names = "bus", "di0", "di1", + "di0_sel", "di1_sel", + "ldb_di0", "ldb_di1"; resets = <&src 2>; + bypass_reset = <0>; ipu1_di0: port@2 { #address-cells = <1>; diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h index ec75c883c7f5..a3c24cd5b7c8 100644 --- a/arch/arm/include/asm/glue-cache.h +++ b/arch/arm/include/asm/glue-cache.h @@ -102,19 +102,19 @@ #endif #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) -//# ifdef _CACHE +# ifdef _CACHE # define MULTI_CACHE 1 -//# else -//# define _CACHE v6 -//# endif +# else +# define _CACHE v6 +# endif #endif #if defined(CONFIG_CPU_V7) -//# ifdef _CACHE +# ifdef _CACHE # define MULTI_CACHE 1 -//# else -//# define _CACHE v7 -//# endif +# else +# define _CACHE v7 +# endif #endif #if defined(CONFIG_CPU_V7M) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 60e14ee278f7..ffe350f86bca 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -102,18 +102,6 @@ config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE Be aware that not all cpufreq drivers support the conservative governor. If unsure have a look at the help section of the driver. Fallback governor will be the performance governor. - -config CPU_FREQ_DEFAULT_GOV_INTERACTIVE - bool "interactive" - select CPU_FREQ_GOV_INTERACTIVE - select CPU_FREQ_GOV_PERFORMANCE - help - Use the CPUFreq governor 'interactive' as default. This allows - you to get a full dynamic cpu frequency capable system by simply - loading your cpufreq low-level hardware driver, using the - 'interactive' governor for latency-sensitive workloads. Fallback - governor will be the performance governor. - endchoice config CPU_FREQ_GOV_PERFORMANCE @@ -195,23 +183,6 @@ config CPU_FREQ_GOV_CONSERVATIVE If in doubt, say N. -config CPU_FREQ_GOV_INTERACTIVE - tristate "'interactive' cpufreq policy governor" - help - 'interactive' - This driver adds a dynamic cpufreq policy governor - designed for latency-sensitive workloads. - - This governor attempts to reduce the latency of clock - increases so that the system is more responsive to - interactive workloads. - - To compile this driver as a module, choose M here: the - module will be called cpufreq_interactive. - - For details, take a look at linux/Documentation/cpu-freq. - - If in doubt, say N. - config GENERIC_CPUFREQ_CPU0 tristate "Generic CPU0 cpufreq driver" depends on HAVE_CLK && OF diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 946281eb28a8..db6d9a2fea4d 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o -obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_GENERIC_CPUFREQ_CPU0) += cpufreq-cpu0.o diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c deleted file mode 100644 index 9a6f64f56962..000000000000 --- a/drivers/cpufreq/cpufreq_interactive.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * drivers/cpufreq/cpufreq_interactive.c - * - * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * - * Author: Mike Chan (mike@android.com) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static atomic_t active_count = ATOMIC_INIT(0); - -struct cpufreq_interactive_cpuinfo { - struct timer_list cpu_timer; - int timer_idlecancel; - u64 time_in_idle; - u64 idle_exit_time; - u64 timer_run_time; - int idling; - u64 freq_change_time; - u64 freq_change_time_in_idle; - struct cpufreq_policy *policy; - struct cpufreq_frequency_table *freq_table; - unsigned int target_freq; - int governor_enabled; -}; - -static DEFINE_PER_CPU(struct cpufreq_interactive_cpuinfo, cpuinfo); - -/* Workqueues handle frequency scaling */ -static struct task_struct *up_task; -static struct workqueue_struct *down_wq; -static struct work_struct freq_scale_down_work; -static cpumask_t up_cpumask; -static spinlock_t up_cpumask_lock; -static cpumask_t down_cpumask; -static spinlock_t down_cpumask_lock; -static struct mutex set_speed_lock; - -/* Hi speed to bump to from lo speed when load burst (default max) */ -static u64 hispeed_freq; - -/* Go to hi speed when CPU load at or above this value. */ -#define DEFAULT_GO_HISPEED_LOAD 95 -static unsigned long go_hispeed_load; - -/* - * The minimum amount of time to spend at a frequency before we can ramp down. - */ -#define DEFAULT_MIN_SAMPLE_TIME (20 * USEC_PER_MSEC) -static unsigned long min_sample_time; - -/* - * The sample rate of the timer used to increase frequency - */ -#define DEFAULT_TIMER_RATE (50 * USEC_PER_MSEC) -#define CPUFREQ_IRQ_LEN 60 -#define CPUFREQ_NOTE_LEN 120 -static unsigned long timer_rate; - -static int cpufreq_governor_interactive(struct cpufreq_policy *policy, - unsigned int event); - -#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE -static -#endif -struct cpufreq_governor cpufreq_gov_interactive = { - .name = "interactive", - .governor = cpufreq_governor_interactive, - .max_transition_latency = 10000000, - .owner = THIS_MODULE, -}; - -static void cpufreq_interactive_timer(unsigned long data) -{ - unsigned int delta_idle; - unsigned int delta_time; - int cpu_load; - int load_since_change; - u64 time_in_idle; - u64 idle_exit_time; - struct cpufreq_interactive_cpuinfo *pcpu = - &per_cpu(cpuinfo, data); - u64 now_idle; - unsigned int new_freq; - unsigned int index; - unsigned long flags; - - smp_rmb(); - - if (!pcpu->governor_enabled) - goto exit; - - /* - * Once pcpu->timer_run_time is updated to >= pcpu->idle_exit_time, - * this lets idle exit know the current idle time sample has - * been processed, and idle exit can generate a new sample and - * re-arm the timer. This prevents a concurrent idle - * exit on that CPU from writing a new set of info at the same time - * the timer function runs (the timer function can't use that info - * until more time passes). - */ - time_in_idle = pcpu->time_in_idle; - idle_exit_time = pcpu->idle_exit_time; - now_idle = get_cpu_idle_time_us(data, &pcpu->timer_run_time); - smp_wmb(); - - /* If we raced with cancelling a timer, skip. */ - if (!idle_exit_time) - goto exit; - - delta_idle = (unsigned int)(now_idle - time_in_idle); - delta_time = (unsigned int)(pcpu->timer_run_time - idle_exit_time); - - /* - * If timer ran less than 1ms after short-term sample started, retry. - */ - if (delta_time < 1000) - goto rearm; - - if (delta_idle > delta_time) - cpu_load = 0; - else - cpu_load = 100 * (delta_time - delta_idle) / delta_time; - - delta_idle = (unsigned int)(now_idle - pcpu->freq_change_time_in_idle); - delta_time = (unsigned int)(pcpu->timer_run_time - - pcpu->freq_change_time); - - if ((delta_time == 0) || (delta_idle > delta_time)) - load_since_change = 0; - else - load_since_change = - 100 * (delta_time - delta_idle) / delta_time; - - /* - * Choose greater of short-term load (since last idle timer - * started or timer function re-armed itself) or long-term load - * (since last frequency change). - */ - if (load_since_change > cpu_load) - cpu_load = load_since_change; - - if (cpu_load >= go_hispeed_load) { - if (pcpu->policy->cur == pcpu->policy->min) - new_freq = hispeed_freq; - else - new_freq = pcpu->policy->max * cpu_load / 100; - } else { - new_freq = pcpu->policy->cur * cpu_load / 100; - } - - if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table, - new_freq, CPUFREQ_RELATION_H, - &index)) { - pr_warn_once("timer %d: cpufreq_frequency_table_target error\n", - (int) data); - goto rearm; - } - - new_freq = pcpu->freq_table[index].frequency; - if (pcpu->target_freq == new_freq) - goto rearm_if_notmax; - - /* - * Do not scale down unless we have been at this frequency for the - * minimum sample time. - */ - if (new_freq < pcpu->target_freq) { - if ((pcpu->timer_run_time - pcpu->freq_change_time) - < min_sample_time) - goto rearm; - } - - if (new_freq < pcpu->target_freq) { - pcpu->target_freq = new_freq; - spin_lock_irqsave(&down_cpumask_lock, flags); - cpumask_set_cpu(data, &down_cpumask); - spin_unlock_irqrestore(&down_cpumask_lock, flags); - queue_work(down_wq, &freq_scale_down_work); - } else { - pcpu->target_freq = new_freq; - spin_lock_irqsave(&up_cpumask_lock, flags); - cpumask_set_cpu(data, &up_cpumask); - spin_unlock_irqrestore(&up_cpumask_lock, flags); - wake_up_process(up_task); - } - -rearm_if_notmax: - /* - * Already set max speed and don't see a need to change that, - * wait until next idle to re-evaluate, don't need timer. - */ - if (pcpu->target_freq == pcpu->policy->max) - goto exit; - -rearm: - if (!timer_pending(&pcpu->cpu_timer)) { - /* - * If already at min: if that CPU is idle, don't set timer. - * Else cancel the timer if that CPU goes idle. We don't - * need to re-evaluate speed until the next idle exit. - */ - if (pcpu->target_freq == pcpu->policy->min) { - smp_rmb(); - - if (pcpu->idling) - goto exit; - - pcpu->timer_idlecancel = 1; - } - - pcpu->time_in_idle = get_cpu_idle_time_us( - data, &pcpu->idle_exit_time); - mod_timer(&pcpu->cpu_timer, - jiffies + usecs_to_jiffies(timer_rate)); - } - -exit: - return; -} - -static void cpufreq_interactive_idle_start(void) -{ - struct cpufreq_interactive_cpuinfo *pcpu = - &per_cpu(cpuinfo, smp_processor_id()); - int pending; - - pcpu->idling = 1; - smp_wmb(); - if (!pcpu->governor_enabled) - return; - pending = timer_pending(&pcpu->cpu_timer); - - if (pcpu->target_freq != pcpu->policy->min) { -#ifdef CONFIG_SMP - /* - * Entering idle while not at lowest speed. On some - * platforms this can hold the other CPU(s) at that speed - * even though the CPU is idle. Set a timer to re-evaluate - * speed so this idle CPU doesn't hold the other CPUs above - * min indefinitely. This should probably be a quirk of - * the CPUFreq driver. - */ - if (!pending) { - pcpu->time_in_idle = get_cpu_idle_time_us( - smp_processor_id(), &pcpu->idle_exit_time); - pcpu->timer_idlecancel = 0; - mod_timer(&pcpu->cpu_timer, - jiffies + usecs_to_jiffies(timer_rate)); - } -#endif - } else { - /* - * If at min speed and entering idle after load has - * already been evaluated, and a timer has been set just in - * case the CPU suddenly goes busy, cancel that timer. The - * CPU didn't go busy; we'll recheck things upon idle exit. - */ - if (pending && pcpu->timer_idlecancel) { - del_timer(&pcpu->cpu_timer); - /* - * Ensure last timer run time is after current idle - * sample start time, so next idle exit will always - * start a new idle sampling period. - */ - pcpu->idle_exit_time = 0; - pcpu->timer_idlecancel = 0; - } - } - -} - -static void cpufreq_interactive_idle_end(void) -{ - struct cpufreq_interactive_cpuinfo *pcpu = - &per_cpu(cpuinfo, smp_processor_id()); - - pcpu->idling = 0; - smp_wmb(); - - /* - * Arm the timer for 1-2 ticks later if not already, and if the timer - * function has already processed the previous load sampling - * interval. (If the timer is not pending but has not processed - * the previous interval, it is probably racing with us on another - * CPU. Let it compute load based on the previous sample and then - * re-arm the timer for another interval when it's done, rather - * than updating the interval start time to be "now", which doesn't - * give the timer function enough time to make a decision on this - * run.) - */ - if (timer_pending(&pcpu->cpu_timer) == 0 && - pcpu->timer_run_time >= pcpu->idle_exit_time && - pcpu->governor_enabled) { - pcpu->time_in_idle = - get_cpu_idle_time_us(smp_processor_id(), - &pcpu->idle_exit_time); - pcpu->timer_idlecancel = 0; - mod_timer(&pcpu->cpu_timer, - jiffies + usecs_to_jiffies(timer_rate)); - } - -} - -static int cpufreq_interactive_up_task(void *data) -{ - unsigned int cpu; - unsigned long flags; - struct cpufreq_interactive_cpuinfo *pcpu; - - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - spin_lock_irqsave(&up_cpumask_lock, flags); - - if (cpumask_empty(&up_cpumask)) { - spin_unlock_irqrestore(&up_cpumask_lock, flags); - schedule(); - - if (kthread_should_stop()) - break; - - spin_lock_irqsave(&up_cpumask_lock, flags); - } - - set_current_state(TASK_RUNNING); - cpumask_clear(&up_cpumask); - spin_unlock_irqrestore(&up_cpumask_lock, flags); - - for_each_online_cpu(cpu) { - unsigned int j; - unsigned int max_freq = 0; - - pcpu = &per_cpu(cpuinfo, cpu); - smp_rmb(); - - if (!pcpu->governor_enabled) - continue; - - mutex_lock(&set_speed_lock); - - for_each_online_cpu(j) { - struct cpufreq_interactive_cpuinfo *pjcpu = - &per_cpu(cpuinfo, j); - if (pjcpu->target_freq > max_freq) - max_freq = pjcpu->target_freq; - } - if (max_freq != pcpu->policy->cur) - __cpufreq_driver_target(pcpu->policy, - max_freq, - CPUFREQ_RELATION_H); - mutex_unlock(&set_speed_lock); - - pcpu->freq_change_time_in_idle = - get_cpu_idle_time_us(cpu, - &pcpu->freq_change_time); - } - } - - return 0; -} - -static void cpufreq_interactive_freq_down(struct work_struct *work) -{ - unsigned int cpu; - unsigned long flags; - struct cpufreq_interactive_cpuinfo *pcpu; - - spin_lock_irqsave(&down_cpumask_lock, flags); - cpumask_clear(&down_cpumask); - spin_unlock_irqrestore(&down_cpumask_lock, flags); - - for_each_online_cpu(cpu) { - unsigned int j; - unsigned int max_freq = 0; - - pcpu = &per_cpu(cpuinfo, cpu); - smp_rmb(); - - if (!pcpu->governor_enabled) - continue; - - mutex_lock(&set_speed_lock); - - for_each_online_cpu(j) { - struct cpufreq_interactive_cpuinfo *pjcpu = - &per_cpu(cpuinfo, j); - - if (pjcpu->target_freq > max_freq) - max_freq = pjcpu->target_freq; - } - - if (max_freq != pcpu->policy->cur) - __cpufreq_driver_target(pcpu->policy, max_freq, - CPUFREQ_RELATION_H); - - mutex_unlock(&set_speed_lock); - pcpu->freq_change_time_in_idle = - get_cpu_idle_time_us(cpu, - &pcpu->freq_change_time); - } -} - -static ssize_t show_hispeed_freq(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - return sprintf(buf, "%llu\n", hispeed_freq); -} - -static ssize_t store_hispeed_freq(struct kobject *kobj, - struct attribute *attr, const char *buf, - size_t count) -{ - int ret; - u64 val; - - ret = strict_strtoull(buf, 0, &val); - if (ret < 0) - return ret; - hispeed_freq = val; - return count; -} - -static struct global_attr hispeed_freq_attr = __ATTR(hispeed_freq, 0644, - show_hispeed_freq, store_hispeed_freq); - - -static ssize_t show_go_hispeed_load(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - return sprintf(buf, "%lu\n", go_hispeed_load); -} - -static ssize_t store_go_hispeed_load(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t count) -{ - int ret; - unsigned long val; - - ret = strict_strtoul(buf, 0, &val); - if (ret < 0) - return ret; - go_hispeed_load = val; - return count; -} - -static struct global_attr go_hispeed_load_attr = __ATTR(go_hispeed_load, 0644, - show_go_hispeed_load, store_go_hispeed_load); - -static ssize_t show_min_sample_time(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - return sprintf(buf, "%lu\n", min_sample_time); -} - -static ssize_t store_min_sample_time(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t count) -{ - int ret; - unsigned long val; - - ret = strict_strtoul(buf, 0, &val); - if (ret < 0) - return ret; - min_sample_time = val; - return count; -} - -static struct global_attr min_sample_time_attr = __ATTR(min_sample_time, 0644, - show_min_sample_time, store_min_sample_time); - -static ssize_t show_timer_rate(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - return sprintf(buf, "%lu\n", timer_rate); -} - -static ssize_t store_timer_rate(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t count) -{ - int ret; - unsigned long val; - - ret = strict_strtoul(buf, 0, &val); - if (ret < 0) - return ret; - timer_rate = val; - return count; -} - -static struct global_attr timer_rate_attr = __ATTR(timer_rate, 0644, - show_timer_rate, store_timer_rate); - -static struct attribute *interactive_attributes[] = { - &hispeed_freq_attr.attr, - &go_hispeed_load_attr.attr, - &min_sample_time_attr.attr, - &timer_rate_attr.attr, - NULL, -}; - -static struct attribute_group interactive_attr_group = { - .attrs = interactive_attributes, - .name = "interactive", -}; - -static int cpufreq_governor_interactive(struct cpufreq_policy *policy, - unsigned int event) -{ - int rc; - unsigned int j; - struct cpufreq_interactive_cpuinfo *pcpu; - struct cpufreq_frequency_table *freq_table; - - switch (event) { - case CPUFREQ_GOV_START: - if (!cpu_online(policy->cpu)) - return -EINVAL; - - freq_table = - cpufreq_frequency_get_table(policy->cpu); - - for_each_cpu(j, policy->cpus) { - pcpu = &per_cpu(cpuinfo, j); - pcpu->policy = policy; - if (pcpu->idling) - pcpu->target_freq = policy->min; - else - pcpu->target_freq = policy->cur; - - pcpu->freq_table = freq_table; - pcpu->freq_change_time_in_idle = - get_cpu_idle_time_us(j, - &pcpu->freq_change_time); - pcpu->governor_enabled = 1; - smp_wmb(); - } - - if (!hispeed_freq) - hispeed_freq = policy->max; - - /* - * Do not register the idle hook and create sysfs - * entries if we have already done so. - */ - if (atomic_inc_return(&active_count) > 1) - return 0; - - rc = sysfs_create_group(cpufreq_global_kobject, - &interactive_attr_group); - if (rc) - return rc; - - break; - - case CPUFREQ_GOV_STOP: - for_each_cpu(j, policy->cpus) { - pcpu = &per_cpu(cpuinfo, j); - pcpu->governor_enabled = 0; - smp_wmb(); - del_timer_sync(&pcpu->cpu_timer); - - /* - * Reset idle exit time since we may cancel the timer - * before it can run after the last idle exit time, - * to avoid tripping the check in idle exit for a timer - * that is trying to run. - */ - pcpu->idle_exit_time = 0; - } - - flush_work(&freq_scale_down_work); - if (atomic_dec_return(&active_count) > 0) - return 0; - - sysfs_remove_group(cpufreq_global_kobject, - &interactive_attr_group); - - break; - - case CPUFREQ_GOV_LIMITS: - if (policy->max < policy->cur) - __cpufreq_driver_target(policy, - policy->max, CPUFREQ_RELATION_H); - else if (policy->min > policy->cur) - __cpufreq_driver_target(policy, - policy->min, CPUFREQ_RELATION_L); - break; - } - return 0; -} - -static int cpufreq_interactive_idle_notifier(struct notifier_block *nb, - unsigned long val, - void *data) -{ - switch (val) { - case IDLE_START: - cpufreq_interactive_idle_start(); - break; - case IDLE_END: - cpufreq_interactive_idle_end(); - break; - } - - return 0; -} - -static struct notifier_block cpufreq_interactive_idle_nb = { - .notifier_call = cpufreq_interactive_idle_notifier, -}; - -static int __init cpufreq_interactive_init(void) -{ - unsigned int i; - struct cpufreq_interactive_cpuinfo *pcpu; - struct sched_param param = { .sched_priority = 99 }; - - go_hispeed_load = DEFAULT_GO_HISPEED_LOAD; - min_sample_time = DEFAULT_MIN_SAMPLE_TIME; - timer_rate = DEFAULT_TIMER_RATE; - - /* Initalize per-cpu timers */ - for_each_possible_cpu(i) { - pcpu = &per_cpu(cpuinfo, i); - init_timer(&pcpu->cpu_timer); - pcpu->cpu_timer.function = cpufreq_interactive_timer; - pcpu->cpu_timer.data = i; - } - - up_task = kthread_create(cpufreq_interactive_up_task, NULL, - "kinteractiveup"); - if (IS_ERR(up_task)) - return PTR_ERR(up_task); - - sched_setscheduler_nocheck(up_task, SCHED_FIFO, ¶m); - get_task_struct(up_task); - - /* No rescuer thread, bind to CPU queuing the work for possibly - warm cache (probably doesn't matter much). */ - down_wq = alloc_workqueue("kinteractive_down", 0, 1); - - if (!down_wq) - goto err_freeuptask; - - INIT_WORK(&freq_scale_down_work, - cpufreq_interactive_freq_down); - - spin_lock_init(&up_cpumask_lock); - spin_lock_init(&down_cpumask_lock); - mutex_init(&set_speed_lock); - - idle_notifier_register(&cpufreq_interactive_idle_nb); - - return cpufreq_register_governor(&cpufreq_gov_interactive); - -err_freeuptask: - put_task_struct(up_task); - return -ENOMEM; -} - -#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE -late_initcall(cpufreq_interactive_init); -#else -module_init(cpufreq_interactive_init); -#endif - -static void __exit cpufreq_interactive_exit(void) -{ - cpufreq_unregister_governor(&cpufreq_gov_interactive); - kthread_stop(up_task); - put_task_struct(up_task); - destroy_workqueue(down_wq); -} - -module_exit(cpufreq_interactive_exit); - -MODULE_AUTHOR("Mike Chan "); -MODULE_DESCRIPTION("'cpufreq_interactive' - A cpufreq governor for " - "Latency sensitive workloads"); -MODULE_LICENSE("GPL"); diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 3a7c6009fee9..14867e3ac8ff 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -745,8 +745,8 @@ static void sdma_get_pc(struct sdma_channel *sdmac, emi_2_per = sdma->script_addrs->mcu_2_shp_addr; break; case IMX_DMATYPE_ASRC: - per_2_emi = sdma->script_addrs->shp_2_mcu_addr; - emi_2_per = sdma->script_addrs->mcu_2_shp_addr; + per_2_emi = sdma->script_addrs->asrc_2_mcu_addr; + emi_2_per = sdma->script_addrs->asrc_2_mcu_addr; per_2_per = sdma->script_addrs->per_2_per_addr; break; case IMX_DMATYPE_MSHC: diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index c6b2cce327dc..63185c88c81f 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -1,24 +1,3 @@ -############################################################################## -# -# Copyright (C) 2005 - 2013 by Vivante Corp. -# -# 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. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -############################################################################## - - # # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 24cdc2742068..02d3d85829f3 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1652,18 +1652,4 @@ config SENSORS_ATK0110 endif # ACPI -config SENSORS_MAG3110 - tristate "Freescale MAG3110 e-compass sensor" - depends on I2C && SYSFS - help - If you say yes here you get support for the Freescale MAG3110 - e-compass sensor. - This driver can also be built as a module. If so, the module - will be called mag3110. - -config MXC_MMA8451 - tristate "MMA8451 device driver" - depends on I2C - default y - endif # HWMON diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 782464be7e3a..3dc0f02f71d2 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -148,8 +148,6 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o -obj-$(CONFIG_SENSORS_MAG3110) += mag3110.o -obj-$(CONFIG_MXC_MMA8451) += mxc_mma8451.o obj-$(CONFIG_PMBUS) += pmbus/ diff --git a/drivers/hwmon/mag3110.c b/drivers/hwmon/mag3110.c deleted file mode 100755 index 9d7f617bcaef..000000000000 --- a/drivers/hwmon/mag3110.c +++ /dev/null @@ -1,611 +0,0 @@ -/* - * - * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. - * - * 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. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAG3110_DRV_NAME "mag3110" -#define MAG3110_ID 0xC4 -#define MAG3110_XYZ_DATA_LEN 6 -#define MAG3110_STATUS_ZYXDR 0x08 - -#define MAG3110_AC_MASK (0x01) -#define MAG3110_AC_OFFSET 0 -#define MAG3110_DR_MODE_MASK (0x7 << 5) -#define MAG3110_DR_MODE_OFFSET 5 -#define MAG3110_IRQ_USED 0 - -#define POLL_INTERVAL_MAX 500 -#define POLL_INTERVAL 100 -#define INT_TIMEOUT 1000 -#define DEFAULT_POSITION 2 -/* register enum for mag3110 registers */ -enum { - MAG3110_DR_STATUS = 0x00, - MAG3110_OUT_X_MSB, - MAG3110_OUT_X_LSB, - MAG3110_OUT_Y_MSB, - MAG3110_OUT_Y_LSB, - MAG3110_OUT_Z_MSB, - MAG3110_OUT_Z_LSB, - MAG3110_WHO_AM_I, - - MAG3110_OFF_X_MSB, - MAG3110_OFF_X_LSB, - MAG3110_OFF_Y_MSB, - MAG3110_OFF_Y_LSB, - MAG3110_OFF_Z_MSB, - MAG3110_OFF_Z_LSB, - - MAG3110_DIE_TEMP, - - MAG3110_CTRL_REG1 = 0x10, - MAG3110_CTRL_REG2, -}; -enum { - MAG_STANDBY, - MAG_ACTIVED -}; -struct mag3110_data { - struct i2c_client *client; - struct input_polled_dev *poll_dev; - struct device *hwmon_dev; - wait_queue_head_t waitq; - bool data_ready; - u8 ctl_reg1; - int active; - int position; -}; -static short MAGHAL[8][3][3] = { - { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} }, - { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }, - { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} }, - { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} }, - - { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} }, - { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} }, - { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} }, - { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} }, -}; - -static struct mag3110_data *mag3110_pdata; -/*! - * This function do one mag3110 register read. - */ -static DEFINE_MUTEX(mag3110_lock); -static int mag3110_adjust_position(short *x, short *y, short *z) -{ - short rawdata[3], data[3]; - int i, j; - int position = mag3110_pdata->position; - if (position < 0 || position > 7) - position = 0; - rawdata[0] = *x; - rawdata[1] = *y; - rawdata[2] = *z; - for (i = 0; i < 3; i++) { - data[i] = 0; - for (j = 0; j < 3; j++) - data[i] += rawdata[j] * MAGHAL[position][i][j]; - } - *x = data[0]; - *y = data[1]; - *z = data[2]; - return 0; -} - -static int mag3110_read_reg(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -/*! - * This function do one mag3110 register write. - */ -static int mag3110_write_reg(struct i2c_client *client, u8 reg, char value) -{ - int ret; - - ret = i2c_smbus_write_byte_data(client, reg, value); - if (ret < 0) - dev_err(&client->dev, "i2c write failed\n"); - return ret; -} - -/*! - * This function do multiple mag3110 registers read. - */ -static int mag3110_read_block_data(struct i2c_client *client, u8 reg, - int count, u8 *addr) -{ - if (i2c_smbus_read_i2c_block_data(client, reg, count, addr) < count) { - dev_err(&client->dev, "i2c block read failed\n"); - return -1; - } - - return count; -} - -/* - * Initialization function - */ -static int mag3110_init_client(struct i2c_client *client) -{ - int val, ret; - - /* enable automatic resets */ - val = 0x80; - ret = mag3110_write_reg(client, MAG3110_CTRL_REG2, val); - - /* set default data rate to 10HZ */ - val = mag3110_read_reg(client, MAG3110_CTRL_REG1); - val |= (0x0 << MAG3110_DR_MODE_OFFSET); - ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, val); - - return ret; -} - -/*************************************************************** -* -* read sensor data from mag3110 -* -***************************************************************/ -static int mag3110_read_data(short *x, short *y, short *z) -{ - struct mag3110_data *data; - int retry = 3; - u8 tmp_data[MAG3110_XYZ_DATA_LEN]; - int result; - if (!mag3110_pdata || mag3110_pdata->active == MAG_STANDBY) - return -EINVAL; - - data = mag3110_pdata; -#if MAG3110_IRQ_USED - if (!wait_event_interruptible_timeout - (data->waitq, data->data_ready != 0, - msecs_to_jiffies(INT_TIMEOUT))) { - dev_dbg(&data->client->dev, "interrupt not received\n"); - return -ETIME; - } -#else - do { - msleep(1); - result = i2c_smbus_read_byte_data(data->client, - MAG3110_DR_STATUS); - retry--; - } while (!(result & MAG3110_STATUS_ZYXDR) && retry > 0); - /* Clear data_ready flag after data is read out */ - if (retry == 0) - return -EINVAL; -#endif - - data->data_ready = 0; - - if (mag3110_read_block_data(data->client, - MAG3110_OUT_X_MSB, MAG3110_XYZ_DATA_LEN, - tmp_data) < 0) - return -1; - - *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1]; - *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3]; - *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5]; - - return 0; -} - -static void report_abs(void) -{ - struct input_dev *idev; - short x, y, z; - - mutex_lock(&mag3110_lock); - if (mag3110_read_data(&x, &y, &z) != 0) - goto out; - mag3110_adjust_position(&x, &y, &z); - idev = mag3110_pdata->poll_dev->input; - input_report_abs(idev, ABS_X, x); - input_report_abs(idev, ABS_Y, y); - input_report_abs(idev, ABS_Z, z); - input_sync(idev); -out: - mutex_unlock(&mag3110_lock); -} - -static void mag3110_dev_poll(struct input_polled_dev *dev) -{ - report_abs(); -} - -#if MAG3110_IRQ_USED -static irqreturn_t mag3110_irq_handler(int irq, void *dev_id) -{ - mag3110_pdata->data_ready = 1; - wake_up_interruptible(&mag3110_pdata->waitq); - - return IRQ_HANDLED; -} -#endif -static ssize_t mag3110_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_client *client; - int val; - mutex_lock(&mag3110_lock); - client = mag3110_pdata->client; - val = mag3110_read_reg(client, MAG3110_CTRL_REG1) & MAG3110_AC_MASK; - - mutex_unlock(&mag3110_lock); - return sprintf(buf, "%d\n", val); -} - -static ssize_t mag3110_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client; - int reg, ret; - long enable; - u8 tmp_data[MAG3110_XYZ_DATA_LEN]; - - ret = strict_strtol(buf, 10, &enable); - if (ret) { - dev_err(dev, "string to long error\n"); - return ret; - } - - mutex_lock(&mag3110_lock); - client = mag3110_pdata->client; - reg = mag3110_read_reg(client, MAG3110_CTRL_REG1); - if (enable && mag3110_pdata->active == MAG_STANDBY) { - reg |= MAG3110_AC_MASK; - ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg); - if (!ret) - mag3110_pdata->active = MAG_ACTIVED; - } else if (!enable && mag3110_pdata->active == MAG_ACTIVED) { - reg &= ~MAG3110_AC_MASK; - ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg); - if (!ret) - mag3110_pdata->active = MAG_STANDBY; - } - - if (mag3110_pdata->active == MAG_ACTIVED) { - msleep(100); - /* Read out MSB data to clear interrupt flag automatically */ - mag3110_read_block_data(client, MAG3110_OUT_X_MSB, - MAG3110_XYZ_DATA_LEN, tmp_data); - } - mutex_unlock(&mag3110_lock); - return count; -} - -static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, - mag3110_enable_show, mag3110_enable_store); - -static ssize_t mag3110_dr_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_client *client; - int val; - - client = mag3110_pdata->client; - val = (mag3110_read_reg(client, MAG3110_CTRL_REG1) - & MAG3110_DR_MODE_MASK) >> MAG3110_DR_MODE_OFFSET; - - return sprintf(buf, "%d\n", val); -} - -static ssize_t mag3110_dr_mode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client; - int reg, ret; - unsigned long val; - - /* This must be done when mag3110 is disabled */ - if ((strict_strtoul(buf, 10, &val) < 0) || (val > 7)) - return -EINVAL; - - client = mag3110_pdata->client; - reg = mag3110_read_reg(client, MAG3110_CTRL_REG1) & - ~MAG3110_DR_MODE_MASK; - reg |= (val << MAG3110_DR_MODE_OFFSET); - /* MAG3110_CTRL_REG1 bit 5-7: data rate mode */ - ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg); - if (ret < 0) - return ret; - - return count; -} - -static DEVICE_ATTR(dr_mode, S_IWUSR | S_IRUGO, - mag3110_dr_mode_show, mag3110_dr_mode_store); - -static ssize_t mag3110_position_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int val; - mutex_lock(&mag3110_lock); - val = mag3110_pdata->position; - mutex_unlock(&mag3110_lock); - return sprintf(buf, "%d\n", val); -} - -static ssize_t mag3110_position_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - long position; - int ret; - ret = strict_strtol(buf, 10, &position); - if (ret) { - dev_err(dev, "string to long error\n"); - return ret; - } - - mutex_lock(&mag3110_lock); - mag3110_pdata->position = (int)position; - mutex_unlock(&mag3110_lock); - return count; -} - -static DEVICE_ATTR(position, S_IWUSR | S_IRUGO, - mag3110_position_show, mag3110_position_store); - -static struct attribute *mag3110_attributes[] = { - &dev_attr_enable.attr, - &dev_attr_dr_mode.attr, - &dev_attr_position.attr, - NULL -}; - -static const struct attribute_group mag3110_attr_group = { - .attrs = mag3110_attributes, -}; - -static int mag3110_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter; - struct input_dev *idev; - struct mag3110_data *data; - int ret = 0; - struct regulator *vdd, *vdd_io; - u32 pos = 0; - struct device_node *of_node = client->dev.of_node; - vdd = NULL; - vdd_io = NULL; - - vdd = devm_regulator_get(&client->dev, "vdd"); - if (!IS_ERR(vdd)) { - ret = regulator_enable(vdd); - if (ret) { - dev_err(&client->dev, "vdd set voltage error\n"); - return ret; - } - } - - vdd_io = devm_regulator_get(&client->dev, "vddio"); - if (!IS_ERR(vdd_io)) { - ret = regulator_enable(vdd_io); - if (ret) { - dev_err(&client->dev, "vddio set voltage error\n"); - return ret; - } - } - - adapter = to_i2c_adapter(client->dev.parent); - if (!i2c_check_functionality(adapter, - I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_I2C_BLOCK)) - return -EIO; - - dev_info(&client->dev, "check mag3110 chip ID\n"); - ret = mag3110_read_reg(client, MAG3110_WHO_AM_I); - - if (MAG3110_ID != ret) { - dev_err(&client->dev, - "read chip ID 0x%x is not equal to 0x%x!\n", ret, - MAG3110_ID); - return -EINVAL; - } - data = kzalloc(sizeof(struct mag3110_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - data->client = client; - i2c_set_clientdata(client, data); - /* Init queue */ - init_waitqueue_head(&data->waitq); - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - dev_err(&client->dev, "hwmon register failed!\n"); - ret = PTR_ERR(data->hwmon_dev); - goto error_rm_dev_sysfs; - } - - /*input poll device register */ - data->poll_dev = input_allocate_polled_device(); - if (!data->poll_dev) { - dev_err(&client->dev, "alloc poll device failed!\n"); - ret = -ENOMEM; - goto error_rm_hwmon_dev; - } - data->poll_dev->poll = mag3110_dev_poll; - data->poll_dev->poll_interval = POLL_INTERVAL; - data->poll_dev->poll_interval_max = POLL_INTERVAL_MAX; - idev = data->poll_dev->input; - idev->name = MAG3110_DRV_NAME; - idev->id.bustype = BUS_I2C; - idev->evbit[0] = BIT_MASK(EV_ABS); - input_set_abs_params(idev, ABS_X, -15000, 15000, 0, 0); - input_set_abs_params(idev, ABS_Y, -15000, 15000, 0, 0); - input_set_abs_params(idev, ABS_Z, -15000, 15000, 0, 0); - ret = input_register_polled_device(data->poll_dev); - if (ret) { - dev_err(&client->dev, "register poll device failed!\n"); - goto error_free_poll_dev; - } - - /*create device group in sysfs as user interface */ - ret = sysfs_create_group(&idev->dev.kobj, &mag3110_attr_group); - if (ret) { - dev_err(&client->dev, "create device file failed!\n"); - ret = -EINVAL; - goto error_rm_poll_dev; - } - /* set irq type to edge rising */ -#if MAG3110_IRQ_USED - ret = request_irq(client->irq, mag3110_irq_handler, - IRQF_TRIGGER_RISING, client->dev.driver->name, idev); - if (ret < 0) { - dev_err(&client->dev, "failed to register irq %d!\n", - client->irq); - goto error_rm_dev_sysfs; - } -#endif - /* Initialize mag3110 chip */ - mag3110_init_client(client); - mag3110_pdata = data; - mag3110_pdata->active = MAG_STANDBY; - ret = of_property_read_u32(of_node, "position", &pos); - if (ret) - pos = DEFAULT_POSITION; - mag3110_pdata->position = (int)pos; - dev_info(&client->dev, "mag3110 is probed\n"); - return 0; -error_rm_dev_sysfs: - sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group); -error_rm_poll_dev: - input_unregister_polled_device(data->poll_dev); -error_free_poll_dev: - input_free_polled_device(data->poll_dev); -error_rm_hwmon_dev: - hwmon_device_unregister(data->hwmon_dev); - - kfree(data); - mag3110_pdata = NULL; - - return ret; -} - -static int mag3110_remove(struct i2c_client *client) -{ - struct mag3110_data *data; - int ret; - - data = i2c_get_clientdata(client); - - data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1); - ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, - data->ctl_reg1 & ~MAG3110_AC_MASK); - - free_irq(client->irq, data); - input_unregister_polled_device(data->poll_dev); - input_free_polled_device(data->poll_dev); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group); - kfree(data); - mag3110_pdata = NULL; - - return ret; -} - -#ifdef CONFIG_PM -static int mag3110_suspend(struct i2c_client *client, pm_message_t mesg) -{ - int ret = 0; - struct mag3110_data *data = i2c_get_clientdata(client); - if (data->active == MAG_ACTIVED) { - data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1); - ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, - data->ctl_reg1 & ~MAG3110_AC_MASK); - } - return ret; -} - -static int mag3110_resume(struct i2c_client *client) -{ - int ret = 0; - u8 tmp_data[MAG3110_XYZ_DATA_LEN]; - struct mag3110_data *data = i2c_get_clientdata(client); - if (data->active == MAG_ACTIVED) { - ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, - data->ctl_reg1); - - if (data->ctl_reg1 & MAG3110_AC_MASK) { - /* Read out MSB data to clear interrupt - flag automatically */ - mag3110_read_block_data(client, MAG3110_OUT_X_MSB, - MAG3110_XYZ_DATA_LEN, tmp_data); - } - } - return ret; -} - -#else -#define mag3110_suspend NULL -#define mag3110_resume NULL -#endif /* CONFIG_PM */ - -static const struct i2c_device_id mag3110_id[] = { - {MAG3110_DRV_NAME, 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, mag3110_id); -static struct i2c_driver mag3110_driver = { - .driver = {.name = MAG3110_DRV_NAME, - .owner = THIS_MODULE,}, - .suspend = mag3110_suspend, - .resume = mag3110_resume, - .probe = mag3110_probe, - .remove = mag3110_remove, - .id_table = mag3110_id, -}; - -static int __init mag3110_init(void) -{ - return i2c_add_driver(&mag3110_driver); -} - -static void __exit mag3110_exit(void) -{ - i2c_del_driver(&mag3110_driver); -} - -module_init(mag3110_init); -module_exit(mag3110_exit); -MODULE_AUTHOR("Freescale Semiconductor, Inc."); -MODULE_DESCRIPTION("Freescale mag3110 3-axis magnetometer driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/mxc_mma8451.c b/drivers/hwmon/mxc_mma8451.c deleted file mode 100644 index f4407bc5beba..000000000000 --- a/drivers/hwmon/mxc_mma8451.c +++ /dev/null @@ -1,598 +0,0 @@ -/* - * mma8451.c - Linux kernel modules for 3-Axis Orientation/Motion - * Detection Sensor - * - * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MMA8451_I2C_ADDR 0x1C -#define MMA8451_ID 0x1A -#define MMA8452_ID 0x2A -#define MMA8453_ID 0x3A - -#define POLL_INTERVAL_MIN 1 -#define POLL_INTERVAL_MAX 500 -#define POLL_INTERVAL 100 /* msecs */ -#define INPUT_FUZZ 32 -#define INPUT_FLAT 32 -#define MODE_CHANGE_DELAY_MS 100 - -#define MMA8451_STATUS_ZYXDR 0x08 -#define MMA8451_BUF_SIZE 7 -#define DEFAULT_POSITION 0 - -/* register enum for mma8451 registers */ -enum { - MMA8451_STATUS = 0x00, - MMA8451_OUT_X_MSB, - MMA8451_OUT_X_LSB, - MMA8451_OUT_Y_MSB, - MMA8451_OUT_Y_LSB, - MMA8451_OUT_Z_MSB, - MMA8451_OUT_Z_LSB, - - MMA8451_F_SETUP = 0x09, - MMA8451_TRIG_CFG, - MMA8451_SYSMOD, - MMA8451_INT_SOURCE, - MMA8451_WHO_AM_I, - MMA8451_XYZ_DATA_CFG, - MMA8451_HP_FILTER_CUTOFF, - - MMA8451_PL_STATUS, - MMA8451_PL_CFG, - MMA8451_PL_COUNT, - MMA8451_PL_BF_ZCOMP, - MMA8451_P_L_THS_REG, - - MMA8451_FF_MT_CFG, - MMA8451_FF_MT_SRC, - MMA8451_FF_MT_THS, - MMA8451_FF_MT_COUNT, - - MMA8451_TRANSIENT_CFG = 0x1D, - MMA8451_TRANSIENT_SRC, - MMA8451_TRANSIENT_THS, - MMA8451_TRANSIENT_COUNT, - - MMA8451_PULSE_CFG, - MMA8451_PULSE_SRC, - MMA8451_PULSE_THSX, - MMA8451_PULSE_THSY, - MMA8451_PULSE_THSZ, - MMA8451_PULSE_TMLT, - MMA8451_PULSE_LTCY, - MMA8451_PULSE_WIND, - - MMA8451_ASLP_COUNT, - MMA8451_CTRL_REG1, - MMA8451_CTRL_REG2, - MMA8451_CTRL_REG3, - MMA8451_CTRL_REG4, - MMA8451_CTRL_REG5, - - MMA8451_OFF_X, - MMA8451_OFF_Y, - MMA8451_OFF_Z, - - MMA8451_REG_END, -}; - -/* The sensitivity is represented in counts/g. In 2g mode the -sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512 -counts/g and in 8g mode the sensitivity is 256 counts/g. - */ -enum { - MODE_2G = 0, - MODE_4G, - MODE_8G, -}; - -enum { - MMA_STANDBY = 0, - MMA_ACTIVED, -}; - -/* mma8451 status */ -struct mma8451_status { - u8 mode; - u8 ctl_reg1; - int active; - int position; -}; - -static struct mma8451_status mma_status; -static struct input_polled_dev *mma8451_idev; -static struct device *hwmon_dev; -static struct i2c_client *mma8451_i2c_client; - -static int senstive_mode = MODE_2G; -static int ACCHAL[8][3][3] = { - { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} }, - { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} }, - { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} }, - { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }, - - { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} }, - { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} }, - { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} }, - { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} }, -}; - -static DEFINE_MUTEX(mma8451_lock); -static int mma8451_adjust_position(short *x, short *y, short *z) -{ - short rawdata[3], data[3]; - int i, j; - int position = mma_status.position; - if (position < 0 || position > 7) - position = 0; - rawdata[0] = *x; - rawdata[1] = *y; - rawdata[2] = *z; - for (i = 0; i < 3; i++) { - data[i] = 0; - for (j = 0; j < 3; j++) - data[i] += rawdata[j] * ACCHAL[position][i][j]; - } - *x = data[0]; - *y = data[1]; - *z = data[2]; - return 0; -} - -static int mma8451_change_mode(struct i2c_client *client, int mode) -{ - int result; - - mma_status.ctl_reg1 = 0; - result = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 0); - if (result < 0) - goto out; - mma_status.active = MMA_STANDBY; - - result = i2c_smbus_write_byte_data(client, MMA8451_XYZ_DATA_CFG, - mode); - if (result < 0) - goto out; - mdelay(MODE_CHANGE_DELAY_MS); - mma_status.mode = mode; - - return 0; -out: - dev_err(&client->dev, "error when init mma8451:(%d)", result); - return result; -} - -static int mma8451_read_data(short *x, short *y, short *z) -{ - u8 tmp_data[MMA8451_BUF_SIZE]; - int ret; - - ret = i2c_smbus_read_i2c_block_data(mma8451_i2c_client, - MMA8451_OUT_X_MSB, 7, tmp_data); - if (ret < MMA8451_BUF_SIZE) { - dev_err(&mma8451_i2c_client->dev, "i2c block read failed\n"); - return -EIO; - } - - *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1]; - *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3]; - *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5]; - return 0; -} - -static void report_abs(void) -{ - short x, y, z; - int result; - int retry = 3; - - mutex_lock(&mma8451_lock); - if (mma_status.active == MMA_STANDBY) - goto out; - /* wait for the data ready */ - do { - result = i2c_smbus_read_byte_data(mma8451_i2c_client, - MMA8451_STATUS); - retry--; - msleep(1); - } while (!(result & MMA8451_STATUS_ZYXDR) && retry > 0); - if (retry == 0) - goto out; - if (mma8451_read_data(&x, &y, &z) != 0) - goto out; - mma8451_adjust_position(&x, &y, &z); - input_report_abs(mma8451_idev->input, ABS_X, x); - input_report_abs(mma8451_idev->input, ABS_Y, y); - input_report_abs(mma8451_idev->input, ABS_Z, z); - input_sync(mma8451_idev->input); -out: - mutex_unlock(&mma8451_lock); -} - -static void mma8451_dev_poll(struct input_polled_dev *dev) -{ - report_abs(); -} - -static ssize_t mma8451_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_client *client; - u8 val; - int enable; - - mutex_lock(&mma8451_lock); - client = mma8451_i2c_client; - val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); - if ((val & 0x01) && mma_status.active == MMA_ACTIVED) - enable = 1; - else - enable = 0; - mutex_unlock(&mma8451_lock); - return sprintf(buf, "%d\n", enable); -} - -static ssize_t mma8451_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client; - int ret; - unsigned long enable; - u8 val = 0; - - ret = strict_strtoul(buf, 10, &enable); - if (ret) { - dev_err(dev, "string transform error\n"); - return ret; - } - - mutex_lock(&mma8451_lock); - client = mma8451_i2c_client; - enable = (enable > 0) ? 1 : 0; - if (enable && mma_status.active == MMA_STANDBY) { - val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); - ret = - i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, - val | 0x01); - if (!ret) - mma_status.active = MMA_ACTIVED; - - } else if (enable == 0 && mma_status.active == MMA_ACTIVED) { - val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); - ret = - i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, - val & 0xFE); - if (!ret) - mma_status.active = MMA_STANDBY; - - } - mutex_unlock(&mma8451_lock); - return count; -} - -static ssize_t mma8451_position_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int position = 0; - mutex_lock(&mma8451_lock); - position = mma_status.position; - mutex_unlock(&mma8451_lock); - return sprintf(buf, "%d\n", position); -} - -static ssize_t mma8451_position_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long position; - int ret; - ret = strict_strtoul(buf, 10, &position); - if (ret) { - dev_err(dev, "string transform error\n"); - return ret; - } - - mutex_lock(&mma8451_lock); - mma_status.position = (int)position; - mutex_unlock(&mma8451_lock); - return count; -} - -static ssize_t mma8451_scalemode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int mode = 0; - mutex_lock(&mma8451_lock); - mode = (int)mma_status.mode; - mutex_unlock(&mma8451_lock); - - return sprintf(buf, "%d\n", mode); -} - -static ssize_t mma8451_scalemode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long mode; - int ret, active_save; - struct i2c_client *client = mma8451_i2c_client; - - ret = strict_strtoul(buf, 10, &mode); - if (ret) { - dev_err(dev, "string transform error\n"); - goto out; - } - - if (mode > MODE_8G) { - dev_warn(dev, "not supported mode\n"); - ret = count; - goto out; - } - - mutex_lock(&mma8451_lock); - if (mode == mma_status.mode) { - ret = count; - goto out_unlock; - } - - active_save = mma_status.active; - ret = mma8451_change_mode(client, mode); - if (ret) - goto out_unlock; - - if (active_save == MMA_ACTIVED) { - ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 1); - - if (ret) - goto out_unlock; - mma_status.active = active_save; - } - -out_unlock: - mutex_unlock(&mma8451_lock); -out: - return ret; -} - -static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, - mma8451_enable_show, mma8451_enable_store); -static DEVICE_ATTR(position, S_IWUSR | S_IRUGO, - mma8451_position_show, mma8451_position_store); -static DEVICE_ATTR(scalemode, S_IWUSR | S_IRUGO, - mma8451_scalemode_show, mma8451_scalemode_store); - -static struct attribute *mma8451_attributes[] = { - &dev_attr_enable.attr, - &dev_attr_position.attr, - &dev_attr_scalemode.attr, - NULL -}; - -static const struct attribute_group mma8451_attr_group = { - .attrs = mma8451_attributes, -}; - -static int mma8451_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int result, client_id; - struct input_dev *idev; - struct i2c_adapter *adapter; - u32 pos; - struct device_node *of_node = client->dev.of_node; - struct regulator *vdd, *vdd_io; - - mma8451_i2c_client = client; - - vdd = devm_regulator_get(&client->dev, "vdd"); - if (!IS_ERR(vdd)) { - result = regulator_enable(vdd); - if (result) { - dev_err(&client->dev, "vdd set voltage error\n"); - return result; - } - } - - vdd_io = devm_regulator_get(&client->dev, "vddio"); - if (!IS_ERR(vdd_io)) { - result = regulator_enable(vdd_io); - if (result) { - dev_err(&client->dev, "vddio set voltage error\n"); - return result; - } - } - - adapter = to_i2c_adapter(client->dev.parent); - result = i2c_check_functionality(adapter, - I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA); - if (!result) - goto err_out; - - client_id = i2c_smbus_read_byte_data(client, MMA8451_WHO_AM_I); - if (client_id != MMA8451_ID && client_id != MMA8452_ID - && client_id != MMA8453_ID) { - dev_err(&client->dev, - "read chip ID 0x%x is not equal to 0x%x or 0x%x!\n", - result, MMA8451_ID, MMA8452_ID); - result = -EINVAL; - goto err_out; - } - - /* Initialize the MMA8451 chip */ - result = mma8451_change_mode(client, senstive_mode); - if (result) { - dev_err(&client->dev, - "error when init mma8451 chip:(%d)\n", result); - goto err_out; - } - - hwmon_dev = hwmon_device_register(&client->dev); - if (!hwmon_dev) { - result = -ENOMEM; - dev_err(&client->dev, "error when register hwmon device\n"); - goto err_out; - } - - mma8451_idev = input_allocate_polled_device(); - if (!mma8451_idev) { - result = -ENOMEM; - dev_err(&client->dev, "alloc poll device failed!\n"); - goto err_alloc_poll_device; - } - mma8451_idev->poll = mma8451_dev_poll; - mma8451_idev->poll_interval = POLL_INTERVAL; - mma8451_idev->poll_interval_min = POLL_INTERVAL_MIN; - mma8451_idev->poll_interval_max = POLL_INTERVAL_MAX; - idev = mma8451_idev->input; - idev->name = "mma845x"; - idev->id.bustype = BUS_I2C; - idev->evbit[0] = BIT_MASK(EV_ABS); - - input_set_abs_params(idev, ABS_X, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); - input_set_abs_params(idev, ABS_Y, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); - input_set_abs_params(idev, ABS_Z, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); - - result = input_register_polled_device(mma8451_idev); - if (result) { - dev_err(&client->dev, "register poll device failed!\n"); - goto err_register_polled_device; - } - result = sysfs_create_group(&idev->dev.kobj, &mma8451_attr_group); - if (result) { - dev_err(&client->dev, "create device file failed!\n"); - result = -EINVAL; - goto err_register_polled_device; - } - - result = of_property_read_u32(of_node, "position", &pos); - if (result) - pos = DEFAULT_POSITION; - mma_status.position = (int)pos; - - return 0; -err_register_polled_device: - input_free_polled_device(mma8451_idev); -err_alloc_poll_device: - hwmon_device_unregister(&client->dev); -err_out: - return result; -} - -static int mma8451_stop_chip(struct i2c_client *client) -{ - int ret = 0; - if (mma_status.active == MMA_ACTIVED) { - mma_status.ctl_reg1 = i2c_smbus_read_byte_data(client, - MMA8451_CTRL_REG1); - ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, - mma_status.ctl_reg1 & 0xFE); - } - return ret; -} - -static int mma8451_remove(struct i2c_client *client) -{ - int ret; - ret = mma8451_stop_chip(client); - hwmon_device_unregister(hwmon_dev); - - return ret; -} - -#ifdef CONFIG_PM_SLEEP -static int mma8451_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - - return mma8451_stop_chip(client); -} - -static int mma8451_resume(struct device *dev) -{ - int ret = 0; - struct i2c_client *client = to_i2c_client(dev); - if (mma_status.active == MMA_ACTIVED) - ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, - mma_status.ctl_reg1); - return ret; - -} -#endif - -static const struct i2c_device_id mma8451_id[] = { - {"mma8451", 0}, -}; - -MODULE_DEVICE_TABLE(i2c, mma8451_id); - -static SIMPLE_DEV_PM_OPS(mma8451_pm_ops, mma8451_suspend, mma8451_resume); -static struct i2c_driver mma8451_driver = { - .driver = { - .name = "mma8451", - .owner = THIS_MODULE, - .pm = &mma8451_pm_ops, - }, - .probe = mma8451_probe, - .remove = mma8451_remove, - .id_table = mma8451_id, -}; - -static int __init mma8451_init(void) -{ - /* register driver */ - int res; - - res = i2c_add_driver(&mma8451_driver); - if (res < 0) { - printk(KERN_INFO "add mma8451 i2c driver failed\n"); - return -ENODEV; - } - return res; -} - -static void __exit mma8451_exit(void) -{ - i2c_del_driver(&mma8451_driver); -} - -MODULE_AUTHOR("Freescale Semiconductor, Inc."); -MODULE_DESCRIPTION("MMA8451 3-Axis Orientation/Motion Detection Sensor driver"); -MODULE_LICENSE("GPL"); - -module_init(mma8451_init); -module_exit(mma8451_exit); diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index a1023b3e05bb..a23a94bb4bcb 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -270,27 +270,6 @@ config TOUCHSCREEN_EGALAX To compile this driver as a module, choose M here: the module will be called egalax_ts. -config TOUCHSCREEN_EGALAX_SINGLE_TOUCH - bool "EETI eGalax touchscreen as single-touch" - default N - depends on TOUCHSCREEN_EGALAX - help - If you say yes here you get single-touch touchscreen support - on the eGalax I2C controller. - If you say "no", you'll get the normal multi-touch - -config TOUCHSCREEN_ELAN - tristate "ELAN touchscreen input driver" - depends on I2C - help - Say Y here if you have an I2C ELAN touchscreen - attached. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called elan-touch. - config TOUCHSCREEN_FUJITSU tristate "Fujitsu serial touchscreen" select SERIO diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index bfe4ce2f52ee..126479d8c29a 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -30,7 +30,6 @@ obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o -obj-$(CONFIG_TOUCHSCREEN_ELAN) += elan_ts.o obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index db214af0ebd2..c8057847d71d 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -1,7 +1,7 @@ /* * Driver for EETI eGalax Multiple Touch Controller * - * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2011 Freescale Semiconductor, Inc. * * based on max11801_ts.c * @@ -34,7 +34,7 @@ * which can only report one point at a given time. * This driver will ignore events in this mode. */ -#define REPORT_MODE_SINGLE 0x1 +#define REPORT_MODE_MOUSE 0x1 /* * Vendor Mode: this mode is used to transfer some vendor specific * messages. @@ -46,8 +46,6 @@ #define MAX_SUPPORT_POINTS 5 -#define EVENT_MODE 0 -#define EVENT_STATUS 1 #define EVENT_VALID_OFFSET 7 #define EVENT_VALID_MASK (0x1 << EVENT_VALID_OFFSET) #define EVENT_ID_OFFSET 2 @@ -57,21 +55,13 @@ #define MAX_I2C_DATA_LEN 10 -#define EGALAX_MAX_X 32767 -#define EGALAX_MAX_Y 32767 +#define EGALAX_MAX_X 32760 +#define EGALAX_MAX_Y 32760 #define EGALAX_MAX_TRIES 100 -struct egalax_pointer { - bool valid; - bool status; - u16 x; - u16 y; -}; - struct egalax_ts { struct i2c_client *client; struct input_dev *input_dev; - struct egalax_pointer events[MAX_SUPPORT_POINTS]; }; static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id) @@ -79,9 +69,8 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id) struct egalax_ts *ts = dev_id; struct input_dev *input_dev = ts->input_dev; struct i2c_client *client = ts->client; - struct egalax_pointer *events = ts->events; u8 buf[MAX_I2C_DATA_LEN]; - int i, id, ret, x, y; + int id, ret, x, y, z; int tries = 0; bool down, valid; u8 state; @@ -93,38 +82,15 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id) if (ret < 0) return IRQ_HANDLED; - dev_dbg(&client->dev, "recv ret:%d", ret); - for (i = 0; i < MAX_I2C_DATA_LEN; i++) - dev_dbg(&client->dev, " %x ", buf[i]); - - if (buf[0] != REPORT_MODE_VENDOR - && buf[0] != REPORT_MODE_SINGLE - && buf[0] != REPORT_MODE_MTTOUCH) { - /* invalid point */ - return IRQ_HANDLED; - } - - if (buf[0] == REPORT_MODE_VENDOR) { - dev_dbg(&client->dev, "vendor message, ignored\n"); + if (buf[0] != REPORT_MODE_MTTOUCH) { + /* ignore mouse events and vendor events */ return IRQ_HANDLED; } state = buf[1]; x = (buf[3] << 8) | buf[2]; y = (buf[5] << 8) | buf[4]; - - /* Currently, the panel Freescale using on SMD board _NOT_ - * support single pointer mode. All event are going to - * multiple pointer mode. Add single pointer mode according - * to EETI eGalax I2C programming manual. - */ - if (buf[0] == REPORT_MODE_SINGLE) { - input_report_abs(input_dev, ABS_X, x); - input_report_abs(input_dev, ABS_Y, y); - input_report_key(input_dev, BTN_TOUCH, !!state); - input_sync(input_dev); - return IRQ_HANDLED; - } + z = (buf[7] << 8) | buf[6]; valid = state & EVENT_VALID_MASK; id = (state & EVENT_ID_MASK) >> EVENT_ID_OFFSET; @@ -135,50 +101,19 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } + input_mt_slot(input_dev, id); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, down); + + dev_dbg(&client->dev, "%s id:%d x:%d y:%d z:%d", + down ? "down" : "up", id, x, y, z); + if (down) { - events[id].valid = valid; - events[id].status = down; - events[id].x = x; - events[id].y = y; - -#ifdef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH - input_report_abs(input_dev, ABS_X, x); - input_report_abs(input_dev, ABS_Y, y); - input_event(ts->input_dev, EV_KEY, BTN_TOUCH, 1); - input_report_abs(input_dev, ABS_PRESSURE, 1); -#endif - } else { - dev_dbg(&client->dev, "release id:%d\n", id); - events[id].valid = 0; - events[id].status = 0; -#ifdef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH - input_report_key(input_dev, BTN_TOUCH, 0); - input_report_abs(input_dev, ABS_PRESSURE, 0); -#else - input_report_abs(input_dev, ABS_MT_TRACKING_ID, id); - input_event(input_dev, EV_ABS, ABS_MT_TOUCH_MAJOR, 0); - input_mt_sync(input_dev); -#endif + input_report_abs(input_dev, ABS_MT_POSITION_X, x); + input_report_abs(input_dev, ABS_MT_POSITION_Y, y); + input_report_abs(input_dev, ABS_MT_PRESSURE, z); } -#ifndef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH - /* report all pointers */ - for (i = 0; i < MAX_SUPPORT_POINTS; i++) { - if (!events[i].valid) - continue; - dev_dbg(&client->dev, "report id:%d valid:%d x:%d y:%d", - i, valid, x, y); - input_report_abs(input_dev, - ABS_MT_TRACKING_ID, i); - input_report_abs(input_dev, - ABS_MT_TOUCH_MAJOR, 1); - input_report_abs(input_dev, - ABS_MT_POSITION_X, events[i].x); - input_report_abs(input_dev, - ABS_MT_POSITION_Y, events[i].y); - input_mt_sync(input_dev); - } -#endif + input_mt_report_pointer_emulation(input_dev, true); input_sync(input_dev); return IRQ_HANDLED; @@ -264,34 +199,21 @@ static int egalax_ts_probe(struct i2c_client *client, return error; } - input_dev->name = "eGalax Touch Screen"; - input_dev->phys = "I2C", + input_dev->name = "EETI eGalax Touch Screen"; input_dev->id.bustype = BUS_I2C; - input_dev->id.vendor = 0x0EEF; - input_dev->id.product = 0x0020; - input_dev->id.version = 0x0001; - input_dev->dev.parent = &client->dev; __set_bit(EV_ABS, input_dev->evbit); __set_bit(EV_KEY, input_dev->evbit); __set_bit(BTN_TOUCH, input_dev->keybit); - __set_bit(ABS_X, input_dev->absbit); - __set_bit(ABS_Y, input_dev->absbit); - __set_bit(ABS_PRESSURE, input_dev->absbit); + input_set_abs_params(input_dev, ABS_X, 0, EGALAX_MAX_X, 0, 0); input_set_abs_params(input_dev, ABS_Y, 0, EGALAX_MAX_Y, 0, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0); - -#ifndef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH - input_set_abs_params(input_dev, ABS_MT_POSITION_X, - 0, EGALAX_MAX_X, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, - 0, EGALAX_MAX_Y, 0, 0); - input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); - input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); - input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, - MAX_SUPPORT_POINTS, 0, 0); -#endif + input_set_abs_params(input_dev, + ABS_MT_POSITION_X, 0, EGALAX_MAX_X, 0, 0); + input_set_abs_params(input_dev, + ABS_MT_POSITION_Y, 0, EGALAX_MAX_Y, 0, 0); + input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS, 0); + input_set_drvdata(input_dev, ts); error = devm_request_threaded_irq(&client->dev, client->irq, NULL, diff --git a/drivers/input/touchscreen/elan_ts.c b/drivers/input/touchscreen/elan_ts.c deleted file mode 100644 index 783a72f15d7e..000000000000 --- a/drivers/input/touchscreen/elan_ts.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright (C) 2007-2008 HTC Corporation. - * - * Copyright (C) 2013 Freescale Semiconductor, Inc. - * - * This driver is adapted from elan8232_i2c.c written by Shan-Fu Chiou - * and Jay Tu . - * This driver is also adapted from the ELAN Touch Screen driver - * written by Stanley Zeng - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const char ELAN_TS_NAME[] = "elan-touch"; - -#define ELAN_TS_X_MAX 1088 -#define ELAN_TS_Y_MAX 768 -#define ELAN_USER_X_MAX 800 -#define ELAN_USER_Y_MAX 600 -#define IDX_PACKET_SIZE 8 - -enum { - hello_packet = 0x55, - idx_coordinate_packet = 0x5a, -}; - -enum { - idx_finger_state = 7, -}; - -static struct workqueue_struct *elan_wq; - -static struct elan_data { - int intr_gpio; - int use_irq; - struct hrtimer timer; - struct work_struct work; - struct i2c_client *client; - struct input_dev *input; - wait_queue_head_t wait; -} elan_touch_data; - -/*--------------------------------------------------------------*/ -static int elan_touch_detect_int_level(void) -{ - int v; - v = gpio_get_value(elan_touch_data.intr_gpio); - - return v; -} - -static int __elan_touch_poll(struct i2c_client *client) -{ - int status = 0, retry = 20; - - do { - status = elan_touch_detect_int_level(); - retry--; - mdelay(20); - } while (status == 1 && retry > 0); - - return (status == 0 ? 0 : -ETIMEDOUT); -} - -static int elan_touch_poll(struct i2c_client *client) -{ - return __elan_touch_poll(client); -} - -static int __hello_packet_handler(struct i2c_client *client) -{ - int rc; - uint8_t buf_recv[4] = { 0 }; - - rc = elan_touch_poll(client); - - if (rc < 0) - return -EINVAL; - - rc = i2c_master_recv(client, buf_recv, 4); - - if (rc != 4) { - return rc; - } else { - int i; - pr_info("hello packet: [0x%02x 0x%02x 0x%02x 0x%02x]\n", - buf_recv[0], buf_recv[1], buf_recv[2], buf_recv[3]); - - for (i = 0; i < 4; i++) - if (buf_recv[i] != hello_packet) - return -EINVAL; - } - - return 0; -} - -static inline int elan_touch_parse_xy(uint8_t *data, uint16_t *x, - uint16_t *y) -{ - *x = (data[0] & 0xf0); - *x <<= 4; - *x |= data[1]; - if (*x >= ELAN_TS_X_MAX) - *x = ELAN_TS_X_MAX; - *x = ((((ELAN_TS_X_MAX - - *x) * 1000) / ELAN_TS_X_MAX) * ELAN_USER_X_MAX) / 1000; - - *y = (data[0] & 0x0f); - *y <<= 8; - *y |= data[2]; - if (*y >= ELAN_TS_Y_MAX) - *y = ELAN_TS_Y_MAX; - *y = ((((ELAN_TS_Y_MAX - - *y) * 1000) / ELAN_TS_Y_MAX) * ELAN_USER_Y_MAX) / 1000; - - return 0; -} - -/* __elan_touch_init -- hand shaking with touch panel - * - * 1.recv hello packet - */ -static int __elan_touch_init(struct i2c_client *client) -{ - int rc; - rc = __hello_packet_handler(client); - if (rc < 0) - goto hand_shake_failed; - -hand_shake_failed: - return rc; -} - -static int elan_touch_recv_data(struct i2c_client *client, uint8_t * buf) -{ - int rc, bytes_to_recv = IDX_PACKET_SIZE; - - if (buf == NULL) - return -EINVAL; - - memset(buf, 0, bytes_to_recv); - rc = i2c_master_recv(client, buf, bytes_to_recv); - if (rc != bytes_to_recv) - return -EINVAL; - - return rc; -} - -static void elan_touch_report_data(struct i2c_client *client, uint8_t * buf) -{ - switch (buf[0]) { - case idx_coordinate_packet: - { - uint16_t x1, x2, y1, y2; - uint8_t finger_stat; - - finger_stat = (buf[idx_finger_state] & 0x06) >> 1; - - if (finger_stat == 0) { - input_report_key(elan_touch_data.input, BTN_TOUCH, 0); - input_report_key(elan_touch_data.input, BTN_2, 0); - } else if (finger_stat == 1) { - elan_touch_parse_xy(&buf[1], &x1, &y1); - input_report_abs(elan_touch_data.input, ABS_X, x1); - input_report_abs(elan_touch_data.input, ABS_Y, y1); - input_report_key(elan_touch_data.input, BTN_TOUCH, 1); - input_report_key(elan_touch_data.input, BTN_2, 0); - } else if (finger_stat == 2) { - elan_touch_parse_xy(&buf[1], &x1, &y1); - input_report_abs(elan_touch_data.input, ABS_X, x1); - input_report_abs(elan_touch_data.input, ABS_Y, y1); - input_report_key(elan_touch_data.input, BTN_TOUCH, 1); - elan_touch_parse_xy(&buf[4], &x2, &y2); - input_report_abs(elan_touch_data.input, ABS_HAT0X, x2); - input_report_abs(elan_touch_data.input, ABS_HAT0Y, y2); - input_report_key(elan_touch_data.input, BTN_2, 1); - } - input_sync(elan_touch_data.input); - break; - } - - default: - break; - } -} - -static void elan_touch_work_func(struct work_struct *work) -{ - int rc; - uint8_t buf[IDX_PACKET_SIZE] = { 0 }; - struct i2c_client *client = elan_touch_data.client; - - if (elan_touch_detect_int_level()) - return; - - rc = elan_touch_recv_data(client, buf); - if (rc < 0) - return; - - elan_touch_report_data(client, buf); -} - -static irqreturn_t elan_touch_ts_interrupt(int irq, void *dev_id) -{ - queue_work(elan_wq, &elan_touch_data.work); - - return IRQ_HANDLED; -} - -static enum hrtimer_restart elan_touch_timer_func(struct hrtimer *timer) -{ - queue_work(elan_wq, &elan_touch_data.work); - hrtimer_start(&elan_touch_data.timer, ktime_set(0, 12500000), - HRTIMER_MODE_REL); - - return HRTIMER_NORESTART; -} - -static int elan_touch_register_interrupt(struct i2c_client *client) -{ - int err = 0; - - if (client->irq) { - elan_touch_data.use_irq = 1; - err = - request_irq(client->irq, elan_touch_ts_interrupt, - IRQF_TRIGGER_FALLING, ELAN_TS_NAME, - &elan_touch_data); - - if (err < 0) { - pr_info("%s(%s): Can't allocate irq %d\n", __FILE__, - __func__, client->irq); - elan_touch_data.use_irq = 0; - } - } - - if (!elan_touch_data.use_irq) { - hrtimer_init(&elan_touch_data.timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - elan_touch_data.timer.function = elan_touch_timer_func; - hrtimer_start(&elan_touch_data.timer, ktime_set(1, 0), - HRTIMER_MODE_REL); - } - - pr_info("elan ts starts in %s mode.\n", - elan_touch_data.use_irq == 1 ? "interrupt" : "polling"); - - return 0; -} - -static int elan_touch_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct device_node *np = client->dev.of_node; - int gpio_elan_cs, gpio_elan_rst, err = 0; - - if (!np) - return -ENODEV; - - elan_touch_data.intr_gpio = of_get_named_gpio(np, "gpio_intr", 0); - if (!gpio_is_valid(elan_touch_data.intr_gpio)) - return -ENODEV; - - err = devm_gpio_request_one(&client->dev, elan_touch_data.intr_gpio, - GPIOF_IN, "gpio_elan_intr"); - if (err < 0) { - dev_err(&client->dev, - "request gpio failed: %d\n", err); - return err; - } - - /* elan touch init */ - gpio_elan_cs = of_get_named_gpio(np, "gpio_elan_cs", 0); - if (!gpio_is_valid(gpio_elan_cs)) - return -ENODEV; - - err = devm_gpio_request_one(&client->dev, gpio_elan_cs, - GPIOF_OUT_INIT_HIGH, "gpio_elan_cs"); - if (err < 0) { - dev_err(&client->dev, - "request gpio failed: %d\n", err); - return err; - } - gpio_set_value(gpio_elan_cs, 0); - - gpio_elan_rst = of_get_named_gpio(np, "gpio_elan_rst", 0); - if (!gpio_is_valid(gpio_elan_rst)) - return -ENODEV; - - err = devm_gpio_request_one(&client->dev, gpio_elan_rst, - GPIOF_OUT_INIT_HIGH, "gpio_elan_rst"); - if (err < 0) { - dev_err(&client->dev, - "request gpio failed: %d\n", err); - return err; - } - gpio_set_value(gpio_elan_rst, 0); - msleep(10); - gpio_set_value(gpio_elan_rst, 1); - - gpio_set_value(gpio_elan_cs, 1); - msleep(100); - - elan_wq = create_singlethread_workqueue("elan_wq"); - if (!elan_wq) { - err = -ENOMEM; - goto fail; - } - - elan_touch_data.client = client; - strlcpy(client->name, ELAN_TS_NAME, I2C_NAME_SIZE); - - INIT_WORK(&elan_touch_data.work, elan_touch_work_func); - - elan_touch_data.input = input_allocate_device(); - if (elan_touch_data.input == NULL) { - err = -ENOMEM; - goto fail; - } - - err = __elan_touch_init(client); - if (err < 0) { - dev_err(&client->dev, "elan - Read Hello Packet Failed\n"); - goto fail; - } - - elan_touch_data.input->name = ELAN_TS_NAME; - elan_touch_data.input->id.bustype = BUS_I2C; - - set_bit(EV_SYN, elan_touch_data.input->evbit); - - set_bit(EV_KEY, elan_touch_data.input->evbit); - set_bit(BTN_TOUCH, elan_touch_data.input->keybit); - set_bit(BTN_2, elan_touch_data.input->keybit); - - set_bit(EV_ABS, elan_touch_data.input->evbit); - set_bit(ABS_X, elan_touch_data.input->absbit); - set_bit(ABS_Y, elan_touch_data.input->absbit); - set_bit(ABS_HAT0X, elan_touch_data.input->absbit); - set_bit(ABS_HAT0Y, elan_touch_data.input->absbit); - - input_set_abs_params(elan_touch_data.input, ABS_X, 0, ELAN_USER_X_MAX, - 0, 0); - input_set_abs_params(elan_touch_data.input, ABS_Y, 0, ELAN_USER_Y_MAX, - 0, 0); - input_set_abs_params(elan_touch_data.input, ABS_HAT0X, 0, - ELAN_USER_X_MAX, 0, 0); - input_set_abs_params(elan_touch_data.input, ABS_HAT0Y, 0, - ELAN_USER_Y_MAX, 0, 0); - - err = input_register_device(elan_touch_data.input); - if (err < 0) - goto fail; - - elan_touch_register_interrupt(elan_touch_data.client); - - return 0; - -fail: - input_free_device(elan_touch_data.input); - if (elan_wq) - destroy_workqueue(elan_wq); - return err; -} - -static int elan_touch_remove(struct i2c_client *client) -{ - if (elan_wq) - destroy_workqueue(elan_wq); - - input_unregister_device(elan_touch_data.input); - - if (elan_touch_data.use_irq) - free_irq(client->irq, client); - else - hrtimer_cancel(&elan_touch_data.timer); - return 0; -} - -/* -------------------------------------------------------------------- */ -static const struct i2c_device_id elan_touch_id[] = { - {"elan-touch", 0}, - {} -}; - -static const struct of_device_id elan_dt_ids[] = { - { - .compatible = "elan,elan-touch", - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(of, elan_dt_ids); - -static int elan_suspend(struct device *dev) -{ - return 0; -} - -static int elan_resume(struct device *dev) -{ - uint8_t buf[IDX_PACKET_SIZE] = { 0 }; - - if (0 == elan_touch_detect_int_level()) { - dev_dbg(dev, "Got touch during suspend period.\n"); - /* - * if touch screen during suspend, recv and drop the - * data, then touch interrupt pin will return high after - * receving data. - */ - elan_touch_recv_data(elan_touch_data.client, buf); - } - - return 0; -} - -static const struct dev_pm_ops elan_dev_pm_ops = { - .suspend = elan_suspend, - .resume = elan_resume, -}; - -static struct i2c_driver elan_touch_driver = { - .probe = elan_touch_probe, - .remove = elan_touch_remove, - .id_table = elan_touch_id, - .driver = { - .name = "elan-touch", - .owner = THIS_MODULE, - .of_match_table = elan_dt_ids, -#ifdef CONFIG_PM - .pm = &elan_dev_pm_ops, -#endif - }, -}; - -static int __init elan_touch_init(void) -{ - return i2c_add_driver(&elan_touch_driver); -} - -static void __exit elan_touch_exit(void) -{ - i2c_del_driver(&elan_touch_driver); -} - -module_init(elan_touch_init); -module_exit(elan_touch_exit); - -MODULE_AUTHOR("Stanley Zeng "); -MODULE_DESCRIPTION("ELAN Touch Screen driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 5650e487d8a6..57ff20fecf57 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -3,7 +3,7 @@ * * Copyright (C) 2007 8D Technologies inc. * Raphael Assenat - * Copyright (C) 2008, 2014 Freescale Semiconductor, Inc. + * Copyright (C) 2008 Freescale Semiconductor, Inc. * * 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 @@ -202,8 +202,6 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev) else led.default_state = LEDS_GPIO_DEFSTATE_OFF; } - if (of_get_property(child, "retain-state-suspended", NULL)) - led.retain_state_suspended = 1; if (of_get_property(child, "retain-state-suspended", NULL)) led.retain_state_suspended = 1; diff --git a/drivers/media/platform/mxc/output/mxc_pxp_v4l2.c b/drivers/media/platform/mxc/output/mxc_pxp_v4l2.c index dc078320acb0..7b7629b8cb82 100644 --- a/drivers/media/platform/mxc/output/mxc_pxp_v4l2.c +++ b/drivers/media/platform/mxc/output/mxc_pxp_v4l2.c @@ -602,9 +602,9 @@ static int pxp_try_fmt_output_overlay(struct file *file, void *fh, wf->w.left = srect.left; wf->w.top = srect.top; wf->w.width = min(srect.width, - ((__s32)pxp->pxp_conf.s0_param.width - wf->w.left)); + ((__u32)pxp->pxp_conf.s0_param.width - wf->w.left)); wf->w.height = min(srect.height, - ((__s32)pxp->pxp_conf.s0_param.height - wf->w.top)); + ((__u32)pxp->pxp_conf.s0_param.height - wf->w.top)); return 0; } diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c index 8ac23dff91a1..6f1ef63086c9 100644 --- a/drivers/mfd/si476x-cmd.c +++ b/drivers/mfd/si476x-cmd.c @@ -303,13 +303,13 @@ static int si476x_core_send_command(struct si476x_core *core, * possible racing conditions when working in polling mode */ atomic_set(&core->cts, 0); - if (!(command == CMD_POWER_DOWN)) - if (!wait_event_timeout(core->command, - atomic_read(&core->cts), - usecs_to_jiffies(usecs) + 1)) - dev_warn(&core->client->dev, - "(%s) [CMD 0x%02x] Answer timeout.\n", - __func__, command); + /* if (unlikely(command == CMD_POWER_DOWN) */ + if (!wait_event_timeout(core->command, + atomic_read(&core->cts), + usecs_to_jiffies(usecs) + 1)) + dev_warn(&core->client->dev, + "(%s) [CMD 0x%02x] Answer timeout.\n", + __func__, command); /* When working in polling mode, for some reason the tuner will diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c index d32e25c2128d..0e4a76daf187 100644 --- a/drivers/mfd/si476x-i2c.c +++ b/drivers/mfd/si476x-i2c.c @@ -303,7 +303,7 @@ int si476x_core_set_power_state(struct si476x_core *core, */ udelay(100); - err = si476x_core_start(core, true); + err = si476x_core_start(core, false); if (err < 0) goto disable_regulators; @@ -312,7 +312,7 @@ int si476x_core_set_power_state(struct si476x_core *core, case SI476X_POWER_DOWN: core->power_state = next_state; - err = si476x_core_stop(core, true); + err = si476x_core_stop(core, false); if (err < 0) core->power_state = SI476X_POWER_INCONSISTENT; disable_regulators: @@ -740,15 +740,8 @@ static int si476x_core_probe(struct i2c_client *client, memcpy(&core->pinmux, &pdata->pinmux, sizeof(struct si476x_pinmux)); } else { - dev_warn(&client->dev, "Using default platform data.\n"); - core->power_up_parameters.xcload = 0x28; - core->power_up_parameters.func = SI476X_FUNC_FM_RECEIVER; - core->power_up_parameters.freq = SI476X_FREQ_37P209375_MHZ; - core->diversity_mode = SI476X_PHDIV_DISABLED; - core->pinmux.dclk = SI476X_DCLK_DAUDIO; - core->pinmux.dfs = SI476X_DFS_DAUDIO; - core->pinmux.dout = SI476X_DOUT_I2S_OUTPUT; - core->pinmux.xout = SI476X_XOUT_TRISTATE; + dev_err(&client->dev, "No platform data provided\n"); + return -EINVAL; } core->supplies[0].supply = "vd"; @@ -806,10 +799,6 @@ static int si476x_core_probe(struct i2c_client *client, core->chip_id = id->driver_data; - /* Power down si476x first */ - core->power_state = SI476X_POWER_UP_FULL; - si476x_core_set_power_state(core, SI476X_POWER_DOWN); - rval = si476x_core_get_revision_info(core); if (rval < 0) { rval = -ENODEV; diff --git a/drivers/mfd/si476x-prop.c b/drivers/mfd/si476x-prop.c index 3ff2cae9cbab..cfeffa6e15d9 100644 --- a/drivers/mfd/si476x-prop.c +++ b/drivers/mfd/si476x-prop.c @@ -217,36 +217,15 @@ static int si476x_core_regmap_read(void *context, unsigned int reg, return 0; } -static bool si476x_core_regmap_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case SI476X_PROP_DIGITAL_IO_OUTPUT_SAMPLE_RATE: - case SI476X_PROP_DIGITAL_IO_OUTPUT_FORMAT: - return false; - default: - return true; - } - - return true; -} - -/* These two register is used by the codec, so add reg_default here */ -static struct reg_default si476x_core_reg[] = { - { 0x202, 0xBB80 }, - { 0x203, 0x1700 }, -}; static const struct regmap_config si476x_regmap_config = { .reg_bits = 16, .val_bits = 16, .max_register = 0x4003, - .reg_defaults = si476x_core_reg, - .num_reg_defaults = ARRAY_SIZE(si476x_core_reg), .writeable_reg = si476x_core_regmap_writable_register, .readable_reg = si476x_core_regmap_readable_register, - .volatile_reg = si476x_core_regmap_volatile_register, .reg_read = si476x_core_regmap_read, .reg_write = si476x_core_regmap_write, diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index b2ce321737d4..21181fa243df 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c @@ -32,7 +32,7 @@ #include #include -#define SRAM_GRANULARITY 4096 +#define SRAM_GRANULARITY 32 struct sram_dev { struct gen_pool *pool; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 249f4d5bca65..793c6f7ddb04 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -348,11 +348,6 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) mmc_card_set_blockaddr(card); } - card->ext_csd.boot_info = ext_csd[EXT_CSD_BOOT_INFO]; - card->ext_csd.boot_config = ext_csd[EXT_CSD_PART_CONFIG]; - card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT]; - card->ext_csd.boot_bus_width = ext_csd[EXT_CSD_BOOT_BUS_WIDTH]; - card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; mmc_select_card_type(card); @@ -696,372 +691,6 @@ out: return err; } -static ssize_t mmc_boot_info_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - char *boot_partition[8] = { - "Device not boot enabled", - "Boot partition 1 enabled", - "Boot partition 2 enabled", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "User area enabled for boot"}; - - char *bus_width[4] = { - "x1 (sdr) or x4 (ddr) bus width in boot operation mode", - "x4 (sdr/ddr) bus width in boot operation mode", - "x8 (sdr/ddr) bus width in boot operation mode", - "Reserved"}; - - char *boot_mode[4] = { - "Use single data rate + backward compatible timings in boot operation", - "Use single data rate + high speed timings in boot operation mode", - "Use dual data rate in boot operation", - "Reserved"}; - - int partition; - int width; - int mode; - int err; - u8 *ext_csd = NULL; - struct mmc_card *card = container_of(dev, struct mmc_card, dev); - - /* read it again because user may change it */ - mmc_claim_host(card->host); - err = mmc_get_ext_csd(card, &ext_csd); - mmc_release_host(card->host); - if (err || !ext_csd) { - pr_err("%s: failed to get ext_csd, err=%d\n", - mmc_hostname(card->host), - err); - return err; - } - - mmc_read_ext_csd(card, ext_csd); - mmc_free_ext_csd(ext_csd); - - partition = (card->ext_csd.boot_config >> 3) & 0x7; - width = card->ext_csd.boot_bus_width & 0x3; - mode = (card->ext_csd.boot_bus_width >> 3) & 0x3; - - return sprintf(buf, - "boot_info:0x%02x;\n" - " ALT_BOOT_MODE:%x - %s\n" - " DDR_BOOT_MODE:%x - %s\n" - " HS_BOOTMODE:%x - %s\n" - "boot_size:%04dKB\n" - "boot_partition:0x%02x;\n" - " BOOT_ACK:%x - %s\n" - " BOOT_PARTITION-ENABLE: %x - %s\n" - "boot_bus:0x%02x\n" - " BOOT_MODE:%x - %s\n" - " RESET_BOOT_BUS_WIDTH:%x - %s\n" - " BOOT_BUS_WIDTH:%x - %s\n", - - card->ext_csd.boot_info, - !!(card->ext_csd.boot_info & 0x1), - (card->ext_csd.boot_info & 0x1) ? - "Supports alternate boot method" : - "Does not support alternate boot method", - !!(card->ext_csd.boot_info & 0x2), - (card->ext_csd.boot_info & 0x2) ? - "Supports alternate dual data rate during boot" : - "Does not support dual data rate during boot", - !!(card->ext_csd.boot_info & 0x4), - (card->ext_csd.boot_info & 0x4) ? - "Supports high speed timing during boot" : - "Does not support high speed timing during boot", - - card->ext_csd.boot_size * 128, - - card->ext_csd.boot_config, - !!(card->ext_csd.boot_config & 0x40), - (card->ext_csd.boot_config & 0x40) ? - "Boot acknowledge sent during boot operation" : - "No boot acknowledge sent", - partition, - boot_partition[partition], - - card->ext_csd.boot_bus_width, - mode, - boot_mode[mode], - !!(card->ext_csd.boot_bus_width & 0x4), - (card->ext_csd.boot_bus_width & 0x4) ? - "Retain boot bus width and boot mode after boot operation" : - "Reset bus width to x1, single data rate and backward" - "compatible timings after boot operation", - width, - bus_width[width]); -} - -/* set up boot partitions */ -static ssize_t -setup_boot_partitions(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int err, busy = 0; - u32 part; - u8 *ext_csd, boot_config; - struct mmc_command cmd; - struct mmc_card *card = container_of(dev, struct mmc_card, dev); - - BUG_ON(!card); - - sscanf(buf, "%d\n", &part); - - if (card->csd.mmca_vsn < CSD_SPEC_VER_4) { - pr_err("%s: invalid mmc version" \ - " mmc version is below version 4!)\n", - mmc_hostname(card->host)); - return -EINVAL; - } - - /* it's a normal SD/MMC but user request to configure boot partition */ - if (card->ext_csd.boot_size <= 0) { - pr_err("%s: fail to send SWITCH command to card " \ - "to update boot_config of the EXT_CSD!\n", - mmc_hostname(card->host)); - return -EINVAL; - } - - /* - * partition must be - - * 0 - user area - * 1 - boot partition 1 - * 2 - boot partition 2 - * DO NOT switch the partitions that used to be accessed - * in OS layer HERE - */ - if (part & EXT_CSD_BOOT_PARTITION_ACCESS_MASK) { - pr_err("%s: DO NOT switch the partitions that used to be\n" \ - " accessed in OS layer HERE. please following the\n" \ - " guidance of Documentation/mmc/mmc-dev-parts.txt.\n", - mmc_hostname(card->host)); - return -EINVAL; - } - - ext_csd = kmalloc(512, GFP_KERNEL); - if (!ext_csd) { - pr_err("%s: could not allocate a buffer to " \ - "receive the ext_csd.\n", mmc_hostname(card->host)); - return -ENOMEM; - } - - mmc_claim_host(card->host); - err = mmc_send_ext_csd(card, ext_csd); - if (err) { - pr_err("%s: unable to read EXT_CSD.\n", - mmc_hostname(card->host)); - goto err_rtn; - } - - /* enable the boot partition in boot mode */ - /* boot enable be - - * 0x00 - disable boot enable. - * 0x08 - boot partition 1 is enabled for boot. - * 0x10 - boot partition 2 is enabled for boot. - * 0x38 - User area is enabled for boot. - */ - switch (part & EXT_CSD_BOOT_PARTITION_ENABLE_MASK) { - case 0: - boot_config = (ext_csd[EXT_CSD_PART_CONFIG] - & ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK - & ~EXT_CSD_BOOT_ACK_ENABLE); - break; - case EXT_CSD_BOOT_PARTITION_PART1: - boot_config = ((ext_csd[EXT_CSD_PART_CONFIG] - & ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK) - | EXT_CSD_BOOT_PARTITION_PART1 - | EXT_CSD_BOOT_ACK_ENABLE); - break; - case EXT_CSD_BOOT_PARTITION_PART2: - boot_config = ((ext_csd[EXT_CSD_PART_CONFIG] - & ~EXT_CSD_BOOT_PARTITION_ENABLE_MASK) - | EXT_CSD_BOOT_PARTITION_PART2 - | EXT_CSD_BOOT_ACK_ENABLE); - break; - case EXT_CSD_BOOT_PARTITION_ENABLE_MASK: - boot_config = ((ext_csd[EXT_CSD_PART_CONFIG] - | EXT_CSD_BOOT_PARTITION_ENABLE_MASK) - & ~EXT_CSD_BOOT_ACK_ENABLE); - break; - default: - pr_err("%s: wrong boot config parameter" \ - " 00 (disable boot), 08 (enable boot1)," \ - "16 (enable boot2), 56 (User area)\n", - mmc_hostname(card->host)); - err = -EINVAL; - goto err_rtn; - } - - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_PART_CONFIG, boot_config, card->ext_csd.part_time); - if (err) { - pr_err("%s: fail to send SWITCH command to card " \ - "to update boot_config of the EXT_CSD!\n", - mmc_hostname(card->host)); - goto err_rtn; - } - - /* waiting for the card to finish the busy state */ - do { - memset(&cmd, 0, sizeof(struct mmc_command)); - - cmd.opcode = MMC_SEND_STATUS; - cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - - err = mmc_wait_for_cmd(card->host, &cmd, 0); - if (err || busy > 100) { - pr_err("%s: failed to wait for" \ - "the busy state to end.\n", - mmc_hostname(card->host)); - break; - } - - if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) { - pr_info("%s: card is in busy state" \ - "pls wait for busy state to end.\n", - mmc_hostname(card->host)); - } - busy++; - } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); - - /* Now check whether it works */ - err = mmc_send_ext_csd(card, ext_csd); - if (err) { - pr_err("%s: %d unable to re-read EXT_CSD.\n", - mmc_hostname(card->host), err); - goto err_rtn; - } - - card->ext_csd.boot_config = ext_csd[EXT_CSD_PART_CONFIG]; - -err_rtn: - mmc_release_host(card->host); - kfree(ext_csd); - if (err) - return err; - else - return count; -} - -/* configure the boot bus */ -static ssize_t -setup_boot_bus(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int err, busy = 0; - u32 boot_bus, new_bus; - u8 *ext_csd; - struct mmc_command cmd; - struct mmc_card *card = container_of(dev, struct mmc_card, dev); - - BUG_ON(!card); - - sscanf(buf, "%d\n", &boot_bus); - - if (card->csd.mmca_vsn < CSD_SPEC_VER_4) { - pr_err("%s: invalid mmc version" \ - " mmc version is below version 4!)\n", - mmc_hostname(card->host)); - return -EINVAL; - } - - /* it's a normal SD/MMC but user request to configure boot bus */ - if (card->ext_csd.boot_size <= 0) { - pr_err("%s: this is a normal SD/MMC card" \ - " but you request to configure boot bus !\n", - mmc_hostname(card->host)); - return -EINVAL; - } - - ext_csd = kmalloc(512, GFP_KERNEL); - if (!ext_csd) { - pr_err("%s: could not allocate a buffer to " \ - "receive the ext_csd.\n", mmc_hostname(card->host)); - return -ENOMEM; - } - - mmc_claim_host(card->host); - err = mmc_send_ext_csd(card, ext_csd); - if (err) { - pr_err("%s: unable to read EXT_CSD.\n", - mmc_hostname(card->host)); - goto err_rtn; - } - - /* Configure the boot bus width when boot partition is enabled */ - if (((boot_bus & EXT_CSD_BOOT_BUS_WIDTH_MODE_MASK) >> 3) > 2 - || (boot_bus & EXT_CSD_BOOT_BUS_WIDTH_WIDTH_MASK) > 2 - || (boot_bus & ~EXT_CSD_BOOT_BUS_WIDTH_MASK) > 0) { - pr_err("%s: Invalid inputs!\n", - mmc_hostname(card->host)); - err = -EINVAL; - goto err_rtn; - } - - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BOOT_BUS_WIDTH, boot_bus, card->ext_csd.part_time); - if (err) { - pr_err("%s: fail to send SWITCH command to card " \ - "to update boot_config of the EXT_CSD!\n", - mmc_hostname(card->host)); - goto err_rtn; - } - - /* waiting for the card to finish the busy state */ - do { - memset(&cmd, 0, sizeof(struct mmc_command)); - - cmd.opcode = MMC_SEND_STATUS; - cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - - err = mmc_wait_for_cmd(card->host, &cmd, 0); - if (err || busy > 100) { - pr_err("%s: failed to wait for" \ - "the busy state to end.\n", - mmc_hostname(card->host)); - break; - } - - if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) { - pr_info("%s: card is in busy state" \ - "pls wait for busy state to end.\n", - mmc_hostname(card->host)); - } - busy++; - } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); - - /* Now check whether it works */ - err = mmc_send_ext_csd(card, ext_csd); - if (err) { - pr_err("%s: %d unable to re-read EXT_CSD.\n", - mmc_hostname(card->host), err); - goto err_rtn; - } - - new_bus = ext_csd[EXT_CSD_BOOT_BUS_WIDTH]; - if (boot_bus != new_bus) { - pr_err("%s: after SWITCH, current boot bus mode %d" \ - " is not same as requested bus mode %d!\n", - mmc_hostname(card->host), new_bus, boot_bus); - goto err_rtn; - } - card->ext_csd.boot_bus_width = ext_csd[EXT_CSD_BOOT_BUS_WIDTH]; - -err_rtn: - mmc_release_host(card->host); - mmc_free_ext_csd(ext_csd); - if (err) - return err; - else - return count; -} - MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], card->raw_cid[2], card->raw_cid[3]); MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], @@ -1081,9 +710,6 @@ MMC_DEV_ATTR(enhanced_area_offset, "%llu\n", MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult); MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors); -DEVICE_ATTR(boot_info, S_IRUGO, mmc_boot_info_show, NULL); -DEVICE_ATTR(boot_config, S_IWUGO, NULL, setup_boot_partitions); -DEVICE_ATTR(boot_bus_config, S_IWUGO, NULL, setup_boot_bus); static struct attribute *mmc_std_attrs[] = { &dev_attr_cid.attr, @@ -1102,9 +728,6 @@ static struct attribute *mmc_std_attrs[] = { &dev_attr_enhanced_area_size.attr, &dev_attr_raw_rpmb_size_mult.attr, &dev_attr_rel_sectors.attr, - &dev_attr_boot_info.attr, - &dev_attr_boot_config.attr, - &dev_attr_boot_bus_config.attr, NULL, }; ATTRIBUTE_GROUPS(mmc_std); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 8d62cecd3002..47055f3f01b8 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2518,7 +2518,6 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) #ifdef CONFIG_PM void sdhci_enable_irq_wakeups(struct sdhci_host *host) { - int gpio_cd = mmc_gpio_get_cd(host->mmc); u8 val; u8 mask = SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE | SDHCI_WAKE_ON_INT; @@ -2526,8 +2525,7 @@ void sdhci_enable_irq_wakeups(struct sdhci_host *host) val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL); val |= mask ; /* Avoid fake wake up */ - if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION || - !IS_ERR_VALUE(gpio_cd)) + if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) val &= ~(SDHCI_WAKE_ON_INSERT | SDHCI_WAKE_ON_REMOVE); sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL); } diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index fe88ba3ac92d..e21fde9d4d7e 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -1053,13 +1053,17 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip, #define UDELAY(map, chip, adr, usec) \ do { \ + mutex_unlock(&chip->mutex); \ cfi_udelay(usec); \ + mutex_lock(&chip->mutex); \ } while (0) #define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \ do { \ + mutex_unlock(&chip->mutex); \ INVALIDATE_CACHED_RANGE(map, adr, len); \ cfi_udelay(usec); \ + mutex_lock(&chip->mutex); \ } while (0) #endif diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 405a92297719..6e30a3c280d0 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -640,7 +640,7 @@ static int io_init(struct ubi_device *ubi, int max_beb_per1024) dbg_gen("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb)); dbg_gen("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry)); - if (ubi->mtd->numeraseregions > 1) { + if (ubi->mtd->numeraseregions != 0) { /* * Some flashes have several erase regions. Different regions * may have different eraseblock size and other diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c index 96c79d5add1c..564682c64a55 100644 --- a/drivers/mxc/vpu/mxc_vpu.c +++ b/drivers/mxc/vpu/mxc_vpu.c @@ -45,33 +45,15 @@ #include #include #include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) #include #include #include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) -#include -#include -#include -#include -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) #include #include +#include #include #include #include -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) -#include -#include -#else -#include -#endif /* Define one new pgprot which combined uncached and XN(never executable) */ #define pgprot_noncachedxn(prot) \ @@ -82,6 +64,15 @@ struct vpu_priv { struct work_struct work; struct workqueue_struct *workqueue; struct mutex lock; + const struct mxc_vpu_soc_data *soc_data; + int clk_enabled; + struct list_head users; +}; + +struct vpu_user_data { + struct vpu_priv *vpu_data; + struct list_head list; + int clk_enable_cnt; }; /* To track the allocated memory buffer */ @@ -95,32 +86,36 @@ struct iram_setting { u32 end; }; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) +struct mxc_vpu_soc_data { + unsigned vpu_pwr_mgmnt:1, + regulator_required:1, + quirk_subblk_en:1, + is_mx51:1, + is_mx53:1, + is_mx6dl:1, + is_mx6q:1, + has_jpu:1; +}; + static struct gen_pool *iram_pool; static u32 iram_base; -#endif -static LIST_HEAD(head); +static LIST_HEAD(mem_list); static int vpu_major; -static int vpu_clk_usercount; static struct class *vpu_class; static struct vpu_priv vpu_data; static u8 open_count; static struct clk *vpu_clk; -static struct vpu_mem_desc bitwork_mem = { 0 }; -static struct vpu_mem_desc pic_para_mem = { 0 }; -static struct vpu_mem_desc user_data_mem = { 0 }; -static struct vpu_mem_desc share_mem = { 0 }; -static struct vpu_mem_desc vshare_mem = { 0 }; +static struct vpu_mem_desc bitwork_mem; +static struct vpu_mem_desc pic_para_mem; +static struct vpu_mem_desc user_data_mem; +static struct vpu_mem_desc share_mem; +static struct vpu_mem_desc vshare_mem; static void __iomem *vpu_base; static int vpu_ipi_irq; static u32 phy_vpu_base_addr; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) -static phys_addr_t top_address_DRAM; -static struct mxc_vpu_platform_data *vpu_plat; -#endif static struct device *vpu_dev; @@ -132,122 +127,68 @@ static int irq_status; static int codec_done; static wait_queue_head_t vpu_queue; -#ifdef CONFIG_SOC_IMX6Q -#define MXC_VPU_HAS_JPU -#endif - -#ifdef MXC_VPU_HAS_JPU static int vpu_jpu_irq; -#endif #ifdef CONFIG_PM static unsigned int regBk[64]; static unsigned int pc_before_suspend; #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) static struct regulator *vpu_regulator; -#endif -static atomic_t clk_cnt_from_ioc = ATOMIC_INIT(0); -#define READ_REG(x) readl_relaxed(vpu_base + x) -#define WRITE_REG(val, x) writel_relaxed(val, vpu_base + x) +#define READ_REG(x) readl_relaxed(vpu_base + (x)) +#define WRITE_REG(val, x) writel_relaxed(val, vpu_base + (x)) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) -/* redirect to static functions */ -static int cpu_is_mx6dl(void) +static int vpu_clk_enable(struct vpu_priv *vpu_data) { - int ret; - ret = of_machine_is_compatible("fsl,imx6dl"); - return ret; -} + int ret = 0; -static int cpu_is_mx6q(void) -{ - int ret; - ret = of_machine_is_compatible("fsl,imx6q"); - return ret; -} -#endif + if (vpu_data->clk_enabled++ == 0) + ret = clk_prepare_enable(vpu_clk); -static void vpu_reset(void) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) - device_reset(vpu_dev); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) - imx_src_reset_vpu(); -#else - if (vpu_plat->reset) - vpu_plat->reset(); -#endif -} + if (WARN_ON(vpu_data->clk_enabled <= 0)) + return -EINVAL; -static long vpu_power_get(bool on) -{ - long ret = 0; - - if (on) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) - vpu_regulator = regulator_get(NULL, "cpu_vddvpu"); - ret = IS_ERR(vpu_regulator); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) - vpu_regulator = devm_regulator_get(vpu_dev, "pu"); - ret = IS_ERR(vpu_regulator); -#endif - } else { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) - if (!IS_ERR(vpu_regulator)) - regulator_put(vpu_regulator); -#endif - } return ret; } -static void vpu_power_up(bool on) +static int vpu_clk_disable(struct vpu_priv *vpu_data) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) - int ret = 0; + if (WARN_ON(vpu_data->clk_enabled == 0)) + return -EINVAL; - if (on) { - if (!IS_ERR(vpu_regulator)) { - ret = regulator_enable(vpu_regulator); - if (ret) - dev_err(vpu_dev, "failed to power up vpu\n"); - } - } else { - if (!IS_ERR(vpu_regulator)) { - ret = regulator_disable(vpu_regulator); - if (ret) - dev_err(vpu_dev, "failed to power down vpu\n"); - } - } -#else - imx_gpc_power_up_pu(on); -#endif + if (--vpu_data->clk_enabled == 0) + clk_disable_unprepare(vpu_clk); + return 0; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) -static void request_bus_freq(int freq) +static inline int vpu_reset(void) { + return device_reset(vpu_dev); } -static void release_bus_freq(int freq) +static void vpu_power_up(void) { -} + int ret; -static int cpu_is_mx53(void) -{ - return 0; + if (IS_ERR(vpu_regulator)) + return; + + ret = regulator_enable(vpu_regulator); + if (ret) + dev_err(vpu_dev, "failed to power up vpu: %d\n", ret); } -static int cpu_is_mx51(void) +static void vpu_power_down(void) { - return 0; -} + int ret; -#define VM_RESERVED 0 -#define BUS_FREQ_HIGH 0 + if (IS_ERR(vpu_regulator)) + return; -#endif + ret = regulator_disable(vpu_regulator); + if (ret) + dev_err(vpu_dev, "failed to power down vpu: %d\n", ret); +} /*! * Private function to alloc dma buffer @@ -255,14 +196,13 @@ static int cpu_is_mx51(void) */ static int vpu_alloc_dma_buffer(struct vpu_mem_desc *mem) { - mem->cpu_addr = (unsigned long) - dma_alloc_coherent(NULL, PAGE_ALIGN(mem->size), - (dma_addr_t *) (&mem->phy_addr), - GFP_DMA | GFP_KERNEL); - dev_dbg(vpu_dev, "[ALLOC] mem alloc cpu_addr = 0x%x\n", mem->cpu_addr); - if ((void *)(mem->cpu_addr) == NULL) { + mem->cpu_addr = dma_alloc_coherent(vpu_dev, PAGE_ALIGN(mem->size), + &mem->phy_addr, + GFP_DMA | GFP_KERNEL); + dev_dbg(vpu_dev, "[ALLOC] mem alloc cpu_addr = %p\n", mem->cpu_addr); + if (mem->cpu_addr == NULL) { dev_err(vpu_dev, "Physical memory allocation error!\n"); - return -1; + return -ENOMEM; } return 0; } @@ -272,10 +212,9 @@ static int vpu_alloc_dma_buffer(struct vpu_mem_desc *mem) */ static void vpu_free_dma_buffer(struct vpu_mem_desc *mem) { - if (mem->cpu_addr != 0) { - dma_free_coherent(0, PAGE_ALIGN(mem->size), - (void *)mem->cpu_addr, mem->phy_addr); - } + if (mem->cpu_addr != NULL) + dma_free_coherent(vpu_dev, PAGE_ALIGN(mem->size), + mem->cpu_addr, mem->phy_addr); } /*! @@ -287,7 +226,7 @@ static int vpu_free_buffers(void) struct memalloc_record *rec, *n; struct vpu_mem_desc mem; - list_for_each_entry_safe(rec, n, &head, list) { + list_for_each_entry_safe(rec, n, &mem_list, list) { mem = rec->mem; if (mem.cpu_addr != 0) { vpu_free_dma_buffer(&mem); @@ -303,8 +242,7 @@ static int vpu_free_buffers(void) static inline void vpu_worker_callback(struct work_struct *w) { - struct vpu_priv *dev = container_of(w, struct vpu_priv, - work); + struct vpu_priv *dev = container_of(w, struct vpu_priv, work); if (dev->async_queue) kill_fasync(&dev->async_queue, SIGIO, POLL_IN); @@ -341,7 +279,6 @@ static irqreturn_t vpu_ipi_irq_handler(int irq, void *dev_id) /*! * @brief vpu jpu interrupt handler */ -#ifdef MXC_VPU_HAS_JPU static irqreturn_t vpu_jpu_irq_handler(int irq, void *dev_id) { struct vpu_priv *dev = dev_id; @@ -355,24 +292,6 @@ static irqreturn_t vpu_jpu_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -#endif - -/*! - * @brief check phy memory prepare to pass to vpu is valid or not, we - * already address some issue that if pass a wrong address to vpu - * (like virtual address), system will hang. - * - * @return true return is a valid phy memory address, false return not. - */ -bool vpu_is_valid_phy_memory(u32 paddr) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) - if (paddr > top_address_DRAM) - return false; -#endif - - return true; -} /*! * @brief open function for vpu file operation @@ -381,27 +300,25 @@ bool vpu_is_valid_phy_memory(u32 paddr) */ static int vpu_open(struct inode *inode, struct file *filp) { + struct vpu_user_data *user_data = devm_kzalloc(vpu_dev, + sizeof(*user_data), + GFP_KERNEL); + if (user_data == NULL) + return -ENOMEM; + + user_data->vpu_data = &vpu_data; + + INIT_LIST_HEAD(&user_data->list); + list_add(&user_data->list, &vpu_data.users); mutex_lock(&vpu_data.lock); if (open_count++ == 0) { - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) pm_runtime_get_sync(vpu_dev); -#endif - vpu_power_up(true); - -#ifdef CONFIG_SOC_IMX6Q - clk_prepare(vpu_clk); - clk_enable(vpu_clk); - if (READ_REG(BIT_CUR_PC)) - dev_dbg(vpu_dev, "Not power off before vpu open!\n"); - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); -#endif + vpu_power_up(); } - filp->private_data = (void *)(&vpu_data); + filp->private_data = user_data; mutex_unlock(&vpu_data.lock); return 0; } @@ -414,278 +331,250 @@ static int vpu_open(struct inode *inode, struct file *filp) static long vpu_ioctl(struct file *filp, u_int cmd, u_long arg) { - int ret = 0; + int ret = -EINVAL; + struct vpu_user_data *user_data = filp->private_data; + struct vpu_priv *vpu_data = user_data->vpu_data; switch (cmd) { case VPU_IOC_PHYMEM_ALLOC: - { - struct memalloc_record *rec; + { + struct memalloc_record *rec; - rec = kzalloc(sizeof(*rec), GFP_KERNEL); - if (!rec) - return -ENOMEM; + rec = kzalloc(sizeof(*rec), GFP_KERNEL); + if (!rec) + return -ENOMEM; - ret = copy_from_user(&(rec->mem), - (struct vpu_mem_desc *)arg, - sizeof(struct vpu_mem_desc)); - if (ret) { - kfree(rec); - return -EFAULT; - } + if (copy_from_user(&rec->mem, + (struct vpu_mem_desc *)arg, + sizeof(struct vpu_mem_desc))) { + kfree(rec); + return -EFAULT; + } - dev_dbg(vpu_dev, "[ALLOC] mem alloc size = 0x%x\n", - rec->mem.size); + dev_dbg(vpu_dev, "[ALLOC] mem alloc size = 0x%x\n", + rec->mem.size); - ret = vpu_alloc_dma_buffer(&(rec->mem)); - if (ret == -1) { - kfree(rec); - dev_err(vpu_dev, - "Physical memory allocation error!\n"); - break; - } - ret = copy_to_user((void __user *)arg, &(rec->mem), - sizeof(struct vpu_mem_desc)); - if (ret) { - kfree(rec); - ret = -EFAULT; - break; - } + ret = vpu_alloc_dma_buffer(&rec->mem); + if (ret) { + kfree(rec); + return ret; + } + if (copy_to_user((void __user *)arg, &rec->mem, + sizeof(struct vpu_mem_desc))) { + kfree(rec); + return -EFAULT; + } - mutex_lock(&vpu_data.lock); - list_add(&rec->list, &head); - mutex_unlock(&vpu_data.lock); + mutex_lock(&vpu_data->lock); + list_add(&rec->list, &mem_list); + mutex_unlock(&vpu_data->lock); - break; - } + break; + } case VPU_IOC_PHYMEM_FREE: - { - struct memalloc_record *rec, *n; - struct vpu_mem_desc vpu_mem; - - ret = copy_from_user(&vpu_mem, - (struct vpu_mem_desc *)arg, - sizeof(struct vpu_mem_desc)); - if (ret) - return -EACCES; - - dev_dbg(vpu_dev, "[FREE] mem freed cpu_addr = 0x%x\n", - vpu_mem.cpu_addr); - if ((void *)vpu_mem.cpu_addr != NULL) - vpu_free_dma_buffer(&vpu_mem); - - mutex_lock(&vpu_data.lock); - list_for_each_entry_safe(rec, n, &head, list) { - if (rec->mem.cpu_addr == vpu_mem.cpu_addr) { - /* delete from list */ - list_del(&rec->list); - kfree(rec); - break; - } + { + struct memalloc_record *rec, *n; + struct vpu_mem_desc vpu_mem; + + if (copy_from_user(&vpu_mem, + (struct vpu_mem_desc *)arg, + sizeof(struct vpu_mem_desc))) + return -EFAULT; + + dev_dbg(vpu_dev, "[FREE] mem freed cpu_addr = %p\n", + vpu_mem.cpu_addr); + if (vpu_mem.cpu_addr != NULL) + vpu_free_dma_buffer(&vpu_mem); + + mutex_lock(&vpu_data->lock); + list_for_each_entry_safe(rec, n, &mem_list, list) { + if (rec->mem.cpu_addr == vpu_mem.cpu_addr) { + list_del(&rec->list); + break; } - mutex_unlock(&vpu_data.lock); - - break; } + kfree(rec); + mutex_unlock(&vpu_data->lock); + + break; + } case VPU_IOC_WAIT4INT: - { - u_long timeout = (u_long) arg; - if (!wait_event_interruptible_timeout - (vpu_queue, irq_status != 0, - msecs_to_jiffies(timeout))) { - dev_warn(vpu_dev, "VPU blocking: timeout.\n"); - ret = -ETIME; - } else if (signal_pending(current)) { - dev_warn(vpu_dev, "VPU interrupt received.\n"); - ret = -ERESTARTSYS; - } else - irq_status = 0; - break; + { + u_long timeout = arg; + + ret = wait_event_interruptible_timeout(vpu_queue, + irq_status != 0, + msecs_to_jiffies(timeout)); + if (ret == 0) { + dev_warn(vpu_dev, "VPU blocking: timeout.\n"); + ret = -ETIMEDOUT; + } else if (signal_pending(current)) { + dev_warn(vpu_dev, "VPU interrupt received.\n"); + ret = -ERESTARTSYS; + } else { + irq_status = 0; } + break; + } case VPU_IOC_IRAM_SETTING: - { - ret = copy_to_user((void __user *)arg, &iram, - sizeof(struct iram_setting)); - if (ret) - ret = -EFAULT; + ret = copy_to_user((void __user *)arg, &iram, + sizeof(struct iram_setting)); + if (ret) + ret = -EFAULT; - break; - } + break; case VPU_IOC_CLKGATE_SETTING: - { - u32 clkgate_en; + { + u32 clkgate_en; - if (get_user(clkgate_en, (u32 __user *) arg)) - return -EFAULT; + if (get_user(clkgate_en, (u32 __user *)arg)) + return -EFAULT; - if (clkgate_en) { - clk_prepare(vpu_clk); - clk_enable(vpu_clk); - atomic_inc(&clk_cnt_from_ioc); + mutex_lock(&vpu_data->lock); + if (clkgate_en) { + ret = vpu_clk_enable(vpu_data); + if (ret == 0) + user_data->clk_enable_cnt++; + } else { + if (user_data->clk_enable_cnt == 0) { + ret = -EINVAL; } else { - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); - atomic_dec(&clk_cnt_from_ioc); + if (--user_data->clk_enable_cnt == 0) + vpu_clk_disable(vpu_data); + ret = 0; } - - break; } + mutex_unlock(&vpu_data->lock); + break; + } case VPU_IOC_GET_SHARE_MEM: - { - mutex_lock(&vpu_data.lock); - if (share_mem.cpu_addr != 0) { - ret = copy_to_user((void __user *)arg, - &share_mem, - sizeof(struct vpu_mem_desc)); - mutex_unlock(&vpu_data.lock); - break; - } else { - if (copy_from_user(&share_mem, - (struct vpu_mem_desc *)arg, - sizeof(struct vpu_mem_desc))) { - mutex_unlock(&vpu_data.lock); - return -EFAULT; - } - if (vpu_alloc_dma_buffer(&share_mem) == -1) - ret = -EFAULT; - else { - if (copy_to_user((void __user *)arg, - &share_mem, - sizeof(struct - vpu_mem_desc))) - ret = -EFAULT; - } + mutex_lock(&vpu_data->lock); + if (share_mem.cpu_addr == NULL) { + if (copy_from_user(&share_mem, + (struct vpu_mem_desc *)arg, + sizeof(struct vpu_mem_desc))) { + mutex_unlock(&vpu_data->lock); + return -EFAULT; + } + ret = vpu_alloc_dma_buffer(&share_mem); + if (ret) { + mutex_unlock(&vpu_data->lock); + return ret; } - mutex_unlock(&vpu_data.lock); - break; } + if (copy_to_user((void __user *)arg, + &share_mem, + sizeof(struct vpu_mem_desc))) + ret = -EFAULT; + else + ret = 0; + mutex_unlock(&vpu_data->lock); + break; case VPU_IOC_REQ_VSHARE_MEM: - { - mutex_lock(&vpu_data.lock); - if (vshare_mem.cpu_addr != 0) { - ret = copy_to_user((void __user *)arg, - &vshare_mem, - sizeof(struct vpu_mem_desc)); - mutex_unlock(&vpu_data.lock); - break; - } else { - if (copy_from_user(&vshare_mem, - (struct vpu_mem_desc *)arg, - sizeof(struct - vpu_mem_desc))) { - mutex_unlock(&vpu_data.lock); - return -EFAULT; - } - /* vmalloc shared memory if not allocated */ - if (!vshare_mem.cpu_addr) - vshare_mem.cpu_addr = - (unsigned long) - vmalloc_user(vshare_mem.size); - if (copy_to_user - ((void __user *)arg, &vshare_mem, - sizeof(struct vpu_mem_desc))) - ret = -EFAULT; + mutex_lock(&vpu_data->lock); + if (vshare_mem.cpu_addr == NULL) { + if (copy_from_user(&vshare_mem, + (struct vpu_mem_desc *)arg, + sizeof(struct + vpu_mem_desc))) { + mutex_unlock(&vpu_data->lock); + return -EFAULT; + } + vshare_mem.cpu_addr = vmalloc_user(vshare_mem.size); + if (vshare_mem.cpu_addr == NULL) { + mutex_unlock(&vpu_data->lock); + return -ENOMEM; } - mutex_unlock(&vpu_data.lock); - break; } + if (copy_to_user((void __user *)arg, &vshare_mem, + sizeof(struct vpu_mem_desc))) + ret = -EFAULT; + else + ret = 0; + mutex_unlock(&vpu_data->lock); + break; case VPU_IOC_GET_WORK_ADDR: - { - if (bitwork_mem.cpu_addr != 0) { - ret = - copy_to_user((void __user *)arg, - &bitwork_mem, - sizeof(struct vpu_mem_desc)); - break; - } else { - if (copy_from_user(&bitwork_mem, - (struct vpu_mem_desc *)arg, - sizeof(struct vpu_mem_desc))) - return -EFAULT; - - if (vpu_alloc_dma_buffer(&bitwork_mem) == -1) - ret = -EFAULT; - else if (copy_to_user((void __user *)arg, - &bitwork_mem, - sizeof(struct - vpu_mem_desc))) - ret = -EFAULT; - } - break; + if (bitwork_mem.cpu_addr == 0) { + if (copy_from_user(&bitwork_mem, + (struct vpu_mem_desc *)arg, + sizeof(struct vpu_mem_desc))) + return -EFAULT; + + ret = vpu_alloc_dma_buffer(&bitwork_mem); + if (ret) + return ret; } + if (copy_to_user((void __user *)arg, + &bitwork_mem, + sizeof(struct + vpu_mem_desc))) + ret = -EFAULT; + else + ret = 0; + break; /* - * The following two ioctl is used when user allocates working buffer - * and register it to vpu driver. + * The following two ioctls are used when user allocates a working buffer + * and registers it to vpu driver. */ case VPU_IOC_QUERY_BITWORK_MEM: - { - if (copy_to_user((void __user *)arg, - &bitwork_mem, - sizeof(struct vpu_mem_desc))) - ret = -EFAULT; - break; - } + if (copy_to_user((void __user *)arg, + &bitwork_mem, + sizeof(struct vpu_mem_desc))) + ret = -EFAULT; + else + ret = 0; + break; case VPU_IOC_SET_BITWORK_MEM: - { - if (copy_from_user(&bitwork_mem, - (struct vpu_mem_desc *)arg, - sizeof(struct vpu_mem_desc))) - ret = -EFAULT; - break; - } + if (copy_from_user(&bitwork_mem, + (struct vpu_mem_desc *)arg, + sizeof(struct vpu_mem_desc))) + ret = -EFAULT; + else + ret = 0; + break; case VPU_IOC_SYS_SW_RESET: - { - vpu_reset(); - break; - } - case VPU_IOC_REG_DUMP: + ret = vpu_reset(); break; + case VPU_IOC_REG_DUMP: case VPU_IOC_PHYMEM_DUMP: + ret = 0; break; case VPU_IOC_PHYMEM_CHECK: { struct vpu_mem_desc check_memory; + ret = copy_from_user(&check_memory, - (void __user *)arg, - sizeof(struct vpu_mem_desc)); + (void __user *)arg, + sizeof(struct vpu_mem_desc)); if (ret != 0) { dev_err(vpu_dev, "copy from user failure:%d\n", ret); ret = -EFAULT; break; } - ret = vpu_is_valid_phy_memory((u32)check_memory.phy_addr); - - dev_dbg(vpu_dev, "vpu: memory phy:0x%x %s phy memory\n", - check_memory.phy_addr, (ret ? "is" : "isn't")); - /* borrow .size to pass back the result. */ - check_memory.size = ret; - ret = copy_to_user((void __user *)arg, &check_memory, - sizeof(struct vpu_mem_desc)); - if (ret) { + check_memory.size = 1; + if (copy_to_user((void __user *)arg, &check_memory, + sizeof(struct vpu_mem_desc))) ret = -EFAULT; - break; - } + else + ret = 0; break; } case VPU_IOC_LOCK_DEV: - { - u32 lock_en; - - if (get_user(lock_en, (u32 __user *) arg)) - return -EFAULT; + { + u32 lock_en; - if (lock_en) - mutex_lock(&vpu_data.lock); - else - mutex_unlock(&vpu_data.lock); + if (get_user(lock_en, (u32 __user *)arg)) + return -EFAULT; - break; - } + if (lock_en) + mutex_lock(&vpu_data->lock); + else + mutex_unlock(&vpu_data->lock); + ret = 0; + break; + } default: - { - dev_err(vpu_dev, "No such IOCTL, cmd is %d\n", cmd); - ret = -EINVAL; - break; - } + dev_err(vpu_dev, "No such IOCTL, cmd is %d\n", cmd); } return ret; } @@ -696,16 +585,15 @@ static long vpu_ioctl(struct file *filp, u_int cmd, */ static int vpu_release(struct inode *inode, struct file *filp) { - int i; unsigned long timeout; + struct vpu_user_data *user_data = filp->private_data; + struct vpu_priv *vpu_data = user_data->vpu_data; - mutex_lock(&vpu_data.lock); - - if (open_count > 0 && !(--open_count)) { + mutex_lock(&vpu_data->lock); + if (open_count > 0 && !--open_count) { /* Wait for vpu go to idle state */ - clk_prepare(vpu_clk); - clk_enable(vpu_clk); + vpu_clk_enable(vpu_data); if (READ_REG(BIT_CUR_PC)) { timeout = jiffies + HZ; @@ -716,29 +604,23 @@ static int vpu_release(struct inode *inode, struct file *filp) break; } } - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); /* Clean up interrupt */ - cancel_work_sync(&vpu_data.work); - flush_workqueue(vpu_data.workqueue); + cancel_work_sync(&vpu_data->work); + flush_workqueue(vpu_data->workqueue); irq_status = 0; - clk_prepare(vpu_clk); - clk_enable(vpu_clk); if (READ_REG(BIT_BUSY_FLAG)) { - - if (cpu_is_mx51() || cpu_is_mx53()) { + if (vpu_data->soc_data->is_mx51 || + vpu_data->soc_data->is_mx53) { dev_err(vpu_dev, "fatal error: can't gate/power off when VPU is busy\n"); - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); - mutex_unlock(&vpu_data.lock); - return -EFAULT; + vpu_clk_disable(vpu_data); + mutex_unlock(&vpu_data->lock); + return -EBUSY; } - -#ifdef CONFIG_SOC_IMX6Q - if (cpu_is_mx6dl() || cpu_is_mx6q()) { + if (vpu_data->soc_data->is_mx6dl || + vpu_data->soc_data->is_mx6q) { WRITE_REG(0x11, 0x10F0); timeout = jiffies + HZ; while (READ_REG(0x10F4) != 0x77) { @@ -751,41 +633,32 @@ static int vpu_release(struct inode *inode, struct file *filp) dev_err(vpu_dev, "fatal error: can't gate/power off when VPU is busy\n"); WRITE_REG(0x0, 0x10F0); - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); - mutex_unlock(&vpu_data.lock); - return -EFAULT; - } else - vpu_reset(); + vpu_clk_disable(vpu_data); + mutex_unlock(&vpu_data->lock); + return -EBUSY; + } + vpu_reset(); } -#endif } } - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); vpu_free_buffers(); /* Free shared memory when vpu device is idle */ vpu_free_dma_buffer(&share_mem); share_mem.cpu_addr = 0; - vfree((void *)vshare_mem.cpu_addr); + vfree(vshare_mem.cpu_addr); vshare_mem.cpu_addr = 0; - vpu_clk_usercount = atomic_read(&clk_cnt_from_ioc); - for (i = 0; i < vpu_clk_usercount; i++) { - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); - atomic_dec(&clk_cnt_from_ioc); - } + if (user_data->clk_enable_cnt) + vpu_clk_disable(vpu_data); - vpu_power_up(false); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + vpu_clk_disable(vpu_data); + vpu_power_down(); pm_runtime_put_sync_suspend(vpu_dev); -#endif - + devm_kfree(vpu_dev, user_data); } - mutex_unlock(&vpu_data.lock); + mutex_unlock(&vpu_data->lock); return 0; } @@ -796,8 +669,9 @@ static int vpu_release(struct inode *inode, struct file *filp) */ static int vpu_fasync(int fd, struct file *filp, int mode) { - struct vpu_priv *dev = (struct vpu_priv *)filp->private_data; - return fasync_helper(fd, filp, mode, &dev->async_queue); + struct vpu_user_data *user_data = filp->private_data; + struct vpu_priv *vpu_data = user_data->vpu_data; + return fasync_helper(fd, filp, mode, &vpu_data->async_queue); } /*! @@ -808,7 +682,7 @@ static int vpu_map_hwregs(struct file *fp, struct vm_area_struct *vm) { unsigned long pfn; - vm->vm_flags |= VM_IO | VM_RESERVED; + vm->vm_flags |= VM_IO; /* * Since vpu registers have been mapped with ioremap() at probe * which L_PTE_XN is 1, and the same physical address must be @@ -817,10 +691,11 @@ static int vpu_map_hwregs(struct file *fp, struct vm_area_struct *vm) */ vm->vm_page_prot = pgprot_noncachedxn(vm->vm_page_prot); pfn = phy_vpu_base_addr >> PAGE_SHIFT; - dev_dbg(vpu_dev, "size=0x%x, page no.=0x%x\n", - (int)(vm->vm_end - vm->vm_start), (int)pfn); - return remap_pfn_range(vm, vm->vm_start, pfn, vm->vm_end - vm->vm_start, - vm->vm_page_prot) ? -EAGAIN : 0; + dev_dbg(vpu_dev, "size=0x%lx, page no.=0x%lx\n", + vm->vm_end - vm->vm_start, pfn); + return remap_pfn_range(vm, vm->vm_start, pfn, + vm->vm_end - vm->vm_start, + vm->vm_page_prot) ? -EAGAIN : 0; } /*! @@ -829,19 +704,16 @@ static int vpu_map_hwregs(struct file *fp, struct vm_area_struct *vm) */ static int vpu_map_dma_mem(struct file *fp, struct vm_area_struct *vm) { - int request_size; - request_size = vm->vm_end - vm->vm_start; + size_t request_size = vm->vm_end - vm->vm_start; - dev_dbg(vpu_dev, "start=0x%x, pgoff=0x%x, size=0x%x\n", - (unsigned int)(vm->vm_start), (unsigned int)(vm->vm_pgoff), - request_size); + dev_dbg(vpu_dev, "start=0x%08lx, pgoff=0x%08lx, size=%zx\n", + vm->vm_start, vm->vm_pgoff, request_size); - vm->vm_flags |= VM_IO | VM_RESERVED; + vm->vm_flags |= VM_IO; vm->vm_page_prot = pgprot_writecombine(vm->vm_page_prot); return remap_pfn_range(vm, vm->vm_start, vm->vm_pgoff, request_size, vm->vm_page_prot) ? -EAGAIN : 0; - } /* ! @@ -850,11 +722,10 @@ static int vpu_map_dma_mem(struct file *fp, struct vm_area_struct *vm) */ static int vpu_map_vshare_mem(struct file *fp, struct vm_area_struct *vm) { - int ret = -EINVAL; + int ret; ret = remap_vmalloc_range(vm, (void *)(vm->vm_pgoff << PAGE_SHIFT), 0); vm->vm_flags |= VM_IO; - return ret; } /*! @@ -865,7 +736,7 @@ static int vpu_mmap(struct file *fp, struct vm_area_struct *vm) { unsigned long offset; - offset = vshare_mem.cpu_addr >> PAGE_SHIFT; + offset = (unsigned long)vshare_mem.cpu_addr >> PAGE_SHIFT; if (vm->vm_pgoff && (vm->vm_pgoff == offset)) return vpu_map_vshare_mem(fp, vm); @@ -875,7 +746,7 @@ static int vpu_mmap(struct file *fp, struct vm_area_struct *vm) return vpu_map_hwregs(fp, vm); } -const struct file_operations vpu_fops = { +static const struct file_operations vpu_fops = { .owner = THIS_MODULE, .open = vpu_open, .unlocked_ioctl = vpu_ioctl, @@ -884,6 +755,35 @@ const struct file_operations vpu_fops = { .mmap = vpu_mmap, }; +static const struct mxc_vpu_soc_data imx6dl_vpu_data = { + .regulator_required = 1, + .vpu_pwr_mgmnt = 1, + .has_jpu = 1, +}; + +static const struct mxc_vpu_soc_data imx6q_vpu_data = { + .quirk_subblk_en = 1, + .regulator_required = 1, + .vpu_pwr_mgmnt = 1, + .has_jpu = 1, +}; + +static const struct mxc_vpu_soc_data imx53_vpu_data = { +}; + +static const struct mxc_vpu_soc_data imx51_vpu_data = { + .vpu_pwr_mgmnt = 1, +}; + +static const struct of_device_id vpu_of_match[] = { + { .compatible = "fsl,imx6dl-vpu", .data = &imx6dl_vpu_data, }, + { .compatible = "fsl,imx6q-vpu", .data = &imx6q_vpu_data, }, + { .compatible = "fsl,imx53-vpu", .data = &imx53_vpu_data, }, + { .compatible = "fsl,imx51-vpu", .data = &imx51_vpu_data, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, vpu_of_match); + /*! * This function is called by the driver framework to initialize the vpu device. * @param dev The device structure for the vpu passed in by the framework. @@ -895,15 +795,24 @@ static int vpu_dev_probe(struct platform_device *pdev) struct device *temp_class; struct resource *res; unsigned long addr = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) struct device_node *np = pdev->dev.of_node; u32 iramsize; + struct vpu_priv *drv_data; + const struct of_device_id *of_id = of_match_device(vpu_of_match, + &pdev->dev); + const struct mxc_vpu_soc_data *soc_data = of_id->data; - err = of_property_read_u32(np, "iramsize", (u32 *)&iramsize); - if (!err && iramsize) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) - { + drv_data = devm_kzalloc(&pdev->dev, sizeof(*drv_data), GFP_KERNEL); + if (drv_data == NULL) + return -ENOMEM; + + drv_data->soc_data = soc_data; + INIT_LIST_HEAD(&drv_data->users); + + init_waitqueue_head(&vpu_queue); + + err = of_property_read_u32(np, "iramsize", &iramsize); + if (!err && iramsize) { iram_pool = of_get_named_gen_pool(np, "iram", 0); if (!iram_pool) { dev_err(&pdev->dev, "iram pool not available\n"); @@ -918,28 +827,13 @@ static int vpu_dev_probe(struct platform_device *pdev) addr = gen_pool_virt_to_phys(iram_pool, iram_base); } -#else - iram_alloc(iramsize, &addr); -#endif - if (addr == 0) - iram.start = iram.end = 0; - else { - iram.start = addr; - iram.end = addr + iramsize - 1; - } -#else - - vpu_plat = pdev->dev.platform_data; - if (vpu_plat && vpu_plat->iram_enable && vpu_plat->iram_size) - iram_alloc(vpu_plat->iram_size, &addr); if (addr == 0) iram.start = iram.end = 0; else { iram.start = addr; - iram.end = addr + vpu_plat->iram_size - 1; + iram.end = addr + iramsize - 1; } -#endif vpu_dev = &pdev->dev; @@ -949,13 +843,14 @@ static int vpu_dev_probe(struct platform_device *pdev) return -ENODEV; } phy_vpu_base_addr = res->start; - vpu_base = ioremap(res->start, res->end - res->start); + vpu_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(vpu_base)) + return PTR_ERR(vpu_base); vpu_major = register_chrdev(vpu_major, "mxc_vpu", &vpu_fops); if (vpu_major < 0) { dev_err(vpu_dev, "vpu: unable to get a major for VPU\n"); - err = -EBUSY; - goto error; + return vpu_major; } vpu_class = class_create(THIS_MODULE, "mxc_vpu"); @@ -973,222 +868,180 @@ static int vpu_dev_probe(struct platform_device *pdev) vpu_clk = clk_get(&pdev->dev, "vpu_clk"); if (IS_ERR(vpu_clk)) { - err = -ENOENT; + err = PTR_ERR(vpu_clk); goto err_out_class; } vpu_ipi_irq = platform_get_irq_byname(pdev, "vpu_ipi_irq"); if (vpu_ipi_irq < 0) { dev_err(vpu_dev, "vpu: unable to get vpu interrupt\n"); - err = -ENXIO; + err = vpu_ipi_irq; goto err_out_class; } err = request_irq(vpu_ipi_irq, vpu_ipi_irq_handler, 0, "VPU_CODEC_IRQ", - (void *)(&vpu_data)); + &vpu_data); if (err) goto err_out_class; - if (vpu_power_get(true)) { - if (!(cpu_is_mx51() || cpu_is_mx53())) { + + vpu_regulator = devm_regulator_get(vpu_dev, "pu"); + if (IS_ERR(vpu_regulator)) { + if (drv_data->soc_data->regulator_required) { dev_err(vpu_dev, "failed to get vpu power\n"); goto err_out_class; } else { /* regulator_get will return error on MX5x, - * just igore it everywhere*/ + * just igore it everywhere + */ dev_warn(vpu_dev, "failed to get vpu power\n"); } } -#ifdef MXC_VPU_HAS_JPU - vpu_jpu_irq = platform_get_irq_byname(pdev, "vpu_jpu_irq"); - if (vpu_jpu_irq < 0) { - dev_err(vpu_dev, "vpu: unable to get vpu jpu interrupt\n"); - err = -ENXIO; - free_irq(vpu_ipi_irq, &vpu_data); - goto err_out_class; - } - err = request_irq(vpu_jpu_irq, vpu_jpu_irq_handler, IRQF_TRIGGER_RISING, - "VPU_JPG_IRQ", (void *)(&vpu_data)); - if (err) { - free_irq(vpu_ipi_irq, &vpu_data); - goto err_out_class; + platform_set_drvdata(pdev, drv_data); + + if (drv_data->soc_data->has_jpu) { + vpu_jpu_irq = platform_get_irq_byname(pdev, "vpu_jpu_irq"); + if (vpu_jpu_irq < 0) { + dev_err(vpu_dev, "vpu: unable to get vpu jpu interrupt\n"); + err = vpu_jpu_irq; + goto err_out_class; + } + err = request_irq(vpu_jpu_irq, vpu_jpu_irq_handler, IRQF_TRIGGER_RISING, + "VPU_JPG_IRQ", &vpu_data); + if (err) + goto err_out_class; } -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) pm_runtime_enable(&pdev->dev); -#endif vpu_data.workqueue = create_workqueue("vpu_wq"); INIT_WORK(&vpu_data.work, vpu_worker_callback); mutex_init(&vpu_data.lock); dev_info(vpu_dev, "VPU initialized\n"); - goto out; + return 0; err_out_class: device_destroy(vpu_class, MKDEV(vpu_major, 0)); class_destroy(vpu_class); err_out_chrdev: unregister_chrdev(vpu_major, "mxc_vpu"); -error: - iounmap(vpu_base); -out: return err; } static int vpu_dev_remove(struct platform_device *pdev) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + struct vpu_priv *vpu_data = platform_get_drvdata(pdev); + pm_runtime_disable(&pdev->dev); -#endif + free_irq(vpu_ipi_irq, &vpu_data); #ifdef MXC_VPU_HAS_JPU free_irq(vpu_jpu_irq, &vpu_data); #endif - cancel_work_sync(&vpu_data.work); - flush_workqueue(vpu_data.workqueue); - destroy_workqueue(vpu_data.workqueue); + cancel_work_sync(&vpu_data->work); + flush_workqueue(vpu_data->workqueue); + destroy_workqueue(vpu_data->workqueue); iounmap(vpu_base); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) if (iram.start) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) gen_pool_free(iram_pool, iram_base, iram.end-iram.start+1); -#else - iram_free(iram.start, iram.end-iram.start+1); -#endif -#else - if (vpu_plat && vpu_plat->iram_enable && vpu_plat->iram_size) - iram_free(iram.start, vpu_plat->iram_size); -#endif - vpu_power_get(false); + if (vpu_major > 0) { + device_destroy(vpu_class, MKDEV(vpu_major, 0)); + class_destroy(vpu_class); + unregister_chrdev(vpu_major, "mxc_vpu"); + vpu_major = 0; + } + + vpu_free_dma_buffer(&bitwork_mem); + vpu_free_dma_buffer(&pic_para_mem); + vpu_free_dma_buffer(&user_data_mem); + + /* reset VPU state */ + vpu_power_up(); + vpu_clk_enable(vpu_data); + vpu_reset(); + vpu_clk_disable(vpu_data); + vpu_power_down(); + + clk_put(vpu_clk); return 0; } #ifdef CONFIG_PM -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) static int vpu_suspend(struct device *dev) -#else -static int vpu_suspend(struct platform_device *pdev, pm_message_t state) -#endif { - int i; + struct vpu_priv *vpu_data = dev_get_drvdata(dev); unsigned long timeout; - mutex_lock(&vpu_data.lock); - if (open_count == 0) { - /* VPU is released (all instances are freed), - * clock is already off, context is no longer needed, - * power is already off on MX6, - * gate power on MX51 */ - if (cpu_is_mx51()) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) - if (vpu_plat->pg) - vpu_plat->pg(1); -#endif - } - } else { + mutex_lock(&vpu_data->lock); + + if (open_count) { /* Wait for vpu go to idle state, suspect vpu cannot be changed to idle state after about 1 sec */ timeout = jiffies + HZ; - clk_prepare(vpu_clk); - clk_enable(vpu_clk); while (READ_REG(BIT_BUSY_FLAG)) { msleep(1); if (time_after(jiffies, timeout)) { - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); - mutex_unlock(&vpu_data.lock); + mutex_unlock(&vpu_data->lock); return -EAGAIN; } } - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); - - /* Make sure clock is disabled before suspend */ - vpu_clk_usercount = atomic_read(&clk_cnt_from_ioc); - for (i = 0; i < vpu_clk_usercount; i++) { - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); - } - if (cpu_is_mx53()) { - mutex_unlock(&vpu_data.lock); + if (vpu_data->soc_data->is_mx53) { + mutex_unlock(&vpu_data->lock); return 0; } if (bitwork_mem.cpu_addr != 0) { - clk_prepare(vpu_clk); - clk_enable(vpu_clk); + int i; + /* Save 64 registers from BIT_CODE_BUF_ADDR */ for (i = 0; i < 64; i++) regBk[i] = READ_REG(BIT_CODE_BUF_ADDR + (i * 4)); pc_before_suspend = READ_REG(BIT_CUR_PC); - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) - if (vpu_plat->pg) - vpu_plat->pg(1); -#endif - + vpu_clk_disable(vpu_data); /* If VPU is working before suspend, disable - * regulator to make usecount right. */ - vpu_power_up(false); + * regulator to make usecount right. + */ + vpu_power_down(); } - mutex_unlock(&vpu_data.lock); + mutex_unlock(&vpu_data->lock); return 0; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) static int vpu_resume(struct device *dev) -#else -static int vpu_resume(struct platform_device *pdev) -#endif { int i; + struct vpu_priv *vpu_data = dev_get_drvdata(dev); - mutex_lock(&vpu_data.lock); - if (open_count == 0) { - /* VPU is released (all instances are freed), - * clock should be kept off, context is no longer needed, - * power should be kept off on MX6, - * disable power gating on MX51 */ - if (cpu_is_mx51()) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) - if (vpu_plat->pg) - vpu_plat->pg(0); -#endif + mutex_lock(&vpu_data->lock); + + if (open_count) { + if (vpu_data->soc_data->is_mx53) { + vpu_clk_enable(vpu_data); + goto out; } - } else { - if (cpu_is_mx53()) - goto recover_clk; /* If VPU is working before suspend, enable - * regulator to make usecount right. */ - vpu_power_up(true); -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) - if (vpu_plat->pg) - vpu_plat->pg(0); -#endif + * regulator to make usecount right. + */ + vpu_power_up(); - if (bitwork_mem.cpu_addr != 0) { - u32 *p = (u32 *) bitwork_mem.cpu_addr; + if (bitwork_mem.cpu_addr != NULL) { + u32 *p = bitwork_mem.cpu_addr; u32 data, pc; u16 data_hi; u16 data_lo; - clk_prepare(vpu_clk); - clk_enable(vpu_clk); + vpu_clk_enable(vpu_data); pc = READ_REG(BIT_CUR_PC); if (pc) { dev_warn(vpu_dev, "Not power off after suspend (PC=0x%x)\n", pc); - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); - goto recover_clk; + goto out; } /* Restore registers */ @@ -1198,9 +1051,8 @@ static int vpu_resume(struct platform_device *pdev) WRITE_REG(0x0, BIT_RESET_CTRL); WRITE_REG(0x0, BIT_CODE_RUN); /* MX6 RTL has a bug not to init MBC_SET_SUBBLK_EN on reset */ -#ifdef CONFIG_SOC_IMX6Q - WRITE_REG(0x0, MBC_SET_SUBBLK_EN); -#endif + if (vpu_data->soc_data->quirk_subblk_en) + WRITE_REG(0x0, MBC_SET_SUBBLK_EN); /* * Re-load boot code, from the codebuffer in external RAM. @@ -1231,121 +1083,34 @@ static int vpu_resume(struct platform_device *pdev) } else { dev_warn(vpu_dev, "PC=0 before suspend\n"); } - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); - } - -recover_clk: - /* Recover vpu clock */ - for (i = 0; i < vpu_clk_usercount; i++) { - clk_prepare(vpu_clk); - clk_enable(vpu_clk); } } - - mutex_unlock(&vpu_data.lock); - return 0; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) -static int vpu_runtime_suspend(struct device *dev) -{ - release_bus_freq(BUS_FREQ_HIGH); - return 0; -} - -static int vpu_runtime_resume(struct device *dev) -{ - request_bus_freq(BUS_FREQ_HIGH); +out: + mutex_unlock(&vpu_data->lock); return 0; } -static const struct dev_pm_ops vpu_pm_ops = { - SET_RUNTIME_PM_OPS(vpu_runtime_suspend, vpu_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(vpu_suspend, vpu_resume) -}; -#endif - +static SIMPLE_DEV_PM_OPS(vpu_pm_ops, vpu_suspend, vpu_resume); +#define VPU_PM_OPS &vpu_pm_ops #else -#define vpu_suspend NULL -#define vpu_resume NULL -#endif /* !CONFIG_PM */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) -static const struct of_device_id vpu_of_match[] = { - { .compatible = "fsl,imx6-vpu", }, - {/* sentinel */} -}; -MODULE_DEVICE_TABLE(of, vpu_of_match); -#endif +#define VPU_PM_OPS NULL +#endif /* !CONFIG_PM */ /*! Driver definition * */ static struct platform_driver mxcvpu_driver = { .driver = { - .name = "mxc_vpu", -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) - .of_match_table = vpu_of_match, -#ifdef CONFIG_PM - .pm = &vpu_pm_ops, -#endif -#endif - }, + .name = "mxc_vpu", + .of_match_table = vpu_of_match, + .pm = VPU_PM_OPS, + }, .probe = vpu_dev_probe, .remove = vpu_dev_remove, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) - .suspend = vpu_suspend, - .resume = vpu_resume, -#endif }; -static int __init vpu_init(void) -{ - int ret = platform_driver_register(&mxcvpu_driver); - - init_waitqueue_head(&vpu_queue); - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) - memblock_analyze(); - top_address_DRAM = memblock_end_of_DRAM_with_reserved(); -#endif - - return ret; -} - -static void __exit vpu_exit(void) -{ - if (vpu_major > 0) { - device_destroy(vpu_class, MKDEV(vpu_major, 0)); - class_destroy(vpu_class); - unregister_chrdev(vpu_major, "mxc_vpu"); - vpu_major = 0; - } - - vpu_free_dma_buffer(&bitwork_mem); - vpu_free_dma_buffer(&pic_para_mem); - vpu_free_dma_buffer(&user_data_mem); - - /* reset VPU state */ - vpu_power_up(true); - clk_prepare(vpu_clk); - clk_enable(vpu_clk); - vpu_reset(); - clk_disable(vpu_clk); - clk_unprepare(vpu_clk); - vpu_power_up(false); - - clk_put(vpu_clk); - - platform_driver_unregister(&mxcvpu_driver); - return; -} +module_platform_driver(mxcvpu_driver); MODULE_AUTHOR("Freescale Semiconductor, Inc."); MODULE_DESCRIPTION("Linux VPU driver for Freescale i.MX/MXC"); MODULE_LICENSE("GPL"); - -module_init(vpu_init); -module_exit(vpu_exit); diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 5bcad0165a1b..f425ec2c7839 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -125,8 +125,7 @@ FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT) /* FLEXCAN interrupt flag register (IFLAG) bits */ -#define FLEXCAN_RESERVED_BUF_ID 8 -#define FLEXCAN_TX_BUF_ID 13 +#define FLEXCAN_TX_BUF_ID 8 #define FLEXCAN_IFLAG_BUF(x) BIT(x) #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7) #define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6) @@ -163,7 +162,6 @@ */ #define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ #define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */ -#define FLEXCAN_HAS_ERR005829 BIT(3) /* have errata ERR005829 */ /* Structure of the message buffer */ struct flexcan_mb { @@ -223,7 +221,7 @@ static struct flexcan_devtype_data fsl_p1010_devtype_data = { }; static struct flexcan_devtype_data fsl_imx28_devtype_data; static struct flexcan_devtype_data fsl_imx6q_devtype_data = { - .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_ERR005829, + .features = FLEXCAN_HAS_V10_FEATURES, }; static const struct can_bittiming_const flexcan_bittiming_const = { @@ -430,11 +428,6 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id); flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); - if (priv->devtype_data->features & FLEXCAN_HAS_ERR005829) { - writel(0x0, ®s->cantxfg[FLEXCAN_RESERVED_BUF_ID].can_ctrl); - writel(0x0, ®s->cantxfg[FLEXCAN_RESERVED_BUF_ID].can_ctrl); - } - return NETDEV_TX_OK; } diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 7a3426c72699..671d080105a7 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -328,8 +328,6 @@ struct fec_enet_private { struct napi_struct napi; int csum_flags; - int phy_reset_gpio; - struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_caps; unsigned long last_overflow_check; diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 2a025e69ff89..339d89f14d32 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -222,7 +222,6 @@ static void ath6kl_sdio_setup_scat_data(struct hif_scatter_req *scat_req, struct mmc_data *data) { struct scatterlist *sg; - struct hif_scatter_item *scat_list; int i; data->blksz = HIF_MBOX_BLOCK_SIZE; @@ -241,14 +240,14 @@ static void ath6kl_sdio_setup_scat_data(struct hif_scatter_req *scat_req, sg = scat_req->sgentries; sg_init_table(sg, scat_req->scat_entries); - scat_list = &scat_req->scat_list[0]; - /* assemble SG list */ - for (i = 0; i < scat_req->scat_entries; i++, sg++, scat_list++) { + for (i = 0; i < scat_req->scat_entries; i++, sg++) { ath6kl_dbg(ATH6KL_DBG_SCATTER, "%d: addr:0x%p, len:%d\n", - i, scat_list->buf, scat_list->len); + i, scat_req->scat_list[i].buf, + scat_req->scat_list[i].len); - sg_set_buf(sg, scat_list->buf, scat_list->len); + sg_set_buf(sg, scat_req->scat_list[i].buf, + scat_req->scat_list[i].len); } /* set scatter-gather table for request */ diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index ff046d49ff63..c5d0ca384502 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c @@ -265,58 +265,6 @@ static void exynos_pcie_power_off_phy(struct pcie_port *pp) exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER); } -static void exynos_pcie_power_on_phy(struct pcie_port *pp) -{ - u32 val; - struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); - - val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER); - val &= ~PCIE_PHY_COMMON_PD_CMN; - exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER); - - val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER); - val &= ~PCIE_PHY_TRSV0_PD_TSV; - exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER); - - val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER); - val &= ~PCIE_PHY_TRSV1_PD_TSV; - exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER); - - val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER); - val &= ~PCIE_PHY_TRSV2_PD_TSV; - exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER); - - val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER); - val &= ~PCIE_PHY_TRSV3_PD_TSV; - exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER); -} - -static void exynos_pcie_power_off_phy(struct pcie_port *pp) -{ - u32 val; - struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); - - val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER); - val |= PCIE_PHY_COMMON_PD_CMN; - exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER); - - val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER); - val |= PCIE_PHY_TRSV0_PD_TSV; - exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER); - - val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER); - val |= PCIE_PHY_TRSV1_PD_TSV; - exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER); - - val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER); - val |= PCIE_PHY_TRSV2_PD_TSV; - exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER); - - val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER); - val |= PCIE_PHY_TRSV3_PD_TSV; - exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER); -} - static void exynos_pcie_init_phy(struct pcie_port *pp) { struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c index 02b11f7d11db..eda13de2e7c0 100644 --- a/drivers/pinctrl/devicetree.c +++ b/drivers/pinctrl/devicetree.c @@ -18,7 +18,6 @@ #include #include -#include #include #include @@ -173,43 +172,6 @@ static int dt_remember_dummy_state(struct pinctrl *p, const char *statename) return dt_remember_or_free_map(p, statename, NULL, map, 1); } -static int dt_gpio_assert_pinctrl(struct pinctrl *p) -{ - struct device_node *np = p->dev->of_node; - enum of_gpio_flags flags; - int gpio; - int index = 0; - int ret; - - if (!of_find_property(np, "pinctrl-assert-gpios", NULL)) - return 0; /* Missing the property, so nothing to be done */ - - for (;; index++) { - gpio = of_get_named_gpio_flags(np, "pinctrl-assert-gpios", - index, &flags); - if (gpio < 0) - break; /* End of the phandle list */ - - if (!gpio_is_valid(gpio)) - return -EINVAL; - - ret = devm_gpio_request_one(p->dev, gpio, GPIOF_OUT_INIT_LOW, - NULL); - if (ret < 0) - return ret; - - if (flags & OF_GPIO_ACTIVE_LOW) - continue; - - if (gpio_cansleep(gpio)) - gpio_set_value_cansleep(gpio, 1); - else - gpio_set_value(gpio, 1); - } - - return 0; -} - int pinctrl_dt_to_map(struct pinctrl *p) { struct device_node *np = p->dev->of_node; @@ -230,12 +192,6 @@ int pinctrl_dt_to_map(struct pinctrl *p) return 0; } - ret = dt_gpio_assert_pinctrl(p); - if (ret) { - dev_dbg(p->dev, "failed to assert pinctrl setting: %d\n", ret); - return ret; - } - /* We may store pointers to property names within the node */ of_node_get(np); diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 5b5a75d1d200..ba6975123071 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -276,14 +276,6 @@ config CHARGER_MAX8903 pins based on the status of charger connections with interrupt handlers. -config SABRESD_MAX8903 - tristate "Sabresd Board Battery DC-DC Charger for USB and Adapter Power" - depends on GENERIC_HARDIRQS && TOUCHSCREEN_MAX11801 - help - Say Y to enable support for the MAX8903 DC-DC charger and sysfs on - sabresd board.The driver supports controlling charger and battery - based on the status of charger connections with interrupt handlers. - config CHARGER_TWL4030 tristate "OMAP TWL4030 BCI charger driver" depends on TWL4030_CORE @@ -397,12 +389,6 @@ config BATTERY_GOLDFISH Say Y to enable support for the battery and AC power in the Goldfish emulator. -config IMX6_USB_CHARGER - bool "Freescale imx6 USB Charger" - depends on SOC_IMX6Q || SOC_IMX6SL - help - Say Y to enable Freescale imx6 USB Charger Detect. - source "drivers/power/reset/Kconfig" endif # POWER_SUPPLY diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 4c828bc23e1b..ee54a3e4c90a 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -43,7 +43,6 @@ obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o pm2301_charger.o obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o -obj-$(CONFIG_SABRESD_MAX8903) += sabresd_battery.o obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o @@ -59,4 +58,3 @@ obj-$(CONFIG_POWER_AVS) += avs/ obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o obj-$(CONFIG_POWER_RESET) += reset/ -obj-$(CONFIG_IMX6_USB_CHARGER) += imx6_usb_charger.o diff --git a/drivers/power/imx6_usb_charger.c b/drivers/power/imx6_usb_charger.c deleted file mode 100644 index d94a30226664..000000000000 --- a/drivers/power/imx6_usb_charger.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include - -#define HW_ANADIG_REG_3P0_SET (0x00000124) -#define HW_ANADIG_REG_3P0_CLR (0x00000128) -#define BM_ANADIG_REG_3P0_ENABLE_ILIMIT 0x00000004 -#define BM_ANADIG_REG_3P0_ENABLE_LINREG 0x00000001 - -#define HW_ANADIG_USB1_CHRG_DETECT_SET (0x000001b4) -#define HW_ANADIG_USB1_CHRG_DETECT_CLR (0x000001b8) - -#define BM_ANADIG_USB1_CHRG_DETECT_EN_B 0x00100000 -#define BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B 0x00080000 -#define BM_ANADIG_USB1_CHRG_DETECT_CHK_CONTACT 0x00040000 - -#define HW_ANADIG_USB1_VBUS_DET_STAT (0x000001c0) - -#define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID 0x00000008 - -#define HW_ANADIG_USB1_CHRG_DET_STAT (0x000001d0) - -#define BM_ANADIG_USB1_CHRG_DET_STAT_DM_STATE 0x00000004 -#define BM_ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED 0x00000002 -#define BM_ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT 0x00000001 - -static char *imx6_usb_charger_supplied_to[] = { - "imx6_usb_charger", -}; - -static enum power_supply_property imx6_usb_charger_power_props[] = { - POWER_SUPPLY_PROP_PRESENT, /* Charger detected */ - POWER_SUPPLY_PROP_ONLINE, /* VBUS online */ - POWER_SUPPLY_PROP_CURRENT_MAX, /* Maximum current in mA */ -}; - -static int imx6_usb_charger_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct usb_charger *charger = - container_of(psy, struct usb_charger, psy); - - switch (psp) { - case POWER_SUPPLY_PROP_PRESENT: - val->intval = charger->present; - break; - case POWER_SUPPLY_PROP_ONLINE: - val->intval = charger->online; - break; - case POWER_SUPPLY_PROP_CURRENT_MAX: - val->intval = charger->max_current; - break; - default: - return -EINVAL; - } - return 0; -} - -static void disable_charger_detector(struct regmap *regmap) -{ - regmap_write(regmap, HW_ANADIG_USB1_CHRG_DETECT_SET, - BM_ANADIG_USB1_CHRG_DETECT_EN_B | - BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B); -} - -static void disable_current_limiter(struct regmap *regmap) -{ - /* Disable the vdd3p0 current limiter */ - regmap_write(regmap, HW_ANADIG_REG_3P0_CLR, - BM_ANADIG_REG_3P0_ENABLE_ILIMIT); -} - -/* Return value if the charger is present */ -static int imx6_usb_charger_detect(struct usb_charger *charger) -{ - struct regmap *regmap = charger->anatop; - u32 val; - int i, data_pin_contact_count = 0; - - /* Enable the vdd3p0 curret limiter */ - regmap_write(regmap, HW_ANADIG_REG_3P0_SET, - BM_ANADIG_REG_3P0_ENABLE_LINREG | - BM_ANADIG_REG_3P0_ENABLE_ILIMIT); - - /* check if vbus is valid */ - regmap_read(regmap, HW_ANADIG_USB1_VBUS_DET_STAT, &val); - if (!(val & BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)) { - dev_err(charger->dev, "vbus is error\n"); - disable_current_limiter(regmap); - return -EINVAL; - } - - /* Enable charger detector */ - regmap_write(regmap, HW_ANADIG_USB1_CHRG_DETECT_CLR, - BM_ANADIG_USB1_CHRG_DETECT_EN_B); - /* - * - Do not check whether a charger is connected to the USB port - * - Check whether the USB plug has been in contact with each other - */ - regmap_write(regmap, HW_ANADIG_USB1_CHRG_DETECT_SET, - BM_ANADIG_USB1_CHRG_DETECT_CHK_CONTACT | - BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B); - - /* Check if plug is connected */ - for (i = 0; i < 100; i = i + 1) { - regmap_read(regmap, HW_ANADIG_USB1_CHRG_DET_STAT, &val); - if (val & BM_ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT) { - if (data_pin_contact_count++ > 5) - /* Data pin makes contact */ - break; - } else { - msleep(20); - } - } - - if (i == 100) { - dev_err(charger->dev, - "VBUS is coming from a dedicated power supply.\n"); - disable_current_limiter(regmap); - disable_charger_detector(regmap); - return -ENXIO; - } - - /* - * - Do check whether a charger is connected to the USB port - * - Do not Check whether the USB plug has been in contact with - * each other - */ - regmap_write(regmap, HW_ANADIG_USB1_CHRG_DETECT_CLR, - BM_ANADIG_USB1_CHRG_DETECT_CHK_CONTACT | - BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B); - msleep(45); - - /* Check if it is a charger */ - regmap_read(regmap, HW_ANADIG_USB1_CHRG_DET_STAT, &val); - if (!(val & BM_ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED)) { - dev_dbg(charger->dev, "It is a stardard downstream port\n"); - charger->psy.type = POWER_SUPPLY_TYPE_USB; - charger->max_current = 500; - disable_charger_detector(regmap); - } else { - /* It is a charger */ - disable_charger_detector(regmap); - msleep(45); - } - - disable_current_limiter(regmap); - - return 0; -} - -/* - * imx6_usb_vbus_connect - inform about VBUS connection - * @charger: the usb charger - * - * Inform the charger VBUS is connected, vbus detect supplier should call it. - * Besides, the USB device controller is expected to keep the dataline - * pullups disabled. - */ -int imx6_usb_vbus_connect(struct usb_charger *charger) -{ - int ret; - - charger->online = 1; - - mutex_lock(&charger->lock); - - /* Start the 1st period charger detection. */ - ret = imx6_usb_charger_detect(charger); - if (ret) - dev_err(charger->dev, - "Error occurs during detection: %d\n", - ret); - else - charger->present = 1; - - mutex_unlock(&charger->lock); - - return ret; -} -EXPORT_SYMBOL(imx6_usb_vbus_connect); - -/* - * It must be called after dp is pulled up (from USB controller driver), - * That is used to differentiate DCP and CDP - */ -int imx6_usb_charger_detect_post(struct usb_charger *charger) -{ - struct regmap *regmap = charger->anatop; - int val; - - mutex_lock(&charger->lock); - - msleep(40); - - regmap_read(regmap, HW_ANADIG_USB1_CHRG_DET_STAT, &val); - if (val & BM_ANADIG_USB1_CHRG_DET_STAT_DM_STATE) { - dev_dbg(charger->dev, "It is a dedicate charging port\n"); - charger->psy.type = POWER_SUPPLY_TYPE_USB_DCP; - charger->max_current = 1500; - } else { - dev_dbg(charger->dev, "It is a charging downstream port\n"); - charger->psy.type = POWER_SUPPLY_TYPE_USB_CDP; - charger->max_current = 900; - } - - power_supply_changed(&charger->psy); - - mutex_unlock(&charger->lock); - - return 0; -} -EXPORT_SYMBOL(imx6_usb_charger_detect_post); - -/* - * imx6_usb_vbus_disconnect - inform about VBUS disconnection - * @charger: the usb charger - * - * Inform the charger that VBUS is disconnected. The charging will be - * stopped and the charger properties cleared. - */ -int imx6_usb_vbus_disconnect(struct usb_charger *charger) -{ - charger->online = 0; - charger->present = 0; - charger->max_current = 0; - charger->psy.type = POWER_SUPPLY_TYPE_MAINS; - - power_supply_changed(&charger->psy); - - return 0; -} -EXPORT_SYMBOL(imx6_usb_vbus_disconnect); - -/* - * imx6_usb_create_charger - create a USB charger - * @charger: the charger to be initialized - * @name: name for the power supply - - * Registers a power supply for the charger. The USB Controller - * driver will call this after filling struct usb_charger. - */ -int imx6_usb_create_charger(struct usb_charger *charger, - const char *name) -{ - struct power_supply *psy = &charger->psy; - - if (!charger->dev) - return -EINVAL; - - if (name) - psy->name = name; - else - psy->name = "imx6_usb_charger"; - - charger->bc = BATTERY_CHARGING_SPEC_1_2; - mutex_init(&charger->lock); - - psy->type = POWER_SUPPLY_TYPE_MAINS; - psy->properties = imx6_usb_charger_power_props; - psy->num_properties = ARRAY_SIZE(imx6_usb_charger_power_props); - psy->get_property = imx6_usb_charger_get_property; - psy->supplied_to = imx6_usb_charger_supplied_to; - psy->num_supplicants = sizeof(imx6_usb_charger_supplied_to) - / sizeof(char *); - - return power_supply_register(charger->dev, psy); -} -EXPORT_SYMBOL(imx6_usb_create_charger); - -/* - * imx6_usb_remove_charger - remove a USB charger - * @charger: the charger to be removed - * - * Unregister the chargers power supply. - */ -void imx6_usb_remove_charger(struct usb_charger *charger) -{ - power_supply_unregister(&charger->psy); -} -EXPORT_SYMBOL(imx6_usb_remove_charger); diff --git a/drivers/power/sabresd_battery.c b/drivers/power/sabresd_battery.c deleted file mode 100644 index e9b774197cd6..000000000000 --- a/drivers/power/sabresd_battery.c +++ /dev/null @@ -1,998 +0,0 @@ -/* - * sabresd_battery.c - Maxim 8903 USB/Adapter Charger Driver - * - * Copyright (C) 2011 Samsung Electronics - * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. - * Based on max8903_charger.c - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BATTERY_UPDATE_INTERVAL 5 /*seconds*/ -#define LOW_VOLT_THRESHOLD 2800000 -#define HIGH_VOLT_THRESHOLD 4200000 -#define ADC_SAMPLE_COUNT 6 - -struct max8903_data { - struct max8903_pdata *pdata; - struct device *dev; - struct power_supply psy; - struct power_supply usb; - bool fault; - bool usb_in; - bool ta_in; - bool chg_state; - struct delayed_work work; - unsigned int interval; - unsigned short thermal_raw; - int voltage_uV; - int current_uA; - int battery_status; - int charger_online; - int charger_voltage_uV; - int real_capacity; - int percent; - int old_percent; - int usb_charger_online; - int first_delay_count; - struct power_supply bat; - struct power_supply detect_usb; -}; - -typedef struct { - u32 voltage; - u32 percent; -} battery_capacity , *pbattery_capacity; - -static int offset_discharger; -static int offset_charger; -static int offset_usb_charger; - -static battery_capacity chargingTable[] = { - {4050, 99}, - {4040, 98}, - {4020, 97}, - {4010, 96}, - {3990, 95}, - {3980, 94}, - {3970, 93}, - {3960, 92}, - {3950, 91}, - {3940, 90}, - {3930, 85}, - {3920, 81}, - {3910, 77}, - {3900, 73}, - {3890, 70}, - {3860, 65}, - {3830, 60}, - {3780, 55}, - {3760, 50}, - {3740, 45}, - {3720, 40}, - {3700, 35}, - {3680, 30}, - {3660, 25}, - {3640, 20}, - {3620, 17}, - {3600, 14}, - {3580, 13}, - {3560, 12}, - {3540, 11}, - {3520, 10}, - {3500, 9}, - {3480, 8}, - {3460, 7}, - {3440, 6}, - {3430, 5}, - {3420, 4}, - {3020, 0}, -}; - -static battery_capacity dischargingTable[] = { - {4050, 100}, - {4035, 99}, - {4020, 98}, - {4010, 97}, - {4000, 96}, - {3990, 96}, - {3980, 95}, - {3970, 92}, - {3960, 91}, - {3950, 90}, - {3940, 88}, - {3930, 86}, - {3920, 84}, - {3910, 82}, - {3900, 80}, - {3890, 74}, - {3860, 69}, - {3830, 64}, - {3780, 59}, - {3760, 54}, - {3740, 49}, - {3720, 44}, - {3700, 39}, - {3680, 34}, - {3660, 29}, - {3640, 24}, - {3620, 19}, - {3600, 14}, - {3580, 13}, - {3560, 12}, - {3540, 11}, - {3520, 10}, - {3500, 9}, - {3480, 8}, - {3460, 7}, - {3440, 6}, - {3430, 5}, - {3420, 4}, - {3020, 0}, -}; - -u32 calibrate_battery_capability_percent(struct max8903_data *data) -{ - u8 i; - pbattery_capacity pTable; - u32 tableSize; - - if (data->battery_status == POWER_SUPPLY_STATUS_DISCHARGING) { - pTable = dischargingTable; - tableSize = sizeof(dischargingTable)/ - sizeof(dischargingTable[0]); - } else { - pTable = chargingTable; - tableSize = sizeof(chargingTable)/ - sizeof(chargingTable[0]); - } - for (i = 0; i < tableSize; i++) { - if (data->voltage_uV >= pTable[i].voltage) - return pTable[i].percent; - } - - return 0; -} - -static enum power_supply_property max8903_charger_props[] = { - POWER_SUPPLY_PROP_ONLINE, -}; - -static enum power_supply_property max8903_battery_props[] = { - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, - POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, - POWER_SUPPLY_PROP_HEALTH, - POWER_SUPPLY_PROP_CAPACITY_LEVEL, -}; - -extern u32 max11801_read_adc(void); - -static void max8903_charger_update_status(struct max8903_data *data) -{ - if (data->ta_in) { - data->charger_online = 1; - } else if (data->usb_in) { - data->usb_charger_online = 1; - } else { - data->charger_online = 0; - data->usb_charger_online = 0; - } - - if (!data->charger_online && !data->usb_charger_online) { - data->battery_status = POWER_SUPPLY_STATUS_DISCHARGING; - } else if (gpio_get_value(data->pdata->chg) == 0) { - data->battery_status = POWER_SUPPLY_STATUS_CHARGING; - } else if ((data->ta_in || data->usb_in) && - gpio_get_value(data->pdata->chg) > 0) { - if (!data->pdata->feature_flag) { - if (data->percent >= 99) - data->battery_status = POWER_SUPPLY_STATUS_FULL; - else - data->battery_status = - POWER_SUPPLY_STATUS_NOT_CHARGING; - } else { - data->battery_status = POWER_SUPPLY_STATUS_FULL; - } - } -} - -u32 calibration_voltage(struct max8903_data *data) -{ - u32 voltage_data = 0; - int i; - int offset; - - if (!data->charger_online && !data->usb_charger_online) - offset = offset_discharger; - else if (data->usb_charger_online) - offset = offset_usb_charger; - else if (data->charger_online) - offset = offset_charger; - - /* simple average */ - for (i = 0; i < ADC_SAMPLE_COUNT; i++) - voltage_data += max11801_read_adc()-offset; - voltage_data = voltage_data / ADC_SAMPLE_COUNT; - dev_dbg(data->dev, "volt: %d\n", voltage_data); - - return voltage_data; -} - -static void max8903_battery_update_status(struct max8903_data *data) -{ - if (!data->pdata->feature_flag) { - data->voltage_uV = calibration_voltage(data); - data->percent = calibrate_battery_capability_percent(data); - if (data->percent != data->old_percent) { - data->old_percent = data->percent; - power_supply_changed(&data->bat); - } - /* - * because boot time gap between led framwork and charger - * framwork,when system boots with charger attatched, - * charger led framwork loses the first charger online event, - * add once extra power_supply_changed can fix this issure - */ - if (data->first_delay_count < 200) { - data->first_delay_count = data->first_delay_count + 1; - power_supply_changed(&data->bat); - } - } -} - -static int max8903_battery_get_property(struct power_supply *bat, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct max8903_data *di = container_of(bat, struct max8903_data, bat); - - switch (psp) { - case POWER_SUPPLY_PROP_STATUS: - val->intval = POWER_SUPPLY_STATUS_UNKNOWN; - if (gpio_get_value(di->pdata->chg) == 0) { - di->battery_status = POWER_SUPPLY_STATUS_CHARGING; - } else if ((di->ta_in || di->usb_in) && - gpio_get_value(di->pdata->chg) > 0) { - if (!di->pdata->feature_flag) { - if (di->percent >= 99) - di->battery_status = - POWER_SUPPLY_STATUS_FULL; - else - di->battery_status = - POWER_SUPPLY_STATUS_NOT_CHARGING; - } else { - di->battery_status = POWER_SUPPLY_STATUS_FULL; - } - } - val->intval = di->battery_status; - return 0; - default: - break; - } - - switch (psp) { - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = di->voltage_uV; - break; - case POWER_SUPPLY_PROP_CHARGE_NOW: - val->intval = 0; - break; - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - val->intval = HIGH_VOLT_THRESHOLD; - break; - case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: - val->intval = LOW_VOLT_THRESHOLD; - break; - case POWER_SUPPLY_PROP_PRESENT: - val->intval = 1; - break; - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = di->percent < 0 ? 0 : - (di->percent > 100 ? 100 : di->percent); - break; - case POWER_SUPPLY_PROP_HEALTH: - val->intval = POWER_SUPPLY_HEALTH_GOOD; - if (di->fault) - val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; - break; - case POWER_SUPPLY_PROP_CAPACITY_LEVEL: - if (di->battery_status == POWER_SUPPLY_STATUS_FULL) - val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL; - else if (di->percent <= 15) - val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW; - else - val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int max8903_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct max8903_data *data = container_of(psy, - struct max8903_data, psy); - - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = 0; - if (data->ta_in) - val->intval = 1; - data->charger_online = val->intval; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int max8903_get_usb_property(struct power_supply *usb, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct max8903_data *data = container_of(usb, - struct max8903_data, usb); - - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = 0; - if (data->usb_in) - val->intval = 1; - data->usb_charger_online = val->intval; - break; - default: - return -EINVAL; - } - - return 0; -} - -static irqreturn_t max8903_dcin(int irq, void *_data) -{ - struct max8903_data *data = _data; - struct max8903_pdata *pdata = data->pdata; - bool ta_in = false; - - if (pdata->dok) - ta_in = gpio_get_value(pdata->dok) ? false : true; - - if (ta_in == data->ta_in) - return IRQ_HANDLED; - - data->ta_in = ta_in; - dev_info(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ? - "Connected" : "Disconnected"); - max8903_charger_update_status(data); - power_supply_changed(&data->psy); - power_supply_changed(&data->bat); - - return IRQ_HANDLED; -} - -static irqreturn_t max8903_usbin(int irq, void *_data) -{ - struct max8903_data *data = _data; - struct max8903_pdata *pdata = data->pdata; - bool usb_in = false; - - if (pdata->uok) - usb_in = gpio_get_value(pdata->uok) ? false : true; - if (usb_in == data->usb_in) - return IRQ_HANDLED; - data->usb_in = usb_in; - dev_info(data->dev, "USB Charger %s.\n", usb_in ? - "Connected" : "Disconnected"); - max8903_charger_update_status(data); - power_supply_changed(&data->bat); - power_supply_changed(&data->usb); - - return IRQ_HANDLED; -} - -static irqreturn_t max8903_fault(int irq, void *_data) -{ - struct max8903_data *data = _data; - struct max8903_pdata *pdata = data->pdata; - bool fault; - - fault = gpio_get_value(pdata->flt) ? false : true; - - if (fault == data->fault) - return IRQ_HANDLED; - data->fault = fault; - - if (fault) - dev_err(data->dev, "Charger suffers a fault and stops.\n"); - else - dev_err(data->dev, "Charger recovered from a fault.\n"); - max8903_charger_update_status(data); - power_supply_changed(&data->psy); - power_supply_changed(&data->bat); - power_supply_changed(&data->usb); - - return IRQ_HANDLED; -} - -static irqreturn_t max8903_chg(int irq, void *_data) -{ - struct max8903_data *data = _data; - struct max8903_pdata *pdata = data->pdata; - int chg_state; - - chg_state = gpio_get_value(pdata->chg) ? false : true; - - if (chg_state == data->chg_state) - return IRQ_HANDLED; - data->chg_state = chg_state; - max8903_charger_update_status(data); - power_supply_changed(&data->psy); - power_supply_changed(&data->bat); - power_supply_changed(&data->usb); - - return IRQ_HANDLED; -} - -static void max8903_battery_work(struct work_struct *work) -{ - struct max8903_data *data; - - data = container_of(work, struct max8903_data, work.work); - data->interval = HZ * BATTERY_UPDATE_INTERVAL; - - max8903_charger_update_status(data); - max8903_battery_update_status(data); - dev_dbg(data->dev, "battery voltage: %4d mV\n", data->voltage_uV); - dev_dbg(data->dev, "charger online status: %d\n", - data->charger_online); - dev_dbg(data->dev, "battery status : %d\n" , data->battery_status); - dev_dbg(data->dev, "battery capacity percent: %3d\n", data->percent); - dev_dbg(data->dev, "data->usb_in: %x , data->ta_in: %x\n", - data->usb_in, data->ta_in); - /* reschedule for the next time */ - schedule_delayed_work(&data->work, data->interval); -} - -static ssize_t max8903_voltage_offset_discharger_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "read offset_discharger:%04d\n", - offset_discharger); -} - -static ssize_t max8903_voltage_offset_discharger_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - int ret; - unsigned long data; - - ret = strict_strtoul(buf, 10, &data); - offset_discharger = (int)data; - pr_info("read offset_discharger:%04d\n", offset_discharger); - - return count; -} - -static ssize_t max8903_voltage_offset_charger_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "read offset_charger:%04d\n", - offset_charger); -} - -static ssize_t max8903_voltage_offset_charger_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - int ret; - unsigned long data; - - ret = strict_strtoul(buf, 10, &data); - offset_charger = (int)data; - pr_info("read offset_charger:%04d\n", offset_charger); - return count; -} - -static ssize_t max8903_voltage_offset_usb_charger_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "read offset_usb_charger:%04d\n", - offset_usb_charger); -} - -static ssize_t max8903_voltage_offset_usb_charger_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - int ret; - unsigned long data; - - ret = strict_strtoul(buf, 10, &data); - offset_usb_charger = (int)data; - pr_info("read offset_charger:%04d\n", offset_usb_charger); - - return count; -} - -static struct device_attribute max8903_discharger_dev_attr = { - .attr = { - .name = "max8903_ctl_offset_discharger", - .mode = S_IRUSR | S_IWUSR, - }, - .show = max8903_voltage_offset_discharger_show, - .store = max8903_voltage_offset_discharger_store, -}; - -static struct device_attribute max8903_charger_dev_attr = { - .attr = { - .name = "max8903_ctl_offset_charger", - .mode = S_IRUSR | S_IWUSR, - }, - .show = max8903_voltage_offset_charger_show, - .store = max8903_voltage_offset_charger_store, -}; - -static struct device_attribute max8903_usb_charger_dev_attr = { - .attr = { - .name = "max8903_ctl_offset_usb_charger", - .mode = S_IRUSR | S_IWUSR, - }, - .show = max8903_voltage_offset_usb_charger_show, - .store = max8903_voltage_offset_usb_charger_store, -}; - -#if defined(CONFIG_OF) -static const struct of_device_id max8903_dt_ids[] = { - { .compatible = "fsl,max8903-charger", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, max8903_dt_ids); - -static struct max8903_pdata *max8903_of_populate_pdata( - struct device *dev) -{ - struct device_node *of_node = dev->of_node; - struct max8903_pdata *pdata = dev->platform_data; - - if (!of_node || pdata) - return pdata; - - pdata = devm_kzalloc(dev, sizeof(struct max8903_pdata), - GFP_KERNEL); - if (!pdata) - return pdata; - - if (of_get_property(of_node, "fsl,dcm_always_high", NULL)) - pdata->dcm_always_high = true; - if (of_get_property(of_node, "fsl,dc_valid", NULL)) - pdata->dc_valid = true; - if (of_get_property(of_node, "fsl,usb_valid", NULL)) - pdata->usb_valid = true; - if (of_get_property(of_node, "fsl,adc_disable", NULL)) - pdata->feature_flag = true; - - if (pdata->dc_valid) { - pdata->dok = of_get_named_gpio(of_node, "dok_input", 0); - if (!gpio_is_valid(pdata->dok)) { - dev_err(dev, "pin pdata->dok: invalid gpio %d\n", pdata->dok); - return NULL; - } - } - if (pdata->usb_valid) { - pdata->uok = of_get_named_gpio(of_node, "uok_input", 0); - if (!gpio_is_valid(pdata->uok)) { - dev_err(dev, "pin pdata->uok: invalid gpio %d\n", pdata->uok); - return NULL; - } - } - pdata->chg = of_get_named_gpio(of_node, "chg_input", 0); - if (!gpio_is_valid(pdata->chg)) { - dev_err(dev, "pin pdata->chg: invalid gpio %d\n", pdata->chg); - return NULL; - } - pdata->flt = of_get_named_gpio(of_node, "flt_input", 0); - if (!gpio_is_valid(pdata->flt)) { - dev_err(dev, "pin pdata->flt: invalid gpio %d\n", pdata->flt); - return NULL; - } - /* no need check offset without adc converter */ - if (!pdata->feature_flag) { - if (of_property_read_u32(of_node, "offset-charger", - &offset_charger)) - dev_err(dev, "Not setting offset-charger in dts!\n"); - - if (of_property_read_u32(of_node, "offset-discharger", - &offset_discharger)) - dev_err(dev, "Not setting offset-discharger in dts!\n"); - - if (of_property_read_u32(of_node, "offset-usb-charger", - &offset_usb_charger)) - dev_err(dev, "Not setting offset-usb-charger in dts!\n"); - } - - return pdata; -} -#endif - -static int max8903_probe(struct platform_device *pdev) -{ - struct max8903_data *data; - struct device *dev = &pdev->dev; - struct max8903_pdata *pdata = pdev->dev.platform_data; - int ret = 0; - int gpio = 0; - int ta_in = 0; - int usb_in = 0; - int retval; - - data = devm_kzalloc(dev, sizeof(struct max8903_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - pdata = pdev->dev.platform_data; - if (!pdata) { - pdata = max8903_of_populate_pdata(&pdev->dev); - if (!pdata) - return -EINVAL; - } - - data->first_delay_count = 0; - data->pdata = pdata; - data->dev = dev; - data->usb_in = 0; - data->ta_in = 0; - platform_set_drvdata(pdev, data); - - if (pdata->dc_valid == false && pdata->usb_valid == false) { - dev_err(dev, "No valid power sources.\n"); - ret = -EINVAL; - goto err; - } - if (pdata->dc_valid) { - if (pdata->dok && pdata->dcm_always_high) { - gpio = pdata->dok; - ret = gpio_request_one(gpio, GPIOF_IN, "max8903-DOK"); - if (ret) { - dev_err(dev, "request max8903-DOK error!!\n"); - goto err; - } - ta_in = gpio_get_value(gpio) ? 0 : 1; - } else { - dev_err(dev, "When DC is wired, DOK and DCM should be" - " wired as well or set dcm always high!\n"); - ret = -EINVAL; - goto err; - } - } - - if (pdata->usb_valid) { - if (pdata->uok) { - gpio = pdata->uok; - ret = gpio_request_one(gpio, GPIOF_IN, "max8903-UOK"); - if (ret) { - dev_err(dev, "request max8903-UOK error!!\n"); - goto err; - } - usb_in = gpio_get_value(gpio) ? 0 : 1; - } else { - dev_err(dev, "When USB is wired, UOK should be wired" - " as well.\n"); - ret = -EINVAL; - goto err; - } - } - - if (pdata->chg) { - ret = gpio_request_one(pdata->chg, GPIOF_IN, "max8903-CHG"); - if (ret) { - dev_err(dev, "request max8903-CHG error!!\n"); - goto err; - } - } - - if (pdata->flt) { - ret = gpio_request_one(pdata->flt, GPIOF_IN, "max8903-FLT"); - if (ret) { - dev_err(dev, "request max8903-FLT error!!\n"); - goto err; - } - } - - data->fault = false; - data->ta_in = ta_in; - data->usb_in = usb_in; - data->psy.name = "max8903-ac"; - data->psy.type = POWER_SUPPLY_TYPE_MAINS; - data->psy.get_property = max8903_get_property; - data->psy.properties = max8903_charger_props; - data->psy.num_properties = ARRAY_SIZE(max8903_charger_props); - ret = power_supply_register(dev, &data->psy); - if (ret) { - dev_err(dev, "failed: power supply register.\n"); - goto err_psy; - } - - data->usb.name = "max8903-usb"; - data->usb.type = POWER_SUPPLY_TYPE_USB; - data->usb.get_property = max8903_get_usb_property; - data->usb.properties = max8903_charger_props; - data->usb.num_properties = ARRAY_SIZE(max8903_charger_props); - ret = power_supply_register(dev, &data->usb); - if (ret) { - dev_err(dev, "failed: power supply register.\n"); - goto err_psy; - } - - data->bat.name = "max8903-charger"; - data->bat.type = POWER_SUPPLY_TYPE_BATTERY; - data->bat.properties = max8903_battery_props; - data->bat.num_properties = ARRAY_SIZE(max8903_battery_props); - data->bat.get_property = max8903_battery_get_property; - data->bat.use_for_apm = 1; - retval = power_supply_register(&pdev->dev, &data->bat); - if (retval) { - dev_err(data->dev, "failed to register battery\n"); - goto battery_failed; - } - - INIT_DELAYED_WORK(&data->work, max8903_battery_work); - schedule_delayed_work(&data->work, data->interval); - - if (pdata->dc_valid) { - ret = request_threaded_irq(gpio_to_irq(pdata->dok), NULL, - max8903_dcin, IRQF_TRIGGER_FALLING | - IRQF_TRIGGER_RISING | IRQF_ONESHOT, "MAX8903 DC IN", - data); - if (ret) { - dev_err(dev, "Cannot request irq %d for DC (%d)\n", - gpio_to_irq(pdata->dok), ret); - goto err_dc_irq; - } - } - - if (pdata->usb_valid) { - ret = request_threaded_irq(gpio_to_irq(pdata->uok), NULL, - max8903_usbin, IRQF_TRIGGER_FALLING | - IRQF_TRIGGER_RISING | IRQF_ONESHOT, "MAX8903 USB IN", - data); - if (ret) { - dev_err(dev, "Cannot request irq %d for USB (%d)\n", - gpio_to_irq(pdata->uok), ret); - goto err_usb_irq; - } - } - - if (pdata->flt) { - ret = request_threaded_irq(gpio_to_irq(pdata->flt), NULL, - max8903_fault, IRQF_TRIGGER_FALLING | - IRQF_TRIGGER_RISING | IRQF_ONESHOT, "MAX8903 Fault", - data); - if (ret) { - dev_err(dev, "Cannot request irq %d for Fault (%d)\n", - gpio_to_irq(pdata->flt), ret); - goto err_flt_irq; - } - } - - if (pdata->chg) { - ret = request_threaded_irq(gpio_to_irq(pdata->chg), NULL, - max8903_chg, IRQF_TRIGGER_FALLING | - IRQF_TRIGGER_RISING | IRQF_ONESHOT, "MAX8903 Status", - data); - if (ret) { - dev_err(dev, "Cannot request irq %d for Status (%d)\n", - gpio_to_irq(pdata->flt), ret); - goto err_chg_irq; - } - } - - ret = device_create_file(&pdev->dev, &max8903_discharger_dev_attr); - if (ret) - dev_err(&pdev->dev, "create device file failed!\n"); - ret = device_create_file(&pdev->dev, &max8903_charger_dev_attr); - if (ret) - dev_err(&pdev->dev, "create device file failed!\n"); - ret = device_create_file(&pdev->dev, &max8903_usb_charger_dev_attr); - if (ret) - dev_err(&pdev->dev, "create device file failed!\n"); - - device_set_wakeup_capable(&pdev->dev, true); - - max8903_charger_update_status(data); - max8903_battery_update_status(data); - - return 0; -err_psy: - power_supply_unregister(&data->psy); -battery_failed: - power_supply_unregister(&data->bat); -err_usb_irq: - if (pdata->usb_valid) - free_irq(gpio_to_irq(pdata->uok), data); - cancel_delayed_work(&data->work); -err_dc_irq: - if (pdata->dc_valid) - free_irq(gpio_to_irq(pdata->dok), data); - cancel_delayed_work(&data->work); -err_flt_irq: - if (pdata->usb_valid) - free_irq(gpio_to_irq(pdata->uok), data); - cancel_delayed_work(&data->work); -err_chg_irq: - if (pdata->dc_valid) - free_irq(gpio_to_irq(pdata->dok), data); - cancel_delayed_work(&data->work); -err: - if (pdata->uok) - gpio_free(pdata->uok); - if (pdata->dok) - gpio_free(pdata->dok); - if (pdata->flt) - gpio_free(pdata->flt); - if (pdata->chg) - gpio_free(pdata->chg); - return ret; -} - -static int max8903_remove(struct platform_device *pdev) -{ - struct max8903_data *data = platform_get_drvdata(pdev); - if (data) { - struct max8903_pdata *pdata = data->pdata; - - cancel_delayed_work_sync(&data->work); - power_supply_unregister(&data->psy); - power_supply_unregister(&data->usb); - power_supply_unregister(&data->bat); - - if (pdata->flt) { - free_irq(gpio_to_irq(pdata->flt), data); - gpio_free(pdata->flt); - } - if (pdata->usb_valid && pdata->uok) { - free_irq(gpio_to_irq(pdata->uok), data); - gpio_free(pdata->uok); - } - if (pdata->dc_valid) { - if (pdata->dok) { - free_irq(gpio_to_irq(pdata->dok), data); - gpio_free(pdata->dok); - } else if (pdata->chg) { - free_irq(gpio_to_irq(pdata->chg), data); - gpio_free(pdata->chg); - } - } - - device_remove_file(&pdev->dev, &max8903_discharger_dev_attr); - device_remove_file(&pdev->dev, &max8903_charger_dev_attr); - device_remove_file(&pdev->dev, &max8903_usb_charger_dev_attr); - - platform_set_drvdata(pdev, NULL); - kfree(data); - } - - return 0; -} - -static int max8903_suspend(struct platform_device *pdev, - pm_message_t state) -{ - struct max8903_data *data = platform_get_drvdata(pdev); - int irq; - if (data) { - struct max8903_pdata *pdata = data->pdata; - if (pdata) { - if (pdata->dc_valid && device_may_wakeup(&pdev->dev)) { - irq = gpio_to_irq(pdata->dok); - enable_irq_wake(irq); - } - - if (pdata->usb_valid && device_may_wakeup(&pdev->dev)) { - irq = gpio_to_irq(pdata->uok); - enable_irq_wake(irq); - } - cancel_delayed_work(&data->work); - } - } - return 0; -} - -static int max8903_resume(struct platform_device *pdev) -{ - struct max8903_data *data = platform_get_drvdata(pdev); - bool ta_in = false; - bool usb_in = false; - int irq; - - if (data) { - struct max8903_pdata *pdata = data->pdata; - - if (pdata) { - if (pdata->dok) - ta_in = gpio_get_value(pdata->dok) ? false : true; - if (pdata->uok) - usb_in = gpio_get_value(pdata->uok) ? false : true; - - if (ta_in != data->ta_in) { - data->ta_in = ta_in; - dev_info(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ? - "Connected" : "Disconnected"); - max8903_charger_update_status(data); - power_supply_changed(&data->psy); - } - - if (usb_in != data->usb_in) { - data->usb_in = usb_in; - dev_info(data->dev, "USB Charger %s.\n", usb_in ? - "Connected" : "Disconnected"); - max8903_charger_update_status(data); - power_supply_changed(&data->usb); - } - - if (pdata->dc_valid && device_may_wakeup(&pdev->dev)) { - irq = gpio_to_irq(pdata->dok); - disable_irq_wake(irq); - } - if (pdata->usb_valid && device_may_wakeup(&pdev->dev)) { - irq = gpio_to_irq(pdata->uok); - disable_irq_wake(irq); - } - - schedule_delayed_work(&data->work, - BATTERY_UPDATE_INTERVAL); - } - } - - return 0; -} - -static struct platform_driver max8903_driver = { - .probe = max8903_probe, - .remove = max8903_remove, - .suspend = max8903_suspend, - .resume = max8903_resume, - .driver = { - .name = "max8903-charger", - .owner = THIS_MODULE, - .of_match_table = max8903_dt_ids, - }, -}; -module_platform_driver(max8903_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Freescale Semiconductor, Inc."); -MODULE_DESCRIPTION("Sabresd Battery Driver"); -MODULE_ALIAS("sabresd_battery"); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 3ee46ffe90b4..d4f9670b51bc 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1843,11 +1843,6 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) if (list_empty(&message->transfers)) return -EINVAL; - if (list_empty(&message->transfers)) - return -EINVAL; - if (!message->complete) - return -EINVAL; - /* Half-duplex links include original MicroWire, and ones with * only one data pin like SPI_3WIRE (switches direction) or where * either MOSI or MISO is missing. They can also be caused by diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 85fc4b4b0246..1143db7a97ad 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -316,7 +316,7 @@ static int imx_get_trend(struct thermal_zone_device *tz, return 0; } -static const struct thermal_zone_device_ops imx_tz_ops = { +static struct thermal_zone_device_ops imx_tz_ops = { .bind = imx_bind, .unbind = imx_unbind, .get_temp = imx_get_temp, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 69d3afbe8ed5..0e950ad8cb25 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4553,7 +4553,8 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, /* Disconnect any existing devices under this port */ if (udev) { - if (hcd->phy && !hdev->parent) + if (hcd->phy && !hdev->parent && + !(portstatus & USB_PORT_STAT_CONNECTION)) usb_phy_notify_disconnect(hcd->phy, udev->speed); usb_disconnect(&port_dev->child); } diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 8bf495ffb020..75acc8b3accd 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -30,6 +30,8 @@ menu "Frame buffer Devices" source "drivers/video/fbdev/Kconfig" endmenu +source "drivers/video/mxc/Kconfig" + source "drivers/video/backlight/Kconfig" config VGASTATE diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 9ad3c17d6456..7da258c6090e 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_LOGO) += logo/ obj-y += backlight/ obj-y += fbdev/ +obj-y += mxc/ obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o ifeq ($(CONFIG_OF),y) diff --git a/drivers/video/mxc/Kconfig b/drivers/video/mxc/Kconfig new file mode 100644 index 000000000000..2269de1e02cb --- /dev/null +++ b/drivers/video/mxc/Kconfig @@ -0,0 +1,71 @@ +config FB_MXC + tristate "MXC Framebuffer support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MODE_HELPERS + default y + help + This is a framebuffer device for the MXC LCD Controller. + See for information on framebuffer + devices. + + If you plan to use the LCD display with your MXC system, say + Y here. + +config FB_MXC_SYNC_PANEL + depends on FB_MXC + tristate "Synchronous Panel Framebuffer" + +config FB_MXC_LDB + tristate "MXC LDB" + depends on FB_MXC_SYNC_PANEL + depends on MXC_IPU_V3 + +config FB_MXC_MIPI_DSI + tristate "MXC MIPI_DSI" + depends on FB_MXC_SYNC_PANEL + depends on MXC_IPU_V3 + +config FB_MXC_TRULY_WVGA_SYNC_PANEL + tristate "TRULY WVGA Panel" + depends on FB_MXC_SYNC_PANEL + depends on FB_MXC_MIPI_DSI + +config FB_MXC_HDMI + depends on FB_MXC_SYNC_PANEL + depends on MXC_IPU_V3 + depends on I2C + tristate "MXC HDMI driver support" + select MFD_MXC_HDMI + help + Driver for the on-chip MXC HDMI controller. + +config FB_MXC_EDID + depends on FB_MXC && I2C + tristate "MXC EDID support" + default y + +config FB_MXC_EINK_PANEL + depends on FB_MXC + depends on DMA_ENGINE + select FB_DEFERRED_IO + tristate "E-Ink Panel Framebuffer" + +config FB_MXC_EINK_AUTO_UPDATE_MODE + bool "E-Ink Auto-update Mode Support" + default n + depends on FB_MXC_EINK_PANEL + +config FB_MXS_SII902X + tristate "Si Image SII9022 DVI/HDMI Interface Chip" + depends on FB_MXS && I2C + +config HANNSTAR_CABC + tristate "Hannstar CABC function" + help + Say yes here to support switching on/off Hannstar CABC + function. This function turns backlight density of a + display panel automatically according to the content + shown on the panel. diff --git a/drivers/video/mxc/Makefile b/drivers/video/mxc/Makefile new file mode 100644 index 000000000000..c0fec9e79727 --- /dev/null +++ b/drivers/video/mxc/Makefile @@ -0,0 +1,9 @@ +obj-$(CONFIG_FB_MXC_LDB) += ldb.o +obj-$(CONFIG_FB_MXC_MIPI_DSI) += mipi_dsi.o +obj-$(CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL) += mxcfb_hx8369_wvga.o +obj-$(CONFIG_FB_MXC_HDMI) += mxc_hdmi.o +obj-$(CONFIG_FB_MXC_EDID) += mxc_edid.o +obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mxc_dispdrv.o mxc_lcdif.o mxc_ipuv3_fb.o +obj-$(CONFIG_FB_MXC_EINK_PANEL) += mxc_epdc_fb.o +obj-$(CONFIG_FB_MXS_SII902X) += mxsfb_sii902x.o +obj-$(CONFIG_HANNSTAR_CABC) += hannstar_cabc.o diff --git a/drivers/video/mxc/ldb.c b/drivers/video/mxc/ldb.c new file mode 100644 index 000000000000..2c7d647cc89c --- /dev/null +++ b/drivers/video/mxc/ldb.c @@ -0,0 +1,1036 @@ +/* + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * 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. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/*! + * @file mxc_ldb.c + * + * @brief This file contains the LDB driver device interface and fops + * functions. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mxc_dispdrv.h" + +#define DISPDRV_LDB "ldb" + +#define LDB_BGREF_RMODE_MASK 0x00008000 +#define LDB_BGREF_RMODE_INT 0x00008000 +#define LDB_BGREF_RMODE_EXT 0x0 + +#define LDB_DI1_VS_POL_MASK 0x00000400 +#define LDB_DI1_VS_POL_ACT_LOW 0x00000400 +#define LDB_DI1_VS_POL_ACT_HIGH 0x0 +#define LDB_DI0_VS_POL_MASK 0x00000200 +#define LDB_DI0_VS_POL_ACT_LOW 0x00000200 +#define LDB_DI0_VS_POL_ACT_HIGH 0x0 + +#define LDB_BIT_MAP_CH1_MASK 0x00000100 +#define LDB_BIT_MAP_CH1_JEIDA 0x00000100 +#define LDB_BIT_MAP_CH1_SPWG 0x0 +#define LDB_BIT_MAP_CH0_MASK 0x00000040 +#define LDB_BIT_MAP_CH0_JEIDA 0x00000040 +#define LDB_BIT_MAP_CH0_SPWG 0x0 + +#define LDB_DATA_WIDTH_CH1_MASK 0x00000080 +#define LDB_DATA_WIDTH_CH1_24 0x00000080 +#define LDB_DATA_WIDTH_CH1_18 0x0 +#define LDB_DATA_WIDTH_CH0_MASK 0x00000020 +#define LDB_DATA_WIDTH_CH0_24 0x00000020 +#define LDB_DATA_WIDTH_CH0_18 0x0 + +#define LDB_CH1_MODE_MASK 0x0000000C +#define LDB_CH1_MODE_EN_TO_DI1 0x0000000C +#define LDB_CH1_MODE_EN_TO_DI0 0x00000004 +#define LDB_CH1_MODE_DISABLE 0x0 +#define LDB_CH0_MODE_MASK 0x00000003 +#define LDB_CH0_MODE_EN_TO_DI1 0x00000003 +#define LDB_CH0_MODE_EN_TO_DI0 0x00000001 +#define LDB_CH0_MODE_DISABLE 0x0 + +#define LDB_SPLIT_MODE_EN 0x00000010 + +enum { + IMX6_LDB, +}; + +enum { + LDB_IMX6 = 1, +}; + +struct fsl_mxc_ldb_platform_data { + int devtype; + u32 ext_ref; +#define LDB_SPL_DI0 1 +#define LDB_SPL_DI1 2 +#define LDB_DUL_DI0 3 +#define LDB_DUL_DI1 4 +#define LDB_SIN0 5 +#define LDB_SIN1 6 +#define LDB_SEP0 7 +#define LDB_SEP1 8 + int mode; + int ipu_id; + int disp_id; + + /*only work for separate mode*/ + int sec_ipu_id; + int sec_disp_id; +}; + +struct ldb_data { + struct platform_device *pdev; + struct mxc_dispdrv_handle *disp_ldb; + uint32_t *reg; + uint32_t *control_reg; + uint32_t *gpr3_reg; + uint32_t control_reg_data; + struct regulator *lvds_bg_reg; + int mode; + bool inited; + struct ldb_setting { + struct clk *di_clk; + struct clk *ldb_di_clk; + struct clk *div_3_5_clk; + struct clk *div_7_clk; + struct clk *div_sel_clk; + bool active; + bool clk_en; + int ipu; + int di; + uint32_t ch_mask; + uint32_t ch_val; + } setting[2]; + struct notifier_block nb; +}; + +static int g_ldb_mode; + +static struct fb_videomode ldb_modedb[] = { + { + "LDB-WXGA", 60, 1280, 800, 14065, + 40, 40, + 10, 3, + 80, 10, + 0, + FB_VMODE_NONINTERLACED, + FB_MODE_IS_DETAILED,}, + { + "LDB-XGA", 60, 1024, 768, 15385, + 220, 40, + 21, 7, + 60, 10, + 0, + FB_VMODE_NONINTERLACED, + FB_MODE_IS_DETAILED,}, + { + "LDB-1080P60", 60, 1920, 1080, 7692, + 100, 40, + 30, 3, + 10, 2, + 0, + FB_VMODE_NONINTERLACED, + FB_MODE_IS_DETAILED,}, +}; +static int ldb_modedb_sz = ARRAY_SIZE(ldb_modedb); + +static inline int is_imx6_ldb(struct fsl_mxc_ldb_platform_data *plat_data) +{ + return (plat_data->devtype == LDB_IMX6); +} + +static int bits_per_pixel(int pixel_fmt) +{ + switch (pixel_fmt) { + case IPU_PIX_FMT_BGR24: + case IPU_PIX_FMT_RGB24: + return 24; + break; + case IPU_PIX_FMT_BGR666: + case IPU_PIX_FMT_RGB666: + case IPU_PIX_FMT_LVDS666: + return 18; + break; + default: + break; + } + return 0; +} + +static int valid_mode(int pixel_fmt) +{ + return ((pixel_fmt == IPU_PIX_FMT_RGB24) || + (pixel_fmt == IPU_PIX_FMT_BGR24) || + (pixel_fmt == IPU_PIX_FMT_LVDS666) || + (pixel_fmt == IPU_PIX_FMT_RGB666) || + (pixel_fmt == IPU_PIX_FMT_BGR666)); +} + +static int parse_ldb_mode(char *mode) +{ + int ldb_mode; + + if (!strcmp(mode, "spl0")) + ldb_mode = LDB_SPL_DI0; + else if (!strcmp(mode, "spl1")) + ldb_mode = LDB_SPL_DI1; + else if (!strcmp(mode, "dul0")) + ldb_mode = LDB_DUL_DI0; + else if (!strcmp(mode, "dul1")) + ldb_mode = LDB_DUL_DI1; + else if (!strcmp(mode, "sin0")) + ldb_mode = LDB_SIN0; + else if (!strcmp(mode, "sin1")) + ldb_mode = LDB_SIN1; + else if (!strcmp(mode, "sep0")) + ldb_mode = LDB_SEP0; + else if (!strcmp(mode, "sep1")) + ldb_mode = LDB_SEP1; + else + ldb_mode = -EINVAL; + + return ldb_mode; +} + +#ifndef MODULE +/* + * "ldb=spl0/1" -- split mode on DI0/1 + * "ldb=dul0/1" -- dual mode on DI0/1 + * "ldb=sin0/1" -- single mode on LVDS0/1 + * "ldb=sep0/1" -- separate mode begin from LVDS0/1 + * + * there are two LVDS channels(LVDS0 and LVDS1) which can transfer video + * datas, there two channels can be used as split/dual/single/separate mode. + * + * split mode means display data from DI0 or DI1 will send to both channels + * LVDS0+LVDS1. + * dual mode means display data from DI0 or DI1 will be duplicated on LVDS0 + * and LVDS1, it said, LVDS0 and LVDS1 has the same content. + * single mode means only work for DI0/DI1->LVDS0 or DI0/DI1->LVDS1. + * separate mode means you can make DI0/DI1->LVDS0 and DI0/DI1->LVDS1 work + * at the same time. + */ +static int __init ldb_setup(char *options) +{ + g_ldb_mode = parse_ldb_mode(options); + return (g_ldb_mode < 0) ? 0 : 1; +} +__setup("ldb=", ldb_setup); +#endif + +static int ldb_get_of_property(struct platform_device *pdev, + struct fsl_mxc_ldb_platform_data *plat_data) +{ + struct device_node *np = pdev->dev.of_node; + int err; + u32 ipu_id, disp_id; + u32 sec_ipu_id, sec_disp_id; + char *mode; + u32 ext_ref; + + err = of_property_read_string(np, "mode", (const char **)&mode); + if (err) { + dev_dbg(&pdev->dev, "get of property mode fail\n"); + return err; + } + err = of_property_read_u32(np, "ext_ref", &ext_ref); + if (err) { + dev_dbg(&pdev->dev, "get of property ext_ref fail\n"); + return err; + } + err = of_property_read_u32(np, "ipu_id", &ipu_id); + if (err) { + dev_dbg(&pdev->dev, "get of property ipu_id fail\n"); + return err; + } + err = of_property_read_u32(np, "disp_id", &disp_id); + if (err) { + dev_dbg(&pdev->dev, "get of property disp_id fail\n"); + return err; + } + err = of_property_read_u32(np, "sec_ipu_id", &sec_ipu_id); + if (err) { + dev_dbg(&pdev->dev, "get of property sec_ipu_id fail\n"); + return err; + } + err = of_property_read_u32(np, "sec_disp_id", &sec_disp_id); + if (err) { + dev_dbg(&pdev->dev, "get of property sec_disp_id fail\n"); + return err; + } + + plat_data->mode = parse_ldb_mode(mode); + plat_data->ext_ref = ext_ref; + plat_data->ipu_id = ipu_id; + plat_data->disp_id = disp_id; + plat_data->sec_ipu_id = sec_ipu_id; + plat_data->sec_disp_id = sec_disp_id; + + return err; +} + +static int find_ldb_setting(struct ldb_data *ldb, struct fb_info *fbi) +{ + char *id_di[] = { + "DISP3 BG", + "DISP3 BG - DI1", + }; + char id[16]; + int i; + + for (i = 0; i < 2; i++) { + if (ldb->setting[i].active) { + memset(id, 0, 16); + memcpy(id, id_di[ldb->setting[i].di], + strlen(id_di[ldb->setting[i].di])); + id[4] += ldb->setting[i].ipu; + if (!strcmp(id, fbi->fix.id)) + return i; + } + } + return -EINVAL; +} + +static int ldb_disp_setup(struct mxc_dispdrv_handle *disp, struct fb_info *fbi) +{ + uint32_t reg, val; + uint32_t pixel_clk, rounded_pixel_clk; + struct clk *ldb_clk_parent; + struct ldb_data *ldb = mxc_dispdrv_getdata(disp); + int setting_idx, di; + int ret; + + setting_idx = find_ldb_setting(ldb, fbi); + if (setting_idx < 0) + return setting_idx; + + di = ldb->setting[setting_idx].di; + + /* restore channel mode setting */ + val = readl(ldb->control_reg); + val |= ldb->setting[setting_idx].ch_val; + writel(val, ldb->control_reg); + dev_dbg(&ldb->pdev->dev, "LDB setup, control reg:0x%x\n", + readl(ldb->control_reg)); + + /* vsync setup */ + reg = readl(ldb->control_reg); + if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) { + if (di == 0) + reg = (reg & ~LDB_DI0_VS_POL_MASK) + | LDB_DI0_VS_POL_ACT_HIGH; + else + reg = (reg & ~LDB_DI1_VS_POL_MASK) + | LDB_DI1_VS_POL_ACT_HIGH; + } else { + if (di == 0) + reg = (reg & ~LDB_DI0_VS_POL_MASK) + | LDB_DI0_VS_POL_ACT_LOW; + else + reg = (reg & ~LDB_DI1_VS_POL_MASK) + | LDB_DI1_VS_POL_ACT_LOW; + } + writel(reg, ldb->control_reg); + + /* clk setup */ + if (ldb->setting[setting_idx].clk_en) + clk_disable_unprepare(ldb->setting[setting_idx].ldb_di_clk); + pixel_clk = (PICOS2KHZ(fbi->var.pixclock)) * 1000UL; + ldb_clk_parent = clk_get_parent(ldb->setting[setting_idx].ldb_di_clk); + if (IS_ERR(ldb_clk_parent)) { + dev_err(&ldb->pdev->dev, "get ldb di parent clk fail\n"); + return PTR_ERR(ldb_clk_parent); + } + if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1)) + ret = clk_set_rate(ldb_clk_parent, pixel_clk * 7 / 2); + else + ret = clk_set_rate(ldb_clk_parent, pixel_clk * 7); + if (ret < 0) { + dev_err(&ldb->pdev->dev, "set ldb parent clk fail:%d\n", ret); + return ret; + } + rounded_pixel_clk = clk_round_rate(ldb->setting[setting_idx].ldb_di_clk, + pixel_clk); + dev_dbg(&ldb->pdev->dev, "pixel_clk:%d, rounded_pixel_clk:%d\n", + pixel_clk, rounded_pixel_clk); + ret = clk_set_rate(ldb->setting[setting_idx].ldb_di_clk, + rounded_pixel_clk); + if (ret < 0) { + dev_err(&ldb->pdev->dev, "set ldb di clk fail:%d\n", ret); + return ret; + } + ret = clk_prepare_enable(ldb->setting[setting_idx].ldb_di_clk); + if (ret < 0) { + dev_err(&ldb->pdev->dev, "enable ldb di clk fail:%d\n", ret); + return ret; + } + + if (!ldb->setting[setting_idx].clk_en) + ldb->setting[setting_idx].clk_en = true; + + return 0; +} + +int ldb_fb_event(struct notifier_block *nb, unsigned long val, void *v) +{ + struct ldb_data *ldb = container_of(nb, struct ldb_data, nb); + struct fb_event *event = v; + struct fb_info *fbi = event->info; + int index; + uint32_t data; + + index = find_ldb_setting(ldb, fbi); + if (index < 0) + return 0; + + fbi->mode = (struct fb_videomode *)fb_match_mode(&fbi->var, + &fbi->modelist); + + if (!fbi->mode) { + dev_warn(&ldb->pdev->dev, + "LDB: can not find mode for xres=%d, yres=%d\n", + fbi->var.xres, fbi->var.yres); + if (ldb->setting[index].clk_en) { + clk_disable(ldb->setting[index].ldb_di_clk); + ldb->setting[index].clk_en = false; + data = readl(ldb->control_reg); + data &= ~ldb->setting[index].ch_mask; + writel(data, ldb->control_reg); + } + return 0; + } + + switch (val) { + case FB_EVENT_BLANK: + { + if (*((int *)event->data) == FB_BLANK_UNBLANK) { + if (!ldb->setting[index].clk_en) { + clk_enable(ldb->setting[index].ldb_di_clk); + ldb->setting[index].clk_en = true; + } + } else { + if (ldb->setting[index].clk_en) { + clk_disable(ldb->setting[index].ldb_di_clk); + ldb->setting[index].clk_en = false; + data = readl(ldb->control_reg); + data &= ~ldb->setting[index].ch_mask; + writel(data, ldb->control_reg); + dev_dbg(&ldb->pdev->dev, + "LDB blank, control reg:0x%x\n", + readl(ldb->control_reg)); + } + } + break; + } + case FB_EVENT_SUSPEND: + if (ldb->setting[index].clk_en) { + clk_disable(ldb->setting[index].ldb_di_clk); + ldb->setting[index].clk_en = false; + } + break; + default: + break; + } + return 0; +} + +#define LVDS_MUX_CTL_WIDTH 2 +#define LVDS_MUX_CTL_MASK 3 +#define LVDS0_MUX_CTL_OFFS 6 +#define LVDS1_MUX_CTL_OFFS 8 +#define LVDS0_MUX_CTL_MASK (LVDS_MUX_CTL_MASK << 6) +#define LVDS1_MUX_CTL_MASK (LVDS_MUX_CTL_MASK << 8) +#define ROUTE_IPU_DI(ipu, di) (((ipu << 1) | di) & LVDS_MUX_CTL_MASK) +static int ldb_ipu_ldb_route(int ipu, int di, struct ldb_data *ldb) +{ + uint32_t reg; + int channel; + int shift; + int mode = ldb->mode; + + reg = readl(ldb->gpr3_reg); + if (mode < LDB_SIN0) { + reg &= ~(LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK); + reg |= (ROUTE_IPU_DI(ipu, di) << LVDS0_MUX_CTL_OFFS) | + (ROUTE_IPU_DI(ipu, di) << LVDS1_MUX_CTL_OFFS); + dev_dbg(&ldb->pdev->dev, + "Dual/Split mode both channels route to IPU%d-DI%d\n", + ipu, di); + } else if ((mode == LDB_SIN0) || (mode == LDB_SIN1)) { + reg &= ~(LVDS0_MUX_CTL_MASK | LVDS1_MUX_CTL_MASK); + channel = mode - LDB_SIN0; + shift = LVDS0_MUX_CTL_OFFS + channel * LVDS_MUX_CTL_WIDTH; + reg |= ROUTE_IPU_DI(ipu, di) << shift; + dev_dbg(&ldb->pdev->dev, + "Single mode channel %d route to IPU%d-DI%d\n", + channel, ipu, di); + } else { + static bool first = true; + + if (first) { + if (mode == LDB_SEP0) { + reg &= ~LVDS0_MUX_CTL_MASK; + channel = 0; + } else { + reg &= ~LVDS1_MUX_CTL_MASK; + channel = 1; + } + first = false; + } else { + if (mode == LDB_SEP0) { + reg &= ~LVDS1_MUX_CTL_MASK; + channel = 1; + } else { + reg &= ~LVDS0_MUX_CTL_MASK; + channel = 0; + } + } + + shift = LVDS0_MUX_CTL_OFFS + channel * LVDS_MUX_CTL_WIDTH; + reg |= ROUTE_IPU_DI(ipu, di) << shift; + + dev_dbg(&ldb->pdev->dev, + "Separate mode channel %d route to IPU%d-DI%d\n", + channel, ipu, di); + } + writel(reg, ldb->gpr3_reg); + + return 0; +} + +static int ldb_disp_init(struct mxc_dispdrv_handle *disp, + struct mxc_dispdrv_setting *setting) +{ + int ret = 0, i, lvds_channel = 0; + struct ldb_data *ldb = mxc_dispdrv_getdata(disp); + struct fsl_mxc_ldb_platform_data *plat_data = ldb->pdev->dev.platform_data; + struct resource *res; + uint32_t reg, setting_idx; + uint32_t ch_mask = 0, ch_val = 0; + uint32_t ipu_id, disp_id; + char di_clk[] = "ipu1_di0_sel"; + char ldb_clk[] = "ldb_di0"; + char div_3_5_clk[] = "di0_div_3_5"; + char div_7_clk[] = "di0_div_7"; + char div_sel_clk[] = "di0_div_sel"; + + /* if input format not valid, make RGB666 as default*/ + if (!valid_mode(setting->if_fmt)) { + dev_warn(&ldb->pdev->dev, "Input pixel format not valid" + " use default RGB666\n"); + setting->if_fmt = IPU_PIX_FMT_RGB666; + } + + if (!ldb->inited) { + setting_idx = 0; + res = platform_get_resource(ldb->pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&ldb->pdev->dev, "get iomem fail.\n"); + return -ENOMEM; + } + + ldb->reg = devm_ioremap(&ldb->pdev->dev, res->start, + resource_size(res)); + ldb->control_reg = ldb->reg + 2; + ldb->gpr3_reg = ldb->reg + 3; + + /* ipu selected by platform data setting */ + setting->dev_id = plat_data->ipu_id; + + reg = readl(ldb->control_reg); + + /* refrence resistor select */ + reg &= ~LDB_BGREF_RMODE_MASK; + if (plat_data->ext_ref) + reg |= LDB_BGREF_RMODE_EXT; + else + reg |= LDB_BGREF_RMODE_INT; + + /* TODO: now only use SPWG data mapping for both channel */ + reg &= ~(LDB_BIT_MAP_CH0_MASK | LDB_BIT_MAP_CH1_MASK); + reg |= LDB_BIT_MAP_CH0_SPWG | LDB_BIT_MAP_CH1_SPWG; + + /* channel mode setting */ + reg &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK); + reg &= ~(LDB_DATA_WIDTH_CH0_MASK | LDB_DATA_WIDTH_CH1_MASK); + + if (bits_per_pixel(setting->if_fmt) == 24) + reg |= LDB_DATA_WIDTH_CH0_24 | LDB_DATA_WIDTH_CH1_24; + else + reg |= LDB_DATA_WIDTH_CH0_18 | LDB_DATA_WIDTH_CH1_18; + + if (g_ldb_mode >= LDB_SPL_DI0) + ldb->mode = g_ldb_mode; + else + ldb->mode = plat_data->mode; + + if ((ldb->mode == LDB_SIN0) || (ldb->mode == LDB_SIN1)) { + ret = ldb->mode - LDB_SIN0; + if (plat_data->disp_id != ret) { + dev_warn(&ldb->pdev->dev, + "change IPU DI%d to IPU DI%d for LDB " + "channel%d.\n", + plat_data->disp_id, ret, ret); + plat_data->disp_id = ret; + } + } else if (((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1)) + && is_imx6_ldb(plat_data)) { + if (plat_data->disp_id == plat_data->sec_disp_id) { + dev_err(&ldb->pdev->dev, + "For LVDS separate mode," + "two DIs should be different!\n"); + return -EINVAL; + } + + if (((!plat_data->disp_id) && (ldb->mode == LDB_SEP1)) + || ((plat_data->disp_id) && + (ldb->mode == LDB_SEP0))) { + dev_dbg(&ldb->pdev->dev, + "LVDS separate mode:" + "swap DI configuration!\n"); + ipu_id = plat_data->ipu_id; + disp_id = plat_data->disp_id; + plat_data->ipu_id = plat_data->sec_ipu_id; + plat_data->disp_id = plat_data->sec_disp_id; + plat_data->sec_ipu_id = ipu_id; + plat_data->sec_disp_id = disp_id; + } + } + + if (ldb->mode == LDB_SPL_DI0) { + reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI0 + | LDB_CH1_MODE_EN_TO_DI0; + setting->disp_id = 0; + } else if (ldb->mode == LDB_SPL_DI1) { + reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI1 + | LDB_CH1_MODE_EN_TO_DI1; + setting->disp_id = 1; + } else if (ldb->mode == LDB_DUL_DI0) { + reg &= ~LDB_SPLIT_MODE_EN; + reg |= LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI0; + setting->disp_id = 0; + } else if (ldb->mode == LDB_DUL_DI1) { + reg &= ~LDB_SPLIT_MODE_EN; + reg |= LDB_CH0_MODE_EN_TO_DI1 | LDB_CH1_MODE_EN_TO_DI1; + setting->disp_id = 1; + } else if (ldb->mode == LDB_SIN0) { + reg &= ~LDB_SPLIT_MODE_EN; + setting->disp_id = plat_data->disp_id; + if (setting->disp_id == 0) + reg |= LDB_CH0_MODE_EN_TO_DI0; + else + reg |= LDB_CH0_MODE_EN_TO_DI1; + ch_mask = LDB_CH0_MODE_MASK; + ch_val = reg & LDB_CH0_MODE_MASK; + } else if (ldb->mode == LDB_SIN1) { + reg &= ~LDB_SPLIT_MODE_EN; + setting->disp_id = plat_data->disp_id; + if (setting->disp_id == 0) + reg |= LDB_CH1_MODE_EN_TO_DI0; + else + reg |= LDB_CH1_MODE_EN_TO_DI1; + ch_mask = LDB_CH1_MODE_MASK; + ch_val = reg & LDB_CH1_MODE_MASK; + } else { /* separate mode*/ + setting->disp_id = plat_data->disp_id; + + /* first output is LVDS0 or LVDS1 */ + if (ldb->mode == LDB_SEP0) + lvds_channel = 0; + else + lvds_channel = 1; + + reg &= ~LDB_SPLIT_MODE_EN; + + if ((lvds_channel == 0) && (setting->disp_id == 0)) + reg |= LDB_CH0_MODE_EN_TO_DI0; + else if ((lvds_channel == 0) && (setting->disp_id == 1)) + reg |= LDB_CH0_MODE_EN_TO_DI1; + else if ((lvds_channel == 1) && (setting->disp_id == 0)) + reg |= LDB_CH1_MODE_EN_TO_DI0; + else + reg |= LDB_CH1_MODE_EN_TO_DI1; + ch_mask = lvds_channel ? LDB_CH1_MODE_MASK : + LDB_CH0_MODE_MASK; + ch_val = reg & ch_mask; + + if (bits_per_pixel(setting->if_fmt) == 24) { + if (lvds_channel == 0) + reg &= ~LDB_DATA_WIDTH_CH1_24; + else + reg &= ~LDB_DATA_WIDTH_CH0_24; + } else { + if (lvds_channel == 0) + reg &= ~LDB_DATA_WIDTH_CH1_18; + else + reg &= ~LDB_DATA_WIDTH_CH0_18; + } + } + + writel(reg, ldb->control_reg); + if (ldb->mode < LDB_SIN0) { + ch_mask = LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK; + ch_val = reg & (LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK); + } + } else { /* second time for separate mode */ + if ((ldb->mode == LDB_SPL_DI0) || + (ldb->mode == LDB_SPL_DI1) || + (ldb->mode == LDB_DUL_DI0) || + (ldb->mode == LDB_DUL_DI1) || + (ldb->mode == LDB_SIN0) || + (ldb->mode == LDB_SIN1)) { + dev_err(&ldb->pdev->dev, "for second ldb disp" + "ldb mode should in separate mode\n"); + return -EINVAL; + } + + setting_idx = 1; + if (is_imx6_ldb(plat_data)) { + setting->dev_id = plat_data->sec_ipu_id; + setting->disp_id = plat_data->sec_disp_id; + } else { + setting->dev_id = plat_data->ipu_id; + setting->disp_id = !plat_data->disp_id; + } + if (setting->disp_id == ldb->setting[0].di) { + dev_err(&ldb->pdev->dev, "Err: for second ldb disp in" + "separate mode, DI should be different!\n"); + return -EINVAL; + } + + /* second output is LVDS0 or LVDS1 */ + if (ldb->mode == LDB_SEP0) + lvds_channel = 1; + else + lvds_channel = 0; + + reg = readl(ldb->control_reg); + if ((lvds_channel == 0) && (setting->disp_id == 0)) + reg |= LDB_CH0_MODE_EN_TO_DI0; + else if ((lvds_channel == 0) && (setting->disp_id == 1)) + reg |= LDB_CH0_MODE_EN_TO_DI1; + else if ((lvds_channel == 1) && (setting->disp_id == 0)) + reg |= LDB_CH1_MODE_EN_TO_DI0; + else + reg |= LDB_CH1_MODE_EN_TO_DI1; + ch_mask = lvds_channel ? LDB_CH1_MODE_MASK : + LDB_CH0_MODE_MASK; + ch_val = reg & ch_mask; + + if (bits_per_pixel(setting->if_fmt) == 24) { + if (lvds_channel == 0) + reg |= LDB_DATA_WIDTH_CH0_24; + else + reg |= LDB_DATA_WIDTH_CH1_24; + } else { + if (lvds_channel == 0) + reg |= LDB_DATA_WIDTH_CH0_18; + else + reg |= LDB_DATA_WIDTH_CH1_18; + } + writel(reg, ldb->control_reg); + } + + /* get clocks */ + if (is_imx6_ldb(plat_data) && + ((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1))) { + ldb_clk[6] += lvds_channel; + div_3_5_clk[2] += lvds_channel; + div_7_clk[2] += lvds_channel; + div_sel_clk[2] += lvds_channel; + } else { + ldb_clk[6] += setting->disp_id; + div_3_5_clk[2] += setting->disp_id; + div_7_clk[2] += setting->disp_id; + div_sel_clk[2] += setting->disp_id; + } + ldb->setting[setting_idx].ldb_di_clk = clk_get(&ldb->pdev->dev, + ldb_clk); + if (IS_ERR(ldb->setting[setting_idx].ldb_di_clk)) { + dev_err(&ldb->pdev->dev, "get ldb clk failed\n"); + return PTR_ERR(ldb->setting[setting_idx].ldb_di_clk); + } + + ldb->setting[setting_idx].div_3_5_clk = clk_get(&ldb->pdev->dev, + div_3_5_clk); + if (IS_ERR(ldb->setting[setting_idx].div_3_5_clk)) { + dev_err(&ldb->pdev->dev, "get div 3.5 clk failed\n"); + return PTR_ERR(ldb->setting[setting_idx].div_3_5_clk); + } + ldb->setting[setting_idx].div_7_clk = clk_get(&ldb->pdev->dev, + div_7_clk); + if (IS_ERR(ldb->setting[setting_idx].div_7_clk)) { + dev_err(&ldb->pdev->dev, "get div 7 clk failed\n"); + return PTR_ERR(ldb->setting[setting_idx].div_7_clk); + } + + ldb->setting[setting_idx].div_sel_clk = clk_get(&ldb->pdev->dev, + div_sel_clk); + if (IS_ERR(ldb->setting[setting_idx].div_sel_clk)) { + dev_err(&ldb->pdev->dev, "get div sel clk failed\n"); + return PTR_ERR(ldb->setting[setting_idx].div_sel_clk); + } + + di_clk[3] += setting->dev_id; + di_clk[7] += setting->disp_id; + ldb->setting[setting_idx].di_clk = clk_get(&ldb->pdev->dev, + di_clk); + if (IS_ERR(ldb->setting[setting_idx].di_clk)) { + dev_err(&ldb->pdev->dev, "get di clk failed\n"); + return PTR_ERR(ldb->setting[setting_idx].di_clk); + } + + ldb->setting[setting_idx].ch_mask = ch_mask; + ldb->setting[setting_idx].ch_val = ch_val; + + if (is_imx6_ldb(plat_data)) + ldb_ipu_ldb_route(setting->dev_id, setting->disp_id, ldb); + + /* must use spec video mode defined by driver */ + ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str, + ldb_modedb, ldb_modedb_sz, NULL, setting->default_bpp); + if (ret != 1) + fb_videomode_to_var(&setting->fbi->var, &ldb_modedb[0]); + + INIT_LIST_HEAD(&setting->fbi->modelist); + for (i = 0; i < ldb_modedb_sz; i++) { + struct fb_videomode m; + fb_var_to_videomode(&m, &setting->fbi->var); + if (fb_mode_is_equal(&m, &ldb_modedb[i])) { + fb_add_videomode(&ldb_modedb[i], + &setting->fbi->modelist); + break; + } + } + + ldb->setting[setting_idx].ipu = setting->dev_id; + ldb->setting[setting_idx].di = setting->disp_id; + + return ret; +} + +static int ldb_post_disp_init(struct mxc_dispdrv_handle *disp, + int ipu_id, int disp_id) +{ + struct ldb_data *ldb = mxc_dispdrv_getdata(disp); + int setting_idx = ldb->inited ? 1 : 0; + int ret = 0; + + if (!ldb->inited) { + ldb->nb.notifier_call = ldb_fb_event; + fb_register_client(&ldb->nb); + } + + ret = clk_set_parent(ldb->setting[setting_idx].di_clk, + ldb->setting[setting_idx].ldb_di_clk); + if (ret) { + dev_err(&ldb->pdev->dev, "fail to set ldb_di clk as" + "the parent of ipu_di clk\n"); + return ret; + } + + if ((ldb->mode == LDB_SPL_DI0) || (ldb->mode == LDB_SPL_DI1)) { + ret = clk_set_parent(ldb->setting[setting_idx].div_sel_clk, + ldb->setting[setting_idx].div_3_5_clk); + if (ret) { + dev_err(&ldb->pdev->dev, "fail to set div 3.5 clk as" + "the parent of div sel clk\n"); + return ret; + } + } else { + ret = clk_set_parent(ldb->setting[setting_idx].div_sel_clk, + ldb->setting[setting_idx].div_7_clk); + if (ret) { + dev_err(&ldb->pdev->dev, "fail to set div 7 clk as" + "the parent of div sel clk\n"); + return ret; + } + } + + /* save active ldb setting for fb notifier */ + ldb->setting[setting_idx].active = true; + + ldb->inited = true; + return ret; +} + +static void ldb_disp_deinit(struct mxc_dispdrv_handle *disp) +{ + struct ldb_data *ldb = mxc_dispdrv_getdata(disp); + int i; + + writel(0, ldb->control_reg); + + for (i = 0; i < 2; i++) { + clk_disable(ldb->setting[i].ldb_di_clk); + clk_put(ldb->setting[i].ldb_di_clk); + clk_put(ldb->setting[i].div_3_5_clk); + clk_put(ldb->setting[i].div_7_clk); + clk_put(ldb->setting[i].div_sel_clk); + } + + fb_unregister_client(&ldb->nb); +} + +static struct mxc_dispdrv_driver ldb_drv = { + .name = DISPDRV_LDB, + .init = ldb_disp_init, + .post_init = ldb_post_disp_init, + .deinit = ldb_disp_deinit, + .setup = ldb_disp_setup, +}; + +static int ldb_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct ldb_data *ldb = dev_get_drvdata(&pdev->dev); + uint32_t data; + + if (!ldb->inited) + return 0; + data = readl(ldb->control_reg); + ldb->control_reg_data = data; + data &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK); + writel(data, ldb->control_reg); + + return 0; +} + +static int ldb_resume(struct platform_device *pdev) +{ + struct ldb_data *ldb = dev_get_drvdata(&pdev->dev); + + if (!ldb->inited) + return 0; + writel(ldb->control_reg_data, ldb->control_reg); + + return 0; +} + +static struct platform_device_id imx_ldb_devtype[] = { + { + .name = "ldb-imx6", + .driver_data = LDB_IMX6, + }, { + /* sentinel */ + } +}; + +static const struct of_device_id imx_ldb_dt_ids[] = { + { .compatible = "fsl,imx6q-ldb", .data = &imx_ldb_devtype[IMX6_LDB],}, + { /* sentinel */ } +}; + +/*! + * This function is called by the driver framework to initialize the LDB + * device. + * + * @param dev The device structure for the LDB passed in by the + * driver framework. + * + * @return Returns 0 on success or negative error code on error + */ +static int ldb_probe(struct platform_device *pdev) +{ + int ret = 0; + struct ldb_data *ldb; + struct fsl_mxc_ldb_platform_data *plat_data; + const struct of_device_id *of_id = + of_match_device(imx_ldb_dt_ids, &pdev->dev); + + dev_dbg(&pdev->dev, "%s enter\n", __func__); + ldb = devm_kzalloc(&pdev->dev, sizeof(struct ldb_data), GFP_KERNEL); + if (!ldb) + return -ENOMEM; + + plat_data = devm_kzalloc(&pdev->dev, + sizeof(struct fsl_mxc_ldb_platform_data), + GFP_KERNEL); + if (!plat_data) + return -ENOMEM; + pdev->dev.platform_data = plat_data; + if (of_id) + pdev->id_entry = of_id->data; + plat_data->devtype = pdev->id_entry->driver_data; + + ret = ldb_get_of_property(pdev, plat_data); + if (ret < 0) { + dev_err(&pdev->dev, "get ldb of property fail\n"); + return ret; + } + + ldb->pdev = pdev; + ldb->disp_ldb = mxc_dispdrv_register(&ldb_drv); + mxc_dispdrv_setdata(ldb->disp_ldb, ldb); + + dev_set_drvdata(&pdev->dev, ldb); + + dev_dbg(&pdev->dev, "%s exit\n", __func__); + return ret; +} + +static int ldb_remove(struct platform_device *pdev) +{ + struct ldb_data *ldb = dev_get_drvdata(&pdev->dev); + + if (!ldb->inited) + return 0; + mxc_dispdrv_puthandle(ldb->disp_ldb); + mxc_dispdrv_unregister(ldb->disp_ldb); + return 0; +} + +static struct platform_driver mxcldb_driver = { + .driver = { + .name = "mxc_ldb", + .of_match_table = imx_ldb_dt_ids, + }, + .probe = ldb_probe, + .remove = ldb_remove, + .suspend = ldb_suspend, + .resume = ldb_resume, +}; + +static int __init ldb_init(void) +{ + return platform_driver_register(&mxcldb_driver); +} + +static void __exit ldb_uninit(void) +{ + platform_driver_unregister(&mxcldb_driver); +} + +module_init(ldb_init); +module_exit(ldb_uninit); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("MXC LDB driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/mxc/mxc_dispdrv.c b/drivers/video/mxc/mxc_dispdrv.c new file mode 100644 index 000000000000..5193c7deef00 --- /dev/null +++ b/drivers/video/mxc/mxc_dispdrv.c @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/*! + * @file mxc_dispdrv.c + * @brief mxc display driver framework. + * + * A display device driver could call mxc_dispdrv_register(drv) in its dev_probe() function. + * Move all dev_probe() things into mxc_dispdrv_driver->init(), init() function should init + * and feedback setting; + * Necessary deferred operations can be done in mxc_dispdrv_driver->post_init(), + * after dev_id and disp_id pass usage check; + * Move all dev_remove() things into mxc_dispdrv_driver->deinit(); + * Move all dev_suspend() things into fb_notifier for SUSPEND, if there is; + * Move all dev_resume() things into fb_notifier for RESUME, if there is; + * + * ipuv3 fb driver could call mxc_dispdrv_gethandle(name, setting) before a fb + * need be added, with fbi param passing by setting, after + * mxc_dispdrv_gethandle() return, FB driver should get the basic setting + * about fbi info and ipuv3-hw (ipu_id and disp_id). + * + * @ingroup Framebuffer + */ + +#include +#include +#include +#include +#include +#include +#include +#include "mxc_dispdrv.h" + +static LIST_HEAD(dispdrv_list); +static DEFINE_MUTEX(dispdrv_lock); + +struct mxc_dispdrv_entry { + /* Note: drv always the first element */ + struct mxc_dispdrv_driver *drv; + bool active; + void *priv; + struct list_head list; +}; + +struct mxc_dispdrv_handle *mxc_dispdrv_register(struct mxc_dispdrv_driver *drv) +{ + struct mxc_dispdrv_entry *new; + + mutex_lock(&dispdrv_lock); + + new = kzalloc(sizeof(struct mxc_dispdrv_entry), GFP_KERNEL); + if (!new) { + mutex_unlock(&dispdrv_lock); + return ERR_PTR(-ENOMEM); + } + + new->drv = drv; + list_add_tail(&new->list, &dispdrv_list); + + mutex_unlock(&dispdrv_lock); + + return (struct mxc_dispdrv_handle *)new; +} +EXPORT_SYMBOL_GPL(mxc_dispdrv_register); + +int mxc_dispdrv_unregister(struct mxc_dispdrv_handle *handle) +{ + struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle; + + if (entry) { + mutex_lock(&dispdrv_lock); + list_del(&entry->list); + mutex_unlock(&dispdrv_lock); + kfree(entry); + return 0; + } else + return -EINVAL; +} +EXPORT_SYMBOL_GPL(mxc_dispdrv_unregister); + +struct mxc_dispdrv_handle *mxc_dispdrv_gethandle(char *name, + struct mxc_dispdrv_setting *setting) +{ + int ret, found = 0; + struct mxc_dispdrv_entry *entry; + + mutex_lock(&dispdrv_lock); + list_for_each_entry(entry, &dispdrv_list, list) { + if (!strcmp(entry->drv->name, name) && (entry->drv->init)) { + ret = entry->drv->init((struct mxc_dispdrv_handle *) + entry, setting); + if (ret >= 0) { + entry->active = true; + found = 1; + break; + } + } + } + mutex_unlock(&dispdrv_lock); + + return found ? (struct mxc_dispdrv_handle *)entry:ERR_PTR(-ENODEV); +} +EXPORT_SYMBOL_GPL(mxc_dispdrv_gethandle); + +void mxc_dispdrv_puthandle(struct mxc_dispdrv_handle *handle) +{ + struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle; + + mutex_lock(&dispdrv_lock); + if (entry && entry->active && entry->drv->deinit) { + entry->drv->deinit(handle); + entry->active = false; + } + mutex_unlock(&dispdrv_lock); + +} +EXPORT_SYMBOL_GPL(mxc_dispdrv_puthandle); + +int mxc_dispdrv_setdata(struct mxc_dispdrv_handle *handle, void *data) +{ + struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle; + + if (entry) { + entry->priv = data; + return 0; + } else + return -EINVAL; +} +EXPORT_SYMBOL_GPL(mxc_dispdrv_setdata); + +void *mxc_dispdrv_getdata(struct mxc_dispdrv_handle *handle) +{ + struct mxc_dispdrv_entry *entry = (struct mxc_dispdrv_entry *)handle; + + if (entry) { + return entry->priv; + } else + return ERR_PTR(-EINVAL); +} +EXPORT_SYMBOL_GPL(mxc_dispdrv_getdata); diff --git a/drivers/video/mxc/mxc_dispdrv.h b/drivers/video/mxc/mxc_dispdrv.h new file mode 100644 index 000000000000..127fd08ea391 --- /dev/null +++ b/drivers/video/mxc/mxc_dispdrv.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef __MXC_DISPDRV_H__ +#define __MXC_DISPDRV_H__ +#include + +struct mxc_dispdrv_handle { + struct mxc_dispdrv_driver *drv; +}; + +struct mxc_dispdrv_setting { + /*input-feedback parameter*/ + struct fb_info *fbi; + int if_fmt; + int default_bpp; + char *dft_mode_str; + + /*feedback parameter*/ + int dev_id; + int disp_id; +}; + +struct mxc_dispdrv_driver { + const char *name; + int (*init) (struct mxc_dispdrv_handle *, struct mxc_dispdrv_setting *); + /* deferred operations after dev_id and disp_id pass usage check */ + int (*post_init) (struct mxc_dispdrv_handle *, int dev_id, int disp_id); + void (*deinit) (struct mxc_dispdrv_handle *); + /* display driver enable function for extension */ + int (*enable) (struct mxc_dispdrv_handle *); + /* display driver disable function, called at early part of fb_blank */ + void (*disable) (struct mxc_dispdrv_handle *); + /* display driver setup function, called at early part of fb_set_par */ + int (*setup) (struct mxc_dispdrv_handle *, struct fb_info *fbi); +}; + +struct mxc_dispdrv_handle *mxc_dispdrv_register(struct mxc_dispdrv_driver *drv); +int mxc_dispdrv_unregister(struct mxc_dispdrv_handle *handle); +struct mxc_dispdrv_handle *mxc_dispdrv_gethandle(char *name, + struct mxc_dispdrv_setting *setting); +void mxc_dispdrv_puthandle(struct mxc_dispdrv_handle *handle); +int mxc_dispdrv_setdata(struct mxc_dispdrv_handle *handle, void *data); +void *mxc_dispdrv_getdata(struct mxc_dispdrv_handle *handle); +#endif diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c index ca3c85526813..9ba601f8b757 100644 --- a/drivers/video/mxc/mxc_ipuv3_fb.c +++ b/drivers/video/mxc/mxc_ipuv3_fb.c @@ -10,7 +10,7 @@ * http://www.opensource.org/licenses/gpl-license.html * http://www.gnu.org/copyleft/gpl.html */ - +#define DEBUG /*! * @defgroup Framebuffer Framebuffer Driver for SDC and ADC. */ @@ -446,8 +446,8 @@ static int mxcfb_set_par(struct fb_info *fbi) if (ipu_ch_param_bad_alpha_pos(fbi_to_pixfmt(fbi)) && mxc_fbi->alpha_chan_en) { - dev_err(fbi->device, "Bad pixel format for " - "graphics plane fb\n"); + dev_err(fbi->device, + "Bad pixel format for graphics plane fb\n"); return -EINVAL; } @@ -570,8 +570,8 @@ static int mxcfb_set_par(struct fb_info *fbi) if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->setup) { retval = mxc_fbi->dispdrv->drv->setup(mxc_fbi->dispdrv, fbi); if (retval < 0) { - dev_err(fbi->device, "setup error, dispdrv:%s.\n", - mxc_fbi->dispdrv->drv->name); + dev_err(fbi->device, "setup error, dispdrv: %s (%d)\n", + mxc_fbi->dispdrv->drv->name, retval); return -EINVAL; } } @@ -656,8 +656,8 @@ static int mxcfb_set_par(struct fb_info *fbi) if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->enable) { retval = mxc_fbi->dispdrv->drv->enable(mxc_fbi->dispdrv); if (retval < 0) { - dev_err(fbi->device, "enable error, dispdrv:%s.\n", - mxc_fbi->dispdrv->drv->name); + dev_err(fbi->device, "enable error, dispdrv: %s (%d)\n", + mxc_fbi->dispdrv->drv->name, retval); return -EINVAL; } } @@ -2355,7 +2355,7 @@ static int mxcfb_probe(struct platform_device *pdev) ret = mxcfb_get_of_property(pdev, plat_data); if (ret < 0) { - dev_err(&pdev->dev, "get mxcfb of property fail\n"); + dev_err(&pdev->dev, "get mxcfb of property failed: %d\n", ret); return ret; } diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 95b0bf8d5f4c..8f8ae95c6e27 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -475,9 +475,6 @@ extern struct cpufreq_governor cpufreq_gov_ondemand; #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE) extern struct cpufreq_governor cpufreq_gov_conservative; #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative) -#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE) -extern struct cpufreq_governor cpufreq_gov_interactive; -#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_interactive) #endif /********************************************************************* diff --git a/include/linux/isl29023.h b/include/linux/isl29023.h deleted file mode 100644 index 044b41dadb27..000000000000 --- a/include/linux/isl29023.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * 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. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef __ISL29023_H__ -#define __ISL29023_H__ - -#include - -#define ISL29023_PD_MODE 0x0 -#define ISL29023_ALS_ONCE_MODE 0x1 -#define ISL29023_IR_ONCE_MODE 0x2 -#define ISL29023_ALS_CONT_MODE 0x5 -#define ISL29023_IR_CONT_MODE 0x6 - -#define ISL29023_INT_PERSISTS_1 0x0 -#define ISL29023_INT_PERSISTS_4 0x1 -#define ISL29023_INT_PERSISTS_8 0x2 -#define ISL29023_INT_PERSISTS_16 0x3 - -#define ISL29023_RES_16 0x0 -#define ISL29023_RES_12 0x1 -#define ISL29023_RES_8 0x2 -#define ISL29023_RES_4 0x3 - -#define ISL29023_RANGE_1K 0x0 -#define ISL29023_RANGE_4K 0x1 -#define ISL29023_RANGE_16K 0x2 -#define ISL29023_RANGE_64K 0x3 - -#endif diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 3f81170f6df1..d424b9de3aff 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -86,13 +86,10 @@ struct mmc_ext_csd { unsigned int data_sector_size; /* 512 bytes or 4KB */ unsigned int data_tag_unit_size; /* DATA TAG UNIT size */ unsigned int boot_ro_lock; /* ro lock support */ - unsigned int boot_size; bool boot_ro_lockable; u8 raw_exception_status; /* 54 */ u8 raw_partition_support; /* 160 */ u8 raw_rpmb_size_mult; /* 168 */ - u8 boot_bus_width; /* 177 */ - u8 boot_config; /* 179 */ u8 raw_erased_mem_count; /* 181 */ u8 raw_ext_csd_structure; /* 194 */ u8 raw_card_type; /* 196 */ @@ -105,7 +102,6 @@ struct mmc_ext_csd { u8 raw_hc_erase_gap_size; /* 221 */ u8 raw_erase_timeout_mult; /* 223 */ u8 raw_hc_erase_grp_size; /* 224 */ - u8 boot_info; /* 228 */ u8 raw_sec_trim_mult; /* 229 */ u8 raw_sec_erase_mult; /* 230 */ u8 raw_sec_feature_support;/* 231 */ diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index e175d05186af..64ec963ed347 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -292,7 +292,6 @@ struct _mmc_csd { #define EXT_CSD_RPMB_MULT 168 /* RO */ #define EXT_CSD_BOOT_WP 173 /* R/W */ #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ -#define EXT_CSD_BOOT_BUS_WIDTH 177 /* R/W */ #define EXT_CSD_PART_CONFIG 179 /* R/W */ #define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ #define EXT_CSD_BUS_WIDTH 183 /* R/W */ @@ -314,7 +313,6 @@ struct _mmc_csd { #define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ #define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ #define EXT_CSD_BOOT_MULT 226 /* RO */ -#define EXT_CSD_BOOT_INFO 228 /* RO, 1 bytes */ #define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ #define EXT_CSD_SEC_ERASE_MULT 230 /* RO */ #define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ @@ -393,29 +391,6 @@ struct _mmc_csd { #define EXT_CSD_SEC_GB_CL_EN BIT(4) #define EXT_CSD_SEC_SANITIZE BIT(6) /* v4.5 only */ -#define EXT_CSD_BOOT_BUS_WIDTH_MASK (0x1F) -#define EXT_CSD_BOOT_BUS_WIDTH_MODE_MASK (0x3 << 3) -#define EXT_CSD_BOOT_BUS_WIDTH_MODE_SDR_NORMAL (0x0) -#define EXT_CSD_BOOT_BUS_WIDTH_MODE_SDR_HIGH (0x1) -#define EXT_CSD_BOOT_BUS_WIDTH_MODE_DDR (0x2) -#define EXT_CSD_BOOT_BUS_WIDTH_RST_WIDTH (1 << 2) -#define EXT_CSD_BOOT_BUS_WIDTH_WIDTH_MASK (0x3) -#define EXT_CSD_BOOT_BUS_WIDTH_1_SDR_4_DDR (0x0) -#define EXT_CSD_BOOT_BUS_WIDTH_4_SDR_4_DDR (0x1) -#define EXT_CSD_BOOT_BUS_WIDTH_8_SDR_8_DDR (0x2) - -#define EXT_CSD_BOOT_ACK_ENABLE (0x1 << 6) -#define EXT_CSD_BOOT_PARTITION_ENABLE_MASK (0x7 << 3) -#define EXT_CSD_BOOT_PARTITION_DISABLE (0x0) -#define EXT_CSD_BOOT_PARTITION_PART1 (0x1 << 3) -#define EXT_CSD_BOOT_PARTITION_PART2 (0x2 << 3) -#define EXT_CSD_BOOT_PARTITION_USER (0x7 << 3) - -#define EXT_CSD_BOOT_PARTITION_ACCESS_MASK (0x7) -#define EXT_CSD_BOOT_PARTITION_ACCESS_DISABLE (0x0) -#define EXT_CSD_BOOT_PARTITION_ACCESS_PART1 (0x1) -#define EXT_CSD_BOOT_PARTITION_ACCESS_PART2 (0x2) - #define EXT_CSD_RST_N_EN_MASK 0x3 #define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */ diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index dba6b9e47ff2..5f487d776411 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -438,7 +438,7 @@ static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned if (map->cached) memcpy(to, (char *)map->cached + from, len); else - memcpy(to, map->virt + from, len); + memcpy_fromio(to, map->virt + from, len); } static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) diff --git a/include/linux/mxc_vpu.h b/include/linux/mxc_vpu.h index 27f9377856aa..df6af92e5668 100644 --- a/include/linux/mxc_vpu.h +++ b/include/linux/mxc_vpu.h @@ -38,8 +38,8 @@ struct mxc_vpu_platform_data { struct vpu_mem_desc { u32 size; dma_addr_t phy_addr; - u32 cpu_addr; /* cpu address to free the dma mem */ - u32 virt_uaddr; /* virtual user space address */ + void *cpu_addr; /* cpu address to free the dma mem */ + void *virt_uaddr; /* virtual user space address */ }; #define VPU_IOC_MAGIC 'V' diff --git a/include/linux/mxcfb.h b/include/linux/mxcfb.h new file mode 100644 index 000000000000..67db5ee3fd11 --- /dev/null +++ b/include/linux/mxcfb.h @@ -0,0 +1,46 @@ +/* + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU Lesser General + * Public License. You may obtain a copy of the GNU Lesser General + * Public License Version 2.1 or later at the following locations: + * + * http://www.opensource.org/licenses/lgpl-license.html + * http://www.gnu.org/copyleft/lgpl.html + */ + +/* + * @file linux/mxcfb.h + * + * @brief Global header file for the MXC Frame buffer + * + * @ingroup Framebuffer + */ +#ifndef __LINUX_MXCFB_H__ +#define __LINUX_MXCFB_H__ + +#include + +extern struct fb_videomode mxcfb_modedb[]; +extern int mxcfb_modedb_sz; + +enum { + MXC_DISP_SPEC_DEV = 0, + MXC_DISP_DDC_DEV = 1, +}; + +enum { + MXCFB_REFRESH_OFF, + MXCFB_REFRESH_AUTO, + MXCFB_REFRESH_PARTIAL, +}; + +int mxcfb_set_refresh_mode(struct fb_info *fbi, int mode, + struct mxcfb_rect *update_region); +int mxc_elcdif_frame_addr_setup(dma_addr_t phys); +void mxcfb_elcdif_register_mode(const struct fb_videomode *modedb, + int num_modes, int dev_mode); + +#endif diff --git a/include/linux/power/imx6_usb_charger.h b/include/linux/power/imx6_usb_charger.h deleted file mode 100644 index 39358d22f396..000000000000 --- a/include/linux/power/imx6_usb_charger.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#ifndef __IMXUSB6_CHARGER_H -#define __IMXUSB6_CHARGER_H - -#include -enum battery_charging_spec { - BATTERY_CHARGING_SPEC_NONE = 0, - BATTERY_CHARGING_SPEC_UNKNOWN, - BATTERY_CHARGING_SPEC_1_0, - BATTERY_CHARGING_SPEC_1_1, - BATTERY_CHARGING_SPEC_1_2, -}; - -struct usb_charger { - /* The anatop regmap */ - struct regmap *anatop; - /* USB controller */ - struct device *dev; - struct power_supply psy; - struct mutex lock; - - /* Compliant with Battery Charging Specification version (if any) */ - enum battery_charging_spec bc; - - /* properties */ - unsigned present:1; - unsigned online:1; - unsigned max_current; - int (*connect)(struct usb_charger *charger); - int (*disconnect)(struct usb_charger *charger); - int (*set_power)(struct usb_charger *charger, unsigned mA); - - int (*detect)(struct usb_charger *charger); -}; - -#ifdef CONFIG_IMX6_USB_CHARGER -extern void imx6_usb_remove_charger(struct usb_charger *charger); -extern int imx6_usb_create_charger(struct usb_charger *charger, - const char *name); -extern int imx6_usb_vbus_disconnect(struct usb_charger *charger); -extern int imx6_usb_vbus_connect(struct usb_charger *charger); -extern int imx6_usb_charger_detect_post(struct usb_charger *charger); -#else -void imx6_usb_remove_charger(struct usb_charger *charger) -{ - -} - -int imx6_usb_create_charger(struct usb_charger *charger, - const char *name) -{ - return -ENODEV; -} - -int imx6_usb_vbus_disconnect(struct usb_charger *charger) -{ - return -ENODEV; -} - -int imx6_usb_vbus_connect(struct usb_charger *charger) -{ - return -ENODEV; -} -int imx6_usb_charger_detect_post(struct usb_charger *charger) -{ - return -ENODEV; -} -#endif - -#endif /* __IMXUSB6_CHARGER_H */ diff --git a/include/linux/power/sabresd_battery.h b/include/linux/power/sabresd_battery.h deleted file mode 100644 index f157b16fa17e..000000000000 --- a/include/linux/power/sabresd_battery.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * sabresd_battery.h - Maxim 8903 USB/Adapter Charger Driver - * - * Copyright (C) 2011 Samsung Electronics - * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. - * Based on max8903_charger.h - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __MAX8903_SABRESD_H__ -#define __MAX8903_SABRESD_H__ - -struct max8903_pdata { - /* - * GPIOs - * cen, chg, flt, and usus are optional. - * dok, dcm, and uok are not optional depending on the status of - * dc_valid and usb_valid. - */ - int cen; /* Charger Enable input */ - int dok; /* DC(Adapter) Power OK output */ - int uok; /* USB Power OK output */ - int chg; /* Charger status output */ - int flt; /* Fault output */ - int dcm; /* Current-Limit Mode input (1: DC, 2: USB) */ - int usus; /* USB Suspend Input (1: suspended) */ - int feature_flag;/* battery capacity feature(0:enable, 1:disable) */ - - /* - * DCM wired to Logic High Set this true when DCM pin connect to - * Logic high. - */ - bool dcm_always_high; - - /* - * DC(Adapter/TA) is wired - * When dc_valid is true, - * dok and dcm should be valid. - * - * At least one of dc_valid or usb_valid should be true. - */ - bool dc_valid; - /* - * USB is wired - * When usb_valid is true, - * uok should be valid. - */ - bool usb_valid; -}; - -#endif /* __SABRESD_BATTERY_H__ */ diff --git a/include/uapi/linux/isl29023.h b/include/uapi/linux/isl29023.h deleted file mode 100644 index 23ae0c56c202..000000000000 --- a/include/uapi/linux/isl29023.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * 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. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef __UAPI_LINUX_ISL29023_H__ -#define __UAPI_LINUX_ISL29023_H__ - -#include - -#define ISL29023_PD_MODE 0x0 -#define ISL29023_ALS_ONCE_MODE 0x1 -#define ISL29023_IR_ONCE_MODE 0x2 -#define ISL29023_ALS_CONT_MODE 0x5 -#define ISL29023_IR_CONT_MODE 0x6 - -#define ISL29023_INT_PERSISTS_1 0x0 -#define ISL29023_INT_PERSISTS_4 0x1 -#define ISL29023_INT_PERSISTS_8 0x2 -#define ISL29023_INT_PERSISTS_16 0x3 - -#define ISL29023_RES_16 0x0 -#define ISL29023_RES_12 0x1 -#define ISL29023_RES_8 0x2 -#define ISL29023_RES_4 0x3 - -#define ISL29023_RANGE_1K 0x0 -#define ISL29023_RANGE_4K 0x1 -#define ISL29023_RANGE_16K 0x2 -#define ISL29023_RANGE_64K 0x3 - -#endif diff --git a/include/uapi/linux/mxcfb.h b/include/uapi/linux/mxcfb.h new file mode 100644 index 000000000000..672696184897 --- /dev/null +++ b/include/uapi/linux/mxcfb.h @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved + */ + +/* + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * @file uapi/linux/mxcfb.h + * + * @brief Global header file for the MXC frame buffer + * + * @ingroup Framebuffer + */ +#ifndef __ASM_ARCH_MXCFB_H__ +#define __ASM_ARCH_MXCFB_H__ + +#include + +#define FB_SYNC_OE_LOW_ACT 0x80000000 +#define FB_SYNC_CLK_LAT_FALL 0x40000000 +#define FB_SYNC_DATA_INVERT 0x20000000 +#define FB_SYNC_CLK_IDLE_EN 0x10000000 +#define FB_SYNC_SHARP_MODE 0x08000000 +#define FB_SYNC_SWAP_RGB 0x04000000 +#define FB_ACCEL_TRIPLE_FLAG 0x00000000 +#define FB_ACCEL_DOUBLE_FLAG 0x00000001 + +struct mxcfb_gbl_alpha { + int enable; + int alpha; +}; + +struct mxcfb_loc_alpha { + int enable; + int alpha_in_pixel; + unsigned long alpha_phy_addr0; + unsigned long alpha_phy_addr1; +}; + +struct mxcfb_color_key { + int enable; + __u32 color_key; +}; + +struct mxcfb_pos { + __u16 x; + __u16 y; +}; + +struct mxcfb_gamma { + int enable; + int constk[16]; + int slopek[16]; +}; + +struct mxcfb_rect { + __u32 top; + __u32 left; + __u32 width; + __u32 height; +}; + +#define GRAYSCALE_8BIT 0x1 +#define GRAYSCALE_8BIT_INVERTED 0x2 +#define GRAYSCALE_4BIT 0x3 +#define GRAYSCALE_4BIT_INVERTED 0x4 + +#define AUTO_UPDATE_MODE_REGION_MODE 0 +#define AUTO_UPDATE_MODE_AUTOMATIC_MODE 1 + +#define UPDATE_SCHEME_SNAPSHOT 0 +#define UPDATE_SCHEME_QUEUE 1 +#define UPDATE_SCHEME_QUEUE_AND_MERGE 2 + +#define UPDATE_MODE_PARTIAL 0x0 +#define UPDATE_MODE_FULL 0x1 + +#define WAVEFORM_MODE_AUTO 257 + +#define TEMP_USE_AMBIENT 0x1000 + +#define EPDC_FLAG_ENABLE_INVERSION 0x01 +#define EPDC_FLAG_FORCE_MONOCHROME 0x02 +#define EPDC_FLAG_USE_CMAP 0x04 +#define EPDC_FLAG_USE_ALT_BUFFER 0x100 +#define EPDC_FLAG_TEST_COLLISION 0x200 +#define EPDC_FLAG_GROUP_UPDATE 0x400 +#define EPDC_FLAG_USE_DITHERING_Y1 0x2000 +#define EPDC_FLAG_USE_DITHERING_Y4 0x4000 + +#define FB_POWERDOWN_DISABLE -1 + +struct mxcfb_alt_buffer_data { + __u32 phys_addr; + __u32 width; /* width of entire buffer */ + __u32 height; /* height of entire buffer */ + struct mxcfb_rect alt_update_region; /* region within buffer to update */ +}; + +struct mxcfb_update_data { + struct mxcfb_rect update_region; + __u32 waveform_mode; + __u32 update_mode; + __u32 update_marker; + int temp; + unsigned int flags; + struct mxcfb_alt_buffer_data alt_buffer_data; +}; + +struct mxcfb_update_marker_data { + __u32 update_marker; + __u32 collision_test; +}; + +/* + * Structure used to define waveform modes for driver + * Needed for driver to perform auto-waveform selection + */ +struct mxcfb_waveform_modes { + int mode_init; + int mode_du; + int mode_gc4; + int mode_gc8; + int mode_gc16; + int mode_gc32; +}; + +/* + * Structure used to define a 5*3 matrix of parameters for + * setting IPU DP CSC module related to this framebuffer. + */ +struct mxcfb_csc_matrix { + int param[5][3]; +}; + +#define MXCFB_WAIT_FOR_VSYNC _IOW('F', 0x20, u_int32_t) +#define MXCFB_SET_GBL_ALPHA _IOW('F', 0x21, struct mxcfb_gbl_alpha) +#define MXCFB_SET_CLR_KEY _IOW('F', 0x22, struct mxcfb_color_key) +#define MXCFB_SET_OVERLAY_POS _IOWR('F', 0x24, struct mxcfb_pos) +#define MXCFB_GET_FB_IPU_CHAN _IOR('F', 0x25, u_int32_t) +#define MXCFB_SET_LOC_ALPHA _IOWR('F', 0x26, struct mxcfb_loc_alpha) +#define MXCFB_SET_LOC_ALP_BUF _IOW('F', 0x27, unsigned long) +#define MXCFB_SET_GAMMA _IOW('F', 0x28, struct mxcfb_gamma) +#define MXCFB_GET_FB_IPU_DI _IOR('F', 0x29, u_int32_t) +#define MXCFB_GET_DIFMT _IOR('F', 0x2A, u_int32_t) +#define MXCFB_GET_FB_BLANK _IOR('F', 0x2B, u_int32_t) +#define MXCFB_SET_DIFMT _IOW('F', 0x2C, u_int32_t) +#define MXCFB_CSC_UPDATE _IOW('F', 0x2D, struct mxcfb_csc_matrix) + +/* IOCTLs for E-ink panel updates */ +#define MXCFB_SET_WAVEFORM_MODES _IOW('F', 0x2B, struct mxcfb_waveform_modes) +#define MXCFB_SET_TEMPERATURE _IOW('F', 0x2C, int32_t) +#define MXCFB_SET_AUTO_UPDATE_MODE _IOW('F', 0x2D, __u32) +#define MXCFB_SEND_UPDATE _IOW('F', 0x2E, struct mxcfb_update_data) +#define MXCFB_WAIT_FOR_UPDATE_COMPLETE _IOWR('F', 0x2F, struct mxcfb_update_marker_data) +#define MXCFB_SET_PWRDOWN_DELAY _IOW('F', 0x30, int32_t) +#define MXCFB_GET_PWRDOWN_DELAY _IOR('F', 0x31, int32_t) +#define MXCFB_SET_UPDATE_SCHEME _IOW('F', 0x32, __u32) +#define MXCFB_GET_WORK_BUFFER _IOWR('F', 0x34, unsigned long) +#endif diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index daa77e6b5997..37933629cbed 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -218,18 +218,6 @@ config SND_SOC_EUKREA_TLV320 Enable I2S based access to the TLV320AIC23B codec attached to the SSI interface -config SND_SOC_IMX_CS42888 - tristate "SoC Audio support for i.MX boards with cs42888" - depends on OF && I2C - select SND_SOC_CS42888 - select SND_SOC_IMX_PCM_DMA - select SND_SOC_FSL_ESAI - select SND_SOC_FSL_UTILS - help - SoC Audio support for i.MX boards with cs42888 - Say Y if you want to add support for SoC audio on an i.MX board with - a cs42888 codec. - config SND_SOC_IMX_WM8962 tristate "SoC Audio support for i.MX boards with wm8962" depends on OF && I2C && INPUT @@ -269,29 +257,6 @@ config SND_SOC_IMX_MC13783 select SND_SOC_MC13783 select SND_SOC_IMX_PCM_DMA -config SND_SOC_IMX_HDMI - tristate "SoC Audio support for i.MX boards with HDMI port" - depends on MFD_MXC_HDMI - select SND_SOC_IMX_HDMI_DMA - select SND_SOC_FSL_HDMI - select SND_SOC_OMAP_HDMI_CODEC - help - SoC Audio support for i.MX boards with HDMI audio - Say Y if you want to add support for SoC audio on an i.MX board with - IMX HDMI. - -config SND_SOC_IMX_SI476X - tristate "SoC Audio support for i.MX boards with si476x" - select SND_SOC_IMX_PCM_DMA - select SND_SOC_IMX_AUDMUX - select SND_SOC_FSL_SSI - select SND_SOC_FSL_UTILS - select SND_SOC_SI476X - help - SoC Audio support for i.MX boards with SI476x - Say Y if you want to add support for Soc audio for the AMFM Tuner chip - SI476x module. - endif # SND_IMX_SOC endmenu diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 44ec6ef7f961..db254e358c18 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -48,22 +48,16 @@ snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o snd-soc-phycore-ac97-objs := phycore-ac97.o snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o snd-soc-wm1133-ev1-objs := wm1133-ev1.o -snd-soc-imx-cs42888-objs := imx-cs42888.o snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o snd-soc-imx-wm8962-objs := imx-wm8962.o snd-soc-imx-spdif-objs := imx-spdif.o snd-soc-imx-mc13783-objs := imx-mc13783.o -snd-soc-imx-hdmi-objs := imx-hdmi.o -snd-soc-imx-si476x-objs := imx-si476x.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o -obj-$(CONFIG_SND_SOC_IMX_CS42888) += snd-soc-imx-cs42888.o obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o -obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o -obj-$(CONFIG_SND_SOC_IMX_SI476X) += snd-soc-imx-si476x.o diff --git a/sound/soc/fsl/imx-cs42888.c b/sound/soc/fsl/imx-cs42888.c deleted file mode 100644 index e723e6a17ac0..000000000000 --- a/sound/soc/fsl/imx-cs42888.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fsl_esai.h" -#include "fsl_asrc.h" - -#define CODEC_CLK_EXTER_OSC 1 -#define CODEC_CLK_ESAI_HCKT 2 - -struct imx_priv { - int hw; - int fe_output_rate; - int fe_output_width; - unsigned int mclk_freq; - unsigned int codec_mclk; - struct platform_device *pdev; -}; - -static struct imx_priv card_priv; - -static int imx_cs42888_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct imx_priv *priv = &card_priv; - - if (!cpu_dai->active) - priv->hw = 0; - return 0; -} - -static void imx_cs42888_shutdown(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct imx_priv *priv = &card_priv; - - if (!cpu_dai->active) - priv->hw = 0; -} - -static const struct { - int rate; - int ratio1; - int ratio2; -} sr_vals[] = { - { 32000, 5, 3 }, - { 48000, 5, 3 }, - { 64000, 2, 1 }, - { 96000, 2, 1 }, - { 128000, 2, 1 }, - { 44100, 5, 3 }, - { 88200, 2, 1 }, - { 176400, 0, 0 }, - { 192000, 0, 0 }, -}; - -static int imx_cs42888_surround_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - 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 imx_priv *priv = &card_priv; - unsigned int rate = params_rate(params); - unsigned int lrclk_ratio = 0, i; - u32 dai_format = 0; - - if (priv->hw) - return 0; - - priv->hw = 1; - - if (priv->codec_mclk & CODEC_CLK_ESAI_HCKT) { - for (i = 0; i < ARRAY_SIZE(sr_vals); i++) { - if (sr_vals[i].rate == rate) { - lrclk_ratio = sr_vals[i].ratio1; - break; - } - } - if (i == ARRAY_SIZE(sr_vals)) { - dev_err(&priv->pdev->dev, "Unsupported rate %dHz\n", rate); - return -EINVAL; - } - - dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS; - - /* set the ESAI system clock as output */ - snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL_DIV, - priv->mclk_freq, SND_SOC_CLOCK_OUT); - snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 2); - snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 2); - /* set codec Master clock */ - snd_soc_dai_set_sysclk(codec_dai, 0, priv->mclk_freq,\ - SND_SOC_CLOCK_IN); - } else if (priv->codec_mclk & CODEC_CLK_EXTER_OSC) { - for (i = 0; i < ARRAY_SIZE(sr_vals); i++) { - if (sr_vals[i].rate == rate) { - lrclk_ratio = sr_vals[i].ratio2; - break; - } - } - if (i == ARRAY_SIZE(sr_vals)) { - dev_err(&priv->pdev->dev, "Unsupported rate %dHz\n", rate); - return -EINVAL; - } - - dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS; - - snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL, - priv->mclk_freq, SND_SOC_CLOCK_OUT); - snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 0); - snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 0); - snd_soc_dai_set_sysclk(codec_dai, 0, priv->mclk_freq,\ - SND_SOC_CLOCK_IN); - } - - /* set cpu DAI configuration */ - snd_soc_dai_set_fmt(cpu_dai, dai_format); - /* set i.MX active slot mask */ - snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); - /* set the ratio */ - snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PSR, 1); - snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_FP, lrclk_ratio); - snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PSR, 1); - snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_FP, lrclk_ratio); - - /* set codec DAI configuration */ - snd_soc_dai_set_fmt(codec_dai, dai_format); - return 0; -} - -static struct snd_soc_ops imx_cs42888_surround_ops = { - .startup = imx_cs42888_startup, - .shutdown = imx_cs42888_shutdown, - .hw_params = imx_cs42888_surround_hw_params, -}; - -static const struct snd_soc_dapm_widget imx_cs42888_dapm_widgets[] = { - SND_SOC_DAPM_LINE("Line Out Jack", NULL), - SND_SOC_DAPM_LINE("Line In Jack", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* Line out jack */ - {"Line Out Jack", NULL, "AOUT1L"}, - {"Line Out Jack", NULL, "AOUT1R"}, - {"Line Out Jack", NULL, "AOUT2L"}, - {"Line Out Jack", NULL, "AOUT2R"}, - {"Line Out Jack", NULL, "AOUT3L"}, - {"Line Out Jack", NULL, "AOUT3R"}, - {"Line Out Jack", NULL, "AOUT4L"}, - {"Line Out Jack", NULL, "AOUT4R"}, - {"AIN1L", NULL, "Line In Jack"}, - {"AIN1R", NULL, "Line In Jack"}, - {"AIN2L", NULL, "Line In Jack"}, - {"AIN2R", NULL, "Line In Jack"}, - {"esai-Playback", NULL, "asrc-Playback"}, - {"codec-Playback", NULL, "esai-Playback"},/*Playback is the codec dai*/ -}; - -static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) { - - struct imx_priv *priv = &card_priv; - - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min = priv->fe_output_rate; - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max = priv->fe_output_rate; - snd_mask_none(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT)); - if (priv->fe_output_width == 16) - snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), - SNDRV_PCM_FORMAT_S16_LE); - else - snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), - SNDRV_PCM_FORMAT_S24_LE); - return 0; -} - -static struct snd_soc_dai_link imx_cs42888_dai[] = { - { - .name = "HiFi", - .stream_name = "HiFi", - .codec_dai_name = "CS42888", - .ops = &imx_cs42888_surround_ops, - }, - { - .name = "HiFi-ASRC-FE", - .stream_name = "HiFi-ASRC-FE", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", - .dynamic = 1, - }, - { - .name = "HiFi-ASRC-BE", - .stream_name = "HiFi-ASRC-BE", - .codec_dai_name = "CS42888", - .platform_name = "snd-soc-dummy", - .no_pcm = 1, - .ops = &imx_cs42888_surround_ops, - .be_hw_params_fixup = be_hw_params_fixup, - }, -}; - -static struct snd_soc_card snd_soc_card_imx_cs42888 = { - .name = "cs42888-audio", - .dai_link = imx_cs42888_dai, - .dapm_widgets = imx_cs42888_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(imx_cs42888_dapm_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map), -}; - -/* - * This function will register the snd_soc_pcm_link drivers. - */ -static int imx_cs42888_probe(struct platform_device *pdev) -{ - struct device_node *esai_np, *codec_np; - struct device_node *asrc_np; - struct platform_device *esai_pdev; - struct platform_device *asrc_pdev = NULL; - struct i2c_client *codec_dev; - struct imx_priv *priv = &card_priv; - struct clk *codec_clk = NULL; - const char *mclk_name; - int ret; - - priv->pdev = pdev; - - esai_np = of_parse_phandle(pdev->dev.of_node, "esai-controller", 0); - codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0); - if (!esai_np || !codec_np) { - dev_err(&pdev->dev, "phandle missing or invalid\n"); - ret = -EINVAL; - goto fail; - } - - asrc_np = of_parse_phandle(pdev->dev.of_node, "asrc-controller", 0); - if (asrc_np) { - asrc_pdev = of_find_device_by_node(asrc_np); - if (asrc_pdev) { - struct fsl_asrc_p2p *asrc_p2p; - asrc_p2p = platform_get_drvdata(asrc_pdev); - asrc_p2p->per_dev = ESAI; - priv->fe_output_rate = asrc_p2p->output_rate; - priv->fe_output_width = asrc_p2p->output_width; - } - } - - esai_pdev = of_find_device_by_node(esai_np); - if (!esai_pdev) { - dev_err(&pdev->dev, "failed to find ESAI platform device\n"); - ret = -EINVAL; - goto fail; - } - codec_dev = of_find_i2c_device_by_node(codec_np); - if (!codec_dev) { - dev_err(&pdev->dev, "failed to find codec platform device\n"); - ret = -EINVAL; - goto fail; - } - - /*if there is no asrc controller, we only enable one device*/ - if (!asrc_pdev) { - imx_cs42888_dai[0].codec_of_node = codec_np; - imx_cs42888_dai[0].cpu_dai_name = dev_name(&esai_pdev->dev); - imx_cs42888_dai[0].platform_of_node = esai_np; - snd_soc_card_imx_cs42888.num_links = 1; - } else { - imx_cs42888_dai[0].codec_of_node = codec_np; - imx_cs42888_dai[0].cpu_dai_name = dev_name(&esai_pdev->dev); - imx_cs42888_dai[0].platform_of_node = esai_np; - imx_cs42888_dai[1].cpu_dai_name = dev_name(&asrc_pdev->dev); - imx_cs42888_dai[1].platform_name = "imx-pcm-asrc"; - imx_cs42888_dai[2].codec_of_node = codec_np; - imx_cs42888_dai[2].cpu_dai_name = dev_name(&esai_pdev->dev); - snd_soc_card_imx_cs42888.num_links = 3; - } - - codec_clk = devm_clk_get(&codec_dev->dev, NULL); - if (IS_ERR(codec_clk)) { - ret = PTR_ERR(codec_clk); - dev_err(&codec_dev->dev, "failed to get codec clk: %d\n", ret); - goto fail; - } - priv->mclk_freq = clk_get_rate(codec_clk); - - ret = of_property_read_string(codec_np, "clock-names", &mclk_name); - if (ret) { - dev_err(&pdev->dev, "%s: failed to get mclk source\n", __func__); - goto fail; - } - if (!strcmp(mclk_name, "codec_osc")) - priv->codec_mclk = CODEC_CLK_EXTER_OSC; - else if (!strcmp(mclk_name, "esai")) - priv->codec_mclk = CODEC_CLK_ESAI_HCKT; - else { - dev_err(&pdev->dev, "mclk source is not correct %s\n", mclk_name); - goto fail; - } - - snd_soc_card_imx_cs42888.dev = &pdev->dev; - - ret = snd_soc_register_card(&snd_soc_card_imx_cs42888); - if (ret) - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); -fail: - if (esai_np) - of_node_put(esai_np); - if (codec_np) - of_node_put(codec_np); - return ret; -} - -static int imx_cs42888_remove(struct platform_device *pdev) -{ - snd_soc_unregister_card(&snd_soc_card_imx_cs42888); - return 0; -} - -static const struct of_device_id imx_cs42888_dt_ids[] = { - { .compatible = "fsl,imx-audio-cs42888", }, - { /* sentinel */ } -}; - -static struct platform_driver imx_cs42888_driver = { - .probe = imx_cs42888_probe, - .remove = imx_cs42888_remove, - .driver = { - .name = "imx-cs42888", - .owner = THIS_MODULE, - .of_match_table = imx_cs42888_dt_ids, - }, -}; -module_platform_driver(imx_cs42888_driver); - -MODULE_AUTHOR("Freescale Semiconductor, Inc."); -MODULE_DESCRIPTION("ALSA SoC cs42888 Machine Layer Driver"); -MODULE_ALIAS("platform:imx-cs42888"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c deleted file mode 100644 index 04fcff8cca6e..000000000000 --- a/sound/soc/fsl/imx-hdmi.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * ASoC HDMI Transmitter driver for IMX development boards - * - * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. - * - * based on stmp3780_devb_hdmi.c - * - * Vladimir Barinov - * - * Copyright 2008 SigmaTel, Inc - * Copyright 2008 Embedded Alley Solutions, Inc - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include -#include -#include -#include - -#include "imx-hdmi.h" - -/* imx digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link imx_hdmi_dai_link = { - .name = "i.MX HDMI Audio Tx", - .stream_name = "i.MX HDMI Audio Tx", - .codec_dai_name = "hdmi-hifi", - .codec_name = "hdmi-audio-codec", - .platform_name = "imx-hdmi-audio", -}; - -static struct snd_soc_card snd_soc_card_imx_hdmi = { - .name = "imx-hdmi-soc", - .dai_link = &imx_hdmi_dai_link, - .num_links = 1, -}; - -static struct platform_device *codec_dev; - -static int imx_hdmi_audio_probe(struct platform_device *pdev) -{ - struct device_node *hdmi_np, *np = pdev->dev.of_node; - struct snd_soc_card *card = &snd_soc_card_imx_hdmi; - struct platform_device *hdmi_pdev; - int ret = 0; - - if (!hdmi_get_registered()) { - dev_err(&pdev->dev, "initialize HDMI-audio failed. load HDMI-video first!\n"); - return -ENODEV; - } - - hdmi_np = of_parse_phandle(np, "hdmi-controller", 0); - if (!hdmi_np) { - dev_err(&pdev->dev, "failed to find hdmi-audio cpudai\n"); - ret = -EINVAL; - goto end; - } - - hdmi_pdev = of_find_device_by_node(hdmi_np); - if (!hdmi_pdev) { - dev_err(&pdev->dev, "failed to find SSI platform device\n"); - ret = -EINVAL; - goto end; - } - - codec_dev = platform_device_register_simple("hdmi-audio-codec", -1, NULL, 0); - if (IS_ERR(codec_dev)) { - dev_err(&pdev->dev, "failed to register HDMI audio codec\n"); - ret = PTR_ERR(codec_dev); - goto end; - } - - card->dev = &pdev->dev; - card->dai_link->cpu_dai_name = dev_name(&hdmi_pdev->dev); - - ret = snd_soc_register_card(card); - if (ret) { - dev_err(&pdev->dev, "failed to register card: %d\n", ret); - goto err_card; - } - - goto end; - -err_card: - platform_device_unregister(codec_dev); -end: - if (hdmi_np) - of_node_put(hdmi_np); - - return ret; -} - -static int imx_hdmi_audio_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_card_imx_hdmi; - - platform_device_unregister(codec_dev); - snd_soc_unregister_card(card); - - return 0; -} - -static const struct of_device_id imx_hdmi_dt_ids[] = { - { .compatible = "fsl,imx-audio-hdmi", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids); - -static struct platform_driver imx_hdmi_audio_driver = { - .probe = imx_hdmi_audio_probe, - .remove = imx_hdmi_audio_remove, - .driver = { - .of_match_table = imx_hdmi_dt_ids, - .name = "imx-audio-hdmi", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(imx_hdmi_audio_driver); - -MODULE_AUTHOR("Freescale Semiconductor, Inc."); -MODULE_DESCRIPTION("IMX HDMI TX ASoC driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-audio-hdmi"); diff --git a/sound/soc/fsl/imx-si476x.c b/sound/soc/fsl/imx-si476x.c deleted file mode 100644 index fbdc5877fe4d..000000000000 --- a/sound/soc/fsl/imx-si476x.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2008-2013 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include - -#include "imx-audmux.h" - -static int imx_audmux_config(int slave, int master) -{ - unsigned int ptcr, pdcr; - slave = slave - 1; - master = master - 1; - - ptcr = IMX_AUDMUX_V2_PTCR_SYN | - IMX_AUDMUX_V2_PTCR_TFSDIR | - IMX_AUDMUX_V2_PTCR_TFSEL(slave) | - IMX_AUDMUX_V2_PTCR_TCLKDIR | - IMX_AUDMUX_V2_PTCR_TCSEL(slave); - pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(slave); - imx_audmux_v2_configure_port(master, ptcr, pdcr); - - ptcr = IMX_AUDMUX_V2_PTCR_SYN; - pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(master); - imx_audmux_v2_configure_port(slave, ptcr, pdcr); - - return 0; -} - -static int imx_si476x_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - u32 channels = params_channels(params); - u32 rate = params_rate(params); - u32 bclk = rate * channels * 32; - int ret = 0; - - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S - | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - if (ret) { - dev_err(cpu_dai->dev, "failed to set dai fmt\n"); - return ret; - } - - ret = snd_soc_dai_set_tdm_slot(cpu_dai, - channels == 1 ? 0xfffffffe : 0xfffffffc, - channels == 1 ? 0xfffffffe : 0xfffffffc, - 2, 32); - if (ret) { - dev_err(cpu_dai->dev, "failed to set dai tdm slot\n"); - return ret; - } - - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, bclk, SND_SOC_CLOCK_OUT); - if (ret) - dev_err(cpu_dai->dev, "failed to set sysclk\n"); - - return ret; -} - -static struct snd_soc_ops imx_si476x_ops = { - .hw_params = imx_si476x_hw_params, -}; - -static struct snd_soc_dai_link imx_dai = { - .name = "imx-si476x", - .stream_name = "imx-si476x", - .codec_dai_name = "si476x-codec", - .codec_name = "si476x-codec.99", - .ops = &imx_si476x_ops, -}; - -static struct snd_soc_card snd_soc_card_imx_3stack = { - .name = "imx-audio-si476x", - .dai_link = &imx_dai, - .num_links = 1, -}; - -static int imx_si476x_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_card_imx_3stack; - struct device_node *ssi_np, *np = pdev->dev.of_node; - struct platform_device *ssi_pdev; - int int_port, ext_port, ret; - - ret = of_property_read_u32(np, "mux-int-port", &int_port); - if (ret) { - dev_err(&pdev->dev, "mux-int-port missing or invalid\n"); - return ret; - } - - ret = of_property_read_u32(np, "mux-ext-port", &ext_port); - if (ret) { - dev_err(&pdev->dev, "mux-ext-port missing or invalid\n"); - return ret; - } - - imx_audmux_config(int_port, ext_port); - - ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0); - if (!ssi_np) { - dev_err(&pdev->dev, "phandle missing or invalid\n"); - return -EINVAL; - } - - ssi_pdev = of_find_device_by_node(ssi_np); - if (!ssi_pdev) { - dev_err(&pdev->dev, "failed to find SSI platform device\n"); - ret = -EINVAL; - goto end; - } - - card->dev = &pdev->dev; - card->dai_link->cpu_dai_name = dev_name(&ssi_pdev->dev); - card->dai_link->platform_of_node = ssi_np; - - ret = snd_soc_register_card(card); - if (ret) - dev_err(&pdev->dev, "Failed to register card: %d\n", ret); - -end: - if (ssi_np) - of_node_put(ssi_np); - - return ret; -} - -static int imx_si476x_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_card_imx_3stack; - - snd_soc_unregister_card(card); - - return 0; -} - -static const struct of_device_id imx_si476x_dt_ids[] = { - { .compatible = "fsl,imx-audio-si476x", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, imx_si476x_dt_ids); - -static struct platform_driver imx_si476x_driver = { - .driver = { - .name = "imx-tuner-si476x", - .owner = THIS_MODULE, - .of_match_table = imx_si476x_dt_ids, - }, - .probe = imx_si476x_probe, - .remove = imx_si476x_remove, -}; - -module_platform_driver(imx_si476x_driver); - -/* Module information */ -MODULE_AUTHOR("Freescale Semiconductor, Inc."); -MODULE_DESCRIPTION("ALSA SoC i.MX si476x"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-tuner-si476x"); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ce14e37c11ea..54d18f22a33e 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1012,7 +1012,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, } } - dev_dbg(card->dev, "ASoC: can't get %s BE for %s\n", + dev_err(card->dev, "ASoC: can't get %s BE for %s\n", stream ? "capture" : "playback", widget->name); return NULL; } @@ -1120,7 +1120,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, /* is there a valid BE rtd for this widget */ be = dpcm_get_be(card, list->widgets[i], stream); if (!be) { - dev_dbg(fe->dev, "ASoC: no BE found for %s\n", + dev_err(fe->dev, "ASoC: no BE found for %s\n", list->widgets[i]->name); continue; } -- 2.39.2