提交 a7d7a143 编写于 作者: L Linus Torvalds

Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux

Pull DRM updates from Dave Airlie:
 "Like all good pull reqs this ends with a revert, so it must mean we
  tested it,

[ Ed. That's _one_ way of looking at it ]

  This pull is missing nouveau, Ben has been stuck trying to track down
  a very longstanding bug that revealed itself due to some other
  changes.  I've asked him to send you a direct pull request for nouveau
  once he cleans things up.  I'm away until Monday so don't want to
  delay things, you can make a decision on that when he sends it, I have
  my phone so I can ack things just not really merge much.

  It has one trivial conflict with your tree in armada_drv.c, and also
  the pull request contains some component changes that are already in
  your tree, the base tree from Russell went via Greg's tree already,
  but some stuff still shows up in here that doesn't when I merge my
  tree into yours.

  Otherwise all pretty standard graphics fare, one new driver and
  changes all over the place.

  New drivers:
   - sti kms driver for STMicroelectronics chipsets stih416 and stih407.

  core:
   - lots of cleanups to the drm core
   - DP MST helper code merged
   - universal cursor planes.
   - render nodes enabled by default

  panel:
   - better panel interfaces
   - new panel support
   - non-continuous cock advertising ability

  ttm:
   - shrinker fixes

  i915:
   - hopefully ditched UMS support
   - runtime pm fixes
   - psr tracking and locking - now enabled by default
   - userptr fixes
   - backlight brightness fixes
   - MST support merged
   - runtime PM for dpms
   - primary planes locking fixes
   - gen8 hw semaphore support
   - fbc fixes
   - runtime PM on SOix sleep state hw.
   - mmio base page flipping
   - lots of vlv/chv fixes.
   - universal cursor planes

  radeon:
   - Hawaii fixes
   - display scalar support for non-fixed mode displays
   - new firmware format support
   - dpm on more asics by default
   - GPUVM improvements
   - uncached and wc GTT buffers
   - BOs > visible VRAM

  exynos:
   - i80 interface support
   - module auto-loading
   - ipp driver consolidated.

  armada:
   - irq handling in crtc layer only
   - crtc renumbering
   - add component support
   - DT interaction changes.

  tegra:
   - load as module fixes
   - eDP bpp and sync polarity fixed
   - DSI non-continuous clock mode support
   - better support for importing buffers from nouveau

  msm:
   - mdp5/adq8084 v1.3 hw enablement
   - devicetree clk changse
   - ifc6410 board working

  tda998x:
   - component support
   - DT documentation update

  vmwgfx:
   - fix compat shader namespace"

* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (551 commits)
  Revert "drm: drop redundant drm_file->is_master"
  drm/panel: simple: Use devm_gpiod_get_optional()
  drm/dsi: Replace upcasting macro by function
  drm/panel: ld9040: Replace upcasting macro by function
  drm/exynos: dp: Modify driver to support drm_panel
  drm/exynos: Move DP setup into commit()
  drm/panel: simple: Add AUO B133HTN01 panel support
  drm/panel: simple: Support delays in panel functions
  drm/panel: simple: Add proper definition for prepare and unprepare
  drm/panel: s6e8aa0: Add proper definition for prepare and unprepare
  drm/panel: ld9040: Add proper definition for prepare and unprepare
  drm/tegra: Add support for panel prepare and unprepare routines
  drm/exynos: dsi: Add support for panel prepare and unprepare routines
  drm/exynos: dpi: Add support for panel prepare and unprepare routines
  drm/panel: simple: Add dummy prepare and unprepare routines
  drm/panel: s6e8aa0: Add dummy prepare and unprepare routines
  drm/panel: ld9040: Add dummy prepare and unprepare routines
  drm/panel: Provide convenience wrapper for .get_modes()
  drm/panel: add .prepare() and .unprepare() functions
  drm/panel: simple: Remove simple-panel compatible
  ...
...@@ -1610,7 +1610,7 @@ int max_width, max_height;</synopsis> ...@@ -1610,7 +1610,7 @@ int max_width, max_height;</synopsis>
The connector is then registered with a call to The connector is then registered with a call to
<function>drm_connector_init</function> with a pointer to the connector <function>drm_connector_init</function> with a pointer to the connector
functions and a connector type, and exposed through sysfs with a call to functions and a connector type, and exposed through sysfs with a call to
<function>drm_sysfs_connector_add</function>. <function>drm_connector_register</function>.
</para> </para>
<para> <para>
Supported connector types are Supported connector types are
...@@ -1768,7 +1768,7 @@ int max_width, max_height;</synopsis> ...@@ -1768,7 +1768,7 @@ int max_width, max_height;</synopsis>
(<function>drm_encoder_cleanup</function>) and connectors (<function>drm_encoder_cleanup</function>) and connectors
(<function>drm_connector_cleanup</function>). Furthermore, connectors (<function>drm_connector_cleanup</function>). Furthermore, connectors
that have been added to sysfs must be removed by a call to that have been added to sysfs must be removed by a call to
<function>drm_sysfs_connector_remove</function> before calling <function>drm_connector_unregister</function> before calling
<function>drm_connector_cleanup</function>. <function>drm_connector_cleanup</function>.
</para> </para>
<para> <para>
...@@ -1813,7 +1813,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -1813,7 +1813,7 @@ void intel_crt_init(struct drm_device *dev)
drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs); drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs);
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
drm_sysfs_connector_add(connector); drm_connector_register(connector);
}]]></programlisting> }]]></programlisting>
<para> <para>
In the example above (taken from the i915 driver), a CRTC, connector and In the example above (taken from the i915 driver), a CRTC, connector and
...@@ -2336,6 +2336,12 @@ void intel_crt_init(struct drm_device *dev) ...@@ -2336,6 +2336,12 @@ void intel_crt_init(struct drm_device *dev)
!Pdrivers/gpu/drm/drm_dp_helper.c dp helpers !Pdrivers/gpu/drm/drm_dp_helper.c dp helpers
!Iinclude/drm/drm_dp_helper.h !Iinclude/drm/drm_dp_helper.h
!Edrivers/gpu/drm/drm_dp_helper.c !Edrivers/gpu/drm/drm_dp_helper.c
</sect2>
<sect2>
<title>Display Port MST Helper Functions Reference</title>
!Pdrivers/gpu/drm/drm_dp_mst_topology.c dp mst helper
!Iinclude/drm/drm_dp_mst_helper.h
!Edrivers/gpu/drm/drm_dp_mst_topology.c
</sect2> </sect2>
<sect2> <sect2>
<title>EDID Helper Functions Reference</title> <title>EDID Helper Functions Reference</title>
...@@ -2502,7 +2508,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -2502,7 +2508,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >Description/Restrictions</td> <td valign="top" >Description/Restrictions</td>
</tr> </tr>
<tr> <tr>
<td rowspan="20" valign="top" >DRM</td> <td rowspan="21" valign="top" >DRM</td>
<td rowspan="2" valign="top" >Generic</td> <td rowspan="2" valign="top" >Generic</td>
<td valign="top" >“EDID”</td> <td valign="top" >“EDID”</td>
<td valign="top" >BLOB | IMMUTABLE</td> <td valign="top" >BLOB | IMMUTABLE</td>
...@@ -2633,7 +2639,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -2633,7 +2639,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td rowspan="2" valign="top" >Optional</td> <td rowspan="3" valign="top" >Optional</td>
<td valign="top" >“scaling mode”</td> <td valign="top" >“scaling mode”</td>
<td valign="top" >ENUM</td> <td valign="top" >ENUM</td>
<td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td> <td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td>
...@@ -2641,6 +2647,15 @@ void intel_crt_init(struct drm_device *dev) ...@@ -2641,6 +2647,15 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td valign="top" >"aspect ratio"</td>
<td valign="top" >ENUM</td>
<td valign="top" >{ "None", "4:3", "16:9" }</td>
<td valign="top" >Connector</td>
<td valign="top" >DRM property to set aspect ratio from user space app.
This enum is made generic to allow addition of custom aspect
ratios.</td>
</tr>
<tr>
<td valign="top" >“dirty”</td> <td valign="top" >“dirty”</td>
<td valign="top" >ENUM | IMMUTABLE</td> <td valign="top" >ENUM | IMMUTABLE</td>
<td valign="top" >{ "Off", "On", "Annotate" }</td> <td valign="top" >{ "Off", "On", "Annotate" }</td>
...@@ -2649,7 +2664,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -2649,7 +2664,7 @@ void intel_crt_init(struct drm_device *dev)
</tr> </tr>
<tr> <tr>
<td rowspan="21" valign="top" >i915</td> <td rowspan="21" valign="top" >i915</td>
<td rowspan="3" valign="top" >Generic</td> <td rowspan="2" valign="top" >Generic</td>
<td valign="top" >"Broadcast RGB"</td> <td valign="top" >"Broadcast RGB"</td>
<td valign="top" >ENUM</td> <td valign="top" >ENUM</td>
<td valign="top" >{ "Automatic", "Full", "Limited 16:235" }</td> <td valign="top" >{ "Automatic", "Full", "Limited 16:235" }</td>
...@@ -2664,10 +2679,11 @@ void intel_crt_init(struct drm_device *dev) ...@@ -2664,10 +2679,11 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td valign="top" >Standard name as in DRM</td> <td rowspan="1" valign="top" >Plane</td>
<td valign="top" >Standard type as in DRM</td> <td valign="top" >“rotation”</td>
<td valign="top" >Standard value as in DRM</td> <td valign="top" >BITMASK</td>
<td valign="top" >Standard Object as in DRM</td> <td valign="top" >{ 0, "rotate-0" }, { 2, "rotate-180" }</td>
<td valign="top" >Plane</td>
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
...@@ -2799,8 +2815,8 @@ void intel_crt_init(struct drm_device *dev) ...@@ -2799,8 +2815,8 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td rowspan="3" valign="top" >CDV gma-500</td> <td rowspan="2" valign="top" >CDV gma-500</td>
<td rowspan="3" valign="top" >Generic</td> <td rowspan="2" valign="top" >Generic</td>
<td valign="top" >"Broadcast RGB"</td> <td valign="top" >"Broadcast RGB"</td>
<td valign="top" >ENUM</td> <td valign="top" >ENUM</td>
<td valign="top" >{ “Full”, “Limited 16:235” }</td> <td valign="top" >{ “Full”, “Limited 16:235” }</td>
...@@ -2815,15 +2831,8 @@ void intel_crt_init(struct drm_device *dev) ...@@ -2815,15 +2831,8 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td valign="top" >Standard name as in DRM</td> <td rowspan="19" valign="top" >Poulsbo</td>
<td valign="top" >Standard type as in DRM</td> <td rowspan="1" valign="top" >Generic</td>
<td valign="top" >Standard value as in DRM</td>
<td valign="top" >Standard Object as in DRM</td>
<td valign="top" >TBD</td>
</tr>
<tr>
<td rowspan="20" valign="top" >Poulsbo</td>
<td rowspan="2" valign="top" >Generic</td>
<td valign="top" >“backlight”</td> <td valign="top" >“backlight”</td>
<td valign="top" >RANGE</td> <td valign="top" >RANGE</td>
<td valign="top" >Min=0, Max=100</td> <td valign="top" >Min=0, Max=100</td>
...@@ -2831,13 +2840,6 @@ void intel_crt_init(struct drm_device *dev) ...@@ -2831,13 +2840,6 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td valign="top" >Standard name as in DRM</td>
<td valign="top" >Standard type as in DRM</td>
<td valign="top" >Standard value as in DRM</td>
<td valign="top" >Standard Object as in DRM</td>
<td valign="top" >TBD</td>
</tr>
<tr>
<td rowspan="17" valign="top" >SDVO-TV</td> <td rowspan="17" valign="top" >SDVO-TV</td>
<td valign="top" >“mode”</td> <td valign="top" >“mode”</td>
<td valign="top" >ENUM</td> <td valign="top" >ENUM</td>
...@@ -3064,7 +3066,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -3064,7 +3066,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td rowspan="3" valign="top" >i2c/ch7006_drv</td> <td rowspan="2" valign="top" >i2c/ch7006_drv</td>
<td valign="top" >Generic</td> <td valign="top" >Generic</td>
<td valign="top" >“scale”</td> <td valign="top" >“scale”</td>
<td valign="top" >RANGE</td> <td valign="top" >RANGE</td>
...@@ -3073,14 +3075,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -3073,14 +3075,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td rowspan="2" valign="top" >TV</td> <td rowspan="1" valign="top" >TV</td>
<td valign="top" >Standard names as in DRM</td>
<td valign="top" >Standard types as in DRM</td>
<td valign="top" >Standard Values as in DRM</td>
<td valign="top" >Standard object as in DRM</td>
<td valign="top" >TBD</td>
</tr>
<tr>
<td valign="top" >“mode”</td> <td valign="top" >“mode”</td>
<td valign="top" >ENUM</td> <td valign="top" >ENUM</td>
<td valign="top" >{ "PAL", "PAL-M","PAL-N"}, ”PAL-Nc" <td valign="top" >{ "PAL", "PAL-M","PAL-N"}, ”PAL-Nc"
...@@ -3089,7 +3084,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -3089,7 +3084,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td rowspan="16" valign="top" >nouveau</td> <td rowspan="15" valign="top" >nouveau</td>
<td rowspan="6" valign="top" >NV10 Overlay</td> <td rowspan="6" valign="top" >NV10 Overlay</td>
<td valign="top" >"colorkey"</td> <td valign="top" >"colorkey"</td>
<td valign="top" >RANGE</td> <td valign="top" >RANGE</td>
...@@ -3198,14 +3193,6 @@ void intel_crt_init(struct drm_device *dev) ...@@ -3198,14 +3193,6 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td valign="top" >Generic</td>
<td valign="top" >Standard name as in DRM</td>
<td valign="top" >Standard type as in DRM</td>
<td valign="top" >Standard value as in DRM</td>
<td valign="top" >Standard Object as in DRM</td>
<td valign="top" >TBD</td>
</tr>
<tr>
<td rowspan="2" valign="top" >omap</td> <td rowspan="2" valign="top" >omap</td>
<td rowspan="2" valign="top" >Generic</td> <td rowspan="2" valign="top" >Generic</td>
<td valign="top" >“rotation”</td> <td valign="top" >“rotation”</td>
...@@ -3236,7 +3223,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -3236,7 +3223,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td rowspan="10" valign="top" >radeon</td> <td rowspan="9" valign="top" >radeon</td>
<td valign="top" >DVI-I</td> <td valign="top" >DVI-I</td>
<td valign="top" >“coherent”</td> <td valign="top" >“coherent”</td>
<td valign="top" >RANGE</td> <td valign="top" >RANGE</td>
...@@ -3308,14 +3295,6 @@ void intel_crt_init(struct drm_device *dev) ...@@ -3308,14 +3295,6 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td> <td valign="top" >TBD</td>
</tr> </tr>
<tr> <tr>
<td valign="top" >Generic</td>
<td valign="top" >Standard name as in DRM</td>
<td valign="top" >Standard type as in DRM</td>
<td valign="top" >Standard value as in DRM</td>
<td valign="top" >Standard Object as in DRM</td>
<td valign="top" >TBD</td>
</tr>
<tr>
<td rowspan="3" valign="top" >rcar-du</td> <td rowspan="3" valign="top" >rcar-du</td>
<td rowspan="3" valign="top" >Generic</td> <td rowspan="3" valign="top" >Generic</td>
<td valign="top" >"alpha"</td> <td valign="top" >"alpha"</td>
......
Device Tree bindings for Armada DRM CRTC driver
Required properties:
- compatible: value should be "marvell,dove-lcd".
- reg: base address and size of the LCD controller
- interrupts: single interrupt number for the LCD controller
- port: video output port with endpoints, as described by graph.txt
Optional properties:
- clocks: as described by clock-bindings.txt
- clock-names: as described by clock-bindings.txt
"axiclk" - axi bus clock for pixel clock
"plldivider" - pll divider clock for pixel clock
"ext_ref_clk0" - external clock 0 for pixel clock
"ext_ref_clk1" - external clock 1 for pixel clock
Note: all clocks are optional but at least one must be specified.
Further clocks may be added in the future according to requirements of
different SoCs.
Example:
lcd0: lcd-controller@820000 {
compatible = "marvell,dove-lcd";
reg = <0x820000 0x1000>;
interrupts = <47>;
clocks = <&si5351 0>;
clock-names = "ext_ref_clk_1";
};
...@@ -3,6 +3,8 @@ Device-Tree bindings for the NXP TDA998x HDMI transmitter ...@@ -3,6 +3,8 @@ Device-Tree bindings for the NXP TDA998x HDMI transmitter
Required properties; Required properties;
- compatible: must be "nxp,tda998x" - compatible: must be "nxp,tda998x"
- reg: I2C address
Optional properties: Optional properties:
- interrupts: interrupt number and trigger type - interrupts: interrupt number and trigger type
default: polling default: polling
......
Qualcomm adreno/snapdragon GPU
Required properties:
- compatible: "qcom,adreno-3xx"
- reg: Physical base address and length of the controller's registers.
- interrupts: The interrupt signal from the gpu.
- clocks: device clocks
See ../clocks/clock-bindings.txt for details.
- clock-names: the following clocks are required:
* "core_clk"
* "iface_clk"
* "mem_iface_clk"
- qcom,chipid: gpu chip-id. Note this may become optional for future
devices if we can reliably read the chipid from hw
- qcom,gpu-pwrlevels: list of operating points
- compatible: "qcom,gpu-pwrlevels"
- for each qcom,gpu-pwrlevel:
- qcom,gpu-freq: requested gpu clock speed
- NOTE: downstream android driver defines additional parameters to
configure memory bandwidth scaling per OPP.
Example:
/ {
...
gpu: qcom,kgsl-3d0@4300000 {
compatible = "qcom,adreno-3xx";
reg = <0x04300000 0x20000>;
reg-names = "kgsl_3d0_reg_memory";
interrupts = <GIC_SPI 80 0>;
interrupt-names = "kgsl_3d0_irq";
clock-names =
"core_clk",
"iface_clk",
"mem_iface_clk";
clocks =
<&mmcc GFX3D_CLK>,
<&mmcc GFX3D_AHB_CLK>,
<&mmcc MMSS_IMEM_AHB_CLK>;
qcom,chipid = <0x03020100>;
qcom,gpu-pwrlevels {
compatible = "qcom,gpu-pwrlevels";
qcom,gpu-pwrlevel@0 {
qcom,gpu-freq = <450000000>;
};
qcom,gpu-pwrlevel@1 {
qcom,gpu-freq = <27000000>;
};
};
};
};
Qualcomm adreno/snapdragon hdmi output
Required properties:
- compatible: one of the following
* "qcom,hdmi-tx-8660"
* "qcom,hdmi-tx-8960"
- reg: Physical base address and length of the controller's registers
- reg-names: "core_physical"
- interrupts: The interrupt signal from the hdmi block.
- clocks: device clocks
See ../clocks/clock-bindings.txt for details.
- qcom,hdmi-tx-ddc-clk-gpio: ddc clk pin
- qcom,hdmi-tx-ddc-data-gpio: ddc data pin
- qcom,hdmi-tx-hpd-gpio: hpd pin
- core-vdda-supply: phandle to supply regulator
- hdmi-mux-supply: phandle to mux regulator
Optional properties:
- qcom,hdmi-tx-mux-en-gpio: hdmi mux enable pin
- qcom,hdmi-tx-mux-sel-gpio: hdmi mux select pin
Example:
/ {
...
hdmi: qcom,hdmi-tx-8960@4a00000 {
compatible = "qcom,hdmi-tx-8960";
reg-names = "core_physical";
reg = <0x04a00000 0x1000>;
interrupts = <GIC_SPI 79 0>;
clock-names =
"core_clk",
"master_iface_clk",
"slave_iface_clk";
clocks =
<&mmcc HDMI_APP_CLK>,
<&mmcc HDMI_M_AHB_CLK>,
<&mmcc HDMI_S_AHB_CLK>;
qcom,hdmi-tx-ddc-clk = <&msmgpio 70 GPIO_ACTIVE_HIGH>;
qcom,hdmi-tx-ddc-data = <&msmgpio 71 GPIO_ACTIVE_HIGH>;
qcom,hdmi-tx-hpd = <&msmgpio 72 GPIO_ACTIVE_HIGH>;
core-vdda-supply = <&pm8921_hdmi_mvs>;
hdmi-mux-supply = <&ext_3p3v>;
};
};
Qualcomm adreno/snapdragon display controller
Required properties:
- compatible:
* "qcom,mdp" - mdp4
- reg: Physical base address and length of the controller's registers.
- interrupts: The interrupt signal from the display controller.
- connectors: array of phandles for output device(s)
- clocks: device clocks
See ../clocks/clock-bindings.txt for details.
- clock-names: the following clocks are required:
* "core_clk"
* "iface_clk"
* "lut_clk"
* "src_clk"
* "hdmi_clk"
* "mpd_clk"
Optional properties:
- gpus: phandle for gpu device
Example:
/ {
...
mdp: qcom,mdp@5100000 {
compatible = "qcom,mdp";
reg = <0x05100000 0xf0000>;
interrupts = <GIC_SPI 75 0>;
connectors = <&hdmi>;
gpus = <&gpu>;
clock-names =
"core_clk",
"iface_clk",
"lut_clk",
"src_clk",
"hdmi_clk",
"mdp_clk";
clocks =
<&mmcc MDP_SRC>,
<&mmcc MDP_AHB_CLK>,
<&mmcc MDP_LUT_CLK>,
<&mmcc TV_SRC>,
<&mmcc HDMI_TV_CLK>,
<&mmcc MDP_TV_CLK>;
};
};
STMicroelectronics stih4xx platforms
- sti-vtg: video timing generator
Required properties:
- compatible: "st,vtg"
- reg: Physical base address of the IP registers and length of memory mapped region.
Optional properties:
- interrupts : VTG interrupt number to the CPU.
- st,slave: phandle on a slave vtg
- sti-vtac: video timing advanced inter dye communication Rx and TX
Required properties:
- compatible: "st,vtac-main" or "st,vtac-aux"
- reg: Physical base address of the IP registers and length of memory mapped region.
- clocks: from common clock binding: handle hardware IP needed clocks, the
number of clocks may depend of the SoC type.
See ../clocks/clock-bindings.txt for details.
- clock-names: names of the clocks listed in clocks property in the same
order.
- sti-display-subsystem: Master device for DRM sub-components
This device must be the parent of all the sub-components and is responsible
of bind them.
Required properties:
- compatible: "st,sti-display-subsystem"
- ranges: to allow probing of subdevices
- sti-compositor: frame compositor engine
must be a child of sti-display-subsystem
Required properties:
- compatible: "st,stih<chip>-compositor"
- reg: Physical base address of the IP registers and length of memory mapped region.
- clocks: from common clock binding: handle hardware IP needed clocks, the
number of clocks may depend of the SoC type.
See ../clocks/clock-bindings.txt for details.
- clock-names: names of the clocks listed in clocks property in the same
order.
- resets: resets to be used by the device
See ../reset/reset.txt for details.
- reset-names: names of the resets listed in resets property in the same
order.
- st,vtg: phandle(s) on vtg device (main and aux) nodes.
- sti-tvout: video out hardware block
must be a child of sti-display-subsystem
Required properties:
- compatible: "st,stih<chip>-tvout"
- reg: Physical base address of the IP registers and length of memory mapped region.
- reg-names: names of the mapped memory regions listed in regs property in
the same order.
- resets: resets to be used by the device
See ../reset/reset.txt for details.
- reset-names: names of the resets listed in resets property in the same
order.
- ranges: to allow probing of subdevices
- sti-hdmi: hdmi output block
must be a child of sti-tvout
Required properties:
- compatible: "st,stih<chip>-hdmi";
- reg: Physical base address of the IP registers and length of memory mapped region.
- reg-names: names of the mapped memory regions listed in regs property in
the same order.
- interrupts : HDMI interrupt number to the CPU.
- interrupt-names: name of the interrupts listed in interrupts property in
the same order
- clocks: from common clock binding: handle hardware IP needed clocks, the
number of clocks may depend of the SoC type.
- clock-names: names of the clocks listed in clocks property in the same
order.
- hdmi,hpd-gpio: gpio id to detect if an hdmi cable is plugged or not.
sti-hda:
Required properties:
must be a child of sti-tvout
- compatible: "st,stih<chip>-hda"
- reg: Physical base address of the IP registers and length of memory mapped region.
- reg-names: names of the mapped memory regions listed in regs property in
the same order.
- clocks: from common clock binding: handle hardware IP needed clocks, the
number of clocks may depend of the SoC type.
See ../clocks/clock-bindings.txt for details.
- clock-names: names of the clocks listed in clocks property in the same
order.
Example:
/ {
...
vtg_main_slave: sti-vtg-main-slave@fe85A800 {
compatible = "st,vtg";
reg = <0xfe85A800 0x300>;
interrupts = <GIC_SPI 175 IRQ_TYPE_NONE>;
};
vtg_main: sti-vtg-main-master@fd348000 {
compatible = "st,vtg";
reg = <0xfd348000 0x400>;
st,slave = <&vtg_main_slave>;
};
vtg_aux_slave: sti-vtg-aux-slave@fd348400 {
compatible = "st,vtg";
reg = <0xfe858200 0x300>;
interrupts = <GIC_SPI 176 IRQ_TYPE_NONE>;
};
vtg_aux: sti-vtg-aux-master@fd348400 {
compatible = "st,vtg";
reg = <0xfd348400 0x400>;
st,slave = <&vtg_aux_slave>;
};
sti-vtac-rx-main@fee82800 {
compatible = "st,vtac-main";
reg = <0xfee82800 0x200>;
clock-names = "vtac";
clocks = <&clk_m_a2_div0 CLK_M_VTAC_MAIN_PHY>;
};
sti-vtac-rx-aux@fee82a00 {
compatible = "st,vtac-aux";
reg = <0xfee82a00 0x200>;
clock-names = "vtac";
clocks = <&clk_m_a2_div0 CLK_M_VTAC_AUX_PHY>;
};
sti-vtac-tx-main@fd349000 {
compatible = "st,vtac-main";
reg = <0xfd349000 0x200>, <0xfd320000 0x10000>;
clock-names = "vtac";
clocks = <&clk_s_a1_hs CLK_S_VTAC_TX_PHY>;
};
sti-vtac-tx-aux@fd349200 {
compatible = "st,vtac-aux";
reg = <0xfd349200 0x200>, <0xfd320000 0x10000>;
clock-names = "vtac";
clocks = <&clk_s_a1_hs CLK_S_VTAC_TX_PHY>;
};
sti-display-subsystem {
compatible = "st,sti-display-subsystem";
ranges;
sti-compositor@fd340000 {
compatible = "st,stih416-compositor";
reg = <0xfd340000 0x1000>;
clock-names = "compo_main", "compo_aux",
"pix_main", "pix_aux";
clocks = <&clk_m_a2_div1 CLK_M_COMPO_MAIN>, <&clk_m_a2_div1 CLK_M_COMPO_AUX>,
<&clockgen_c_vcc CLK_S_PIX_MAIN>, <&clockgen_c_vcc CLK_S_PIX_AUX>;
reset-names = "compo-main", "compo-aux";
resets = <&softreset STIH416_COMPO_M_SOFTRESET>, <&softreset STIH416_COMPO_A_SOFTRESET>;
st,vtg = <&vtg_main>, <&vtg_aux>;
};
sti-tvout@fe000000 {
compatible = "st,stih416-tvout";
reg = <0xfe000000 0x1000>, <0xfe85a000 0x400>, <0xfe830000 0x10000>;
reg-names = "tvout-reg", "hda-reg", "syscfg";
reset-names = "tvout";
resets = <&softreset STIH416_HDTVOUT_SOFTRESET>;
ranges;
sti-hdmi@fe85c000 {
compatible = "st,stih416-hdmi";
reg = <0xfe85c000 0x1000>, <0xfe830000 0x10000>;
reg-names = "hdmi-reg", "syscfg";
interrupts = <GIC_SPI 173 IRQ_TYPE_NONE>;
interrupt-names = "irq";
clock-names = "pix", "tmds", "phy", "audio";
clocks = <&clockgen_c_vcc CLK_S_PIX_HDMI>, <&clockgen_c_vcc CLK_S_TMDS_HDMI>, <&clockgen_c_vcc CLK_S_HDMI_REJECT_PLL>, <&clockgen_b1 CLK_S_PCM_0>;
hdmi,hpd-gpio = <&PIO2 5>;
};
sti-hda@fe85a000 {
compatible = "st,stih416-hda";
reg = <0xfe85a000 0x400>, <0xfe83085c 0x4>;
reg-names = "hda-reg", "video-dacs-ctrl";
clock-names = "pix", "hddac";
clocks = <&clockgen_c_vcc CLK_S_PIX_HD>, <&clockgen_c_vcc CLK_S_HDDAC>;
};
};
};
...
};
AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
Required properties:
- compatible: should be "auo,b133htn01"
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.
Foxlink Group 5" WVGA TFT LCD panel
Required properties:
- compatible: should be "foxlink,fl500wvr00-a0t"
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.
Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
Required properties:
- compatible: should be "innolux,n116bge"
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.
InnoLux 15.6" WXGA TFT LCD panel
Required properties:
- compatible: should be "innolux,n156bge-l21"
This binding is compatible with the simple-panel binding, which is specified
in simple-panel.txt in this directory.
Exynos MIPI DSI Master Exynos MIPI DSI Master
Required properties: Required properties:
- compatible: "samsung,exynos4210-mipi-dsi" - compatible: value should be one of the following
"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
- reg: physical base address and length of the registers set for the device - reg: physical base address and length of the registers set for the device
- interrupts: should contain DSI interrupt - interrupts: should contain DSI interrupt
- clocks: list of clock specifiers, must contain an entry for each required - clocks: list of clock specifiers, must contain an entry for each required
......
...@@ -4,8 +4,9 @@ Required properties: ...@@ -4,8 +4,9 @@ Required properties:
- compatible: value should be one of the following: - compatible: value should be one of the following:
1) "samsung,exynos5-mixer" <DEPRECATED> 1) "samsung,exynos5-mixer" <DEPRECATED>
2) "samsung,exynos4210-mixer" 2) "samsung,exynos4210-mixer"
3) "samsung,exynos5250-mixer" 3) "samsung,exynos4212-mixer"
4) "samsung,exynos5420-mixer" 4) "samsung,exynos5250-mixer"
5) "samsung,exynos5420-mixer"
- reg: physical base address of the mixer and length of memory mapped - reg: physical base address of the mixer and length of memory mapped
region. region.
......
...@@ -44,6 +44,34 @@ Optional Properties: ...@@ -44,6 +44,34 @@ Optional Properties:
- display-timings: timing settings for FIMD, as described in document [1]. - display-timings: timing settings for FIMD, as described in document [1].
Can be used in case timings cannot be provided otherwise Can be used in case timings cannot be provided otherwise
or to override timings provided by the panel. or to override timings provided by the panel.
- samsung,sysreg: handle to syscon used to control the system registers
- i80-if-timings: timing configuration for lcd i80 interface support.
- cs-setup: clock cycles for the active period of address signal is enabled
until chip select is enabled.
If not specified, the default value(0) will be used.
- wr-setup: clock cycles for the active period of CS signal is enabled until
write signal is enabled.
If not specified, the default value(0) will be used.
- wr-active: clock cycles for the active period of CS is enabled.
If not specified, the default value(1) will be used.
- wr-hold: clock cycles for the active period of CS is disabled until write
signal is disabled.
If not specified, the default value(0) will be used.
The parameters are defined as:
VCLK(internal) __|??????|_____|??????|_____|??????|_____|??????|_____|??
: : : : :
Address Output --:<XXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XX
| cs-setup+1 | : : :
|<---------->| : : :
Chip Select ???????????????|____________:____________:____________|??
| wr-setup+1 | | wr-hold+1 |
|<---------->| |<---------->|
Write Enable ????????????????????????????|____________|???????????????
| wr-active+1|
|<---------->|
Video Data ----------------------------<XXXXXXXXXXXXXXXXXXXXXXXXX>--
The device node can contain 'port' child nodes according to the bindings defined The device node can contain 'port' child nodes according to the bindings defined
in [2]. The following are properties specific to those nodes: in [2]. The following are properties specific to those nodes:
......
...@@ -612,6 +612,7 @@ ...@@ -612,6 +612,7 @@
clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>; clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>;
clock-names = "sclk_fimd", "fimd"; clock-names = "sclk_fimd", "fimd";
samsung,power-domain = <&pd_lcd0>; samsung,power-domain = <&pd_lcd0>;
samsung,sysreg = <&sys_reg>;
status = "disabled"; status = "disabled";
}; };
}; };
...@@ -94,6 +94,7 @@ ...@@ -94,6 +94,7 @@
reg = <0x14400000 0x40000>; reg = <0x14400000 0x40000>;
interrupt-names = "fifo", "vsync", "lcd_sys"; interrupt-names = "fifo", "vsync", "lcd_sys";
interrupts = <18 4>, <18 5>, <18 6>; interrupts = <18 4>, <18 5>, <18 6>;
samsung,sysreg = <&sysreg_system_controller>;
status = "disabled"; status = "disabled";
}; };
......
...@@ -520,6 +520,26 @@ ...@@ -520,6 +520,26 @@
phy-names = "dp"; phy-names = "dp";
}; };
mipi_phy: video-phy@10040714 {
compatible = "samsung,s5pv210-mipi-video-phy";
reg = <0x10040714 12>;
#phy-cells = <1>;
};
dsi@14500000 {
compatible = "samsung,exynos5410-mipi-dsi";
reg = <0x14500000 0x10000>;
interrupts = <0 82 0>;
samsung,power-domain = <&disp_pd>;
phys = <&mipi_phy 1>;
phy-names = "dsim";
clocks = <&clock CLK_DSIM1>, <&clock CLK_SCLK_MIPI1>;
clock-names = "bus_clk", "pll_clk";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
fimd: fimd@14400000 { fimd: fimd@14400000 {
samsung,power-domain = <&disp_pd>; samsung,power-domain = <&disp_pd>;
clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>; clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
......
...@@ -710,19 +710,6 @@ static int agp_open(struct inode *inode, struct file *file) ...@@ -710,19 +710,6 @@ static int agp_open(struct inode *inode, struct file *file)
return 0; return 0;
} }
static ssize_t agp_read(struct file *file, char __user *buf,
size_t count, loff_t * ppos)
{
return -EINVAL;
}
static ssize_t agp_write(struct file *file, const char __user *buf,
size_t count, loff_t * ppos)
{
return -EINVAL;
}
static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg) static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
{ {
struct agp_info userinfo; struct agp_info userinfo;
...@@ -1047,8 +1034,6 @@ static const struct file_operations agp_fops = ...@@ -1047,8 +1034,6 @@ static const struct file_operations agp_fops =
{ {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.read = agp_read,
.write = agp_write,
.unlocked_ioctl = agp_ioctl, .unlocked_ioctl = agp_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = compat_agp_ioctl, .compat_ioctl = compat_agp_ioctl,
......
...@@ -114,6 +114,7 @@ config DRM_RADEON ...@@ -114,6 +114,7 @@ config DRM_RADEON
select POWER_SUPPLY select POWER_SUPPLY
select HWMON select HWMON
select BACKLIGHT_CLASS_DEVICE select BACKLIGHT_CLASS_DEVICE
select INTERVAL_TREE
help help
Choose this option if you have an ATI Radeon graphics card. There Choose this option if you have an ATI Radeon graphics card. There
are both PCI and AGP versions. You don't need to choose this to are both PCI and AGP versions. You don't need to choose this to
...@@ -201,3 +202,5 @@ source "drivers/gpu/drm/msm/Kconfig" ...@@ -201,3 +202,5 @@ source "drivers/gpu/drm/msm/Kconfig"
source "drivers/gpu/drm/tegra/Kconfig" source "drivers/gpu/drm/tegra/Kconfig"
source "drivers/gpu/drm/panel/Kconfig" source "drivers/gpu/drm/panel/Kconfig"
source "drivers/gpu/drm/sti/Kconfig"
...@@ -6,8 +6,8 @@ ccflags-y := -Iinclude/drm ...@@ -6,8 +6,8 @@ ccflags-y := -Iinclude/drm
drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
drm_context.o drm_dma.o \ drm_context.o drm_dma.o \
drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
drm_lock.o drm_memory.o drm_stub.o drm_vm.o \ drm_lock.o drm_memory.o drm_drv.o drm_vm.o \
drm_agpsupport.o drm_scatter.o drm_pci.o \ drm_agpsupport.o drm_scatter.o drm_pci.o \
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
drm_crtc.o drm_modes.o drm_edid.o \ drm_crtc.o drm_modes.o drm_edid.o \
...@@ -20,11 +20,12 @@ drm-$(CONFIG_COMPAT) += drm_ioc32.o ...@@ -20,11 +20,12 @@ drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
drm-$(CONFIG_PCI) += ati_pcigart.o drm-$(CONFIG_PCI) += ati_pcigart.o
drm-$(CONFIG_DRM_PANEL) += drm_panel.o drm-$(CONFIG_DRM_PANEL) += drm_panel.o
drm-$(CONFIG_OF) += drm_of.o
drm-usb-y := drm_usb.o drm-usb-y := drm_usb.o
drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
drm_plane_helper.o drm_plane_helper.o drm_dp_mst_topology.o
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
...@@ -63,6 +64,7 @@ obj-$(CONFIG_DRM_QXL) += qxl/ ...@@ -63,6 +64,7 @@ obj-$(CONFIG_DRM_QXL) += qxl/
obj-$(CONFIG_DRM_BOCHS) += bochs/ obj-$(CONFIG_DRM_BOCHS) += bochs/
obj-$(CONFIG_DRM_MSM) += msm/ obj-$(CONFIG_DRM_MSM) += msm/
obj-$(CONFIG_DRM_TEGRA) += tegra/ obj-$(CONFIG_DRM_TEGRA) += tegra/
obj-$(CONFIG_DRM_STI) += sti/
obj-y += i2c/ obj-y += i2c/
obj-y += panel/ obj-y += panel/
obj-y += bridge/ obj-y += bridge/
...@@ -15,20 +15,19 @@ ...@@ -15,20 +15,19 @@
#include "armada_drm.h" #include "armada_drm.h"
#include "armada_hw.h" #include "armada_hw.h"
static int armada510_init(struct armada_private *priv, struct device *dev) static int armada510_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
{ {
priv->extclk[0] = devm_clk_get(dev, "ext_ref_clk_1"); struct clk *clk;
if (IS_ERR(priv->extclk[0]) && PTR_ERR(priv->extclk[0]) == -ENOENT) clk = devm_clk_get(dev, "ext_ref_clk1");
priv->extclk[0] = ERR_PTR(-EPROBE_DEFER); if (IS_ERR(clk))
return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER : PTR_ERR(clk);
return PTR_RET(priv->extclk[0]); dcrtc->extclk[0] = clk;
}
static int armada510_crtc_init(struct armada_crtc *dcrtc)
{
/* Lower the watermark so to eliminate jitter at higher bandwidths */ /* Lower the watermark so to eliminate jitter at higher bandwidths */
armada_updatel(0x20, (1 << 11) | 0xff, dcrtc->base + LCD_CFG_RDREG4F); armada_updatel(0x20, (1 << 11) | 0xff, dcrtc->base + LCD_CFG_RDREG4F);
return 0; return 0;
} }
...@@ -45,8 +44,7 @@ static int armada510_crtc_init(struct armada_crtc *dcrtc) ...@@ -45,8 +44,7 @@ static int armada510_crtc_init(struct armada_crtc *dcrtc)
static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc, static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
const struct drm_display_mode *mode, uint32_t *sclk) const struct drm_display_mode *mode, uint32_t *sclk)
{ {
struct armada_private *priv = dcrtc->crtc.dev->dev_private; struct clk *clk = dcrtc->extclk[0];
struct clk *clk = priv->extclk[0];
int ret; int ret;
if (dcrtc->num == 1) if (dcrtc->num == 1)
...@@ -81,7 +79,6 @@ static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc, ...@@ -81,7 +79,6 @@ static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
const struct armada_variant armada510_ops = { const struct armada_variant armada510_ops = {
.has_spu_adv_reg = true, .has_spu_adv_reg = true,
.spu_adv_reg = ADV_HWC32ENABLE | ADV_HWC32ARGB | ADV_HWC32BLEND, .spu_adv_reg = ADV_HWC32ENABLE | ADV_HWC32ARGB | ADV_HWC32BLEND,
.init = armada510_init, .init = armada510_crtc_init,
.crtc_init = armada510_crtc_init, .compute_clock = armada510_crtc_compute_clock,
.crtc_compute_clock = armada510_crtc_compute_clock,
}; };
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/component.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include "armada_crtc.h" #include "armada_crtc.h"
...@@ -332,24 +335,23 @@ static void armada_drm_crtc_commit(struct drm_crtc *crtc) ...@@ -332,24 +335,23 @@ static void armada_drm_crtc_commit(struct drm_crtc *crtc)
static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc, static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode, struct drm_display_mode *adj) const struct drm_display_mode *mode, struct drm_display_mode *adj)
{ {
struct armada_private *priv = crtc->dev->dev_private;
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
int ret; int ret;
/* We can't do interlaced modes if we don't have the SPU_ADV_REG */ /* We can't do interlaced modes if we don't have the SPU_ADV_REG */
if (!priv->variant->has_spu_adv_reg && if (!dcrtc->variant->has_spu_adv_reg &&
adj->flags & DRM_MODE_FLAG_INTERLACE) adj->flags & DRM_MODE_FLAG_INTERLACE)
return false; return false;
/* Check whether the display mode is possible */ /* Check whether the display mode is possible */
ret = priv->variant->crtc_compute_clock(dcrtc, adj, NULL); ret = dcrtc->variant->compute_clock(dcrtc, adj, NULL);
if (ret) if (ret)
return false; return false;
return true; return true;
} }
void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
{ {
struct armada_vbl_event *e, *n; struct armada_vbl_event *e, *n;
void __iomem *base = dcrtc->base; void __iomem *base = dcrtc->base;
...@@ -410,6 +412,27 @@ void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) ...@@ -410,6 +412,27 @@ void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
} }
} }
static irqreturn_t armada_drm_irq(int irq, void *arg)
{
struct armada_crtc *dcrtc = arg;
u32 v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
/*
* This is rediculous - rather than writing bits to clear, we
* have to set the actual status register value. This is racy.
*/
writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
/* Mask out those interrupts we haven't enabled */
v = stat & dcrtc->irq_ena;
if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
armada_drm_crtc_irq(dcrtc, stat);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
/* These are locked by dev->vbl_lock */ /* These are locked by dev->vbl_lock */
void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask) void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)
{ {
...@@ -470,7 +493,6 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, ...@@ -470,7 +493,6 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode, struct drm_display_mode *adj, struct drm_display_mode *mode, struct drm_display_mode *adj,
int x, int y, struct drm_framebuffer *old_fb) int x, int y, struct drm_framebuffer *old_fb)
{ {
struct armada_private *priv = crtc->dev->dev_private;
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
struct armada_regs regs[17]; struct armada_regs regs[17];
uint32_t lm, rm, tm, bm, val, sclk; uint32_t lm, rm, tm, bm, val, sclk;
...@@ -515,7 +537,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, ...@@ -515,7 +537,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
} }
/* Now compute the divider for real */ /* Now compute the divider for real */
priv->variant->crtc_compute_clock(dcrtc, adj, &sclk); dcrtc->variant->compute_clock(dcrtc, adj, &sclk);
/* Ensure graphic fifo is enabled */ /* Ensure graphic fifo is enabled */
armada_reg_queue_mod(regs, i, 0, CFG_PDWN64x66, LCD_SPU_SRAM_PARA1); armada_reg_queue_mod(regs, i, 0, CFG_PDWN64x66, LCD_SPU_SRAM_PARA1);
...@@ -537,7 +559,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, ...@@ -537,7 +559,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
dcrtc->v[1].spu_v_porch = tm << 16 | bm; dcrtc->v[1].spu_v_porch = tm << 16 | bm;
val = adj->crtc_hsync_start; val = adj->crtc_hsync_start;
dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN | dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
priv->variant->spu_adv_reg; dcrtc->variant->spu_adv_reg;
if (interlaced) { if (interlaced) {
/* Odd interlaced frame */ /* Odd interlaced frame */
...@@ -546,7 +568,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, ...@@ -546,7 +568,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1; dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1;
val = adj->crtc_hsync_start - adj->crtc_htotal / 2; val = adj->crtc_hsync_start - adj->crtc_htotal / 2;
dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN | dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
priv->variant->spu_adv_reg; dcrtc->variant->spu_adv_reg;
} else { } else {
dcrtc->v[0] = dcrtc->v[1]; dcrtc->v[0] = dcrtc->v[1];
} }
...@@ -561,7 +583,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, ...@@ -561,7 +583,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total, armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,
LCD_SPUT_V_H_TOTAL); LCD_SPUT_V_H_TOTAL);
if (priv->variant->has_spu_adv_reg) { if (dcrtc->variant->has_spu_adv_reg) {
armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg, armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg,
ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF | ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF |
ADV_VSYNCOFFEN, LCD_SPU_ADV_REG); ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);
...@@ -805,12 +827,11 @@ static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -805,12 +827,11 @@ static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc,
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
struct armada_private *priv = crtc->dev->dev_private;
struct armada_gem_object *obj = NULL; struct armada_gem_object *obj = NULL;
int ret; int ret;
/* If no cursor support, replicate drm's return value */ /* If no cursor support, replicate drm's return value */
if (!priv->variant->has_spu_adv_reg) if (!dcrtc->variant->has_spu_adv_reg)
return -ENXIO; return -ENXIO;
if (handle && w > 0 && h > 0) { if (handle && w > 0 && h > 0) {
...@@ -858,11 +879,10 @@ static int armada_drm_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) ...@@ -858,11 +879,10 @@ static int armada_drm_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
struct armada_private *priv = crtc->dev->dev_private;
int ret; int ret;
/* If no cursor support, replicate drm's return value */ /* If no cursor support, replicate drm's return value */
if (!priv->variant->has_spu_adv_reg) if (!dcrtc->variant->has_spu_adv_reg)
return -EFAULT; return -EFAULT;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
...@@ -888,6 +908,10 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc) ...@@ -888,6 +908,10 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
if (!IS_ERR(dcrtc->clk)) if (!IS_ERR(dcrtc->clk))
clk_disable_unprepare(dcrtc->clk); clk_disable_unprepare(dcrtc->clk);
writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ENA);
of_node_put(dcrtc->crtc.port);
kfree(dcrtc); kfree(dcrtc);
} }
...@@ -1027,19 +1051,20 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev) ...@@ -1027,19 +1051,20 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev)
return 0; return 0;
} }
int armada_drm_crtc_create(struct drm_device *dev, unsigned num, int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
struct resource *res) struct resource *res, int irq, const struct armada_variant *variant,
struct device_node *port)
{ {
struct armada_private *priv = dev->dev_private; struct armada_private *priv = drm->dev_private;
struct armada_crtc *dcrtc; struct armada_crtc *dcrtc;
void __iomem *base; void __iomem *base;
int ret; int ret;
ret = armada_drm_crtc_create_properties(dev); ret = armada_drm_crtc_create_properties(drm);
if (ret) if (ret)
return ret; return ret;
base = devm_ioremap_resource(dev->dev, res); base = devm_ioremap_resource(dev, res);
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);
...@@ -1049,8 +1074,12 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num, ...@@ -1049,8 +1074,12 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
return -ENOMEM; return -ENOMEM;
} }
if (dev != drm->dev)
dev_set_drvdata(dev, dcrtc);
dcrtc->variant = variant;
dcrtc->base = base; dcrtc->base = base;
dcrtc->num = num; dcrtc->num = drm->mode_config.num_crtc;
dcrtc->clk = ERR_PTR(-EINVAL); dcrtc->clk = ERR_PTR(-EINVAL);
dcrtc->csc_yuv_mode = CSC_AUTO; dcrtc->csc_yuv_mode = CSC_AUTO;
dcrtc->csc_rgb_mode = CSC_AUTO; dcrtc->csc_rgb_mode = CSC_AUTO;
...@@ -1072,9 +1101,18 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num, ...@@ -1072,9 +1101,18 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1); CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1); writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);
writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN); writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN);
writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
ret = devm_request_irq(dev, irq, armada_drm_irq, 0, "armada_drm_crtc",
dcrtc);
if (ret < 0) {
kfree(dcrtc);
return ret;
}
if (priv->variant->crtc_init) { if (dcrtc->variant->init) {
ret = priv->variant->crtc_init(dcrtc); ret = dcrtc->variant->init(dcrtc, dev);
if (ret) { if (ret) {
kfree(dcrtc); kfree(dcrtc);
return ret; return ret;
...@@ -1086,7 +1124,8 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num, ...@@ -1086,7 +1124,8 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
priv->dcrtc[dcrtc->num] = dcrtc; priv->dcrtc[dcrtc->num] = dcrtc;
drm_crtc_init(dev, &dcrtc->crtc, &armada_crtc_funcs); dcrtc->crtc.port = port;
drm_crtc_init(drm, &dcrtc->crtc, &armada_crtc_funcs);
drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs); drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop, drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop,
...@@ -1094,5 +1133,107 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num, ...@@ -1094,5 +1133,107 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
drm_object_attach_property(&dcrtc->crtc.base, priv->csc_rgb_prop, drm_object_attach_property(&dcrtc->crtc.base, priv->csc_rgb_prop,
dcrtc->csc_rgb_mode); dcrtc->csc_rgb_mode);
return armada_overlay_plane_create(dev, 1 << dcrtc->num); return armada_overlay_plane_create(drm, 1 << dcrtc->num);
}
static int
armada_lcd_bind(struct device *dev, struct device *master, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
struct drm_device *drm = data;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int irq = platform_get_irq(pdev, 0);
const struct armada_variant *variant;
struct device_node *port = NULL;
if (irq < 0)
return irq;
if (!dev->of_node) {
const struct platform_device_id *id;
id = platform_get_device_id(pdev);
if (!id)
return -ENXIO;
variant = (const struct armada_variant *)id->driver_data;
} else {
const struct of_device_id *match;
struct device_node *np, *parent = dev->of_node;
match = of_match_device(dev->driver->of_match_table, dev);
if (!match)
return -ENXIO;
np = of_get_child_by_name(parent, "ports");
if (np)
parent = np;
port = of_get_child_by_name(parent, "port");
of_node_put(np);
if (!port) {
dev_err(dev, "no port node found in %s\n",
parent->full_name);
return -ENXIO;
}
variant = match->data;
}
return armada_drm_crtc_create(drm, dev, res, irq, variant, port);
}
static void
armada_lcd_unbind(struct device *dev, struct device *master, void *data)
{
struct armada_crtc *dcrtc = dev_get_drvdata(dev);
armada_drm_crtc_destroy(&dcrtc->crtc);
} }
static const struct component_ops armada_lcd_ops = {
.bind = armada_lcd_bind,
.unbind = armada_lcd_unbind,
};
static int armada_lcd_probe(struct platform_device *pdev)
{
return component_add(&pdev->dev, &armada_lcd_ops);
}
static int armada_lcd_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &armada_lcd_ops);
return 0;
}
static struct of_device_id armada_lcd_of_match[] = {
{
.compatible = "marvell,dove-lcd",
.data = &armada510_ops,
},
{}
};
MODULE_DEVICE_TABLE(of, armada_lcd_of_match);
static const struct platform_device_id armada_lcd_platform_ids[] = {
{
.name = "armada-lcd",
.driver_data = (unsigned long)&armada510_ops,
}, {
.name = "armada-510-lcd",
.driver_data = (unsigned long)&armada510_ops,
},
{ },
};
MODULE_DEVICE_TABLE(platform, armada_lcd_platform_ids);
struct platform_driver armada_lcd_platform_driver = {
.probe = armada_lcd_probe,
.remove = armada_lcd_remove,
.driver = {
.name = "armada-lcd",
.owner = THIS_MODULE,
.of_match_table = armada_lcd_of_match,
},
.id_table = armada_lcd_platform_ids,
};
...@@ -32,12 +32,15 @@ struct armada_regs { ...@@ -32,12 +32,15 @@ struct armada_regs {
armada_reg_queue_mod(_r, _i, 0, 0, ~0) armada_reg_queue_mod(_r, _i, 0, 0, ~0)
struct armada_frame_work; struct armada_frame_work;
struct armada_variant;
struct armada_crtc { struct armada_crtc {
struct drm_crtc crtc; struct drm_crtc crtc;
const struct armada_variant *variant;
unsigned num; unsigned num;
void __iomem *base; void __iomem *base;
struct clk *clk; struct clk *clk;
struct clk *extclk[2];
struct { struct {
uint32_t spu_v_h_total; uint32_t spu_v_h_total;
uint32_t spu_v_porch; uint32_t spu_v_porch;
...@@ -72,12 +75,16 @@ struct armada_crtc { ...@@ -72,12 +75,16 @@ struct armada_crtc {
}; };
#define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *); struct device_node;
int armada_drm_crtc_create(struct drm_device *, struct device *,
struct resource *, int, const struct armada_variant *,
struct device_node *);
void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
void armada_drm_crtc_irq(struct armada_crtc *, u32);
void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
void armada_drm_crtc_enable_irq(struct armada_crtc *, u32); void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *); void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
extern struct platform_driver armada_lcd_platform_driver;
#endif #endif
...@@ -59,26 +59,23 @@ void armada_drm_vbl_event_remove_unlocked(struct armada_crtc *, ...@@ -59,26 +59,23 @@ void armada_drm_vbl_event_remove_unlocked(struct armada_crtc *,
struct armada_private; struct armada_private;
struct armada_variant { struct armada_variant {
bool has_spu_adv_reg; bool has_spu_adv_reg;
uint32_t spu_adv_reg; uint32_t spu_adv_reg;
int (*init)(struct armada_private *, struct device *); int (*init)(struct armada_crtc *, struct device *);
int (*crtc_init)(struct armada_crtc *); int (*compute_clock)(struct armada_crtc *,
int (*crtc_compute_clock)(struct armada_crtc *, const struct drm_display_mode *,
const struct drm_display_mode *, uint32_t *);
uint32_t *);
}; };
/* Variant ops */ /* Variant ops */
extern const struct armada_variant armada510_ops; extern const struct armada_variant armada510_ops;
struct armada_private { struct armada_private {
const struct armada_variant *variant;
struct work_struct fb_unref_work; struct work_struct fb_unref_work;
DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8); DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8);
struct drm_fb_helper *fbdev; struct drm_fb_helper *fbdev;
struct armada_crtc *dcrtc[2]; struct armada_crtc *dcrtc[2];
struct drm_mm linear; struct drm_mm linear;
struct clk *extclk[2];
struct drm_property *csc_yuv_prop; struct drm_property *csc_yuv_prop;
struct drm_property *csc_rgb_prop; struct drm_property *csc_rgb_prop;
struct drm_property *colorkey_prop; struct drm_property *colorkey_prop;
......
...@@ -6,7 +6,9 @@ ...@@ -6,7 +6,9 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/component.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_graph.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include "armada_crtc.h" #include "armada_crtc.h"
...@@ -52,6 +54,11 @@ static const struct armada_drm_slave_config tda19988_config = { ...@@ -52,6 +54,11 @@ static const struct armada_drm_slave_config tda19988_config = {
}; };
#endif #endif
static bool is_componentized(struct device *dev)
{
return dev->of_node || dev->platform_data;
}
static void armada_drm_unref_work(struct work_struct *work) static void armada_drm_unref_work(struct work_struct *work)
{ {
struct armada_private *priv = struct armada_private *priv =
...@@ -85,6 +92,7 @@ void armada_drm_queue_unref_work(struct drm_device *dev, ...@@ -85,6 +92,7 @@ void armada_drm_queue_unref_work(struct drm_device *dev,
static int armada_drm_load(struct drm_device *dev, unsigned long flags) static int armada_drm_load(struct drm_device *dev, unsigned long flags)
{ {
const struct platform_device_id *id; const struct platform_device_id *id;
const struct armada_variant *variant;
struct armada_private *priv; struct armada_private *priv;
struct resource *res[ARRAY_SIZE(priv->dcrtc)]; struct resource *res[ARRAY_SIZE(priv->dcrtc)];
struct resource *mem = NULL; struct resource *mem = NULL;
...@@ -107,7 +115,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) ...@@ -107,7 +115,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
return -EINVAL; return -EINVAL;
} }
if (!res[0] || !mem) if (!mem)
return -ENXIO; return -ENXIO;
if (!devm_request_mem_region(dev->dev, mem->start, if (!devm_request_mem_region(dev->dev, mem->start,
...@@ -128,11 +136,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) ...@@ -128,11 +136,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
if (!id) if (!id)
return -ENXIO; return -ENXIO;
priv->variant = (struct armada_variant *)id->driver_data; variant = (const struct armada_variant *)id->driver_data;
ret = priv->variant->init(priv, dev->dev);
if (ret)
return ret;
INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work); INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
INIT_KFIFO(priv->fb_unref); INIT_KFIFO(priv->fb_unref);
...@@ -155,40 +159,50 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) ...@@ -155,40 +159,50 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
/* Create all LCD controllers */ /* Create all LCD controllers */
for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) { for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
int irq;
if (!res[n]) if (!res[n])
break; break;
ret = armada_drm_crtc_create(dev, n, res[n]); irq = platform_get_irq(dev->platformdev, n);
if (irq < 0)
goto err_kms;
ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq,
variant, NULL);
if (ret) if (ret)
goto err_kms; goto err_kms;
} }
if (is_componentized(dev->dev)) {
ret = component_bind_all(dev->dev, dev);
if (ret)
goto err_kms;
} else {
#ifdef CONFIG_DRM_ARMADA_TDA1998X #ifdef CONFIG_DRM_ARMADA_TDA1998X
ret = armada_drm_connector_slave_create(dev, &tda19988_config); ret = armada_drm_connector_slave_create(dev, &tda19988_config);
if (ret) if (ret)
goto err_kms; goto err_kms;
#endif #endif
}
ret = drm_vblank_init(dev, n); ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
if (ret)
goto err_kms;
ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
if (ret) if (ret)
goto err_kms; goto err_comp;
dev->vblank_disable_allowed = 1; dev->vblank_disable_allowed = 1;
ret = armada_fbdev_init(dev); ret = armada_fbdev_init(dev);
if (ret) if (ret)
goto err_irq; goto err_comp;
drm_kms_helper_poll_init(dev); drm_kms_helper_poll_init(dev);
return 0; return 0;
err_irq: err_comp:
drm_irq_uninstall(dev); if (is_componentized(dev->dev))
component_unbind_all(dev->dev, dev);
err_kms: err_kms:
drm_mode_config_cleanup(dev); drm_mode_config_cleanup(dev);
drm_mm_takedown(&priv->linear); drm_mm_takedown(&priv->linear);
...@@ -203,7 +217,10 @@ static int armada_drm_unload(struct drm_device *dev) ...@@ -203,7 +217,10 @@ static int armada_drm_unload(struct drm_device *dev)
drm_kms_helper_poll_fini(dev); drm_kms_helper_poll_fini(dev);
armada_fbdev_fini(dev); armada_fbdev_fini(dev);
drm_irq_uninstall(dev);
if (is_componentized(dev->dev))
component_unbind_all(dev->dev, dev);
drm_mode_config_cleanup(dev); drm_mode_config_cleanup(dev);
drm_mm_takedown(&priv->linear); drm_mm_takedown(&priv->linear);
flush_work(&priv->fb_unref_work); flush_work(&priv->fb_unref_work);
...@@ -259,52 +276,6 @@ static void armada_drm_disable_vblank(struct drm_device *dev, int crtc) ...@@ -259,52 +276,6 @@ static void armada_drm_disable_vblank(struct drm_device *dev, int crtc)
armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA); armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
} }
static irqreturn_t armada_drm_irq_handler(int irq, void *arg)
{
struct drm_device *dev = arg;
struct armada_private *priv = dev->dev_private;
struct armada_crtc *dcrtc = priv->dcrtc[0];
uint32_t v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
irqreturn_t handled = IRQ_NONE;
/*
* This is rediculous - rather than writing bits to clear, we
* have to set the actual status register value. This is racy.
*/
writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
/* Mask out those interrupts we haven't enabled */
v = stat & dcrtc->irq_ena;
if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
armada_drm_crtc_irq(dcrtc, stat);
handled = IRQ_HANDLED;
}
return handled;
}
static int armada_drm_irq_postinstall(struct drm_device *dev)
{
struct armada_private *priv = dev->dev_private;
struct armada_crtc *dcrtc = priv->dcrtc[0];
spin_lock_irq(&dev->vbl_lock);
writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
spin_unlock_irq(&dev->vbl_lock);
return 0;
}
static void armada_drm_irq_uninstall(struct drm_device *dev)
{
struct armada_private *priv = dev->dev_private;
struct armada_crtc *dcrtc = priv->dcrtc[0];
writel(0, dcrtc->base + LCD_SPU_IRQ_ENA);
}
static struct drm_ioctl_desc armada_ioctls[] = { static struct drm_ioctl_desc armada_ioctls[] = {
DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl, DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
DRM_UNLOCKED), DRM_UNLOCKED),
...@@ -340,9 +311,6 @@ static struct drm_driver armada_drm_driver = { ...@@ -340,9 +311,6 @@ static struct drm_driver armada_drm_driver = {
.get_vblank_counter = drm_vblank_count, .get_vblank_counter = drm_vblank_count,
.enable_vblank = armada_drm_enable_vblank, .enable_vblank = armada_drm_enable_vblank,
.disable_vblank = armada_drm_disable_vblank, .disable_vblank = armada_drm_disable_vblank,
.irq_handler = armada_drm_irq_handler,
.irq_postinstall = armada_drm_irq_postinstall,
.irq_uninstall = armada_drm_irq_uninstall,
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
.debugfs_init = armada_drm_debugfs_init, .debugfs_init = armada_drm_debugfs_init,
.debugfs_cleanup = armada_drm_debugfs_cleanup, .debugfs_cleanup = armada_drm_debugfs_cleanup,
...@@ -362,19 +330,140 @@ static struct drm_driver armada_drm_driver = { ...@@ -362,19 +330,140 @@ static struct drm_driver armada_drm_driver = {
.desc = "Armada SoC DRM", .desc = "Armada SoC DRM",
.date = "20120730", .date = "20120730",
.driver_features = DRIVER_GEM | DRIVER_MODESET | .driver_features = DRIVER_GEM | DRIVER_MODESET |
DRIVER_HAVE_IRQ | DRIVER_PRIME, DRIVER_PRIME,
.ioctls = armada_ioctls, .ioctls = armada_ioctls,
.fops = &armada_drm_fops, .fops = &armada_drm_fops,
}; };
static int armada_drm_bind(struct device *dev)
{
return drm_platform_init(&armada_drm_driver, to_platform_device(dev));
}
static void armada_drm_unbind(struct device *dev)
{
drm_put_dev(dev_get_drvdata(dev));
}
static int compare_of(struct device *dev, void *data)
{
return dev->of_node == data;
}
static int compare_dev_name(struct device *dev, void *data)
{
const char *name = data;
return !strcmp(dev_name(dev), name);
}
static void armada_add_endpoints(struct device *dev,
struct component_match **match, struct device_node *port)
{
struct device_node *ep, *remote;
for_each_child_of_node(port, ep) {
remote = of_graph_get_remote_port_parent(ep);
if (!remote || !of_device_is_available(remote)) {
of_node_put(remote);
continue;
} else if (!of_device_is_available(remote->parent)) {
dev_warn(dev, "parent device of %s is not available\n",
remote->full_name);
of_node_put(remote);
continue;
}
component_match_add(dev, match, compare_of, remote);
of_node_put(remote);
}
}
static int armada_drm_find_components(struct device *dev,
struct component_match **match)
{
struct device_node *port;
int i;
if (dev->of_node) {
struct device_node *np = dev->of_node;
for (i = 0; ; i++) {
port = of_parse_phandle(np, "ports", i);
if (!port)
break;
component_match_add(dev, match, compare_of, port);
of_node_put(port);
}
if (i == 0) {
dev_err(dev, "missing 'ports' property\n");
return -ENODEV;
}
for (i = 0; ; i++) {
port = of_parse_phandle(np, "ports", i);
if (!port)
break;
armada_add_endpoints(dev, match, port);
of_node_put(port);
}
} else if (dev->platform_data) {
char **devices = dev->platform_data;
struct device *d;
for (i = 0; devices[i]; i++)
component_match_add(dev, match, compare_dev_name,
devices[i]);
if (i == 0) {
dev_err(dev, "missing 'ports' property\n");
return -ENODEV;
}
for (i = 0; devices[i]; i++) {
d = bus_find_device_by_name(&platform_bus_type, NULL,
devices[i]);
if (d && d->of_node) {
for_each_child_of_node(d->of_node, port)
armada_add_endpoints(dev, match, port);
}
put_device(d);
}
}
return 0;
}
static const struct component_master_ops armada_master_ops = {
.bind = armada_drm_bind,
.unbind = armada_drm_unbind,
};
static int armada_drm_probe(struct platform_device *pdev) static int armada_drm_probe(struct platform_device *pdev)
{ {
return drm_platform_init(&armada_drm_driver, pdev); if (is_componentized(&pdev->dev)) {
struct component_match *match = NULL;
int ret;
ret = armada_drm_find_components(&pdev->dev, &match);
if (ret < 0)
return ret;
return component_master_add_with_match(&pdev->dev,
&armada_master_ops, match);
} else {
return drm_platform_init(&armada_drm_driver, pdev);
}
} }
static int armada_drm_remove(struct platform_device *pdev) static int armada_drm_remove(struct platform_device *pdev)
{ {
drm_put_dev(platform_get_drvdata(pdev)); if (is_componentized(&pdev->dev))
component_master_del(&pdev->dev, &armada_master_ops);
else
drm_put_dev(platform_get_drvdata(pdev));
return 0; return 0;
} }
...@@ -402,14 +491,24 @@ static struct platform_driver armada_drm_platform_driver = { ...@@ -402,14 +491,24 @@ static struct platform_driver armada_drm_platform_driver = {
static int __init armada_drm_init(void) static int __init armada_drm_init(void)
{ {
int ret;
armada_drm_driver.num_ioctls = ARRAY_SIZE(armada_ioctls); armada_drm_driver.num_ioctls = ARRAY_SIZE(armada_ioctls);
return platform_driver_register(&armada_drm_platform_driver);
ret = platform_driver_register(&armada_lcd_platform_driver);
if (ret)
return ret;
ret = platform_driver_register(&armada_drm_platform_driver);
if (ret)
platform_driver_unregister(&armada_lcd_platform_driver);
return ret;
} }
module_init(armada_drm_init); module_init(armada_drm_init);
static void __exit armada_drm_exit(void) static void __exit armada_drm_exit(void)
{ {
platform_driver_unregister(&armada_drm_platform_driver); platform_driver_unregister(&armada_drm_platform_driver);
platform_driver_unregister(&armada_lcd_platform_driver);
} }
module_exit(armada_drm_exit); module_exit(armada_drm_exit);
......
...@@ -131,7 +131,7 @@ static int armada_fb_probe(struct drm_fb_helper *fbh, ...@@ -131,7 +131,7 @@ static int armada_fb_probe(struct drm_fb_helper *fbh,
return ret; return ret;
} }
static struct drm_fb_helper_funcs armada_fb_helper_funcs = { static const struct drm_fb_helper_funcs armada_fb_helper_funcs = {
.gamma_set = armada_drm_crtc_gamma_set, .gamma_set = armada_drm_crtc_gamma_set,
.gamma_get = armada_drm_crtc_gamma_get, .gamma_get = armada_drm_crtc_gamma_get,
.fb_probe = armada_fb_probe, .fb_probe = armada_fb_probe,
...@@ -149,7 +149,7 @@ int armada_fbdev_init(struct drm_device *dev) ...@@ -149,7 +149,7 @@ int armada_fbdev_init(struct drm_device *dev)
priv->fbdev = fbh; priv->fbdev = fbh;
fbh->funcs = &armada_fb_helper_funcs; drm_fb_helper_prepare(dev, fbh, &armada_fb_helper_funcs);
ret = drm_fb_helper_init(dev, fbh, 1, 1); ret = drm_fb_helper_init(dev, fbh, 1, 1);
if (ret) { if (ret) {
......
...@@ -48,7 +48,7 @@ static void armada_drm_connector_destroy(struct drm_connector *conn) ...@@ -48,7 +48,7 @@ static void armada_drm_connector_destroy(struct drm_connector *conn)
{ {
struct armada_connector *dconn = drm_to_armada_conn(conn); struct armada_connector *dconn = drm_to_armada_conn(conn);
drm_sysfs_connector_remove(conn); drm_connector_unregister(conn);
drm_connector_cleanup(conn); drm_connector_cleanup(conn);
kfree(dconn); kfree(dconn);
} }
...@@ -141,7 +141,7 @@ int armada_output_create(struct drm_device *dev, ...@@ -141,7 +141,7 @@ int armada_output_create(struct drm_device *dev,
if (ret) if (ret)
goto err_conn; goto err_conn;
ret = drm_sysfs_connector_add(&dconn->conn); ret = drm_connector_register(&dconn->conn);
if (ret) if (ret)
goto err_sysfs; goto err_sysfs;
......
...@@ -362,7 +362,7 @@ static inline int ast_bo_reserve(struct ast_bo *bo, bool no_wait) ...@@ -362,7 +362,7 @@ static inline int ast_bo_reserve(struct ast_bo *bo, bool no_wait)
{ {
int ret; int ret;
ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0); ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
if (ret) { if (ret) {
if (ret != -ERESTARTSYS && ret != -EBUSY) if (ret != -ERESTARTSYS && ret != -EBUSY)
DRM_ERROR("reserve failed %p\n", bo); DRM_ERROR("reserve failed %p\n", bo);
......
...@@ -287,7 +287,7 @@ static void ast_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, ...@@ -287,7 +287,7 @@ static void ast_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
*blue = ast_crtc->lut_b[regno] << 8; *blue = ast_crtc->lut_b[regno] << 8;
} }
static struct drm_fb_helper_funcs ast_fb_helper_funcs = { static const struct drm_fb_helper_funcs ast_fb_helper_funcs = {
.gamma_set = ast_fb_gamma_set, .gamma_set = ast_fb_gamma_set,
.gamma_get = ast_fb_gamma_get, .gamma_get = ast_fb_gamma_get,
.fb_probe = astfb_create, .fb_probe = astfb_create,
...@@ -328,8 +328,10 @@ int ast_fbdev_init(struct drm_device *dev) ...@@ -328,8 +328,10 @@ int ast_fbdev_init(struct drm_device *dev)
return -ENOMEM; return -ENOMEM;
ast->fbdev = afbdev; ast->fbdev = afbdev;
afbdev->helper.funcs = &ast_fb_helper_funcs;
spin_lock_init(&afbdev->dirty_lock); spin_lock_init(&afbdev->dirty_lock);
drm_fb_helper_prepare(dev, &afbdev->helper, &ast_fb_helper_funcs);
ret = drm_fb_helper_init(dev, &afbdev->helper, ret = drm_fb_helper_init(dev, &afbdev->helper,
1, 1); 1, 1);
if (ret) { if (ret) {
......
...@@ -667,17 +667,9 @@ static void ast_encoder_destroy(struct drm_encoder *encoder) ...@@ -667,17 +667,9 @@ static void ast_encoder_destroy(struct drm_encoder *encoder)
static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector) static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector)
{ {
int enc_id = connector->encoder_ids[0]; int enc_id = connector->encoder_ids[0];
struct drm_mode_object *obj;
struct drm_encoder *encoder;
/* pick the encoder ids */ /* pick the encoder ids */
if (enc_id) { if (enc_id)
obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); return drm_encoder_find(connector->dev, enc_id);
if (!obj)
return NULL;
encoder = obj_to_encoder(obj);
return encoder;
}
return NULL; return NULL;
} }
...@@ -829,7 +821,7 @@ static void ast_connector_destroy(struct drm_connector *connector) ...@@ -829,7 +821,7 @@ static void ast_connector_destroy(struct drm_connector *connector)
{ {
struct ast_connector *ast_connector = to_ast_connector(connector); struct ast_connector *ast_connector = to_ast_connector(connector);
ast_i2c_destroy(ast_connector->i2c); ast_i2c_destroy(ast_connector->i2c);
drm_sysfs_connector_remove(connector); drm_connector_unregister(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(connector); kfree(connector);
} }
...@@ -871,7 +863,7 @@ static int ast_connector_init(struct drm_device *dev) ...@@ -871,7 +863,7 @@ static int ast_connector_init(struct drm_device *dev)
connector->interlace_allowed = 0; connector->interlace_allowed = 0;
connector->doublescan_allowed = 0; connector->doublescan_allowed = 0;
drm_sysfs_connector_add(connector); drm_connector_register(connector);
connector->polled = DRM_CONNECTOR_POLL_CONNECT; connector->polled = DRM_CONNECTOR_POLL_CONNECT;
......
...@@ -97,6 +97,7 @@ static struct drm_driver bochs_driver = { ...@@ -97,6 +97,7 @@ static struct drm_driver bochs_driver = {
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* pm interface */ /* pm interface */
#ifdef CONFIG_PM_SLEEP
static int bochs_pm_suspend(struct device *dev) static int bochs_pm_suspend(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
...@@ -131,6 +132,7 @@ static int bochs_pm_resume(struct device *dev) ...@@ -131,6 +132,7 @@ static int bochs_pm_resume(struct device *dev)
drm_kms_helper_poll_enable(drm_dev); drm_kms_helper_poll_enable(drm_dev);
return 0; return 0;
} }
#endif
static const struct dev_pm_ops bochs_pm_ops = { static const struct dev_pm_ops bochs_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend, SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend,
......
...@@ -72,7 +72,7 @@ static int bochsfb_create(struct drm_fb_helper *helper, ...@@ -72,7 +72,7 @@ static int bochsfb_create(struct drm_fb_helper *helper,
bo = gem_to_bochs_bo(gobj); bo = gem_to_bochs_bo(gobj);
ret = ttm_bo_reserve(&bo->bo, true, false, false, 0); ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
if (ret) if (ret)
return ret; return ret;
...@@ -179,7 +179,7 @@ void bochs_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, ...@@ -179,7 +179,7 @@ void bochs_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
*blue = regno; *blue = regno;
} }
static struct drm_fb_helper_funcs bochs_fb_helper_funcs = { static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
.gamma_set = bochs_fb_gamma_set, .gamma_set = bochs_fb_gamma_set,
.gamma_get = bochs_fb_gamma_get, .gamma_get = bochs_fb_gamma_get,
.fb_probe = bochsfb_create, .fb_probe = bochsfb_create,
...@@ -189,7 +189,8 @@ int bochs_fbdev_init(struct bochs_device *bochs) ...@@ -189,7 +189,8 @@ int bochs_fbdev_init(struct bochs_device *bochs)
{ {
int ret; int ret;
bochs->fb.helper.funcs = &bochs_fb_helper_funcs; drm_fb_helper_prepare(bochs->dev, &bochs->fb.helper,
&bochs_fb_helper_funcs);
ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper, ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper,
1, 1); 1, 1);
......
...@@ -53,7 +53,7 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -53,7 +53,7 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
if (old_fb) { if (old_fb) {
bochs_fb = to_bochs_framebuffer(old_fb); bochs_fb = to_bochs_framebuffer(old_fb);
bo = gem_to_bochs_bo(bochs_fb->obj); bo = gem_to_bochs_bo(bochs_fb->obj);
ret = ttm_bo_reserve(&bo->bo, true, false, false, 0); ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
if (ret) { if (ret) {
DRM_ERROR("failed to reserve old_fb bo\n"); DRM_ERROR("failed to reserve old_fb bo\n");
} else { } else {
...@@ -67,7 +67,7 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -67,7 +67,7 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
bochs_fb = to_bochs_framebuffer(crtc->primary->fb); bochs_fb = to_bochs_framebuffer(crtc->primary->fb);
bo = gem_to_bochs_bo(bochs_fb->obj); bo = gem_to_bochs_bo(bochs_fb->obj);
ret = ttm_bo_reserve(&bo->bo, true, false, false, 0); ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
if (ret) if (ret)
return ret; return ret;
...@@ -216,18 +216,9 @@ static struct drm_encoder * ...@@ -216,18 +216,9 @@ static struct drm_encoder *
bochs_connector_best_encoder(struct drm_connector *connector) bochs_connector_best_encoder(struct drm_connector *connector)
{ {
int enc_id = connector->encoder_ids[0]; int enc_id = connector->encoder_ids[0];
struct drm_mode_object *obj;
struct drm_encoder *encoder;
/* pick the encoder ids */ /* pick the encoder ids */
if (enc_id) { if (enc_id)
obj = drm_mode_object_find(connector->dev, enc_id, return drm_encoder_find(connector->dev, enc_id);
DRM_MODE_OBJECT_ENCODER);
if (!obj)
return NULL;
encoder = obj_to_encoder(obj);
return encoder;
}
return NULL; return NULL;
} }
......
...@@ -387,7 +387,7 @@ int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel, ...@@ -387,7 +387,7 @@ int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel,
*obj = NULL; *obj = NULL;
size = ALIGN(size, PAGE_SIZE); size = PAGE_ALIGN(size);
if (size == 0) if (size == 0)
return -EINVAL; return -EINVAL;
......
...@@ -328,7 +328,7 @@ int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder, ...@@ -328,7 +328,7 @@ int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
} }
drm_connector_helper_add(&ptn_bridge->connector, drm_connector_helper_add(&ptn_bridge->connector,
&ptn3460_connector_helper_funcs); &ptn3460_connector_helper_funcs);
drm_sysfs_connector_add(&ptn_bridge->connector); drm_connector_register(&ptn_bridge->connector);
drm_mode_connector_attach_encoder(&ptn_bridge->connector, encoder); drm_mode_connector_attach_encoder(&ptn_bridge->connector, encoder);
return 0; return 0;
......
...@@ -76,6 +76,7 @@ static void cirrus_pci_remove(struct pci_dev *pdev) ...@@ -76,6 +76,7 @@ static void cirrus_pci_remove(struct pci_dev *pdev)
drm_put_dev(dev); drm_put_dev(dev);
} }
#ifdef CONFIG_PM_SLEEP
static int cirrus_pm_suspend(struct device *dev) static int cirrus_pm_suspend(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
...@@ -110,6 +111,7 @@ static int cirrus_pm_resume(struct device *dev) ...@@ -110,6 +111,7 @@ static int cirrus_pm_resume(struct device *dev)
drm_kms_helper_poll_enable(drm_dev); drm_kms_helper_poll_enable(drm_dev);
return 0; return 0;
} }
#endif
static const struct file_operations cirrus_driver_fops = { static const struct file_operations cirrus_driver_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -241,7 +241,7 @@ static inline int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait) ...@@ -241,7 +241,7 @@ static inline int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait)
{ {
int ret; int ret;
ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0); ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
if (ret) { if (ret) {
if (ret != -ERESTARTSYS && ret != -EBUSY) if (ret != -ERESTARTSYS && ret != -EBUSY)
DRM_ERROR("reserve failed %p\n", bo); DRM_ERROR("reserve failed %p\n", bo);
......
...@@ -288,7 +288,7 @@ static int cirrus_fbdev_destroy(struct drm_device *dev, ...@@ -288,7 +288,7 @@ static int cirrus_fbdev_destroy(struct drm_device *dev,
return 0; return 0;
} }
static struct drm_fb_helper_funcs cirrus_fb_helper_funcs = { static const struct drm_fb_helper_funcs cirrus_fb_helper_funcs = {
.gamma_set = cirrus_crtc_fb_gamma_set, .gamma_set = cirrus_crtc_fb_gamma_set,
.gamma_get = cirrus_crtc_fb_gamma_get, .gamma_get = cirrus_crtc_fb_gamma_get,
.fb_probe = cirrusfb_create, .fb_probe = cirrusfb_create,
...@@ -306,9 +306,11 @@ int cirrus_fbdev_init(struct cirrus_device *cdev) ...@@ -306,9 +306,11 @@ int cirrus_fbdev_init(struct cirrus_device *cdev)
return -ENOMEM; return -ENOMEM;
cdev->mode_info.gfbdev = gfbdev; cdev->mode_info.gfbdev = gfbdev;
gfbdev->helper.funcs = &cirrus_fb_helper_funcs;
spin_lock_init(&gfbdev->dirty_lock); spin_lock_init(&gfbdev->dirty_lock);
drm_fb_helper_prepare(cdev->dev, &gfbdev->helper,
&cirrus_fb_helper_funcs);
ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper, ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,
cdev->num_crtc, CIRRUSFB_CONN_LIMIT); cdev->num_crtc, CIRRUSFB_CONN_LIMIT);
if (ret) { if (ret) {
......
...@@ -509,19 +509,9 @@ static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector ...@@ -509,19 +509,9 @@ static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
*connector) *connector)
{ {
int enc_id = connector->encoder_ids[0]; int enc_id = connector->encoder_ids[0];
struct drm_mode_object *obj;
struct drm_encoder *encoder;
/* pick the encoder ids */ /* pick the encoder ids */
if (enc_id) { if (enc_id)
obj = return drm_encoder_find(connector->dev, enc_id);
drm_mode_object_find(connector->dev, enc_id,
DRM_MODE_OBJECT_ENCODER);
if (!obj)
return NULL;
encoder = obj_to_encoder(obj);
return encoder;
}
return NULL; return NULL;
} }
......
...@@ -80,11 +80,7 @@ int drm_buffer_alloc(struct drm_buffer **buf, int size) ...@@ -80,11 +80,7 @@ int drm_buffer_alloc(struct drm_buffer **buf, int size)
error_out: error_out:
/* Only last element can be null pointer so check for it first. */ for (; idx >= 0; --idx)
if ((*buf)->data[idx])
kfree((*buf)->data[idx]);
for (--idx; idx >= 0; --idx)
kfree((*buf)->data[idx]); kfree((*buf)->data[idx]);
kfree(*buf); kfree(*buf);
......
...@@ -1217,7 +1217,6 @@ int drm_infobufs(struct drm_device *dev, void *data, ...@@ -1217,7 +1217,6 @@ int drm_infobufs(struct drm_device *dev, void *data,
struct drm_buf_desc __user *to = struct drm_buf_desc __user *to =
&request->list[count]; &request->list[count];
struct drm_buf_entry *from = &dma->bufs[i]; struct drm_buf_entry *from = &dma->bufs[i];
struct drm_freelist *list = &dma->bufs[i].freelist;
if (copy_to_user(&to->count, if (copy_to_user(&to->count,
&from->buf_count, &from->buf_count,
sizeof(from->buf_count)) || sizeof(from->buf_count)) ||
...@@ -1225,19 +1224,19 @@ int drm_infobufs(struct drm_device *dev, void *data, ...@@ -1225,19 +1224,19 @@ int drm_infobufs(struct drm_device *dev, void *data,
&from->buf_size, &from->buf_size,
sizeof(from->buf_size)) || sizeof(from->buf_size)) ||
copy_to_user(&to->low_mark, copy_to_user(&to->low_mark,
&list->low_mark, &from->low_mark,
sizeof(list->low_mark)) || sizeof(from->low_mark)) ||
copy_to_user(&to->high_mark, copy_to_user(&to->high_mark,
&list->high_mark, &from->high_mark,
sizeof(list->high_mark))) sizeof(from->high_mark)))
return -EFAULT; return -EFAULT;
DRM_DEBUG("%d %d %d %d %d\n", DRM_DEBUG("%d %d %d %d %d\n",
i, i,
dma->bufs[i].buf_count, dma->bufs[i].buf_count,
dma->bufs[i].buf_size, dma->bufs[i].buf_size,
dma->bufs[i].freelist.low_mark, dma->bufs[i].low_mark,
dma->bufs[i].freelist.high_mark); dma->bufs[i].high_mark);
++count; ++count;
} }
} }
...@@ -1290,8 +1289,8 @@ int drm_markbufs(struct drm_device *dev, void *data, ...@@ -1290,8 +1289,8 @@ int drm_markbufs(struct drm_device *dev, void *data,
if (request->high_mark < 0 || request->high_mark > entry->buf_count) if (request->high_mark < 0 || request->high_mark > entry->buf_count)
return -EINVAL; return -EINVAL;
entry->freelist.low_mark = request->low_mark; entry->low_mark = request->low_mark;
entry->freelist.high_mark = request->high_mark; entry->high_mark = request->high_mark;
return 0; return 0;
} }
......
/**
* \file drm_context.c
* IOCTLs for generic contexts
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
*/
/* /*
* Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com * Legacy: Generic DRM Contexts
* *
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved. * All Rights Reserved.
* *
* Author: Rickard E. (Rik) Faith <faith@valinux.com>
* Author: Gareth Hughes <gareth@valinux.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation * to deal in the Software without restriction, including without limitation
...@@ -33,14 +28,14 @@ ...@@ -33,14 +28,14 @@
* OTHER DEALINGS IN THE SOFTWARE. * OTHER DEALINGS IN THE SOFTWARE.
*/ */
/*
* ChangeLog:
* 2001-11-16 Torsten Duwe <duwe@caldera.de>
* added context constructor/destructor hooks,
* needed by SiS driver's memory management.
*/
#include <drm/drmP.h> #include <drm/drmP.h>
#include "drm_legacy.h"
struct drm_ctx_list {
struct list_head head;
drm_context_t handle;
struct drm_file *tag;
};
/******************************************************************/ /******************************************************************/
/** \name Context bitmap support */ /** \name Context bitmap support */
...@@ -56,7 +51,7 @@ ...@@ -56,7 +51,7 @@
* in drm_device::ctx_idr, while holding the drm_device::struct_mutex * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
* lock. * lock.
*/ */
void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle) void drm_legacy_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
{ {
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
idr_remove(&dev->ctx_idr, ctx_handle); idr_remove(&dev->ctx_idr, ctx_handle);
...@@ -72,7 +67,7 @@ void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle) ...@@ -72,7 +67,7 @@ void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
* Allocate a new idr from drm_device::ctx_idr while holding the * Allocate a new idr from drm_device::ctx_idr while holding the
* drm_device::struct_mutex lock. * drm_device::struct_mutex lock.
*/ */
static int drm_ctxbitmap_next(struct drm_device * dev) static int drm_legacy_ctxbitmap_next(struct drm_device * dev)
{ {
int ret; int ret;
...@@ -90,7 +85,7 @@ static int drm_ctxbitmap_next(struct drm_device * dev) ...@@ -90,7 +85,7 @@ static int drm_ctxbitmap_next(struct drm_device * dev)
* *
* Initialise the drm_device::ctx_idr * Initialise the drm_device::ctx_idr
*/ */
int drm_ctxbitmap_init(struct drm_device * dev) int drm_legacy_ctxbitmap_init(struct drm_device * dev)
{ {
idr_init(&dev->ctx_idr); idr_init(&dev->ctx_idr);
return 0; return 0;
...@@ -104,13 +99,43 @@ int drm_ctxbitmap_init(struct drm_device * dev) ...@@ -104,13 +99,43 @@ int drm_ctxbitmap_init(struct drm_device * dev)
* Free all idr members using drm_ctx_sarea_free helper function * Free all idr members using drm_ctx_sarea_free helper function
* while holding the drm_device::struct_mutex lock. * while holding the drm_device::struct_mutex lock.
*/ */
void drm_ctxbitmap_cleanup(struct drm_device * dev) void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev)
{ {
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
idr_destroy(&dev->ctx_idr); idr_destroy(&dev->ctx_idr);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
} }
/**
* drm_ctxbitmap_flush() - Flush all contexts owned by a file
* @dev: DRM device to operate on
* @file: Open file to flush contexts for
*
* This iterates over all contexts on @dev and drops them if they're owned by
* @file. Note that after this call returns, new contexts might be added if
* the file is still alive.
*/
void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file)
{
struct drm_ctx_list *pos, *tmp;
mutex_lock(&dev->ctxlist_mutex);
list_for_each_entry_safe(pos, tmp, &dev->ctxlist, head) {
if (pos->tag == file &&
pos->handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_dtor)
dev->driver->context_dtor(dev, pos->handle);
drm_legacy_ctxbitmap_free(dev, pos->handle);
list_del(&pos->head);
kfree(pos);
}
}
mutex_unlock(&dev->ctxlist_mutex);
}
/*@}*/ /*@}*/
/******************************************************************/ /******************************************************************/
...@@ -129,8 +154,8 @@ void drm_ctxbitmap_cleanup(struct drm_device * dev) ...@@ -129,8 +154,8 @@ void drm_ctxbitmap_cleanup(struct drm_device * dev)
* Gets the map from drm_device::ctx_idr with the handle specified and * Gets the map from drm_device::ctx_idr with the handle specified and
* returns its handle. * returns its handle.
*/ */
int drm_getsareactx(struct drm_device *dev, void *data, int drm_legacy_getsareactx(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_ctx_priv_map *request = data; struct drm_ctx_priv_map *request = data;
struct drm_local_map *map; struct drm_local_map *map;
...@@ -173,8 +198,8 @@ int drm_getsareactx(struct drm_device *dev, void *data, ...@@ -173,8 +198,8 @@ int drm_getsareactx(struct drm_device *dev, void *data,
* Searches the mapping specified in \p arg and update the entry in * Searches the mapping specified in \p arg and update the entry in
* drm_device::ctx_idr with it. * drm_device::ctx_idr with it.
*/ */
int drm_setsareactx(struct drm_device *dev, void *data, int drm_legacy_setsareactx(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_ctx_priv_map *request = data; struct drm_ctx_priv_map *request = data;
struct drm_local_map *map = NULL; struct drm_local_map *map = NULL;
...@@ -273,8 +298,8 @@ static int drm_context_switch_complete(struct drm_device *dev, ...@@ -273,8 +298,8 @@ static int drm_context_switch_complete(struct drm_device *dev,
* \param arg user argument pointing to a drm_ctx_res structure. * \param arg user argument pointing to a drm_ctx_res structure.
* \return zero on success or a negative number on failure. * \return zero on success or a negative number on failure.
*/ */
int drm_resctx(struct drm_device *dev, void *data, int drm_legacy_resctx(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_ctx_res *res = data; struct drm_ctx_res *res = data;
struct drm_ctx ctx; struct drm_ctx ctx;
...@@ -304,16 +329,16 @@ int drm_resctx(struct drm_device *dev, void *data, ...@@ -304,16 +329,16 @@ int drm_resctx(struct drm_device *dev, void *data,
* *
* Get a new handle for the context and copy to userspace. * Get a new handle for the context and copy to userspace.
*/ */
int drm_addctx(struct drm_device *dev, void *data, int drm_legacy_addctx(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_ctx_list *ctx_entry; struct drm_ctx_list *ctx_entry;
struct drm_ctx *ctx = data; struct drm_ctx *ctx = data;
ctx->handle = drm_ctxbitmap_next(dev); ctx->handle = drm_legacy_ctxbitmap_next(dev);
if (ctx->handle == DRM_KERNEL_CONTEXT) { if (ctx->handle == DRM_KERNEL_CONTEXT) {
/* Skip kernel's context and get a new one. */ /* Skip kernel's context and get a new one. */
ctx->handle = drm_ctxbitmap_next(dev); ctx->handle = drm_legacy_ctxbitmap_next(dev);
} }
DRM_DEBUG("%d\n", ctx->handle); DRM_DEBUG("%d\n", ctx->handle);
if (ctx->handle == -1) { if (ctx->handle == -1) {
...@@ -348,7 +373,8 @@ int drm_addctx(struct drm_device *dev, void *data, ...@@ -348,7 +373,8 @@ int drm_addctx(struct drm_device *dev, void *data,
* \param arg user argument pointing to a drm_ctx structure. * \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure. * \return zero on success or a negative number on failure.
*/ */
int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv) int drm_legacy_getctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{ {
struct drm_ctx *ctx = data; struct drm_ctx *ctx = data;
...@@ -369,8 +395,8 @@ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv) ...@@ -369,8 +395,8 @@ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
* *
* Calls context_switch(). * Calls context_switch().
*/ */
int drm_switchctx(struct drm_device *dev, void *data, int drm_legacy_switchctx(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_ctx *ctx = data; struct drm_ctx *ctx = data;
...@@ -389,8 +415,8 @@ int drm_switchctx(struct drm_device *dev, void *data, ...@@ -389,8 +415,8 @@ int drm_switchctx(struct drm_device *dev, void *data,
* *
* Calls context_switch_complete(). * Calls context_switch_complete().
*/ */
int drm_newctx(struct drm_device *dev, void *data, int drm_legacy_newctx(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_ctx *ctx = data; struct drm_ctx *ctx = data;
...@@ -411,8 +437,8 @@ int drm_newctx(struct drm_device *dev, void *data, ...@@ -411,8 +437,8 @@ int drm_newctx(struct drm_device *dev, void *data,
* *
* If not the special kernel context, calls ctxbitmap_free() to free the specified context. * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
*/ */
int drm_rmctx(struct drm_device *dev, void *data, int drm_legacy_rmctx(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_ctx *ctx = data; struct drm_ctx *ctx = data;
...@@ -420,7 +446,7 @@ int drm_rmctx(struct drm_device *dev, void *data, ...@@ -420,7 +446,7 @@ int drm_rmctx(struct drm_device *dev, void *data,
if (ctx->handle != DRM_KERNEL_CONTEXT) { if (ctx->handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_dtor) if (dev->driver->context_dtor)
dev->driver->context_dtor(dev, ctx->handle); dev->driver->context_dtor(dev, ctx->handle);
drm_ctxbitmap_free(dev, ctx->handle); drm_legacy_ctxbitmap_free(dev, ctx->handle);
} }
mutex_lock(&dev->ctxlist_mutex); mutex_lock(&dev->ctxlist_mutex);
......
此差异已折叠。
...@@ -818,6 +818,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, ...@@ -818,6 +818,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
&fb->bits_per_pixel); &fb->bits_per_pixel);
fb->pixel_format = mode_cmd->pixel_format; fb->pixel_format = mode_cmd->pixel_format;
fb->flags = mode_cmd->flags;
} }
EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/export.h> #include <linux/export.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_edid.h>
#if defined(CONFIG_DEBUG_FS) #if defined(CONFIG_DEBUG_FS)
...@@ -237,5 +238,186 @@ int drm_debugfs_cleanup(struct drm_minor *minor) ...@@ -237,5 +238,186 @@ int drm_debugfs_cleanup(struct drm_minor *minor)
return 0; return 0;
} }
static int connector_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
const char *status;
switch (connector->force) {
case DRM_FORCE_ON:
status = "on\n";
break;
case DRM_FORCE_ON_DIGITAL:
status = "digital\n";
break;
case DRM_FORCE_OFF:
status = "off\n";
break;
case DRM_FORCE_UNSPECIFIED:
status = "unspecified\n";
break;
default:
return 0;
}
seq_puts(m, status);
return 0;
}
static int connector_open(struct inode *inode, struct file *file)
{
struct drm_connector *dev = inode->i_private;
return single_open(file, connector_show, dev);
}
static ssize_t connector_write(struct file *file, const char __user *ubuf,
size_t len, loff_t *offp)
{
struct seq_file *m = file->private_data;
struct drm_connector *connector = m->private;
char buf[12];
if (len > sizeof(buf) - 1)
return -EINVAL;
if (copy_from_user(buf, ubuf, len))
return -EFAULT;
buf[len] = '\0';
if (!strcmp(buf, "on"))
connector->force = DRM_FORCE_ON;
else if (!strcmp(buf, "digital"))
connector->force = DRM_FORCE_ON_DIGITAL;
else if (!strcmp(buf, "off"))
connector->force = DRM_FORCE_OFF;
else if (!strcmp(buf, "unspecified"))
connector->force = DRM_FORCE_UNSPECIFIED;
else
return -EINVAL;
return len;
}
static int edid_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
struct drm_property_blob *edid = connector->edid_blob_ptr;
if (connector->override_edid && edid)
seq_write(m, edid->data, edid->length);
return 0;
}
static int edid_open(struct inode *inode, struct file *file)
{
struct drm_connector *dev = inode->i_private;
return single_open(file, edid_show, dev);
}
static ssize_t edid_write(struct file *file, const char __user *ubuf,
size_t len, loff_t *offp)
{
struct seq_file *m = file->private_data;
struct drm_connector *connector = m->private;
char *buf;
struct edid *edid;
int ret;
buf = memdup_user(ubuf, len);
if (IS_ERR(buf))
return PTR_ERR(buf);
edid = (struct edid *) buf;
if (len == 5 && !strncmp(buf, "reset", 5)) {
connector->override_edid = false;
ret = drm_mode_connector_update_edid_property(connector, NULL);
} else if (len < EDID_LENGTH ||
EDID_LENGTH * (1 + edid->extensions) > len)
ret = -EINVAL;
else {
connector->override_edid = false;
ret = drm_mode_connector_update_edid_property(connector, edid);
if (!ret)
connector->override_edid = true;
}
kfree(buf);
return (ret) ? ret : len;
}
static const struct file_operations drm_edid_fops = {
.owner = THIS_MODULE,
.open = edid_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = edid_write
};
static const struct file_operations drm_connector_fops = {
.owner = THIS_MODULE,
.open = connector_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = connector_write
};
int drm_debugfs_connector_add(struct drm_connector *connector)
{
struct drm_minor *minor = connector->dev->primary;
struct dentry *root, *ent;
if (!minor->debugfs_root)
return -1;
root = debugfs_create_dir(connector->name, minor->debugfs_root);
if (!root)
return -ENOMEM;
connector->debugfs_entry = root;
/* force */
ent = debugfs_create_file("force", S_IRUGO | S_IWUSR, root, connector,
&drm_connector_fops);
if (!ent)
goto error;
/* edid */
ent = debugfs_create_file("edid_override", S_IRUGO | S_IWUSR, root,
connector, &drm_edid_fops);
if (!ent)
goto error;
return 0;
error:
debugfs_remove_recursive(connector->debugfs_entry);
connector->debugfs_entry = NULL;
return -ENOMEM;
}
void drm_debugfs_connector_remove(struct drm_connector *connector)
{
if (!connector->debugfs_entry)
return;
debugfs_remove_recursive(connector->debugfs_entry);
connector->debugfs_entry = NULL;
}
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
此差异已折叠。
此差异已折叠。
...@@ -3305,6 +3305,7 @@ struct drm_connector *drm_select_eld(struct drm_encoder *encoder, ...@@ -3305,6 +3305,7 @@ struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
list_for_each_entry(connector, &dev->mode_config.connector_list, head) list_for_each_entry(connector, &dev->mode_config.connector_list, head)
if (connector->encoder == encoder && connector->eld[0]) if (connector->encoder == encoder && connector->eld[0])
...@@ -3775,8 +3776,14 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, ...@@ -3775,8 +3776,14 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE; frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
/* Populate picture aspect ratio from CEA mode list */ /*
if (frame->video_code > 0) * Populate picture aspect ratio from either
* user input (if specified) or from the CEA mode list.
*/
if (mode->picture_aspect_ratio == HDMI_PICTURE_ASPECT_4_3 ||
mode->picture_aspect_ratio == HDMI_PICTURE_ASPECT_16_9)
frame->picture_aspect = mode->picture_aspect_ratio;
else if (frame->video_code > 0)
frame->picture_aspect = drm_get_cea_aspect_ratio( frame->picture_aspect = drm_get_cea_aspect_ratio(
frame->video_code); frame->video_code);
......
...@@ -327,7 +327,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, ...@@ -327,7 +327,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
return ret; return ret;
} }
static struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = { static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
.fb_probe = drm_fbdev_cma_create, .fb_probe = drm_fbdev_cma_create,
}; };
...@@ -354,9 +354,10 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev, ...@@ -354,9 +354,10 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
fbdev_cma->fb_helper.funcs = &drm_fb_cma_helper_funcs;
helper = &fbdev_cma->fb_helper; helper = &fbdev_cma->fb_helper;
drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count); ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count);
if (ret < 0) { if (ret < 0) {
dev_err(dev->dev, "Failed to initialize drm fb helper.\n"); dev_err(dev->dev, "Failed to initialize drm fb helper.\n");
......
...@@ -49,10 +49,11 @@ static LIST_HEAD(kernel_fb_helper_list); ...@@ -49,10 +49,11 @@ static LIST_HEAD(kernel_fb_helper_list);
* helper functions used by many drivers to implement the kernel mode setting * helper functions used by many drivers to implement the kernel mode setting
* interfaces. * interfaces.
* *
* Initialization is done as a three-step process with drm_fb_helper_init(), * Initialization is done as a four-step process with drm_fb_helper_prepare(),
* drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config(). * drm_fb_helper_init(), drm_fb_helper_single_add_all_connectors() and
* Drivers with fancier requirements than the default behaviour can override the * drm_fb_helper_initial_config(). Drivers with fancier requirements than the
* second step with their own code. Teardown is done with drm_fb_helper_fini(). * default behaviour can override the third step with their own code.
* Teardown is done with drm_fb_helper_fini().
* *
* At runtime drivers should restore the fbdev console by calling * At runtime drivers should restore the fbdev console by calling
* drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They
...@@ -63,6 +64,19 @@ static LIST_HEAD(kernel_fb_helper_list); ...@@ -63,6 +64,19 @@ static LIST_HEAD(kernel_fb_helper_list);
* *
* All other functions exported by the fb helper library can be used to * All other functions exported by the fb helper library can be used to
* implement the fbdev driver interface by the driver. * implement the fbdev driver interface by the driver.
*
* It is possible, though perhaps somewhat tricky, to implement race-free
* hotplug detection using the fbdev helpers. The drm_fb_helper_prepare()
* helper must be called first to initialize the minimum required to make
* hotplug detection work. Drivers also need to make sure to properly set up
* the dev->mode_config.funcs member. After calling drm_kms_helper_poll_init()
* it is safe to enable interrupts and start processing hotplug events. At the
* same time, drivers should initialize all modeset objects such as CRTCs,
* encoders and connectors. To finish up the fbdev helper initialization, the
* drm_fb_helper_init() function is called. To probe for all attached displays
* and set up an initial configuration using the detected hardware, drivers
* should call drm_fb_helper_single_add_all_connectors() followed by
* drm_fb_helper_initial_config().
*/ */
/** /**
...@@ -105,6 +119,58 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) ...@@ -105,6 +119,58 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
} }
EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector)
{
struct drm_fb_helper_connector **temp;
struct drm_fb_helper_connector *fb_helper_connector;
WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) {
temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector) * (fb_helper->connector_count + 1), GFP_KERNEL);
if (!temp)
return -ENOMEM;
fb_helper->connector_info_alloc_count = fb_helper->connector_count + 1;
fb_helper->connector_info = temp;
}
fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
if (!fb_helper_connector)
return -ENOMEM;
fb_helper_connector->connector = connector;
fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
return 0;
}
EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector)
{
struct drm_fb_helper_connector *fb_helper_connector;
int i, j;
WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
for (i = 0; i < fb_helper->connector_count; i++) {
if (fb_helper->connector_info[i]->connector == connector)
break;
}
if (i == fb_helper->connector_count)
return -EINVAL;
fb_helper_connector = fb_helper->connector_info[i];
for (j = i + 1; j < fb_helper->connector_count; j++) {
fb_helper->connector_info[j - 1] = fb_helper->connector_info[j];
}
fb_helper->connector_count--;
kfree(fb_helper_connector);
return 0;
}
EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper) static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
{ {
struct drm_fb_helper_connector *fb_helper_conn; struct drm_fb_helper_connector *fb_helper_conn;
...@@ -199,9 +265,6 @@ int drm_fb_helper_debug_enter(struct fb_info *info) ...@@ -199,9 +265,6 @@ int drm_fb_helper_debug_enter(struct fb_info *info)
struct drm_crtc_helper_funcs *funcs; struct drm_crtc_helper_funcs *funcs;
int i; int i;
if (list_empty(&kernel_fb_helper_list))
return false;
list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
for (i = 0; i < helper->crtc_count; i++) { for (i = 0; i < helper->crtc_count; i++) {
struct drm_mode_set *mode_set = struct drm_mode_set *mode_set =
...@@ -530,6 +593,24 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) ...@@ -530,6 +593,24 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
kfree(helper->crtc_info); kfree(helper->crtc_info);
} }
/**
* drm_fb_helper_prepare - setup a drm_fb_helper structure
* @dev: DRM device
* @helper: driver-allocated fbdev helper structure to set up
* @funcs: pointer to structure of functions associate with this helper
*
* Sets up the bare minimum to make the framebuffer helper usable. This is
* useful to implement race-free initialization of the polling helpers.
*/
void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
const struct drm_fb_helper_funcs *funcs)
{
INIT_LIST_HEAD(&helper->kernel_fb_list);
helper->funcs = funcs;
helper->dev = dev;
}
EXPORT_SYMBOL(drm_fb_helper_prepare);
/** /**
* drm_fb_helper_init - initialize a drm_fb_helper structure * drm_fb_helper_init - initialize a drm_fb_helper structure
* @dev: drm device * @dev: drm device
...@@ -542,8 +623,7 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) ...@@ -542,8 +623,7 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
* nor register the fbdev. This is only done in drm_fb_helper_initial_config() * nor register the fbdev. This is only done in drm_fb_helper_initial_config()
* to allow driver writes more control over the exact init sequence. * to allow driver writes more control over the exact init sequence.
* *
* Drivers must set fb_helper->funcs before calling * Drivers must call drm_fb_helper_prepare() before calling this function.
* drm_fb_helper_initial_config().
* *
* RETURNS: * RETURNS:
* Zero if everything went ok, nonzero otherwise. * Zero if everything went ok, nonzero otherwise.
...@@ -558,10 +638,6 @@ int drm_fb_helper_init(struct drm_device *dev, ...@@ -558,10 +638,6 @@ int drm_fb_helper_init(struct drm_device *dev,
if (!max_conn_count) if (!max_conn_count)
return -EINVAL; return -EINVAL;
fb_helper->dev = dev;
INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL); fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
if (!fb_helper->crtc_info) if (!fb_helper->crtc_info)
return -ENOMEM; return -ENOMEM;
...@@ -572,6 +648,7 @@ int drm_fb_helper_init(struct drm_device *dev, ...@@ -572,6 +648,7 @@ int drm_fb_helper_init(struct drm_device *dev,
kfree(fb_helper->crtc_info); kfree(fb_helper->crtc_info);
return -ENOMEM; return -ENOMEM;
} }
fb_helper->connector_info_alloc_count = dev->mode_config.num_connector;
fb_helper->connector_count = 0; fb_helper->connector_count = 0;
for (i = 0; i < crtc_count; i++) { for (i = 0; i < crtc_count; i++) {
...@@ -1056,7 +1133,6 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, ...@@ -1056,7 +1133,6 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
info->fix.ypanstep = 1; /* doing it in hw */ info->fix.ypanstep = 1; /* doing it in hw */
info->fix.ywrapstep = 0; info->fix.ywrapstep = 0;
info->fix.accel = FB_ACCEL_NONE; info->fix.accel = FB_ACCEL_NONE;
info->fix.type_aux = 0;
info->fix.line_length = pitch; info->fix.line_length = pitch;
return; return;
...@@ -1613,8 +1689,10 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config); ...@@ -1613,8 +1689,10 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
* either the output polling work or a work item launched from the driver's * either the output polling work or a work item launched from the driver's
* hotplug interrupt). * hotplug interrupt).
* *
* Note that the driver must ensure that this is only called _after_ the fb has * Note that drivers may call this even before calling
* been fully set up, i.e. after the call to drm_fb_helper_initial_config. * drm_fb_helper_initial_config but only aftert drm_fb_helper_init. This allows
* for a race-free fbcon setup and will make sure that the fbdev emulation will
* not miss any hotplug events.
* *
* RETURNS: * RETURNS:
* 0 on success and a non-zero error code otherwise. * 0 on success and a non-zero error code otherwise.
...@@ -1624,11 +1702,8 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) ...@@ -1624,11 +1702,8 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
struct drm_device *dev = fb_helper->dev; struct drm_device *dev = fb_helper->dev;
u32 max_width, max_height; u32 max_width, max_height;
if (!fb_helper->fb)
return 0;
mutex_lock(&fb_helper->dev->mode_config.mutex); mutex_lock(&fb_helper->dev->mode_config.mutex);
if (!drm_fb_helper_is_bound(fb_helper)) { if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
fb_helper->delayed_hotplug = true; fb_helper->delayed_hotplug = true;
mutex_unlock(&fb_helper->dev->mode_config.mutex); mutex_unlock(&fb_helper->dev->mode_config.mutex);
return 0; return 0;
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include "drm_legacy.h"
/* from BKL pushdown */ /* from BKL pushdown */
DEFINE_MUTEX(drm_global_mutex); DEFINE_MUTEX(drm_global_mutex);
...@@ -111,45 +112,6 @@ int drm_open(struct inode *inode, struct file *filp) ...@@ -111,45 +112,6 @@ int drm_open(struct inode *inode, struct file *filp)
} }
EXPORT_SYMBOL(drm_open); EXPORT_SYMBOL(drm_open);
/**
* File \c open operation.
*
* \param inode device inode.
* \param filp file pointer.
*
* Puts the dev->fops corresponding to the device minor number into
* \p filp, call the \c open method, and restore the file operations.
*/
int drm_stub_open(struct inode *inode, struct file *filp)
{
struct drm_device *dev;
struct drm_minor *minor;
int err = -ENODEV;
const struct file_operations *new_fops;
DRM_DEBUG("\n");
mutex_lock(&drm_global_mutex);
minor = drm_minor_acquire(iminor(inode));
if (IS_ERR(minor))
goto out_unlock;
dev = minor->dev;
new_fops = fops_get(dev->driver->fops);
if (!new_fops)
goto out_release;
replace_fops(filp, new_fops);
if (filp->f_op->open)
err = filp->f_op->open(inode, filp);
out_release:
drm_minor_release(minor);
out_unlock:
mutex_unlock(&drm_global_mutex);
return err;
}
/** /**
* Check whether DRI will run on this CPU. * Check whether DRI will run on this CPU.
* *
...@@ -157,10 +119,6 @@ int drm_stub_open(struct inode *inode, struct file *filp) ...@@ -157,10 +119,6 @@ int drm_stub_open(struct inode *inode, struct file *filp)
*/ */
static int drm_cpu_valid(void) static int drm_cpu_valid(void)
{ {
#if defined(__i386__)
if (boot_cpu_data.x86 == 3)
return 0; /* No cmpxchg on a 386 */
#endif
#if defined(__sparc__) && !defined(__sparc_v9__) #if defined(__sparc__) && !defined(__sparc_v9__)
return 0; /* No cmpxchg before v9 sparc. */ return 0; /* No cmpxchg before v9 sparc. */
#endif #endif
...@@ -203,8 +161,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) ...@@ -203,8 +161,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
priv->minor = minor; priv->minor = minor;
/* for compatibility root is always authenticated */ /* for compatibility root is always authenticated */
priv->always_authenticated = capable(CAP_SYS_ADMIN); priv->authenticated = capable(CAP_SYS_ADMIN);
priv->authenticated = priv->always_authenticated;
priv->lock_count = 0; priv->lock_count = 0;
INIT_LIST_HEAD(&priv->lhead); INIT_LIST_HEAD(&priv->lhead);
...@@ -429,6 +386,10 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -429,6 +386,10 @@ int drm_release(struct inode *inode, struct file *filp)
DRM_DEBUG("open_count = %d\n", dev->open_count); DRM_DEBUG("open_count = %d\n", dev->open_count);
mutex_lock(&dev->struct_mutex);
list_del(&file_priv->lhead);
mutex_unlock(&dev->struct_mutex);
if (dev->driver->preclose) if (dev->driver->preclose)
dev->driver->preclose(dev, file_priv); dev->driver->preclose(dev, file_priv);
...@@ -461,44 +422,18 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -461,44 +422,18 @@ int drm_release(struct inode *inode, struct file *filp)
if (dev->driver->driver_features & DRIVER_GEM) if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_release(dev, file_priv); drm_gem_release(dev, file_priv);
mutex_lock(&dev->ctxlist_mutex); drm_legacy_ctxbitmap_flush(dev, file_priv);
if (!list_empty(&dev->ctxlist)) {
struct drm_ctx_list *pos, *n;
list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
if (pos->tag == file_priv &&
pos->handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_dtor)
dev->driver->context_dtor(dev,
pos->handle);
drm_ctxbitmap_free(dev, pos->handle);
list_del(&pos->head);
kfree(pos);
}
}
}
mutex_unlock(&dev->ctxlist_mutex);
mutex_lock(&dev->master_mutex); mutex_lock(&dev->master_mutex);
if (file_priv->is_master) { if (file_priv->is_master) {
struct drm_master *master = file_priv->master; struct drm_master *master = file_priv->master;
struct drm_file *temp;
mutex_lock(&dev->struct_mutex);
list_for_each_entry(temp, &dev->filelist, lhead) {
if ((temp->master == file_priv->master) &&
(temp != file_priv))
temp->authenticated = temp->always_authenticated;
}
/** /**
* Since the master is disappearing, so is the * Since the master is disappearing, so is the
* possibility to lock. * possibility to lock.
*/ */
mutex_lock(&dev->struct_mutex);
if (master->lock.hw_lock) { if (master->lock.hw_lock) {
if (dev->sigdata.lock == master->lock.hw_lock) if (dev->sigdata.lock == master->lock.hw_lock)
dev->sigdata.lock = NULL; dev->sigdata.lock = NULL;
...@@ -522,10 +457,6 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -522,10 +457,6 @@ int drm_release(struct inode *inode, struct file *filp)
file_priv->is_master = 0; file_priv->is_master = 0;
mutex_unlock(&dev->master_mutex); mutex_unlock(&dev->master_mutex);
mutex_lock(&dev->struct_mutex);
list_del(&file_priv->lhead);
mutex_unlock(&dev->struct_mutex);
if (dev->driver->postclose) if (dev->driver->postclose)
dev->driver->postclose(dev, file_priv); dev->driver->postclose(dev, file_priv);
......
...@@ -441,18 +441,31 @@ EXPORT_SYMBOL(drm_gem_create_mmap_offset); ...@@ -441,18 +441,31 @@ EXPORT_SYMBOL(drm_gem_create_mmap_offset);
* drm_gem_get_pages - helper to allocate backing pages for a GEM object * drm_gem_get_pages - helper to allocate backing pages for a GEM object
* from shmem * from shmem
* @obj: obj in question * @obj: obj in question
* @gfpmask: gfp mask of requested pages *
* This reads the page-array of the shmem-backing storage of the given gem
* object. An array of pages is returned. If a page is not allocated or
* swapped-out, this will allocate/swap-in the required pages. Note that the
* whole object is covered by the page-array and pinned in memory.
*
* Use drm_gem_put_pages() to release the array and unpin all pages.
*
* This uses the GFP-mask set on the shmem-mapping (see mapping_set_gfp_mask()).
* If you require other GFP-masks, you have to do those allocations yourself.
*
* Note that you are not allowed to change gfp-zones during runtime. That is,
* shmem_read_mapping_page_gfp() must be called with the same gfp_zone(gfp) as
* set during initialization. If you have special zone constraints, set them
* after drm_gem_init_object() via mapping_set_gfp_mask(). shmem-core takes care
* to keep pages in the required zone during swap-in.
*/ */
struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask) struct page **drm_gem_get_pages(struct drm_gem_object *obj)
{ {
struct inode *inode;
struct address_space *mapping; struct address_space *mapping;
struct page *p, **pages; struct page *p, **pages;
int i, npages; int i, npages;
/* This is the shared memory object that backs the GEM resource */ /* This is the shared memory object that backs the GEM resource */
inode = file_inode(obj->filp); mapping = file_inode(obj->filp)->i_mapping;
mapping = inode->i_mapping;
/* We already BUG_ON() for non-page-aligned sizes in /* We already BUG_ON() for non-page-aligned sizes in
* drm_gem_object_init(), so we should never hit this unless * drm_gem_object_init(), so we should never hit this unless
...@@ -466,10 +479,8 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask) ...@@ -466,10 +479,8 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
if (pages == NULL) if (pages == NULL)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
gfpmask |= mapping_gfp_mask(mapping);
for (i = 0; i < npages; i++) { for (i = 0; i < npages; i++) {
p = shmem_read_mapping_page_gfp(mapping, i, gfpmask); p = shmem_read_mapping_page(mapping, i);
if (IS_ERR(p)) if (IS_ERR(p))
goto fail; goto fail;
pages[i] = p; pages[i] = p;
...@@ -479,7 +490,7 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask) ...@@ -479,7 +490,7 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
* __GFP_DMA32 to be set in mapping_gfp_mask(inode->i_mapping) * __GFP_DMA32 to be set in mapping_gfp_mask(inode->i_mapping)
* so shmem can relocate pages during swapin if required. * so shmem can relocate pages during swapin if required.
*/ */
BUG_ON((gfpmask & __GFP_DMA32) && BUG_ON((mapping_gfp_mask(mapping) & __GFP_DMA32) &&
(page_to_pfn(p) >= 0x00100000UL)); (page_to_pfn(p) >= 0x00100000UL));
} }
......
...@@ -327,7 +327,7 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev, size_t size, ...@@ -327,7 +327,7 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev, size_t size,
/* Create a CMA GEM buffer. */ /* Create a CMA GEM buffer. */
cma_obj = __drm_gem_cma_create(dev, size); cma_obj = __drm_gem_cma_create(dev, size);
if (IS_ERR(cma_obj)) if (IS_ERR(cma_obj))
return ERR_PTR(PTR_ERR(cma_obj)); return ERR_CAST(cma_obj);
cma_obj->paddr = sg_dma_address(sgt->sgl); cma_obj->paddr = sg_dma_address(sgt->sgl);
cma_obj->sgt = sgt; cma_obj->sgt = sgt;
......
...@@ -132,7 +132,7 @@ int drm_bufs_info(struct seq_file *m, void *data) ...@@ -132,7 +132,7 @@ int drm_bufs_info(struct seq_file *m, void *data)
i, i,
dma->bufs[i].buf_size, dma->bufs[i].buf_size,
dma->bufs[i].buf_count, dma->bufs[i].buf_count,
atomic_read(&dma->bufs[i].freelist.count), 0,
dma->bufs[i].seg_count, dma->bufs[i].seg_count,
seg_pages, seg_pages,
seg_pages * PAGE_SIZE / 1024); seg_pages * PAGE_SIZE / 1024);
......
此差异已折叠。
#ifndef __DRM_LEGACY_H__
#define __DRM_LEGACY_H__
/*
* Copyright (c) 2014 David Herrmann <dh.herrmann@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
struct drm_device;
struct drm_file;
/*
* Generic DRM Contexts
*/
#define DRM_KERNEL_CONTEXT 0
#define DRM_RESERVED_CONTEXTS 1
int drm_legacy_ctxbitmap_init(struct drm_device *dev);
void drm_legacy_ctxbitmap_cleanup(struct drm_device *dev);
void drm_legacy_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file);
int drm_legacy_resctx(struct drm_device *d, void *v, struct drm_file *f);
int drm_legacy_addctx(struct drm_device *d, void *v, struct drm_file *f);
int drm_legacy_getctx(struct drm_device *d, void *v, struct drm_file *f);
int drm_legacy_switchctx(struct drm_device *d, void *v, struct drm_file *f);
int drm_legacy_newctx(struct drm_device *d, void *v, struct drm_file *f);
int drm_legacy_rmctx(struct drm_device *d, void *v, struct drm_file *f);
int drm_legacy_setsareactx(struct drm_device *d, void *v, struct drm_file *f);
int drm_legacy_getsareactx(struct drm_device *d, void *v, struct drm_file *f);
#endif /* __DRM_LEGACY_H__ */
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/export.h> #include <linux/export.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include "drm_legacy.h"
static int drm_notifier(void *priv); static int drm_notifier(void *priv);
......
...@@ -201,16 +201,15 @@ EXPORT_SYMBOL(mipi_dsi_detach); ...@@ -201,16 +201,15 @@ EXPORT_SYMBOL(mipi_dsi_detach);
/** /**
* mipi_dsi_dcs_write - send DCS write command * mipi_dsi_dcs_write - send DCS write command
* @dsi: DSI device * @dsi: DSI device
* @channel: virtual channel
* @data: pointer to the command followed by parameters * @data: pointer to the command followed by parameters
* @len: length of @data * @len: length of @data
*/ */
int mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, unsigned int channel, ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, const void *data,
const void *data, size_t len) size_t len)
{ {
const struct mipi_dsi_host_ops *ops = dsi->host->ops; const struct mipi_dsi_host_ops *ops = dsi->host->ops;
struct mipi_dsi_msg msg = { struct mipi_dsi_msg msg = {
.channel = channel, .channel = dsi->channel,
.tx_buf = data, .tx_buf = data,
.tx_len = len .tx_len = len
}; };
...@@ -239,19 +238,18 @@ EXPORT_SYMBOL(mipi_dsi_dcs_write); ...@@ -239,19 +238,18 @@ EXPORT_SYMBOL(mipi_dsi_dcs_write);
/** /**
* mipi_dsi_dcs_read - send DCS read request command * mipi_dsi_dcs_read - send DCS read request command
* @dsi: DSI device * @dsi: DSI device
* @channel: virtual channel
* @cmd: DCS read command * @cmd: DCS read command
* @data: pointer to read buffer * @data: pointer to read buffer
* @len: length of @data * @len: length of @data
* *
* Function returns number of read bytes or error code. * Function returns number of read bytes or error code.
*/ */
ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, unsigned int channel, ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
u8 cmd, void *data, size_t len) size_t len)
{ {
const struct mipi_dsi_host_ops *ops = dsi->host->ops; const struct mipi_dsi_host_ops *ops = dsi->host->ops;
struct mipi_dsi_msg msg = { struct mipi_dsi_msg msg = {
.channel = channel, .channel = dsi->channel,
.type = MIPI_DSI_DCS_READ, .type = MIPI_DSI_DCS_READ,
.tx_buf = &cmd, .tx_buf = &cmd,
.tx_len = 1, .tx_len = 1,
......
#include <linux/export.h>
#include <linux/list.h>
#include <linux/of_graph.h>
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_of.h>
/**
* drm_crtc_port_mask - find the mask of a registered CRTC by port OF node
* @dev: DRM device
* @port: port OF node
*
* Given a port OF node, return the possible mask of the corresponding
* CRTC within a device's list of CRTCs. Returns zero if not found.
*/
static uint32_t drm_crtc_port_mask(struct drm_device *dev,
struct device_node *port)
{
unsigned int index = 0;
struct drm_crtc *tmp;
list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
if (tmp->port == port)
return 1 << index;
index++;
}
return 0;
}
/**
* drm_of_find_possible_crtcs - find the possible CRTCs for an encoder port
* @dev: DRM device
* @port: encoder port to scan for endpoints
*
* Scan all endpoints attached to a port, locate their attached CRTCs,
* and generate the DRM mask of CRTCs which may be attached to this
* encoder.
*
* See Documentation/devicetree/bindings/graph.txt for the bindings.
*/
uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
struct device_node *port)
{
struct device_node *remote_port, *ep = NULL;
uint32_t possible_crtcs = 0;
do {
ep = of_graph_get_next_endpoint(port, ep);
if (!ep)
break;
remote_port = of_graph_get_remote_port(ep);
if (!remote_port) {
of_node_put(ep);
return 0;
}
possible_crtcs |= drm_crtc_port_mask(dev, remote_port);
of_node_put(remote_port);
} while (1);
return possible_crtcs;
}
EXPORT_SYMBOL(drm_of_find_possible_crtcs);
...@@ -335,9 +335,10 @@ struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev, ...@@ -335,9 +335,10 @@ struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev,
} }
/* possible_crtc's will be filled in later by crtc_init */ /* possible_crtc's will be filled in later by crtc_init */
ret = drm_plane_init(dev, primary, 0, &drm_primary_helper_funcs, ret = drm_universal_plane_init(dev, primary, 0,
formats, num_formats, &drm_primary_helper_funcs,
DRM_PLANE_TYPE_PRIMARY); formats, num_formats,
DRM_PLANE_TYPE_PRIMARY);
if (ret) { if (ret) {
kfree(primary); kfree(primary);
primary = NULL; primary = NULL;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册