diff options
23 files changed, 476 insertions, 94 deletions
diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt index 164cbb15f04c..adbd2ca0af2f 100644 --- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt @@ -18,6 +18,7 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt. Optional properties: - vdd-supply: Power supply for DAC +- de-active: data-enable pulse is active low/high/ignored Example ------- diff --git a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts index d5f7a1703aae..47191d154867 100644 --- a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts @@ -99,7 +99,6 @@ compatible = "fsl,imx-parallel-display"; #address-cells = <1>; #size-cells = <0>; - interface-pix-fmt = "bgr666"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ipu1_lcdif>; status = "okay"; @@ -121,13 +120,25 @@ }; }; - panel: panel { - /* - * edt,et057090dhu: EDT 5.7" LCD TFT - * edt,et070080dh6: EDT 7.0" LCD TFT - */ - compatible = "edt,et057090dhu"; + panel_dpi: panel-dpi { + compatible = "panel-dpi"; backlight = <&backlight>; + width-mm = <115>; + height-mm = <86>; + + data-mapping = "bgr666"; + + panel-timing { + clock-frequency = <25175000>; + hactive = <640>; + vactive = <480>; + hsync-len = <30>; + hfront-porch = <16>; + hback-porch = <114>; + vsync-len = <3>; + vfront-porch = <10>; + vback-porch = <32>; + }; port { lcd_panel_in: endpoint { @@ -228,10 +239,11 @@ &weim { status = "okay"; - /* weim memory map: 32MB on CS0, 32MB on CS1, 32MB on CS2 */ + /* weim memory map: 32MB on CS0, CS1, CS2 and CS3 */ ranges = <0 0 0x08000000 0x02000000 1 0 0x0a000000 0x02000000 - 2 0 0x0c000000 0x02000000>; + 2 0 0x0c000000 0x02000000 + 3 0 0x0e000000 0x02000000>; /* SRAM on Colibri nEXT_CS0 */ sram@0,0 { diff --git a/arch/arm/boot/dts/imx6q-apalis-eval.dts b/arch/arm/boot/dts/imx6q-apalis-eval.dts index 0edd3043d9c1..db6818c61e43 100644 --- a/arch/arm/boot/dts/imx6q-apalis-eval.dts +++ b/arch/arm/boot/dts/imx6q-apalis-eval.dts @@ -84,10 +84,9 @@ compatible = "fsl,imx-parallel-display"; #address-cells = <1>; #size-cells = <0>; - interface-pix-fmt = "rgb24"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ipu1_lcdif>; - status = "okay"; + status = "disabled"; port@0 { reg = <0>; @@ -106,14 +105,28 @@ }; }; - panel: panel { - /* - * edt,et057090dhu: EDT 5.7" LCD TFT - * edt,et070080dh6: EDT 7.0" LCD TFT - */ - compatible = "edt,et057090dhu"; + panel_dpi: panel-dpi { + compatible = "panel-dpi"; + backlight = <&backlight>; - power-supply = <®_3v3_sw>; + + width-mm = <115>; + height-mm = <86>; + + data-mapping = "rgb24"; + status = "disabled"; + + panel-timing { + clock-frequency = <25175000>; + hactive = <640>; + vactive = <480>; + hsync-len = <30>; + hfront-porch = <16>; + hback-porch = <114>; + vsync-len = <3>; + vfront-porch = <10>; + vback-porch = <32>; + }; port { lcd_panel_in: endpoint { @@ -122,6 +135,39 @@ }; }; + panel_lvds: panel-lvds { + compatible = "panel-lvds"; + + backlight = <&backlight>; + + width-mm = <218>; + height-mm = <137>; + + data-mapping = "vesa-24"; + status = "disabled"; + + panel-timing { + clock-frequency = <68930000>; + hactive = <1280>; + vactive = <800>; + hback-porch = <64>; + hfront-porch = <64>; + vback-porch = <5>; + vfront-porch = <5>; + hsync-len = <40>; + vsync-len = <6>; + hsync-active = <0>; + vsync-active = <0>; + pixelclk-active = <0>; + }; + + port { + lvds_panel_in: endpoint { + remote-endpoint = <&lvds_out>; + }; + }; + }; + reg_pcie_switch: regulator-pcie-switch { compatible = "regulator-fixed"; regulator-name = "pcie_switch"; @@ -140,6 +186,16 @@ regulator-max-microvolt = <3300000>; regulator-always-on; }; + + vga { + compatible = "vga-connector"; + + port { + vga_con_in: endpoint { + remote-endpoint = <&vga_bridge_out>; + }; + }; + }; }; &backlight { @@ -159,6 +215,13 @@ status = "okay"; }; +&clks { + assigned-clocks = <&clks IMX6QDL_CLK_IPU1_DI1_PRE_SEL>, + <&clks IMX6QDL_CLK_IPU2_DI0_PRE_SEL>; + assigned-clock-parents = <&clks IMX6QDL_CLK_PLL2_PFD2_396M>, + <&clks IMX6QDL_CLK_PLL2_PFD2_396M>; +}; + &hdmi { status = "okay"; }; @@ -192,7 +255,20 @@ }; &ldb { - status = "okay"; + status = "disabled"; + + lvds-channel@0 { + status = "okay"; + primary; + + port@4 { + reg = <4>; + + lvds_out: endpoint { + remote-endpoint = <&lvds_panel_in>; + }; + }; + }; }; &pcie { @@ -283,6 +359,24 @@ status = "okay"; }; +&vgabridge { + status = "okay"; + + ports { + port@1 { + reg = <1>; + + vga_bridge_out: endpoint { + remote-endpoint = <&vga_con_in>; + }; + }; + }; +}; + +&vgadisplay { + status = "okay"; +}; + &iomuxc { /* * Mux the Apalis GPIOs diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/imx6qdl-apalis.dtsi index 8380f1b26826..1cbd6e430e34 100644 --- a/arch/arm/boot/dts/imx6qdl-apalis.dtsi +++ b/arch/arm/boot/dts/imx6qdl-apalis.dtsi @@ -62,6 +62,18 @@ status = "disabled"; }; + /* DDC_I2C: I2C2_SDA/SCL on MXM3 205/207 */ + i2cddc: i2c@0 { + compatible = "i2c-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c_ddc>; + gpios = <&gpio3 16 GPIO_ACTIVE_HIGH /* sda */ + &gpio2 30 GPIO_ACTIVE_HIGH /* scl */ + >; + i2c-gpio,delay-us = <2>; /* ~100 kHz */ + status = "disabled"; + }; + reg_module_3v3: regulator-module-3v3 { compatible = "regulator-fixed"; regulator-name = "+V3.3"; @@ -139,6 +151,54 @@ spdif-out; status = "disabled"; }; + + vgabridge: bridge { + compatible = "dumb-vga-dac"; + #address-cells = <1>; + #size-cells = <0>; + de-active = <0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + vga_bridge_in: endpoint { + remote-endpoint = <&vga_display_out>; + }; + }; + }; + }; + + vgadisplay: display@di0 { + compatible = "fsl,imx-parallel-display"; + #address-cells = <1>; + #size-cells = <0>; + interface-pix-fmt = "rgb565"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu2_vdac>; + status = "disabled"; + + port@0 { + reg = <0>; + + vga_display_in: endpoint { + remote-endpoint = <&ipu2_di0_disp0>; + }; + }; + + port@1 { + reg = <1>; + + vga_display_out: endpoint { + remote-endpoint = <&vga_bridge_in>; + }; + }; + }; + }; &audmux { @@ -369,11 +429,15 @@ pinctrl-names = "default", "recovery"; pinctrl-0 = <&pinctrl_i2c3>; pinctrl-1 = <&pinctrl_i2c3_recovery>; - scl-gpios = <&gpio3 17 GPIO_ACTIVE_HIGH>; - sda-gpios = <&gpio3 18 GPIO_ACTIVE_HIGH>; + scl-gpios = <&gpio3 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio3 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "disabled"; }; +&ipu2_di0_disp0 { + remote-endpoint = <&vga_display_in>; +}; + &pwm1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pwm1>; @@ -633,6 +697,14 @@ >; }; + pinctrl_i2c_ddc: gpioi2cddcgrp { + fsl,pins = < + /* DDC bitbang */ + MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x1b0b0 + MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x1b0b0 + >; + }; + pinctrl_i2c1: i2c1grp { fsl,pins = < MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1 diff --git a/arch/arm/boot/dts/imx6qdl-colibri.dtsi b/arch/arm/boot/dts/imx6qdl-colibri.dtsi index 87e15e7cb32b..8a27c2a05678 100644 --- a/arch/arm/boot/dts/imx6qdl-colibri.dtsi +++ b/arch/arm/boot/dts/imx6qdl-colibri.dtsi @@ -298,8 +298,8 @@ pinctrl-names = "default", "recovery"; pinctrl-0 = <&pinctrl_i2c3>; pinctrl-1 = <&pinctrl_i2c3_recovery>; - scl-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; - sda-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; + scl-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index 62ed30c781ed..3282eed497ea 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -226,6 +226,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI1>, <&clks IMX6UL_CLK_ECSPI1>; clock-names = "ipg", "per"; + dmas = <&sdma 3 7 1>, <&sdma 4 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -238,6 +240,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI2>, <&clks IMX6UL_CLK_ECSPI2>; clock-names = "ipg", "per"; + dmas = <&sdma 5 7 1>, <&sdma 6 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -250,6 +254,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI3>, <&clks IMX6UL_CLK_ECSPI3>; clock-names = "ipg", "per"; + dmas = <&sdma 7 7 1>, <&sdma 8 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -262,6 +268,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI4>, <&clks IMX6UL_CLK_ECSPI4>; clock-names = "ipg", "per"; + dmas = <&sdma 9 7 1>, <&sdma 10 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx6ull-colibri.dtsi b/arch/arm/boot/dts/imx6ull-colibri.dtsi index 6c63a7384611..9ad1da159768 100644 --- a/arch/arm/boot/dts/imx6ull-colibri.dtsi +++ b/arch/arm/boot/dts/imx6ull-colibri.dtsi @@ -94,16 +94,16 @@ pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1>; pinctrl-1 = <&pinctrl_i2c1_gpio>; - sda-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>; - scl-gpios = <&gpio1 28 GPIO_ACTIVE_LOW>; + sda-gpios = <&gpio1 29 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio1 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; }; &i2c2 { pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c2>; pinctrl-1 = <&pinctrl_i2c2_gpio>; - sda-gpios = <&gpio1 31 GPIO_ACTIVE_LOW>; - scl-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>; + sda-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio1 30 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; ad7879@2c { diff --git a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi index 3f2746169181..b6a4cc387695 100644 --- a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi +++ b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi @@ -52,13 +52,30 @@ clock-frequency = <16000000>; }; - panel: panel { - compatible = "edt,et057090dhu"; + panel_dpi: panel-dpi { + compatible = "panel-dpi"; backlight = <&bl>; power-supply = <®_3v3>; + width-mm = <115>; + height-mm = <86>; + + data-mapping = "bgr666"; + + panel-timing { + clock-frequency = <25175000>; + hactive = <640>; + vactive = <480>; + hsync-len = <30>; + hfront-porch = <16>; + hback-porch = <114>; + vsync-len = <3>; + vfront-porch = <10>; + vback-porch = <32>; + }; + port { - panel_in: endpoint { + lcd_panel_in: endpoint { remote-endpoint = <&lcdif_out>; }; }; @@ -143,7 +160,7 @@ port { lcdif_out: endpoint { - remote-endpoint = <&panel_in>; + remote-endpoint = <&lcd_panel_in>; }; }; }; diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi index 895fbde4d433..37aeba999be3 100644 --- a/arch/arm/boot/dts/imx7-colibri.dtsi +++ b/arch/arm/boot/dts/imx7-colibri.dtsi @@ -319,10 +319,10 @@ assigned-clock-rates = <400000000>; bus-width = <8>; fsl,tuning-step = <2>; - max-frequency = <100000000>; vmmc-supply = <®_module_3v3>; vqmmc-supply = <®_DCDC3>; non-removable; + sdhci-caps-mask = <0x80000000 0x0>; }; &iomuxc { diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index e88f53a4c7f4..81fe18c0b7da 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -649,6 +649,8 @@ clocks = <&clks IMX7D_ECSPI4_ROOT_CLK>, <&clks IMX7D_ECSPI4_ROOT_CLK>; clock-names = "ipg", "per"; + dmas = <&sdma 6 7 1>, <&sdma 7 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -730,6 +732,8 @@ clocks = <&clks IMX7D_ECSPI1_ROOT_CLK>, <&clks IMX7D_ECSPI1_ROOT_CLK>; clock-names = "ipg", "per"; + dmas = <&sdma 0 7 1>, <&sdma 1 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -742,6 +746,8 @@ clocks = <&clks IMX7D_ECSPI2_ROOT_CLK>, <&clks IMX7D_ECSPI2_ROOT_CLK>; clock-names = "ipg", "per"; + dmas = <&sdma 2 7 1>, <&sdma 3 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -754,6 +760,8 @@ clocks = <&clks IMX7D_ECSPI3_ROOT_CLK>, <&clks IMX7D_ECSPI3_ROOT_CLK>; clock-names = "ipg", "per"; + dmas = <&sdma 4 7 1>, <&sdma 5 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 8af2f7e91d13..b6c87d7d3a5d 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -31,7 +31,7 @@ obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o obj-$(CONFIG_SOC_IMX6UL) += cpuidle-imx6sx.o endif -ifdef CONFIG_SND_IMX_SOC +ifdef CONFIG_SND_SOC_IMX_PCM_FIQ obj-y += ssi-fiq.o obj-y += ssi-fiq-ksym.o endif diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c index 9b706789a341..2b8c3d629f2f 100644 --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c @@ -179,6 +179,7 @@ static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev) static int dumb_vga_probe(struct platform_device *pdev) { struct dumb_vga *vga; + u32 de; vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL); if (!vga) @@ -194,6 +195,23 @@ static int dumb_vga_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret); } + vga->bridge.funcs = &dumb_vga_bridge_funcs; + vga->bridge.of_node = pdev->dev.of_node; + vga->bridge.timings = of_device_get_match_data(&pdev->dev); + + if (!vga->bridge.timings && + !of_property_read_u32(pdev->dev.of_node, "de-active", &de)) { + struct drm_bridge_timings *timings; + + timings = devm_kzalloc(&pdev->dev, sizeof(*timings), GFP_KERNEL); + if (!timings) + return -ENOMEM; + + timings->bus_flags = de ? DRM_BUS_FLAG_DE_HIGH : + DRM_BUS_FLAG_DE_LOW; + vga->bridge.timings = timings; + } + vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev); if (IS_ERR(vga->ddc)) { if (PTR_ERR(vga->ddc) == -ENODEV) { @@ -205,10 +223,6 @@ static int dumb_vga_probe(struct platform_device *pdev) } } - vga->bridge.funcs = &dumb_vga_bridge_funcs; - vga->bridge.of_node = pdev->dev.of_node; - vga->bridge.timings = of_device_get_match_data(&pdev->dev); - drm_bridge_add(&vga->bridge); return 0; @@ -234,7 +248,7 @@ static int dumb_vga_remove(struct platform_device *pdev) */ static const struct drm_bridge_timings default_dac_timings = { /* Timing specifications, datasheet page 7 */ - .sampling_edge = DRM_BUS_FLAG_PIXDATA_POSEDGE, + .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE, .setup_time_ps = 500, .hold_time_ps = 1500, }; @@ -245,7 +259,7 @@ static const struct drm_bridge_timings default_dac_timings = { */ static const struct drm_bridge_timings ti_ths8134_dac_timings = { /* From timing diagram, datasheet page 9 */ - .sampling_edge = DRM_BUS_FLAG_PIXDATA_POSEDGE, + .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE, /* From datasheet, page 12 */ .setup_time_ps = 3000, /* I guess this means latched input */ @@ -258,7 +272,7 @@ static const struct drm_bridge_timings ti_ths8134_dac_timings = { */ static const struct drm_bridge_timings ti_ths8135_dac_timings = { /* From timing diagram, datasheet page 14 */ - .sampling_edge = DRM_BUS_FLAG_PIXDATA_POSEDGE, + .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE, /* From datasheet, page 16 */ .setup_time_ps = 2000, .hold_time_ps = 500, diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index f3ce51121dd6..ee30e2a4036d 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -231,6 +231,13 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) if (ret && ret != -ENODEV) return ret; + if (imxpd->bridge) { + const struct drm_bridge_timings *btimings = imxpd->bridge->timings; + + if (btimings) + imxpd->bus_flags = btimings->bus_flags; + } + imxpd->dev = dev; ret = imx_pd_register(drm, imxpd); diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c index 3f6550e6b6a4..4012a74d710e 100644 --- a/drivers/gpu/drm/panel/panel-lvds.c +++ b/drivers/gpu/drm/panel/panel-lvds.c @@ -24,6 +24,11 @@ #include <video/of_display_timing.h> #include <video/videomode.h> +enum panel_type { + PANEL_LVDS, + PANEL_DPI +}; + struct panel_lvds { struct drm_panel panel; struct device *dev; @@ -125,7 +130,9 @@ static int panel_lvds_get_modes(struct drm_panel *panel) connector->display_info.height_mm = lvds->height; drm_display_info_set_bus_formats(&connector->display_info, &lvds->bus_format, 1); - connector->display_info.bus_flags = lvds->data_mirror + drm_bus_flags_from_videomode(&lvds->video_mode, + &connector->display_info.bus_flags); + connector->display_info.bus_flags |= lvds->data_mirror ? DRM_BUS_FLAG_DATA_LSB_TO_MSB : DRM_BUS_FLAG_DATA_MSB_TO_LSB; @@ -146,6 +153,7 @@ static int panel_lvds_parse_dt(struct panel_lvds *lvds) struct display_timing timing; const char *mapping; int ret; + enum panel_type type; ret = of_get_display_timing(np, "panel-timing", &timing); if (ret < 0) @@ -175,13 +183,30 @@ static int panel_lvds_parse_dt(struct panel_lvds *lvds) return -ENODEV; } - if (!strcmp(mapping, "jeida-18")) { - lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG; - } else if (!strcmp(mapping, "jeida-24")) { - lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA; - } else if (!strcmp(mapping, "vesa-24")) { - lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG; - } else { + type = (enum panel_type)of_device_get_match_data(lvds->dev); + switch (type) { + case PANEL_LVDS: + if (!strcmp(mapping, "jeida-18")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG; + } else if (!strcmp(mapping, "jeida-24")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA; + } else if (!strcmp(mapping, "vesa-24")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG; + } + break; + case PANEL_DPI: + if (!strcmp(mapping, "rgb24")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X24; + } else if (!strcmp(mapping, "rgb565")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB565_1X16; + } else if (!strcmp(mapping, "bgr666")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X18; + } else if (!strcmp(mapping, "lvds666")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; + } + }; + + if (!lvds->bus_format) { dev_err(lvds->dev, "%pOF: invalid or missing %s DT property\n", np, "data-mapping"); return -EINVAL; @@ -289,7 +314,8 @@ static int panel_lvds_remove(struct platform_device *pdev) } static const struct of_device_id panel_lvds_of_table[] = { - { .compatible = "panel-lvds", }, + { .compatible = "panel-lvds", .data = (void *)PANEL_LVDS }, + { .compatible = "panel-dpi", .data = (void *)PANEL_DPI }, { /* Sentinel */ }, }; @@ -299,7 +325,7 @@ static struct platform_driver panel_lvds_driver = { .probe = panel_lvds_probe, .remove = panel_lvds_remove, .driver = { - .name = "panel-lvds", + .name = "panel-generic", .of_match_table = panel_lvds_of_table, }, }; diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c index e86217a6b9ca..ca759d9c0253 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_event.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c @@ -300,7 +300,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) mwifiex_11h_handle_radar_detected(priv, adapter->event_skb); break; case EVENT_BT_COEX_WLAN_PARA_CHANGE: - dev_err(adapter->dev, "EVENT: BT coex wlan param update\n"); + mwifiex_dbg(adapter, EVENT, "event: BT coex wlan param update\n"); mwifiex_bt_coex_wlan_param_update_event(priv, adapter->event_skb); break; diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index 0a7a470ee859..9bbe2816400a 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -26,7 +26,7 @@ config NVMEM_IMX_IIM config NVMEM_IMX_OCOTP tristate "i.MX6 On-Chip OTP Controller support" - depends on SOC_IMX6 || COMPILE_TEST + depends on SOC_IMX6 || SOC_IMX7D || COMPILE_TEST depends on HAS_IOMEM help This is a driver for the On-Chip OTP Controller (OCOTP) available on diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 80f843030e36..2f993a7239b4 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -29,6 +29,7 @@ #include <linux/reset.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h> +#include <asm/opcodes.h> #include "pcie-designware.h" @@ -41,6 +42,11 @@ enum imx6_pcie_variants { IMX7D, }; +struct imx6_pcie_drvdata { + enum imx6_pcie_variants variant; + int dbi_length; +}; + struct imx6_pcie { struct dw_pcie *pci; int reset_gpio; @@ -53,7 +59,6 @@ struct imx6_pcie { struct reset_control *pciephy_reset; struct reset_control *apps_reset; struct reset_control *turnoff_reset; - enum imx6_pcie_variants variant; u32 tx_deemph_gen1; u32 tx_deemph_gen2_3p5db; u32 tx_deemph_gen2_6db; @@ -66,6 +71,7 @@ struct imx6_pcie { struct device *pd_pcie; /* power domain for pcie phy */ struct device *pd_pcie_phy; + const struct imx6_pcie_drvdata *drvdata; }; /* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ @@ -269,8 +275,14 @@ static int imx6q_pcie_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { unsigned long pc = instruction_pointer(regs); - unsigned long instr = *(unsigned long *)pc; - int reg = (instr >> 12) & 15; + unsigned long instr; + int reg; + + if (user_mode(regs)) + return 1; + + instr = *(unsigned long *)pc; + reg = (instr >> 12) & 15; /* * If the instruction being executed was a read, @@ -338,11 +350,64 @@ static int imx6_pcie_attach_pd(struct device *dev) return 0; } +static int imx6q_pcie_abort_handler_thumb2(unsigned long addr, + unsigned int fsr, struct pt_regs *regs) +{ + unsigned long pc = instruction_pointer(regs); + unsigned long instr; + + if (user_mode(regs)) + return 1; + + instr = __mem_to_opcode_thumb32(*(unsigned long *)pc); + + if (__opcode_is_thumb32(instr)) { + /* Load word/byte and halfword immediate offset */ + if ((instr & 0xff100000UL) == 0xf8100000UL) { + int reg = (instr >> 12) & 0xf; + unsigned long val; + + if ((instr & 0x00700000UL) == 0x00100000UL) + val = 0xff; + else if ((instr & 0x00700000UL) == 0x00300000UL) + val = 0xffff; + else + val = 0xffffffffUL; + + regs->uregs[reg] = val; + regs->ARM_pc += 4; + return 0; + } + } else { + instr = __mem_to_opcode_thumb16(*(unsigned long *)pc); + + /* Load word/byte and halfword immediate offset */ + if (((instr & 0xe800) == 0x6800) || + ((instr & 0xf800) == 0x8800)) { + int reg = instr & 0x7; + unsigned long val; + + if (instr & 0x1000) + val = 0xff; + else if (instr & 0x8000) + val = 0xffff; + else + val = 0xffffffffUL; + + regs->uregs[reg] = val; + regs->ARM_pc += 2; + return 0; + } + } + + return 1; +} + static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) { struct device *dev = imx6_pcie->pci->dev; - switch (imx6_pcie->variant) { + switch (imx6_pcie->drvdata->variant) { case IMX7D: reset_control_assert(imx6_pcie->pciephy_reset); reset_control_assert(imx6_pcie->apps_reset); @@ -384,7 +449,7 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) struct device *dev = pci->dev; int ret = 0; - switch (imx6_pcie->variant) { + switch (imx6_pcie->drvdata->variant) { case IMX6SX: ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi); if (ret) { @@ -487,7 +552,7 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) !imx6_pcie->gpio_active_high); } - switch (imx6_pcie->variant) { + switch (imx6_pcie->drvdata->variant) { case IMX7D: reset_control_deassert(imx6_pcie->pciephy_reset); imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie); @@ -525,7 +590,7 @@ err_pcie_phy: static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) { - switch (imx6_pcie->variant) { + switch (imx6_pcie->drvdata->variant) { case IMX7D: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0); @@ -647,7 +712,7 @@ static void imx6_pcie_ltssm_enable(struct device *dev) { struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); - switch (imx6_pcie->variant) { + switch (imx6_pcie->drvdata->variant) { case IMX6Q: case IMX6SX: case IMX6QP: @@ -700,7 +765,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) tmp |= PORT_LOGIC_SPEED_CHANGE; dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); - if (imx6_pcie->variant != IMX7D) { + if (imx6_pcie->drvdata->variant != IMX7D) { /* * On i.MX7, DIRECT_SPEED_CHANGE behaves differently * from i.MX6 family when no link speed transition @@ -797,7 +862,7 @@ static void imx6_pcie_ltssm_disable(struct device *dev) { struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); - switch (imx6_pcie->variant) { + switch (imx6_pcie->drvdata->variant) { case IMX6SX: case IMX6QP: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, @@ -823,7 +888,7 @@ static void imx6_pcie_pm_turnoff(struct imx6_pcie *imx6_pcie) } /* Others poke directly at IOMUXC registers */ - switch (imx6_pcie->variant) { + switch (imx6_pcie->drvdata->variant) { case IMX6SX: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_PM_TURN_OFF, @@ -853,7 +918,7 @@ static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie) clk_disable_unprepare(imx6_pcie->pcie_phy); clk_disable_unprepare(imx6_pcie->pcie_bus); - switch (imx6_pcie->variant) { + switch (imx6_pcie->drvdata->variant) { case IMX6SX: clk_disable_unprepare(imx6_pcie->pcie_inbound_axi); break; @@ -869,8 +934,8 @@ static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie) static inline bool imx6_pcie_supports_suspend(struct imx6_pcie *imx6_pcie) { - return (imx6_pcie->variant == IMX7D || - imx6_pcie->variant == IMX6SX); + return (imx6_pcie->drvdata->variant == IMX7D || + imx6_pcie->drvdata->variant == IMX6SX); } static int imx6_pcie_suspend_noirq(struct device *dev) @@ -936,8 +1001,7 @@ static int imx6_pcie_probe(struct platform_device *pdev) pci->ops = &dw_pcie_ops; imx6_pcie->pci = pci; - imx6_pcie->variant = - (enum imx6_pcie_variants)of_device_get_match_data(dev); + imx6_pcie->drvdata = of_device_get_match_data(dev); dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); pci->dbi_base = devm_ioremap_resource(dev, dbi_base); @@ -981,7 +1045,7 @@ static int imx6_pcie_probe(struct platform_device *pdev) return PTR_ERR(imx6_pcie->pcie); } - switch (imx6_pcie->variant) { + switch (imx6_pcie->drvdata->variant) { case IMX6SX: imx6_pcie->pcie_inbound_axi = devm_clk_get(dev, "pcie_inbound_axi"); @@ -1087,11 +1151,27 @@ static void imx6_pcie_shutdown(struct platform_device *pdev) imx6_pcie_assert_core_reset(imx6_pcie); } +static const struct imx6_pcie_drvdata drvdata[] = { + [IMX6Q] = { + .variant = IMX6Q, + .dbi_length = 0x200, + }, + [IMX6SX] = { + .variant = IMX6SX, + }, + [IMX6QP] = { + .variant = IMX6QP, + }, + [IMX7D] = { + .variant = IMX7D, + }, +}; + static const struct of_device_id imx6_pcie_of_match[] = { - { .compatible = "fsl,imx6q-pcie", .data = (void *)IMX6Q, }, - { .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, }, - { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, }, - { .compatible = "fsl,imx7d-pcie", .data = (void *)IMX7D, }, + { .compatible = "fsl,imx6q-pcie", .data = &drvdata[IMX6Q], }, + { .compatible = "fsl,imx6sx-pcie", .data = &drvdata[IMX6SX], }, + { .compatible = "fsl,imx6qp-pcie", .data = &drvdata[IMX6QP], }, + { .compatible = "fsl,imx7d-pcie", .data = &drvdata[IMX7D], }, {}, }; @@ -1106,8 +1186,41 @@ static struct platform_driver imx6_pcie_driver = { .shutdown = imx6_pcie_shutdown, }; +static void imx6_pcie_quirk(struct pci_dev *dev) +{ + struct pci_bus *bus = dev->bus; + struct pcie_port *pp = bus->sysdata; + + /* Bus parent is the PCI bridge, its parent is this platform driver */ + if (!bus->dev.parent || !bus->dev.parent->parent) + return; + + /* Make sure we only quirk devices associated with this driver */ + if (bus->dev.parent->parent->driver != &imx6_pcie_driver.driver) + return; + + if (bus->number == pp->root_bus_nr) { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci); + + /* + * Limit config length to avoid the kernel reading beyond + * the register set and causing an abort on i.MX 6Quad + */ + if (imx6_pcie->drvdata->dbi_length) { + dev->cfg_size = imx6_pcie->drvdata->dbi_length; + dev_info(&dev->dev, "Limiting cfg_size to %d\n", + dev->cfg_size); + } + } +} +DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, + PCI_CLASS_BRIDGE_PCI, 8, imx6_pcie_quirk); + static int __init imx6_pcie_init(void) { + bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL); + /* * Since probe() can be deferred we need to make sure that * hook_fault_code is not called after __init memory is freed @@ -1115,7 +1228,8 @@ static int __init imx6_pcie_init(void) * we can install the handler here without risking it * accessing some uninitialized driver state. */ - hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0, + hook_fault_code(8, thumb2 ? imx6q_pcie_abort_handler_thumb2 : + imx6q_pcie_abort_handler, SIGBUS, 0, "external abort on non-linefetch"); return platform_driver_register(&imx6_pcie_driver); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index dff75dc94731..af650ac68948 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1962,7 +1962,7 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) * If the port was already initialised (eg, by a boot loader), * try to determine the current setup. */ -static void __init +static void imx_uart_console_get_options(struct imx_port *sport, int *baud, int *parity, int *bits) { @@ -2021,7 +2021,7 @@ imx_uart_console_get_options(struct imx_port *sport, int *baud, } } -static int __init +static int imx_uart_console_setup(struct console *co, char *options) { struct imx_port *sport; @@ -2081,7 +2081,7 @@ static struct console imx_uart_console = { .data = &imx_uart_uart_driver, }; -#define IMX_CONSOLE &imx_uart_console +#define IMX_CONSOLE (&imx_uart_console) #ifdef CONFIG_OF static void imx_uart_console_early_putchar(struct uart_port *port, int ch) @@ -2374,8 +2374,17 @@ static int imx_uart_probe(struct platform_device *pdev) static int imx_uart_remove(struct platform_device *pdev) { struct imx_port *sport = platform_get_drvdata(pdev); + int ret; + + ret = uart_remove_one_port(&imx_uart_uart_driver, &sport->port); - return uart_remove_one_port(&imx_uart_uart_driver, &sport->port); + if (IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE) && IMX_CONSOLE->index >= 0) { + clk_unprepare(sport->clk_ipg); + clk_unprepare(sport->clk_per); + IMX_CONSOLE->index = -1; + } + + return ret; } static void imx_uart_restore_context(struct imx_port *sport) diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index bd850747ce54..85d4b51eae19 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -244,14 +244,13 @@ struct drm_bridge_funcs { */ struct drm_bridge_timings { /** - * @sampling_edge: + * @bus_flags: * - * Tells whether the bridge samples the digital input signal - * from the display engine on the positive or negative edge of the - * clock, this should reuse the DRM_BUS_FLAG_PIXDATA_[POS|NEG]EDGE - * bitwise flags from the DRM connector (bit 2 and 3 valid). + * Tells what additional settings for the pixel data on the bus + * this bridge requires (like pixel signal polarity). See also + * &drm_display_info->bus_flags. */ - u32 sampling_edge; + u32 bus_flags; /** * @setup_time_ps: * diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 740b90df44bb..a26686e7281c 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1320,7 +1320,7 @@ static int fsl_spdif_probe(struct platform_device *pdev) } ret = imx_pcm_dma_init(pdev, IMX_SPDIF_DMABUF_SIZE); - if (ret) + if (ret && ret != -EPROBE_DEFER) dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret); return ret; diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 9b9a7ec52905..bf8597f57dce 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -104,15 +104,16 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) ssi_pdev = of_find_device_by_node(ssi_np); if (!ssi_pdev) { - dev_err(&pdev->dev, "failed to find SSI platform device\n"); + dev_dbg(&pdev->dev, "failed to find SSI platform device\n"); ret = -EPROBE_DEFER; goto fail; } put_device(&ssi_pdev->dev); codec_dev = of_find_i2c_device_by_node(codec_np); if (!codec_dev) { - dev_err(&pdev->dev, "failed to find codec platform device\n"); - return -EPROBE_DEFER; + dev_dbg(&pdev->dev, "failed to find codec platform device\n"); + ret = -EPROBE_DEFER; + goto fail; } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); @@ -157,7 +158,9 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(&pdev->dev, &data->card); if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); goto fail; } diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index fb896b2c9ba3..797d66e43d49 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -67,10 +67,8 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) goto end; ret = devm_snd_soc_register_card(&pdev->dev, &data->card); - if (ret) { + if (ret && ret != -EPROBE_DEFER) dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret); - goto end; - } end: of_node_put(spdif_np); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 416c371fa01a..3df147535202 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -908,8 +908,8 @@ static int soc_bind_dai_link(struct snd_soc_card *card, for (i = 0; i < rtd->num_codecs; i++) { codec_dais[i] = snd_soc_find_dai(&codecs[i]); if (!codec_dais[i]) { - dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", - codecs[i].dai_name); + dev_info(card->dev, "ASoC: CODEC DAI %s not registered\n", + codecs[i].dai_name); goto _err_defer; } snd_soc_rtdcom_add(rtd, codec_dais[i]->component); |