aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-02-22 20:12:52 -0500
committerDave Airlie <airlied@redhat.com>2018-02-22 20:12:52 -0500
commit727edc744098e2a3d2f9f9ce53edb49cb7817ea1 (patch)
tree0e489963c3f68c6e7615296056ff2402de41e2de
parente53a2079f46aadb4c3d86ba2528e2b5b7eae49dc (diff)
parent2b91e3c43b4f3d3cd4d84a31cfbe6b165d89b70e (diff)
Merge tag 'drm-misc-next-2018-02-21' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 4.17: Cross-subsystem Changes: - Backlight helpers to enable/disable and find devices in dt (Meghana) Core Changes: - Documentation improvements (Chris/Daniel/Jani) - simple_kms_helper: Add mode_valid() support (Linus) - mm: Fix bug in interval_tree causing nodes to be out-of-order (Chris) Driver Changes: - tinydrm/panel: Use the new backlight helpers (Meghana) - rockchip: Support gem_prime_import_sg_table + some fixes (Various) - sun4i: Add A83T HDMI support using dw-hdmi (Jernej) Cc: Meghana Madhyastha <meghana.madhyastha@gmail.com> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Heiko Stuebner <heiko@sntech.de> Cc: Jernej Skrabec <jernej.skrabec@siol.net> * tag 'drm-misc-next-2018-02-21' of git://anongit.freedesktop.org/drm/drm-misc: (41 commits) drm/omapdrm: Use of_find_backlight helper drm/panel: Use of_find_backlight helper drm/omapdrm: Use backlight_enable/disable helpers drm/panel: Use backlight_enable/disable helpers drm/tinydrm: Call devres version of of_find_backlight drm/tinydrm: Replace tinydrm_of_find_backlight with of_find_backlight drm/tinydrm: Convert tinydrm_enable/disable_backlight to backlight_enable/disable drm: add documentation for tv connector state margins drm/doc: Use new substruct support drm/doc: Polish for drm_mode_parse_command_line_for_connector drm/docs: Document "scaling mode" property better drm/docs: Align layout of optional plane blending properties drm/docs: Discourage adding more to kms-properties.csv drm: simple_kms_helper: Add mode_valid() callback support drm/todo: Add idr_init_base todo drm: Use idr_init_base(1) when using id==0 for invalid drm: NULL pointer dereference [null-pointer-deref] (CWE 476) problem drm: NULL pointer dereference [null-pointer-deref] (CWE 476) problem dma-buf/sw_sync: Fix kerneldoc warnings drm: Fix kerneldoc warnings for drm_lease ...
-rw-r--r--Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt74
-rw-r--r--Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt61
-rw-r--r--Documentation/gpu/drm-kms.rst5
-rw-r--r--Documentation/gpu/kms-properties.csv1
-rw-r--r--Documentation/gpu/todo.rst10
-rw-r--r--drivers/dma-buf/sw_sync.c6
-rw-r--r--drivers/gpu/drm/bochs/bochs_mm.c2
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi.c83
-rw-r--r--drivers/gpu/drm/drm_blend.c18
-rw-r--r--drivers/gpu/drm/drm_connector.c32
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c8
-rw-r--r--drivers/gpu/drm/drm_edid.c2
-rw-r--r--drivers/gpu/drm/drm_gem.c4
-rw-r--r--drivers/gpu/drm/drm_lease.c16
-rw-r--r--drivers/gpu/drm/drm_modes.c4
-rw-r--r--drivers/gpu/drm/drm_simple_kms_helper.c15
-rw-r--r--drivers/gpu/drm/drm_syncobj.c2
-rw-r--r--drivers/gpu/drm/imx/dw_hdmi-imx.c13
-rw-r--r--drivers/gpu/drm/meson/meson_dw_hdmi.c22
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-dpi.c36
-rw-r--r--drivers/gpu/drm/panel/panel-innolux-p079zca.c30
-rw-r--r--drivers/gpu/drm/panel/panel-jdi-lt070me05000.c6
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c38
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c37
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c14
-rw-r--r--drivers/gpu/drm/rockchip/dw-mipi-dsi.c3
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c13
-rw-r--r--drivers/gpu/drm/rockchip/inno_hdmi.c3
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c1
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_gem.c125
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_gem.h5
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c5
-rw-r--r--drivers/gpu/drm/sun4i/Kconfig9
-rw-r--r--drivers/gpu/drm/sun4i/Makefile4
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c50
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.h1
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c196
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h44
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c270
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_mixer.c11
-rw-r--r--drivers/gpu/drm/tinydrm/Kconfig2
-rw-r--r--drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c95
-rw-r--r--drivers/gpu/drm/tinydrm/mi0283qt.c3
-rw-r--r--drivers/gpu/drm/tinydrm/mipi-dbi.c4
-rw-r--r--drivers/gpu/drm/tinydrm/st7735r.c3
-rw-r--r--drivers/video/backlight/backlight.c73
-rw-r--r--include/drm/bridge/dw_hdmi.h24
-rw-r--r--include/drm/drm_connector.h6
-rw-r--r--include/drm/drm_dp_helper.h30
-rw-r--r--include/drm/drm_simple_kms_helper.h14
-rw-r--r--include/drm/drm_vblank.h16
-rw-r--r--include/drm/tinydrm/tinydrm-helpers.h4
-rw-r--r--include/linux/backlight.h58
53 files changed, 1253 insertions, 358 deletions
diff --git a/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt
new file mode 100644
index 000000000000..8df7d2e393d6
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt
@@ -0,0 +1,74 @@
1Rockchip RK3399 specific extensions to the cdn Display Port
2================================
3
4Required properties:
5- compatible: must be "rockchip,rk3399-cdn-dp"
6
7- reg: physical base address of the controller and length
8
9- clocks: from common clock binding: handle to dp clock.
10
11- clock-names: from common clock binding:
12 Required elements: "core-clk" "pclk" "spdif" "grf"
13
14- resets : a list of phandle + reset specifier pairs
15- reset-names : string of reset names
16 Required elements: "apb", "core", "dptx", "spdif"
17- power-domains : power-domain property defined with a phandle
18 to respective power domain.
19- assigned-clocks: main clock, should be <&cru SCLK_DP_CORE>
20- assigned-clock-rates : the DP core clk frequency, shall be: 100000000
21
22- rockchip,grf: this soc should set GRF regs, so need get grf here.
23
24- ports: contain a port nodes with endpoint definitions as defined in
25 Documentation/devicetree/bindings/media/video-interfaces.txt.
26 contained 2 endpoints, connecting to the output of vop.
27
28- phys: from general PHY binding: the phandle for the PHY device.
29
30- extcon: extcon specifier for the Power Delivery
31
32- #sound-dai-cells = it must be 1 if your system is using 2 DAIs: I2S, SPDIF
33
34-------------------------------------------------------------------------------
35
36Example:
37 cdn_dp: dp@fec00000 {
38 compatible = "rockchip,rk3399-cdn-dp";
39 reg = <0x0 0xfec00000 0x0 0x100000>;
40 interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
41 clocks = <&cru SCLK_DP_CORE>, <&cru PCLK_DP_CTRL>,
42 <&cru SCLK_SPDIF_REC_DPTX>, <&cru PCLK_VIO_GRF>;
43 clock-names = "core-clk", "pclk", "spdif", "grf";
44 assigned-clocks = <&cru SCLK_DP_CORE>;
45 assigned-clock-rates = <100000000>;
46 power-domains = <&power RK3399_PD_HDCP>;
47 phys = <&tcphy0_dp>, <&tcphy1_dp>;
48 resets = <&cru SRST_DPTX_SPDIF_REC>;
49 reset-names = "spdif";
50 extcon = <&fusb0>, <&fusb1>;
51 rockchip,grf = <&grf>;
52 #address-cells = <1>;
53 #size-cells = <0>;
54 #sound-dai-cells = <1>;
55
56 ports {
57 #address-cells = <1>;
58 #size-cells = <0>;
59
60 dp_in: port {
61 #address-cells = <1>;
62 #size-cells = <0>;
63 dp_in_vopb: endpoint@0 {
64 reg = <0>;
65 remote-endpoint = <&vopb_out_dp>;
66 };
67
68 dp_in_vopl: endpoint@1 {
69 reg = <1>;
70 remote-endpoint = <&vopl_out_dp>;
71 };
72 };
73 };
74 };
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index cd626ee1147a..b995bfee734a 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -64,6 +64,52 @@ Required properties:
64 first port should be the input endpoint. The second should be the 64 first port should be the input endpoint. The second should be the
65 output, usually to an HDMI connector. 65 output, usually to an HDMI connector.
66 66
67DWC HDMI TX Encoder
68-------------------
69
70The HDMI transmitter is a Synopsys DesignWare HDMI 1.4 TX controller IP
71with Allwinner's own PHY IP. It supports audio and video outputs and CEC.
72
73These DT bindings follow the Synopsys DWC HDMI TX bindings defined in
74Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt with the
75following device-specific properties.
76
77Required properties:
78
79 - compatible: value must be one of:
80 * "allwinner,sun8i-a83t-dw-hdmi"
81 - reg: base address and size of memory-mapped region
82 - reg-io-width: See dw_hdmi.txt. Shall be 1.
83 - interrupts: HDMI interrupt number
84 - clocks: phandles to the clocks feeding the HDMI encoder
85 * iahb: the HDMI bus clock
86 * isfr: the HDMI register clock
87 * tmds: TMDS clock
88 - clock-names: the clock names mentioned above
89 - resets: phandle to the reset controller
90 - reset-names: must be "ctrl"
91 - phys: phandle to the DWC HDMI PHY
92 - phy-names: must be "phy"
93
94 - ports: A ports node with endpoint definitions as defined in
95 Documentation/devicetree/bindings/media/video-interfaces.txt. The
96 first port should be the input endpoint. The second should be the
97 output, usually to an HDMI connector.
98
99DWC HDMI PHY
100------------
101
102Required properties:
103 - compatible: value must be one of:
104 * allwinner,sun8i-a83t-hdmi-phy
105 - reg: base address and size of memory-mapped region
106 - clocks: phandles to the clocks feeding the HDMI PHY
107 * bus: the HDMI PHY interface clock
108 * mod: the HDMI PHY module clock
109 - clock-names: the clock names mentioned above
110 - resets: phandle to the reset controller driving the PHY
111 - reset-names: must be "phy"
112
67TV Encoder 113TV Encoder
68---------- 114----------
69 115
@@ -94,24 +140,26 @@ Required properties:
94 * allwinner,sun7i-a20-tcon 140 * allwinner,sun7i-a20-tcon
95 * allwinner,sun8i-a33-tcon 141 * allwinner,sun8i-a33-tcon
96 * allwinner,sun8i-a83t-tcon-lcd 142 * allwinner,sun8i-a83t-tcon-lcd
143 * allwinner,sun8i-a83t-tcon-tv
97 * allwinner,sun8i-v3s-tcon 144 * allwinner,sun8i-v3s-tcon
98 - reg: base address and size of memory-mapped region 145 - reg: base address and size of memory-mapped region
99 - interrupts: interrupt associated to this IP 146 - interrupts: interrupt associated to this IP
100 - clocks: phandles to the clocks feeding the TCON. Three are needed: 147 - clocks: phandles to the clocks feeding the TCON.
101 - 'ahb': the interface clocks 148 - 'ahb': the interface clocks
102 - 'tcon-ch0': The clock driving the TCON channel 0 149 - 'tcon-ch0': The clock driving the TCON channel 0, except for A83T TV TCON
103 - resets: phandles to the reset controllers driving the encoder 150 - resets: phandles to the reset controllers driving the encoder
104 - "lcd": the reset line for the TCON channel 0 151 - "lcd": the reset line for the TCON channel 0
105 152
106 - clock-names: the clock names mentioned above 153 - clock-names: the clock names mentioned above
107 - reset-names: the reset names mentioned above 154 - reset-names: the reset names mentioned above
108 - clock-output-names: Name of the pixel clock created 155 - clock-output-names: Name of the pixel clock created, if TCON supports
156 channel 0.
109 157
110- ports: A ports node with endpoint definitions as defined in 158- ports: A ports node with endpoint definitions as defined in
111 Documentation/devicetree/bindings/media/video-interfaces.txt. The 159 Documentation/devicetree/bindings/media/video-interfaces.txt. The
112 first port should be the input endpoint, the second one the output 160 first port should be the input endpoint, the second one the output
113 161
114 The output may have multiple endpoints. The TCON has two channels, 162 The output may have multiple endpoints. TCON can have 1 or 2 channels,
115 usually with the first channel being used for the panels interfaces 163 usually with the first channel being used for the panels interfaces
116 (RGB, LVDS, etc.), and the second being used for the outputs that 164 (RGB, LVDS, etc.), and the second being used for the outputs that
117 require another controller (TV Encoder, HDMI, etc.). The endpoints 165 require another controller (TV Encoder, HDMI, etc.). The endpoints
@@ -122,8 +170,8 @@ Required properties:
122On SoCs other than the A33 and V3s, there is one more clock required: 170On SoCs other than the A33 and V3s, there is one more clock required:
123 - 'tcon-ch1': The clock driving the TCON channel 1 171 - 'tcon-ch1': The clock driving the TCON channel 1
124 172
125On SoCs that support LVDS (all SoCs but the A13, H3, H5 and V3s), you 173When TCON support LVDS (all TCONs except TV TCON on A83T and those found
126need one more reset line: 174in A13, H3, H5 and V3s SoCs), you need one more reset line:
127 - 'lvds': The reset line driving the LVDS logic 175 - 'lvds': The reset line driving the LVDS logic
128 176
129And on the A23, A31, A31s and A33, you need one more clock line: 177And on the A23, A31, A31s and A33, you need one more clock line:
@@ -226,6 +274,7 @@ supported.
226Required properties: 274Required properties:
227 - compatible: value must be one of: 275 - compatible: value must be one of:
228 * allwinner,sun8i-a83t-de2-mixer-0 276 * allwinner,sun8i-a83t-de2-mixer-0
277 * allwinner,sun8i-a83t-de2-mixer-1
229 * allwinner,sun8i-v3s-de2-mixer 278 * allwinner,sun8i-v3s-de2-mixer
230 - reg: base address and size of the memory-mapped region. 279 - reg: base address and size of the memory-mapped region.
231 - clocks: phandles to the clocks feeding the mixer 280 - clocks: phandles to the clocks feeding the mixer
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 2dcf5b42015d..56a3780e39b8 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -547,8 +547,9 @@ Explicit Fencing Properties
547Existing KMS Properties 547Existing KMS Properties
548----------------------- 548-----------------------
549 549
550The following table gives description of drm properties exposed by 550The following table gives description of drm properties exposed by various
551various modules/drivers. 551modules/drivers. Because this table is very unwieldy, do not add any new
552properties here. Instead document them in a section above.
552 553
553.. csv-table:: 554.. csv-table::
554 :header-rows: 1 555 :header-rows: 1
diff --git a/Documentation/gpu/kms-properties.csv b/Documentation/gpu/kms-properties.csv
index 927b65e14219..6b28b014cb7d 100644
--- a/Documentation/gpu/kms-properties.csv
+++ b/Documentation/gpu/kms-properties.csv
@@ -1,5 +1,4 @@
1Owner Module/Drivers,Group,Property Name,Type,Property Values,Object attached,Description/Restrictions 1Owner Module/Drivers,Group,Property Name,Type,Property Values,Object attached,Description/Restrictions
2,,“scaling mode”,ENUM,"{ ""None"", ""Full"", ""Center"", ""Full aspect"" }",Connector,"Supported by: amdgpu, gma500, i915, nouveau and radeon."
3,DVI-I,“subconnector”,ENUM,"{ “Unknown”, “DVI-D”, “DVI-A” }",Connector,TBD 2,DVI-I,“subconnector”,ENUM,"{ “Unknown”, “DVI-D”, “DVI-A” }",Connector,TBD
4,,“select subconnector”,ENUM,"{ “Automatic”, “DVI-D”, “DVI-A” }",Connector,TBD 3,,“select subconnector”,ENUM,"{ “Automatic”, “DVI-D”, “DVI-A” }",Connector,TBD
5,TV,“subconnector”,ENUM,"{ ""Unknown"", ""Composite"", ""SVIDEO"", ""Component"", ""SCART"" }",Connector,TBD 4,TV,“subconnector”,ENUM,"{ ""Unknown"", ""Composite"", ""SVIDEO"", ""Component"", ""SCART"" }",Connector,TBD
diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 1e593370f64f..1a0a413eeced 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -212,6 +212,16 @@ probably use drm_fb_helper_fbdev_teardown().
212 212
213Contact: Maintainer of the driver you plan to convert 213Contact: Maintainer of the driver you plan to convert
214 214
215idr_init_base()
216---------------
217
218DRM core&drivers uses a lot of idr (integer lookup directories) for mapping
219userspace IDs to internal objects, and in most places ID=0 means NULL and hence
220is never used. Switching to idr_init_base() for these would make the idr more
221efficient.
222
223Contact: Daniel Vetter
224
215Core refactorings 225Core refactorings
216================= 226=================
217 227
diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index 7779bdbd18d1..3d78ca89a605 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -235,10 +235,10 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
235 235
236/** 236/**
237 * sync_pt_create() - creates a sync pt 237 * sync_pt_create() - creates a sync pt
238 * @parent: fence's parent sync_timeline 238 * @obj: parent sync_timeline
239 * @inc: value of the fence 239 * @value: value of the fence
240 * 240 *
241 * Creates a new sync_pt as a child of @parent. @size bytes will be 241 * Creates a new sync_pt (fence) as a child of @parent. @size bytes will be
242 * allocated allowing for implementation specific data to be kept after 242 * allocated allowing for implementation specific data to be kept after
243 * the generic sync_timeline struct. Returns the sync_pt object or 243 * the generic sync_timeline struct. Returns the sync_pt object or
244 * NULL in case of error. 244 * NULL in case of error.
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
index 704e879711e4..b1d5aee46316 100644
--- a/drivers/gpu/drm/bochs/bochs_mm.c
+++ b/drivers/gpu/drm/bochs/bochs_mm.c
@@ -194,7 +194,7 @@ static struct ttm_tt *bochs_ttm_tt_create(struct ttm_bo_device *bdev,
194 return tt; 194 return tt;
195} 195}
196 196
197struct ttm_bo_driver bochs_bo_driver = { 197static struct ttm_bo_driver bochs_bo_driver = {
198 .ttm_tt_create = bochs_ttm_tt_create, 198 .ttm_tt_create = bochs_ttm_tt_create,
199 .ttm_tt_populate = ttm_pool_populate, 199 .ttm_tt_populate = ttm_pool_populate,
200 .ttm_tt_unpopulate = ttm_pool_unpopulate, 200 .ttm_tt_unpopulate = ttm_pool_unpopulate,
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index a38db40ce990..f9802399cc0d 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1037,19 +1037,21 @@ static void dw_hdmi_phy_enable_svsret(struct dw_hdmi *hdmi, u8 enable)
1037 HDMI_PHY_CONF0_SVSRET_MASK); 1037 HDMI_PHY_CONF0_SVSRET_MASK);
1038} 1038}
1039 1039
1040static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable) 1040void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable)
1041{ 1041{
1042 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 1042 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
1043 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET, 1043 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET,
1044 HDMI_PHY_CONF0_GEN2_PDDQ_MASK); 1044 HDMI_PHY_CONF0_GEN2_PDDQ_MASK);
1045} 1045}
1046EXPORT_SYMBOL_GPL(dw_hdmi_phy_gen2_pddq);
1046 1047
1047static void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable) 1048void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable)
1048{ 1049{
1049 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 1050 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
1050 HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET, 1051 HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET,
1051 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK); 1052 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
1052} 1053}
1054EXPORT_SYMBOL_GPL(dw_hdmi_phy_gen2_txpwron);
1053 1055
1054static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable) 1056static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable)
1055{ 1057{
@@ -1065,6 +1067,22 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
1065 HDMI_PHY_CONF0_SELDIPIF_MASK); 1067 HDMI_PHY_CONF0_SELDIPIF_MASK);
1066} 1068}
1067 1069
1070void dw_hdmi_phy_reset(struct dw_hdmi *hdmi)
1071{
1072 /* PHY reset. The reset signal is active high on Gen2 PHYs. */
1073 hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ);
1074 hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ);
1075}
1076EXPORT_SYMBOL_GPL(dw_hdmi_phy_reset);
1077
1078void dw_hdmi_phy_i2c_set_addr(struct dw_hdmi *hdmi, u8 address)
1079{
1080 hdmi_phy_test_clear(hdmi, 1);
1081 hdmi_writeb(hdmi, address, HDMI_PHY_I2CM_SLAVE_ADDR);
1082 hdmi_phy_test_clear(hdmi, 0);
1083}
1084EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_set_addr);
1085
1068static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi) 1086static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi)
1069{ 1087{
1070 const struct dw_hdmi_phy_data *phy = hdmi->phy.data; 1088 const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
@@ -1203,16 +1221,11 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
1203 if (phy->has_svsret) 1221 if (phy->has_svsret)
1204 dw_hdmi_phy_enable_svsret(hdmi, 1); 1222 dw_hdmi_phy_enable_svsret(hdmi, 1);
1205 1223
1206 /* PHY reset. The reset signal is active high on Gen2 PHYs. */ 1224 dw_hdmi_phy_reset(hdmi);
1207 hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ);
1208 hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ);
1209 1225
1210 hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST); 1226 hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
1211 1227
1212 hdmi_phy_test_clear(hdmi, 1); 1228 dw_hdmi_phy_i2c_set_addr(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2);
1213 hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
1214 HDMI_PHY_I2CM_SLAVE_ADDR);
1215 hdmi_phy_test_clear(hdmi, 0);
1216 1229
1217 /* Write to the PHY as configured by the platform */ 1230 /* Write to the PHY as configured by the platform */
1218 if (pdata->configure_phy) 1231 if (pdata->configure_phy)
@@ -1251,15 +1264,16 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
1251 dw_hdmi_phy_power_off(hdmi); 1264 dw_hdmi_phy_power_off(hdmi);
1252} 1265}
1253 1266
1254static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, 1267enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
1255 void *data) 1268 void *data)
1256{ 1269{
1257 return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? 1270 return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
1258 connector_status_connected : connector_status_disconnected; 1271 connector_status_connected : connector_status_disconnected;
1259} 1272}
1273EXPORT_SYMBOL_GPL(dw_hdmi_phy_read_hpd);
1260 1274
1261static void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data, 1275void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data,
1262 bool force, bool disabled, bool rxsense) 1276 bool force, bool disabled, bool rxsense)
1263{ 1277{
1264 u8 old_mask = hdmi->phy_mask; 1278 u8 old_mask = hdmi->phy_mask;
1265 1279
@@ -1271,8 +1285,9 @@ static void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data,
1271 if (old_mask != hdmi->phy_mask) 1285 if (old_mask != hdmi->phy_mask)
1272 hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); 1286 hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
1273} 1287}
1288EXPORT_SYMBOL_GPL(dw_hdmi_phy_update_hpd);
1274 1289
1275static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data) 1290void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data)
1276{ 1291{
1277 /* 1292 /*
1278 * Configure the PHY RX SENSE and HPD interrupts polarities and clear 1293 * Configure the PHY RX SENSE and HPD interrupts polarities and clear
@@ -1291,6 +1306,7 @@ static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data)
1291 hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), 1306 hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
1292 HDMI_IH_MUTE_PHY_STAT0); 1307 HDMI_IH_MUTE_PHY_STAT0);
1293} 1308}
1309EXPORT_SYMBOL_GPL(dw_hdmi_phy_setup_hpd);
1294 1310
1295static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = { 1311static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
1296 .init = dw_hdmi_phy_init, 1312 .init = dw_hdmi_phy_init,
@@ -1634,9 +1650,10 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
1634 * then write one of the FC registers several times. 1650 * then write one of the FC registers several times.
1635 * 1651 *
1636 * The number of iterations matters and depends on the HDMI TX revision 1652 * The number of iterations matters and depends on the HDMI TX revision
1637 * (and possibly on the platform). So far only i.MX6Q (v1.30a) and 1653 * (and possibly on the platform). So far i.MX6Q (v1.30a), i.MX6DL
1638 * i.MX6DL (v1.31a) have been identified as needing the workaround, with 1654 * (v1.31a) and multiple Allwinner SoCs (v1.32a) have been identified
1639 * 4 and 1 iterations respectively. 1655 * as needing the workaround, with 4 iterations for v1.30a and 1
1656 * iteration for others.
1640 */ 1657 */
1641 1658
1642 switch (hdmi->version) { 1659 switch (hdmi->version) {
@@ -1644,6 +1661,7 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
1644 count = 4; 1661 count = 4;
1645 break; 1662 break;
1646 case 0x131a: 1663 case 0x131a:
1664 case 0x132a:
1647 count = 1; 1665 count = 1;
1648 break; 1666 break;
1649 default: 1667 default:
@@ -2525,8 +2543,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
2525 if (hdmi->i2c) 2543 if (hdmi->i2c)
2526 dw_hdmi_i2c_init(hdmi); 2544 dw_hdmi_i2c_init(hdmi);
2527 2545
2528 platform_set_drvdata(pdev, hdmi);
2529
2530 return hdmi; 2546 return hdmi;
2531 2547
2532err_iahb: 2548err_iahb:
@@ -2576,25 +2592,23 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
2576/* ----------------------------------------------------------------------------- 2592/* -----------------------------------------------------------------------------
2577 * Probe/remove API, used from platforms based on the DRM bridge API. 2593 * Probe/remove API, used from platforms based on the DRM bridge API.
2578 */ 2594 */
2579int dw_hdmi_probe(struct platform_device *pdev, 2595struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
2580 const struct dw_hdmi_plat_data *plat_data) 2596 const struct dw_hdmi_plat_data *plat_data)
2581{ 2597{
2582 struct dw_hdmi *hdmi; 2598 struct dw_hdmi *hdmi;
2583 2599
2584 hdmi = __dw_hdmi_probe(pdev, plat_data); 2600 hdmi = __dw_hdmi_probe(pdev, plat_data);
2585 if (IS_ERR(hdmi)) 2601 if (IS_ERR(hdmi))
2586 return PTR_ERR(hdmi); 2602 return hdmi;
2587 2603
2588 drm_bridge_add(&hdmi->bridge); 2604 drm_bridge_add(&hdmi->bridge);
2589 2605
2590 return 0; 2606 return hdmi;
2591} 2607}
2592EXPORT_SYMBOL_GPL(dw_hdmi_probe); 2608EXPORT_SYMBOL_GPL(dw_hdmi_probe);
2593 2609
2594void dw_hdmi_remove(struct platform_device *pdev) 2610void dw_hdmi_remove(struct dw_hdmi *hdmi)
2595{ 2611{
2596 struct dw_hdmi *hdmi = platform_get_drvdata(pdev);
2597
2598 drm_bridge_remove(&hdmi->bridge); 2612 drm_bridge_remove(&hdmi->bridge);
2599 2613
2600 __dw_hdmi_remove(hdmi); 2614 __dw_hdmi_remove(hdmi);
@@ -2604,31 +2618,30 @@ EXPORT_SYMBOL_GPL(dw_hdmi_remove);
2604/* ----------------------------------------------------------------------------- 2618/* -----------------------------------------------------------------------------
2605 * Bind/unbind API, used from platforms based on the component framework. 2619 * Bind/unbind API, used from platforms based on the component framework.
2606 */ 2620 */
2607int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, 2621struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
2608 const struct dw_hdmi_plat_data *plat_data) 2622 struct drm_encoder *encoder,
2623 const struct dw_hdmi_plat_data *plat_data)
2609{ 2624{
2610 struct dw_hdmi *hdmi; 2625 struct dw_hdmi *hdmi;
2611 int ret; 2626 int ret;
2612 2627
2613 hdmi = __dw_hdmi_probe(pdev, plat_data); 2628 hdmi = __dw_hdmi_probe(pdev, plat_data);
2614 if (IS_ERR(hdmi)) 2629 if (IS_ERR(hdmi))
2615 return PTR_ERR(hdmi); 2630 return hdmi;
2616 2631
2617 ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL); 2632 ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL);
2618 if (ret) { 2633 if (ret) {
2619 dw_hdmi_remove(pdev); 2634 dw_hdmi_remove(hdmi);
2620 DRM_ERROR("Failed to initialize bridge with drm\n"); 2635 DRM_ERROR("Failed to initialize bridge with drm\n");
2621 return ret; 2636 return ERR_PTR(ret);
2622 } 2637 }
2623 2638
2624 return 0; 2639 return hdmi;
2625} 2640}
2626EXPORT_SYMBOL_GPL(dw_hdmi_bind); 2641EXPORT_SYMBOL_GPL(dw_hdmi_bind);
2627 2642
2628void dw_hdmi_unbind(struct device *dev) 2643void dw_hdmi_unbind(struct dw_hdmi *hdmi)
2629{ 2644{
2630 struct dw_hdmi *hdmi = dev_get_drvdata(dev);
2631
2632 __dw_hdmi_remove(hdmi); 2645 __dw_hdmi_remove(hdmi);
2633} 2646}
2634EXPORT_SYMBOL_GPL(dw_hdmi_unbind); 2647EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
index 4c62dff14893..5a81e1b4c076 100644
--- a/drivers/gpu/drm/drm_blend.c
+++ b/drivers/gpu/drm/drm_blend.c
@@ -88,15 +88,17 @@
88 * On top of this basic transformation additional properties can be exposed by 88 * On top of this basic transformation additional properties can be exposed by
89 * the driver: 89 * the driver:
90 * 90 *
91 * - Rotation is set up with drm_plane_create_rotation_property(). It adds a 91 * rotation:
92 * rotation and reflection step between the source and destination rectangles. 92 * Rotation is set up with drm_plane_create_rotation_property(). It adds a
93 * Without this property the rectangle is only scaled, but not rotated or 93 * rotation and reflection step between the source and destination rectangles.
94 * reflected. 94 * Without this property the rectangle is only scaled, but not rotated or
95 * reflected.
95 * 96 *
96 * - Z position is set up with drm_plane_create_zpos_immutable_property() and 97 * zpos:
97 * drm_plane_create_zpos_property(). It controls the visibility of overlapping 98 * Z position is set up with drm_plane_create_zpos_immutable_property() and
98 * planes. Without this property the primary plane is always below the cursor 99 * drm_plane_create_zpos_property(). It controls the visibility of overlapping
99 * plane, and ordering between all other planes is undefined. 100 * planes. Without this property the primary plane is always below the cursor
101 * plane, and ordering between all other planes is undefined.
100 * 102 *
101 * Note that all the property extensions described here apply either to the 103 * Note that all the property extensions described here apply either to the
102 * plane or the CRTC (e.g. for the background color, which currently is not 104 * plane or the CRTC (e.g. for the background color, which currently is not
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 16b9c3810af2..b3cde897cd80 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -849,13 +849,13 @@ DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
849 * 849 *
850 * The value of this property can be one of the following: 850 * The value of this property can be one of the following:
851 * 851 *
852 * - DRM_MODE_CONTENT_PROTECTION_UNDESIRED = 0 852 * DRM_MODE_CONTENT_PROTECTION_UNDESIRED = 0
853 * The link is not protected, content is transmitted in the clear. 853 * The link is not protected, content is transmitted in the clear.
854 * - DRM_MODE_CONTENT_PROTECTION_DESIRED = 1 854 * DRM_MODE_CONTENT_PROTECTION_DESIRED = 1
855 * Userspace has requested content protection, but the link is not 855 * Userspace has requested content protection, but the link is not
856 * currently protected. When in this state, kernel should enable 856 * currently protected. When in this state, kernel should enable
857 * Content Protection as soon as possible. 857 * Content Protection as soon as possible.
858 * - DRM_MODE_CONTENT_PROTECTION_ENABLED = 2 858 * DRM_MODE_CONTENT_PROTECTION_ENABLED = 2
859 * Userspace has requested content protection, and the link is 859 * Userspace has requested content protection, and the link is
860 * protected. Only the driver can set the property to this value. 860 * protected. Only the driver can set the property to this value.
861 * If userspace attempts to set to ENABLED, kernel will return 861 * If userspace attempts to set to ENABLED, kernel will return
@@ -889,7 +889,31 @@ DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
889 * INPUT_PROP_DIRECT) will still map 1:1 to the actual LCD panel 889 * INPUT_PROP_DIRECT) will still map 1:1 to the actual LCD panel
890 * coordinates, so if userspace rotates the picture to adjust for 890 * coordinates, so if userspace rotates the picture to adjust for
891 * the orientation it must also apply the same transformation to the 891 * the orientation it must also apply the same transformation to the
892 * touchscreen input coordinates. 892 * touchscreen input coordinates. This property is initialized by calling
893 * drm_connector_init_panel_orientation_property().
894 *
895 * scaling mode:
896 * This property defines how a non-native mode is upscaled to the native
897 * mode of an LCD panel:
898 *
899 * None:
900 * No upscaling happens, scaling is left to the panel. Not all
901 * drivers expose this mode.
902 * Full:
903 * The output is upscaled to the full resolution of the panel,
904 * ignoring the aspect ratio.
905 * Center:
906 * No upscaling happens, the output is centered within the native
907 * resolution the panel.
908 * Full aspect:
909 * The output is upscaled to maximize either the width or height
910 * while retaining the aspect ratio.
911 *
912 * This property should be set up by calling
913 * drm_connector_attach_scaling_mode_property(). Note that drivers
914 * can also expose this property to external outputs, in which case they
915 * must support "None", which should be the default (since external screens
916 * have a built-in scaler).
893 */ 917 */
894 918
895int drm_connector_create_standard_properties(struct drm_device *dev) 919int drm_connector_create_standard_properties(struct drm_device *dev)
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 36df7df5fe1a..6fac4129e6a2 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1082,10 +1082,12 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port)
1082 lct = drm_dp_calculate_rad(port, rad); 1082 lct = drm_dp_calculate_rad(port, rad);
1083 1083
1084 port->mstb = drm_dp_add_mst_branch_device(lct, rad); 1084 port->mstb = drm_dp_add_mst_branch_device(lct, rad);
1085 port->mstb->mgr = port->mgr; 1085 if (port->mstb) {
1086 port->mstb->port_parent = port; 1086 port->mstb->mgr = port->mgr;
1087 port->mstb->port_parent = port;
1087 1088
1088 send_link = true; 1089 send_link = true;
1090 }
1089 break; 1091 break;
1090 } 1092 }
1091 return send_link; 1093 return send_link;
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index b1cb2627548f..a797bbf1cab8 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2083,6 +2083,8 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid,
2083 if (hsize == 1366 && vsize == 768 && vrefresh_rate == 60) { 2083 if (hsize == 1366 && vsize == 768 && vrefresh_rate == 60) {
2084 mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0, 2084 mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0,
2085 false); 2085 false);
2086 if (!mode)
2087 return NULL;
2086 mode->hdisplay = 1366; 2088 mode->hdisplay = 1366;
2087 mode->hsync_start = mode->hsync_start - 1; 2089 mode->hsync_start = mode->hsync_start - 1;
2088 mode->hsync_end = mode->hsync_end - 1; 2090 mode->hsync_end = mode->hsync_end - 1;
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 01f8d9481211..4975ba9a7bc8 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -98,7 +98,7 @@ drm_gem_init(struct drm_device *dev)
98 struct drm_vma_offset_manager *vma_offset_manager; 98 struct drm_vma_offset_manager *vma_offset_manager;
99 99
100 mutex_init(&dev->object_name_lock); 100 mutex_init(&dev->object_name_lock);
101 idr_init(&dev->object_name_idr); 101 idr_init_base(&dev->object_name_idr, 1);
102 102
103 vma_offset_manager = kzalloc(sizeof(*vma_offset_manager), GFP_KERNEL); 103 vma_offset_manager = kzalloc(sizeof(*vma_offset_manager), GFP_KERNEL);
104 if (!vma_offset_manager) { 104 if (!vma_offset_manager) {
@@ -776,7 +776,7 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
776void 776void
777drm_gem_open(struct drm_device *dev, struct drm_file *file_private) 777drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
778{ 778{
779 idr_init(&file_private->object_idr); 779 idr_init_base(&file_private->object_idr, 1);
780 spin_lock_init(&file_private->table_lock); 780 spin_lock_init(&file_private->table_lock);
781} 781}
782 782
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 1402c0e71b03..d345563fdff3 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -44,7 +44,7 @@ EXPORT_SYMBOL(drm_lease_owner);
44/** 44/**
45 * _drm_find_lessee - find lessee by id (idr_mutex held) 45 * _drm_find_lessee - find lessee by id (idr_mutex held)
46 * @master: drm_master of lessor 46 * @master: drm_master of lessor
47 * @id: lessee_id 47 * @lessee_id: id
48 * 48 *
49 * RETURN: 49 * RETURN:
50 * 50 *
@@ -101,7 +101,7 @@ static bool _drm_has_leased(struct drm_master *master, int id)
101 101
102/** 102/**
103 * _drm_lease_held - check drm_mode_object lease status (idr_mutex held) 103 * _drm_lease_held - check drm_mode_object lease status (idr_mutex held)
104 * @master: the drm_master 104 * @file_priv: the master drm_file
105 * @id: the object id 105 * @id: the object id
106 * 106 *
107 * Checks if the specified master holds a lease on the object. Return 107 * Checks if the specified master holds a lease on the object. Return
@@ -121,7 +121,7 @@ EXPORT_SYMBOL(_drm_lease_held);
121 121
122/** 122/**
123 * drm_lease_held - check drm_mode_object lease status (idr_mutex not held) 123 * drm_lease_held - check drm_mode_object lease status (idr_mutex not held)
124 * @master: the drm_master 124 * @file_priv: the master drm_file
125 * @id: the object id 125 * @id: the object id
126 * 126 *
127 * Checks if the specified master holds a lease on the object. Return 127 * Checks if the specified master holds a lease on the object. Return
@@ -149,7 +149,7 @@ EXPORT_SYMBOL(drm_lease_held);
149/** 149/**
150 * drm_lease_filter_crtcs - restricted crtc set to leased values (idr_mutex not held) 150 * drm_lease_filter_crtcs - restricted crtc set to leased values (idr_mutex not held)
151 * @file_priv: requestor file 151 * @file_priv: requestor file
152 * @crtcs: bitmask of crtcs to check 152 * @crtcs_in: bitmask of crtcs to check
153 * 153 *
154 * Reconstructs a crtc mask based on the crtcs which are visible 154 * Reconstructs a crtc mask based on the crtcs which are visible
155 * through the specified file. 155 * through the specified file.
@@ -305,7 +305,7 @@ void drm_lease_destroy(struct drm_master *master)
305 305
306/** 306/**
307 * _drm_lease_revoke - revoke access to all leased objects (idr_mutex held) 307 * _drm_lease_revoke - revoke access to all leased objects (idr_mutex held)
308 * @master: the master losing its lease 308 * @top: the master losing its lease
309 */ 309 */
310static void _drm_lease_revoke(struct drm_master *top) 310static void _drm_lease_revoke(struct drm_master *top)
311{ 311{
@@ -482,7 +482,7 @@ out_free_objects:
482 * drm_mode_create_lease_ioctl - create a new lease 482 * drm_mode_create_lease_ioctl - create a new lease
483 * @dev: the drm device 483 * @dev: the drm device
484 * @data: pointer to struct drm_mode_create_lease 484 * @data: pointer to struct drm_mode_create_lease
485 * @file_priv: the file being manipulated 485 * @lessor_priv: the file being manipulated
486 * 486 *
487 * The master associated with the specified file will have a lease 487 * The master associated with the specified file will have a lease
488 * created containing the objects specified in the ioctl structure. 488 * created containing the objects specified in the ioctl structure.
@@ -662,7 +662,7 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev,
662 * drm_mode_get_lease_ioctl - list leased objects 662 * drm_mode_get_lease_ioctl - list leased objects
663 * @dev: the drm device 663 * @dev: the drm device
664 * @data: pointer to struct drm_mode_get_lease 664 * @data: pointer to struct drm_mode_get_lease
665 * @file_priv: the file being manipulated 665 * @lessee_priv: the file being manipulated
666 * 666 *
667 * Return the list of leased objects for the specified lessee 667 * Return the list of leased objects for the specified lessee
668 */ 668 */
@@ -722,7 +722,7 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev,
722 * drm_mode_revoke_lease_ioctl - revoke lease 722 * drm_mode_revoke_lease_ioctl - revoke lease
723 * @dev: the drm device 723 * @dev: the drm device
724 * @data: pointer to struct drm_mode_revoke_lease 724 * @data: pointer to struct drm_mode_revoke_lease
725 * @file_priv: the file being manipulated 725 * @lessor_priv: the file being manipulated
726 * 726 *
727 * This removes all of the objects from the lease without 727 * This removes all of the objects from the lease without
728 * actually getting rid of the lease itself; that way all 728 * actually getting rid of the lease itself; that way all
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index c397b523c945..5a8033fda4e3 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1346,9 +1346,9 @@ EXPORT_SYMBOL(drm_mode_connector_list_update);
1346 * modeline in fb_mode_option will be parsed instead. 1346 * modeline in fb_mode_option will be parsed instead.
1347 * 1347 *
1348 * This uses the same parameters as the fb modedb.c, except for an extra 1348 * This uses the same parameters as the fb modedb.c, except for an extra
1349 * force-enable, force-enable-digital and force-disable bit at the end: 1349 * force-enable, force-enable-digital and force-disable bit at the end::
1350 * 1350 *
1351 * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd] 1351 * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
1352 * 1352 *
1353 * The intermediate drm_cmdline_mode structure is required to store additional 1353 * The intermediate drm_cmdline_mode structure is required to store additional
1354 * options from the command line modline like the force-enable/disable flag. 1354 * options from the command line modline like the force-enable/disable flag.
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 9d3f6b70812c..6c327fdbaaee 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -34,6 +34,20 @@ static const struct drm_encoder_funcs drm_simple_kms_encoder_funcs = {
34 .destroy = drm_encoder_cleanup, 34 .destroy = drm_encoder_cleanup,
35}; 35};
36 36
37static enum drm_mode_status
38drm_simple_kms_crtc_mode_valid(struct drm_crtc *crtc,
39 const struct drm_display_mode *mode)
40{
41 struct drm_simple_display_pipe *pipe;
42
43 pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
44 if (!pipe->funcs || !pipe->funcs->mode_valid)
45 /* Anything goes */
46 return MODE_OK;
47
48 return pipe->funcs->mode_valid(crtc, mode);
49}
50
37static int drm_simple_kms_crtc_check(struct drm_crtc *crtc, 51static int drm_simple_kms_crtc_check(struct drm_crtc *crtc,
38 struct drm_crtc_state *state) 52 struct drm_crtc_state *state)
39{ 53{
@@ -72,6 +86,7 @@ static void drm_simple_kms_crtc_disable(struct drm_crtc *crtc,
72} 86}
73 87
74static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = { 88static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = {
89 .mode_valid = drm_simple_kms_crtc_mode_valid,
75 .atomic_check = drm_simple_kms_crtc_check, 90 .atomic_check = drm_simple_kms_crtc_check,
76 .atomic_enable = drm_simple_kms_crtc_enable, 91 .atomic_enable = drm_simple_kms_crtc_enable,
77 .atomic_disable = drm_simple_kms_crtc_disable, 92 .atomic_disable = drm_simple_kms_crtc_disable,
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 0b7b0d1ad2d5..d4f4ce484529 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -546,7 +546,7 @@ err_put_fd:
546void 546void
547drm_syncobj_open(struct drm_file *file_private) 547drm_syncobj_open(struct drm_file *file_private)
548{ 548{
549 idr_init(&file_private->syncobj_idr); 549 idr_init_base(&file_private->syncobj_idr, 1);
550 spin_lock_init(&file_private->syncobj_table_lock); 550 spin_lock_init(&file_private->syncobj_table_lock);
551} 551}
552 552
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index b62763aa8706..fe6becdcc29e 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -25,6 +25,7 @@
25struct imx_hdmi { 25struct imx_hdmi {
26 struct device *dev; 26 struct device *dev;
27 struct drm_encoder encoder; 27 struct drm_encoder encoder;
28 struct dw_hdmi *hdmi;
28 struct regmap *regmap; 29 struct regmap *regmap;
29}; 30};
30 31
@@ -239,14 +240,18 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
239 drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs, 240 drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs,
240 DRM_MODE_ENCODER_TMDS, NULL); 241 DRM_MODE_ENCODER_TMDS, NULL);
241 242
242 ret = dw_hdmi_bind(pdev, encoder, plat_data); 243 platform_set_drvdata(pdev, hdmi);
244
245 hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
243 246
244 /* 247 /*
245 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), 248 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
246 * which would have called the encoder cleanup. Do it manually. 249 * which would have called the encoder cleanup. Do it manually.
247 */ 250 */
248 if (ret) 251 if (IS_ERR(hdmi->hdmi)) {
252 ret = PTR_ERR(hdmi->hdmi);
249 drm_encoder_cleanup(encoder); 253 drm_encoder_cleanup(encoder);
254 }
250 255
251 return ret; 256 return ret;
252} 257}
@@ -254,7 +259,9 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
254static void dw_hdmi_imx_unbind(struct device *dev, struct device *master, 259static void dw_hdmi_imx_unbind(struct device *dev, struct device *master,
255 void *data) 260 void *data)
256{ 261{
257 return dw_hdmi_unbind(dev); 262 struct imx_hdmi *hdmi = dev_get_drvdata(dev);
263
264 dw_hdmi_unbind(hdmi->hdmi);
258} 265}
259 266
260static const struct component_ops dw_hdmi_imx_ops = { 267static const struct component_ops dw_hdmi_imx_ops = {
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
index 17de3afd98f6..d49af17310c9 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
@@ -140,6 +140,7 @@ struct meson_dw_hdmi {
140 struct clk *venci_clk; 140 struct clk *venci_clk;
141 struct regulator *hdmi_supply; 141 struct regulator *hdmi_supply;
142 u32 irq_stat; 142 u32 irq_stat;
143 struct dw_hdmi *hdmi;
143}; 144};
144#define encoder_to_meson_dw_hdmi(x) \ 145#define encoder_to_meson_dw_hdmi(x) \
145 container_of(x, struct meson_dw_hdmi, encoder) 146 container_of(x, struct meson_dw_hdmi, encoder)
@@ -302,7 +303,7 @@ static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
302 } 303 }
303} 304}
304 305
305static inline void dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi) 306static inline void meson_dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi)
306{ 307{
307 struct meson_drm *priv = dw_hdmi->priv; 308 struct meson_drm *priv = dw_hdmi->priv;
308 309
@@ -409,9 +410,9 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
409 msleep(100); 410 msleep(100);
410 411
411 /* Reset PHY 3 times in a row */ 412 /* Reset PHY 3 times in a row */
412 dw_hdmi_phy_reset(dw_hdmi); 413 meson_dw_hdmi_phy_reset(dw_hdmi);
413 dw_hdmi_phy_reset(dw_hdmi); 414 meson_dw_hdmi_phy_reset(dw_hdmi);
414 dw_hdmi_phy_reset(dw_hdmi); 415 meson_dw_hdmi_phy_reset(dw_hdmi);
415 416
416 /* Temporary Disable VENC video stream */ 417 /* Temporary Disable VENC video stream */
417 if (priv->venc.hdmi_use_enci) 418 if (priv->venc.hdmi_use_enci)
@@ -878,9 +879,12 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
878 dw_plat_data->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24; 879 dw_plat_data->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
879 dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709; 880 dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
880 881
881 ret = dw_hdmi_bind(pdev, encoder, &meson_dw_hdmi->dw_plat_data); 882 platform_set_drvdata(pdev, meson_dw_hdmi);
882 if (ret) 883
883 return ret; 884 meson_dw_hdmi->hdmi = dw_hdmi_bind(pdev, encoder,
885 &meson_dw_hdmi->dw_plat_data);
886 if (IS_ERR(meson_dw_hdmi->hdmi))
887 return PTR_ERR(meson_dw_hdmi->hdmi);
884 888
885 DRM_DEBUG_DRIVER("HDMI controller initialized\n"); 889 DRM_DEBUG_DRIVER("HDMI controller initialized\n");
886 890
@@ -890,7 +894,9 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
890static void meson_dw_hdmi_unbind(struct device *dev, struct device *master, 894static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
891 void *data) 895 void *data)
892{ 896{
893 dw_hdmi_unbind(dev); 897 struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
898
899 dw_hdmi_unbind(meson_dw_hdmi->hdmi);
894} 900}
895 901
896static const struct component_ops meson_dw_hdmi_ops = { 902static const struct component_ops meson_dw_hdmi_ops = {
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
index efff6dbbb86f..48a03f55610a 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
@@ -87,11 +87,7 @@ static int panel_dpi_enable(struct omap_dss_device *dssdev)
87 } 87 }
88 88
89 gpiod_set_value_cansleep(ddata->enable_gpio, 1); 89 gpiod_set_value_cansleep(ddata->enable_gpio, 1);
90 90 backlight_enable(ddata->backlight);
91 if (ddata->backlight) {
92 ddata->backlight->props.power = FB_BLANK_UNBLANK;
93 backlight_update_status(ddata->backlight);
94 }
95 91
96 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 92 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
97 93
@@ -106,10 +102,7 @@ static void panel_dpi_disable(struct omap_dss_device *dssdev)
106 if (!omapdss_device_is_enabled(dssdev)) 102 if (!omapdss_device_is_enabled(dssdev))
107 return; 103 return;
108 104
109 if (ddata->backlight) { 105 backlight_disable(ddata->backlight);
110 ddata->backlight->props.power = FB_BLANK_POWERDOWN;
111 backlight_update_status(ddata->backlight);
112 }
113 106
114 gpiod_set_value_cansleep(ddata->enable_gpio, 0); 107 gpiod_set_value_cansleep(ddata->enable_gpio, 0);
115 regulator_disable(ddata->vcc_supply); 108 regulator_disable(ddata->vcc_supply);
@@ -164,7 +157,6 @@ static int panel_dpi_probe_of(struct platform_device *pdev)
164{ 157{
165 struct panel_drv_data *ddata = platform_get_drvdata(pdev); 158 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
166 struct device_node *node = pdev->dev.of_node; 159 struct device_node *node = pdev->dev.of_node;
167 struct device_node *bl_node;
168 struct omap_dss_device *in; 160 struct omap_dss_device *in;
169 int r; 161 int r;
170 struct display_timing timing; 162 struct display_timing timing;
@@ -190,19 +182,15 @@ static int panel_dpi_probe_of(struct platform_device *pdev)
190 if (IS_ERR(ddata->vcc_supply)) 182 if (IS_ERR(ddata->vcc_supply))
191 return PTR_ERR(ddata->vcc_supply); 183 return PTR_ERR(ddata->vcc_supply);
192 184
193 bl_node = of_parse_phandle(node, "backlight", 0); 185 ddata->backlight = devm_of_find_backlight(&pdev->dev);
194 if (bl_node) {
195 ddata->backlight = of_find_backlight_by_node(bl_node);
196 of_node_put(bl_node);
197 186
198 if (!ddata->backlight) 187 if (IS_ERR(ddata->backlight))
199 return -EPROBE_DEFER; 188 return PTR_ERR(ddata->backlight);
200 }
201 189
202 r = of_get_display_timing(node, "panel-timing", &timing); 190 r = of_get_display_timing(node, "panel-timing", &timing);
203 if (r) { 191 if (r) {
204 dev_err(&pdev->dev, "failed to get video timing\n"); 192 dev_err(&pdev->dev, "failed to get video timing\n");
205 goto error_free_backlight; 193 return r;
206 } 194 }
207 195
208 videomode_from_timing(&timing, &ddata->vm); 196 videomode_from_timing(&timing, &ddata->vm);
@@ -210,19 +198,12 @@ static int panel_dpi_probe_of(struct platform_device *pdev)
210 in = omapdss_of_find_source_for_first_ep(node); 198 in = omapdss_of_find_source_for_first_ep(node);
211 if (IS_ERR(in)) { 199 if (IS_ERR(in)) {
212 dev_err(&pdev->dev, "failed to find video source\n"); 200 dev_err(&pdev->dev, "failed to find video source\n");
213 r = PTR_ERR(in); 201 return PTR_ERR(in);
214 goto error_free_backlight;
215 } 202 }
216 203
217 ddata->in = in; 204 ddata->in = in;
218 205
219 return 0; 206 return 0;
220
221error_free_backlight:
222 if (ddata->backlight)
223 put_device(&ddata->backlight->dev);
224
225 return r;
226} 207}
227 208
228static int panel_dpi_probe(struct platform_device *pdev) 209static int panel_dpi_probe(struct platform_device *pdev)
@@ -277,9 +258,6 @@ static int __exit panel_dpi_remove(struct platform_device *pdev)
277 258
278 omap_dss_put_device(in); 259 omap_dss_put_device(in);
279 260
280 if (ddata->backlight)
281 put_device(&ddata->backlight->dev);
282
283 return 0; 261 return 0;
284} 262}
285 263
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 6ba93449fcfb..57df39b5c589 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -45,8 +45,7 @@ static int innolux_panel_disable(struct drm_panel *panel)
45 if (!innolux->enabled) 45 if (!innolux->enabled)
46 return 0; 46 return 0;
47 47
48 innolux->backlight->props.power = FB_BLANK_POWERDOWN; 48 backlight_disable(innolux->backlight);
49 backlight_update_status(innolux->backlight);
50 49
51 err = mipi_dsi_dcs_set_display_off(innolux->link); 50 err = mipi_dsi_dcs_set_display_off(innolux->link);
52 if (err < 0) 51 if (err < 0)
@@ -151,8 +150,7 @@ static int innolux_panel_enable(struct drm_panel *panel)
151 if (innolux->enabled) 150 if (innolux->enabled)
152 return 0; 151 return 0;
153 152
154 innolux->backlight->props.power = FB_BLANK_UNBLANK; 153 ret = backlight_enable(innolux->backlight);
155 ret = backlight_update_status(innolux->backlight);
156 if (ret) { 154 if (ret) {
157 DRM_DEV_ERROR(panel->drm->dev, 155 DRM_DEV_ERROR(panel->drm->dev,
158 "Failed to enable backlight %d\n", ret); 156 "Failed to enable backlight %d\n", ret);
@@ -217,7 +215,6 @@ MODULE_DEVICE_TABLE(of, innolux_of_match);
217static int innolux_panel_add(struct innolux_panel *innolux) 215static int innolux_panel_add(struct innolux_panel *innolux)
218{ 216{
219 struct device *dev = &innolux->link->dev; 217 struct device *dev = &innolux->link->dev;
220 struct device_node *np;
221 int err; 218 int err;
222 219
223 innolux->supply = devm_regulator_get(dev, "power"); 220 innolux->supply = devm_regulator_get(dev, "power");
@@ -232,37 +229,22 @@ static int innolux_panel_add(struct innolux_panel *innolux)
232 innolux->enable_gpio = NULL; 229 innolux->enable_gpio = NULL;
233 } 230 }
234 231
235 np = of_parse_phandle(dev->of_node, "backlight", 0); 232 innolux->backlight = devm_of_find_backlight(dev);
236 if (np) {
237 innolux->backlight = of_find_backlight_by_node(np);
238 of_node_put(np);
239 233
240 if (!innolux->backlight) 234 if (IS_ERR(innolux->backlight))
241 return -EPROBE_DEFER; 235 return PTR_ERR(innolux->backlight);
242 }
243 236
244 drm_panel_init(&innolux->base); 237 drm_panel_init(&innolux->base);
245 innolux->base.funcs = &innolux_panel_funcs; 238 innolux->base.funcs = &innolux_panel_funcs;
246 innolux->base.dev = &innolux->link->dev; 239 innolux->base.dev = &innolux->link->dev;
247 240
248 err = drm_panel_add(&innolux->base); 241 return drm_panel_add(&innolux->base);
249 if (err < 0)
250 goto put_backlight;
251
252 return 0;
253
254put_backlight:
255 put_device(&innolux->backlight->dev);
256
257 return err;
258} 242}
259 243
260static void innolux_panel_del(struct innolux_panel *innolux) 244static void innolux_panel_del(struct innolux_panel *innolux)
261{ 245{
262 if (innolux->base.dev) 246 if (innolux->base.dev)
263 drm_panel_remove(&innolux->base); 247 drm_panel_remove(&innolux->base);
264
265 put_device(&innolux->backlight->dev);
266} 248}
267 249
268static int innolux_panel_probe(struct mipi_dsi_device *dsi) 250static int innolux_panel_probe(struct mipi_dsi_device *dsi)
diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
index 5b2340ef74ed..0a94ab79a6c0 100644
--- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
+++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
@@ -192,8 +192,7 @@ static int jdi_panel_disable(struct drm_panel *panel)
192 if (!jdi->enabled) 192 if (!jdi->enabled)
193 return 0; 193 return 0;
194 194
195 jdi->backlight->props.power = FB_BLANK_POWERDOWN; 195 backlight_disable(jdi->backlight);
196 backlight_update_status(jdi->backlight);
197 196
198 jdi->enabled = false; 197 jdi->enabled = false;
199 198
@@ -289,8 +288,7 @@ static int jdi_panel_enable(struct drm_panel *panel)
289 if (jdi->enabled) 288 if (jdi->enabled)
290 return 0; 289 return 0;
291 290
292 jdi->backlight->props.power = FB_BLANK_UNBLANK; 291 backlight_enable(jdi->backlight);
293 backlight_update_status(jdi->backlight);
294 292
295 jdi->enabled = true; 293 jdi->enabled = true;
296 294
diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index 3cce3ca19601..6bf8730f1a21 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -96,10 +96,7 @@ static int sharp_panel_disable(struct drm_panel *panel)
96 if (!sharp->enabled) 96 if (!sharp->enabled)
97 return 0; 97 return 0;
98 98
99 if (sharp->backlight) { 99 backlight_disable(sharp->backlight);
100 sharp->backlight->props.power = FB_BLANK_POWERDOWN;
101 backlight_update_status(sharp->backlight);
102 }
103 100
104 sharp->enabled = false; 101 sharp->enabled = false;
105 102
@@ -263,10 +260,7 @@ static int sharp_panel_enable(struct drm_panel *panel)
263 if (sharp->enabled) 260 if (sharp->enabled)
264 return 0; 261 return 0;
265 262
266 if (sharp->backlight) { 263 backlight_enable(sharp->backlight);
267 sharp->backlight->props.power = FB_BLANK_UNBLANK;
268 backlight_update_status(sharp->backlight);
269 }
270 264
271 sharp->enabled = true; 265 sharp->enabled = true;
272 266
@@ -324,8 +318,7 @@ MODULE_DEVICE_TABLE(of, sharp_of_match);
324 318
325static int sharp_panel_add(struct sharp_panel *sharp) 319static int sharp_panel_add(struct sharp_panel *sharp)
326{ 320{
327 struct device_node *np; 321 struct device *dev = &sharp->link1->dev;
328 int err;
329 322
330 sharp->mode = &default_mode; 323 sharp->mode = &default_mode;
331 324
@@ -333,30 +326,16 @@ static int sharp_panel_add(struct sharp_panel *sharp)
333 if (IS_ERR(sharp->supply)) 326 if (IS_ERR(sharp->supply))
334 return PTR_ERR(sharp->supply); 327 return PTR_ERR(sharp->supply);
335 328
336 np = of_parse_phandle(sharp->link1->dev.of_node, "backlight", 0); 329 sharp->backlight = devm_of_find_backlight(dev);
337 if (np) {
338 sharp->backlight = of_find_backlight_by_node(np);
339 of_node_put(np);
340 330
341 if (!sharp->backlight) 331 if (IS_ERR(sharp->backlight))
342 return -EPROBE_DEFER; 332 return PTR_ERR(sharp->backlight);
343 }
344 333
345 drm_panel_init(&sharp->base); 334 drm_panel_init(&sharp->base);
346 sharp->base.funcs = &sharp_panel_funcs; 335 sharp->base.funcs = &sharp_panel_funcs;
347 sharp->base.dev = &sharp->link1->dev; 336 sharp->base.dev = &sharp->link1->dev;
348 337
349 err = drm_panel_add(&sharp->base); 338 return drm_panel_add(&sharp->base);
350 if (err < 0)
351 goto put_backlight;
352
353 return 0;
354
355put_backlight:
356 if (sharp->backlight)
357 put_device(&sharp->backlight->dev);
358
359 return err;
360} 339}
361 340
362static void sharp_panel_del(struct sharp_panel *sharp) 341static void sharp_panel_del(struct sharp_panel *sharp)
@@ -364,9 +343,6 @@ static void sharp_panel_del(struct sharp_panel *sharp)
364 if (sharp->base.dev) 343 if (sharp->base.dev)
365 drm_panel_remove(&sharp->base); 344 drm_panel_remove(&sharp->base);
366 345
367 if (sharp->backlight)
368 put_device(&sharp->backlight->dev);
369
370 if (sharp->link2) 346 if (sharp->link2)
371 put_device(&sharp->link2->dev); 347 put_device(&sharp->link2->dev);
372} 348}
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
index 3aeb0bda4947..494aa9b1628a 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -117,10 +117,7 @@ static int sharp_nt_panel_disable(struct drm_panel *panel)
117 if (!sharp_nt->enabled) 117 if (!sharp_nt->enabled)
118 return 0; 118 return 0;
119 119
120 if (sharp_nt->backlight) { 120 backlight_disable(sharp_nt->backlight);
121 sharp_nt->backlight->props.power = FB_BLANK_POWERDOWN;
122 backlight_update_status(sharp_nt->backlight);
123 }
124 121
125 sharp_nt->enabled = false; 122 sharp_nt->enabled = false;
126 123
@@ -203,10 +200,7 @@ static int sharp_nt_panel_enable(struct drm_panel *panel)
203 if (sharp_nt->enabled) 200 if (sharp_nt->enabled)
204 return 0; 201 return 0;
205 202
206 if (sharp_nt->backlight) { 203 backlight_enable(sharp_nt->backlight);
207 sharp_nt->backlight->props.power = FB_BLANK_UNBLANK;
208 backlight_update_status(sharp_nt->backlight);
209 }
210 204
211 sharp_nt->enabled = true; 205 sharp_nt->enabled = true;
212 206
@@ -259,8 +253,6 @@ static const struct drm_panel_funcs sharp_nt_panel_funcs = {
259static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt) 253static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt)
260{ 254{
261 struct device *dev = &sharp_nt->dsi->dev; 255 struct device *dev = &sharp_nt->dsi->dev;
262 struct device_node *np;
263 int ret;
264 256
265 sharp_nt->mode = &default_mode; 257 sharp_nt->mode = &default_mode;
266 258
@@ -277,39 +269,22 @@ static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt)
277 gpiod_set_value(sharp_nt->reset_gpio, 0); 269 gpiod_set_value(sharp_nt->reset_gpio, 0);
278 } 270 }
279 271
280 np = of_parse_phandle(dev->of_node, "backlight", 0); 272 sharp_nt->backlight = devm_of_find_backlight(dev);
281 if (np) {
282 sharp_nt->backlight = of_find_backlight_by_node(np);
283 of_node_put(np);
284 273
285 if (!sharp_nt->backlight) 274 if (IS_ERR(sharp_nt->backlight))
286 return -EPROBE_DEFER; 275 return PTR_ERR(sharp_nt->backlight);
287 }
288 276
289 drm_panel_init(&sharp_nt->base); 277 drm_panel_init(&sharp_nt->base);
290 sharp_nt->base.funcs = &sharp_nt_panel_funcs; 278 sharp_nt->base.funcs = &sharp_nt_panel_funcs;
291 sharp_nt->base.dev = &sharp_nt->dsi->dev; 279 sharp_nt->base.dev = &sharp_nt->dsi->dev;
292 280
293 ret = drm_panel_add(&sharp_nt->base); 281 return drm_panel_add(&sharp_nt->base);
294 if (ret < 0)
295 goto put_backlight;
296
297 return 0;
298
299put_backlight:
300 if (sharp_nt->backlight)
301 put_device(&sharp_nt->backlight->dev);
302
303 return ret;
304} 282}
305 283
306static void sharp_nt_panel_del(struct sharp_nt_panel *sharp_nt) 284static void sharp_nt_panel_del(struct sharp_nt_panel *sharp_nt)
307{ 285{
308 if (sharp_nt->base.dev) 286 if (sharp_nt->base.dev)
309 drm_panel_remove(&sharp_nt->base); 287 drm_panel_remove(&sharp_nt->base);
310
311 if (sharp_nt->backlight)
312 put_device(&sharp_nt->backlight->dev);
313} 288}
314 289
315static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi) 290static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi)
diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
index dc85b53d58ef..76210ae25094 100644
--- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
+++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c
@@ -68,12 +68,22 @@ static const struct dw_hdmi_plat_data rcar_dw_hdmi_plat_data = {
68 68
69static int rcar_dw_hdmi_probe(struct platform_device *pdev) 69static int rcar_dw_hdmi_probe(struct platform_device *pdev)
70{ 70{
71 return dw_hdmi_probe(pdev, &rcar_dw_hdmi_plat_data); 71 struct dw_hdmi *hdmi;
72
73 hdmi = dw_hdmi_probe(pdev, &rcar_dw_hdmi_plat_data);
74 if (IS_ERR(hdmi))
75 return PTR_ERR(hdmi);
76
77 platform_set_drvdata(pdev, hdmi);
78
79 return 0;
72} 80}
73 81
74static int rcar_dw_hdmi_remove(struct platform_device *pdev) 82static int rcar_dw_hdmi_remove(struct platform_device *pdev)
75{ 83{
76 dw_hdmi_remove(pdev); 84 struct dw_hdmi *hdmi = platform_get_drvdata(pdev);
85
86 dw_hdmi_remove(hdmi);
77 87
78 return 0; 88 return 0;
79} 89}
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index b1fe0639227e..591953cbdd18 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -1202,9 +1202,6 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
1202 return ret; 1202 return ret;
1203 1203
1204 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1204 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1205 if (!res)
1206 return -ENODEV;
1207
1208 dsi->base = devm_ioremap_resource(dev, res); 1205 dsi->base = devm_ioremap_resource(dev, res);
1209 if (IS_ERR(dsi->base)) 1206 if (IS_ERR(dsi->base))
1210 return PTR_ERR(dsi->base); 1207 return PTR_ERR(dsi->base);
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 1eb02a82fd91..3574b0ae2ad1 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -48,6 +48,7 @@ struct rockchip_hdmi {
48 const struct rockchip_hdmi_chip_data *chip_data; 48 const struct rockchip_hdmi_chip_data *chip_data;
49 struct clk *vpll_clk; 49 struct clk *vpll_clk;
50 struct clk *grf_clk; 50 struct clk *grf_clk;
51 struct dw_hdmi *hdmi;
51}; 52};
52 53
53#define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) 54#define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x)
@@ -377,14 +378,18 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
377 drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, 378 drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
378 DRM_MODE_ENCODER_TMDS, NULL); 379 DRM_MODE_ENCODER_TMDS, NULL);
379 380
380 ret = dw_hdmi_bind(pdev, encoder, plat_data); 381 platform_set_drvdata(pdev, hdmi);
382
383 hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
381 384
382 /* 385 /*
383 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), 386 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
384 * which would have called the encoder cleanup. Do it manually. 387 * which would have called the encoder cleanup. Do it manually.
385 */ 388 */
386 if (ret) 389 if (IS_ERR(hdmi->hdmi)) {
390 ret = PTR_ERR(hdmi->hdmi);
387 drm_encoder_cleanup(encoder); 391 drm_encoder_cleanup(encoder);
392 }
388 393
389 return ret; 394 return ret;
390} 395}
@@ -392,7 +397,9 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
392static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, 397static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
393 void *data) 398 void *data)
394{ 399{
395 return dw_hdmi_unbind(dev); 400 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
401
402 dw_hdmi_unbind(hdmi->hdmi);
396} 403}
397 404
398static const struct component_ops dw_hdmi_rockchip_ops = { 405static const struct component_ops dw_hdmi_rockchip_ops = {
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
index fab30927a889..f6ad48766d49 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -831,9 +831,6 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
831 hdmi->drm_dev = drm; 831 hdmi->drm_dev = drm;
832 832
833 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 833 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
834 if (!iores)
835 return -ENXIO;
836
837 hdmi->regs = devm_ioremap_resource(dev, iores); 834 hdmi->regs = devm_ioremap_resource(dev, iores);
838 if (IS_ERR(hdmi->regs)) 835 if (IS_ERR(hdmi->regs))
839 return PTR_ERR(hdmi->regs); 836 return PTR_ERR(hdmi->regs);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index d85431400a0d..88084ca15115 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -230,6 +230,7 @@ static struct drm_driver rockchip_drm_driver = {
230 .gem_prime_import = drm_gem_prime_import, 230 .gem_prime_import = drm_gem_prime_import,
231 .gem_prime_export = drm_gem_prime_export, 231 .gem_prime_export = drm_gem_prime_export,
232 .gem_prime_get_sg_table = rockchip_gem_prime_get_sg_table, 232 .gem_prime_get_sg_table = rockchip_gem_prime_get_sg_table,
233 .gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table,
233 .gem_prime_vmap = rockchip_gem_prime_vmap, 234 .gem_prime_vmap = rockchip_gem_prime_vmap,
234 .gem_prime_vunmap = rockchip_gem_prime_vunmap, 235 .gem_prime_vunmap = rockchip_gem_prime_vunmap,
235 .gem_prime_mmap = rockchip_gem_mmap_buf, 236 .gem_prime_mmap = rockchip_gem_mmap_buf,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index 1d9655576b6e..074db7a92809 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -16,6 +16,8 @@
16#include <drm/drmP.h> 16#include <drm/drmP.h>
17#include <drm/drm_gem.h> 17#include <drm/drm_gem.h>
18#include <drm/drm_vma_manager.h> 18#include <drm/drm_vma_manager.h>
19
20#include <linux/dma-buf.h>
19#include <linux/iommu.h> 21#include <linux/iommu.h>
20 22
21#include "rockchip_drm_drv.h" 23#include "rockchip_drm_drv.h"
@@ -262,7 +264,6 @@ static int rockchip_drm_gem_object_mmap(struct drm_gem_object *obj,
262 * VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap(). 264 * VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap().
263 */ 265 */
264 vma->vm_flags &= ~VM_PFNMAP; 266 vma->vm_flags &= ~VM_PFNMAP;
265 vma->vm_pgoff = 0;
266 267
267 if (rk_obj->pages) 268 if (rk_obj->pages)
268 ret = rockchip_drm_gem_object_mmap_iommu(obj, vma); 269 ret = rockchip_drm_gem_object_mmap_iommu(obj, vma);
@@ -297,6 +298,12 @@ int rockchip_gem_mmap(struct file *filp, struct vm_area_struct *vma)
297 if (ret) 298 if (ret)
298 return ret; 299 return ret;
299 300
301 /*
302 * Set vm_pgoff (used as a fake buffer offset by DRM) to 0 and map the
303 * whole buffer from the start.
304 */
305 vma->vm_pgoff = 0;
306
300 obj = vma->vm_private_data; 307 obj = vma->vm_private_data;
301 308
302 return rockchip_drm_gem_object_mmap(obj, vma); 309 return rockchip_drm_gem_object_mmap(obj, vma);
@@ -309,12 +316,10 @@ static void rockchip_gem_release_object(struct rockchip_gem_object *rk_obj)
309} 316}
310 317
311struct rockchip_gem_object * 318struct rockchip_gem_object *
312 rockchip_gem_create_object(struct drm_device *drm, unsigned int size, 319 rockchip_gem_alloc_object(struct drm_device *drm, unsigned int size)
313 bool alloc_kmap)
314{ 320{
315 struct rockchip_gem_object *rk_obj; 321 struct rockchip_gem_object *rk_obj;
316 struct drm_gem_object *obj; 322 struct drm_gem_object *obj;
317 int ret;
318 323
319 size = round_up(size, PAGE_SIZE); 324 size = round_up(size, PAGE_SIZE);
320 325
@@ -326,6 +331,20 @@ struct rockchip_gem_object *
326 331
327 drm_gem_object_init(drm, obj, size); 332 drm_gem_object_init(drm, obj, size);
328 333
334 return rk_obj;
335}
336
337struct rockchip_gem_object *
338rockchip_gem_create_object(struct drm_device *drm, unsigned int size,
339 bool alloc_kmap)
340{
341 struct rockchip_gem_object *rk_obj;
342 int ret;
343
344 rk_obj = rockchip_gem_alloc_object(drm, size);
345 if (IS_ERR(rk_obj))
346 return rk_obj;
347
329 ret = rockchip_gem_alloc_buf(rk_obj, alloc_kmap); 348 ret = rockchip_gem_alloc_buf(rk_obj, alloc_kmap);
330 if (ret) 349 if (ret)
331 goto err_free_rk_obj; 350 goto err_free_rk_obj;
@@ -343,11 +362,21 @@ err_free_rk_obj:
343 */ 362 */
344void rockchip_gem_free_object(struct drm_gem_object *obj) 363void rockchip_gem_free_object(struct drm_gem_object *obj)
345{ 364{
346 struct rockchip_gem_object *rk_obj; 365 struct drm_device *drm = obj->dev;
347 366 struct rockchip_drm_private *private = drm->dev_private;
348 rk_obj = to_rockchip_obj(obj); 367 struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
349 368
350 rockchip_gem_free_buf(rk_obj); 369 if (obj->import_attach) {
370 if (private->domain) {
371 rockchip_gem_iommu_unmap(rk_obj);
372 } else {
373 dma_unmap_sg(drm->dev, rk_obj->sgt->sgl,
374 rk_obj->sgt->nents, DMA_BIDIRECTIONAL);
375 }
376 drm_prime_gem_destroy(obj, rk_obj->sgt);
377 } else {
378 rockchip_gem_free_buf(rk_obj);
379 }
351 380
352 rockchip_gem_release_object(rk_obj); 381 rockchip_gem_release_object(rk_obj);
353} 382}
@@ -451,6 +480,86 @@ struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj)
451 return sgt; 480 return sgt;
452} 481}
453 482
483static unsigned long rockchip_sg_get_contiguous_size(struct sg_table *sgt,
484 int count)
485{
486 struct scatterlist *s;
487 dma_addr_t expected = sg_dma_address(sgt->sgl);
488 unsigned int i;
489 unsigned long size = 0;
490
491 for_each_sg(sgt->sgl, s, count, i) {
492 if (sg_dma_address(s) != expected)
493 break;
494 expected = sg_dma_address(s) + sg_dma_len(s);
495 size += sg_dma_len(s);
496 }
497 return size;
498}
499
500static int
501rockchip_gem_iommu_map_sg(struct drm_device *drm,
502 struct dma_buf_attachment *attach,
503 struct sg_table *sg,
504 struct rockchip_gem_object *rk_obj)
505{
506 rk_obj->sgt = sg;
507 return rockchip_gem_iommu_map(rk_obj);
508}
509
510static int
511rockchip_gem_dma_map_sg(struct drm_device *drm,
512 struct dma_buf_attachment *attach,
513 struct sg_table *sg,
514 struct rockchip_gem_object *rk_obj)
515{
516 int count = dma_map_sg(drm->dev, sg->sgl, sg->nents,
517 DMA_BIDIRECTIONAL);
518 if (!count)
519 return -EINVAL;
520
521 if (rockchip_sg_get_contiguous_size(sg, count) < attach->dmabuf->size) {
522 DRM_ERROR("failed to map sg_table to contiguous linear address.\n");
523 dma_unmap_sg(drm->dev, sg->sgl, sg->nents,
524 DMA_BIDIRECTIONAL);
525 return -EINVAL;
526 }
527
528 rk_obj->dma_addr = sg_dma_address(sg->sgl);
529 rk_obj->sgt = sg;
530 return 0;
531}
532
533struct drm_gem_object *
534rockchip_gem_prime_import_sg_table(struct drm_device *drm,
535 struct dma_buf_attachment *attach,
536 struct sg_table *sg)
537{
538 struct rockchip_drm_private *private = drm->dev_private;
539 struct rockchip_gem_object *rk_obj;
540 int ret;
541
542 rk_obj = rockchip_gem_alloc_object(drm, attach->dmabuf->size);
543 if (IS_ERR(rk_obj))
544 return ERR_CAST(rk_obj);
545
546 if (private->domain)
547 ret = rockchip_gem_iommu_map_sg(drm, attach, sg, rk_obj);
548 else
549 ret = rockchip_gem_dma_map_sg(drm, attach, sg, rk_obj);
550
551 if (ret < 0) {
552 DRM_ERROR("failed to import sg table: %d\n", ret);
553 goto err_free_rk_obj;
554 }
555
556 return &rk_obj->base;
557
558err_free_rk_obj:
559 rockchip_gem_release_object(rk_obj);
560 return ERR_PTR(ret);
561}
562
454void *rockchip_gem_prime_vmap(struct drm_gem_object *obj) 563void *rockchip_gem_prime_vmap(struct drm_gem_object *obj)
455{ 564{
456 struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); 565 struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
index f237375582fb..d41fa65219d2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
@@ -36,8 +36,9 @@ struct rockchip_gem_object {
36 36
37struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj); 37struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj);
38struct drm_gem_object * 38struct drm_gem_object *
39rockchip_gem_prime_import_sg_table(struct drm_device *dev, size_t size, 39rockchip_gem_prime_import_sg_table(struct drm_device *dev,
40 struct sg_table *sgt); 40 struct dma_buf_attachment *attach,
41 struct sg_table *sg);
41void *rockchip_gem_prime_vmap(struct drm_gem_object *obj); 42void *rockchip_gem_prime_vmap(struct drm_gem_object *obj);
42void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); 43void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
43 44
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 7715853ef90a..66736227c96e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -95,9 +95,6 @@ struct vop {
95 struct drm_device *drm_dev; 95 struct drm_device *drm_dev;
96 bool is_enabled; 96 bool is_enabled;
97 97
98 /* mutex vsync_ work */
99 struct mutex vsync_mutex;
100 bool vsync_work_pending;
101 struct completion dsp_hold_completion; 98 struct completion dsp_hold_completion;
102 99
103 /* protected by dev->event_lock */ 100 /* protected by dev->event_lock */
@@ -1555,8 +1552,6 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
1555 spin_lock_init(&vop->reg_lock); 1552 spin_lock_init(&vop->reg_lock);
1556 spin_lock_init(&vop->irq_lock); 1553 spin_lock_init(&vop->irq_lock);
1557 1554
1558 mutex_init(&vop->vsync_mutex);
1559
1560 ret = devm_request_irq(dev, vop->irq, vop_isr, 1555 ret = devm_request_irq(dev, vop->irq, vop_isr,
1561 IRQF_SHARED, dev_name(dev), vop); 1556 IRQF_SHARED, dev_name(dev), vop);
1562 if (ret) 1557 if (ret)
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 882d85db9053..7327da3bc94f 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -40,6 +40,15 @@ config DRM_SUN4I_BACKEND
40 do some alpha blending and feed graphics to TCON. If M is 40 do some alpha blending and feed graphics to TCON. If M is
41 selected the module will be called sun4i-backend. 41 selected the module will be called sun4i-backend.
42 42
43config DRM_SUN8I_DW_HDMI
44 tristate "Support for Allwinner version of DesignWare HDMI"
45 depends on DRM_SUN4I
46 select DRM_DW_HDMI
47 help
48 Choose this option if you have an Allwinner SoC with the
49 DesignWare HDMI controller with custom HDMI PHY. If M is
50 selected the module will be called sun8i_dw_hdmi.
51
43config DRM_SUN8I_MIXER 52config DRM_SUN8I_MIXER
44 tristate "Support for Allwinner Display Engine 2.0 Mixer" 53 tristate "Support for Allwinner Display Engine 2.0 Mixer"
45 default MACH_SUN8I 54 default MACH_SUN8I
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 582607c0c488..1610e748119b 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -10,6 +10,9 @@ sun4i-drm-hdmi-y += sun4i_hdmi_enc.o
10sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o 10sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o
11sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o 11sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
12 12
13sun8i-drm-hdmi-y += sun8i_dw_hdmi.o
14sun8i-drm-hdmi-y += sun8i_hdmi_phy.o
15
13sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ 16sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \
14 sun8i_vi_layer.o sun8i_ui_scaler.o \ 17 sun8i_vi_layer.o sun8i_ui_scaler.o \
15 sun8i_vi_scaler.o sun8i_csc.o 18 sun8i_vi_scaler.o sun8i_csc.o
@@ -27,4 +30,5 @@ obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o
27 30
28obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o sun4i-frontend.o 31obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o sun4i-frontend.o
29obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o 32obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o
33obj-$(CONFIG_DRM_SUN8I_DW_HDMI) += sun8i-drm-hdmi.o
30obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o 34obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 4b7340ee6290..0d6c5ed44795 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -84,6 +84,7 @@ static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
84 84
85 switch (channel) { 85 switch (channel) {
86 case 0: 86 case 0:
87 WARN_ON(!tcon->quirks->has_channel_0);
87 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, 88 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
88 SUN4I_TCON0_CTL_TCON_ENABLE, 89 SUN4I_TCON0_CTL_TCON_ENABLE,
89 enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0); 90 enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0);
@@ -276,6 +277,8 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
276 u8 clk_delay; 277 u8 clk_delay;
277 u32 reg, val = 0; 278 u32 reg, val = 0;
278 279
280 WARN_ON(!tcon->quirks->has_channel_0);
281
279 tcon->dclk_min_div = 7; 282 tcon->dclk_min_div = 7;
280 tcon->dclk_max_div = 7; 283 tcon->dclk_max_div = 7;
281 sun4i_tcon0_mode_set_common(tcon, mode); 284 sun4i_tcon0_mode_set_common(tcon, mode);
@@ -344,6 +347,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
344 u8 clk_delay; 347 u8 clk_delay;
345 u32 val = 0; 348 u32 val = 0;
346 349
350 WARN_ON(!tcon->quirks->has_channel_0);
351
347 tcon->dclk_min_div = 6; 352 tcon->dclk_min_div = 6;
348 tcon->dclk_max_div = 127; 353 tcon->dclk_max_div = 127;
349 sun4i_tcon0_mode_set_common(tcon, mode); 354 sun4i_tcon0_mode_set_common(tcon, mode);
@@ -389,10 +394,10 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
389 SUN4I_TCON0_BASIC3_H_SYNC(hsync)); 394 SUN4I_TCON0_BASIC3_H_SYNC(hsync));
390 395
391 /* Setup the polarity of the various signals */ 396 /* Setup the polarity of the various signals */
392 if (!(mode->flags & DRM_MODE_FLAG_PHSYNC)) 397 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
393 val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE; 398 val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
394 399
395 if (!(mode->flags & DRM_MODE_FLAG_PVSYNC)) 400 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
396 val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE; 401 val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
397 402
398 regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG, 403 regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
@@ -574,10 +579,12 @@ static int sun4i_tcon_init_clocks(struct device *dev,
574 } 579 }
575 clk_prepare_enable(tcon->clk); 580 clk_prepare_enable(tcon->clk);
576 581
577 tcon->sclk0 = devm_clk_get(dev, "tcon-ch0"); 582 if (tcon->quirks->has_channel_0) {
578 if (IS_ERR(tcon->sclk0)) { 583 tcon->sclk0 = devm_clk_get(dev, "tcon-ch0");
579 dev_err(dev, "Couldn't get the TCON channel 0 clock\n"); 584 if (IS_ERR(tcon->sclk0)) {
580 return PTR_ERR(tcon->sclk0); 585 dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
586 return PTR_ERR(tcon->sclk0);
587 }
581 } 588 }
582 589
583 if (tcon->quirks->has_channel_1) { 590 if (tcon->quirks->has_channel_1) {
@@ -934,10 +941,12 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
934 goto err_free_clocks; 941 goto err_free_clocks;
935 } 942 }
936 943
937 ret = sun4i_dclk_create(dev, tcon); 944 if (tcon->quirks->has_channel_0) {
938 if (ret) { 945 ret = sun4i_dclk_create(dev, tcon);
939 dev_err(dev, "Couldn't create our TCON dot clock\n"); 946 if (ret) {
940 goto err_free_clocks; 947 dev_err(dev, "Couldn't create our TCON dot clock\n");
948 goto err_free_clocks;
949 }
941 } 950 }
942 951
943 ret = sun4i_tcon_init_irq(dev, tcon); 952 ret = sun4i_tcon_init_irq(dev, tcon);
@@ -995,7 +1004,8 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
995 return 0; 1004 return 0;
996 1005
997err_free_dotclock: 1006err_free_dotclock:
998 sun4i_dclk_free(tcon); 1007 if (tcon->quirks->has_channel_0)
1008 sun4i_dclk_free(tcon);
999err_free_clocks: 1009err_free_clocks:
1000 sun4i_tcon_free_clocks(tcon); 1010 sun4i_tcon_free_clocks(tcon);
1001err_assert_reset: 1011err_assert_reset:
@@ -1009,7 +1019,8 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master,
1009 struct sun4i_tcon *tcon = dev_get_drvdata(dev); 1019 struct sun4i_tcon *tcon = dev_get_drvdata(dev);
1010 1020
1011 list_del(&tcon->list); 1021 list_del(&tcon->list);
1012 sun4i_dclk_free(tcon); 1022 if (tcon->quirks->has_channel_0)
1023 sun4i_dclk_free(tcon);
1013 sun4i_tcon_free_clocks(tcon); 1024 sun4i_tcon_free_clocks(tcon);
1014} 1025}
1015 1026
@@ -1106,16 +1117,19 @@ static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
1106} 1117}
1107 1118
1108static const struct sun4i_tcon_quirks sun4i_a10_quirks = { 1119static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
1120 .has_channel_0 = true,
1109 .has_channel_1 = true, 1121 .has_channel_1 = true,
1110 .set_mux = sun4i_a10_tcon_set_mux, 1122 .set_mux = sun4i_a10_tcon_set_mux,
1111}; 1123};
1112 1124
1113static const struct sun4i_tcon_quirks sun5i_a13_quirks = { 1125static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
1126 .has_channel_0 = true,
1114 .has_channel_1 = true, 1127 .has_channel_1 = true,
1115 .set_mux = sun5i_a13_tcon_set_mux, 1128 .set_mux = sun5i_a13_tcon_set_mux,
1116}; 1129};
1117 1130
1118static const struct sun4i_tcon_quirks sun6i_a31_quirks = { 1131static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
1132 .has_channel_0 = true,
1119 .has_channel_1 = true, 1133 .has_channel_1 = true,
1120 .has_lvds_alt = true, 1134 .has_lvds_alt = true,
1121 .needs_de_be_mux = true, 1135 .needs_de_be_mux = true,
@@ -1123,26 +1137,33 @@ static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
1123}; 1137};
1124 1138
1125static const struct sun4i_tcon_quirks sun6i_a31s_quirks = { 1139static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
1140 .has_channel_0 = true,
1126 .has_channel_1 = true, 1141 .has_channel_1 = true,
1127 .needs_de_be_mux = true, 1142 .needs_de_be_mux = true,
1128}; 1143};
1129 1144
1130static const struct sun4i_tcon_quirks sun7i_a20_quirks = { 1145static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
1146 .has_channel_0 = true,
1131 .has_channel_1 = true, 1147 .has_channel_1 = true,
1132 /* Same display pipeline structure as A10 */ 1148 /* Same display pipeline structure as A10 */
1133 .set_mux = sun4i_a10_tcon_set_mux, 1149 .set_mux = sun4i_a10_tcon_set_mux,
1134}; 1150};
1135 1151
1136static const struct sun4i_tcon_quirks sun8i_a33_quirks = { 1152static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
1153 .has_channel_0 = true,
1137 .has_lvds_alt = true, 1154 .has_lvds_alt = true,
1138}; 1155};
1139 1156
1140static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { 1157static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
1141 /* nothing is supported */ 1158 .has_channel_0 = true,
1159};
1160
1161static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
1162 .has_channel_1 = true,
1142}; 1163};
1143 1164
1144static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { 1165static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
1145 /* nothing is supported */ 1166 .has_channel_0 = true,
1146}; 1167};
1147 1168
1148/* sun4i_drv uses this list to check if a device node is a TCON */ 1169/* sun4i_drv uses this list to check if a device node is a TCON */
@@ -1154,6 +1175,7 @@ const struct of_device_id sun4i_tcon_of_table[] = {
1154 { .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks }, 1175 { .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks },
1155 { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks }, 1176 { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
1156 { .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks }, 1177 { .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks },
1178 { .compatible = "allwinner,sun8i-a83t-tcon-tv", .data = &sun8i_a83t_tv_quirks },
1157 { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks }, 1179 { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
1158 { } 1180 { }
1159}; 1181};
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index b761c7b823c5..78d55e7cd2b3 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -172,6 +172,7 @@
172struct sun4i_tcon; 172struct sun4i_tcon;
173 173
174struct sun4i_tcon_quirks { 174struct sun4i_tcon_quirks {
175 bool has_channel_0; /* a83t does not have channel 0 on second TCON */
175 bool has_channel_1; /* a33 does not have channel 1 */ 176 bool has_channel_1; /* a33 does not have channel 1 */
176 bool has_lvds_alt; /* Does the LVDS clock have a parent other than the TCON clock? */ 177 bool has_lvds_alt; /* Does the LVDS clock have a parent other than the TCON clock? */
177 bool needs_de_be_mux; /* sun6i needs mux to select backend */ 178 bool needs_de_be_mux; /* sun6i needs mux to select backend */
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
new file mode 100644
index 000000000000..9f40a44b456b
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -0,0 +1,196 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net>
4 */
5
6#include <linux/component.h>
7#include <linux/module.h>
8#include <linux/platform_device.h>
9
10#include <drm/drm_of.h>
11#include <drm/drmP.h>
12#include <drm/drm_crtc_helper.h>
13
14#include "sun8i_dw_hdmi.h"
15
16static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder *encoder,
17 struct drm_display_mode *mode,
18 struct drm_display_mode *adj_mode)
19{
20 struct sun8i_dw_hdmi *hdmi = encoder_to_sun8i_dw_hdmi(encoder);
21
22 clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000);
23}
24
25static const struct drm_encoder_helper_funcs
26sun8i_dw_hdmi_encoder_helper_funcs = {
27 .mode_set = sun8i_dw_hdmi_encoder_mode_set,
28};
29
30static const struct drm_encoder_funcs sun8i_dw_hdmi_encoder_funcs = {
31 .destroy = drm_encoder_cleanup,
32};
33
34static enum drm_mode_status
35sun8i_dw_hdmi_mode_valid(struct drm_connector *connector,
36 const struct drm_display_mode *mode)
37{
38 if (mode->clock > 297000)
39 return MODE_CLOCK_HIGH;
40
41 return MODE_OK;
42}
43
44static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
45 void *data)
46{
47 struct platform_device *pdev = to_platform_device(dev);
48 struct dw_hdmi_plat_data *plat_data;
49 struct drm_device *drm = data;
50 struct device_node *phy_node;
51 struct drm_encoder *encoder;
52 struct sun8i_dw_hdmi *hdmi;
53 int ret;
54
55 if (!pdev->dev.of_node)
56 return -ENODEV;
57
58 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
59 if (!hdmi)
60 return -ENOMEM;
61
62 plat_data = &hdmi->plat_data;
63 hdmi->dev = &pdev->dev;
64 encoder = &hdmi->encoder;
65
66 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
67 /*
68 * If we failed to find the CRTC(s) which this encoder is
69 * supposed to be connected to, it's because the CRTC has
70 * not been registered yet. Defer probing, and hope that
71 * the required CRTC is added later.
72 */
73 if (encoder->possible_crtcs == 0)
74 return -EPROBE_DEFER;
75
76 hdmi->rst_ctrl = devm_reset_control_get(dev, "ctrl");
77 if (IS_ERR(hdmi->rst_ctrl)) {
78 dev_err(dev, "Could not get ctrl reset control\n");
79 return PTR_ERR(hdmi->rst_ctrl);
80 }
81
82 hdmi->clk_tmds = devm_clk_get(dev, "tmds");
83 if (IS_ERR(hdmi->clk_tmds)) {
84 dev_err(dev, "Couldn't get the tmds clock\n");
85 return PTR_ERR(hdmi->clk_tmds);
86 }
87
88 ret = reset_control_deassert(hdmi->rst_ctrl);
89 if (ret) {
90 dev_err(dev, "Could not deassert ctrl reset control\n");
91 return ret;
92 }
93
94 ret = clk_prepare_enable(hdmi->clk_tmds);
95 if (ret) {
96 dev_err(dev, "Could not enable tmds clock\n");
97 goto err_assert_ctrl_reset;
98 }
99
100 phy_node = of_parse_phandle(dev->of_node, "phys", 0);
101 if (!phy_node) {
102 dev_err(dev, "Can't found PHY phandle\n");
103 goto err_disable_clk_tmds;
104 }
105
106 ret = sun8i_hdmi_phy_probe(hdmi, phy_node);
107 of_node_put(phy_node);
108 if (ret) {
109 dev_err(dev, "Couldn't get the HDMI PHY\n");
110 goto err_disable_clk_tmds;
111 }
112
113 drm_encoder_helper_add(encoder, &sun8i_dw_hdmi_encoder_helper_funcs);
114 drm_encoder_init(drm, encoder, &sun8i_dw_hdmi_encoder_funcs,
115 DRM_MODE_ENCODER_TMDS, NULL);
116
117 sun8i_hdmi_phy_init(hdmi->phy);
118
119 plat_data->mode_valid = &sun8i_dw_hdmi_mode_valid;
120 plat_data->phy_ops = sun8i_hdmi_phy_get_ops();
121 plat_data->phy_name = "sun8i_dw_hdmi_phy";
122 plat_data->phy_data = hdmi->phy;
123
124 platform_set_drvdata(pdev, hdmi);
125
126 hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
127
128 /*
129 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
130 * which would have called the encoder cleanup. Do it manually.
131 */
132 if (IS_ERR(hdmi->hdmi)) {
133 ret = PTR_ERR(hdmi->hdmi);
134 goto cleanup_encoder;
135 }
136
137 return 0;
138
139cleanup_encoder:
140 drm_encoder_cleanup(encoder);
141 sun8i_hdmi_phy_remove(hdmi);
142err_disable_clk_tmds:
143 clk_disable_unprepare(hdmi->clk_tmds);
144err_assert_ctrl_reset:
145 reset_control_assert(hdmi->rst_ctrl);
146
147 return ret;
148}
149
150static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master,
151 void *data)
152{
153 struct sun8i_dw_hdmi *hdmi = dev_get_drvdata(dev);
154
155 dw_hdmi_unbind(hdmi->hdmi);
156 sun8i_hdmi_phy_remove(hdmi);
157 clk_disable_unprepare(hdmi->clk_tmds);
158 reset_control_assert(hdmi->rst_ctrl);
159}
160
161static const struct component_ops sun8i_dw_hdmi_ops = {
162 .bind = sun8i_dw_hdmi_bind,
163 .unbind = sun8i_dw_hdmi_unbind,
164};
165
166static int sun8i_dw_hdmi_probe(struct platform_device *pdev)
167{
168 return component_add(&pdev->dev, &sun8i_dw_hdmi_ops);
169}
170
171static int sun8i_dw_hdmi_remove(struct platform_device *pdev)
172{
173 component_del(&pdev->dev, &sun8i_dw_hdmi_ops);
174
175 return 0;
176}
177
178static const struct of_device_id sun8i_dw_hdmi_dt_ids[] = {
179 { .compatible = "allwinner,sun8i-a83t-dw-hdmi" },
180 { /* sentinel */ },
181};
182MODULE_DEVICE_TABLE(of, sun8i_dw_hdmi_dt_ids);
183
184struct platform_driver sun8i_dw_hdmi_pltfm_driver = {
185 .probe = sun8i_dw_hdmi_probe,
186 .remove = sun8i_dw_hdmi_remove,
187 .driver = {
188 .name = "sun8i-dw-hdmi",
189 .of_match_table = sun8i_dw_hdmi_dt_ids,
190 },
191};
192module_platform_driver(sun8i_dw_hdmi_pltfm_driver);
193
194MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>");
195MODULE_DESCRIPTION("Allwinner DW HDMI bridge");
196MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
new file mode 100644
index 000000000000..d8d0684fc8aa
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -0,0 +1,44 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Copyright (C) 2018 Jernej Skrabec <jernej.skrabec@siol.net>
4 */
5
6#ifndef _SUN8I_DW_HDMI_H_
7#define _SUN8I_DW_HDMI_H_
8
9#include <drm/bridge/dw_hdmi.h>
10#include <drm/drm_encoder.h>
11#include <linux/clk.h>
12#include <linux/regmap.h>
13#include <linux/reset.h>
14
15struct sun8i_hdmi_phy {
16 struct clk *clk_bus;
17 struct clk *clk_mod;
18 struct regmap *regs;
19 struct reset_control *rst_phy;
20};
21
22struct sun8i_dw_hdmi {
23 struct clk *clk_tmds;
24 struct device *dev;
25 struct dw_hdmi *hdmi;
26 struct drm_encoder encoder;
27 struct sun8i_hdmi_phy *phy;
28 struct dw_hdmi_plat_data plat_data;
29 struct reset_control *rst_ctrl;
30};
31
32static inline struct sun8i_dw_hdmi *
33encoder_to_sun8i_dw_hdmi(struct drm_encoder *encoder)
34{
35 return container_of(encoder, struct sun8i_dw_hdmi, encoder);
36}
37
38int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node);
39void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi);
40
41void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
42const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
43
44#endif /* _SUN8I_DW_HDMI_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
new file mode 100644
index 000000000000..e5bfcdd43ec9
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -0,0 +1,270 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net>
4 */
5
6#include <linux/of_address.h>
7
8#include "sun8i_dw_hdmi.h"
9
10#define SUN8I_HDMI_PHY_DBG_CTRL_REG 0x0000
11#define SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK BIT(0)
12#define SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK GENMASK(15, 8)
13#define SUN8I_HDMI_PHY_DBG_CTRL_POL(val) (val << 8)
14#define SUN8I_HDMI_PHY_DBG_CTRL_ADDR_MASK GENMASK(23, 16)
15#define SUN8I_HDMI_PHY_DBG_CTRL_ADDR(addr) (addr << 16)
16
17#define SUN8I_HDMI_PHY_REXT_CTRL_REG 0x0004
18#define SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN BIT(31)
19
20#define SUN8I_HDMI_PHY_READ_EN_REG 0x0010
21#define SUN8I_HDMI_PHY_READ_EN_MAGIC 0x54524545
22
23#define SUN8I_HDMI_PHY_UNSCRAMBLE_REG 0x0014
24#define SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC 0x42494E47
25
26/*
27 * Address can be actually any value. Here is set to same value as
28 * it is set in BSP driver.
29 */
30#define I2C_ADDR 0x69
31
32static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
33 struct drm_display_mode *mode)
34{
35 struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data;
36 u32 val = 0;
37
38 if ((mode->flags & DRM_MODE_FLAG_NHSYNC) &&
39 (mode->flags & DRM_MODE_FLAG_NHSYNC)) {
40 val = 0x03;
41 }
42
43 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
44 SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK,
45 SUN8I_HDMI_PHY_DBG_CTRL_POL(val));
46
47 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG,
48 SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN,
49 SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN);
50
51 /* power down */
52 dw_hdmi_phy_gen2_txpwron(hdmi, 0);
53 dw_hdmi_phy_gen2_pddq(hdmi, 1);
54
55 dw_hdmi_phy_reset(hdmi);
56
57 dw_hdmi_phy_gen2_pddq(hdmi, 0);
58
59 dw_hdmi_phy_i2c_set_addr(hdmi, I2C_ADDR);
60
61 /*
62 * Values are taken from BSP HDMI driver. Although AW didn't
63 * release any documentation, explanation of this values can
64 * be found in i.MX 6Dual/6Quad Reference Manual.
65 */
66 if (mode->crtc_clock <= 27000) {
67 dw_hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06);
68 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
69 dw_hdmi_phy_i2c_write(hdmi, 0x08da, 0x10);
70 dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19);
71 dw_hdmi_phy_i2c_write(hdmi, 0x0318, 0x0e);
72 dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09);
73 } else if (mode->crtc_clock <= 74250) {
74 dw_hdmi_phy_i2c_write(hdmi, 0x0540, 0x06);
75 dw_hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
76 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10);
77 dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19);
78 dw_hdmi_phy_i2c_write(hdmi, 0x02b5, 0x0e);
79 dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09);
80 } else if (mode->crtc_clock <= 148500) {
81 dw_hdmi_phy_i2c_write(hdmi, 0x04a0, 0x06);
82 dw_hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
83 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10);
84 dw_hdmi_phy_i2c_write(hdmi, 0x0002, 0x19);
85 dw_hdmi_phy_i2c_write(hdmi, 0x0021, 0x0e);
86 dw_hdmi_phy_i2c_write(hdmi, 0x8029, 0x09);
87 } else {
88 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x06);
89 dw_hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
90 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10);
91 dw_hdmi_phy_i2c_write(hdmi, 0x0002, 0x19);
92 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x0e);
93 dw_hdmi_phy_i2c_write(hdmi, 0x802b, 0x09);
94 }
95
96 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x1e);
97 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x13);
98 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x17);
99
100 dw_hdmi_phy_gen2_txpwron(hdmi, 1);
101
102 return 0;
103};
104
105static void sun8i_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
106{
107 struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data;
108
109 dw_hdmi_phy_gen2_txpwron(hdmi, 0);
110 dw_hdmi_phy_gen2_pddq(hdmi, 1);
111
112 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG,
113 SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, 0);
114}
115
116static const struct dw_hdmi_phy_ops sun8i_hdmi_phy_ops = {
117 .init = &sun8i_hdmi_phy_config,
118 .disable = &sun8i_hdmi_phy_disable,
119 .read_hpd = &dw_hdmi_phy_read_hpd,
120 .update_hpd = &dw_hdmi_phy_update_hpd,
121 .setup_hpd = &dw_hdmi_phy_setup_hpd,
122};
123
124void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
125{
126 /* enable read access to HDMI controller */
127 regmap_write(phy->regs, SUN8I_HDMI_PHY_READ_EN_REG,
128 SUN8I_HDMI_PHY_READ_EN_MAGIC);
129
130 /* unscramble register offsets */
131 regmap_write(phy->regs, SUN8I_HDMI_PHY_UNSCRAMBLE_REG,
132 SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC);
133
134 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
135 SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK,
136 SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK);
137
138 /*
139 * Set PHY I2C address. It must match to the address set by
140 * dw_hdmi_phy_set_slave_addr().
141 */
142 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
143 SUN8I_HDMI_PHY_DBG_CTRL_ADDR_MASK,
144 SUN8I_HDMI_PHY_DBG_CTRL_ADDR(I2C_ADDR));
145}
146
147const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void)
148{
149 return &sun8i_hdmi_phy_ops;
150}
151
152static struct regmap_config sun8i_hdmi_phy_regmap_config = {
153 .reg_bits = 32,
154 .val_bits = 32,
155 .reg_stride = 4,
156 .max_register = SUN8I_HDMI_PHY_UNSCRAMBLE_REG,
157 .name = "phy"
158};
159
160static const struct of_device_id sun8i_hdmi_phy_of_table[] = {
161 { .compatible = "allwinner,sun8i-a83t-hdmi-phy" },
162 { /* sentinel */ }
163};
164
165int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
166{
167 struct device *dev = hdmi->dev;
168 struct sun8i_hdmi_phy *phy;
169 struct resource res;
170 void __iomem *regs;
171 int ret;
172
173 if (!of_match_node(sun8i_hdmi_phy_of_table, node)) {
174 dev_err(dev, "Incompatible HDMI PHY\n");
175 return -EINVAL;
176 }
177
178 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
179 if (!phy)
180 return -ENOMEM;
181
182 ret = of_address_to_resource(node, 0, &res);
183 if (ret) {
184 dev_err(dev, "phy: Couldn't get our resources\n");
185 return ret;
186 }
187
188 regs = devm_ioremap_resource(dev, &res);
189 if (IS_ERR(regs)) {
190 dev_err(dev, "Couldn't map the HDMI PHY registers\n");
191 return PTR_ERR(regs);
192 }
193
194 phy->regs = devm_regmap_init_mmio(dev, regs,
195 &sun8i_hdmi_phy_regmap_config);
196 if (IS_ERR(phy->regs)) {
197 dev_err(dev, "Couldn't create the HDMI PHY regmap\n");
198 return PTR_ERR(phy->regs);
199 }
200
201 phy->clk_bus = of_clk_get_by_name(node, "bus");
202 if (IS_ERR(phy->clk_bus)) {
203 dev_err(dev, "Could not get bus clock\n");
204 return PTR_ERR(phy->clk_bus);
205 }
206
207 phy->clk_mod = of_clk_get_by_name(node, "mod");
208 if (IS_ERR(phy->clk_mod)) {
209 dev_err(dev, "Could not get mod clock\n");
210 ret = PTR_ERR(phy->clk_mod);
211 goto err_put_clk_bus;
212 }
213
214 phy->rst_phy = of_reset_control_get_shared(node, "phy");
215 if (IS_ERR(phy->rst_phy)) {
216 dev_err(dev, "Could not get phy reset control\n");
217 ret = PTR_ERR(phy->rst_phy);
218 goto err_put_clk_mod;
219 }
220
221 ret = reset_control_deassert(phy->rst_phy);
222 if (ret) {
223 dev_err(dev, "Cannot deassert phy reset control: %d\n", ret);
224 goto err_put_rst_phy;
225 }
226
227 ret = clk_prepare_enable(phy->clk_bus);
228 if (ret) {
229 dev_err(dev, "Cannot enable bus clock: %d\n", ret);
230 goto err_deassert_rst_phy;
231 }
232
233 ret = clk_prepare_enable(phy->clk_mod);
234 if (ret) {
235 dev_err(dev, "Cannot enable mod clock: %d\n", ret);
236 goto err_disable_clk_bus;
237 }
238
239 hdmi->phy = phy;
240
241 return 0;
242
243err_disable_clk_bus:
244 clk_disable_unprepare(phy->clk_bus);
245err_deassert_rst_phy:
246 reset_control_assert(phy->rst_phy);
247err_put_rst_phy:
248 reset_control_put(phy->rst_phy);
249err_put_clk_mod:
250 clk_put(phy->clk_mod);
251err_put_clk_bus:
252 clk_put(phy->clk_bus);
253
254 return ret;
255}
256
257void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
258{
259 struct sun8i_hdmi_phy *phy = hdmi->phy;
260
261 clk_disable_unprepare(phy->clk_mod);
262 clk_disable_unprepare(phy->clk_bus);
263
264 reset_control_assert(phy->rst_phy);
265
266 reset_control_put(phy->rst_phy);
267
268 clk_put(phy->clk_mod);
269 clk_put(phy->clk_bus);
270}
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 2cbb2de6d39c..9b0256d31a61 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -485,6 +485,13 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
485 .vi_num = 1, 485 .vi_num = 1,
486}; 486};
487 487
488static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
489 .ccsc = 1,
490 .scaler_mask = 0x3,
491 .ui_num = 1,
492 .vi_num = 1,
493};
494
488static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { 495static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
489 .vi_num = 2, 496 .vi_num = 2,
490 .ui_num = 1, 497 .ui_num = 1,
@@ -499,6 +506,10 @@ static const struct of_device_id sun8i_mixer_of_table[] = {
499 .data = &sun8i_a83t_mixer0_cfg, 506 .data = &sun8i_a83t_mixer0_cfg,
500 }, 507 },
501 { 508 {
509 .compatible = "allwinner,sun8i-a83t-de2-mixer-1",
510 .data = &sun8i_a83t_mixer1_cfg,
511 },
512 {
502 .compatible = "allwinner,sun8i-v3s-de2-mixer", 513 .compatible = "allwinner,sun8i-v3s-de2-mixer",
503 .data = &sun8i_v3s_mixer_cfg, 514 .data = &sun8i_v3s_mixer_cfg,
504 }, 515 },
diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig
index b0e567d416b3..13339be843bc 100644
--- a/drivers/gpu/drm/tinydrm/Kconfig
+++ b/drivers/gpu/drm/tinydrm/Kconfig
@@ -3,8 +3,6 @@ menuconfig DRM_TINYDRM
3 depends on DRM 3 depends on DRM
4 select DRM_KMS_HELPER 4 select DRM_KMS_HELPER
5 select DRM_KMS_CMA_HELPER 5 select DRM_KMS_CMA_HELPER
6 select BACKLIGHT_LCD_SUPPORT
7 select BACKLIGHT_CLASS_DEVICE
8 help 6 help
9 Choose this option if you have a tinydrm supported display. 7 Choose this option if you have a tinydrm supported display.
10 If M is selected the module will be called tinydrm. 8 If M is selected the module will be called tinydrm.
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
index bf96072d1b97..d1c3ce9ab294 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c
@@ -236,101 +236,6 @@ void tinydrm_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
236} 236}
237EXPORT_SYMBOL(tinydrm_xrgb8888_to_gray8); 237EXPORT_SYMBOL(tinydrm_xrgb8888_to_gray8);
238 238
239/**
240 * tinydrm_of_find_backlight - Find backlight device in device-tree
241 * @dev: Device
242 *
243 * This function looks for a DT node pointed to by a property named 'backlight'
244 * and uses of_find_backlight_by_node() to get the backlight device.
245 * Additionally if the brightness property is zero, it is set to
246 * max_brightness.
247 *
248 * Returns:
249 * NULL if there's no backlight property.
250 * Error pointer -EPROBE_DEFER if the DT node is found, but no backlight device
251 * is found.
252 * If the backlight device is found, a pointer to the structure is returned.
253 */
254struct backlight_device *tinydrm_of_find_backlight(struct device *dev)
255{
256 struct backlight_device *backlight;
257 struct device_node *np;
258
259 np = of_parse_phandle(dev->of_node, "backlight", 0);
260 if (!np)
261 return NULL;
262
263 backlight = of_find_backlight_by_node(np);
264 of_node_put(np);
265
266 if (!backlight)
267 return ERR_PTR(-EPROBE_DEFER);
268
269 if (!backlight->props.brightness) {
270 backlight->props.brightness = backlight->props.max_brightness;
271 DRM_DEBUG_KMS("Backlight brightness set to %d\n",
272 backlight->props.brightness);
273 }
274
275 return backlight;
276}
277EXPORT_SYMBOL(tinydrm_of_find_backlight);
278
279/**
280 * tinydrm_enable_backlight - Enable backlight helper
281 * @backlight: Backlight device
282 *
283 * Returns:
284 * Zero on success, negative error code on failure.
285 */
286int tinydrm_enable_backlight(struct backlight_device *backlight)
287{
288 unsigned int old_state;
289 int ret;
290
291 if (!backlight)
292 return 0;
293
294 old_state = backlight->props.state;
295 backlight->props.state &= ~BL_CORE_FBBLANK;
296 DRM_DEBUG_KMS("Backlight state: 0x%x -> 0x%x\n", old_state,
297 backlight->props.state);
298
299 ret = backlight_update_status(backlight);
300 if (ret)
301 DRM_ERROR("Failed to enable backlight %d\n", ret);
302
303 return ret;
304}
305EXPORT_SYMBOL(tinydrm_enable_backlight);
306
307/**
308 * tinydrm_disable_backlight - Disable backlight helper
309 * @backlight: Backlight device
310 *
311 * Returns:
312 * Zero on success, negative error code on failure.
313 */
314int tinydrm_disable_backlight(struct backlight_device *backlight)
315{
316 unsigned int old_state;
317 int ret;
318
319 if (!backlight)
320 return 0;
321
322 old_state = backlight->props.state;
323 backlight->props.state |= BL_CORE_FBBLANK;
324 DRM_DEBUG_KMS("Backlight state: 0x%x -> 0x%x\n", old_state,
325 backlight->props.state);
326 ret = backlight_update_status(backlight);
327 if (ret)
328 DRM_ERROR("Failed to disable backlight %d\n", ret);
329
330 return ret;
331}
332EXPORT_SYMBOL(tinydrm_disable_backlight);
333
334#if IS_ENABLED(CONFIG_SPI) 239#if IS_ENABLED(CONFIG_SPI)
335 240
336/** 241/**
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
index 79cb5af5abac..d8ed6e6f8e05 100644
--- a/drivers/gpu/drm/tinydrm/mi0283qt.c
+++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
@@ -9,6 +9,7 @@
9 * (at your option) any later version. 9 * (at your option) any later version.
10 */ 10 */
11 11
12#include <linux/backlight.h>
12#include <linux/delay.h> 13#include <linux/delay.h>
13#include <linux/gpio/consumer.h> 14#include <linux/gpio/consumer.h>
14#include <linux/module.h> 15#include <linux/module.h>
@@ -195,7 +196,7 @@ static int mi0283qt_probe(struct spi_device *spi)
195 if (IS_ERR(mipi->regulator)) 196 if (IS_ERR(mipi->regulator))
196 return PTR_ERR(mipi->regulator); 197 return PTR_ERR(mipi->regulator);
197 198
198 mipi->backlight = tinydrm_of_find_backlight(dev); 199 mipi->backlight = devm_of_find_backlight(dev);
199 if (IS_ERR(mipi->backlight)) 200 if (IS_ERR(mipi->backlight))
200 return PTR_ERR(mipi->backlight); 201 return PTR_ERR(mipi->backlight);
201 202
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c
index 75dd65c57e74..9e903812b573 100644
--- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
+++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
@@ -286,7 +286,7 @@ void mipi_dbi_enable_flush(struct mipi_dbi *mipi)
286 if (fb) 286 if (fb)
287 fb->funcs->dirty(fb, NULL, 0, 0, NULL, 0); 287 fb->funcs->dirty(fb, NULL, 0, 0, NULL, 0);
288 288
289 tinydrm_enable_backlight(mipi->backlight); 289 backlight_enable(mipi->backlight);
290} 290}
291EXPORT_SYMBOL(mipi_dbi_enable_flush); 291EXPORT_SYMBOL(mipi_dbi_enable_flush);
292 292
@@ -325,7 +325,7 @@ void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe)
325 mipi->enabled = false; 325 mipi->enabled = false;
326 326
327 if (mipi->backlight) 327 if (mipi->backlight)
328 tinydrm_disable_backlight(mipi->backlight); 328 backlight_disable(mipi->backlight);
329 else 329 else
330 mipi_dbi_blank(mipi); 330 mipi_dbi_blank(mipi);
331 331
diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c
index 08b4fb18edb6..67d197ecfc4b 100644
--- a/drivers/gpu/drm/tinydrm/st7735r.c
+++ b/drivers/gpu/drm/tinydrm/st7735r.c
@@ -5,6 +5,7 @@
5 * Copyright 2017 David Lechner <david@lechnology.com> 5 * Copyright 2017 David Lechner <david@lechnology.com>
6 */ 6 */
7 7
8#include <linux/backlight.h>
8#include <linux/delay.h> 9#include <linux/delay.h>
9#include <linux/dma-buf.h> 10#include <linux/dma-buf.h>
10#include <linux/gpio/consumer.h> 11#include <linux/gpio/consumer.h>
@@ -163,7 +164,7 @@ static int st7735r_probe(struct spi_device *spi)
163 return PTR_ERR(dc); 164 return PTR_ERR(dc);
164 } 165 }
165 166
166 mipi->backlight = tinydrm_of_find_backlight(dev); 167 mipi->backlight = devm_of_find_backlight(dev);
167 if (IS_ERR(mipi->backlight)) 168 if (IS_ERR(mipi->backlight))
168 return PTR_ERR(mipi->backlight); 169 return PTR_ERR(mipi->backlight);
169 170
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 8049e7656daa..deb824bef6e2 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -580,6 +580,79 @@ struct backlight_device *of_find_backlight_by_node(struct device_node *node)
580EXPORT_SYMBOL(of_find_backlight_by_node); 580EXPORT_SYMBOL(of_find_backlight_by_node);
581#endif 581#endif
582 582
583/**
584 * of_find_backlight - Get backlight device
585 * @dev: Device
586 *
587 * This function looks for a property named 'backlight' on the DT node
588 * connected to @dev and looks up the backlight device.
589 *
590 * Call backlight_put() to drop the reference on the backlight device.
591 *
592 * Returns:
593 * A pointer to the backlight device if found.
594 * Error pointer -EPROBE_DEFER if the DT property is set, but no backlight
595 * device is found.
596 * NULL if there's no backlight property.
597 */
598struct backlight_device *of_find_backlight(struct device *dev)
599{
600 struct backlight_device *bd = NULL;
601 struct device_node *np;
602
603 if (!dev)
604 return NULL;
605
606 if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
607 np = of_parse_phandle(dev->of_node, "backlight", 0);
608 if (np) {
609 bd = of_find_backlight_by_node(np);
610 of_node_put(np);
611 if (!bd)
612 return ERR_PTR(-EPROBE_DEFER);
613 /*
614 * Note: gpio_backlight uses brightness as
615 * power state during probe
616 */
617 if (!bd->props.brightness)
618 bd->props.brightness = bd->props.max_brightness;
619 }
620 }
621
622 return bd;
623}
624EXPORT_SYMBOL(of_find_backlight);
625
626static void devm_backlight_release(void *data)
627{
628 backlight_put(data);
629}
630
631/**
632 * devm_of_find_backlight - Resource-managed of_find_backlight()
633 * @dev: Device
634 *
635 * Device managed version of of_find_backlight().
636 * The reference on the backlight device is automatically
637 * dropped on driver detach.
638 */
639struct backlight_device *devm_of_find_backlight(struct device *dev)
640{
641 struct backlight_device *bd;
642 int ret;
643
644 bd = of_find_backlight(dev);
645 if (IS_ERR_OR_NULL(bd))
646 return bd;
647 ret = devm_add_action(dev, devm_backlight_release, bd);
648 if (ret) {
649 backlight_put(bd);
650 return ERR_PTR(ret);
651 }
652 return bd;
653}
654EXPORT_SYMBOL(devm_of_find_backlight);
655
583static void __exit backlight_class_exit(void) 656static void __exit backlight_class_exit(void)
584{ 657{
585 class_destroy(backlight_class); 658 class_destroy(backlight_class);
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 182f83283e24..dd2a8cf7d20b 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -143,12 +143,13 @@ struct dw_hdmi_plat_data {
143 unsigned long mpixelclock); 143 unsigned long mpixelclock);
144}; 144};
145 145
146int dw_hdmi_probe(struct platform_device *pdev, 146struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
147 const struct dw_hdmi_plat_data *plat_data); 147 const struct dw_hdmi_plat_data *plat_data);
148void dw_hdmi_remove(struct platform_device *pdev); 148void dw_hdmi_remove(struct dw_hdmi *hdmi);
149void dw_hdmi_unbind(struct device *dev); 149void dw_hdmi_unbind(struct dw_hdmi *hdmi);
150int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, 150struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
151 const struct dw_hdmi_plat_data *plat_data); 151 struct drm_encoder *encoder,
152 const struct dw_hdmi_plat_data *plat_data);
152 153
153void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense); 154void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense);
154 155
@@ -157,7 +158,18 @@ void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
157void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); 158void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
158 159
159/* PHY configuration */ 160/* PHY configuration */
161void dw_hdmi_phy_i2c_set_addr(struct dw_hdmi *hdmi, u8 address);
160void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, 162void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
161 unsigned char addr); 163 unsigned char addr);
162 164
165void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable);
166void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable);
167void dw_hdmi_phy_reset(struct dw_hdmi *hdmi);
168
169enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
170 void *data);
171void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data,
172 bool force, bool disabled, bool rxsense);
173void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data);
174
163#endif /* __IMX_HDMI_H__ */ 175#endif /* __IMX_HDMI_H__ */
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 758a176e7b57..675cc3f8cf85 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -342,7 +342,11 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
342/** 342/**
343 * struct drm_tv_connector_state - TV connector related states 343 * struct drm_tv_connector_state - TV connector related states
344 * @subconnector: selected subconnector 344 * @subconnector: selected subconnector
345 * @margins: left/right/top/bottom margins 345 * @margins: margins
346 * @margins.left: left margin
347 * @margins.right: right margin
348 * @margins.top: top margin
349 * @margins.bottom: bottom margin
346 * @mode: TV mode 350 * @mode: TV mode
347 * @brightness: brightness in percent 351 * @brightness: brightness in percent
348 * @contrast: contrast in percent 352 * @contrast: contrast in percent
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index c239e6e24a10..4de97e94ef9d 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -329,6 +329,13 @@
329# define DP_DS_12BPC 2 329# define DP_DS_12BPC 2
330# define DP_DS_16BPC 3 330# define DP_DS_16BPC 3
331 331
332/* DP Forward error Correction Registers */
333#define DP_FEC_CAPABILITY 0x090 /* 1.4 */
334# define DP_FEC_CAPABLE (1 << 0)
335# define DP_FEC_UNCORR_BLK_ERROR_COUNT_CAP (1 << 1)
336# define DP_FEC_CORR_BLK_ERROR_COUNT_CAP (1 << 2)
337# define DP_FEC_BIT_ERROR_COUNT_CAP (1 << 3)
338
332/* link configuration */ 339/* link configuration */
333#define DP_LINK_BW_SET 0x100 340#define DP_LINK_BW_SET 0x100
334# define DP_LINK_RATE_TABLE 0x00 /* eDP 1.4 */ 341# define DP_LINK_RATE_TABLE 0x00 /* eDP 1.4 */
@@ -445,6 +452,19 @@
445#define DP_UPSTREAM_DEVICE_DP_PWR_NEED 0x118 /* 1.2 */ 452#define DP_UPSTREAM_DEVICE_DP_PWR_NEED 0x118 /* 1.2 */
446# define DP_PWR_NOT_NEEDED (1 << 0) 453# define DP_PWR_NOT_NEEDED (1 << 0)
447 454
455#define DP_FEC_CONFIGURATION 0x120 /* 1.4 */
456# define DP_FEC_READY (1 << 0)
457# define DP_FEC_ERR_COUNT_SEL_MASK (7 << 1)
458# define DP_FEC_ERR_COUNT_DIS (0 << 1)
459# define DP_FEC_UNCORR_BLK_ERROR_COUNT (1 << 1)
460# define DP_FEC_CORR_BLK_ERROR_COUNT (2 << 1)
461# define DP_FEC_BIT_ERROR_COUNT (3 << 1)
462# define DP_FEC_LANE_SELECT_MASK (3 << 4)
463# define DP_FEC_LANE_0_SELECT (0 << 4)
464# define DP_FEC_LANE_1_SELECT (1 << 4)
465# define DP_FEC_LANE_2_SELECT (2 << 4)
466# define DP_FEC_LANE_3_SELECT (3 << 4)
467
448#define DP_AUX_FRAME_SYNC_VALUE 0x15c /* eDP 1.4 */ 468#define DP_AUX_FRAME_SYNC_VALUE 0x15c /* eDP 1.4 */
449# define DP_AUX_FRAME_SYNC_VALID (1 << 0) 469# define DP_AUX_FRAME_SYNC_VALID (1 << 0)
450 470
@@ -620,6 +640,16 @@
620#define DP_TEST_SINK 0x270 640#define DP_TEST_SINK 0x270
621# define DP_TEST_SINK_START (1 << 0) 641# define DP_TEST_SINK_START (1 << 0)
622 642
643#define DP_FEC_STATUS 0x280 /* 1.4 */
644# define DP_FEC_DECODE_EN_DETECTED (1 << 0)
645# define DP_FEC_DECODE_DIS_DETECTED (1 << 1)
646
647#define DP_FEC_ERROR_COUNT_LSB 0x0281 /* 1.4 */
648
649#define DP_FEC_ERROR_COUNT_MSB 0x0282 /* 1.4 */
650# define DP_FEC_ERROR_COUNT_MASK 0x7F
651# define DP_FEC_ERR_COUNT_VALID (1 << 7)
652
623#define DP_PAYLOAD_TABLE_UPDATE_STATUS 0x2c0 /* 1.2 MST */ 653#define DP_PAYLOAD_TABLE_UPDATE_STATUS 0x2c0 /* 1.2 MST */
624# define DP_PAYLOAD_TABLE_UPDATED (1 << 0) 654# define DP_PAYLOAD_TABLE_UPDATED (1 << 0)
625# define DP_PAYLOAD_ACT_HANDLED (1 << 1) 655# define DP_PAYLOAD_ACT_HANDLED (1 << 1)
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h
index 6d9adbb46293..d9e4c3c3f009 100644
--- a/include/drm/drm_simple_kms_helper.h
+++ b/include/drm/drm_simple_kms_helper.h
@@ -22,6 +22,20 @@ struct drm_simple_display_pipe;
22 */ 22 */
23struct drm_simple_display_pipe_funcs { 23struct drm_simple_display_pipe_funcs {
24 /** 24 /**
25 * @mode_valid:
26 *
27 * This function is called to filter out valid modes from the
28 * suggestions suggested by the bridge or display. This optional
29 * hook is passed in when initializing the pipeline.
30 *
31 * RETURNS:
32 *
33 * drm_mode_status Enum
34 */
35 enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
36 const struct drm_display_mode *mode);
37
38 /**
25 * @enable: 39 * @enable:
26 * 40 *
27 * This function should be used to enable the pipeline. 41 * This function should be used to enable the pipeline.
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
index 848b463a0af5..425ad80ed2ac 100644
--- a/include/drm/drm_vblank.h
+++ b/include/drm/drm_vblank.h
@@ -55,8 +55,24 @@ struct drm_pending_vblank_event {
55 * @event: Actual event which will be sent to userspace. 55 * @event: Actual event which will be sent to userspace.
56 */ 56 */
57 union { 57 union {
58 /**
59 * @event.base: DRM event base class.
60 */
58 struct drm_event base; 61 struct drm_event base;
62
63 /**
64 * @event.vbl:
65 *
66 * Event payload for vblank events, requested through
67 * either the MODE_PAGE_FLIP or MODE_ATOMIC IOCTL. Also
68 * generated by the legacy WAIT_VBLANK IOCTL, but new userspace
69 * should use MODE_QUEUE_SEQUENCE and &event.seq instead.
70 */
59 struct drm_event_vblank vbl; 71 struct drm_event_vblank vbl;
72
73 /**
74 * @event.seq: Event payload for the MODE_QUEUEU_SEQUENCE IOCTL.
75 */
60 struct drm_event_crtc_sequence seq; 76 struct drm_event_crtc_sequence seq;
61 } event; 77 } event;
62}; 78};
diff --git a/include/drm/tinydrm/tinydrm-helpers.h b/include/drm/tinydrm/tinydrm-helpers.h
index d554ded60ee9..0a4ddbc04c60 100644
--- a/include/drm/tinydrm/tinydrm-helpers.h
+++ b/include/drm/tinydrm/tinydrm-helpers.h
@@ -46,10 +46,6 @@ void tinydrm_xrgb8888_to_rgb565(u16 *dst, void *vaddr,
46void tinydrm_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb, 46void tinydrm_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb,
47 struct drm_clip_rect *clip); 47 struct drm_clip_rect *clip);
48 48
49struct backlight_device *tinydrm_of_find_backlight(struct device *dev);
50int tinydrm_enable_backlight(struct backlight_device *backlight);
51int tinydrm_disable_backlight(struct backlight_device *backlight);
52
53size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len); 49size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len);
54bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw); 50bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw);
55int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz, 51int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz,
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index af7003548593..2baab6f3861d 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -130,6 +130,48 @@ static inline int backlight_update_status(struct backlight_device *bd)
130 return ret; 130 return ret;
131} 131}
132 132
133/**
134 * backlight_enable - Enable backlight
135 * @bd: the backlight device to enable
136 */
137static inline int backlight_enable(struct backlight_device *bd)
138{
139 if (!bd)
140 return 0;
141
142 bd->props.power = FB_BLANK_UNBLANK;
143 bd->props.fb_blank = FB_BLANK_UNBLANK;
144 bd->props.state &= ~BL_CORE_FBBLANK;
145
146 return backlight_update_status(bd);
147}
148
149/**
150 * backlight_disable - Disable backlight
151 * @bd: the backlight device to disable
152 */
153static inline int backlight_disable(struct backlight_device *bd)
154{
155 if (!bd)
156 return 0;
157
158 bd->props.power = FB_BLANK_POWERDOWN;
159 bd->props.fb_blank = FB_BLANK_POWERDOWN;
160 bd->props.state |= BL_CORE_FBBLANK;
161
162 return backlight_update_status(bd);
163}
164
165/**
166 * backlight_put - Drop backlight reference
167 * @bd: the backlight device to put
168 */
169static inline void backlight_put(struct backlight_device *bd)
170{
171 if (bd)
172 put_device(&bd->dev);
173}
174
133extern struct backlight_device *backlight_device_register(const char *name, 175extern struct backlight_device *backlight_device_register(const char *name,
134 struct device *dev, void *devdata, const struct backlight_ops *ops, 176 struct device *dev, void *devdata, const struct backlight_ops *ops,
135 const struct backlight_properties *props); 177 const struct backlight_properties *props);
@@ -173,4 +215,20 @@ of_find_backlight_by_node(struct device_node *node)
173} 215}
174#endif 216#endif
175 217
218#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
219struct backlight_device *of_find_backlight(struct device *dev);
220struct backlight_device *devm_of_find_backlight(struct device *dev);
221#else
222static inline struct backlight_device *of_find_backlight(struct device *dev)
223{
224 return NULL;
225}
226
227static inline struct backlight_device *
228devm_of_find_backlight(struct device *dev)
229{
230 return NULL;
231}
232#endif
233
176#endif 234#endif