diff options
156 files changed, 5658 insertions, 2657 deletions
diff --git a/Documentation/DocBook/media/v4l/subdev-formats.xml b/Documentation/DocBook/media/v4l/subdev-formats.xml index c5ea868e3909..18b71aff48c9 100644 --- a/Documentation/DocBook/media/v4l/subdev-formats.xml +++ b/Documentation/DocBook/media/v4l/subdev-formats.xml @@ -91,7 +91,9 @@ see <xref linkend="colorspaces" />.</entry> <listitem><para>For formats where the total number of bits per pixel is smaller than the number of bus samples per pixel times the bus width, a padding value stating if the bytes are padded in their most high order bits - (PADHI) or low order bits (PADLO).</para></listitem> + (PADHI) or low order bits (PADLO). A "C" prefix is used for component-wise + padding in the most high order bits (CPADHI) or low order bits (CPADLO) + of each separate component.</para></listitem> <listitem><para>For formats where the number of bus samples per pixel is larger than 1, an endianness value stating if the pixel is transferred MSB first (BE) or LSB first (LE).</para></listitem> @@ -192,6 +194,24 @@ see <xref linkend="colorspaces" />.</entry> </row> </thead> <tbody valign="top"> + <row id="MEDIA-BUS-FMT-RGB444-1X12"> + <entry>MEDIA_BUS_FMT_RGB444_1X12</entry> + <entry>0x100e</entry> + <entry></entry> + &dash-ent-20; + <entry>r<subscript>3</subscript></entry> + <entry>r<subscript>2</subscript></entry> + <entry>r<subscript>1</subscript></entry> + <entry>r<subscript>0</subscript></entry> + <entry>g<subscript>3</subscript></entry> + <entry>g<subscript>2</subscript></entry> + <entry>g<subscript>1</subscript></entry> + <entry>g<subscript>0</subscript></entry> + <entry>b<subscript>3</subscript></entry> + <entry>b<subscript>2</subscript></entry> + <entry>b<subscript>1</subscript></entry> + <entry>b<subscript>0</subscript></entry> + </row> <row id="MEDIA-BUS-FMT-RGB444-2X8-PADHI-BE"> <entry>MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE</entry> <entry>0x1001</entry> @@ -304,6 +324,28 @@ see <xref linkend="colorspaces" />.</entry> <entry>g<subscript>4</subscript></entry> <entry>g<subscript>3</subscript></entry> </row> + <row id="MEDIA-BUS-FMT-RGB565-1X16"> + <entry>MEDIA_BUS_FMT_RGB565_1X16</entry> + <entry>0x100f</entry> + <entry></entry> + &dash-ent-16; + <entry>r<subscript>4</subscript></entry> + <entry>r<subscript>3</subscript></entry> + <entry>r<subscript>2</subscript></entry> + <entry>r<subscript>1</subscript></entry> + <entry>r<subscript>0</subscript></entry> + <entry>g<subscript>5</subscript></entry> + <entry>g<subscript>4</subscript></entry> + <entry>g<subscript>3</subscript></entry> + <entry>g<subscript>2</subscript></entry> + <entry>g<subscript>1</subscript></entry> + <entry>g<subscript>0</subscript></entry> + <entry>b<subscript>4</subscript></entry> + <entry>b<subscript>3</subscript></entry> + <entry>b<subscript>2</subscript></entry> + <entry>b<subscript>1</subscript></entry> + <entry>b<subscript>0</subscript></entry> + </row> <row id="MEDIA-BUS-FMT-BGR565-2X8-BE"> <entry>MEDIA_BUS_FMT_BGR565_2X8_BE</entry> <entry>0x1005</entry> @@ -440,6 +482,96 @@ see <xref linkend="colorspaces" />.</entry> <entry>b<subscript>1</subscript></entry> <entry>b<subscript>0</subscript></entry> </row> + <row id="MEDIA-BUS-FMT-RGB666-1X24_CPADHI"> + <entry>MEDIA_BUS_FMT_RGB666_1X24_CPADHI</entry> + <entry>0x1015</entry> + <entry></entry> + &dash-ent-8; + <entry>0</entry> + <entry>0</entry> + <entry>r<subscript>5</subscript></entry> + <entry>r<subscript>4</subscript></entry> + <entry>r<subscript>3</subscript></entry> + <entry>r<subscript>2</subscript></entry> + <entry>r<subscript>1</subscript></entry> + <entry>r<subscript>0</subscript></entry> + <entry>0</entry> + <entry>0</entry> + <entry>g<subscript>5</subscript></entry> + <entry>g<subscript>4</subscript></entry> + <entry>g<subscript>3</subscript></entry> + <entry>g<subscript>2</subscript></entry> + <entry>g<subscript>1</subscript></entry> + <entry>g<subscript>0</subscript></entry> + <entry>0</entry> + <entry>0</entry> + <entry>b<subscript>5</subscript></entry> + <entry>b<subscript>4</subscript></entry> + <entry>b<subscript>3</subscript></entry> + <entry>b<subscript>2</subscript></entry> + <entry>b<subscript>1</subscript></entry> + <entry>b<subscript>0</subscript></entry> + </row> + <row id="MEDIA-BUS-FMT-BGR888-1X24"> + <entry>MEDIA_BUS_FMT_BGR888_1X24</entry> + <entry>0x1013</entry> + <entry></entry> + &dash-ent-8; + <entry>b<subscript>7</subscript></entry> + <entry>b<subscript>6</subscript></entry> + <entry>b<subscript>5</subscript></entry> + <entry>b<subscript>4</subscript></entry> + <entry>b<subscript>3</subscript></entry> + <entry>b<subscript>2</subscript></entry> + <entry>b<subscript>1</subscript></entry> + <entry>b<subscript>0</subscript></entry> + <entry>g<subscript>7</subscript></entry> + <entry>g<subscript>6</subscript></entry> + <entry>g<subscript>5</subscript></entry> + <entry>g<subscript>4</subscript></entry> + <entry>g<subscript>3</subscript></entry> + <entry>g<subscript>2</subscript></entry> + <entry>g<subscript>1</subscript></entry> + <entry>g<subscript>0</subscript></entry> + <entry>r<subscript>7</subscript></entry> + <entry>r<subscript>6</subscript></entry> + <entry>r<subscript>5</subscript></entry> + <entry>r<subscript>4</subscript></entry> + <entry>r<subscript>3</subscript></entry> + <entry>r<subscript>2</subscript></entry> + <entry>r<subscript>1</subscript></entry> + <entry>r<subscript>0</subscript></entry> + </row> + <row id="MEDIA-BUS-FMT-GBR888-1X24"> + <entry>MEDIA_BUS_FMT_GBR888_1X24</entry> + <entry>0x1014</entry> + <entry></entry> + &dash-ent-8; + <entry>g<subscript>7</subscript></entry> + <entry>g<subscript>6</subscript></entry> + <entry>g<subscript>5</subscript></entry> + <entry>g<subscript>4</subscript></entry> + <entry>g<subscript>3</subscript></entry> + <entry>g<subscript>2</subscript></entry> + <entry>g<subscript>1</subscript></entry> + <entry>g<subscript>0</subscript></entry> + <entry>b<subscript>7</subscript></entry> + <entry>b<subscript>6</subscript></entry> + <entry>b<subscript>5</subscript></entry> + <entry>b<subscript>4</subscript></entry> + <entry>b<subscript>3</subscript></entry> + <entry>b<subscript>2</subscript></entry> + <entry>b<subscript>1</subscript></entry> + <entry>b<subscript>0</subscript></entry> + <entry>r<subscript>7</subscript></entry> + <entry>r<subscript>6</subscript></entry> + <entry>r<subscript>5</subscript></entry> + <entry>r<subscript>4</subscript></entry> + <entry>r<subscript>3</subscript></entry> + <entry>r<subscript>2</subscript></entry> + <entry>r<subscript>1</subscript></entry> + <entry>r<subscript>0</subscript></entry> + </row> <row id="MEDIA-BUS-FMT-RGB888-1X24"> <entry>MEDIA_BUS_FMT_RGB888_1X24</entry> <entry>0x100a</entry> @@ -582,6 +714,261 @@ see <xref linkend="colorspaces" />.</entry> </tbody> </tgroup> </table> + + <para>On LVDS buses, usually each sample is transferred serialized in + seven time slots per pixel clock, on three (18-bit) or four (24-bit) + differential data pairs at the same time. The remaining bits are used for + control signals as defined by SPWG/PSWG/VESA or JEIDA standards. + The 24-bit RGB format serialized in seven time slots on four lanes using + JEIDA defined bit mapping will be named + <constant>MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA</constant>, for example. + </para> + + <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-rgb-lvds"> + <title>LVDS RGB formats</title> + <tgroup cols="8"> + <colspec colname="id" align="left" /> + <colspec colname="code" align="center" /> + <colspec colname="slot" align="center" /> + <colspec colname="lane" /> + <colspec colnum="5" colname="l03" align="center" /> + <colspec colnum="6" colname="l02" align="center" /> + <colspec colnum="7" colname="l01" align="center" /> + <colspec colnum="8" colname="l00" align="center" /> + <spanspec namest="l03" nameend="l00" spanname="l0" /> + <thead> + <row> + <entry>Identifier</entry> + <entry>Code</entry> + <entry></entry> + <entry></entry> + <entry spanname="l0">Data organization</entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>Timeslot</entry> + <entry>Lane</entry> + <entry>3</entry> + <entry>2</entry> + <entry>1</entry> + <entry>0</entry> + </row> + </thead> + <tbody valign="top"> + <row id="MEDIA-BUS-FMT-RGB666-1X7X3-SPWG"> + <entry>MEDIA_BUS_FMT_RGB666_1X7X3_SPWG</entry> + <entry>0x1010</entry> + <entry>0</entry> + <entry></entry> + <entry>-</entry> + <entry>d</entry> + <entry>b<subscript>1</subscript></entry> + <entry>g<subscript>0</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>1</entry> + <entry></entry> + <entry>-</entry> + <entry>d</entry> + <entry>b<subscript>0</subscript></entry> + <entry>r<subscript>5</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>2</entry> + <entry></entry> + <entry>-</entry> + <entry>d</entry> + <entry>g<subscript>5</subscript></entry> + <entry>r<subscript>4</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>3</entry> + <entry></entry> + <entry>-</entry> + <entry>b<subscript>5</subscript></entry> + <entry>g<subscript>4</subscript></entry> + <entry>r<subscript>3</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>4</entry> + <entry></entry> + <entry>-</entry> + <entry>b<subscript>4</subscript></entry> + <entry>g<subscript>3</subscript></entry> + <entry>r<subscript>2</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>5</entry> + <entry></entry> + <entry>-</entry> + <entry>b<subscript>3</subscript></entry> + <entry>g<subscript>2</subscript></entry> + <entry>r<subscript>1</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>6</entry> + <entry></entry> + <entry>-</entry> + <entry>b<subscript>2</subscript></entry> + <entry>g<subscript>1</subscript></entry> + <entry>r<subscript>0</subscript></entry> + </row> + <row id="MEDIA-BUS-FMT-RGB888-1X7X4-SPWG"> + <entry>MEDIA_BUS_FMT_RGB888_1X7X4_SPWG</entry> + <entry>0x1011</entry> + <entry>0</entry> + <entry></entry> + <entry>d</entry> + <entry>d</entry> + <entry>b<subscript>1</subscript></entry> + <entry>g<subscript>0</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>1</entry> + <entry></entry> + <entry>b<subscript>7</subscript></entry> + <entry>d</entry> + <entry>b<subscript>0</subscript></entry> + <entry>r<subscript>5</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>2</entry> + <entry></entry> + <entry>b<subscript>6</subscript></entry> + <entry>d</entry> + <entry>g<subscript>5</subscript></entry> + <entry>r<subscript>4</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>3</entry> + <entry></entry> + <entry>g<subscript>7</subscript></entry> + <entry>b<subscript>5</subscript></entry> + <entry>g<subscript>4</subscript></entry> + <entry>r<subscript>3</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>4</entry> + <entry></entry> + <entry>g<subscript>6</subscript></entry> + <entry>b<subscript>4</subscript></entry> + <entry>g<subscript>3</subscript></entry> + <entry>r<subscript>2</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>5</entry> + <entry></entry> + <entry>r<subscript>7</subscript></entry> + <entry>b<subscript>3</subscript></entry> + <entry>g<subscript>2</subscript></entry> + <entry>r<subscript>1</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>6</entry> + <entry></entry> + <entry>r<subscript>6</subscript></entry> + <entry>b<subscript>2</subscript></entry> + <entry>g<subscript>1</subscript></entry> + <entry>r<subscript>0</subscript></entry> + </row> + <row id="MEDIA-BUS-FMT-RGB888-1X7X4-JEIDA"> + <entry>MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA</entry> + <entry>0x1012</entry> + <entry>0</entry> + <entry></entry> + <entry>d</entry> + <entry>d</entry> + <entry>b<subscript>3</subscript></entry> + <entry>g<subscript>2</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>1</entry> + <entry></entry> + <entry>b<subscript>1</subscript></entry> + <entry>d</entry> + <entry>b<subscript>2</subscript></entry> + <entry>r<subscript>7</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>2</entry> + <entry></entry> + <entry>b<subscript>0</subscript></entry> + <entry>d</entry> + <entry>g<subscript>7</subscript></entry> + <entry>r<subscript>6</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>3</entry> + <entry></entry> + <entry>g<subscript>1</subscript></entry> + <entry>b<subscript>7</subscript></entry> + <entry>g<subscript>6</subscript></entry> + <entry>r<subscript>5</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>4</entry> + <entry></entry> + <entry>g<subscript>0</subscript></entry> + <entry>b<subscript>6</subscript></entry> + <entry>g<subscript>5</subscript></entry> + <entry>r<subscript>4</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>5</entry> + <entry></entry> + <entry>r<subscript>1</subscript></entry> + <entry>b<subscript>5</subscript></entry> + <entry>g<subscript>4</subscript></entry> + <entry>r<subscript>3</subscript></entry> + </row> + <row> + <entry></entry> + <entry></entry> + <entry>6</entry> + <entry></entry> + <entry>r<subscript>0</subscript></entry> + <entry>b<subscript>4</subscript></entry> + <entry>g<subscript>3</subscript></entry> + <entry>r<subscript>2</subscript></entry> + </row> + </tbody> + </tgroup> + </table> </section> <section> @@ -2660,6 +3047,43 @@ see <xref linkend="colorspaces" />.</entry> <entry>u<subscript>1</subscript></entry> <entry>u<subscript>0</subscript></entry> </row> + <row id="MEDIA-BUS-FMT-YUV8-1X24"> + <entry>MEDIA_BUS_FMT_YUV8_1X24</entry> + <entry>0x2024</entry> + <entry></entry> + <entry>-</entry> + <entry>-</entry> + <entry>-</entry> + <entry>-</entry> + <entry>-</entry> + <entry>-</entry> + <entry>-</entry> + <entry>-</entry> + <entry>y<subscript>7</subscript></entry> + <entry>y<subscript>6</subscript></entry> + <entry>y<subscript>5</subscript></entry> + <entry>y<subscript>4</subscript></entry> + <entry>y<subscript>3</subscript></entry> + <entry>y<subscript>2</subscript></entry> + <entry>y<subscript>1</subscript></entry> + <entry>y<subscript>0</subscript></entry> + <entry>u<subscript>7</subscript></entry> + <entry>u<subscript>6</subscript></entry> + <entry>u<subscript>5</subscript></entry> + <entry>u<subscript>4</subscript></entry> + <entry>u<subscript>3</subscript></entry> + <entry>u<subscript>2</subscript></entry> + <entry>u<subscript>1</subscript></entry> + <entry>u<subscript>0</subscript></entry> + <entry>v<subscript>7</subscript></entry> + <entry>v<subscript>6</subscript></entry> + <entry>v<subscript>5</subscript></entry> + <entry>v<subscript>4</subscript></entry> + <entry>v<subscript>3</subscript></entry> + <entry>v<subscript>2</subscript></entry> + <entry>v<subscript>1</subscript></entry> + <entry>v<subscript>0</subscript></entry> + </row> <row id="MEDIA-BUS-FMT-YUV10-1X30"> <entry>MEDIA_BUS_FMT_YUV10_1X30</entry> <entry>0x2016</entry> diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt index 8240c023e202..8240c023e202 100644 --- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt diff --git a/Documentation/devicetree/bindings/arm/bcm/bcm11351.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351.txt index 0ff6560e6094..0ff6560e6094 100644 --- a/Documentation/devicetree/bindings/arm/bcm/bcm11351.txt +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351.txt diff --git a/Documentation/devicetree/bindings/arm/bcm/bcm21664.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm21664.txt index e0774255e1a6..e0774255e1a6 100644 --- a/Documentation/devicetree/bindings/arm/bcm/bcm21664.txt +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm21664.txt diff --git a/Documentation/devicetree/bindings/arm/bcm2835.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt index ac683480c486..ac683480c486 100644 --- a/Documentation/devicetree/bindings/arm/bcm2835.txt +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt diff --git a/Documentation/devicetree/bindings/arm/bcm4708.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.txt index 6b0f49f6f499..6b0f49f6f499 100644 --- a/Documentation/devicetree/bindings/arm/bcm4708.txt +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.txt diff --git a/Documentation/devicetree/bindings/arm/bcm/bcm63138.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm63138.txt index bd49987a8812..bd49987a8812 100644 --- a/Documentation/devicetree/bindings/arm/bcm/bcm63138.txt +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm63138.txt diff --git a/Documentation/devicetree/bindings/arm/brcm-brcmstb.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,brcmstb.txt index 430608ec09f0..430608ec09f0 100644 --- a/Documentation/devicetree/bindings/arm/brcm-brcmstb.txt +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,brcmstb.txt diff --git a/Documentation/devicetree/bindings/arm/bcm/cygnus.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,cygnus.txt index 4c77169bb534..4c77169bb534 100644 --- a/Documentation/devicetree/bindings/arm/bcm/cygnus.txt +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,cygnus.txt diff --git a/Documentation/devicetree/bindings/bus/bcma.txt b/Documentation/devicetree/bindings/bus/brcm,bus-axi.txt index edd44d802139..edd44d802139 100644 --- a/Documentation/devicetree/bindings/bus/bcma.txt +++ b/Documentation/devicetree/bindings/bus/brcm,bus-axi.txt diff --git a/Documentation/devicetree/bindings/clock/bcm-kona-clock.txt b/Documentation/devicetree/bindings/clock/brcm,kona-ccu.txt index 5286e260fcae..5286e260fcae 100644 --- a/Documentation/devicetree/bindings/clock/bcm-kona-clock.txt +++ b/Documentation/devicetree/bindings/clock/brcm,kona-ccu.txt diff --git a/Documentation/devicetree/bindings/dma/bcm2835-dma.txt b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt index 1396078d15ac..1396078d15ac 100644 --- a/Documentation/devicetree/bindings/dma/bcm2835-dma.txt +++ b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt diff --git a/Documentation/devicetree/bindings/drm/imx/ldb.txt b/Documentation/devicetree/bindings/drm/imx/ldb.txt index 443bcb6134d5..9a21366436f6 100644 --- a/Documentation/devicetree/bindings/drm/imx/ldb.txt +++ b/Documentation/devicetree/bindings/drm/imx/ldb.txt @@ -44,23 +44,30 @@ Optional properties: LVDS Channel ============ -Each LVDS Channel has to contain a display-timings node that describes the -video timings for the connected LVDS display. For detailed information, also -have a look at Documentation/devicetree/bindings/video/display-timing.txt. +Each LVDS Channel has to contain either an of graph link to a panel device node +or a display-timings node that describes the video timings for the connected +LVDS display as well as the fsl,data-mapping and fsl,data-width properties. Required properties: - reg : should be <0> or <1> + - port: Input and output port nodes with endpoint definitions as defined in + Documentation/devicetree/bindings/graph.txt. + On i.MX5, the internal two-input-multiplexer is used. Due to hardware + limitations, only one input port (port@[0,1]) can be used for each channel + (lvds-channel@[0,1], respectively). + On i.MX6, there should be four input ports (port@[0-3]) that correspond + to the four LVDS multiplexer inputs. + A single output port (port@2 on i.MX5, port@4 on i.MX6) must be connected + to a panel input port. Optionally, the output port can be left out if + display-timings are used instead. + +Optional properties (required if display-timings are used): + - display-timings : A node that describes the display timings as defined in + Documentation/devicetree/bindings/video/display-timing.txt. - fsl,data-mapping : should be "spwg" or "jeida" This describes how the color bits are laid out in the serialized LVDS signal. - fsl,data-width : should be <18> or <24> - - port: A port node with endpoint definitions as defined in - Documentation/devicetree/bindings/media/video-interfaces.txt. - On i.MX5, the internal two-input-multiplexer is used. - Due to hardware limitations, only one port (port@[0,1]) - can be used for each channel (lvds-channel@[0,1], respectively) - On i.MX6, there should be four ports (port@[0-3]) that correspond - to the four LVDS multiplexer inputs. example: @@ -73,23 +80,21 @@ ldb: ldb@53fa8008 { #size-cells = <0>; compatible = "fsl,imx53-ldb"; gpr = <&gpr>; - clocks = <&clks 122>, <&clks 120>, - <&clks 115>, <&clks 116>, - <&clks 123>, <&clks 85>; + clocks = <&clks IMX5_CLK_LDB_DI0_SEL>, + <&clks IMX5_CLK_LDB_DI1_SEL>, + <&clks IMX5_CLK_IPU_DI0_SEL>, + <&clks IMX5_CLK_IPU_DI1_SEL>, + <&clks IMX5_CLK_LDB_DI0_GATE>, + <&clks IMX5_CLK_LDB_DI1_GATE>; clock-names = "di0_pll", "di1_pll", "di0_sel", "di1_sel", "di0", "di1"; + /* Using an of-graph endpoint link to connect the panel */ lvds-channel@0 { #address-cells = <1>; #size-cells = <0>; reg = <0>; - fsl,data-mapping = "spwg"; - fsl,data-width = <24>; - - display-timings { - /* ... */ - }; port@0 { reg = <0>; @@ -98,8 +103,17 @@ ldb: ldb@53fa8008 { remote-endpoint = <&ipu_di0_lvds0>; }; }; + + port@2 { + reg = <2>; + + lvds0_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; }; + /* Using display-timings and fsl,data-mapping/width instead */ lvds-channel@1 { #address-cells = <1>; #size-cells = <0>; @@ -120,3 +134,13 @@ ldb: ldb@53fa8008 { }; }; }; + +panel: lvds-panel { + /* ... */ + + port { + panel_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; +}; diff --git a/Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt b/Documentation/devicetree/bindings/gpio/brcm,kona-gpio.txt index 4a63bc96b687..4a63bc96b687 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt +++ b/Documentation/devicetree/bindings/gpio/brcm,kona-gpio.txt diff --git a/Documentation/devicetree/bindings/i2c/i2c-bcm-kona.txt b/Documentation/devicetree/bindings/i2c/brcm,kona-i2c.txt index 1b87b741fa8e..1b87b741fa8e 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-bcm-kona.txt +++ b/Documentation/devicetree/bindings/i2c/brcm,kona-i2c.txt diff --git a/Documentation/devicetree/bindings/mfd/bcm590xx.txt b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.txt index be51a15e05f9..be51a15e05f9 100644 --- a/Documentation/devicetree/bindings/mfd/bcm590xx.txt +++ b/Documentation/devicetree/bindings/mfd/brcm,bcm59056.txt diff --git a/Documentation/devicetree/bindings/mips/brcm/bcm3384-intc.txt b/Documentation/devicetree/bindings/mips/brcm/brcm,bcm3384-intc.txt index d4e0141d3620..d4e0141d3620 100644 --- a/Documentation/devicetree/bindings/mips/brcm/bcm3384-intc.txt +++ b/Documentation/devicetree/bindings/mips/brcm/brcm,bcm3384-intc.txt diff --git a/Documentation/devicetree/bindings/mips/brcm/bmips.txt b/Documentation/devicetree/bindings/mips/brcm/brcm,bmips.txt index 8ef71b4085ca..8ef71b4085ca 100644 --- a/Documentation/devicetree/bindings/mips/brcm/bmips.txt +++ b/Documentation/devicetree/bindings/mips/brcm/brcm,bmips.txt diff --git a/Documentation/devicetree/bindings/mips/brcm/cm-dsl.txt b/Documentation/devicetree/bindings/mips/brcm/brcm,cm-dsl.txt index 8a139cb3c0b5..8a139cb3c0b5 100644 --- a/Documentation/devicetree/bindings/mips/brcm/cm-dsl.txt +++ b/Documentation/devicetree/bindings/mips/brcm/brcm,cm-dsl.txt diff --git a/Documentation/devicetree/bindings/misc/smc.txt b/Documentation/devicetree/bindings/misc/brcm,kona-smc.txt index 6c9f176f3571..6c9f176f3571 100644 --- a/Documentation/devicetree/bindings/misc/smc.txt +++ b/Documentation/devicetree/bindings/misc/brcm,kona-smc.txt diff --git a/Documentation/devicetree/bindings/mmc/kona-sdhci.txt b/Documentation/devicetree/bindings/mmc/brcm,kona-sdhci.txt index aaba2483b4ff..aaba2483b4ff 100644 --- a/Documentation/devicetree/bindings/mmc/kona-sdhci.txt +++ b/Documentation/devicetree/bindings/mmc/brcm,kona-sdhci.txt diff --git a/Documentation/devicetree/bindings/net/broadcom-sf2.txt b/Documentation/devicetree/bindings/net/brcm,bcm7445-switch-v4.0.txt index 30d487597ecb..30d487597ecb 100644 --- a/Documentation/devicetree/bindings/net/broadcom-sf2.txt +++ b/Documentation/devicetree/bindings/net/brcm,bcm7445-switch-v4.0.txt diff --git a/Documentation/devicetree/bindings/net/broadcom-bcmgenet.txt b/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt index 451fef26b4df..451fef26b4df 100644 --- a/Documentation/devicetree/bindings/net/broadcom-bcmgenet.txt +++ b/Documentation/devicetree/bindings/net/brcm,bcmgenet.txt diff --git a/Documentation/devicetree/bindings/net/broadcom-systemport.txt b/Documentation/devicetree/bindings/net/brcm,systemport.txt index 877da34145b0..877da34145b0 100644 --- a/Documentation/devicetree/bindings/net/broadcom-systemport.txt +++ b/Documentation/devicetree/bindings/net/brcm,systemport.txt diff --git a/Documentation/devicetree/bindings/net/broadcom-mdio-unimac.txt b/Documentation/devicetree/bindings/net/brcm,unimac-mdio.txt index ab0bb4247d14..ab0bb4247d14 100644 --- a/Documentation/devicetree/bindings/net/broadcom-mdio-unimac.txt +++ b/Documentation/devicetree/bindings/net/brcm,unimac-mdio.txt diff --git a/Documentation/devicetree/bindings/phy/bcm-phy.txt b/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.txt index 3dc8b3d2ffbb..3dc8b3d2ffbb 100644 --- a/Documentation/devicetree/bindings/phy/bcm-phy.txt +++ b/Documentation/devicetree/bindings/phy/brcm,kona-usb2-phy.txt diff --git a/Documentation/devicetree/bindings/pwm/bcm-kona-pwm.txt b/Documentation/devicetree/bindings/pwm/brcm,kona-pwm.txt index 8eae9fe7841c..8eae9fe7841c 100644 --- a/Documentation/devicetree/bindings/pwm/bcm-kona-pwm.txt +++ b/Documentation/devicetree/bindings/pwm/brcm,kona-pwm.txt diff --git a/Documentation/devicetree/bindings/arm/bcm/kona-resetmgr.txt b/Documentation/devicetree/bindings/reset/brcm,bcm21664-resetmgr.txt index 93f31ca1ef4b..93f31ca1ef4b 100644 --- a/Documentation/devicetree/bindings/arm/bcm/kona-resetmgr.txt +++ b/Documentation/devicetree/bindings/reset/brcm,bcm21664-resetmgr.txt diff --git a/Documentation/devicetree/bindings/serial/bcm63xx-uart.txt b/Documentation/devicetree/bindings/serial/brcm,bcm6345-uart.txt index 5c52e5eef16d..5c52e5eef16d 100644 --- a/Documentation/devicetree/bindings/serial/bcm63xx-uart.txt +++ b/Documentation/devicetree/bindings/serial/brcm,bcm6345-uart.txt diff --git a/Documentation/devicetree/bindings/sound/bcm2835-i2s.txt b/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt index 65783de0aedf..65783de0aedf 100644 --- a/Documentation/devicetree/bindings/sound/bcm2835-i2s.txt +++ b/Documentation/devicetree/bindings/sound/brcm,bcm2835-i2s.txt diff --git a/Documentation/devicetree/bindings/arm/bcm/kona-timer.txt b/Documentation/devicetree/bindings/timer/brcm,kona-timer.txt index 39adf54b4388..39adf54b4388 100644 --- a/Documentation/devicetree/bindings/arm/bcm/kona-timer.txt +++ b/Documentation/devicetree/bindings/timer/brcm,kona-timer.txt diff --git a/Documentation/devicetree/bindings/unittest.txt b/Documentation/devicetree/bindings/unittest.txt index 8933211f32f9..3bf58c20fe94 100644 --- a/Documentation/devicetree/bindings/unittest.txt +++ b/Documentation/devicetree/bindings/unittest.txt @@ -1,60 +1,60 @@ -1) OF selftest platform device +1) OF unittest platform device -** selftest +** unittest Required properties: -- compatible: must be "selftest" +- compatible: must be "unittest" All other properties are optional. Example: - selftest { - compatible = "selftest"; + unittest { + compatible = "unittest"; status = "okay"; }; -2) OF selftest i2c adapter platform device +2) OF unittest i2c adapter platform device ** platform device unittest adapter Required properties: -- compatible: must be selftest-i2c-bus +- compatible: must be unittest-i2c-bus -Children nodes contain selftest i2c devices. +Children nodes contain unittest i2c devices. Example: - selftest-i2c-bus { - compatible = "selftest-i2c-bus"; + unittest-i2c-bus { + compatible = "unittest-i2c-bus"; status = "okay"; }; -3) OF selftest i2c device +3) OF unittest i2c device -** I2C selftest device +** I2C unittest device Required properties: -- compatible: must be selftest-i2c-dev +- compatible: must be unittest-i2c-dev All other properties are optional Example: - selftest-i2c-dev { - compatible = "selftest-i2c-dev"; + unittest-i2c-dev { + compatible = "unittest-i2c-dev"; status = "okay"; }; -4) OF selftest i2c mux device +4) OF unittest i2c mux device -** I2C selftest mux +** I2C unittest mux Required properties: -- compatible: must be selftest-i2c-mux +- compatible: must be unittest-i2c-mux -Children nodes contain selftest i2c bus nodes per channel. +Children nodes contain unittest i2c bus nodes per channel. Example: - selftest-i2c-mux { - compatible = "selftest-i2c-mux"; + unittest-i2c-mux { + compatible = "unittest-i2c-mux"; status = "okay"; #address-cells = <1>; #size-cells = <0>; @@ -64,7 +64,7 @@ Example: #size-cells = <0>; i2c-dev { reg = <8>; - compatible = "selftest-i2c-dev"; + compatible = "unittest-i2c-dev"; status = "okay"; }; }; diff --git a/Documentation/devicetree/bindings/mips/brcm/usb.txt b/Documentation/devicetree/bindings/usb/brcm,bcm3384-usb.txt index 452c45c7bf29..452c45c7bf29 100644 --- a/Documentation/devicetree/bindings/mips/brcm/usb.txt +++ b/Documentation/devicetree/bindings/usb/brcm,bcm3384-usb.txt diff --git a/Documentation/devicetree/bindings/arm/bcm/kona-wdt.txt b/Documentation/devicetree/bindings/watchdog/brcm,kona-wdt.txt index 2b86a00e351d..2b86a00e351d 100644 --- a/Documentation/devicetree/bindings/arm/bcm/kona-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/brcm,kona-wdt.txt diff --git a/Documentation/devicetree/of_selftest.txt b/Documentation/devicetree/of_unittest.txt index 57a808b588bf..3e4e7d48ae93 100644 --- a/Documentation/devicetree/of_selftest.txt +++ b/Documentation/devicetree/of_unittest.txt @@ -1,11 +1,11 @@ -Open Firmware Device Tree Selftest +Open Firmware Device Tree Unittest ---------------------------------- Author: Gaurav Minocha <gaurav.minocha.os@gmail.com> 1. Introduction -This document explains how the test data required for executing OF selftest +This document explains how the test data required for executing OF unittest is attached to the live tree dynamically, independent of the machine's architecture. @@ -22,31 +22,31 @@ most of the device drivers in various use cases. 2. Test-data -The Device Tree Source file (drivers/of/testcase-data/testcases.dts) contains +The Device Tree Source file (drivers/of/unittest-data/testcases.dts) contains the test data required for executing the unit tests automated in -drivers/of/selftests.c. Currently, following Device Tree Source Include files -(.dtsi) are included in testcase.dts: +drivers/of/unittest.c. Currently, following Device Tree Source Include files +(.dtsi) are included in testcases.dts: -drivers/of/testcase-data/tests-interrupts.dtsi -drivers/of/testcase-data/tests-platform.dtsi -drivers/of/testcase-data/tests-phandle.dtsi -drivers/of/testcase-data/tests-match.dtsi +drivers/of/unittest-data/tests-interrupts.dtsi +drivers/of/unittest-data/tests-platform.dtsi +drivers/of/unittest-data/tests-phandle.dtsi +drivers/of/unittest-data/tests-match.dtsi When the kernel is build with OF_SELFTEST enabled, then the following make rule $(obj)/%.dtb: $(src)/%.dts FORCE $(call if_changed_dep, dtc) -is used to compile the DT source file (testcase.dts) into a binary blob -(testcase.dtb), also referred as flattened DT. +is used to compile the DT source file (testcases.dts) into a binary blob +(testcases.dtb), also referred as flattened DT. After that, using the following rule the binary blob above is wrapped as an -assembly file (testcase.dtb.S). +assembly file (testcases.dtb.S). $(obj)/%.dtb.S: $(obj)/%.dtb $(call cmd, dt_S_dtb) -The assembly file is compiled into an object file (testcase.dtb.o), and is +The assembly file is compiled into an object file (testcases.dtb.o), and is linked into the kernel image. @@ -98,7 +98,7 @@ child11 -> sibling12 -> sibling13 -> sibling14 -> null Figure 1: Generic structure of un-flattened device tree -Before executing OF selftest, it is required to attach the test data to +Before executing OF unittest, it is required to attach the test data to machine's device tree (if present). So, when selftest_data_add() is called, at first it reads the flattened device tree data linked into the kernel image via the following kernel symbols: diff --git a/MAINTAINERS b/MAINTAINERS index 2c060fd2a98b..652004223ead 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7192,6 +7192,15 @@ F: Documentation/devicetree/ F: arch/*/boot/dts/ F: include/dt-bindings/ +OPEN FIRMWARE AND DEVICE TREE OVERLAYS +M: Pantelis Antoniou <pantelis.antoniou@konsulko.com> +L: devicetree@vger.kernel.org +S: Maintained +F: Documentation/devicetree/dynamic-resolution-notes.txt +F: Documentation/devicetree/overlay-notes.txt +F: drivers/of/overlay.c +F: drivers/of/resolver.c + OPENRISC ARCHITECTURE M: Jonas Bonn <jonas@southpole.se> W: http://openrisc.net diff --git a/drivers/coresight/of_coresight.c b/drivers/coresight/of_coresight.c index c3efa418a86d..6f75e9d5b6fb 100644 --- a/drivers/coresight/of_coresight.c +++ b/drivers/coresight/of_coresight.c @@ -52,15 +52,6 @@ of_coresight_get_endpoint_device(struct device_node *endpoint) endpoint, of_dev_node_match); } -static struct device_node *of_get_coresight_endpoint( - const struct device_node *parent, struct device_node *prev) -{ - struct device_node *node = of_graph_get_next_endpoint(parent, prev); - - of_node_put(prev); - return node; -} - static void of_coresight_get_ports(struct device_node *node, int *nr_inport, int *nr_outport) { @@ -68,7 +59,7 @@ static void of_coresight_get_ports(struct device_node *node, int in = 0, out = 0; do { - ep = of_get_coresight_endpoint(node, ep); + ep = of_graph_get_next_endpoint(node, ep); if (!ep) break; @@ -140,7 +131,7 @@ struct coresight_platform_data *of_get_coresight_platform_data( /* Iterate through each port to discover topology */ do { /* Get a handle on a port */ - ep = of_get_coresight_endpoint(node, ep); + ep = of_graph_get_next_endpoint(node, ep); if (!ep) break; diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index 16150a00c237..aaa130736bf8 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c @@ -43,14 +43,10 @@ static uint32_t drm_crtc_port_mask(struct drm_device *dev, uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, struct device_node *port) { - struct device_node *remote_port, *ep = NULL; + struct device_node *remote_port, *ep; uint32_t possible_crtcs = 0; - do { - ep = of_graph_get_next_endpoint(port, ep); - if (!ep) - break; - + for_each_endpoint_of_node(port, ep) { remote_port = of_graph_get_remote_port(ep); if (!remote_port) { of_node_put(ep); @@ -60,7 +56,7 @@ uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, possible_crtcs |= drm_crtc_port_mask(dev, remote_port); of_node_put(remote_port); - } while (1); + } return possible_crtcs; } diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index 970046199608..1f7e33f59de6 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -28,6 +28,7 @@ #include <video/exynos7_decon.h> #include "exynos_drm_crtc.h" +#include "exynos_drm_plane.h" #include "exynos_drm_drv.h" #include "exynos_drm_fbdev.h" #include "exynos_drm_iommu.h" @@ -41,32 +42,16 @@ #define WINDOWS_NR 2 -struct decon_win_data { - unsigned int ovl_x; - unsigned int ovl_y; - unsigned int offset_x; - unsigned int offset_y; - unsigned int ovl_width; - unsigned int ovl_height; - unsigned int fb_width; - unsigned int fb_height; - unsigned int bpp; - unsigned int pixel_format; - dma_addr_t dma_addr; - bool enabled; - bool resume; -}; - struct decon_context { struct device *dev; struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; + struct exynos_drm_plane planes[WINDOWS_NR]; struct clk *pclk; struct clk *aclk; struct clk *eclk; struct clk *vclk; void __iomem *regs; - struct decon_win_data win_data[WINDOWS_NR]; unsigned int default_win; unsigned long irq_flags; bool i80_if; @@ -296,59 +281,16 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) } } -static void decon_win_mode_set(struct exynos_drm_crtc *crtc, - struct exynos_drm_plane *plane) -{ - struct decon_context *ctx = crtc->ctx; - struct decon_win_data *win_data; - int win, padding; - - if (!plane) { - DRM_ERROR("plane is NULL\n"); - return; - } - - win = plane->zpos; - if (win == DEFAULT_ZPOS) - win = ctx->default_win; - - if (win < 0 || win >= WINDOWS_NR) - return; - - - win_data = &ctx->win_data[win]; - - padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width; - win_data->offset_x = plane->fb_x; - win_data->offset_y = plane->fb_y; - win_data->fb_width = plane->fb_width + padding; - win_data->fb_height = plane->fb_height; - win_data->ovl_x = plane->crtc_x; - win_data->ovl_y = plane->crtc_y; - win_data->ovl_width = plane->crtc_width; - win_data->ovl_height = plane->crtc_height; - win_data->dma_addr = plane->dma_addr[0]; - win_data->bpp = plane->bpp; - win_data->pixel_format = plane->pixel_format; - - DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n", - win_data->offset_x, win_data->offset_y); - DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", - win_data->ovl_width, win_data->ovl_height); - DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr); - DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", - plane->fb_width, plane->crtc_width); -} - static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) { - struct decon_win_data *win_data = &ctx->win_data[win]; + struct exynos_drm_plane *plane = &ctx->planes[win]; unsigned long val; + int padding; val = readl(ctx->regs + WINCON(win)); val &= ~WINCONx_BPPMODE_MASK; - switch (win_data->pixel_format) { + switch (plane->pixel_format) { case DRM_FORMAT_RGB565: val |= WINCONx_BPPMODE_16BPP_565; val |= WINCONx_BURSTLEN_16WORD; @@ -397,7 +339,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) break; } - DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp); + DRM_DEBUG_KMS("bpp = %d\n", plane->bpp); /* * In case of exynos, setting dma-burst to 16Word causes permanent @@ -407,7 +349,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) * movement causes unstable DMA which results into iommu crash/tear. */ - if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) { + padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width; + if (plane->fb_width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) { val &= ~WINCONx_BURSTLEN_MASK; val |= WINCONx_BURSTLEN_8WORD; } @@ -435,7 +378,7 @@ static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win) * @protect: 1 to protect (disable updates) */ static void decon_shadow_protect_win(struct decon_context *ctx, - int win, bool protect) + unsigned int win, bool protect) { u32 bits, val; @@ -449,12 +392,12 @@ static void decon_shadow_protect_win(struct decon_context *ctx, writel(val, ctx->regs + SHADOWCON); } -static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos) +static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) { struct decon_context *ctx = crtc->ctx; struct drm_display_mode *mode = &crtc->base.mode; - struct decon_win_data *win_data; - int win = zpos; + struct exynos_drm_plane *plane; + int padding; unsigned long val, alpha; unsigned int last_x; unsigned int last_y; @@ -462,17 +405,14 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos) if (ctx->suspended) return; - if (win == DEFAULT_ZPOS) - win = ctx->default_win; - if (win < 0 || win >= WINDOWS_NR) return; - win_data = &ctx->win_data[win]; + plane = &ctx->planes[win]; /* If suspended, enable this on resume */ if (ctx->suspended) { - win_data->resume = true; + plane->resume = true; return; } @@ -490,39 +430,41 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos) decon_shadow_protect_win(ctx, win, true); /* buffer start address */ - val = (unsigned long)win_data->dma_addr; + val = (unsigned long)plane->dma_addr[0]; writel(val, ctx->regs + VIDW_BUF_START(win)); + padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width; + /* buffer size */ - writel(win_data->fb_width, ctx->regs + VIDW_WHOLE_X(win)); - writel(win_data->fb_height, ctx->regs + VIDW_WHOLE_Y(win)); + writel(plane->fb_width + padding, ctx->regs + VIDW_WHOLE_X(win)); + writel(plane->fb_height, ctx->regs + VIDW_WHOLE_Y(win)); /* offset from the start of the buffer to read */ - writel(win_data->offset_x, ctx->regs + VIDW_OFFSET_X(win)); - writel(win_data->offset_y, ctx->regs + VIDW_OFFSET_Y(win)); + writel(plane->src_x, ctx->regs + VIDW_OFFSET_X(win)); + writel(plane->src_y, ctx->regs + VIDW_OFFSET_Y(win)); DRM_DEBUG_KMS("start addr = 0x%lx\n", - (unsigned long)win_data->dma_addr); + (unsigned long)val); DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", - win_data->ovl_width, win_data->ovl_height); + plane->crtc_width, plane->crtc_height); /* * OSD position. * In case the window layout goes of LCD layout, DECON fails. */ - if ((win_data->ovl_x + win_data->ovl_width) > mode->hdisplay) - win_data->ovl_x = mode->hdisplay - win_data->ovl_width; - if ((win_data->ovl_y + win_data->ovl_height) > mode->vdisplay) - win_data->ovl_y = mode->vdisplay - win_data->ovl_height; + if ((plane->crtc_x + plane->crtc_width) > mode->hdisplay) + plane->crtc_x = mode->hdisplay - plane->crtc_width; + if ((plane->crtc_y + plane->crtc_height) > mode->vdisplay) + plane->crtc_y = mode->vdisplay - plane->crtc_height; - val = VIDOSDxA_TOPLEFT_X(win_data->ovl_x) | - VIDOSDxA_TOPLEFT_Y(win_data->ovl_y); + val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) | + VIDOSDxA_TOPLEFT_Y(plane->crtc_y); writel(val, ctx->regs + VIDOSD_A(win)); - last_x = win_data->ovl_x + win_data->ovl_width; + last_x = plane->crtc_x + plane->crtc_width; if (last_x) last_x--; - last_y = win_data->ovl_y + win_data->ovl_height; + last_y = plane->crtc_y + plane->crtc_height; if (last_y) last_y--; @@ -531,7 +473,7 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos) writel(val, ctx->regs + VIDOSD_B(win)); DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", - win_data->ovl_x, win_data->ovl_y, last_x, last_y); + plane->crtc_x, plane->crtc_y, last_x, last_y); /* OSD alpha */ alpha = VIDOSDxC_ALPHA0_R_F(0x0) | @@ -565,27 +507,23 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos) val |= DECON_UPDATE_STANDALONE_F; writel(val, ctx->regs + DECON_UPDATE); - win_data->enabled = true; + plane->enabled = true; } -static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos) +static void decon_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) { struct decon_context *ctx = crtc->ctx; - struct decon_win_data *win_data; - int win = zpos; + struct exynos_drm_plane *plane; u32 val; - if (win == DEFAULT_ZPOS) - win = ctx->default_win; - if (win < 0 || win >= WINDOWS_NR) return; - win_data = &ctx->win_data[win]; + plane = &ctx->planes[win]; if (ctx->suspended) { /* do not resume this window*/ - win_data->resume = false; + plane->resume = false; return; } @@ -604,42 +542,42 @@ static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos) val |= DECON_UPDATE_STANDALONE_F; writel(val, ctx->regs + DECON_UPDATE); - win_data->enabled = false; + plane->enabled = false; } static void decon_window_suspend(struct decon_context *ctx) { - struct decon_win_data *win_data; + struct exynos_drm_plane *plane; int i; for (i = 0; i < WINDOWS_NR; i++) { - win_data = &ctx->win_data[i]; - win_data->resume = win_data->enabled; - if (win_data->enabled) + plane = &ctx->planes[i]; + plane->resume = plane->enabled; + if (plane->enabled) decon_win_disable(ctx->crtc, i); } } static void decon_window_resume(struct decon_context *ctx) { - struct decon_win_data *win_data; + struct exynos_drm_plane *plane; int i; for (i = 0; i < WINDOWS_NR; i++) { - win_data = &ctx->win_data[i]; - win_data->enabled = win_data->resume; - win_data->resume = false; + plane = &ctx->planes[i]; + plane->enabled = plane->resume; + plane->resume = false; } } static void decon_apply(struct decon_context *ctx) { - struct decon_win_data *win_data; + struct exynos_drm_plane *plane; int i; for (i = 0; i < WINDOWS_NR; i++) { - win_data = &ctx->win_data[i]; - if (win_data->enabled) + plane = &ctx->planes[i]; + if (plane->enabled) decon_win_commit(ctx->crtc, i); else decon_win_disable(ctx->crtc, i); @@ -779,7 +717,6 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = { .enable_vblank = decon_enable_vblank, .disable_vblank = decon_disable_vblank, .wait_for_vblank = decon_wait_for_vblank, - .win_mode_set = decon_win_mode_set, .win_commit = decon_win_commit, .win_disable = decon_win_disable, }; @@ -818,6 +755,9 @@ static int decon_bind(struct device *dev, struct device *master, void *data) { struct decon_context *ctx = dev_get_drvdata(dev); struct drm_device *drm_dev = data; + struct exynos_drm_plane *exynos_plane; + enum drm_plane_type type; + unsigned int zpos; int ret; ret = decon_ctx_initialize(ctx, drm_dev); @@ -826,8 +766,18 @@ static int decon_bind(struct device *dev, struct device *master, void *data) return ret; } - ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, - EXYNOS_DISPLAY_TYPE_LCD, + for (zpos = 0; zpos < WINDOWS_NR; zpos++) { + type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY : + DRM_PLANE_TYPE_OVERLAY; + ret = exynos_plane_init(drm_dev, &ctx->planes[zpos], + 1 << ctx->pipe, type, zpos); + if (ret) + return ret; + } + + exynos_plane = &ctx->planes[ctx->default_win]; + ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, + ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD, &decon_crtc_ops, ctx); if (IS_ERR(ctx->crtc)) { decon_ctx_remove(ctx); diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index bf17a60b40ed..1dbfba58f909 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -32,10 +32,16 @@ #include <drm/bridge/ptn3460.h> #include "exynos_dp_core.h" +#include "exynos_drm_fimd.h" #define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \ connector) +static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp) +{ + return to_exynos_crtc(dp->encoder->crtc); +} + static inline struct exynos_dp_device * display_to_dp(struct exynos_drm_display *d) { @@ -1070,6 +1076,8 @@ static void exynos_dp_poweron(struct exynos_dp_device *dp) } } + fimd_dp_clock_enable(dp_to_crtc(dp), true); + clk_prepare_enable(dp->clock); exynos_dp_phy_init(dp); exynos_dp_init_dp(dp); @@ -1094,6 +1102,8 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp) exynos_dp_phy_exit(dp); clk_disable_unprepare(dp->clock); + fimd_dp_clock_enable(dp_to_crtc(dp), false); + if (dp->panel) { if (drm_panel_unprepare(dp->panel)) DRM_ERROR("failed to turnoff the panel\n"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 48ccab7fdf63..eb49195cec5c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -34,9 +34,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) if (mode > DRM_MODE_DPMS_ON) { /* wait for the completion of page flip. */ if (!wait_event_timeout(exynos_crtc->pending_flip_queue, - !atomic_read(&exynos_crtc->pending_flip), - HZ/20)) - atomic_set(&exynos_crtc->pending_flip, 0); + (exynos_crtc->event == NULL), HZ/20)) + exynos_crtc->event = NULL; drm_crtc_vblank_off(crtc); } @@ -164,11 +163,10 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, uint32_t page_flip_flags) { struct drm_device *dev = crtc->dev; - struct exynos_drm_private *dev_priv = dev->dev_private; struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct drm_framebuffer *old_fb = crtc->primary->fb; unsigned int crtc_w, crtc_h; - int ret = -EINVAL; + int ret; /* when the page flip is requested, crtc's dpms should be on */ if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) { @@ -176,48 +174,49 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, return -EINVAL; } - mutex_lock(&dev->struct_mutex); + if (!event) + return -EINVAL; - if (event) { - /* - * the pipe from user always is 0 so we can set pipe number - * of current owner to event. - */ - event->pipe = exynos_crtc->pipe; + spin_lock_irq(&dev->event_lock); + if (exynos_crtc->event) { + ret = -EBUSY; + goto out; + } - ret = drm_vblank_get(dev, exynos_crtc->pipe); - if (ret) { - DRM_DEBUG("failed to acquire vblank counter\n"); + ret = drm_vblank_get(dev, exynos_crtc->pipe); + if (ret) { + DRM_DEBUG("failed to acquire vblank counter\n"); + goto out; + } - goto out; - } + exynos_crtc->event = event; + spin_unlock_irq(&dev->event_lock); + /* + * the pipe from user always is 0 so we can set pipe number + * of current owner to event. + */ + event->pipe = exynos_crtc->pipe; + + crtc->primary->fb = fb; + crtc_w = fb->width - crtc->x; + crtc_h = fb->height - crtc->y; + ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0, + crtc_w, crtc_h, crtc->x, crtc->y, + crtc_w, crtc_h); + if (ret) { + crtc->primary->fb = old_fb; spin_lock_irq(&dev->event_lock); - list_add_tail(&event->base.link, - &dev_priv->pageflip_event_list); - atomic_set(&exynos_crtc->pending_flip, 1); + exynos_crtc->event = NULL; + drm_vblank_put(dev, exynos_crtc->pipe); spin_unlock_irq(&dev->event_lock); - - crtc->primary->fb = fb; - crtc_w = fb->width - crtc->x; - crtc_h = fb->height - crtc->y; - ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0, - crtc_w, crtc_h, crtc->x, crtc->y, - crtc_w, crtc_h); - if (ret) { - crtc->primary->fb = old_fb; - - spin_lock_irq(&dev->event_lock); - drm_vblank_put(dev, exynos_crtc->pipe); - list_del(&event->base.link); - atomic_set(&exynos_crtc->pending_flip, 0); - spin_unlock_irq(&dev->event_lock); - - goto out; - } + return ret; } + + return 0; + out: - mutex_unlock(&dev->struct_mutex); + spin_unlock_irq(&dev->event_lock); return ret; } @@ -239,13 +238,13 @@ static struct drm_crtc_funcs exynos_crtc_funcs = { }; struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, + struct drm_plane *plane, int pipe, enum exynos_drm_output_type type, struct exynos_drm_crtc_ops *ops, void *ctx) { struct exynos_drm_crtc *exynos_crtc; - struct drm_plane *plane; struct exynos_drm_private *private = drm_dev->dev_private; struct drm_crtc *crtc; int ret; @@ -255,19 +254,12 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, return ERR_PTR(-ENOMEM); init_waitqueue_head(&exynos_crtc->pending_flip_queue); - atomic_set(&exynos_crtc->pending_flip, 0); exynos_crtc->dpms = DRM_MODE_DPMS_OFF; exynos_crtc->pipe = pipe; exynos_crtc->type = type; exynos_crtc->ops = ops; exynos_crtc->ctx = ctx; - plane = exynos_plane_init(drm_dev, 1 << pipe, - DRM_PLANE_TYPE_PRIMARY); - if (IS_ERR(plane)) { - ret = PTR_ERR(plane); - goto err_plane; - } crtc = &exynos_crtc->base; @@ -284,7 +276,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, err_crtc: plane->funcs->destroy(plane); -err_plane: kfree(exynos_crtc); return ERR_PTR(ret); } @@ -320,26 +311,20 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe) void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe) { struct exynos_drm_private *dev_priv = dev->dev_private; - struct drm_pending_vblank_event *e, *t; struct drm_crtc *drm_crtc = dev_priv->crtc[pipe]; struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc); unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); + if (exynos_crtc->event) { - list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, - base.link) { - /* if event's pipe isn't same as crtc then ignore it. */ - if (pipe != e->pipe) - continue; - - list_del(&e->base.link); - drm_send_vblank_event(dev, -1, e); + drm_send_vblank_event(dev, -1, exynos_crtc->event); drm_vblank_put(dev, pipe); - atomic_set(&exynos_crtc->pending_flip, 0); wake_up(&exynos_crtc->pending_flip_queue); + } + exynos_crtc->event = NULL; spin_unlock_irqrestore(&dev->event_lock, flags); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h index 6258b800aab8..0ecd8fc45cff 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h @@ -18,6 +18,7 @@ #include "exynos_drm_drv.h" struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, + struct drm_plane *plane, int pipe, enum exynos_drm_output_type type, struct exynos_drm_crtc_ops *ops, @@ -27,12 +28,6 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe); void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe); void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb); -void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc, - struct exynos_drm_plane *plane); -void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos); -void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos); -void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos); - /* This function gets pipe value to crtc device matched with out_type. */ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, unsigned int out_type); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 90168d7cf66a..8ac465208eae 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -55,13 +55,11 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) { struct exynos_drm_private *private; int ret; - int nr; private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); if (!private) return -ENOMEM; - INIT_LIST_HEAD(&private->pageflip_event_list); dev_set_drvdata(dev->dev, dev); dev->dev_private = (void *)private; @@ -81,19 +79,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) exynos_drm_mode_config_init(dev); - for (nr = 0; nr < MAX_PLANE; nr++) { - struct drm_plane *plane; - unsigned long possible_crtcs = (1 << MAX_CRTC) - 1; - - plane = exynos_plane_init(dev, possible_crtcs, - DRM_PLANE_TYPE_OVERLAY); - if (!IS_ERR(plane)) - continue; - - ret = PTR_ERR(plane); - goto err_mode_config_cleanup; - } - /* setup possible_clones. */ exynos_drm_encoder_setup(dev); @@ -237,25 +222,13 @@ static void exynos_drm_preclose(struct drm_device *dev, static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) { - struct exynos_drm_private *private = dev->dev_private; - struct drm_pending_vblank_event *v, *vt; struct drm_pending_event *e, *et; unsigned long flags; if (!file->driver_priv) return; - /* Release all events not unhandled by page flip handler. */ spin_lock_irqsave(&dev->event_lock, flags); - list_for_each_entry_safe(v, vt, &private->pageflip_event_list, - base.link) { - if (v->base.file_priv == file) { - list_del(&v->base.link); - drm_vblank_put(dev, v->pipe); - v->base.destroy(&v->base); - } - } - /* Release all events handled by page flip handler but not freed. */ list_for_each_entry_safe(e, et, &file->event_list, link) { list_del(&e->link); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 9afd390d4674..e12ecb5d5d9a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -21,7 +21,6 @@ #define MAX_CRTC 3 #define MAX_PLANE 5 #define MAX_FB_BUFFER 4 -#define DEFAULT_ZPOS -1 #define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc, base) #define to_exynos_plane(x) container_of(x, struct exynos_drm_plane, base) @@ -48,20 +47,22 @@ enum exynos_drm_output_type { * Exynos drm common overlay structure. * * @base: plane object - * @fb_x: offset x on a framebuffer to be displayed. + * @src_x: offset x on a framebuffer to be displayed. * - the unit is screen coordinates. - * @fb_y: offset y on a framebuffer to be displayed. + * @src_y: offset y on a framebuffer to be displayed. * - the unit is screen coordinates. - * @fb_width: width of a framebuffer. - * @fb_height: height of a framebuffer. * @src_width: width of a partial image to be displayed from framebuffer. * @src_height: height of a partial image to be displayed from framebuffer. + * @fb_width: width of a framebuffer. + * @fb_height: height of a framebuffer. * @crtc_x: offset x on hardware screen. * @crtc_y: offset y on hardware screen. * @crtc_width: window width to be displayed (hardware screen). * @crtc_height: window height to be displayed (hardware screen). * @mode_width: width of screen mode. * @mode_height: height of screen mode. + * @h_ratio: horizontal scaling ratio, 16.16 fixed point + * @v_ratio: vertical scaling ratio, 16.16 fixed point * @refresh: refresh rate. * @scan_flag: interlace or progressive way. * (it could be DRM_MODE_FLAG_*) @@ -78,6 +79,7 @@ enum exynos_drm_output_type { * @transparency: transparency on or off. * @activated: activated or not. * @enabled: enabled or not. + * @resume: to resume or not. * * this structure is common to exynos SoC and its contents would be copied * to hardware specific overlay info. @@ -85,25 +87,27 @@ enum exynos_drm_output_type { struct exynos_drm_plane { struct drm_plane base; - unsigned int fb_x; - unsigned int fb_y; - unsigned int fb_width; - unsigned int fb_height; + unsigned int src_x; + unsigned int src_y; unsigned int src_width; unsigned int src_height; + unsigned int fb_width; + unsigned int fb_height; unsigned int crtc_x; unsigned int crtc_y; unsigned int crtc_width; unsigned int crtc_height; unsigned int mode_width; unsigned int mode_height; + unsigned int h_ratio; + unsigned int v_ratio; unsigned int refresh; unsigned int scan_flag; unsigned int bpp; unsigned int pitch; uint32_t pixel_format; dma_addr_t dma_addr[MAX_FB_BUFFER]; - int zpos; + unsigned int zpos; unsigned int index_color; bool default_win:1; @@ -112,6 +116,7 @@ struct exynos_drm_plane { bool transparency:1; bool activated:1; bool enabled:1; + bool resume:1; }; /* @@ -172,9 +177,7 @@ struct exynos_drm_display { * @disable_vblank: specific driver callback for disabling vblank interrupt. * @wait_for_vblank: wait for vblank interrupt to make sure that * hardware overlay is updated. - * @win_mode_set: copy drm overlay info to hw specific overlay info. * @win_commit: apply hardware specific overlay data to registers. - * @win_enable: enable hardware specific overlay. * @win_disable: disable hardware specific overlay. * @te_handler: trigger to transfer video image at the tearing effect * synchronization signal if there is a page flip request. @@ -189,11 +192,8 @@ struct exynos_drm_crtc_ops { int (*enable_vblank)(struct exynos_drm_crtc *crtc); void (*disable_vblank)(struct exynos_drm_crtc *crtc); void (*wait_for_vblank)(struct exynos_drm_crtc *crtc); - void (*win_mode_set)(struct exynos_drm_crtc *crtc, - struct exynos_drm_plane *plane); - void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos); - void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos); - void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos); + void (*win_commit)(struct exynos_drm_crtc *crtc, unsigned int zpos); + void (*win_disable)(struct exynos_drm_crtc *crtc, unsigned int zpos); void (*te_handler)(struct exynos_drm_crtc *crtc); }; @@ -210,6 +210,7 @@ struct exynos_drm_crtc_ops { * we can refer to the crtc to current hardware interrupt occurred through * this pipe value. * @dpms: store the crtc dpms value + * @event: vblank event that is currently queued for flip * @ops: pointer to callbacks for exynos drm specific functionality * @ctx: A pointer to the crtc's implementation specific context */ @@ -219,7 +220,7 @@ struct exynos_drm_crtc { unsigned int pipe; unsigned int dpms; wait_queue_head_t pending_flip_queue; - atomic_t pending_flip; + struct drm_pending_vblank_event *event; struct exynos_drm_crtc_ops *ops; void *ctx; }; @@ -249,9 +250,6 @@ struct drm_exynos_file_private { struct exynos_drm_private { struct drm_fb_helper *fb_helper; - /* list head for new event to be added. */ - struct list_head pageflip_event_list; - /* * created crtc object would be contained at this array and * this array is used to be aware of which crtc did it request vblank. diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 05fe93dc57a8..04927153bf38 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1473,12 +1473,6 @@ static int exynos_dsi_get_modes(struct drm_connector *connector) return 0; } -static int exynos_dsi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - return MODE_OK; -} - static struct drm_encoder * exynos_dsi_best_encoder(struct drm_connector *connector) { @@ -1489,7 +1483,6 @@ exynos_dsi_best_encoder(struct drm_connector *connector) static struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = { .get_modes = exynos_dsi_get_modes, - .mode_valid = exynos_dsi_mode_valid, .best_encoder = exynos_dsi_best_encoder, }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index d346d1e6eda0..929cb03a8eab 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -151,10 +151,8 @@ exynos_drm_framebuffer_init(struct drm_device *dev, exynos_gem_obj = to_exynos_gem_obj(obj); ret = check_fb_gem_memory_type(dev, exynos_gem_obj); - if (ret < 0) { - DRM_ERROR("cannot use this gem memory type for fb.\n"); - return ERR_PTR(-EINVAL); - } + if (ret < 0) + return ERR_PTR(ret); exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); if (!exynos_fb) @@ -250,10 +248,8 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, exynos_fb->exynos_gem_obj[i] = exynos_gem_obj; ret = check_fb_gem_memory_type(dev, exynos_gem_obj); - if (ret < 0) { - DRM_ERROR("cannot use this gem memory type for fb.\n"); + if (ret < 0) goto err_unreference; - } } ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 33a10ce967ea..9819fa6a9e2a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -31,7 +31,9 @@ #include "exynos_drm_drv.h" #include "exynos_drm_fbdev.h" #include "exynos_drm_crtc.h" +#include "exynos_drm_plane.h" #include "exynos_drm_iommu.h" +#include "exynos_drm_fimd.h" /* * FIMD stands for Fully Interactive Mobile Display and @@ -54,6 +56,9 @@ /* size control register for hardware windows 1 ~ 2. */ #define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16) +#define VIDWnALPHA0(win) (VIDW_ALPHA + 0x00 + (win) * 8) +#define VIDWnALPHA1(win) (VIDW_ALPHA + 0x04 + (win) * 8) + #define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8) #define VIDWx_BUF_END(win, buf) (VIDW_BUF_END(buf) + (win) * 8) #define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4) @@ -140,32 +145,15 @@ static struct fimd_driver_data exynos5_fimd_driver_data = { .has_vtsel = 1, }; -struct fimd_win_data { - unsigned int offset_x; - unsigned int offset_y; - unsigned int ovl_width; - unsigned int ovl_height; - unsigned int fb_width; - unsigned int fb_height; - unsigned int fb_pitch; - unsigned int bpp; - unsigned int pixel_format; - dma_addr_t dma_addr; - unsigned int buf_offsize; - unsigned int line_size; /* bytes */ - bool enabled; - bool resume; -}; - struct fimd_context { struct device *dev; struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; + struct exynos_drm_plane planes[WINDOWS_NR]; struct clk *bus_clk; struct clk *lcd_clk; void __iomem *regs; struct regmap *sysreg; - struct fimd_win_data win_data[WINDOWS_NR]; unsigned int default_win; unsigned long irq_flags; u32 vidcon0; @@ -502,59 +490,9 @@ static void fimd_disable_vblank(struct exynos_drm_crtc *crtc) } } -static void fimd_win_mode_set(struct exynos_drm_crtc *crtc, - struct exynos_drm_plane *plane) -{ - struct fimd_context *ctx = crtc->ctx; - struct fimd_win_data *win_data; - int win; - unsigned long offset; - - if (!plane) { - DRM_ERROR("plane is NULL\n"); - return; - } - - win = plane->zpos; - if (win == DEFAULT_ZPOS) - win = ctx->default_win; - - if (win < 0 || win >= WINDOWS_NR) - return; - - offset = plane->fb_x * (plane->bpp >> 3); - offset += plane->fb_y * plane->pitch; - - DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch); - - win_data = &ctx->win_data[win]; - - win_data->offset_x = plane->crtc_x; - win_data->offset_y = plane->crtc_y; - win_data->ovl_width = plane->crtc_width; - win_data->ovl_height = plane->crtc_height; - win_data->fb_pitch = plane->pitch; - win_data->fb_width = plane->fb_width; - win_data->fb_height = plane->fb_height; - win_data->dma_addr = plane->dma_addr[0] + offset; - win_data->bpp = plane->bpp; - win_data->pixel_format = plane->pixel_format; - win_data->buf_offsize = - plane->pitch - (plane->crtc_width * (plane->bpp >> 3)); - win_data->line_size = plane->crtc_width * (plane->bpp >> 3); - - DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n", - win_data->offset_x, win_data->offset_y); - DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", - win_data->ovl_width, win_data->ovl_height); - DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr); - DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", - plane->fb_width, plane->crtc_width); -} - static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) { - struct fimd_win_data *win_data = &ctx->win_data[win]; + struct exynos_drm_plane *plane = &ctx->planes[win]; unsigned long val; val = WINCONx_ENWIN; @@ -564,11 +502,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) * So the request format is ARGB8888 then change it to XRGB8888. */ if (ctx->driver_data->has_limited_fmt && !win) { - if (win_data->pixel_format == DRM_FORMAT_ARGB8888) - win_data->pixel_format = DRM_FORMAT_XRGB8888; + if (plane->pixel_format == DRM_FORMAT_ARGB8888) + plane->pixel_format = DRM_FORMAT_XRGB8888; } - switch (win_data->pixel_format) { + switch (plane->pixel_format) { case DRM_FORMAT_C8: val |= WINCON0_BPPMODE_8BPP_PALETTE; val |= WINCONx_BURSTLEN_8WORD; @@ -604,7 +542,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) break; } - DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp); + DRM_DEBUG_KMS("bpp = %d\n", plane->bpp); /* * In case of exynos, setting dma-burst to 16Word causes permanent @@ -614,12 +552,30 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) * movement causes unstable DMA which results into iommu crash/tear. */ - if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) { + if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) { val &= ~WINCONx_BURSTLEN_MASK; val |= WINCONx_BURSTLEN_4WORD; } writel(val, ctx->regs + WINCON(win)); + + /* hardware window 0 doesn't support alpha channel. */ + if (win != 0) { + /* OSD alpha */ + val = VIDISD14C_ALPHA0_R(0xf) | + VIDISD14C_ALPHA0_G(0xf) | + VIDISD14C_ALPHA0_B(0xf) | + VIDISD14C_ALPHA1_R(0xf) | + VIDISD14C_ALPHA1_G(0xf) | + VIDISD14C_ALPHA1_B(0xf); + + writel(val, ctx->regs + VIDOSD_C(win)); + + val = VIDW_ALPHA_R(0xf) | VIDW_ALPHA_G(0xf) | + VIDW_ALPHA_G(0xf); + writel(val, ctx->regs + VIDWnALPHA0(win)); + writel(val, ctx->regs + VIDWnALPHA1(win)); + } } static void fimd_win_set_colkey(struct fimd_context *ctx, unsigned int win) @@ -642,7 +598,7 @@ static void fimd_win_set_colkey(struct fimd_context *ctx, unsigned int win) * @protect: 1 to protect (disable updates) */ static void fimd_shadow_protect_win(struct fimd_context *ctx, - int win, bool protect) + unsigned int win, bool protect) { u32 reg, bits, val; @@ -662,29 +618,25 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx, writel(val, ctx->regs + reg); } -static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos) +static void fimd_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) { struct fimd_context *ctx = crtc->ctx; - struct fimd_win_data *win_data; - int win = zpos; - unsigned long val, alpha, size; - unsigned int last_x; - unsigned int last_y; + struct exynos_drm_plane *plane; + dma_addr_t dma_addr; + unsigned long val, size, offset; + unsigned int last_x, last_y, buf_offsize, line_size; if (ctx->suspended) return; - if (win == DEFAULT_ZPOS) - win = ctx->default_win; - if (win < 0 || win >= WINDOWS_NR) return; - win_data = &ctx->win_data[win]; + plane = &ctx->planes[win]; /* If suspended, enable this on resume */ if (ctx->suspended) { - win_data->resume = true; + plane->resume = true; return; } @@ -701,38 +653,45 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos) /* protect windows */ fimd_shadow_protect_win(ctx, win, true); + + offset = plane->src_x * (plane->bpp >> 3); + offset += plane->src_y * plane->pitch; + /* buffer start address */ - val = (unsigned long)win_data->dma_addr; + dma_addr = plane->dma_addr[0] + offset; + val = (unsigned long)dma_addr; writel(val, ctx->regs + VIDWx_BUF_START(win, 0)); /* buffer end address */ - size = win_data->fb_pitch * win_data->ovl_height * (win_data->bpp >> 3); - val = (unsigned long)(win_data->dma_addr + size); + size = plane->pitch * plane->crtc_height; + val = (unsigned long)(dma_addr + size); writel(val, ctx->regs + VIDWx_BUF_END(win, 0)); DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", - (unsigned long)win_data->dma_addr, val, size); + (unsigned long)dma_addr, val, size); DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", - win_data->ovl_width, win_data->ovl_height); + plane->crtc_width, plane->crtc_height); /* buffer size */ - val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) | - VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size) | - VIDW_BUF_SIZE_OFFSET_E(win_data->buf_offsize) | - VIDW_BUF_SIZE_PAGEWIDTH_E(win_data->line_size); + buf_offsize = plane->pitch - (plane->crtc_width * (plane->bpp >> 3)); + line_size = plane->crtc_width * (plane->bpp >> 3); + val = VIDW_BUF_SIZE_OFFSET(buf_offsize) | + VIDW_BUF_SIZE_PAGEWIDTH(line_size) | + VIDW_BUF_SIZE_OFFSET_E(buf_offsize) | + VIDW_BUF_SIZE_PAGEWIDTH_E(line_size); writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0)); /* OSD position */ - val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) | - VIDOSDxA_TOPLEFT_Y(win_data->offset_y) | - VIDOSDxA_TOPLEFT_X_E(win_data->offset_x) | - VIDOSDxA_TOPLEFT_Y_E(win_data->offset_y); + val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) | + VIDOSDxA_TOPLEFT_Y(plane->crtc_y) | + VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) | + VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y); writel(val, ctx->regs + VIDOSD_A(win)); - last_x = win_data->offset_x + win_data->ovl_width; + last_x = plane->crtc_x + plane->crtc_width; if (last_x) last_x--; - last_y = win_data->offset_y + win_data->ovl_height; + last_y = plane->crtc_y + plane->crtc_height; if (last_y) last_y--; @@ -742,24 +701,14 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos) writel(val, ctx->regs + VIDOSD_B(win)); DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", - win_data->offset_x, win_data->offset_y, last_x, last_y); - - /* hardware window 0 doesn't support alpha channel. */ - if (win != 0) { - /* OSD alpha */ - alpha = VIDISD14C_ALPHA1_R(0xf) | - VIDISD14C_ALPHA1_G(0xf) | - VIDISD14C_ALPHA1_B(0xf); - - writel(alpha, ctx->regs + VIDOSD_C(win)); - } + plane->crtc_x, plane->crtc_y, last_x, last_y); /* OSD size */ if (win != 3 && win != 4) { u32 offset = VIDOSD_D(win); if (win == 0) offset = VIDOSD_C(win); - val = win_data->ovl_width * win_data->ovl_height; + val = plane->crtc_width * plane->crtc_height; writel(val, ctx->regs + offset); DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); @@ -779,29 +728,25 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos) /* Enable DMA channel and unprotect windows */ fimd_shadow_protect_win(ctx, win, false); - win_data->enabled = true; + plane->enabled = true; if (ctx->i80_if) atomic_set(&ctx->win_updated, 1); } -static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos) +static void fimd_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) { struct fimd_context *ctx = crtc->ctx; - struct fimd_win_data *win_data; - int win = zpos; - - if (win == DEFAULT_ZPOS) - win = ctx->default_win; + struct exynos_drm_plane *plane; if (win < 0 || win >= WINDOWS_NR) return; - win_data = &ctx->win_data[win]; + plane = &ctx->planes[win]; if (ctx->suspended) { /* do not resume this window*/ - win_data->resume = false; + plane->resume = false; return; } @@ -816,42 +761,42 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos) /* unprotect windows */ fimd_shadow_protect_win(ctx, win, false); - win_data->enabled = false; + plane->enabled = false; } static void fimd_window_suspend(struct fimd_context *ctx) { - struct fimd_win_data *win_data; + struct exynos_drm_plane *plane; int i; for (i = 0; i < WINDOWS_NR; i++) { - win_data = &ctx->win_data[i]; - win_data->resume = win_data->enabled; - if (win_data->enabled) + plane = &ctx->planes[i]; + plane->resume = plane->enabled; + if (plane->enabled) fimd_win_disable(ctx->crtc, i); } } static void fimd_window_resume(struct fimd_context *ctx) { - struct fimd_win_data *win_data; + struct exynos_drm_plane *plane; int i; for (i = 0; i < WINDOWS_NR; i++) { - win_data = &ctx->win_data[i]; - win_data->enabled = win_data->resume; - win_data->resume = false; + plane = &ctx->planes[i]; + plane->enabled = plane->resume; + plane->resume = false; } } static void fimd_apply(struct fimd_context *ctx) { - struct fimd_win_data *win_data; + struct exynos_drm_plane *plane; int i; for (i = 0; i < WINDOWS_NR; i++) { - win_data = &ctx->win_data[i]; - if (win_data->enabled) + plane = &ctx->planes[i]; + if (plane->enabled) fimd_win_commit(ctx->crtc, i); else fimd_win_disable(ctx->crtc, i); @@ -1008,7 +953,6 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = { .enable_vblank = fimd_enable_vblank, .disable_vblank = fimd_disable_vblank, .wait_for_vblank = fimd_wait_for_vblank, - .win_mode_set = fimd_win_mode_set, .win_commit = fimd_win_commit, .win_disable = fimd_win_disable, .te_handler = fimd_te_handler, @@ -1054,14 +998,29 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) struct fimd_context *ctx = dev_get_drvdata(dev); struct drm_device *drm_dev = data; struct exynos_drm_private *priv = drm_dev->dev_private; + struct exynos_drm_plane *exynos_plane; + enum drm_plane_type type; + unsigned int zpos; int ret; ctx->drm_dev = drm_dev; ctx->pipe = priv->pipe++; - ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, - EXYNOS_DISPLAY_TYPE_LCD, + for (zpos = 0; zpos < WINDOWS_NR; zpos++) { + type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY : + DRM_PLANE_TYPE_OVERLAY; + ret = exynos_plane_init(drm_dev, &ctx->planes[zpos], + 1 << ctx->pipe, type, zpos); + if (ret) + return ret; + } + + exynos_plane = &ctx->planes[ctx->default_win]; + ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, + ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD, &fimd_crtc_ops, ctx); + if (IS_ERR(ctx->crtc)) + return PTR_ERR(ctx->crtc); if (ctx->display) exynos_drm_create_enc_conn(drm_dev, ctx->display); @@ -1233,6 +1192,24 @@ static int fimd_remove(struct platform_device *pdev) return 0; } +void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable) +{ + struct fimd_context *ctx = crtc->ctx; + u32 val; + + /* + * Only Exynos 5250, 5260, 5410 and 542x requires enabling DP/MIE + * clock. On these SoCs the bootloader may enable it but any + * power domain off/on will reset it to disable state. + */ + if (ctx->driver_data != &exynos5_fimd_driver_data) + return; + + val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE; + writel(DP_MIE_CLK_DP_ENABLE, ctx->regs + DP_MIE_CLKCON); +} +EXPORT_SYMBOL_GPL(fimd_dp_clock_enable); + struct platform_driver fimd_driver = { .probe = fimd_probe, .remove = fimd_remove, diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.h b/drivers/gpu/drm/exynos/exynos_drm_fimd.h new file mode 100644 index 000000000000..b4fcaa568456 --- /dev/null +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef _EXYNOS_DRM_FIMD_H_ +#define _EXYNOS_DRM_FIMD_H_ + +extern void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable); + +#endif /* _EXYNOS_DRM_FIMD_H_ */ diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index d5ad17dfc24d..b7f1cbc46cc2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -476,6 +476,45 @@ err_clear: return ret; } +static int ipp_validate_mem_node(struct drm_device *drm_dev, + struct drm_exynos_ipp_mem_node *m_node, + struct drm_exynos_ipp_cmd_node *c_node) +{ + struct drm_exynos_ipp_config *ipp_cfg; + unsigned int num_plane; + unsigned long min_size, size; + unsigned int bpp; + int i; + + /* The property id should already be varified */ + ipp_cfg = &c_node->property.config[m_node->prop_id]; + num_plane = drm_format_num_planes(ipp_cfg->fmt); + + /** + * This is a rather simplified validation of a memory node. + * It basically verifies provided gem object handles + * and the buffer sizes with respect to current configuration. + * This is not the best that can be done + * but it seems more than enough + */ + for (i = 0; i < num_plane; ++i) { + if (!m_node->buf_info.handles[i]) { + DRM_ERROR("invalid handle for plane %d\n", i); + return -EINVAL; + } + bpp = drm_format_plane_cpp(ipp_cfg->fmt, i); + min_size = (ipp_cfg->sz.hsize * ipp_cfg->sz.vsize * bpp) >> 3; + size = exynos_drm_gem_get_size(drm_dev, + m_node->buf_info.handles[i], + c_node->filp); + if (min_size > size) { + DRM_ERROR("invalid size for plane %d\n", i); + return -EINVAL; + } + } + return 0; +} + static int ipp_put_mem_node(struct drm_device *drm_dev, struct drm_exynos_ipp_cmd_node *c_node, struct drm_exynos_ipp_mem_node *m_node) @@ -552,6 +591,11 @@ static struct drm_exynos_ipp_mem_node } mutex_lock(&c_node->mem_lock); + if (ipp_validate_mem_node(drm_dev, m_node, c_node)) { + ipp_put_mem_node(drm_dev, c_node, m_node); + mutex_unlock(&c_node->mem_lock); + return ERR_PTR(-EFAULT); + } list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]); mutex_unlock(&c_node->mem_lock); diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 8ad5b7294eb4..13ea3349363b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -92,7 +92,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_w, uint32_t src_h) { struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); unsigned int actual_w; unsigned int actual_h; @@ -111,13 +110,17 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, crtc_y = 0; } + /* set ratio */ + exynos_plane->h_ratio = (src_w << 16) / crtc_w; + exynos_plane->v_ratio = (src_h << 16) / crtc_h; + /* set drm framebuffer data. */ - exynos_plane->fb_x = src_x; - exynos_plane->fb_y = src_y; + exynos_plane->src_x = src_x; + exynos_plane->src_y = src_y; + exynos_plane->src_width = (actual_w * exynos_plane->h_ratio) >> 16; + exynos_plane->src_height = (actual_h * exynos_plane->v_ratio) >> 16; exynos_plane->fb_width = fb->width; exynos_plane->fb_height = fb->height; - exynos_plane->src_width = src_w; - exynos_plane->src_height = src_h; exynos_plane->bpp = fb->bits_per_pixel; exynos_plane->pitch = fb->pitches[0]; exynos_plane->pixel_format = fb->pixel_format; @@ -139,9 +142,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, exynos_plane->crtc_width, exynos_plane->crtc_height); plane->crtc = crtc; - - if (exynos_crtc->ops->win_mode_set) - exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane); } int @@ -182,39 +182,14 @@ static int exynos_disable_plane(struct drm_plane *plane) return 0; } -static void exynos_plane_destroy(struct drm_plane *plane) -{ - struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); - - exynos_disable_plane(plane); - drm_plane_cleanup(plane); - kfree(exynos_plane); -} - -static int exynos_plane_set_property(struct drm_plane *plane, - struct drm_property *property, - uint64_t val) -{ - struct drm_device *dev = plane->dev; - struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); - struct exynos_drm_private *dev_priv = dev->dev_private; - - if (property == dev_priv->plane_zpos_property) { - exynos_plane->zpos = val; - return 0; - } - - return -EINVAL; -} - static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = exynos_update_plane, .disable_plane = exynos_disable_plane, - .destroy = exynos_plane_destroy, - .set_property = exynos_plane_set_property, + .destroy = drm_plane_cleanup, }; -static void exynos_plane_attach_zpos_property(struct drm_plane *plane) +static void exynos_plane_attach_zpos_property(struct drm_plane *plane, + unsigned int zpos) { struct drm_device *dev = plane->dev; struct exynos_drm_private *dev_priv = dev->dev_private; @@ -222,41 +197,36 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane) prop = dev_priv->plane_zpos_property; if (!prop) { - prop = drm_property_create_range(dev, 0, "zpos", 0, - MAX_PLANE - 1); + prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, + "zpos", 0, MAX_PLANE - 1); if (!prop) return; dev_priv->plane_zpos_property = prop; } - drm_object_attach_property(&plane->base, prop, 0); + drm_object_attach_property(&plane->base, prop, zpos); } -struct drm_plane *exynos_plane_init(struct drm_device *dev, - unsigned long possible_crtcs, - enum drm_plane_type type) +int exynos_plane_init(struct drm_device *dev, + struct exynos_drm_plane *exynos_plane, + unsigned long possible_crtcs, enum drm_plane_type type, + unsigned int zpos) { - struct exynos_drm_plane *exynos_plane; int err; - exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL); - if (!exynos_plane) - return ERR_PTR(-ENOMEM); - err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs, &exynos_plane_funcs, formats, ARRAY_SIZE(formats), type); if (err) { DRM_ERROR("failed to initialize plane\n"); - kfree(exynos_plane); - return ERR_PTR(err); + return err; } - if (type == DRM_PLANE_TYPE_PRIMARY) - exynos_plane->zpos = DEFAULT_ZPOS; - else - exynos_plane_attach_zpos_property(&exynos_plane->base); + exynos_plane->zpos = zpos; - return &exynos_plane->base; + if (type == DRM_PLANE_TYPE_OVERLAY) + exynos_plane_attach_zpos_property(&exynos_plane->base, zpos); + + return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h index 9d3c374e7b3e..f360590d1412 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h @@ -20,6 +20,7 @@ int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h); -struct drm_plane *exynos_plane_init(struct drm_device *dev, - unsigned long possible_crtcs, - enum drm_plane_type type); +int exynos_plane_init(struct drm_device *dev, + struct exynos_drm_plane *exynos_plane, + unsigned long possible_crtcs, enum drm_plane_type type, + unsigned int zpos); diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index b886972b5888..27e84ec21694 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -23,6 +23,7 @@ #include "exynos_drm_drv.h" #include "exynos_drm_crtc.h" +#include "exynos_drm_plane.h" #include "exynos_drm_encoder.h" #include "exynos_drm_vidi.h" @@ -32,20 +33,6 @@ #define ctx_from_connector(c) container_of(c, struct vidi_context, \ connector) -struct vidi_win_data { - unsigned int offset_x; - unsigned int offset_y; - unsigned int ovl_width; - unsigned int ovl_height; - unsigned int fb_width; - unsigned int fb_height; - unsigned int bpp; - dma_addr_t dma_addr; - unsigned int buf_offsize; - unsigned int line_size; /* bytes */ - bool enabled; -}; - struct vidi_context { struct exynos_drm_display display; struct platform_device *pdev; @@ -53,7 +40,7 @@ struct vidi_context { struct exynos_drm_crtc *crtc; struct drm_encoder *encoder; struct drm_connector connector; - struct vidi_win_data win_data[WINDOWS_NR]; + struct exynos_drm_plane planes[WINDOWS_NR]; struct edid *raw_edid; unsigned int clkdiv; unsigned int default_win; @@ -97,19 +84,6 @@ static const char fake_edid_info[] = { 0x00, 0x00, 0x00, 0x06 }; -static void vidi_apply(struct vidi_context *ctx) -{ - struct exynos_drm_crtc_ops *crtc_ops = ctx->crtc->ops; - struct vidi_win_data *win_data; - int i; - - for (i = 0; i < WINDOWS_NR; i++) { - win_data = &ctx->win_data[i]; - if (win_data->enabled && (crtc_ops && crtc_ops->win_commit)) - crtc_ops->win_commit(ctx->crtc, i); - } -} - static int vidi_enable_vblank(struct exynos_drm_crtc *crtc) { struct vidi_context *ctx = crtc->ctx; @@ -143,104 +117,46 @@ static void vidi_disable_vblank(struct exynos_drm_crtc *crtc) ctx->vblank_on = false; } -static void vidi_win_mode_set(struct exynos_drm_crtc *crtc, - struct exynos_drm_plane *plane) -{ - struct vidi_context *ctx = crtc->ctx; - struct vidi_win_data *win_data; - int win; - unsigned long offset; - - if (!plane) { - DRM_ERROR("plane is NULL\n"); - return; - } - - win = plane->zpos; - if (win == DEFAULT_ZPOS) - win = ctx->default_win; - - if (win < 0 || win >= WINDOWS_NR) - return; - - offset = plane->fb_x * (plane->bpp >> 3); - offset += plane->fb_y * plane->pitch; - - DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch); - - win_data = &ctx->win_data[win]; - - win_data->offset_x = plane->crtc_x; - win_data->offset_y = plane->crtc_y; - win_data->ovl_width = plane->crtc_width; - win_data->ovl_height = plane->crtc_height; - win_data->fb_width = plane->fb_width; - win_data->fb_height = plane->fb_height; - win_data->dma_addr = plane->dma_addr[0] + offset; - win_data->bpp = plane->bpp; - win_data->buf_offsize = (plane->fb_width - plane->crtc_width) * - (plane->bpp >> 3); - win_data->line_size = plane->crtc_width * (plane->bpp >> 3); - - /* - * some parts of win_data should be transferred to user side - * through specific ioctl. - */ - - DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n", - win_data->offset_x, win_data->offset_y); - DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", - win_data->ovl_width, win_data->ovl_height); - DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr); - DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", - plane->fb_width, plane->crtc_width); -} - -static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos) +static void vidi_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) { struct vidi_context *ctx = crtc->ctx; - struct vidi_win_data *win_data; - int win = zpos; + struct exynos_drm_plane *plane; if (ctx->suspended) return; - if (win == DEFAULT_ZPOS) - win = ctx->default_win; - if (win < 0 || win >= WINDOWS_NR) return; - win_data = &ctx->win_data[win]; + plane = &ctx->planes[win]; - win_data->enabled = true; + plane->enabled = true; - DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr); + DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr); if (ctx->vblank_on) schedule_work(&ctx->work); } -static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos) +static void vidi_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) { struct vidi_context *ctx = crtc->ctx; - struct vidi_win_data *win_data; - int win = zpos; - - if (win == DEFAULT_ZPOS) - win = ctx->default_win; + struct exynos_drm_plane *plane; if (win < 0 || win >= WINDOWS_NR) return; - win_data = &ctx->win_data[win]; - win_data->enabled = false; + plane = &ctx->planes[win]; + plane->enabled = false; /* TODO. */ } static int vidi_power_on(struct vidi_context *ctx, bool enable) { + struct exynos_drm_plane *plane; + int i; + DRM_DEBUG_KMS("%s\n", __FILE__); if (enable != false && enable != true) @@ -253,7 +169,11 @@ static int vidi_power_on(struct vidi_context *ctx, bool enable) if (test_and_clear_bit(0, &ctx->irq_flags)) vidi_enable_vblank(ctx->crtc); - vidi_apply(ctx); + for (i = 0; i < WINDOWS_NR; i++) { + plane = &ctx->planes[i]; + if (plane->enabled) + vidi_win_commit(ctx->crtc, i); + } } else { ctx->suspended = true; } @@ -301,7 +221,6 @@ static struct exynos_drm_crtc_ops vidi_crtc_ops = { .dpms = vidi_dpms, .enable_vblank = vidi_enable_vblank, .disable_vblank = vidi_disable_vblank, - .win_mode_set = vidi_win_mode_set, .win_commit = vidi_win_commit, .win_disable = vidi_win_disable, }; @@ -543,12 +462,25 @@ static int vidi_bind(struct device *dev, struct device *master, void *data) { struct vidi_context *ctx = dev_get_drvdata(dev); struct drm_device *drm_dev = data; + struct exynos_drm_plane *exynos_plane; + enum drm_plane_type type; + unsigned int zpos; int ret; vidi_ctx_initialize(ctx, drm_dev); - ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, - EXYNOS_DISPLAY_TYPE_VIDI, + for (zpos = 0; zpos < WINDOWS_NR; zpos++) { + type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY : + DRM_PLANE_TYPE_OVERLAY; + ret = exynos_plane_init(drm_dev, &ctx->planes[zpos], + 1 << ctx->pipe, type, zpos); + if (ret) + return ret; + } + + exynos_plane = &ctx->planes[ctx->default_win]; + ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, + ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI, &vidi_crtc_ops, ctx); if (IS_ERR(ctx->crtc)) { DRM_ERROR("failed to create crtc.\n"); diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 229b3613c60b..722cbf32192a 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2007,7 +2007,7 @@ static void hdmi_mode_set(struct exynos_drm_display *display, DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n", m->hdisplay, m->vdisplay, m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ? - "INTERLACED" : "PROGERESSIVE"); + "INTERLACED" : "PROGRESSIVE"); /* preserve mode information for later use. */ drm_mode_copy(&hdata->current_mode, mode); diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 2e3bc57ea50e..fbec750574e6 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -37,35 +37,13 @@ #include "exynos_drm_drv.h" #include "exynos_drm_crtc.h" +#include "exynos_drm_plane.h" #include "exynos_drm_iommu.h" #include "exynos_mixer.h" #define MIXER_WIN_NR 3 #define MIXER_DEFAULT_WIN 0 -struct hdmi_win_data { - dma_addr_t dma_addr; - dma_addr_t chroma_dma_addr; - uint32_t pixel_format; - unsigned int bpp; - unsigned int crtc_x; - unsigned int crtc_y; - unsigned int crtc_width; - unsigned int crtc_height; - unsigned int fb_x; - unsigned int fb_y; - unsigned int fb_width; - unsigned int fb_pitch; - unsigned int fb_height; - unsigned int src_width; - unsigned int src_height; - unsigned int mode_width; - unsigned int mode_height; - unsigned int scan_flags; - bool enabled; - bool resume; -}; - struct mixer_resources { int irq; void __iomem *mixer_regs; @@ -90,6 +68,7 @@ struct mixer_context { struct device *dev; struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; + struct exynos_drm_plane planes[MIXER_WIN_NR]; int pipe; bool interlace; bool powered; @@ -99,7 +78,6 @@ struct mixer_context { struct mutex mixer_mutex; struct mixer_resources mixer_res; - struct hdmi_win_data win_data[MIXER_WIN_NR]; enum mixer_version_id mxr_ver; wait_queue_head_t wait_vsync_queue; atomic_t wait_vsync_event; @@ -289,7 +267,7 @@ static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height) /* choosing between interlace and progressive mode */ val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE : - MXR_CFG_SCAN_PROGRASSIVE); + MXR_CFG_SCAN_PROGRESSIVE); if (ctx->mxr_ver != MXR_VER_128_0_0_184) { /* choosing between proper HD and SD mode */ @@ -403,17 +381,16 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) { struct mixer_resources *res = &ctx->mixer_res; unsigned long flags; - struct hdmi_win_data *win_data; - unsigned int x_ratio, y_ratio; + struct exynos_drm_plane *plane; unsigned int buf_num = 1; dma_addr_t luma_addr[2], chroma_addr[2]; bool tiled_mode = false; bool crcb_mode = false; u32 val; - win_data = &ctx->win_data[win]; + plane = &ctx->planes[win]; - switch (win_data->pixel_format) { + switch (plane->pixel_format) { case DRM_FORMAT_NV12: crcb_mode = false; buf_num = 2; @@ -421,35 +398,31 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) /* TODO: single buffer format NV12, NV21 */ default: /* ignore pixel format at disable time */ - if (!win_data->dma_addr) + if (!plane->dma_addr[0]) break; DRM_ERROR("pixel format for vp is wrong [%d].\n", - win_data->pixel_format); + plane->pixel_format); return; } - /* scaling feature: (src << 16) / dst */ - x_ratio = (win_data->src_width << 16) / win_data->crtc_width; - y_ratio = (win_data->src_height << 16) / win_data->crtc_height; - if (buf_num == 2) { - luma_addr[0] = win_data->dma_addr; - chroma_addr[0] = win_data->chroma_dma_addr; + luma_addr[0] = plane->dma_addr[0]; + chroma_addr[0] = plane->dma_addr[1]; } else { - luma_addr[0] = win_data->dma_addr; - chroma_addr[0] = win_data->dma_addr - + (win_data->fb_pitch * win_data->fb_height); + luma_addr[0] = plane->dma_addr[0]; + chroma_addr[0] = plane->dma_addr[0] + + (plane->pitch * plane->fb_height); } - if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) { + if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) { ctx->interlace = true; if (tiled_mode) { luma_addr[1] = luma_addr[0] + 0x40; chroma_addr[1] = chroma_addr[0] + 0x40; } else { - luma_addr[1] = luma_addr[0] + win_data->fb_pitch; - chroma_addr[1] = chroma_addr[0] + win_data->fb_pitch; + luma_addr[1] = luma_addr[0] + plane->pitch; + chroma_addr[1] = chroma_addr[0] + plane->pitch; } } else { ctx->interlace = false; @@ -470,30 +443,30 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); /* setting size of input image */ - vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_pitch) | - VP_IMG_VSIZE(win_data->fb_height)); + vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) | + VP_IMG_VSIZE(plane->fb_height)); /* chroma height has to reduced by 2 to avoid chroma distorions */ - vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_pitch) | - VP_IMG_VSIZE(win_data->fb_height / 2)); + vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) | + VP_IMG_VSIZE(plane->fb_height / 2)); - vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width); - vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height); + vp_reg_write(res, VP_SRC_WIDTH, plane->src_width); + vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height); vp_reg_write(res, VP_SRC_H_POSITION, - VP_SRC_H_POSITION_VAL(win_data->fb_x)); - vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y); + VP_SRC_H_POSITION_VAL(plane->src_x)); + vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y); - vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width); - vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x); + vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width); + vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x); if (ctx->interlace) { - vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2); - vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2); + vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2); + vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2); } else { - vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height); - vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y); + vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height); + vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y); } - vp_reg_write(res, VP_H_RATIO, x_ratio); - vp_reg_write(res, VP_V_RATIO, y_ratio); + vp_reg_write(res, VP_H_RATIO, plane->h_ratio); + vp_reg_write(res, VP_V_RATIO, plane->v_ratio); vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE); @@ -503,8 +476,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]); vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]); - mixer_cfg_scan(ctx, win_data->mode_height); - mixer_cfg_rgb_fmt(ctx, win_data->mode_height); + mixer_cfg_scan(ctx, plane->mode_height); + mixer_cfg_rgb_fmt(ctx, plane->mode_height); mixer_cfg_layer(ctx, win, true); mixer_run(ctx); @@ -521,25 +494,49 @@ static void mixer_layer_update(struct mixer_context *ctx) mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); } +static int mixer_setup_scale(const struct exynos_drm_plane *plane, + unsigned int *x_ratio, unsigned int *y_ratio) +{ + if (plane->crtc_width != plane->src_width) { + if (plane->crtc_width == 2 * plane->src_width) + *x_ratio = 1; + else + goto fail; + } + + if (plane->crtc_height != plane->src_height) { + if (plane->crtc_height == 2 * plane->src_height) + *y_ratio = 1; + else + goto fail; + } + + return 0; + +fail: + DRM_DEBUG_KMS("only 2x width/height scaling of plane supported\n"); + return -ENOTSUPP; +} + static void mixer_graph_buffer(struct mixer_context *ctx, int win) { struct mixer_resources *res = &ctx->mixer_res; unsigned long flags; - struct hdmi_win_data *win_data; - unsigned int x_ratio, y_ratio; + struct exynos_drm_plane *plane; + unsigned int x_ratio = 0, y_ratio = 0; unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; dma_addr_t dma_addr; unsigned int fmt; u32 val; - win_data = &ctx->win_data[win]; + plane = &ctx->planes[win]; #define RGB565 4 #define ARGB1555 5 #define ARGB4444 6 #define ARGB8888 7 - switch (win_data->bpp) { + switch (plane->bpp) { case 16: fmt = ARGB4444; break; @@ -550,21 +547,21 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win) fmt = ARGB8888; } - /* 2x scaling feature */ - x_ratio = 0; - y_ratio = 0; + /* check if mixer supports requested scaling setup */ + if (mixer_setup_scale(plane, &x_ratio, &y_ratio)) + return; - dst_x_offset = win_data->crtc_x; - dst_y_offset = win_data->crtc_y; + dst_x_offset = plane->crtc_x; + dst_y_offset = plane->crtc_y; /* converting dma address base and source offset */ - dma_addr = win_data->dma_addr - + (win_data->fb_x * win_data->bpp >> 3) - + (win_data->fb_y * win_data->fb_pitch); + dma_addr = plane->dma_addr[0] + + (plane->src_x * plane->bpp >> 3) + + (plane->src_y * plane->pitch); src_x_offset = 0; src_y_offset = 0; - if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) + if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) ctx->interlace = true; else ctx->interlace = false; @@ -578,18 +575,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win) /* setup geometry */ mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), - win_data->fb_pitch / (win_data->bpp >> 3)); + plane->pitch / (plane->bpp >> 3)); /* setup display size */ if (ctx->mxr_ver == MXR_VER_128_0_0_184 && win == MIXER_DEFAULT_WIN) { - val = MXR_MXR_RES_HEIGHT(win_data->mode_height); - val |= MXR_MXR_RES_WIDTH(win_data->mode_width); + val = MXR_MXR_RES_HEIGHT(plane->mode_height); + val |= MXR_MXR_RES_WIDTH(plane->mode_width); mixer_reg_write(res, MXR_RESOLUTION, val); } - val = MXR_GRP_WH_WIDTH(win_data->crtc_width); - val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height); + val = MXR_GRP_WH_WIDTH(plane->src_width); + val |= MXR_GRP_WH_HEIGHT(plane->src_height); val |= MXR_GRP_WH_H_SCALE(x_ratio); val |= MXR_GRP_WH_V_SCALE(y_ratio); mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); @@ -607,8 +604,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win) /* set buffer address to mixer */ mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr); - mixer_cfg_scan(ctx, win_data->mode_height); - mixer_cfg_rgb_fmt(ctx, win_data->mode_height); + mixer_cfg_scan(ctx, plane->mode_height); + mixer_cfg_rgb_fmt(ctx, plane->mode_height); mixer_cfg_layer(ctx, win, true); /* layer update mandatory for mixer 16.0.33.0 */ @@ -920,63 +917,9 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc) mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); } -static void mixer_win_mode_set(struct exynos_drm_crtc *crtc, - struct exynos_drm_plane *plane) -{ - struct mixer_context *mixer_ctx = crtc->ctx; - struct hdmi_win_data *win_data; - int win; - - if (!plane) { - DRM_ERROR("plane is NULL\n"); - return; - } - - DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n", - plane->fb_width, plane->fb_height, - plane->fb_x, plane->fb_y, - plane->crtc_width, plane->crtc_height, - plane->crtc_x, plane->crtc_y); - - win = plane->zpos; - if (win == DEFAULT_ZPOS) - win = MIXER_DEFAULT_WIN; - - if (win < 0 || win >= MIXER_WIN_NR) { - DRM_ERROR("mixer window[%d] is wrong\n", win); - return; - } - - win_data = &mixer_ctx->win_data[win]; - - win_data->dma_addr = plane->dma_addr[0]; - win_data->chroma_dma_addr = plane->dma_addr[1]; - win_data->pixel_format = plane->pixel_format; - win_data->bpp = plane->bpp; - - win_data->crtc_x = plane->crtc_x; - win_data->crtc_y = plane->crtc_y; - win_data->crtc_width = plane->crtc_width; - win_data->crtc_height = plane->crtc_height; - - win_data->fb_x = plane->fb_x; - win_data->fb_y = plane->fb_y; - win_data->fb_width = plane->fb_width; - win_data->fb_height = plane->fb_height; - win_data->fb_pitch = plane->pitch; - win_data->src_width = plane->src_width; - win_data->src_height = plane->src_height; - - win_data->mode_width = plane->mode_width; - win_data->mode_height = plane->mode_height; - - win_data->scan_flags = plane->scan_flag; -} - -static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos) +static void mixer_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) { struct mixer_context *mixer_ctx = crtc->ctx; - int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; DRM_DEBUG_KMS("win: %d\n", win); @@ -992,14 +935,13 @@ static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos) else mixer_graph_buffer(mixer_ctx, win); - mixer_ctx->win_data[win].enabled = true; + mixer_ctx->planes[win].enabled = true; } -static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos) +static void mixer_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) { struct mixer_context *mixer_ctx = crtc->ctx; struct mixer_resources *res = &mixer_ctx->mixer_res; - int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; unsigned long flags; DRM_DEBUG_KMS("win: %d\n", win); @@ -1007,7 +949,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos) mutex_lock(&mixer_ctx->mixer_mutex); if (!mixer_ctx->powered) { mutex_unlock(&mixer_ctx->mixer_mutex); - mixer_ctx->win_data[win].resume = false; + mixer_ctx->planes[win].resume = false; return; } mutex_unlock(&mixer_ctx->mixer_mutex); @@ -1020,7 +962,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos) mixer_vsync_set_update(mixer_ctx, true); spin_unlock_irqrestore(&res->reg_slock, flags); - mixer_ctx->win_data[win].enabled = false; + mixer_ctx->planes[win].enabled = false; } static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) @@ -1057,12 +999,12 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) static void mixer_window_suspend(struct mixer_context *ctx) { - struct hdmi_win_data *win_data; + struct exynos_drm_plane *plane; int i; for (i = 0; i < MIXER_WIN_NR; i++) { - win_data = &ctx->win_data[i]; - win_data->resume = win_data->enabled; + plane = &ctx->planes[i]; + plane->resume = plane->enabled; mixer_win_disable(ctx->crtc, i); } mixer_wait_for_vblank(ctx->crtc); @@ -1070,14 +1012,14 @@ static void mixer_window_suspend(struct mixer_context *ctx) static void mixer_window_resume(struct mixer_context *ctx) { - struct hdmi_win_data *win_data; + struct exynos_drm_plane *plane; int i; for (i = 0; i < MIXER_WIN_NR; i++) { - win_data = &ctx->win_data[i]; - win_data->enabled = win_data->resume; - win_data->resume = false; - if (win_data->enabled) + plane = &ctx->planes[i]; + plane->enabled = plane->resume; + plane->resume = false; + if (plane->enabled) mixer_win_commit(ctx->crtc, i); } } @@ -1189,7 +1131,6 @@ static struct exynos_drm_crtc_ops mixer_crtc_ops = { .enable_vblank = mixer_enable_vblank, .disable_vblank = mixer_disable_vblank, .wait_for_vblank = mixer_wait_for_vblank, - .win_mode_set = mixer_win_mode_set, .win_commit = mixer_win_commit, .win_disable = mixer_win_disable, }; @@ -1253,15 +1194,28 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) { struct mixer_context *ctx = dev_get_drvdata(dev); struct drm_device *drm_dev = data; + struct exynos_drm_plane *exynos_plane; + enum drm_plane_type type; + unsigned int zpos; int ret; ret = mixer_initialize(ctx, drm_dev); if (ret) return ret; - ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, - EXYNOS_DISPLAY_TYPE_HDMI, - &mixer_crtc_ops, ctx); + for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) { + type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY : + DRM_PLANE_TYPE_OVERLAY; + ret = exynos_plane_init(drm_dev, &ctx->planes[zpos], + 1 << ctx->pipe, type, zpos); + if (ret) + return ret; + } + + exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN]; + ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, + ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI, + &mixer_crtc_ops, ctx); if (IS_ERR(ctx->crtc)) { mixer_ctx_remove(ctx); ret = PTR_ERR(ctx->crtc); diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h index 5f32e1a29411..ac60260c2389 100644 --- a/drivers/gpu/drm/exynos/regs-mixer.h +++ b/drivers/gpu/drm/exynos/regs-mixer.h @@ -101,7 +101,7 @@ #define MXR_CFG_GRP0_ENABLE (1 << 4) #define MXR_CFG_VP_ENABLE (1 << 3) #define MXR_CFG_SCAN_INTERLACE (0 << 2) -#define MXR_CFG_SCAN_PROGRASSIVE (1 << 2) +#define MXR_CFG_SCAN_PROGRESSIVE (1 << 2) #define MXR_CFG_SCAN_NTSC (0 << 1) #define MXR_CFG_SCAN_PAL (1 << 1) #define MXR_CFG_SCAN_SD (0 << 0) diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig index 33cdddf26684..2b81a417cf29 100644 --- a/drivers/gpu/drm/imx/Kconfig +++ b/drivers/gpu/drm/imx/Kconfig @@ -36,6 +36,7 @@ config DRM_IMX_TVE config DRM_IMX_LDB tristate "Support for LVDS displays" depends on DRM_IMX && MFD_SYSCON + select DRM_PANEL help Choose this to enable the internal LVDS Display Bridge (LDB) found on i.MX53 and i.MX6 processors. diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index 87fe8ed92ebe..1834ac8998cc 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c @@ -123,7 +123,7 @@ static void dw_hdmi_imx_encoder_commit(struct drm_encoder *encoder) static void dw_hdmi_imx_encoder_prepare(struct drm_encoder *encoder) { - imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24); + imx_drm_set_bus_format(encoder, MEDIA_BUS_FMT_RGB888_1X24); } static struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = { diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index a002f53aab0e..74f505b0dd02 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -103,8 +103,8 @@ static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc) return NULL; } -int imx_drm_panel_format_pins(struct drm_encoder *encoder, - u32 interface_pix_fmt, int hsync_pin, int vsync_pin) +int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, u32 bus_format, + int hsync_pin, int vsync_pin) { struct imx_drm_crtc_helper_funcs *helper; struct imx_drm_crtc *imx_crtc; @@ -116,16 +116,16 @@ int imx_drm_panel_format_pins(struct drm_encoder *encoder, helper = &imx_crtc->imx_drm_helper_funcs; if (helper->set_interface_pix_fmt) return helper->set_interface_pix_fmt(encoder->crtc, - interface_pix_fmt, hsync_pin, vsync_pin); + bus_format, hsync_pin, vsync_pin); return 0; } -EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins); +EXPORT_SYMBOL_GPL(imx_drm_set_bus_format_pins); -int imx_drm_panel_format(struct drm_encoder *encoder, u32 interface_pix_fmt) +int imx_drm_set_bus_format(struct drm_encoder *encoder, u32 bus_format) { - return imx_drm_panel_format_pins(encoder, interface_pix_fmt, 2, 3); + return imx_drm_set_bus_format_pins(encoder, bus_format, 2, 3); } -EXPORT_SYMBOL_GPL(imx_drm_panel_format); +EXPORT_SYMBOL_GPL(imx_drm_set_bus_format); int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc) { @@ -431,15 +431,6 @@ int imx_drm_encoder_parse_of(struct drm_device *drm, } EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of); -static struct device_node *imx_drm_of_get_next_endpoint( - const struct device_node *parent, struct device_node *prev) -{ - struct device_node *node = of_graph_get_next_endpoint(parent, prev); - - of_node_put(prev); - return node; -} - /* * @node: device tree node containing encoder input ports * @encoder: drm_encoder @@ -448,7 +439,7 @@ int imx_drm_encoder_get_mux_id(struct device_node *node, struct drm_encoder *encoder) { struct imx_drm_crtc *imx_crtc = imx_drm_find_crtc(encoder->crtc); - struct device_node *ep = NULL; + struct device_node *ep; struct of_endpoint endpoint; struct device_node *port; int ret; @@ -456,18 +447,15 @@ int imx_drm_encoder_get_mux_id(struct device_node *node, if (!node || !imx_crtc) return -EINVAL; - do { - ep = imx_drm_of_get_next_endpoint(node, ep); - if (!ep) - break; - + for_each_endpoint_of_node(node, ep) { port = of_graph_get_remote_port(ep); of_node_put(port); if (port == imx_crtc->crtc->port) { ret = of_graph_parse_endpoint(ep, &endpoint); + of_node_put(ep); return ret ? ret : endpoint.port; } - } while (ep); + } return -EINVAL; } diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h index 3c559ccd6af0..28e776d8d9d2 100644 --- a/drivers/gpu/drm/imx/imx-drm.h +++ b/drivers/gpu/drm/imx/imx-drm.h @@ -18,7 +18,7 @@ struct imx_drm_crtc_helper_funcs { int (*enable_vblank)(struct drm_crtc *crtc); void (*disable_vblank)(struct drm_crtc *crtc); int (*set_interface_pix_fmt)(struct drm_crtc *crtc, - u32 pix_fmt, int hsync_pin, int vsync_pin); + u32 bus_format, int hsync_pin, int vsync_pin); const struct drm_crtc_helper_funcs *crtc_helper_funcs; const struct drm_crtc_funcs *crtc_funcs; }; @@ -40,10 +40,10 @@ void imx_drm_mode_config_init(struct drm_device *drm); struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb); -int imx_drm_panel_format_pins(struct drm_encoder *encoder, - u32 interface_pix_fmt, int hsync_pin, int vsync_pin); -int imx_drm_panel_format(struct drm_encoder *encoder, - u32 interface_pix_fmt); +int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, + u32 bus_format, int hsync_pin, int vsync_pin); +int imx_drm_set_bus_format(struct drm_encoder *encoder, + u32 bus_format); int imx_drm_encoder_get_mux_id(struct device_node *node, struct drm_encoder *encoder); diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 2d6dc94e1e64..abacc8f67469 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -19,10 +19,11 @@ #include <drm/drmP.h> #include <drm/drm_fb_helper.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_panel.h> #include <linux/mfd/syscon.h> #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> -#include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_graph.h> #include <video/of_videomode.h> #include <linux/regmap.h> #include <linux/videodev2.h> @@ -55,12 +56,14 @@ struct imx_ldb_channel { struct imx_ldb *ldb; struct drm_connector connector; struct drm_encoder encoder; + struct drm_panel *panel; struct device_node *child; int chno; void *edid; int edid_len; struct drm_display_mode mode; int mode_valid; + int bus_format; }; struct bus_mux { @@ -75,6 +78,7 @@ struct imx_ldb { struct imx_ldb_channel channel[2]; struct clk *clk[2]; /* our own clock */ struct clk *clk_sel[4]; /* parent of display clock */ + struct clk *clk_parent[4]; /* original parent of clk_sel */ struct clk *clk_pll[2]; /* upstream clock we can adjust */ u32 ldb_ctrl; const struct bus_mux *lvds_mux; @@ -91,6 +95,17 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector) struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector); int num_modes = 0; + if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs && + imx_ldb_ch->panel->funcs->get_modes) { + struct drm_display_info *di = &connector->display_info; + + num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel); + if (!imx_ldb_ch->bus_format && di->num_bus_formats) + imx_ldb_ch->bus_format = di->bus_formats[0]; + if (num_modes > 0) + return num_modes; + } + if (imx_ldb_ch->edid) { drm_mode_connector_update_edid_property(connector, imx_ldb_ch->edid); @@ -163,24 +178,36 @@ static void imx_ldb_encoder_prepare(struct drm_encoder *encoder) { struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); struct imx_ldb *ldb = imx_ldb_ch->ldb; - u32 pixel_fmt; + int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; + u32 bus_format; - switch (imx_ldb_ch->chno) { - case 0: - pixel_fmt = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH0_24) ? - V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666; + switch (imx_ldb_ch->bus_format) { + default: + dev_warn(ldb->dev, + "could not determine data mapping, default to 18-bit \"spwg\"\n"); + /* fallthrough */ + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + bus_format = MEDIA_BUS_FMT_RGB666_1X18; break; - case 1: - pixel_fmt = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH1_24) ? - V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666; + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + bus_format = MEDIA_BUS_FMT_RGB888_1X24; + if (imx_ldb_ch->chno == 0 || dual) + ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24; + if (imx_ldb_ch->chno == 1 || dual) + ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: + bus_format = MEDIA_BUS_FMT_RGB888_1X24; + if (imx_ldb_ch->chno == 0 || dual) + ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 | + LDB_BIT_MAP_CH0_JEIDA; + if (imx_ldb_ch->chno == 1 || dual) + ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | + LDB_BIT_MAP_CH1_JEIDA; break; - default: - dev_err(ldb->dev, "unable to config di%d panel format\n", - imx_ldb_ch->chno); - pixel_fmt = V4L2_PIX_FMT_RGB24; } - imx_drm_panel_format(encoder, pixel_fmt); + imx_drm_set_bus_format(encoder, bus_format); } static void imx_ldb_encoder_commit(struct drm_encoder *encoder) @@ -190,6 +217,8 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder) int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder); + drm_panel_prepare(imx_ldb_ch->panel); + if (dual) { clk_prepare_enable(ldb->clk[0]); clk_prepare_enable(ldb->clk[1]); @@ -223,6 +252,8 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder) } regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl); + + drm_panel_enable(imx_ldb_ch->panel); } static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, @@ -274,6 +305,7 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder) { struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); struct imx_ldb *ldb = imx_ldb_ch->ldb; + int mux, ret; /* * imx_ldb_encoder_disable is called by @@ -287,6 +319,8 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder) (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0) return; + drm_panel_disable(imx_ldb_ch->panel); + if (imx_ldb_ch == &ldb->channel[0]) ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; else if (imx_ldb_ch == &ldb->channel[1]) @@ -298,6 +332,30 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder) clk_disable_unprepare(ldb->clk[0]); clk_disable_unprepare(ldb->clk[1]); } + + if (ldb->lvds_mux) { + const struct bus_mux *lvds_mux = NULL; + + if (imx_ldb_ch == &ldb->channel[0]) + lvds_mux = &ldb->lvds_mux[0]; + else if (imx_ldb_ch == &ldb->channel[1]) + lvds_mux = &ldb->lvds_mux[1]; + + regmap_read(ldb->regmap, lvds_mux->reg, &mux); + mux &= lvds_mux->mask; + mux >>= lvds_mux->shift; + } else { + mux = (imx_ldb_ch == &ldb->channel[0]) ? 0 : 1; + } + + /* set display clock mux back to original input clock */ + ret = clk_set_parent(ldb->clk_sel[mux], ldb->clk_parent[mux]); + if (ret) + dev_err(ldb->dev, + "unable to set di%d parent clock to original parent\n", + mux); + + drm_panel_unprepare(imx_ldb_ch->panel); } static struct drm_connector_funcs imx_ldb_connector_funcs = { @@ -371,6 +429,9 @@ static int imx_ldb_register(struct drm_device *drm, drm_connector_init(drm, &imx_ldb_ch->connector, &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS); + if (imx_ldb_ch->panel) + drm_panel_attach(imx_ldb_ch->panel, &imx_ldb_ch->connector); + drm_mode_connector_attach_encoder(&imx_ldb_ch->connector, &imx_ldb_ch->encoder); @@ -382,25 +443,39 @@ enum { LVDS_BIT_MAP_JEIDA }; -static const char * const imx_ldb_bit_mappings[] = { - [LVDS_BIT_MAP_SPWG] = "spwg", - [LVDS_BIT_MAP_JEIDA] = "jeida", +struct imx_ldb_bit_mapping { + u32 bus_format; + u32 datawidth; + const char * const mapping; +}; + +static const struct imx_ldb_bit_mapping imx_ldb_bit_mappings[] = { + { MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, 18, "spwg" }, + { MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, 24, "spwg" }, + { MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, 24, "jeida" }, }; -static const int of_get_data_mapping(struct device_node *np) +static u32 of_get_bus_format(struct device *dev, struct device_node *np) { const char *bm; + u32 datawidth = 0; int ret, i; ret = of_property_read_string(np, "fsl,data-mapping", &bm); if (ret < 0) return ret; - for (i = 0; i < ARRAY_SIZE(imx_ldb_bit_mappings); i++) - if (!strcasecmp(bm, imx_ldb_bit_mappings[i])) - return i; + of_property_read_u32(np, "fsl,data-width", &datawidth); - return -EINVAL; + for (i = 0; i < ARRAY_SIZE(imx_ldb_bit_mappings); i++) { + if (!strcasecmp(bm, imx_ldb_bit_mappings[i].mapping) && + datawidth == imx_ldb_bit_mappings[i].datawidth) + return imx_ldb_bit_mappings[i].bus_format; + } + + dev_err(dev, "invalid data mapping: %d-bit \"%s\"\n", datawidth, bm); + + return -ENOENT; } static struct bus_mux imx6q_lvds_mux[2] = { @@ -437,8 +512,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) struct device_node *child; const u8 *edidp; struct imx_ldb *imx_ldb; - int datawidth; - int mapping; int dual; int ret; int i; @@ -479,12 +552,15 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) imx_ldb->clk_sel[i] = NULL; break; } + + imx_ldb->clk_parent[i] = clk_get_parent(imx_ldb->clk_sel[i]); } if (i == 0) return ret; for_each_child_of_node(np, child) { struct imx_ldb_channel *channel; + struct device_node *port; ret = of_property_read_u32(child, "reg", &i); if (ret || i < 0 || i > 1) @@ -503,49 +579,53 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) channel->chno = i; channel->child = child; + /* + * The output port is port@4 with an external 4-port mux or + * port@2 with the internal 2-port mux. + */ + port = of_graph_get_port_by_id(child, imx_ldb->lvds_mux ? 4 : 2); + if (port) { + struct device_node *endpoint, *remote; + + endpoint = of_get_child_by_name(port, "endpoint"); + if (endpoint) { + remote = of_graph_get_remote_port_parent(endpoint); + if (remote) + channel->panel = of_drm_find_panel(remote); + else + return -EPROBE_DEFER; + if (!channel->panel) { + dev_err(dev, "panel not found: %s\n", + remote->full_name); + return -EPROBE_DEFER; + } + } + } + edidp = of_get_property(child, "edid", &channel->edid_len); if (edidp) { channel->edid = kmemdup(edidp, channel->edid_len, GFP_KERNEL); - } else { + } else if (!channel->panel) { ret = of_get_drm_display_mode(child, &channel->mode, 0); if (!ret) channel->mode_valid = 1; } - ret = of_property_read_u32(child, "fsl,data-width", &datawidth); - if (ret) - datawidth = 0; - else if (datawidth != 18 && datawidth != 24) - return -EINVAL; - - mapping = of_get_data_mapping(child); - switch (mapping) { - case LVDS_BIT_MAP_SPWG: - if (datawidth == 24) { - if (i == 0 || dual) - imx_ldb->ldb_ctrl |= - LDB_DATA_WIDTH_CH0_24; - if (i == 1 || dual) - imx_ldb->ldb_ctrl |= - LDB_DATA_WIDTH_CH1_24; - } - break; - case LVDS_BIT_MAP_JEIDA: - if (datawidth == 18) { - dev_err(dev, "JEIDA standard only supported in 24 bit\n"); - return -EINVAL; - } - if (i == 0 || dual) - imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 | - LDB_BIT_MAP_CH0_JEIDA; - if (i == 1 || dual) - imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | - LDB_BIT_MAP_CH1_JEIDA; - break; - default: - dev_err(dev, "data mapping not specified or invalid\n"); - return -EINVAL; + channel->bus_format = of_get_bus_format(dev, child); + if (channel->bus_format == -EINVAL) { + /* + * If no bus format was specified in the device tree, + * we can still get it from the connected panel later. + */ + if (channel->panel && channel->panel->funcs && + channel->panel->funcs->get_modes) + channel->bus_format = 0; + } + if (channel->bus_format < 0) { + dev_err(dev, "could not determine data mapping: %d\n", + channel->bus_format); + return channel->bus_format; } ret = imx_ldb_register(drm, channel); diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c index 4216e479a9be..214eceefc981 100644 --- a/drivers/gpu/drm/imx/imx-tve.c +++ b/drivers/gpu/drm/imx/imx-tve.c @@ -301,11 +301,11 @@ static void imx_tve_encoder_prepare(struct drm_encoder *encoder) switch (tve->mode) { case TVE_MODE_VGA: - imx_drm_panel_format_pins(encoder, IPU_PIX_FMT_GBR24, - tve->hsync_pin, tve->vsync_pin); + imx_drm_set_bus_format_pins(encoder, MEDIA_BUS_FMT_YUV8_1X24, + tve->hsync_pin, tve->vsync_pin); break; case TVE_MODE_TVOUT: - imx_drm_panel_format(encoder, V4L2_PIX_FMT_YUV444); + imx_drm_set_bus_format(encoder, MEDIA_BUS_FMT_YUV8_1X24); break; } } diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index 98551e356e12..7bc8301fafff 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -45,7 +45,7 @@ struct ipu_crtc { struct drm_pending_vblank_event *page_flip_event; struct drm_framebuffer *newfb; int irq; - u32 interface_pix_fmt; + u32 bus_format; int di_hsync_pin; int di_vsync_pin; }; @@ -145,7 +145,6 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc, struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); struct ipu_di_signal_cfg sig_cfg = {}; unsigned long encoder_types = 0; - u32 out_pixel_fmt; int ret; dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, @@ -161,21 +160,21 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc, __func__, encoder_types); /* - * If we have DAC, TVDAC or LDB, then we need the IPU DI clock - * to be the same as the LDB DI clock. + * If we have DAC or LDB, then we need the IPU DI clock to be + * the same as the LDB DI clock. For TVDAC, derive the IPU DI + * clock from 27 MHz TVE_DI clock, but allow to divide it. */ if (encoder_types & (BIT(DRM_MODE_ENCODER_DAC) | - BIT(DRM_MODE_ENCODER_TVDAC) | BIT(DRM_MODE_ENCODER_LVDS))) sig_cfg.clkflags = IPU_DI_CLKMODE_SYNC | IPU_DI_CLKMODE_EXT; + else if (encoder_types & BIT(DRM_MODE_ENCODER_TVDAC)) + sig_cfg.clkflags = IPU_DI_CLKMODE_EXT; else sig_cfg.clkflags = 0; - out_pixel_fmt = ipu_crtc->interface_pix_fmt; - sig_cfg.enable_pol = 1; sig_cfg.clk_pol = 0; - sig_cfg.pixel_fmt = out_pixel_fmt; + sig_cfg.bus_format = ipu_crtc->bus_format; sig_cfg.v_to_h_sync = 0; sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin; sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin; @@ -184,7 +183,7 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc, ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, mode->flags & DRM_MODE_FLAG_INTERLACE, - out_pixel_fmt, mode->hdisplay); + ipu_crtc->bus_format, mode->hdisplay); if (ret) { dev_err(ipu_crtc->dev, "initializing display controller failed with %d\n", @@ -202,7 +201,8 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc, return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode, crtc->primary->fb, 0, 0, mode->hdisplay, mode->vdisplay, - x, y, mode->hdisplay, mode->vdisplay); + x, y, mode->hdisplay, mode->vdisplay, + mode->flags & DRM_MODE_FLAG_INTERLACE); } static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc) @@ -291,11 +291,11 @@ static void ipu_disable_vblank(struct drm_crtc *crtc) } static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, - u32 pixfmt, int hsync_pin, int vsync_pin) + u32 bus_format, int hsync_pin, int vsync_pin) { struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - ipu_crtc->interface_pix_fmt = pixfmt; + ipu_crtc->bus_format = bus_format; ipu_crtc->di_hsync_pin = hsync_pin; ipu_crtc->di_vsync_pin = vsync_pin; diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 6987e16fe99b..878a643d72e4 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -99,7 +99,7 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) + uint32_t src_w, uint32_t src_h, bool interlaced) { struct device *dev = ipu_plane->base.dev->dev; int ret; @@ -213,6 +213,8 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, ret = ipu_plane_set_base(ipu_plane, fb, src_x, src_y); if (ret < 0) return ret; + if (interlaced) + ipu_cpmem_interlaced_scan(ipu_plane->ipu_ch, fb->pitches[0]); ipu_plane->w = src_w; ipu_plane->h = src_h; @@ -312,7 +314,8 @@ static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, ret = ipu_plane_mode_set(ipu_plane, crtc, &crtc->hwmode, fb, crtc_x, crtc_y, crtc_w, crtc_h, - src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16); + src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16, + false); if (ret < 0) { ipu_plane_put_resources(ipu_plane); return ret; diff --git a/drivers/gpu/drm/imx/ipuv3-plane.h b/drivers/gpu/drm/imx/ipuv3-plane.h index af125fb40ef5..9b5eff18f5b8 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.h +++ b/drivers/gpu/drm/imx/ipuv3-plane.h @@ -42,7 +42,7 @@ int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, - uint32_t src_h); + uint32_t src_h, bool interlaced); void ipu_plane_enable(struct ipu_plane *plane); void ipu_plane_disable(struct ipu_plane *plane); diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 900dda6a8e71..74a9ce40ddc4 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -33,7 +33,7 @@ struct imx_parallel_display { struct device *dev; void *edid; int edid_len; - u32 interface_pix_fmt; + u32 bus_format; int mode_valid; struct drm_display_mode mode; struct drm_panel *panel; @@ -118,7 +118,7 @@ static void imx_pd_encoder_prepare(struct drm_encoder *encoder) { struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); - imx_drm_panel_format(encoder, imxpd->interface_pix_fmt); + imx_drm_set_bus_format(encoder, imxpd->bus_format); } static void imx_pd_encoder_commit(struct drm_encoder *encoder) @@ -225,14 +225,13 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) ret = of_property_read_string(np, "interface-pix-fmt", &fmt); if (!ret) { if (!strcmp(fmt, "rgb24")) - imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB24; + imxpd->bus_format = MEDIA_BUS_FMT_RGB888_1X24; else if (!strcmp(fmt, "rgb565")) - imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB565; + imxpd->bus_format = MEDIA_BUS_FMT_RGB565_1X16; else if (!strcmp(fmt, "bgr666")) - imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666; + imxpd->bus_format = MEDIA_BUS_FMT_RGB666_1X18; else if (!strcmp(fmt, "lvds666")) - imxpd->interface_pix_fmt = - v4l2_fourcc('L', 'V', 'D', '6'); + imxpd->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; } panel_node = of_parse_phandle(np, "fsl,panel", 0); diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index 5ad17fc36ae3..0b5af0fe8659 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -12,6 +12,13 @@ #define NV_DMA_TO_MEMORY 0x00000003 #define NV_DMA_IN_MEMORY 0x0000003d +#define FERMI_TWOD_A 0x0000902d + +#define FERMI_MEMORY_TO_MEMORY_FORMAT_A 0x0000903d + +#define KEPLER_INLINE_TO_MEMORY_A 0x0000a040 +#define KEPLER_INLINE_TO_MEMORY_B 0x0000a140 + #define NV04_DISP 0x00000046 #define NV03_CHANNEL_DMA 0x0000006b @@ -25,6 +32,7 @@ #define G82_CHANNEL_GPFIFO 0x0000826f #define FERMI_CHANNEL_GPFIFO 0x0000906f #define KEPLER_CHANNEL_GPFIFO_A 0x0000a06f +#define MAXWELL_CHANNEL_GPFIFO_A 0x0000b06f #define NV50_DISP 0x00005070 #define G82_DISP 0x00008270 @@ -84,6 +92,7 @@ #define KEPLER_C 0x0000a297 #define MAXWELL_A 0x0000b097 +#define MAXWELL_B 0x0000b197 #define FERMI_COMPUTE_A 0x000090c0 #define FERMI_COMPUTE_B 0x000091c0 @@ -92,6 +101,7 @@ #define KEPLER_COMPUTE_B 0x0000a1c0 #define MAXWELL_COMPUTE_A 0x0000b0c0 +#define MAXWELL_COMPUTE_B 0x0000b1c0 /******************************************************************************* diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h index 7e29c52617ea..e832f729e1b4 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h @@ -10,4 +10,7 @@ extern struct nvkm_oclass gf100_ce1_oclass; extern struct nvkm_oclass gk104_ce0_oclass; extern struct nvkm_oclass gk104_ce1_oclass; extern struct nvkm_oclass gk104_ce2_oclass; +extern struct nvkm_oclass gm204_ce0_oclass; +extern struct nvkm_oclass gm204_ce1_oclass; +extern struct nvkm_oclass gm204_ce2_oclass; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 05321ce7ab15..97cdeab8e44c 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -116,6 +116,7 @@ extern struct nvkm_oclass *gf100_fifo_oclass; extern struct nvkm_oclass *gk104_fifo_oclass; extern struct nvkm_oclass *gk20a_fifo_oclass; extern struct nvkm_oclass *gk208_fifo_oclass; +extern struct nvkm_oclass *gm204_fifo_oclass; int nvkm_fifo_uevent_ctor(struct nvkm_object *, void *, u32, struct nvkm_notify *); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h index 93ef1f2bfac4..7cbe20280760 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h @@ -38,7 +38,7 @@ nvkm_gr(void *obj) } #define nvkm_gr_create(p,e,c,y,d) \ - nvkm_engine_create((p), (e), (c), (y), "PGR", "graphics", (d)) + nvkm_engine_create((p), (e), (c), (y), "PGRAPH", "graphics", (d)) #define nvkm_gr_destroy(d) \ nvkm_engine_destroy(&(d)->base) #define nvkm_gr_init(d) \ @@ -72,6 +72,8 @@ extern struct nvkm_oclass *gk110_gr_oclass; extern struct nvkm_oclass *gk110b_gr_oclass; extern struct nvkm_oclass *gk208_gr_oclass; extern struct nvkm_oclass *gm107_gr_oclass; +extern struct nvkm_oclass *gm204_gr_oclass; +extern struct nvkm_oclass *gm206_gr_oclass; #include <core/enum.h> diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h index d104c1aac807..1bcb763cfca0 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h @@ -45,4 +45,5 @@ nvkm_instmem(void *obj) extern struct nvkm_oclass *nv04_instmem_oclass; extern struct nvkm_oclass *nv40_instmem_oclass; extern struct nvkm_oclass *nv50_instmem_oclass; +extern struct nvkm_oclass *gk20a_instmem_oclass; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h index 7b86acc634a0..755942352557 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h @@ -35,6 +35,7 @@ extern struct nvkm_oclass *gt215_pmu_oclass; extern struct nvkm_oclass *gf100_pmu_oclass; extern struct nvkm_oclass *gf110_pmu_oclass; extern struct nvkm_oclass *gk104_pmu_oclass; +extern struct nvkm_oclass *gk110_pmu_oclass; extern struct nvkm_oclass *gk208_pmu_oclass; extern struct nvkm_oclass *gk20a_pmu_oclass; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 77326e344dad..6edcce1658b7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1110,6 +1110,8 @@ nouveau_bo_move_init(struct nouveau_drm *drm) struct ttm_mem_reg *, struct ttm_mem_reg *); int (*init)(struct nouveau_channel *, u32 handle); } _methods[] = { + { "COPY", 4, 0xb0b5, nve0_bo_move_copy, nve0_bo_move_init }, + { "GRCE", 0, 0xb0b5, nve0_bo_move_copy, nvc0_bo_move_init }, { "COPY", 4, 0xa0b5, nve0_bo_move_copy, nve0_bo_move_init }, { "GRCE", 0, 0xa0b5, nve0_bo_move_copy, nvc0_bo_move_init }, { "COPY1", 5, 0x90b8, nvc0_bo_move_copy, nvc0_bo_move_init }, diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index e581f63cbf25..0589babc506e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -184,7 +184,8 @@ static int nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, u32 handle, u32 engine, struct nouveau_channel **pchan) { - static const u16 oclasses[] = { KEPLER_CHANNEL_GPFIFO_A, + static const u16 oclasses[] = { MAXWELL_CHANNEL_GPFIFO_A, + KEPLER_CHANNEL_GPFIFO_A, FERMI_CHANNEL_GPFIFO, G82_CHANNEL_GPFIFO, NV50_CHANNEL_GPFIFO, diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 860b0e2d4181..8670d90cdc11 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -869,13 +869,20 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args) { struct nouveau_bo *bo; + uint32_t domain; int ret; args->pitch = roundup(args->width * (args->bpp / 8), 256); args->size = args->pitch * args->height; args->size = roundup(args->size, PAGE_SIZE); - ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo); + /* Use VRAM if there is any ; otherwise fallback to system memory */ + if (nouveau_drm(dev)->device.info.ram_size != 0) + domain = NOUVEAU_GEM_DOMAIN_VRAM; + else + domain = NOUVEAU_GEM_DOMAIN_GART; + + ret = nouveau_gem_new(dev, args->size, 0, domain, 0, 0, &bo); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 8763deb5188b..89049335b738 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -181,6 +181,7 @@ nouveau_accel_init(struct nouveau_drm *drm) break; case FERMI_CHANNEL_GPFIFO: case KEPLER_CHANNEL_GPFIFO_A: + case MAXWELL_CHANNEL_GPFIFO_A: ret = nvc0_fence_create(drm); break; default: diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index fc68f0973f9e..dd726523ca99 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -10,7 +10,7 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 2 -#define DRIVER_PATCHLEVEL 1 +#define DRIVER_PATCHLEVEL 2 /* * 1.1.1: @@ -28,6 +28,8 @@ * - fermi,kepler,maxwell zbc * 1.2.1: * - allow concurrent access to bo's mapped read/write. + * 1.2.2: + * - add NOUVEAU_GEM_DOMAIN_COHERENT flag */ #include <nvif/client.h> diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 7c077fced1d1..0e690bf19fc9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -189,6 +189,9 @@ nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain, if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU) flags |= TTM_PL_FLAG_SYSTEM; + if (domain & NOUVEAU_GEM_DOMAIN_COHERENT) + flags |= TTM_PL_FLAG_UNCACHED; + ret = nouveau_bo_new(dev, size, align, flags, tile_mode, tile_flags, NULL, NULL, pnvbo); if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c index dc5900bf54ff..775277f1edb0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c @@ -27,6 +27,7 @@ #include <linux/of.h> #include <linux/reset.h> #include <linux/regulator/consumer.h> +#include <linux/iommu.h> #include <soc/tegra/fuse.h> #include <soc/tegra/pmc.h> @@ -91,6 +92,72 @@ static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu) return 0; } +static void nouveau_platform_probe_iommu(struct device *dev, + struct nouveau_platform_gpu *gpu) +{ + int err; + unsigned long pgsize_bitmap; + + mutex_init(&gpu->iommu.mutex); + + if (iommu_present(&platform_bus_type)) { + gpu->iommu.domain = iommu_domain_alloc(&platform_bus_type); + if (IS_ERR(gpu->iommu.domain)) + goto error; + + /* + * A IOMMU is only usable if it supports page sizes smaller + * or equal to the system's PAGE_SIZE, with a preference if + * both are equal. + */ + pgsize_bitmap = gpu->iommu.domain->ops->pgsize_bitmap; + if (pgsize_bitmap & PAGE_SIZE) { + gpu->iommu.pgshift = PAGE_SHIFT; + } else { + gpu->iommu.pgshift = fls(pgsize_bitmap & ~PAGE_MASK); + if (gpu->iommu.pgshift == 0) { + dev_warn(dev, "unsupported IOMMU page size\n"); + goto free_domain; + } + gpu->iommu.pgshift -= 1; + } + + err = iommu_attach_device(gpu->iommu.domain, dev); + if (err) + goto free_domain; + + err = nvkm_mm_init(&gpu->iommu._mm, 0, + (1ULL << 40) >> gpu->iommu.pgshift, 1); + if (err) + goto detach_device; + + gpu->iommu.mm = &gpu->iommu._mm; + } + + return; + +detach_device: + iommu_detach_device(gpu->iommu.domain, dev); + +free_domain: + iommu_domain_free(gpu->iommu.domain); + +error: + gpu->iommu.domain = NULL; + gpu->iommu.pgshift = 0; + dev_err(dev, "cannot initialize IOMMU MM\n"); +} + +static void nouveau_platform_remove_iommu(struct device *dev, + struct nouveau_platform_gpu *gpu) +{ + if (gpu->iommu.domain) { + nvkm_mm_fini(&gpu->iommu._mm); + iommu_detach_device(gpu->iommu.domain, dev); + iommu_domain_free(gpu->iommu.domain); + } +} + static int nouveau_platform_probe(struct platform_device *pdev) { struct nouveau_platform_gpu *gpu; @@ -118,6 +185,8 @@ static int nouveau_platform_probe(struct platform_device *pdev) if (IS_ERR(gpu->clk_pwr)) return PTR_ERR(gpu->clk_pwr); + nouveau_platform_probe_iommu(&pdev->dev, gpu); + err = nouveau_platform_power_up(gpu); if (err) return err; @@ -140,10 +209,9 @@ static int nouveau_platform_probe(struct platform_device *pdev) err_unref: drm_dev_unref(drm); - return 0; - power_down: nouveau_platform_power_down(gpu); + nouveau_platform_remove_iommu(&pdev->dev, gpu); return err; } @@ -154,10 +222,15 @@ static int nouveau_platform_remove(struct platform_device *pdev) struct nouveau_drm *drm = nouveau_drm(drm_dev); struct nvkm_device *device = nvxx_device(&drm->device); struct nouveau_platform_gpu *gpu = nv_device_to_platform(device)->gpu; + int err; nouveau_drm_device_remove(drm_dev); - return nouveau_platform_power_down(gpu); + err = nouveau_platform_power_down(gpu); + + nouveau_platform_remove_iommu(&pdev->dev, gpu); + + return err; } #if IS_ENABLED(CONFIG_OF) diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.h b/drivers/gpu/drm/nouveau/nouveau_platform.h index 268bb7213681..392874cf4725 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.h +++ b/drivers/gpu/drm/nouveau/nouveau_platform.h @@ -24,10 +24,12 @@ #define __NOUVEAU_PLATFORM_H__ #include "core/device.h" +#include "core/mm.h" struct reset_control; struct clk; struct regulator; +struct iommu_domain; struct platform_driver; struct nouveau_platform_gpu { @@ -36,6 +38,22 @@ struct nouveau_platform_gpu { struct clk *clk_pwr; struct regulator *vdd; + + struct { + /* + * Protects accesses to mm from subsystems + */ + struct mutex mutex; + + struct nvkm_mm _mm; + /* + * Just points to _mm. We need this to avoid embedding + * struct nvkm_mm in os.h + */ + struct nvkm_mm *mm; + struct iommu_domain *domain; + unsigned long pgshift; + } iommu; }; struct nouveau_platform_device { diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 273e50110ec3..18f449715788 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -82,6 +82,9 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, u32 size_nc = 0; int ret; + if (drm->device.info.ram_size == 0) + return -ENOMEM; + if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) size_nc = 1 << nvbo->page_shift; diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index bf429cabbaa8..a03db4368696 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -215,6 +215,7 @@ nv84_fence_create(struct nouveau_drm *drm) { struct nvkm_fifo *pfifo = nvxx_fifo(&drm->device); struct nv84_fence_priv *priv; + u32 domain; int ret; priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -231,10 +232,17 @@ nv84_fence_create(struct nouveau_drm *drm) priv->base.context_base = fence_context_alloc(priv->base.contexts); priv->base.uevent = true; - ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0, - TTM_PL_FLAG_VRAM, 0, 0, NULL, NULL, &priv->bo); + /* Use VRAM if there is any ; otherwise fallback to system memory */ + domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM : + /* + * fences created in sysmem must be non-cached or we + * will lose CPU/GPU coherency! + */ + TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED; + ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0, domain, 0, + 0, NULL, NULL, &priv->bo); if (ret == 0) { - ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM, false); + ret = nouveau_bo_pin(priv->bo, domain, false); if (ret == 0) { ret = nouveau_bo_map(priv->bo); if (ret) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild index 858797453e0b..fa8cda7058cd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild @@ -1,3 +1,4 @@ nvkm-y += nvkm/engine/ce/gt215.o nvkm-y += nvkm/engine/ce/gf100.o nvkm-y += nvkm/engine/ce/gk104.o +nvkm-y += nvkm/engine/ce/gm204.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm204.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm204.c new file mode 100644 index 000000000000..577eb2eead05 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm204.c @@ -0,0 +1,173 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * 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. + * + * Authors: Ben Skeggs + */ +#include <engine/ce.h> + +#include <core/engctx.h> + +struct gm204_ce_priv { + struct nvkm_engine base; +}; + +/******************************************************************************* + * Copy object classes + ******************************************************************************/ + +static struct nvkm_oclass +gm204_ce_sclass[] = { + { 0xb0b5, &nvkm_object_ofuncs }, + {}, +}; + +/******************************************************************************* + * PCE context + ******************************************************************************/ + +static struct nvkm_ofuncs +gm204_ce_context_ofuncs = { + .ctor = _nvkm_engctx_ctor, + .dtor = _nvkm_engctx_dtor, + .init = _nvkm_engctx_init, + .fini = _nvkm_engctx_fini, + .rd32 = _nvkm_engctx_rd32, + .wr32 = _nvkm_engctx_wr32, +}; + +static struct nvkm_oclass +gm204_ce_cclass = { + .handle = NV_ENGCTX(CE0, 0x24), + .ofuncs = &gm204_ce_context_ofuncs, +}; + +/******************************************************************************* + * PCE engine/subdev functions + ******************************************************************************/ + +static void +gm204_ce_intr(struct nvkm_subdev *subdev) +{ + const int ce = nv_subidx(subdev) - NVDEV_ENGINE_CE0; + struct gm204_ce_priv *priv = (void *)subdev; + u32 stat = nv_rd32(priv, 0x104908 + (ce * 0x1000)); + + if (stat) { + nv_warn(priv, "unhandled intr 0x%08x\n", stat); + nv_wr32(priv, 0x104908 + (ce * 0x1000), stat); + } +} + +static int +gm204_ce0_ctor(struct nvkm_object *parent, struct nvkm_object *engine, + struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + struct gm204_ce_priv *priv; + int ret; + + ret = nvkm_engine_create(parent, engine, oclass, true, + "PCE0", "ce0", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000040; + nv_subdev(priv)->intr = gm204_ce_intr; + nv_engine(priv)->cclass = &gm204_ce_cclass; + nv_engine(priv)->sclass = gm204_ce_sclass; + return 0; +} + +static int +gm204_ce1_ctor(struct nvkm_object *parent, struct nvkm_object *engine, + struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + struct gm204_ce_priv *priv; + int ret; + + ret = nvkm_engine_create(parent, engine, oclass, true, + "PCE1", "ce1", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00000080; + nv_subdev(priv)->intr = gm204_ce_intr; + nv_engine(priv)->cclass = &gm204_ce_cclass; + nv_engine(priv)->sclass = gm204_ce_sclass; + return 0; +} + +static int +gm204_ce2_ctor(struct nvkm_object *parent, struct nvkm_object *engine, + struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + struct gm204_ce_priv *priv; + int ret; + + ret = nvkm_engine_create(parent, engine, oclass, true, + "PCE2", "ce2", &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->unit = 0x00200000; + nv_subdev(priv)->intr = gm204_ce_intr; + nv_engine(priv)->cclass = &gm204_ce_cclass; + nv_engine(priv)->sclass = gm204_ce_sclass; + return 0; +} + +struct nvkm_oclass +gm204_ce0_oclass = { + .handle = NV_ENGINE(CE0, 0x24), + .ofuncs = &(struct nvkm_ofuncs) { + .ctor = gm204_ce0_ctor, + .dtor = _nvkm_engine_dtor, + .init = _nvkm_engine_init, + .fini = _nvkm_engine_fini, + }, +}; + +struct nvkm_oclass +gm204_ce1_oclass = { + .handle = NV_ENGINE(CE1, 0x24), + .ofuncs = &(struct nvkm_ofuncs) { + .ctor = gm204_ce1_ctor, + .dtor = _nvkm_engine_dtor, + .init = _nvkm_engine_init, + .fini = _nvkm_engine_fini, + }, +}; + +struct nvkm_oclass +gm204_ce2_oclass = { + .handle = NV_ENGINE(CE2, 0x24), + .ofuncs = &(struct nvkm_ofuncs) { + .ctor = gm204_ce2_ctor, + .dtor = _nvkm_engine_dtor, + .init = _nvkm_engine_init, + .fini = _nvkm_engine_fini, + }, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 6efa8f38ff54..63d8e52f4b22 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -139,9 +139,13 @@ nvkm_devobj_info(struct nvkm_object *object, void *data, u32 size) args->v0.chipset = device->chipset; args->v0.revision = device->chiprev; - if (pfb) args->v0.ram_size = args->v0.ram_user = pfb->ram->size; - else args->v0.ram_size = args->v0.ram_user = 0; - if (imem) args->v0.ram_user = args->v0.ram_user - imem->reserved; + if (pfb && pfb->ram) + args->v0.ram_size = args->v0.ram_user = pfb->ram->size; + else + args->v0.ram_size = args->v0.ram_user = 0; + if (imem && args->v0.ram_size > 0) + args->v0.ram_user = args->v0.ram_user - imem->reserved; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/gk104.c index bf5893458a47..6a9483f65d83 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/gk104.c @@ -171,7 +171,7 @@ gk104_identify(struct nvkm_device *device) device->oclass[NVDEV_SUBDEV_FB ] = gk20a_fb_oclass; device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; device->oclass[NVDEV_SUBDEV_IBUS ] = &gk20a_ibus_oclass; - device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = gk20a_instmem_oclass; device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &gk20a_bar_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; @@ -202,7 +202,7 @@ gk104_identify(struct nvkm_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gf110_pmu_oclass; + device->oclass[NVDEV_SUBDEV_PMU ] = gk110_pmu_oclass; device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = gk104_fifo_oclass; @@ -236,7 +236,7 @@ gk104_identify(struct nvkm_device *device) device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; device->oclass[NVDEV_SUBDEV_MMU ] = &gf100_mmu_oclass; device->oclass[NVDEV_SUBDEV_BAR ] = &gf100_bar_oclass; - device->oclass[NVDEV_SUBDEV_PMU ] = gf110_pmu_oclass; + device->oclass[NVDEV_SUBDEV_PMU ] = gk110_pmu_oclass; device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; device->oclass[NVDEV_ENGINE_FIFO ] = gk104_fifo_oclass; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c index 108d048da764..70abf1ec7c98 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c @@ -127,16 +127,14 @@ gm100_identify(struct nvkm_device *device) device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; #endif device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; -#if 0 - device->oclass[NVDEV_ENGINE_FIFO ] = gk208_fifo_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = gm204_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gm107_gr_oclass; -#endif + device->oclass[NVDEV_ENGINE_GR ] = gm204_gr_oclass; device->oclass[NVDEV_ENGINE_DISP ] = gm204_disp_oclass; -#if 0 device->oclass[NVDEV_ENGINE_CE0 ] = &gm204_ce0_oclass; device->oclass[NVDEV_ENGINE_CE1 ] = &gm204_ce1_oclass; device->oclass[NVDEV_ENGINE_CE2 ] = &gm204_ce2_oclass; +#if 0 device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; @@ -170,16 +168,14 @@ gm100_identify(struct nvkm_device *device) device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; #endif device->oclass[NVDEV_ENGINE_DMAOBJ ] = gf110_dmaeng_oclass; -#if 0 - device->oclass[NVDEV_ENGINE_FIFO ] = gk208_fifo_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = gm204_fifo_oclass; device->oclass[NVDEV_ENGINE_SW ] = gf100_sw_oclass; - device->oclass[NVDEV_ENGINE_GR ] = gm107_gr_oclass; -#endif + device->oclass[NVDEV_ENGINE_GR ] = gm206_gr_oclass; device->oclass[NVDEV_ENGINE_DISP ] = gm204_disp_oclass; -#if 0 device->oclass[NVDEV_ENGINE_CE0 ] = &gm204_ce0_oclass; device->oclass[NVDEV_ENGINE_CE1 ] = &gm204_ce1_oclass; device->oclass[NVDEV_ENGINE_CE2 ] = &gm204_ce2_oclass; +#if 0 device->oclass[NVDEV_ENGINE_MSVLD ] = &gk104_msvld_oclass; device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass; device->oclass[NVDEV_ENGINE_MSPPP ] = &gf100_msppp_oclass; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c index 0ebf466e9ef3..9ef6728c528d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c @@ -413,8 +413,8 @@ gf110_disp_base_mthd_base = { static const struct nv50_disp_mthd_list gf110_disp_base_mthd_image = { - .mthd = 0x0400, - .addr = 0x000400, + .mthd = 0x0020, + .addr = 0x000020, .data = { { 0x0400, 0x661400 }, { 0x0404, 0x661404 }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index 84ade810e27c..8ba808df24ad 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -229,7 +229,7 @@ nv50_disp_dmac_create_(struct nvkm_object *parent, switch (dmac->pushdma->target) { case NV_MEM_TARGET_VRAM: - dmac->push = 0x00000000 | dmac->pushdma->start >> 8; + dmac->push = 0x00000001 | dmac->pushdma->start >> 8; break; case NV_MEM_TARGET_PCI_NOSNOOP: dmac->push = 0x00000003 | dmac->pushdma->start >> 8; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index c5a2d8718c5b..42891cb71ea3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -9,3 +9,4 @@ nvkm-y += nvkm/engine/fifo/gf100.o nvkm-y += nvkm/engine/fifo/gk104.o nvkm-y += nvkm/engine/fifo/gk20a.o nvkm-y += nvkm/engine/fifo/gk208.o +nvkm-y += nvkm/engine/fifo/gm204.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 9585539e59f2..e10f9644140f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -323,8 +323,8 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend) return nvkm_fifo_channel_fini(&chan->base, suspend); } -static struct nvkm_ofuncs -gk104_fifo_ofuncs = { +struct nvkm_ofuncs +gk104_fifo_chan_ofuncs = { .ctor = gk104_fifo_chan_ctor, .dtor = _nvkm_fifo_channel_dtor, .init = gk104_fifo_chan_init, @@ -337,7 +337,7 @@ gk104_fifo_ofuncs = { static struct nvkm_oclass gk104_fifo_sclass[] = { - { KEPLER_CHANNEL_GPFIFO_A, &gk104_fifo_ofuncs }, + { KEPLER_CHANNEL_GPFIFO_A, &gk104_fifo_chan_ofuncs }, {} }; @@ -774,6 +774,7 @@ gk104_fifo_intr_fault(struct gk104_fifo_priv *priv, int unit) while (object) { switch (nv_mclass(object)) { case KEPLER_CHANNEL_GPFIFO_A: + case MAXWELL_CHANNEL_GPFIFO_A: gk104_fifo_recover(priv, engine, (void *)object); break; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 3046e00ed6ba..318d30d6ee1a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -13,4 +13,6 @@ struct gk104_fifo_impl { struct nvkm_oclass base; u32 channels; }; + +extern struct nvkm_ofuncs gk104_fifo_chan_ofuncs; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c new file mode 100644 index 000000000000..749d525dd8e3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c @@ -0,0 +1,57 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * 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. + * + * Authors: Ben Skeggs + */ +#include "gk104.h" + +#include <nvif/class.h> + +static struct nvkm_oclass +gm204_fifo_sclass[] = { + { MAXWELL_CHANNEL_GPFIFO_A, &gk104_fifo_chan_ofuncs }, + {} +}; + +static int +gm204_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine, + struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + int ret = gk104_fifo_ctor(parent, engine, oclass, data, size, pobject); + if (ret == 0) { + struct gk104_fifo_priv *priv = (void *)*pobject; + nv_engine(priv)->sclass = gm204_fifo_sclass; + } + return ret; +} + +struct nvkm_oclass * +gm204_fifo_oclass = &(struct gk104_fifo_impl) { + .base.handle = NV_ENGINE(FIFO, 0x24), + .base.ofuncs = &(struct nvkm_ofuncs) { + .ctor = gm204_fifo_ctor, + .dtor = gk104_fifo_dtor, + .init = gk104_fifo_init, + .fini = _nvkm_fifo_fini, + }, + .channels = 4096, +}.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild index 1771d944591b..2e1b92f71d9e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild @@ -12,6 +12,8 @@ nvkm-y += nvkm/engine/gr/ctxgk110.o nvkm-y += nvkm/engine/gr/ctxgk110b.o nvkm-y += nvkm/engine/gr/ctxgk208.o nvkm-y += nvkm/engine/gr/ctxgm107.o +nvkm-y += nvkm/engine/gr/ctxgm204.o +nvkm-y += nvkm/engine/gr/ctxgm206.o nvkm-y += nvkm/engine/gr/nv04.o nvkm-y += nvkm/engine/gr/nv10.o nvkm-y += nvkm/engine/gr/nv20.o @@ -34,3 +36,5 @@ nvkm-y += nvkm/engine/gr/gk110.o nvkm-y += nvkm/engine/gr/gk110b.o nvkm-y += nvkm/engine/gr/gk208.o nvkm-y += nvkm/engine/gr/gm107.o +nvkm-y += nvkm/engine/gr/gm204.o +nvkm-y += nvkm/engine/gr/gm206.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 1166b1aa1525..3676a3342bc5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -88,11 +88,22 @@ void gk104_grctx_generate_bundle(struct gf100_grctx *); void gk104_grctx_generate_pagepool(struct gf100_grctx *); void gk104_grctx_generate_unkn(struct gf100_gr_priv *); void gk104_grctx_generate_r418bb8(struct gf100_gr_priv *); +void gk104_grctx_generate_rop_active_fbps(struct gf100_gr_priv *); + extern struct nvkm_oclass *gk110_grctx_oclass; extern struct nvkm_oclass *gk110b_grctx_oclass; extern struct nvkm_oclass *gk208_grctx_oclass; + extern struct nvkm_oclass *gm107_grctx_oclass; +void gm107_grctx_generate_bundle(struct gf100_grctx *); +void gm107_grctx_generate_pagepool(struct gf100_grctx *); +void gm107_grctx_generate_attrib(struct gf100_grctx *); + +extern struct nvkm_oclass *gm204_grctx_oclass; +void gm204_grctx_generate_main(struct gf100_gr_priv *, struct gf100_grctx *); + +extern struct nvkm_oclass *gm206_grctx_oclass; /* context init value lists */ @@ -196,4 +207,22 @@ extern const struct gf100_gr_init gk208_grctx_init_rstr2d_0[]; extern const struct gf100_gr_init gk208_grctx_init_prop_0[]; extern const struct gf100_gr_init gk208_grctx_init_crstr_0[]; + +extern const struct gf100_gr_init gm107_grctx_init_gpc_unk_0[]; +extern const struct gf100_gr_init gm107_grctx_init_wwdx_0[]; + +extern const struct gf100_gr_pack gm204_grctx_pack_icmd[]; + +extern const struct gf100_gr_pack gm204_grctx_pack_mthd[]; + +extern const struct gf100_gr_pack gm204_grctx_pack_hub[]; + +extern const struct gf100_gr_init gm204_grctx_init_prop_0[]; +extern const struct gf100_gr_init gm204_grctx_init_setup_0[]; +extern const struct gf100_gr_init gm204_grctx_init_gpm_0[]; +extern const struct gf100_gr_init gm204_grctx_init_gpc_unk_2[]; + +extern const struct gf100_gr_pack gm204_grctx_pack_tpc[]; + +extern const struct gf100_gr_pack gm204_grctx_pack_ppc[]; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c index 5e9454ba158f..b12f6a9fd926 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c @@ -941,6 +941,14 @@ gk104_grctx_generate_r418bb8(struct gf100_gr_priv *priv) } void +gk104_grctx_generate_rop_active_fbps(struct gf100_gr_priv *priv) +{ + const u32 fbp_count = nv_rd32(priv, 0x120074); + nv_mask(priv, 0x408850, 0x0000000f, fbp_count); /* zrop */ + nv_mask(priv, 0x408958, 0x0000000f, fbp_count); /* crop */ +} + +void gk104_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info) { struct gf100_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass; @@ -970,13 +978,7 @@ gk104_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info) nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000); nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr); - if (priv->gpc_nr == 1) { - nv_mask(priv, 0x408850, 0x0000000f, priv->tpc_nr[0]); - nv_mask(priv, 0x408958, 0x0000000f, priv->tpc_nr[0]); - } else { - nv_mask(priv, 0x408850, 0x0000000f, priv->gpc_nr); - nv_mask(priv, 0x408958, 0x0000000f, priv->gpc_nr); - } + gk104_grctx_generate_rop_active_fbps(priv); nv_mask(priv, 0x419f78, 0x00000001, 0x00000000); gf100_gr_icmd(priv, oclass->icmd); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c index b2fae6e389e2..fbeaae3ae6ce 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c @@ -699,7 +699,7 @@ gm107_grctx_pack_hub[] = { {} }; -static const struct gf100_gr_init +const struct gf100_gr_init gm107_grctx_init_gpc_unk_0[] = { { 0x418380, 1, 0x04, 0x00000056 }, {} @@ -834,7 +834,7 @@ gm107_grctx_init_cbm_0[] = { {} }; -static const struct gf100_gr_init +const struct gf100_gr_init gm107_grctx_init_wwdx_0[] = { { 0x41bf00, 1, 0x04, 0x0a418820 }, { 0x41bf04, 1, 0x04, 0x062080e6 }, @@ -860,7 +860,7 @@ gm107_grctx_pack_ppc[] = { * PGRAPH context implementation ******************************************************************************/ -static void +void gm107_grctx_generate_bundle(struct gf100_grctx *info) { const struct gf100_grctx_oclass *impl = gf100_grctx_impl(info->priv); @@ -877,7 +877,7 @@ gm107_grctx_generate_bundle(struct gf100_grctx *info) mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit); } -static void +void gm107_grctx_generate_pagepool(struct gf100_grctx *info) { const struct gf100_grctx_oclass *impl = gf100_grctx_impl(info->priv); @@ -892,7 +892,7 @@ gm107_grctx_generate_pagepool(struct gf100_grctx *info) mmio_wr32(info, 0x418e30, 0x80000000); /* guess at it being related */ } -static void +void gm107_grctx_generate_attrib(struct gf100_grctx *info) { struct gf100_gr_priv *priv = info->priv; @@ -926,7 +926,7 @@ gm107_grctx_generate_attrib(struct gf100_grctx *info) mmio_wr32(info, o + 0xe4, as); mmio_wr32(info, o + 0xf8, ao); ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc]; - mmio_wr32(info, u, (0x715 /*XXX*/ << 16) | bs); + mmio_wr32(info, u, ((bs / 3 /*XXX*/) << 16) | bs); } } } @@ -982,13 +982,7 @@ gm107_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info) nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr); - if (priv->gpc_nr == 1) { - nv_mask(priv, 0x408850, 0x0000000f, priv->tpc_nr[0]); - nv_mask(priv, 0x408958, 0x0000000f, priv->tpc_nr[0]); - } else { - nv_mask(priv, 0x408850, 0x0000000f, priv->gpc_nr); - nv_mask(priv, 0x408958, 0x0000000f, priv->gpc_nr); - } + gk104_grctx_generate_rop_active_fbps(priv); gf100_gr_icmd(priv, oclass->icmd); nv_wr32(priv, 0x404154, 0x00000400); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm204.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm204.c new file mode 100644 index 000000000000..ea8e66151aa8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm204.c @@ -0,0 +1,1054 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * 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. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "ctxgf100.h" + +/******************************************************************************* + * PGRAPH context register lists + ******************************************************************************/ + +static const struct gf100_gr_init +gm204_grctx_init_icmd_0[] = { + { 0x001000, 1, 0x01, 0x00000002 }, + { 0x0006aa, 1, 0x01, 0x00000001 }, + { 0x0006ad, 2, 0x01, 0x00000100 }, + { 0x0006b1, 1, 0x01, 0x00000011 }, + { 0x00078c, 1, 0x01, 0x00000008 }, + { 0x000792, 1, 0x01, 0x00000001 }, + { 0x000794, 3, 0x01, 0x00000001 }, + { 0x000797, 1, 0x01, 0x000000cf }, + { 0x00079a, 1, 0x01, 0x00000002 }, + { 0x0007a1, 1, 0x01, 0x00000001 }, + { 0x0007a3, 3, 0x01, 0x00000001 }, + { 0x000831, 1, 0x01, 0x00000004 }, + { 0x01e100, 1, 0x01, 0x00000001 }, + { 0x001000, 1, 0x01, 0x00000008 }, + { 0x000039, 3, 0x01, 0x00000000 }, + { 0x000380, 1, 0x01, 0x00000001 }, + { 0x000366, 2, 0x01, 0x00000000 }, + { 0x000368, 1, 0x01, 0x00000fff }, + { 0x000370, 2, 0x01, 0x00000000 }, + { 0x000372, 1, 0x01, 0x000fffff }, + { 0x000374, 1, 0x01, 0x00000100 }, + { 0x000818, 8, 0x01, 0x00000000 }, + { 0x000848, 16, 0x01, 0x00000000 }, + { 0x000738, 1, 0x01, 0x00000000 }, + { 0x000b07, 1, 0x01, 0x00000002 }, + { 0x000b08, 2, 0x01, 0x00000100 }, + { 0x000b0a, 1, 0x01, 0x00000001 }, + { 0x000a04, 1, 0x01, 0x000000ff }, + { 0x000a0b, 1, 0x01, 0x00000040 }, + { 0x00097f, 1, 0x01, 0x00000100 }, + { 0x000a02, 1, 0x01, 0x00000001 }, + { 0x000809, 1, 0x01, 0x00000007 }, + { 0x00c221, 1, 0x01, 0x00000040 }, + { 0x00c401, 1, 0x01, 0x00000001 }, + { 0x00c402, 1, 0x01, 0x00010001 }, + { 0x00c403, 2, 0x01, 0x00000001 }, + { 0x00c40e, 1, 0x01, 0x00000020 }, + { 0x01e100, 1, 0x01, 0x00000001 }, + { 0x001000, 1, 0x01, 0x00000001 }, + { 0x000b07, 1, 0x01, 0x00000002 }, + { 0x000b08, 2, 0x01, 0x00000100 }, + { 0x000b0a, 1, 0x01, 0x00000001 }, + { 0x01e100, 1, 0x01, 0x00000001 }, + { 0x001000, 1, 0x01, 0x00000004 }, + { 0x000039, 3, 0x01, 0x00000000 }, + { 0x0000a9, 1, 0x01, 0x0000ffff }, + { 0x000038, 1, 0x01, 0x0fac6881 }, + { 0x00003d, 1, 0x01, 0x00000001 }, + { 0x0000e8, 8, 0x01, 0x00000400 }, + { 0x000078, 8, 0x01, 0x00000300 }, + { 0x000050, 1, 0x01, 0x00000011 }, + { 0x000058, 8, 0x01, 0x00000008 }, + { 0x000208, 8, 0x01, 0x00000001 }, + { 0x000081, 1, 0x01, 0x00000001 }, + { 0x000085, 1, 0x01, 0x00000004 }, + { 0x000088, 1, 0x01, 0x00000400 }, + { 0x000090, 1, 0x01, 0x00000300 }, + { 0x000098, 1, 0x01, 0x00001001 }, + { 0x0000e3, 1, 0x01, 0x00000001 }, + { 0x0000da, 1, 0x01, 0x00000001 }, + { 0x0000b4, 4, 0x01, 0x88888888 }, + { 0x0000f8, 1, 0x01, 0x00000003 }, + { 0x0000fa, 1, 0x01, 0x00000001 }, + { 0x0000b1, 2, 0x01, 0x00000001 }, + { 0x00009f, 4, 0x01, 0x0000ffff }, + { 0x0000a8, 1, 0x01, 0x0000ffff }, + { 0x0000ad, 1, 0x01, 0x0000013e }, + { 0x0000e1, 1, 0x01, 0x00000010 }, + { 0x000290, 16, 0x01, 0x00000000 }, + { 0x0003b0, 16, 0x01, 0x00000000 }, + { 0x0002a0, 16, 0x01, 0x00000000 }, + { 0x000420, 16, 0x01, 0x00000000 }, + { 0x0002b0, 16, 0x01, 0x00000000 }, + { 0x000430, 16, 0x01, 0x00000000 }, + { 0x0002c0, 16, 0x01, 0x00000000 }, + { 0x0004d0, 16, 0x01, 0x00000000 }, + { 0x000720, 16, 0x01, 0x00000000 }, + { 0x0008c0, 16, 0x01, 0x00000000 }, + { 0x000890, 16, 0x01, 0x00000000 }, + { 0x0008e0, 16, 0x01, 0x00000000 }, + { 0x0008a0, 16, 0x01, 0x00000000 }, + { 0x0008f0, 16, 0x01, 0x00000000 }, + { 0x00094c, 1, 0x01, 0x000000ff }, + { 0x00094d, 1, 0x01, 0xffffffff }, + { 0x00094e, 1, 0x01, 0x00000002 }, + { 0x0002f2, 2, 0x01, 0x00000001 }, + { 0x0002f5, 1, 0x01, 0x00000001 }, + { 0x0002f7, 1, 0x01, 0x00000001 }, + { 0x000303, 1, 0x01, 0x00000001 }, + { 0x0002e6, 1, 0x01, 0x00000001 }, + { 0x000466, 1, 0x01, 0x00000052 }, + { 0x000301, 1, 0x01, 0x3f800000 }, + { 0x000304, 1, 0x01, 0x30201000 }, + { 0x000305, 1, 0x01, 0x70605040 }, + { 0x000306, 1, 0x01, 0xb8a89888 }, + { 0x000307, 1, 0x01, 0xf8e8d8c8 }, + { 0x00030a, 1, 0x01, 0x00ffff00 }, + { 0x00030b, 1, 0x01, 0x0000001a }, + { 0x00030c, 1, 0x01, 0x00000001 }, + { 0x000318, 1, 0x01, 0x00000001 }, + { 0x000340, 1, 0x01, 0x00000000 }, + { 0x00037d, 1, 0x01, 0x00000006 }, + { 0x0003a0, 1, 0x01, 0x00000002 }, + { 0x0003aa, 1, 0x01, 0x00000001 }, + { 0x0003a9, 1, 0x01, 0x00000001 }, + { 0x000380, 1, 0x01, 0x00000001 }, + { 0x000383, 1, 0x01, 0x00000011 }, + { 0x000360, 1, 0x01, 0x00000040 }, + { 0x000366, 2, 0x01, 0x00000000 }, + { 0x000368, 1, 0x01, 0x00000fff }, + { 0x000370, 2, 0x01, 0x00000000 }, + { 0x000372, 1, 0x01, 0x000fffff }, + { 0x000374, 1, 0x01, 0x00000100 }, + { 0x00037a, 1, 0x01, 0x00000012 }, + { 0x000619, 1, 0x01, 0x00000003 }, + { 0x000811, 1, 0x01, 0x00000003 }, + { 0x000812, 1, 0x01, 0x00000004 }, + { 0x000813, 1, 0x01, 0x00000006 }, + { 0x000814, 1, 0x01, 0x00000008 }, + { 0x000815, 1, 0x01, 0x0000000b }, + { 0x000800, 6, 0x01, 0x00000001 }, + { 0x000632, 1, 0x01, 0x00000001 }, + { 0x000633, 1, 0x01, 0x00000002 }, + { 0x000634, 1, 0x01, 0x00000003 }, + { 0x000635, 1, 0x01, 0x00000004 }, + { 0x000654, 1, 0x01, 0x3f800000 }, + { 0x000657, 1, 0x01, 0x3f800000 }, + { 0x000655, 2, 0x01, 0x3f800000 }, + { 0x0006cd, 1, 0x01, 0x3f800000 }, + { 0x0007f5, 1, 0x01, 0x3f800000 }, + { 0x0007dc, 1, 0x01, 0x39291909 }, + { 0x0007dd, 1, 0x01, 0x79695949 }, + { 0x0007de, 1, 0x01, 0xb9a99989 }, + { 0x0007df, 1, 0x01, 0xf9e9d9c9 }, + { 0x0007e8, 1, 0x01, 0x00003210 }, + { 0x0007e9, 1, 0x01, 0x00007654 }, + { 0x0007ea, 1, 0x01, 0x00000098 }, + { 0x0007ec, 1, 0x01, 0x39291909 }, + { 0x0007ed, 1, 0x01, 0x79695949 }, + { 0x0007ee, 1, 0x01, 0xb9a99989 }, + { 0x0007ef, 1, 0x01, 0xf9e9d9c9 }, + { 0x0007f0, 1, 0x01, 0x00003210 }, + { 0x0007f1, 1, 0x01, 0x00007654 }, + { 0x0007f2, 1, 0x01, 0x00000098 }, + { 0x0005a5, 1, 0x01, 0x00000001 }, + { 0x0005aa, 1, 0x01, 0x00000002 }, + { 0x0005cb, 1, 0x01, 0x00000004 }, + { 0x0005d0, 1, 0x01, 0x20181008 }, + { 0x0005d1, 1, 0x01, 0x40383028 }, + { 0x0005d2, 1, 0x01, 0x60585048 }, + { 0x0005d3, 1, 0x01, 0x80787068 }, + { 0x000980, 128, 0x01, 0x00000000 }, + { 0x000468, 1, 0x01, 0x00000004 }, + { 0x00046c, 1, 0x01, 0x00000001 }, + { 0x000470, 96, 0x01, 0x00000000 }, + { 0x0005e0, 16, 0x01, 0x00000d10 }, + { 0x000510, 16, 0x01, 0x3f800000 }, + { 0x000520, 1, 0x01, 0x000002b6 }, + { 0x000529, 1, 0x01, 0x00000001 }, + { 0x000530, 16, 0x01, 0xffff0000 }, + { 0x000550, 32, 0x01, 0xffff0000 }, + { 0x000585, 1, 0x01, 0x0000003f }, + { 0x000576, 1, 0x01, 0x00000003 }, + { 0x00057b, 1, 0x01, 0x00000059 }, + { 0x000586, 1, 0x01, 0x00000040 }, + { 0x000582, 2, 0x01, 0x00000080 }, + { 0x000595, 1, 0x01, 0x00400040 }, + { 0x000596, 1, 0x01, 0x00000492 }, + { 0x000597, 1, 0x01, 0x08080203 }, + { 0x0005ad, 1, 0x01, 0x00000008 }, + { 0x000598, 1, 0x01, 0x00020001 }, + { 0x0005d4, 1, 0x01, 0x00000001 }, + { 0x0005c2, 1, 0x01, 0x00000001 }, + { 0x000638, 2, 0x01, 0x00000001 }, + { 0x00063a, 1, 0x01, 0x00000002 }, + { 0x00063b, 2, 0x01, 0x00000001 }, + { 0x00063d, 1, 0x01, 0x00000002 }, + { 0x00063e, 1, 0x01, 0x00000001 }, + { 0x0008b8, 8, 0x01, 0x00000001 }, + { 0x000900, 8, 0x01, 0x00000001 }, + { 0x000908, 8, 0x01, 0x00000002 }, + { 0x000910, 16, 0x01, 0x00000001 }, + { 0x000920, 8, 0x01, 0x00000002 }, + { 0x000928, 8, 0x01, 0x00000001 }, + { 0x000662, 1, 0x01, 0x00000001 }, + { 0x000648, 9, 0x01, 0x00000001 }, + { 0x000674, 1, 0x01, 0x00000001 }, + { 0x000658, 1, 0x01, 0x0000000f }, + { 0x0007ff, 1, 0x01, 0x0000000a }, + { 0x00066a, 1, 0x01, 0x40000000 }, + { 0x00066b, 1, 0x01, 0x10000000 }, + { 0x00066c, 2, 0x01, 0xffff0000 }, + { 0x0007af, 2, 0x01, 0x00000008 }, + { 0x0007f6, 1, 0x01, 0x00000001 }, + { 0x0006b2, 1, 0x01, 0x00000055 }, + { 0x0007ad, 1, 0x01, 0x00000003 }, + { 0x000971, 1, 0x01, 0x00000008 }, + { 0x000972, 1, 0x01, 0x00000040 }, + { 0x000973, 1, 0x01, 0x0000012c }, + { 0x00097c, 1, 0x01, 0x00000040 }, + { 0x000975, 1, 0x01, 0x00000020 }, + { 0x000976, 1, 0x01, 0x00000001 }, + { 0x000977, 1, 0x01, 0x00000020 }, + { 0x000978, 1, 0x01, 0x00000001 }, + { 0x000957, 1, 0x01, 0x00000003 }, + { 0x00095e, 1, 0x01, 0x20164010 }, + { 0x00095f, 1, 0x01, 0x00000020 }, + { 0x000a0d, 1, 0x01, 0x00000006 }, + { 0x00097d, 1, 0x01, 0x0000000c }, + { 0x000683, 1, 0x01, 0x00000006 }, + { 0x000687, 1, 0x01, 0x003fffff }, + { 0x0006a0, 1, 0x01, 0x00000005 }, + { 0x000840, 1, 0x01, 0x00400008 }, + { 0x000841, 1, 0x01, 0x08000080 }, + { 0x000842, 1, 0x01, 0x00400008 }, + { 0x000843, 1, 0x01, 0x08000080 }, + { 0x000818, 8, 0x01, 0x00000000 }, + { 0x000848, 16, 0x01, 0x00000000 }, + { 0x000738, 1, 0x01, 0x00000000 }, + { 0x0006aa, 1, 0x01, 0x00000001 }, + { 0x0006ab, 1, 0x01, 0x00000002 }, + { 0x0006ac, 1, 0x01, 0x00000080 }, + { 0x0006ad, 2, 0x01, 0x00000100 }, + { 0x0006b1, 1, 0x01, 0x00000011 }, + { 0x0006bb, 1, 0x01, 0x000000cf }, + { 0x0006ce, 1, 0x01, 0x2a712488 }, + { 0x000739, 1, 0x01, 0x4085c000 }, + { 0x00073a, 1, 0x01, 0x00000080 }, + { 0x000786, 1, 0x01, 0x80000100 }, + { 0x00073c, 1, 0x01, 0x00010100 }, + { 0x00073d, 1, 0x01, 0x02800000 }, + { 0x000787, 1, 0x01, 0x000000cf }, + { 0x00078c, 1, 0x01, 0x00000008 }, + { 0x000792, 1, 0x01, 0x00000001 }, + { 0x000794, 3, 0x01, 0x00000001 }, + { 0x000797, 1, 0x01, 0x000000cf }, + { 0x000836, 1, 0x01, 0x00000001 }, + { 0x00079a, 1, 0x01, 0x00000002 }, + { 0x000833, 1, 0x01, 0x04444480 }, + { 0x0007a1, 1, 0x01, 0x00000001 }, + { 0x0007a3, 3, 0x01, 0x00000001 }, + { 0x000831, 1, 0x01, 0x00000004 }, + { 0x000b07, 1, 0x01, 0x00000002 }, + { 0x000b08, 2, 0x01, 0x00000100 }, + { 0x000b0a, 1, 0x01, 0x00000001 }, + { 0x000a04, 1, 0x01, 0x000000ff }, + { 0x000a0b, 1, 0x01, 0x00000040 }, + { 0x00097f, 1, 0x01, 0x00000100 }, + { 0x000a02, 1, 0x01, 0x00000001 }, + { 0x000809, 1, 0x01, 0x00000007 }, + { 0x00c221, 1, 0x01, 0x00000040 }, + { 0x00c1b0, 8, 0x01, 0x0000000f }, + { 0x00c1b8, 1, 0x01, 0x0fac6881 }, + { 0x00c1b9, 1, 0x01, 0x00fac688 }, + { 0x00c401, 1, 0x01, 0x00000001 }, + { 0x00c402, 1, 0x01, 0x00010001 }, + { 0x00c403, 2, 0x01, 0x00000001 }, + { 0x00c40e, 1, 0x01, 0x00000020 }, + { 0x00c413, 4, 0x01, 0x88888888 }, + { 0x00c423, 1, 0x01, 0x0000ff00 }, + { 0x00c420, 1, 0x01, 0x00880101 }, + { 0x01e100, 1, 0x01, 0x00000001 }, + {} +}; + +const struct gf100_gr_pack +gm204_grctx_pack_icmd[] = { + { gm204_grctx_init_icmd_0 }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_b197_0[] = { + { 0x000800, 8, 0x40, 0x00000000 }, + { 0x000804, 8, 0x40, 0x00000000 }, + { 0x000808, 8, 0x40, 0x00000400 }, + { 0x00080c, 8, 0x40, 0x00000300 }, + { 0x000810, 1, 0x04, 0x000000cf }, + { 0x000850, 7, 0x40, 0x00000000 }, + { 0x000814, 8, 0x40, 0x00000040 }, + { 0x000818, 8, 0x40, 0x00000001 }, + { 0x00081c, 8, 0x40, 0x00000000 }, + { 0x000820, 8, 0x40, 0x00000000 }, + { 0x001c00, 16, 0x10, 0x00000000 }, + { 0x001c04, 16, 0x10, 0x00000000 }, + { 0x001c08, 16, 0x10, 0x00000000 }, + { 0x001c0c, 16, 0x10, 0x00000000 }, + { 0x001d00, 16, 0x10, 0x00000000 }, + { 0x001d04, 16, 0x10, 0x00000000 }, + { 0x001d08, 16, 0x10, 0x00000000 }, + { 0x001d0c, 16, 0x10, 0x00000000 }, + { 0x001f00, 16, 0x08, 0x00000000 }, + { 0x001f04, 16, 0x08, 0x00000000 }, + { 0x001f80, 16, 0x08, 0x00000000 }, + { 0x001f84, 16, 0x08, 0x00000000 }, + { 0x002000, 1, 0x04, 0x00000000 }, + { 0x002040, 1, 0x04, 0x00000011 }, + { 0x002080, 1, 0x04, 0x00000020 }, + { 0x0020c0, 1, 0x04, 0x00000030 }, + { 0x002100, 1, 0x04, 0x00000040 }, + { 0x002140, 1, 0x04, 0x00000051 }, + { 0x00200c, 6, 0x40, 0x00000001 }, + { 0x002010, 1, 0x04, 0x00000000 }, + { 0x002050, 1, 0x04, 0x00000000 }, + { 0x002090, 1, 0x04, 0x00000001 }, + { 0x0020d0, 1, 0x04, 0x00000002 }, + { 0x002110, 1, 0x04, 0x00000003 }, + { 0x002150, 1, 0x04, 0x00000004 }, + { 0x000380, 4, 0x20, 0x00000000 }, + { 0x000384, 4, 0x20, 0x00000000 }, + { 0x000388, 4, 0x20, 0x00000000 }, + { 0x00038c, 4, 0x20, 0x00000000 }, + { 0x000700, 4, 0x10, 0x00000000 }, + { 0x000704, 4, 0x10, 0x00000000 }, + { 0x000708, 4, 0x10, 0x00000000 }, + { 0x002800, 128, 0x04, 0x00000000 }, + { 0x000a00, 16, 0x20, 0x00000000 }, + { 0x000a04, 16, 0x20, 0x00000000 }, + { 0x000a08, 16, 0x20, 0x00000000 }, + { 0x000a0c, 16, 0x20, 0x00000000 }, + { 0x000a10, 16, 0x20, 0x00000000 }, + { 0x000a14, 16, 0x20, 0x00000000 }, + { 0x000a18, 16, 0x20, 0x00006420 }, + { 0x000a1c, 16, 0x20, 0x00000000 }, + { 0x000c00, 16, 0x10, 0x00000000 }, + { 0x000c04, 16, 0x10, 0x00000000 }, + { 0x000c08, 16, 0x10, 0x00000000 }, + { 0x000c0c, 16, 0x10, 0x3f800000 }, + { 0x000d00, 8, 0x08, 0xffff0000 }, + { 0x000d04, 8, 0x08, 0xffff0000 }, + { 0x000e00, 16, 0x10, 0x00000000 }, + { 0x000e04, 16, 0x10, 0xffff0000 }, + { 0x000e08, 16, 0x10, 0xffff0000 }, + { 0x000d40, 4, 0x08, 0x00000000 }, + { 0x000d44, 4, 0x08, 0x00000000 }, + { 0x001e00, 8, 0x20, 0x00000001 }, + { 0x001e04, 8, 0x20, 0x00000001 }, + { 0x001e08, 8, 0x20, 0x00000002 }, + { 0x001e0c, 8, 0x20, 0x00000001 }, + { 0x001e10, 8, 0x20, 0x00000001 }, + { 0x001e14, 8, 0x20, 0x00000002 }, + { 0x001e18, 8, 0x20, 0x00000001 }, + { 0x001480, 8, 0x10, 0x00000000 }, + { 0x001484, 8, 0x10, 0x00000000 }, + { 0x001488, 8, 0x10, 0x00000000 }, + { 0x003400, 128, 0x04, 0x00000000 }, + { 0x00030c, 1, 0x04, 0x00000001 }, + { 0x001944, 1, 0x04, 0x00000000 }, + { 0x001514, 1, 0x04, 0x00000000 }, + { 0x000d68, 1, 0x04, 0x0000ffff }, + { 0x00121c, 1, 0x04, 0x0fac6881 }, + { 0x000fac, 1, 0x04, 0x00000001 }, + { 0x001538, 1, 0x04, 0x00000001 }, + { 0x000fe0, 2, 0x04, 0x00000000 }, + { 0x000fe8, 1, 0x04, 0x00000014 }, + { 0x000fec, 1, 0x04, 0x00000040 }, + { 0x000ff0, 1, 0x04, 0x00000000 }, + { 0x00179c, 1, 0x04, 0x00000000 }, + { 0x001228, 1, 0x04, 0x00000400 }, + { 0x00122c, 1, 0x04, 0x00000300 }, + { 0x001230, 1, 0x04, 0x00010001 }, + { 0x0007f8, 1, 0x04, 0x00000000 }, + { 0x001208, 1, 0x04, 0x00000000 }, + { 0x0015b4, 1, 0x04, 0x00000001 }, + { 0x0015cc, 1, 0x04, 0x00000000 }, + { 0x001534, 1, 0x04, 0x00000000 }, + { 0x000754, 1, 0x04, 0x00000001 }, + { 0x000fb0, 1, 0x04, 0x00000000 }, + { 0x0015d0, 1, 0x04, 0x00000000 }, + { 0x0011e0, 4, 0x04, 0x88888888 }, + { 0x00153c, 1, 0x04, 0x00000000 }, + { 0x0016b4, 1, 0x04, 0x00000003 }, + { 0x000fa4, 1, 0x04, 0x00000001 }, + { 0x000fbc, 4, 0x04, 0x0000ffff }, + { 0x000fa8, 1, 0x04, 0x0000ffff }, + { 0x000df8, 2, 0x04, 0x00000000 }, + { 0x001948, 1, 0x04, 0x00000000 }, + { 0x001970, 1, 0x04, 0x00000001 }, + { 0x00161c, 1, 0x04, 0x000009f0 }, + { 0x000dcc, 1, 0x04, 0x00000010 }, + { 0x0015e4, 1, 0x04, 0x00000000 }, + { 0x001160, 32, 0x04, 0x25e00040 }, + { 0x001880, 32, 0x04, 0x00000000 }, + { 0x000f84, 2, 0x04, 0x00000000 }, + { 0x0017c8, 2, 0x04, 0x00000000 }, + { 0x0017d0, 1, 0x04, 0x000000ff }, + { 0x0017d4, 1, 0x04, 0xffffffff }, + { 0x0017d8, 1, 0x04, 0x00000002 }, + { 0x0017dc, 1, 0x04, 0x00000000 }, + { 0x0015f4, 2, 0x04, 0x00000000 }, + { 0x001434, 2, 0x04, 0x00000000 }, + { 0x000d74, 1, 0x04, 0x00000000 }, + { 0x0013a4, 1, 0x04, 0x00000000 }, + { 0x001318, 1, 0x04, 0x00000001 }, + { 0x001080, 2, 0x04, 0x00000000 }, + { 0x001088, 2, 0x04, 0x00000001 }, + { 0x001090, 1, 0x04, 0x00000000 }, + { 0x001094, 1, 0x04, 0x00000001 }, + { 0x001098, 1, 0x04, 0x00000000 }, + { 0x00109c, 1, 0x04, 0x00000001 }, + { 0x0010a0, 2, 0x04, 0x00000000 }, + { 0x001644, 1, 0x04, 0x00000000 }, + { 0x000748, 1, 0x04, 0x00000000 }, + { 0x000de8, 1, 0x04, 0x00000000 }, + { 0x001648, 1, 0x04, 0x00000000 }, + { 0x0012a4, 1, 0x04, 0x00000000 }, + { 0x001120, 4, 0x04, 0x00000000 }, + { 0x001118, 1, 0x04, 0x00000000 }, + { 0x00164c, 1, 0x04, 0x00000000 }, + { 0x001658, 1, 0x04, 0x00000000 }, + { 0x001910, 1, 0x04, 0x00000290 }, + { 0x001518, 1, 0x04, 0x00000000 }, + { 0x00165c, 1, 0x04, 0x00000001 }, + { 0x001520, 1, 0x04, 0x00000000 }, + { 0x001604, 1, 0x04, 0x00000000 }, + { 0x001570, 1, 0x04, 0x00000000 }, + { 0x0013b0, 2, 0x04, 0x3f800000 }, + { 0x00020c, 1, 0x04, 0x00000000 }, + { 0x001670, 1, 0x04, 0x30201000 }, + { 0x001674, 1, 0x04, 0x70605040 }, + { 0x001678, 1, 0x04, 0xb8a89888 }, + { 0x00167c, 1, 0x04, 0xf8e8d8c8 }, + { 0x00166c, 1, 0x04, 0x00000000 }, + { 0x001680, 1, 0x04, 0x00ffff00 }, + { 0x0012d0, 1, 0x04, 0x00000003 }, + { 0x00113c, 1, 0x04, 0x00000000 }, + { 0x0012d4, 1, 0x04, 0x00000002 }, + { 0x001684, 2, 0x04, 0x00000000 }, + { 0x000dac, 2, 0x04, 0x00001b02 }, + { 0x000db4, 1, 0x04, 0x00000000 }, + { 0x00168c, 1, 0x04, 0x00000000 }, + { 0x0015bc, 1, 0x04, 0x00000000 }, + { 0x00156c, 1, 0x04, 0x00000000 }, + { 0x00187c, 1, 0x04, 0x00000000 }, + { 0x001110, 1, 0x04, 0x00000001 }, + { 0x000dc0, 3, 0x04, 0x00000000 }, + { 0x000f40, 5, 0x04, 0x00000000 }, + { 0x001234, 1, 0x04, 0x00000000 }, + { 0x001690, 1, 0x04, 0x00000000 }, + { 0x000790, 5, 0x04, 0x00000000 }, + { 0x00077c, 1, 0x04, 0x00000000 }, + { 0x001000, 1, 0x04, 0x00000010 }, + { 0x0010fc, 1, 0x04, 0x00000000 }, + { 0x001290, 1, 0x04, 0x00000000 }, + { 0x000218, 1, 0x04, 0x00000010 }, + { 0x0012d8, 1, 0x04, 0x00000000 }, + { 0x0012dc, 1, 0x04, 0x00000010 }, + { 0x000d94, 1, 0x04, 0x00000001 }, + { 0x00155c, 2, 0x04, 0x00000000 }, + { 0x001564, 1, 0x04, 0x00000fff }, + { 0x001574, 2, 0x04, 0x00000000 }, + { 0x00157c, 1, 0x04, 0x000fffff }, + { 0x001354, 1, 0x04, 0x00000000 }, + { 0x001610, 1, 0x04, 0x00000012 }, + { 0x001608, 2, 0x04, 0x00000000 }, + { 0x00260c, 1, 0x04, 0x00000000 }, + { 0x0007ac, 1, 0x04, 0x00000000 }, + { 0x00162c, 1, 0x04, 0x00000003 }, + { 0x000210, 1, 0x04, 0x00000000 }, + { 0x000320, 1, 0x04, 0x00000000 }, + { 0x000324, 6, 0x04, 0x3f800000 }, + { 0x000750, 1, 0x04, 0x00000000 }, + { 0x000760, 1, 0x04, 0x39291909 }, + { 0x000764, 1, 0x04, 0x79695949 }, + { 0x000768, 1, 0x04, 0xb9a99989 }, + { 0x00076c, 1, 0x04, 0xf9e9d9c9 }, + { 0x000770, 1, 0x04, 0x30201000 }, + { 0x000774, 1, 0x04, 0x70605040 }, + { 0x000778, 1, 0x04, 0x00009080 }, + { 0x000780, 1, 0x04, 0x39291909 }, + { 0x000784, 1, 0x04, 0x79695949 }, + { 0x000788, 1, 0x04, 0xb9a99989 }, + { 0x00078c, 1, 0x04, 0xf9e9d9c9 }, + { 0x0007d0, 1, 0x04, 0x30201000 }, + { 0x0007d4, 1, 0x04, 0x70605040 }, + { 0x0007d8, 1, 0x04, 0x00009080 }, + { 0x001004, 1, 0x04, 0x00000000 }, + { 0x001240, 8, 0x04, 0x00000000 }, + { 0x00037c, 1, 0x04, 0x00000001 }, + { 0x000740, 1, 0x04, 0x00000000 }, + { 0x001148, 1, 0x04, 0x00000000 }, + { 0x000fb4, 1, 0x04, 0x00000000 }, + { 0x000fb8, 1, 0x04, 0x00000002 }, + { 0x001130, 1, 0x04, 0x00000002 }, + { 0x000fd4, 2, 0x04, 0x00000000 }, + { 0x001030, 1, 0x04, 0x20181008 }, + { 0x001034, 1, 0x04, 0x40383028 }, + { 0x001038, 1, 0x04, 0x60585048 }, + { 0x00103c, 1, 0x04, 0x80787068 }, + { 0x000744, 1, 0x04, 0x00000000 }, + { 0x002600, 1, 0x04, 0x00000000 }, + { 0x001918, 1, 0x04, 0x00000000 }, + { 0x00191c, 1, 0x04, 0x00000900 }, + { 0x001920, 1, 0x04, 0x00000405 }, + { 0x001308, 1, 0x04, 0x00000001 }, + { 0x001924, 1, 0x04, 0x00000000 }, + { 0x0013ac, 1, 0x04, 0x00000000 }, + { 0x00192c, 1, 0x04, 0x00000001 }, + { 0x00193c, 1, 0x04, 0x00002c1c }, + { 0x000d7c, 1, 0x04, 0x00000000 }, + { 0x000f8c, 1, 0x04, 0x00000000 }, + { 0x0002c0, 1, 0x04, 0x00000001 }, + { 0x001510, 1, 0x04, 0x00000000 }, + { 0x001940, 1, 0x04, 0x00000000 }, + { 0x000ff4, 2, 0x04, 0x00000000 }, + { 0x00194c, 2, 0x04, 0x00000000 }, + { 0x001968, 1, 0x04, 0x00000000 }, + { 0x001590, 1, 0x04, 0x0000003f }, + { 0x0007e8, 4, 0x04, 0x00000000 }, + { 0x00196c, 1, 0x04, 0x00000011 }, + { 0x0002e4, 1, 0x04, 0x0000b001 }, + { 0x00036c, 2, 0x04, 0x00000000 }, + { 0x00197c, 1, 0x04, 0x00000000 }, + { 0x000fcc, 2, 0x04, 0x00000000 }, + { 0x0002d8, 1, 0x04, 0x00000040 }, + { 0x001980, 1, 0x04, 0x00000080 }, + { 0x001504, 1, 0x04, 0x00000080 }, + { 0x001984, 1, 0x04, 0x00000000 }, + { 0x000f60, 1, 0x04, 0x00000000 }, + { 0x000f64, 1, 0x04, 0x00400040 }, + { 0x000f68, 1, 0x04, 0x00002212 }, + { 0x000f6c, 1, 0x04, 0x08080203 }, + { 0x001108, 1, 0x04, 0x00000008 }, + { 0x000f70, 1, 0x04, 0x00080001 }, + { 0x000ffc, 1, 0x04, 0x00000000 }, + { 0x001134, 1, 0x04, 0x00000000 }, + { 0x000f1c, 1, 0x04, 0x00000000 }, + { 0x0011f8, 1, 0x04, 0x00000000 }, + { 0x001138, 1, 0x04, 0x00000001 }, + { 0x000300, 1, 0x04, 0x00000001 }, + { 0x0013a8, 1, 0x04, 0x00000000 }, + { 0x001224, 1, 0x04, 0x00000000 }, + { 0x0012ec, 1, 0x04, 0x00000000 }, + { 0x001310, 1, 0x04, 0x00000000 }, + { 0x001314, 1, 0x04, 0x00000001 }, + { 0x001380, 1, 0x04, 0x00000000 }, + { 0x001384, 4, 0x04, 0x00000001 }, + { 0x001394, 1, 0x04, 0x00000000 }, + { 0x00139c, 1, 0x04, 0x00000000 }, + { 0x001398, 1, 0x04, 0x00000000 }, + { 0x001594, 1, 0x04, 0x00000000 }, + { 0x001598, 4, 0x04, 0x00000001 }, + { 0x000f54, 3, 0x04, 0x00000000 }, + { 0x0019bc, 1, 0x04, 0x00000000 }, + { 0x000f9c, 2, 0x04, 0x00000000 }, + { 0x0012cc, 1, 0x04, 0x00000000 }, + { 0x0012e8, 1, 0x04, 0x00000000 }, + { 0x00130c, 1, 0x04, 0x00000001 }, + { 0x001360, 8, 0x04, 0x00000000 }, + { 0x00133c, 2, 0x04, 0x00000001 }, + { 0x001344, 1, 0x04, 0x00000002 }, + { 0x001348, 2, 0x04, 0x00000001 }, + { 0x001350, 1, 0x04, 0x00000002 }, + { 0x001358, 1, 0x04, 0x00000001 }, + { 0x0012e4, 1, 0x04, 0x00000000 }, + { 0x00131c, 4, 0x04, 0x00000000 }, + { 0x0019c0, 1, 0x04, 0x00000000 }, + { 0x001140, 1, 0x04, 0x00000000 }, + { 0x000dd0, 1, 0x04, 0x00000000 }, + { 0x000dd4, 1, 0x04, 0x00000001 }, + { 0x0002f4, 1, 0x04, 0x00000000 }, + { 0x0019c4, 1, 0x04, 0x00000000 }, + { 0x0019c8, 1, 0x04, 0x00001500 }, + { 0x00135c, 1, 0x04, 0x00000000 }, + { 0x000f90, 1, 0x04, 0x00000000 }, + { 0x0019e0, 8, 0x04, 0x00000001 }, + { 0x0019cc, 1, 0x04, 0x00000001 }, + { 0x00111c, 1, 0x04, 0x00000001 }, + { 0x0015b8, 1, 0x04, 0x00000000 }, + { 0x001a00, 1, 0x04, 0x00001111 }, + { 0x001a04, 7, 0x04, 0x00000000 }, + { 0x000d6c, 2, 0x04, 0xffff0000 }, + { 0x0010f8, 1, 0x04, 0x00001010 }, + { 0x000d80, 5, 0x04, 0x00000000 }, + { 0x000da0, 1, 0x04, 0x00000000 }, + { 0x0007a4, 2, 0x04, 0x00000000 }, + { 0x001508, 1, 0x04, 0x80000000 }, + { 0x00150c, 1, 0x04, 0x40000000 }, + { 0x001668, 1, 0x04, 0x00000000 }, + { 0x000318, 2, 0x04, 0x00000008 }, + { 0x000d9c, 1, 0x04, 0x00000001 }, + { 0x000f14, 1, 0x04, 0x00000000 }, + { 0x000374, 1, 0x04, 0x00000000 }, + { 0x000378, 1, 0x04, 0x0000000c }, + { 0x0007dc, 1, 0x04, 0x00000000 }, + { 0x00074c, 1, 0x04, 0x00000055 }, + { 0x001420, 1, 0x04, 0x00000003 }, + { 0x001008, 1, 0x04, 0x00000008 }, + { 0x00100c, 1, 0x04, 0x00000040 }, + { 0x001010, 1, 0x04, 0x0000012c }, + { 0x000d60, 1, 0x04, 0x00000040 }, + { 0x001018, 1, 0x04, 0x00000020 }, + { 0x00101c, 1, 0x04, 0x00000001 }, + { 0x001020, 1, 0x04, 0x00000020 }, + { 0x001024, 1, 0x04, 0x00000001 }, + { 0x001444, 3, 0x04, 0x00000000 }, + { 0x000360, 1, 0x04, 0x20164010 }, + { 0x000364, 1, 0x04, 0x00000020 }, + { 0x000368, 1, 0x04, 0x00000000 }, + { 0x000da8, 1, 0x04, 0x00000030 }, + { 0x000de4, 1, 0x04, 0x00000000 }, + { 0x000204, 1, 0x04, 0x00000006 }, + { 0x0002d0, 1, 0x04, 0x003fffff }, + { 0x001220, 1, 0x04, 0x00000005 }, + { 0x000fdc, 1, 0x04, 0x00000000 }, + { 0x000f98, 1, 0x04, 0x00400008 }, + { 0x001284, 1, 0x04, 0x08000080 }, + { 0x001450, 1, 0x04, 0x00400008 }, + { 0x001454, 1, 0x04, 0x08000080 }, + { 0x000214, 1, 0x04, 0x00000000 }, + {} +}; + +const struct gf100_gr_pack +gm204_grctx_pack_mthd[] = { + { gm204_grctx_init_b197_0, 0xb197 }, + { gf100_grctx_init_902d_0, 0x902d }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_fe_0[] = { + { 0x404004, 8, 0x04, 0x00000000 }, + { 0x404024, 1, 0x04, 0x0000e000 }, + { 0x404028, 8, 0x04, 0x00000000 }, + { 0x4040a8, 8, 0x04, 0x00000000 }, + { 0x4040c8, 1, 0x04, 0xf801008f }, + { 0x4040d0, 6, 0x04, 0x00000000 }, + { 0x4040f8, 1, 0x04, 0x00000000 }, + { 0x404100, 10, 0x04, 0x00000000 }, + { 0x404130, 2, 0x04, 0x00000000 }, + { 0x404150, 1, 0x04, 0x0000002e }, + { 0x404154, 2, 0x04, 0x00000800 }, + { 0x404164, 1, 0x04, 0x00000045 }, + { 0x40417c, 2, 0x04, 0x00000000 }, + { 0x404194, 1, 0x04, 0x33000700 }, + { 0x4041a0, 4, 0x04, 0x00000000 }, + { 0x4041c4, 2, 0x04, 0x00000000 }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_ds_0[] = { + { 0x405800, 1, 0x04, 0x8f8001bf }, + { 0x405830, 1, 0x04, 0x04001000 }, + { 0x405834, 1, 0x04, 0x08000000 }, + { 0x405838, 1, 0x04, 0x00010000 }, + { 0x405854, 1, 0x04, 0x00000000 }, + { 0x405870, 4, 0x04, 0x00000001 }, + { 0x405a00, 2, 0x04, 0x00000000 }, + { 0x405a18, 1, 0x04, 0x00000000 }, + { 0x405a1c, 1, 0x04, 0x000000ff }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_cwd_0[] = { + { 0x405b00, 1, 0x04, 0x00000000 }, + { 0x405b10, 1, 0x04, 0x00001000 }, + { 0x405b20, 1, 0x04, 0x04000000 }, + { 0x405b60, 6, 0x04, 0x00000000 }, + { 0x405ba0, 6, 0x04, 0x00000000 }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_pd_0[] = { + { 0x406020, 1, 0x04, 0x17410001 }, + { 0x406028, 4, 0x04, 0x00000001 }, + { 0x4064a8, 1, 0x04, 0x00000000 }, + { 0x4064ac, 1, 0x04, 0x00003fff }, + { 0x4064b0, 3, 0x04, 0x00000000 }, + { 0x4064c0, 1, 0x04, 0x80400280 }, + { 0x4064c4, 1, 0x04, 0x0400ffff }, + { 0x4064c8, 1, 0x04, 0x01800780 }, + { 0x4064cc, 9, 0x04, 0x00000000 }, + { 0x4064fc, 1, 0x04, 0x0000022a }, + { 0x406500, 1, 0x04, 0x00000000 }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_be_0[] = { + { 0x408800, 1, 0x04, 0x32882a3c }, + { 0x408804, 1, 0x04, 0x00000040 }, + { 0x408808, 1, 0x04, 0x1003e005 }, + { 0x408840, 1, 0x04, 0x00000e0b }, + { 0x408900, 1, 0x04, 0xb080b801 }, + { 0x408904, 1, 0x04, 0x63038001 }, + { 0x408908, 1, 0x04, 0x12c8502f }, + { 0x408980, 1, 0x04, 0x0000011d }, + {} +}; + +const struct gf100_gr_pack +gm204_grctx_pack_hub[] = { + { gf100_grctx_init_main_0 }, + { gm204_grctx_init_fe_0 }, + { gk110_grctx_init_pri_0 }, + { gk104_grctx_init_memfmt_0 }, + { gm204_grctx_init_ds_0 }, + { gm204_grctx_init_cwd_0 }, + { gm204_grctx_init_pd_0 }, + { gk208_grctx_init_rstr2d_0 }, + { gk104_grctx_init_scc_0 }, + { gm204_grctx_init_be_0 }, + {} +}; + +const struct gf100_gr_init +gm204_grctx_init_prop_0[] = { + { 0x418400, 1, 0x04, 0x38e01e00 }, + { 0x418404, 1, 0x04, 0x70001fff }, + { 0x41840c, 1, 0x04, 0x20001008 }, + { 0x418410, 2, 0x04, 0x0fff0fff }, + { 0x418418, 1, 0x04, 0x07ff07ff }, + { 0x41841c, 1, 0x04, 0x3feffbff }, + { 0x418450, 6, 0x04, 0x00000000 }, + { 0x418468, 1, 0x04, 0x00000001 }, + { 0x41846c, 2, 0x04, 0x00000000 }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_gpc_unk_1[] = { + { 0x418600, 1, 0x04, 0x0000007f }, + { 0x418684, 1, 0x04, 0x0000001f }, + { 0x418700, 1, 0x04, 0x00000002 }, + { 0x418704, 1, 0x04, 0x00000080 }, + { 0x418708, 1, 0x04, 0x40000000 }, + { 0x41870c, 2, 0x04, 0x00000000 }, + { 0x418728, 1, 0x04, 0x00010000 }, + {} +}; + +const struct gf100_gr_init +gm204_grctx_init_setup_0[] = { + { 0x418800, 1, 0x04, 0x7006863a }, + { 0x418808, 1, 0x04, 0x00000000 }, + { 0x418810, 1, 0x04, 0x00000000 }, + { 0x418828, 1, 0x04, 0x00000044 }, + { 0x418830, 1, 0x04, 0x10000001 }, + { 0x4188d8, 1, 0x04, 0x00000008 }, + { 0x4188e0, 1, 0x04, 0x01000000 }, + { 0x4188e8, 5, 0x04, 0x00000000 }, + { 0x4188fc, 1, 0x04, 0x20100058 }, + {} +}; + +const struct gf100_gr_init +gm204_grctx_init_gpm_0[] = { + { 0x418c10, 8, 0x04, 0x00000000 }, + { 0x418c40, 1, 0x04, 0xffffffff }, + { 0x418c6c, 1, 0x04, 0x00000001 }, + { 0x418c80, 1, 0x04, 0x20200000 }, + {} +}; + +const struct gf100_gr_init +gm204_grctx_init_gpc_unk_2[] = { + { 0x418e00, 1, 0x04, 0x90040000 }, + { 0x418e24, 1, 0x04, 0x00000000 }, + { 0x418e28, 1, 0x04, 0x00000030 }, + { 0x418e2c, 1, 0x04, 0x00000100 }, + { 0x418e30, 3, 0x04, 0x00000000 }, + { 0x418e40, 22, 0x04, 0x00000000 }, + { 0x418ea0, 12, 0x04, 0x00000000 }, + {} +}; + +static const struct gf100_gr_pack +gm204_grctx_pack_gpc[] = { + { gm107_grctx_init_gpc_unk_0 }, + { gm204_grctx_init_prop_0 }, + { gm204_grctx_init_gpc_unk_1 }, + { gm204_grctx_init_setup_0 }, + { gf100_grctx_init_zcull_0 }, + { gk208_grctx_init_crstr_0 }, + { gm204_grctx_init_gpm_0 }, + { gm204_grctx_init_gpc_unk_2 }, + { gf100_grctx_init_gcc_0 }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_pe_0[] = { + { 0x419848, 1, 0x04, 0x00000000 }, + { 0x419864, 1, 0x04, 0x00000029 }, + { 0x419888, 1, 0x04, 0x00000000 }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_tex_0[] = { + { 0x419a00, 1, 0x04, 0x000100f0 }, + { 0x419a04, 1, 0x04, 0x00000005 }, + { 0x419a08, 1, 0x04, 0x00000621 }, + { 0x419a0c, 1, 0x04, 0x00320000 }, + { 0x419a10, 1, 0x04, 0x00000000 }, + { 0x419a14, 1, 0x04, 0x00000200 }, + { 0x419a1c, 1, 0x04, 0x0010c000 }, + { 0x419a20, 1, 0x04, 0x20008a00 }, + { 0x419a30, 1, 0x04, 0x00000001 }, + { 0x419a3c, 1, 0x04, 0x0000181e }, + { 0x419ac4, 1, 0x04, 0x00000000 }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_mpc_0[] = { + { 0x419c00, 1, 0x04, 0x0000009a }, + { 0x419c04, 1, 0x04, 0x80000bd6 }, + { 0x419c08, 1, 0x04, 0x00000002 }, + { 0x419c20, 1, 0x04, 0x00000000 }, + { 0x419c24, 1, 0x04, 0x00084210 }, + { 0x419c28, 1, 0x04, 0x3efbefbe }, + { 0x419c2c, 1, 0x04, 0x00000000 }, + { 0x419c34, 1, 0x04, 0x71ff1ff3 }, + { 0x419c3c, 1, 0x04, 0x00001919 }, + { 0x419c50, 1, 0x04, 0x00000005 }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_l1c_0[] = { + { 0x419c84, 1, 0x04, 0x0000003e }, + { 0x419c90, 1, 0x04, 0x0000000a }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_sm_0[] = { + { 0x419e04, 3, 0x04, 0x00000000 }, + { 0x419e10, 1, 0x04, 0x00001c02 }, + { 0x419e44, 1, 0x04, 0x00d3eff2 }, + { 0x419e48, 1, 0x04, 0x00000000 }, + { 0x419e4c, 1, 0x04, 0x0000007f }, + { 0x419e50, 1, 0x04, 0x00000000 }, + { 0x419e58, 6, 0x04, 0x00000000 }, + { 0x419e74, 10, 0x04, 0x00000000 }, + { 0x419eac, 1, 0x04, 0x0001cf8b }, + { 0x419eb0, 1, 0x04, 0x00030300 }, + { 0x419eb8, 1, 0x04, 0x40000000 }, + { 0x419ef0, 24, 0x04, 0x00000000 }, + { 0x419f68, 2, 0x04, 0x00000000 }, + { 0x419f70, 1, 0x04, 0x00000020 }, + { 0x419f78, 1, 0x04, 0x00010beb }, + { 0x419f7c, 1, 0x04, 0x00000000 }, + {} +}; + +const struct gf100_gr_pack +gm204_grctx_pack_tpc[] = { + { gm204_grctx_init_pe_0 }, + { gm204_grctx_init_tex_0 }, + { gm204_grctx_init_mpc_0 }, + { gm204_grctx_init_l1c_0 }, + { gm204_grctx_init_sm_0 }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_pes_0[] = { + { 0x41be24, 1, 0x04, 0x0000000e }, + {} +}; + +static const struct gf100_gr_init +gm204_grctx_init_cbm_0[] = { + { 0x41bec0, 1, 0x04, 0x00000000 }, + { 0x41bec4, 1, 0x04, 0x01030000 }, + { 0x41bee4, 1, 0x04, 0x00000000 }, + { 0x41bef0, 1, 0x04, 0x000003ff }, + { 0x41bef4, 2, 0x04, 0x00000000 }, + {} +}; + +const struct gf100_gr_pack +gm204_grctx_pack_ppc[] = { + { gm204_grctx_init_pes_0 }, + { gm204_grctx_init_cbm_0 }, + { gm107_grctx_init_wwdx_0 }, + {} +}; + +/******************************************************************************* + * PGRAPH context implementation + ******************************************************************************/ + +static void +gm204_grctx_generate_tpcid(struct gf100_gr_priv *priv) +{ + int gpc, tpc, id; + + for (tpc = 0, id = 0; tpc < 4; tpc++) { + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + if (tpc < priv->tpc_nr[gpc]) { + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x698), id); + nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x088), id); + id++; + } + } + } +} + +static void +gm204_grctx_generate_rop_active_fbps(struct gf100_gr_priv *priv) +{ + const u32 fbp_count = nv_rd32(priv, 0x12006c); + nv_mask(priv, 0x408850, 0x0000000f, fbp_count); /* zrop */ + nv_mask(priv, 0x408958, 0x0000000f, fbp_count); /* crop */ +} + +static void +gm204_grctx_generate_405b60(struct gf100_gr_priv *priv) +{ + const u32 dist_nr = DIV_ROUND_UP(priv->tpc_total, 4); + u32 dist[TPC_MAX] = {}; + u32 gpcs[GPC_MAX] = {}; + u8 tpcnr[GPC_MAX]; + int tpc, gpc, i; + + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + + /* won't result in the same distribution as the binary driver where + * some of the gpcs have more tpcs than others, but this shall do + * for the moment. the code for earlier gpus has this issue too. + */ + for (gpc = -1, i = 0; i < priv->tpc_total; i++) { + do { + gpc = (gpc + 1) % priv->gpc_nr; + } while(!tpcnr[gpc]); + tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; + + dist[i / 4] |= ((gpc << 4) | tpc) << ((i % 4) * 8); + gpcs[gpc] |= i << (tpc * 8); + } + + for (i = 0; i < dist_nr; i++) + nv_wr32(priv, 0x405b60 + (i * 4), dist[i]); + for (i = 0; i < priv->gpc_nr; i++) + nv_wr32(priv, 0x405ba0 + (i * 4), gpcs[i]); +} + +void +gm204_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info) +{ + struct gf100_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass; + u32 tmp; + int i; + + gf100_gr_mmio(priv, oclass->hub); + gf100_gr_mmio(priv, oclass->gpc); + gf100_gr_mmio(priv, oclass->zcull); + gf100_gr_mmio(priv, oclass->tpc); + gf100_gr_mmio(priv, oclass->ppc); + + nv_wr32(priv, 0x404154, 0x00000000); + + oclass->bundle(info); + oclass->pagepool(info); + oclass->attrib(info); + oclass->unkn(priv); + + gm204_grctx_generate_tpcid(priv); + gf100_grctx_generate_r406028(priv); + gk104_grctx_generate_r418bb8(priv); + + for (i = 0; i < 8; i++) + nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000); + nv_wr32(priv, 0x406500, 0x00000000); + + nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr); + + gm204_grctx_generate_rop_active_fbps(priv); + + for (tmp = 0, i = 0; i < priv->gpc_nr; i++) + tmp |= ((1 << priv->tpc_nr[i]) - 1) << (i * 4); + nv_wr32(priv, 0x4041c4, tmp); + + gm204_grctx_generate_405b60(priv); + + gf100_gr_icmd(priv, oclass->icmd); + nv_wr32(priv, 0x404154, 0x00000800); + gf100_gr_mthd(priv, oclass->mthd); + + nv_mask(priv, 0x418e94, 0xffffffff, 0xc4230000); + nv_mask(priv, 0x418e4c, 0xffffffff, 0x70000000); +} + +struct nvkm_oclass * +gm204_grctx_oclass = &(struct gf100_grctx_oclass) { + .base.handle = NV_ENGCTX(GR, 0x24), + .base.ofuncs = &(struct nvkm_ofuncs) { + .ctor = gf100_gr_context_ctor, + .dtor = gf100_gr_context_dtor, + .init = _nvkm_gr_context_init, + .fini = _nvkm_gr_context_fini, + .rd32 = _nvkm_gr_context_rd32, + .wr32 = _nvkm_gr_context_wr32, + }, + .main = gm204_grctx_generate_main, + .unkn = gk104_grctx_generate_unkn, + .hub = gm204_grctx_pack_hub, + .gpc = gm204_grctx_pack_gpc, + .zcull = gf100_grctx_pack_zcull, + .tpc = gm204_grctx_pack_tpc, + .ppc = gm204_grctx_pack_ppc, + .icmd = gm204_grctx_pack_icmd, + .mthd = gm204_grctx_pack_mthd, + .bundle = gm107_grctx_generate_bundle, + .bundle_size = 0x3000, + .bundle_min_gpm_fifo_depth = 0x180, + .bundle_token_limit = 0x780, + .pagepool = gm107_grctx_generate_pagepool, + .pagepool_size = 0x20000, + .attrib = gm107_grctx_generate_attrib, + .attrib_nr_max = 0x600, + .attrib_nr = 0x400, + .alpha_nr_max = 0x1800, + .alpha_nr = 0x1000, +}.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm206.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm206.c new file mode 100644 index 000000000000..91ec41617943 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm206.c @@ -0,0 +1,83 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * 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. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "ctxgf100.h" + +static const struct gf100_gr_init +gm206_grctx_init_gpc_unk_1[] = { + { 0x418600, 1, 0x04, 0x0000007f }, + { 0x418684, 1, 0x04, 0x0000001f }, + { 0x418700, 1, 0x04, 0x00000002 }, + { 0x418704, 1, 0x04, 0x00000080 }, + { 0x418708, 1, 0x04, 0x40000000 }, + { 0x41870c, 2, 0x04, 0x00000000 }, + { 0x418728, 1, 0x04, 0x00300020 }, + {} +}; + +static const struct gf100_gr_pack +gm206_grctx_pack_gpc[] = { + { gm107_grctx_init_gpc_unk_0 }, + { gm204_grctx_init_prop_0 }, + { gm206_grctx_init_gpc_unk_1 }, + { gm204_grctx_init_setup_0 }, + { gf100_grctx_init_zcull_0 }, + { gk208_grctx_init_crstr_0 }, + { gm204_grctx_init_gpm_0 }, + { gm204_grctx_init_gpc_unk_2 }, + { gf100_grctx_init_gcc_0 }, + {} +}; + +struct nvkm_oclass * +gm206_grctx_oclass = &(struct gf100_grctx_oclass) { + .base.handle = NV_ENGCTX(GR, 0x26), + .base.ofuncs = &(struct nvkm_ofuncs) { + .ctor = gf100_gr_context_ctor, + .dtor = gf100_gr_context_dtor, + .init = _nvkm_gr_context_init, + .fini = _nvkm_gr_context_fini, + .rd32 = _nvkm_gr_context_rd32, + .wr32 = _nvkm_gr_context_wr32, + }, + .main = gm204_grctx_generate_main, + .unkn = gk104_grctx_generate_unkn, + .hub = gm204_grctx_pack_hub, + .gpc = gm206_grctx_pack_gpc, + .zcull = gf100_grctx_pack_zcull, + .tpc = gm204_grctx_pack_tpc, + .ppc = gm204_grctx_pack_ppc, + .icmd = gm204_grctx_pack_icmd, + .mthd = gm204_grctx_pack_mthd, + .bundle = gm107_grctx_generate_bundle, + .bundle_size = 0x3000, + .bundle_min_gpm_fifo_depth = 0x180, + .bundle_token_limit = 0x780, + .pagepool = gm107_grctx_generate_pagepool, + .pagepool_size = 0x20000, + .attrib = gm107_grctx_generate_attrib, + .attrib_nr_max = 0x600, + .attrib_nr = 0x400, + .alpha_nr_max = 0x1800, + .alpha_nr = 0x1000, +}.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc index eaed1599b90f..194afe910d21 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc @@ -52,6 +52,12 @@ mmio_list_base: #endif #ifdef INCLUDE_CODE +#define gpc_wr32(addr,reg) /* +*/ mov b32 $r15 reg /* +*/ imm32($r14, addr) /* +*/ or $r14 NV_PGRAPH_GPCX_GPCCS_MMIO_CTRL_BASE_ENABLE /* +*/ call(nv_wr32) + // reports an exception to the host // // In: $r15 error code (see os.h) @@ -64,6 +70,43 @@ error: pop $r14 ret +#if CHIPSET >= GM107 +tpc_strand_wait: + push $r9 + trace_set(T_STRTPC) + tpc_strand_busy: + nv_iord($r9, NV_PGRAPH_GPCX_GPCCS_TPC_STATUS, 0) + bra b32 $r9 0x0 ne #tpc_strand_busy + trace_clr(T_STRTPC) + pop $r9 + ret + +#define tpc_strand_wait() call(tpc_strand_wait) +#define tpc_strand_enable() /* +*/ mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_ENABLE /* +*/ gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15) /* +*/ tpc_strand_wait() +#define tpc_strand_disable() /* +*/ mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_DISABLE /* +*/ gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15) /* +*/ tpc_strand_wait() +#define tpc_strand_seek(p) /* +*/ mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_INDEX_ALL /* +*/ gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_INDEX, $r15) /* +*/ mov $r15 p /* +*/ gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_SELECT, $r15) /* +*/ mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_SEEK /* +*/ tpc_strand_wait() +#define tpc_strand_info(m) /* +*/ gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15) /* +*/ mov $r15 m /* +*/ gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_DATA, $r15) /* +*/ mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_GET_INFO /* +*/ gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15) /* +*/ tpc_strand_wait() +#endif + + // GPC fuc initialisation, executed by triggering ucode start, will // fall through to main loop after completion. // @@ -101,7 +144,7 @@ init: // enable interrupts bset $flags ie0 - // figure out which GPC we are, and how many TPCs we have + // how many TPCs do we have? nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_UNITS, 0) mov $r3 1 and $r2 0x1f @@ -109,8 +152,12 @@ init: sub b32 $r3 1 st b32 D[$r0 + #tpc_count] $r2 st b32 D[$r0 + #tpc_mask] $r3 + + // determine which GPC we are, setup (optional) mmio access offset nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_MYINDEX, 0) st b32 D[$r0 + #gpc_id] $r2 + shl b32 $r2 15 + nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMIO_BASE, 0, $r2) #if NV_PGRAPH_GPCX_UNK__SIZE > 0 // figure out which, and how many, UNKs are actually present @@ -186,8 +233,56 @@ init: // calculate size of strand context data mov b32 $r15 $r2 call(strand_ctx_init) + add b32 $r2 $r15 add b32 $r3 $r15 +#if CHIPSET >= GM107 + // calculate size of tpc strand context data + mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_INDEX_ALL + gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_INDEX, $r15) + tpc_strand_enable(); + tpc_strand_seek(0); + tpc_strand_info(-1); + + ld b32 $r4 D[$r0 + #tpc_count] + mov $r5 NV_PGRAPH_GPC0_TPC0 + ld b32 $r6 D[$r0 + #gpc_id] + shl b32 $r6 15 + add b32 $r5 $r6 + tpc_strand_init_tpc_loop: + add b32 $r14 $r5 NV_TPC_STRAND_CNT + call(nv_rd32) + mov b32 $r6 $r15 + clear b32 $r7 + tpc_strand_init_idx_loop: + add b32 $r14 $r5 NV_TPC_STRAND_INDEX + mov b32 $r15 $r7 + call(nv_wr32) + add b32 $r14 $r5 NV_TPC_STRAND_SAVE_SWBASE + shr b32 $r15 $r2 8 + call(nv_wr32) + add b32 $r14 $r5 NV_TPC_STRAND_LOAD_SWBASE + shr b32 $r15 $r2 8 + call(nv_wr32) + add b32 $r14 $r5 NV_TPC_STRAND_WORDS + call(nv_rd32) + shr b32 $r15 6 + add b32 $r15 1 + shl b32 $r15 8 + add b32 $r2 $r15 + add b32 $r3 $r15 + add b32 $r7 1 + sub b32 $r6 1 + bra nz #tpc_strand_init_idx_loop + add b32 $r5 NV_PGRAPH_GPC0_TPC0__SIZE + sub b32 $r4 1 + bra nz #tpc_strand_init_tpc_loop + + mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_INDEX_ALL + gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_INDEX, $r15) + tpc_strand_disable(); +#endif + // save context size, and tell HUB we're done nv_iowr(NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(1), 0, $r3) clear b32 $r2 @@ -306,6 +401,9 @@ ctx_redswitch: ctx_xfer: // set context base address nv_iowr(NV_PGRAPH_GPCX_GPCCS_MEM_BASE, 0, $r15) +#if CHIPSET >= GM107 + gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_MEM_BASE, $r15) +#endif bra not $p1 #ctx_xfer_not_load call(ctx_redswitch) ctx_xfer_not_load: @@ -318,6 +416,14 @@ ctx_xfer: add b32 $r2 NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_CMD, 0x3f, $r2) +#if CHIPSET >= GM107 + tpc_strand_enable(); + tpc_strand_seek(0); + xbit $r15 $flags $p1 // SAVE/LOAD + add b32 $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_SAVE + gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15) +#endif + // mmio context xbit $r10 $flags $p1 // direction or $r10 2 // first @@ -362,6 +468,9 @@ ctx_xfer: // wait for strands to finish call(strand_wait) +#if CHIPSET >= GM107 + tpc_strand_wait() +#endif // if load, or a save without a load following, do some // unknown stuff that's done after finishing a block of @@ -370,6 +479,9 @@ ctx_xfer: bra not $p2 #ctx_xfer_done ctx_xfer_post: call(strand_post) +#if CHIPSET >= GM107 + tpc_strand_disable() +#endif // mark completion in HUB's barrier ctx_xfer_done: diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h index ea32f56c0a92..231f696d1e0a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h @@ -310,7 +310,7 @@ uint32_t gf100_grgpc_code[] = { 0x03f01200, 0x0002d000, 0x17f104bd, - 0x10fe04e6, + 0x10fe04f8, 0x0007f100, 0x0003f007, 0xbd0000d0, @@ -329,157 +329,157 @@ uint32_t gf100_grgpc_code[] = { 0xf0860027, 0x22cf0123, 0x04028000, - 0x010027f1, - 0xcf0223f0, - 0x34bd0022, - 0xf1082595, - 0xf0c00007, - 0x05d00103, + 0xf10f24b6, + 0xf0c90007, + 0x02d00103, 0xf104bd00, - 0xf0c10007, - 0x05d00103, - 0x9804bd00, - 0x0f98000e, - 0x5021f501, - 0x002fbb01, - 0x98003fbb, - 0x0f98010e, - 0x5021f502, - 0x050e9801, - 0xbb00effd, - 0x3ebb002e, - 0x0235b600, - 0xd30007f1, - 0xd00103f0, - 0x04bd0003, - 0xb60825b6, - 0x20b60635, - 0x0130b601, - 0xb60824b6, - 0x2fb90834, - 0xd321f502, - 0x003fbb02, - 0x010007f1, + 0xf0010027, + 0x22cf0223, + 0x9534bd00, + 0x07f10825, + 0x03f0c000, + 0x0005d001, + 0x07f104bd, + 0x03f0c100, + 0x0005d001, + 0x0e9804bd, + 0x010f9800, + 0x015021f5, + 0xbb002fbb, + 0x0e98003f, + 0x020f9801, + 0x015021f5, + 0xfd050e98, + 0x2ebb00ef, + 0x003ebb00, + 0xf10235b6, + 0xf0d30007, + 0x03d00103, + 0xb604bd00, + 0x35b60825, + 0x0120b606, + 0xb60130b6, + 0x34b60824, + 0x022fb908, + 0x02d321f5, + 0xbb002fbb, + 0x07f1003f, + 0x03f00100, + 0x0003d002, + 0x24bd04bd, + 0xf11f29f0, + 0xf0080007, + 0x02d00203, +/* 0x04bb: main */ + 0xf404bd00, + 0x28f40031, + 0x1cd7f000, + 0xf43921f4, + 0xe4b0f401, + 0x1e18f404, + 0xf00181fe, + 0x20bd0627, + 0xb60412fd, + 0x1efd01e4, + 0x0018fe05, + 0x05b021f5, +/* 0x04eb: main_not_ctx_xfer */ + 0x94d30ef4, + 0xf5f010ef, + 0x7e21f501, + 0xc60ef403, +/* 0x04f8: ih */ + 0x88fe80f9, + 0xf980f901, + 0xf9a0f990, + 0xf9d0f9b0, + 0xbdf0f9e0, + 0x00a7f104, + 0x00a3f002, + 0xc400aacf, + 0x0bf404ab, + 0x1cd7f02c, + 0x1a00e7f1, + 0xcf00e3f0, + 0xf7f100ee, + 0xf3f01900, + 0x00ffcf00, + 0xf00421f4, + 0x07f101e7, + 0x03f01d00, + 0x000ed000, +/* 0x0546: ih_no_fifo */ + 0x07f104bd, + 0x03f00100, + 0x000ad000, + 0xf0fc04bd, + 0xd0fce0fc, + 0xa0fcb0fc, + 0x80fc90fc, + 0xfc0088fe, + 0x0032f480, +/* 0x056a: hub_barrier_done */ + 0xf7f001f8, + 0x040e9801, + 0xb904febb, + 0xe7f102ff, + 0xe3f09418, + 0x9d21f440, +/* 0x0582: ctx_redswitch */ + 0xf7f000f8, + 0x0007f120, + 0x0103f085, + 0xbd000fd0, + 0x08e7f004, +/* 0x0594: ctx_redswitch_delay */ + 0xf401e2b6, + 0xf5f1fd1b, + 0xf5f10800, + 0x07f10200, + 0x03f08500, + 0x000fd001, + 0x00f804bd, +/* 0x05b0: ctx_xfer */ + 0x810007f1, 0xd00203f0, - 0x04bd0003, - 0x29f024bd, - 0x0007f11f, - 0x0203f008, - 0xbd0002d0, -/* 0x04a9: main */ - 0x0031f404, - 0xf00028f4, - 0x21f41cd7, - 0xf401f439, - 0xf404e4b0, - 0x81fe1e18, - 0x0627f001, - 0x12fd20bd, - 0x01e4b604, - 0xfe051efd, - 0x21f50018, - 0x0ef4059e, -/* 0x04d9: main_not_ctx_xfer */ - 0x10ef94d3, - 0xf501f5f0, - 0xf4037e21, -/* 0x04e6: ih */ - 0x80f9c60e, - 0xf90188fe, - 0xf990f980, - 0xf9b0f9a0, - 0xf9e0f9d0, - 0xf104bdf0, - 0xf00200a7, - 0xaacf00a3, - 0x04abc400, - 0xf02c0bf4, - 0xe7f11cd7, - 0xe3f01a00, - 0x00eecf00, - 0x1900f7f1, - 0xcf00f3f0, - 0x21f400ff, - 0x01e7f004, - 0x1d0007f1, - 0xd00003f0, - 0x04bd000e, -/* 0x0534: ih_no_fifo */ - 0x010007f1, - 0xd00003f0, - 0x04bd000a, - 0xe0fcf0fc, - 0xb0fcd0fc, - 0x90fca0fc, - 0x88fe80fc, - 0xf480fc00, - 0x01f80032, -/* 0x0558: hub_barrier_done */ - 0x9801f7f0, - 0xfebb040e, - 0x02ffb904, - 0x9418e7f1, - 0xf440e3f0, - 0x00f89d21, -/* 0x0570: ctx_redswitch */ - 0xf120f7f0, - 0xf0850007, - 0x0fd00103, - 0xf004bd00, -/* 0x0582: ctx_redswitch_delay */ - 0xe2b608e7, - 0xfd1bf401, - 0x0800f5f1, - 0x0200f5f1, - 0x850007f1, - 0xd00103f0, 0x04bd000f, -/* 0x059e: ctx_xfer */ - 0x07f100f8, - 0x03f08100, - 0x000fd002, - 0x11f404bd, - 0x7021f507, -/* 0x05b1: ctx_xfer_not_load */ - 0x6a21f505, - 0xf124bd02, - 0xf047fc07, + 0xf50711f4, +/* 0x05c3: ctx_xfer_not_load */ + 0xf5058221, + 0xbd026a21, + 0xfc07f124, + 0x0203f047, + 0xbd0002d0, + 0x012cf004, + 0xf10320b6, + 0xf04afc07, 0x02d00203, 0xf004bd00, - 0x20b6012c, - 0xfc07f103, - 0x0203f04a, - 0xbd0002d0, - 0x01acf004, - 0xf102a5f0, - 0xf00000b7, - 0x0c9850b3, - 0x0fc4b604, - 0x9800bcbb, - 0x0d98000c, - 0x00e7f001, - 0x016f21f5, - 0xf001acf0, - 0xb7f104a5, - 0xb3f04000, - 0x040c9850, - 0xbb0fc4b6, - 0x0c9800bc, - 0x020d9801, - 0xf1060f98, - 0xf50800e7, - 0xf5016f21, - 0xf4025e21, - 0x12f40601, -/* 0x0629: ctx_xfer_post */ - 0x7f21f507, -/* 0x062d: ctx_xfer_done */ - 0x5821f502, - 0x0000f805, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, + 0xa5f001ac, + 0x00b7f102, + 0x50b3f000, + 0xb6040c98, + 0xbcbb0fc4, + 0x000c9800, + 0xf0010d98, + 0x21f500e7, + 0xacf0016f, + 0x04a5f001, + 0x4000b7f1, + 0x9850b3f0, + 0xc4b6040c, + 0x00bcbb0f, + 0x98010c98, + 0x0f98020d, + 0x00e7f106, + 0x6f21f508, + 0x5e21f501, + 0x0601f402, +/* 0x063b: ctx_xfer_post */ + 0xf50712f4, +/* 0x063f: ctx_xfer_done */ + 0xf5027f21, + 0xf8056a21, 0x00000000, 0x00000000, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h index 9a36d9cbb8a5..64d07df4b8b1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h @@ -314,7 +314,7 @@ uint32_t gf117_grgpc_code[] = { 0x03f01200, 0x0002d000, 0x17f104bd, - 0x10fe0530, + 0x10fe0542, 0x0007f100, 0x0003f007, 0xbd0000d0, @@ -333,188 +333,188 @@ uint32_t gf117_grgpc_code[] = { 0xf0860027, 0x22cf0123, 0x04028000, - 0x0c30e7f1, - 0xbd50e3f0, - 0xbd34bd24, -/* 0x0421: init_unk_loop */ - 0x6821f444, - 0xf400f6b0, - 0xf7f00f0b, - 0x04f2bb01, - 0xb6054ffd, -/* 0x0436: init_unk_next */ - 0x20b60130, - 0x04e0b601, - 0xf40126b0, -/* 0x0442: init_unk_done */ - 0x0380e21b, - 0x08048007, - 0x010027f1, - 0xcf0223f0, - 0x34bd0022, - 0xf1082595, - 0xf0c00007, - 0x05d00103, + 0xf10f24b6, + 0xf0c90007, + 0x02d00103, 0xf104bd00, - 0xf0c10007, - 0x05d00103, - 0x9804bd00, - 0x0f98000e, - 0x5021f501, - 0x002fbb01, - 0x98003fbb, - 0x0f98010e, - 0x5021f502, - 0x050e9801, - 0xbb00effd, - 0x3ebb002e, - 0x020e9800, - 0xf5030f98, - 0x98015021, - 0xeffd070e, - 0x002ebb00, - 0xb6003ebb, - 0x07f10235, - 0x03f0d300, - 0x0003d001, - 0x25b604bd, - 0x0635b608, - 0xb60120b6, - 0x24b60130, - 0x0834b608, - 0xf5022fb9, - 0xbb02d321, - 0x07f1003f, - 0x03f00100, - 0x0003d002, - 0x24bd04bd, - 0xf11f29f0, - 0xf0080007, - 0x02d00203, -/* 0x04f3: main */ - 0xf404bd00, - 0x28f40031, - 0x24d7f000, - 0xf43921f4, - 0xe4b0f401, - 0x1e18f404, - 0xf00181fe, - 0x20bd0627, - 0xb60412fd, - 0x1efd01e4, - 0x0018fe05, - 0x05e821f5, -/* 0x0523: main_not_ctx_xfer */ - 0x94d30ef4, - 0xf5f010ef, - 0x7e21f501, - 0xc60ef403, -/* 0x0530: ih */ - 0x88fe80f9, - 0xf980f901, - 0xf9a0f990, - 0xf9d0f9b0, - 0xbdf0f9e0, - 0x00a7f104, - 0x00a3f002, - 0xc400aacf, - 0x0bf404ab, - 0x24d7f02c, - 0x1a00e7f1, - 0xcf00e3f0, - 0xf7f100ee, - 0xf3f01900, - 0x00ffcf00, - 0xf00421f4, - 0x07f101e7, - 0x03f01d00, - 0x000ed000, -/* 0x057e: ih_no_fifo */ + 0xf00c30e7, + 0x24bd50e3, + 0x44bd34bd, +/* 0x0430: init_unk_loop */ + 0xb06821f4, + 0x0bf400f6, + 0x01f7f00f, + 0xfd04f2bb, + 0x30b6054f, +/* 0x0445: init_unk_next */ + 0x0120b601, + 0xb004e0b6, + 0x1bf40126, +/* 0x0451: init_unk_done */ + 0x070380e2, + 0xf1080480, + 0xf0010027, + 0x22cf0223, + 0x9534bd00, + 0x07f10825, + 0x03f0c000, + 0x0005d001, 0x07f104bd, - 0x03f00100, - 0x000ad000, - 0xf0fc04bd, - 0xd0fce0fc, - 0xa0fcb0fc, - 0x80fc90fc, - 0xfc0088fe, - 0x0032f480, -/* 0x05a2: hub_barrier_done */ - 0xf7f001f8, - 0x040e9801, - 0xb904febb, - 0xe7f102ff, - 0xe3f09418, - 0x9d21f440, -/* 0x05ba: ctx_redswitch */ - 0xf7f000f8, - 0x0007f120, - 0x0103f085, - 0xbd000fd0, - 0x08e7f004, -/* 0x05cc: ctx_redswitch_delay */ - 0xf401e2b6, - 0xf5f1fd1b, - 0xf5f10800, - 0x07f10200, - 0x03f08500, - 0x000fd001, - 0x00f804bd, -/* 0x05e8: ctx_xfer */ - 0x810007f1, + 0x03f0c100, + 0x0005d001, + 0x0e9804bd, + 0x010f9800, + 0x015021f5, + 0xbb002fbb, + 0x0e98003f, + 0x020f9801, + 0x015021f5, + 0xfd050e98, + 0x2ebb00ef, + 0x003ebb00, + 0x98020e98, + 0x21f5030f, + 0x0e980150, + 0x00effd07, + 0xbb002ebb, + 0x35b6003e, + 0x0007f102, + 0x0103f0d3, + 0xbd0003d0, + 0x0825b604, + 0xb60635b6, + 0x30b60120, + 0x0824b601, + 0xb90834b6, + 0x21f5022f, + 0x2fbb02d3, + 0x003fbb00, + 0x010007f1, 0xd00203f0, - 0x04bd000f, - 0xf50711f4, -/* 0x05fb: ctx_xfer_not_load */ - 0xf505ba21, - 0xbd026a21, - 0xfc07f124, - 0x0203f047, + 0x04bd0003, + 0x29f024bd, + 0x0007f11f, + 0x0203f008, 0xbd0002d0, - 0x012cf004, - 0xf10320b6, - 0xf04afc07, +/* 0x0505: main */ + 0x0031f404, + 0xf00028f4, + 0x21f424d7, + 0xf401f439, + 0xf404e4b0, + 0x81fe1e18, + 0x0627f001, + 0x12fd20bd, + 0x01e4b604, + 0xfe051efd, + 0x21f50018, + 0x0ef405fa, +/* 0x0535: main_not_ctx_xfer */ + 0x10ef94d3, + 0xf501f5f0, + 0xf4037e21, +/* 0x0542: ih */ + 0x80f9c60e, + 0xf90188fe, + 0xf990f980, + 0xf9b0f9a0, + 0xf9e0f9d0, + 0xf104bdf0, + 0xf00200a7, + 0xaacf00a3, + 0x04abc400, + 0xf02c0bf4, + 0xe7f124d7, + 0xe3f01a00, + 0x00eecf00, + 0x1900f7f1, + 0xcf00f3f0, + 0x21f400ff, + 0x01e7f004, + 0x1d0007f1, + 0xd00003f0, + 0x04bd000e, +/* 0x0590: ih_no_fifo */ + 0x010007f1, + 0xd00003f0, + 0x04bd000a, + 0xe0fcf0fc, + 0xb0fcd0fc, + 0x90fca0fc, + 0x88fe80fc, + 0xf480fc00, + 0x01f80032, +/* 0x05b4: hub_barrier_done */ + 0x9801f7f0, + 0xfebb040e, + 0x02ffb904, + 0x9418e7f1, + 0xf440e3f0, + 0x00f89d21, +/* 0x05cc: ctx_redswitch */ + 0xf120f7f0, + 0xf0850007, + 0x0fd00103, + 0xf004bd00, +/* 0x05de: ctx_redswitch_delay */ + 0xe2b608e7, + 0xfd1bf401, + 0x0800f5f1, + 0x0200f5f1, + 0x850007f1, + 0xd00103f0, + 0x04bd000f, +/* 0x05fa: ctx_xfer */ + 0x07f100f8, + 0x03f08100, + 0x000fd002, + 0x11f404bd, + 0xcc21f507, +/* 0x060d: ctx_xfer_not_load */ + 0x6a21f505, + 0xf124bd02, + 0xf047fc07, 0x02d00203, 0xf004bd00, - 0xa5f001ac, - 0x00b7f102, - 0x50b3f000, - 0xb6040c98, - 0xbcbb0fc4, - 0x000c9800, - 0xf0010d98, - 0x21f500e7, - 0xacf0016f, - 0x00b7f101, - 0x50b3f040, - 0xb6040c98, - 0xbcbb0fc4, - 0x010c9800, - 0x98020d98, - 0xe7f1060f, - 0x21f50800, - 0xacf0016f, - 0x04a5f001, - 0x3000b7f1, - 0x9850b3f0, - 0xc4b6040c, - 0x00bcbb0f, - 0x98020c98, - 0x0f98030d, - 0x00e7f108, - 0x6f21f502, - 0x5e21f501, - 0x0601f402, -/* 0x0697: ctx_xfer_post */ - 0xf50712f4, -/* 0x069b: ctx_xfer_done */ - 0xf5027f21, - 0xf805a221, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, + 0x20b6012c, + 0xfc07f103, + 0x0203f04a, + 0xbd0002d0, + 0x01acf004, + 0xf102a5f0, + 0xf00000b7, + 0x0c9850b3, + 0x0fc4b604, + 0x9800bcbb, + 0x0d98000c, + 0x00e7f001, + 0x016f21f5, + 0xf101acf0, + 0xf04000b7, + 0x0c9850b3, + 0x0fc4b604, + 0x9800bcbb, + 0x0d98010c, + 0x060f9802, + 0x0800e7f1, + 0x016f21f5, + 0xf001acf0, + 0xb7f104a5, + 0xb3f03000, + 0x040c9850, + 0xbb0fc4b6, + 0x0c9800bc, + 0x030d9802, + 0xf1080f98, + 0xf50200e7, + 0xf5016f21, + 0xf4025e21, + 0x12f40601, +/* 0x06a9: ctx_xfer_post */ + 0x7f21f507, +/* 0x06ad: ctx_xfer_done */ + 0xb421f502, + 0x0000f805, 0x00000000, 0x00000000, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h index 49020fff4317..2f596433c222 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h @@ -314,7 +314,7 @@ uint32_t gk104_grgpc_code[] = { 0x03f01200, 0x0002d000, 0x17f104bd, - 0x10fe0530, + 0x10fe0542, 0x0007f100, 0x0003f007, 0xbd0000d0, @@ -333,188 +333,188 @@ uint32_t gk104_grgpc_code[] = { 0xf0860027, 0x22cf0123, 0x04028000, - 0x0c30e7f1, - 0xbd50e3f0, - 0xbd34bd24, -/* 0x0421: init_unk_loop */ - 0x6821f444, - 0xf400f6b0, - 0xf7f00f0b, - 0x04f2bb01, - 0xb6054ffd, -/* 0x0436: init_unk_next */ - 0x20b60130, - 0x04e0b601, - 0xf40126b0, -/* 0x0442: init_unk_done */ - 0x0380e21b, - 0x08048007, - 0x010027f1, - 0xcf0223f0, - 0x34bd0022, - 0xf1082595, - 0xf0c00007, - 0x05d00103, + 0xf10f24b6, + 0xf0c90007, + 0x02d00103, 0xf104bd00, - 0xf0c10007, - 0x05d00103, - 0x9804bd00, - 0x0f98000e, - 0x5021f501, - 0x002fbb01, - 0x98003fbb, - 0x0f98010e, - 0x5021f502, - 0x050e9801, - 0xbb00effd, - 0x3ebb002e, - 0x020e9800, - 0xf5030f98, - 0x98015021, - 0xeffd070e, - 0x002ebb00, - 0xb6003ebb, - 0x07f10235, - 0x03f0d300, - 0x0003d001, - 0x25b604bd, - 0x0635b608, - 0xb60120b6, - 0x24b60130, - 0x0834b608, - 0xf5022fb9, - 0xbb02d321, - 0x07f1003f, - 0x03f00100, - 0x0003d002, - 0x24bd04bd, - 0xf11f29f0, - 0xf0080007, - 0x02d00203, -/* 0x04f3: main */ - 0xf404bd00, - 0x28f40031, - 0x24d7f000, - 0xf43921f4, - 0xe4b0f401, - 0x1e18f404, - 0xf00181fe, - 0x20bd0627, - 0xb60412fd, - 0x1efd01e4, - 0x0018fe05, - 0x05e821f5, -/* 0x0523: main_not_ctx_xfer */ - 0x94d30ef4, - 0xf5f010ef, - 0x7e21f501, - 0xc60ef403, -/* 0x0530: ih */ - 0x88fe80f9, - 0xf980f901, - 0xf9a0f990, - 0xf9d0f9b0, - 0xbdf0f9e0, - 0x00a7f104, - 0x00a3f002, - 0xc400aacf, - 0x0bf404ab, - 0x24d7f02c, - 0x1a00e7f1, - 0xcf00e3f0, - 0xf7f100ee, - 0xf3f01900, - 0x00ffcf00, - 0xf00421f4, - 0x07f101e7, - 0x03f01d00, - 0x000ed000, -/* 0x057e: ih_no_fifo */ + 0xf00c30e7, + 0x24bd50e3, + 0x44bd34bd, +/* 0x0430: init_unk_loop */ + 0xb06821f4, + 0x0bf400f6, + 0x01f7f00f, + 0xfd04f2bb, + 0x30b6054f, +/* 0x0445: init_unk_next */ + 0x0120b601, + 0xb004e0b6, + 0x1bf40126, +/* 0x0451: init_unk_done */ + 0x070380e2, + 0xf1080480, + 0xf0010027, + 0x22cf0223, + 0x9534bd00, + 0x07f10825, + 0x03f0c000, + 0x0005d001, 0x07f104bd, - 0x03f00100, - 0x000ad000, - 0xf0fc04bd, - 0xd0fce0fc, - 0xa0fcb0fc, - 0x80fc90fc, - 0xfc0088fe, - 0x0032f480, -/* 0x05a2: hub_barrier_done */ - 0xf7f001f8, - 0x040e9801, - 0xb904febb, - 0xe7f102ff, - 0xe3f09418, - 0x9d21f440, -/* 0x05ba: ctx_redswitch */ - 0xf7f000f8, - 0x0007f120, - 0x0103f085, - 0xbd000fd0, - 0x08e7f004, -/* 0x05cc: ctx_redswitch_delay */ - 0xf401e2b6, - 0xf5f1fd1b, - 0xf5f10800, - 0x07f10200, - 0x03f08500, - 0x000fd001, - 0x00f804bd, -/* 0x05e8: ctx_xfer */ - 0x810007f1, + 0x03f0c100, + 0x0005d001, + 0x0e9804bd, + 0x010f9800, + 0x015021f5, + 0xbb002fbb, + 0x0e98003f, + 0x020f9801, + 0x015021f5, + 0xfd050e98, + 0x2ebb00ef, + 0x003ebb00, + 0x98020e98, + 0x21f5030f, + 0x0e980150, + 0x00effd07, + 0xbb002ebb, + 0x35b6003e, + 0x0007f102, + 0x0103f0d3, + 0xbd0003d0, + 0x0825b604, + 0xb60635b6, + 0x30b60120, + 0x0824b601, + 0xb90834b6, + 0x21f5022f, + 0x2fbb02d3, + 0x003fbb00, + 0x010007f1, 0xd00203f0, - 0x04bd000f, - 0xf50711f4, -/* 0x05fb: ctx_xfer_not_load */ - 0xf505ba21, - 0xbd026a21, - 0xfc07f124, - 0x0203f047, + 0x04bd0003, + 0x29f024bd, + 0x0007f11f, + 0x0203f008, 0xbd0002d0, - 0x012cf004, - 0xf10320b6, - 0xf04afc07, +/* 0x0505: main */ + 0x0031f404, + 0xf00028f4, + 0x21f424d7, + 0xf401f439, + 0xf404e4b0, + 0x81fe1e18, + 0x0627f001, + 0x12fd20bd, + 0x01e4b604, + 0xfe051efd, + 0x21f50018, + 0x0ef405fa, +/* 0x0535: main_not_ctx_xfer */ + 0x10ef94d3, + 0xf501f5f0, + 0xf4037e21, +/* 0x0542: ih */ + 0x80f9c60e, + 0xf90188fe, + 0xf990f980, + 0xf9b0f9a0, + 0xf9e0f9d0, + 0xf104bdf0, + 0xf00200a7, + 0xaacf00a3, + 0x04abc400, + 0xf02c0bf4, + 0xe7f124d7, + 0xe3f01a00, + 0x00eecf00, + 0x1900f7f1, + 0xcf00f3f0, + 0x21f400ff, + 0x01e7f004, + 0x1d0007f1, + 0xd00003f0, + 0x04bd000e, +/* 0x0590: ih_no_fifo */ + 0x010007f1, + 0xd00003f0, + 0x04bd000a, + 0xe0fcf0fc, + 0xb0fcd0fc, + 0x90fca0fc, + 0x88fe80fc, + 0xf480fc00, + 0x01f80032, +/* 0x05b4: hub_barrier_done */ + 0x9801f7f0, + 0xfebb040e, + 0x02ffb904, + 0x9418e7f1, + 0xf440e3f0, + 0x00f89d21, +/* 0x05cc: ctx_redswitch */ + 0xf120f7f0, + 0xf0850007, + 0x0fd00103, + 0xf004bd00, +/* 0x05de: ctx_redswitch_delay */ + 0xe2b608e7, + 0xfd1bf401, + 0x0800f5f1, + 0x0200f5f1, + 0x850007f1, + 0xd00103f0, + 0x04bd000f, +/* 0x05fa: ctx_xfer */ + 0x07f100f8, + 0x03f08100, + 0x000fd002, + 0x11f404bd, + 0xcc21f507, +/* 0x060d: ctx_xfer_not_load */ + 0x6a21f505, + 0xf124bd02, + 0xf047fc07, 0x02d00203, 0xf004bd00, - 0xa5f001ac, - 0x00b7f102, - 0x50b3f000, - 0xb6040c98, - 0xbcbb0fc4, - 0x000c9800, - 0xf0010d98, - 0x21f500e7, - 0xacf0016f, - 0x00b7f101, - 0x50b3f040, - 0xb6040c98, - 0xbcbb0fc4, - 0x010c9800, - 0x98020d98, - 0xe7f1060f, - 0x21f50800, - 0xacf0016f, - 0x04a5f001, - 0x3000b7f1, - 0x9850b3f0, - 0xc4b6040c, - 0x00bcbb0f, - 0x98020c98, - 0x0f98030d, - 0x00e7f108, - 0x6f21f502, - 0x5e21f501, - 0x0601f402, -/* 0x0697: ctx_xfer_post */ - 0xf50712f4, -/* 0x069b: ctx_xfer_done */ - 0xf5027f21, - 0xf805a221, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, + 0x20b6012c, + 0xfc07f103, + 0x0203f04a, + 0xbd0002d0, + 0x01acf004, + 0xf102a5f0, + 0xf00000b7, + 0x0c9850b3, + 0x0fc4b604, + 0x9800bcbb, + 0x0d98000c, + 0x00e7f001, + 0x016f21f5, + 0xf101acf0, + 0xf04000b7, + 0x0c9850b3, + 0x0fc4b604, + 0x9800bcbb, + 0x0d98010c, + 0x060f9802, + 0x0800e7f1, + 0x016f21f5, + 0xf001acf0, + 0xb7f104a5, + 0xb3f03000, + 0x040c9850, + 0xbb0fc4b6, + 0x0c9800bc, + 0x030d9802, + 0xf1080f98, + 0xf50200e7, + 0xf5016f21, + 0xf4025e21, + 0x12f40601, +/* 0x06a9: ctx_xfer_post */ + 0x7f21f507, +/* 0x06ad: ctx_xfer_done */ + 0xb421f502, + 0x0000f805, 0x00000000, 0x00000000, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h index c95b07e3bce5..ee8e54db8fc9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h @@ -314,7 +314,7 @@ uint32_t gk110_grgpc_code[] = { 0x03f01200, 0x0002d000, 0x17f104bd, - 0x10fe0530, + 0x10fe0542, 0x0007f100, 0x0003f007, 0xbd0000d0, @@ -333,188 +333,188 @@ uint32_t gk110_grgpc_code[] = { 0xf0860027, 0x22cf0123, 0x04028000, - 0x0c30e7f1, - 0xbd50e3f0, - 0xbd34bd24, -/* 0x0421: init_unk_loop */ - 0x6821f444, - 0xf400f6b0, - 0xf7f00f0b, - 0x04f2bb01, - 0xb6054ffd, -/* 0x0436: init_unk_next */ - 0x20b60130, - 0x04e0b601, - 0xf40226b0, -/* 0x0442: init_unk_done */ - 0x0380e21b, - 0x08048007, - 0x010027f1, - 0xcf0223f0, - 0x34bd0022, - 0xf1082595, - 0xf0c00007, - 0x05d00103, + 0xf10f24b6, + 0xf0c90007, + 0x02d00103, 0xf104bd00, - 0xf0c10007, - 0x05d00103, - 0x9804bd00, - 0x0f98000e, - 0x5021f501, - 0x002fbb01, - 0x98003fbb, - 0x0f98010e, - 0x5021f502, - 0x050e9801, - 0xbb00effd, - 0x3ebb002e, - 0x020e9800, - 0xf5030f98, - 0x98015021, - 0xeffd070e, - 0x002ebb00, - 0xb6003ebb, - 0x07f10235, - 0x03f0d300, - 0x0003d001, - 0x25b604bd, - 0x0635b608, - 0xb60120b6, - 0x24b60130, - 0x0834b608, - 0xf5022fb9, - 0xbb02d321, - 0x07f1003f, - 0x03f00100, - 0x0003d002, - 0x24bd04bd, - 0xf11f29f0, - 0xf0300007, - 0x02d00203, -/* 0x04f3: main */ - 0xf404bd00, - 0x28f40031, - 0x24d7f000, - 0xf43921f4, - 0xe4b0f401, - 0x1e18f404, - 0xf00181fe, - 0x20bd0627, - 0xb60412fd, - 0x1efd01e4, - 0x0018fe05, - 0x05e821f5, -/* 0x0523: main_not_ctx_xfer */ - 0x94d30ef4, - 0xf5f010ef, - 0x7e21f501, - 0xc60ef403, -/* 0x0530: ih */ - 0x88fe80f9, - 0xf980f901, - 0xf9a0f990, - 0xf9d0f9b0, - 0xbdf0f9e0, - 0x00a7f104, - 0x00a3f002, - 0xc400aacf, - 0x0bf404ab, - 0x24d7f02c, - 0x1a00e7f1, - 0xcf00e3f0, - 0xf7f100ee, - 0xf3f01900, - 0x00ffcf00, - 0xf00421f4, - 0x07f101e7, - 0x03f01d00, - 0x000ed000, -/* 0x057e: ih_no_fifo */ + 0xf00c30e7, + 0x24bd50e3, + 0x44bd34bd, +/* 0x0430: init_unk_loop */ + 0xb06821f4, + 0x0bf400f6, + 0x01f7f00f, + 0xfd04f2bb, + 0x30b6054f, +/* 0x0445: init_unk_next */ + 0x0120b601, + 0xb004e0b6, + 0x1bf40226, +/* 0x0451: init_unk_done */ + 0x070380e2, + 0xf1080480, + 0xf0010027, + 0x22cf0223, + 0x9534bd00, + 0x07f10825, + 0x03f0c000, + 0x0005d001, 0x07f104bd, - 0x03f00100, - 0x000ad000, - 0xf0fc04bd, - 0xd0fce0fc, - 0xa0fcb0fc, - 0x80fc90fc, - 0xfc0088fe, - 0x0032f480, -/* 0x05a2: hub_barrier_done */ - 0xf7f001f8, - 0x040e9801, - 0xb904febb, - 0xe7f102ff, - 0xe3f09418, - 0x9d21f440, -/* 0x05ba: ctx_redswitch */ - 0xf7f000f8, - 0x0007f120, - 0x0103f085, - 0xbd000fd0, - 0x08e7f004, -/* 0x05cc: ctx_redswitch_delay */ - 0xf401e2b6, - 0xf5f1fd1b, - 0xf5f10800, - 0x07f10200, - 0x03f08500, - 0x000fd001, - 0x00f804bd, -/* 0x05e8: ctx_xfer */ - 0x810007f1, + 0x03f0c100, + 0x0005d001, + 0x0e9804bd, + 0x010f9800, + 0x015021f5, + 0xbb002fbb, + 0x0e98003f, + 0x020f9801, + 0x015021f5, + 0xfd050e98, + 0x2ebb00ef, + 0x003ebb00, + 0x98020e98, + 0x21f5030f, + 0x0e980150, + 0x00effd07, + 0xbb002ebb, + 0x35b6003e, + 0x0007f102, + 0x0103f0d3, + 0xbd0003d0, + 0x0825b604, + 0xb60635b6, + 0x30b60120, + 0x0824b601, + 0xb90834b6, + 0x21f5022f, + 0x2fbb02d3, + 0x003fbb00, + 0x010007f1, 0xd00203f0, - 0x04bd000f, - 0xf50711f4, -/* 0x05fb: ctx_xfer_not_load */ - 0xf505ba21, - 0xbd026a21, - 0xfc07f124, - 0x0203f047, + 0x04bd0003, + 0x29f024bd, + 0x0007f11f, + 0x0203f030, 0xbd0002d0, - 0x012cf004, - 0xf10320b6, - 0xf04afc07, +/* 0x0505: main */ + 0x0031f404, + 0xf00028f4, + 0x21f424d7, + 0xf401f439, + 0xf404e4b0, + 0x81fe1e18, + 0x0627f001, + 0x12fd20bd, + 0x01e4b604, + 0xfe051efd, + 0x21f50018, + 0x0ef405fa, +/* 0x0535: main_not_ctx_xfer */ + 0x10ef94d3, + 0xf501f5f0, + 0xf4037e21, +/* 0x0542: ih */ + 0x80f9c60e, + 0xf90188fe, + 0xf990f980, + 0xf9b0f9a0, + 0xf9e0f9d0, + 0xf104bdf0, + 0xf00200a7, + 0xaacf00a3, + 0x04abc400, + 0xf02c0bf4, + 0xe7f124d7, + 0xe3f01a00, + 0x00eecf00, + 0x1900f7f1, + 0xcf00f3f0, + 0x21f400ff, + 0x01e7f004, + 0x1d0007f1, + 0xd00003f0, + 0x04bd000e, +/* 0x0590: ih_no_fifo */ + 0x010007f1, + 0xd00003f0, + 0x04bd000a, + 0xe0fcf0fc, + 0xb0fcd0fc, + 0x90fca0fc, + 0x88fe80fc, + 0xf480fc00, + 0x01f80032, +/* 0x05b4: hub_barrier_done */ + 0x9801f7f0, + 0xfebb040e, + 0x02ffb904, + 0x9418e7f1, + 0xf440e3f0, + 0x00f89d21, +/* 0x05cc: ctx_redswitch */ + 0xf120f7f0, + 0xf0850007, + 0x0fd00103, + 0xf004bd00, +/* 0x05de: ctx_redswitch_delay */ + 0xe2b608e7, + 0xfd1bf401, + 0x0800f5f1, + 0x0200f5f1, + 0x850007f1, + 0xd00103f0, + 0x04bd000f, +/* 0x05fa: ctx_xfer */ + 0x07f100f8, + 0x03f08100, + 0x000fd002, + 0x11f404bd, + 0xcc21f507, +/* 0x060d: ctx_xfer_not_load */ + 0x6a21f505, + 0xf124bd02, + 0xf047fc07, 0x02d00203, 0xf004bd00, - 0xa5f001ac, - 0x00b7f102, - 0x50b3f000, - 0xb6040c98, - 0xbcbb0fc4, - 0x000c9800, - 0xf0010d98, - 0x21f500e7, - 0xacf0016f, - 0x00b7f101, - 0x50b3f040, - 0xb6040c98, - 0xbcbb0fc4, - 0x010c9800, - 0x98020d98, - 0xe7f1060f, - 0x21f50800, - 0xacf0016f, - 0x04a5f001, - 0x3000b7f1, - 0x9850b3f0, - 0xc4b6040c, - 0x00bcbb0f, - 0x98020c98, - 0x0f98030d, - 0x00e7f108, - 0x6f21f502, - 0x5e21f501, - 0x0601f402, -/* 0x0697: ctx_xfer_post */ - 0xf50712f4, -/* 0x069b: ctx_xfer_done */ - 0xf5027f21, - 0xf805a221, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, + 0x20b6012c, + 0xfc07f103, + 0x0203f04a, + 0xbd0002d0, + 0x01acf004, + 0xf102a5f0, + 0xf00000b7, + 0x0c9850b3, + 0x0fc4b604, + 0x9800bcbb, + 0x0d98000c, + 0x00e7f001, + 0x016f21f5, + 0xf101acf0, + 0xf04000b7, + 0x0c9850b3, + 0x0fc4b604, + 0x9800bcbb, + 0x0d98010c, + 0x060f9802, + 0x0800e7f1, + 0x016f21f5, + 0xf001acf0, + 0xb7f104a5, + 0xb3f03000, + 0x040c9850, + 0xbb0fc4b6, + 0x0c9800bc, + 0x030d9802, + 0xf1080f98, + 0xf50200e7, + 0xf5016f21, + 0xf4025e21, + 0x12f40601, +/* 0x06a9: ctx_xfer_post */ + 0x7f21f507, +/* 0x06ad: ctx_xfer_done */ + 0xb421f502, + 0x0000f805, 0x00000000, 0x00000000, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h index 7e1c28ee7591..fbcc342f896f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h @@ -276,7 +276,7 @@ uint32_t gk208_grgpc_code[] = { 0x02020014, 0xf6120040, 0x04bd0002, - 0xfe047241, + 0xfe048141, 0x00400010, 0x0000f607, 0x040204bd, @@ -291,20 +291,23 @@ uint32_t gk208_grgpc_code[] = { 0x820603b5, 0xcf018600, 0x02b50022, + 0x0f24b604, + 0x01c90080, + 0xbd0002f6, 0x0c308e04, 0xbd24bd50, -/* 0x0377: init_unk_loop */ +/* 0x0383: init_unk_loop */ 0x7e44bd34, 0xb0000065, 0x0bf400f6, 0xbb010f0e, 0x4ffd04f2, 0x0130b605, -/* 0x038c: init_unk_next */ +/* 0x0398: init_unk_next */ 0xb60120b6, 0x26b004e0, 0xe21bf401, -/* 0x0398: init_unk_done */ +/* 0x03a4: init_unk_done */ 0xb50703b5, 0x00820804, 0x22cf0201, @@ -338,121 +341,118 @@ uint32_t gk208_grgpc_code[] = { 0xb60824b6, 0x2fb20834, 0x0002687e, - 0x80003fbb, - 0xf6020100, - 0x04bd0003, - 0x29f024bd, - 0x3000801f, - 0x0002f602, -/* 0x0436: main */ - 0x31f404bd, - 0x0028f400, - 0x377e240d, - 0x01f40000, - 0x04e4b0f4, - 0xfe1d18f4, - 0x06020181, - 0x12fd20bd, - 0x01e4b604, - 0xfe051efd, - 0x097e0018, - 0x0ef40005, -/* 0x0465: main_not_ctx_xfer */ - 0x10ef94d4, - 0x7e01f5f0, - 0xf40002f8, -/* 0x0472: ih */ - 0x80f9c70e, - 0xf90188fe, - 0xf990f980, - 0xf9b0f9a0, - 0xf9e0f9d0, - 0x4a04bdf0, - 0xaacf0200, - 0x04abc400, - 0x0d1f0bf4, - 0x1a004e24, - 0x4f00eecf, - 0xffcf1900, - 0x00047e00, - 0x40010e00, - 0x0ef61d00, -/* 0x04af: ih_no_fifo */ - 0x4004bd00, - 0x0af60100, - 0xfc04bd00, - 0xfce0fcf0, - 0xfcb0fcd0, - 0xfc90fca0, - 0x0088fe80, - 0x32f480fc, -/* 0x04cf: hub_barrier_done */ - 0x0f01f800, - 0x040e9801, - 0xb204febb, - 0x94188eff, - 0x008f7e40, -/* 0x04e3: ctx_redswitch */ - 0x0f00f800, - 0x85008020, + 0xbb002fbb, + 0x0080003f, + 0x03f60201, + 0xbd04bd00, + 0x1f29f024, + 0x02300080, + 0xbd0002f6, +/* 0x0445: main */ + 0x0031f404, + 0x0d0028f4, + 0x00377e24, + 0xf401f400, + 0xf404e4b0, + 0x81fe1d18, + 0xbd060201, + 0x0412fd20, + 0xfd01e4b6, + 0x18fe051e, + 0x05187e00, + 0xd40ef400, +/* 0x0474: main_not_ctx_xfer */ + 0xf010ef94, + 0xf87e01f5, + 0x0ef40002, +/* 0x0481: ih */ + 0xfe80f9c7, + 0x80f90188, + 0xa0f990f9, + 0xd0f9b0f9, + 0xf0f9e0f9, + 0x004a04bd, + 0x00aacf02, + 0xf404abc4, + 0x240d1f0b, + 0xcf1a004e, + 0x004f00ee, + 0x00ffcf19, + 0x0000047e, + 0x0040010e, + 0x000ef61d, +/* 0x04be: ih_no_fifo */ + 0x004004bd, + 0x000af601, + 0xf0fc04bd, + 0xd0fce0fc, + 0xa0fcb0fc, + 0x80fc90fc, + 0xfc0088fe, + 0x0032f480, +/* 0x04de: hub_barrier_done */ + 0x010f01f8, + 0xbb040e98, + 0xffb204fe, + 0x4094188e, + 0x00008f7e, +/* 0x04f2: ctx_redswitch */ + 0x200f00f8, + 0x01850080, + 0xbd000ff6, +/* 0x04ff: ctx_redswitch_delay */ + 0xb6080e04, + 0x1bf401e2, + 0x00f5f1fd, + 0x00f5f108, + 0x85008002, 0x000ff601, - 0x080e04bd, -/* 0x04f0: ctx_redswitch_delay */ - 0xf401e2b6, - 0xf5f1fd1b, - 0xf5f10800, - 0x00800200, - 0x0ff60185, - 0xf804bd00, -/* 0x0509: ctx_xfer */ - 0x81008000, - 0x000ff602, - 0x11f404bd, - 0x04e37e07, -/* 0x0519: ctx_xfer_not_load */ - 0x02167e00, - 0x8024bd00, - 0xf60247fc, - 0x04bd0002, - 0xb6012cf0, - 0xfc800320, - 0x02f6024a, + 0x00f804bd, +/* 0x0518: ctx_xfer */ + 0x02810080, + 0xbd000ff6, + 0x0711f404, + 0x0004f27e, +/* 0x0528: ctx_xfer_not_load */ + 0x0002167e, + 0xfc8024bd, + 0x02f60247, 0xf004bd00, - 0xa5f001ac, - 0x00008b02, - 0x040c9850, - 0xbb0fc4b6, - 0x0c9800bc, - 0x010d9800, - 0x3d7e000e, - 0xacf00001, - 0x40008b01, - 0x040c9850, - 0xbb0fc4b6, - 0x0c9800bc, - 0x020d9801, - 0x4e060f98, - 0x3d7e0800, - 0xacf00001, - 0x04a5f001, - 0x5030008b, + 0x20b6012c, + 0x4afc8003, + 0x0002f602, + 0xacf004bd, + 0x02a5f001, + 0x5000008b, 0xb6040c98, 0xbcbb0fc4, - 0x020c9800, - 0x98030d98, - 0x004e080f, - 0x013d7e02, - 0x020a7e00, - 0x0601f400, -/* 0x05a3: ctx_xfer_post */ - 0x7e0712f4, -/* 0x05a7: ctx_xfer_done */ - 0x7e000227, - 0xf80004cf, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, + 0x000c9800, + 0x0e010d98, + 0x013d7e00, + 0x01acf000, + 0x5040008b, + 0xb6040c98, + 0xbcbb0fc4, + 0x010c9800, + 0x98020d98, + 0x004e060f, + 0x013d7e08, + 0x01acf000, + 0x8b04a5f0, + 0x98503000, + 0xc4b6040c, + 0x00bcbb0f, + 0x98020c98, + 0x0f98030d, + 0x02004e08, + 0x00013d7e, + 0x00020a7e, + 0xf40601f4, +/* 0x05b2: ctx_xfer_post */ + 0x277e0712, +/* 0x05b6: ctx_xfer_done */ + 0xde7e0002, + 0x00f80004, 0x00000000, 0x00000000, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5 b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5 index e730603891d7..47802c7ecca1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5 +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5 @@ -24,7 +24,7 @@ #define NV_PGRAPH_GPCX_UNK__SIZE 0x00000002 -#define CHIPSET GK208 +#define CHIPSET GM107 #include "macros.fuc" .section #gm107_grgpc_data diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h index 6d53b67dd3c4..51f5c3c6e966 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h @@ -41,7 +41,7 @@ uint32_t gm107_grgpc_data[] = { }; uint32_t gm107_grgpc_code[] = { - 0x03140ef5, + 0x03410ef5, /* 0x0004: queue_put */ 0x9800d898, 0x86f001d9, @@ -268,187 +268,319 @@ uint32_t gm107_grgpc_code[] = { 0x409c1c8e, 0x00008f7e, 0x00f8e0fc, -/* 0x0314: init */ - 0x004104bd, - 0x0011cf42, - 0x010911e7, - 0xfe0814b6, - 0x02020014, - 0xf6120040, - 0x04bd0002, - 0xfe047241, - 0x00400010, - 0x0000f607, - 0x040204bd, - 0xf6040040, - 0x04bd0002, - 0x821031f4, - 0xcf018200, - 0x01030022, - 0xbb1f24f0, - 0x32b60432, - 0x0502b501, - 0x820603b5, - 0xcf018600, - 0x02b50022, - 0x0c308e04, - 0xbd24bd50, -/* 0x0377: init_unk_loop */ - 0x7e44bd34, - 0xb0000065, - 0x0bf400f6, - 0xbb010f0e, - 0x4ffd04f2, - 0x0130b605, -/* 0x038c: init_unk_next */ - 0xb60120b6, - 0x26b004e0, - 0xe21bf402, -/* 0x0398: init_unk_done */ - 0xb50703b5, - 0x00820804, - 0x22cf0201, - 0x9534bd00, - 0x00800825, - 0x05f601c0, - 0x8004bd00, - 0xf601c100, +/* 0x0314: tpc_strand_wait */ + 0x94bd90f9, + 0x800a99f0, + 0xf6023700, + 0x04bd0009, +/* 0x0324: tpc_strand_busy */ + 0x033f0089, + 0xb30099cf, + 0xbdf90094, + 0x0a99f094, + 0x02170080, + 0xbd0009f6, + 0xf890fc04, +/* 0x0341: init */ + 0x4104bd00, + 0x11cf4200, + 0x0911e700, + 0x0814b601, + 0x020014fe, + 0x12004002, + 0xbd0002f6, + 0x05b04104, + 0x400010fe, + 0x00f60700, + 0x0204bd00, + 0x04004004, + 0xbd0002f6, + 0x1031f404, + 0x01820082, + 0x030022cf, + 0x1f24f001, + 0xb60432bb, + 0x02b50132, + 0x0603b505, + 0x01860082, + 0xb50022cf, + 0x24b60402, + 0xc900800f, + 0x0002f601, + 0x308e04bd, + 0x24bd500c, + 0x44bd34bd, +/* 0x03b0: init_unk_loop */ + 0x0000657e, + 0xf400f6b0, + 0x010f0e0b, + 0xfd04f2bb, + 0x30b6054f, +/* 0x03c5: init_unk_next */ + 0x0120b601, + 0xb004e0b6, + 0x1bf40226, +/* 0x03d1: init_unk_done */ + 0x0703b5e2, + 0x820804b5, + 0xcf020100, + 0x34bd0022, + 0x80082595, + 0xf601c000, 0x04bd0005, - 0x98000e98, - 0x207e010f, - 0x2fbb0001, + 0x01c10080, + 0xbd0005f6, + 0x000e9804, + 0x7e010f98, + 0xbb000120, + 0x3fbb002f, + 0x010e9800, + 0x7e020f98, + 0x98000120, + 0xeffd050e, + 0x002ebb00, + 0x98003ebb, + 0x0f98020e, + 0x01207e03, + 0x070e9800, + 0xbb00effd, + 0x3ebb002e, + 0x0235b600, + 0x01d30080, + 0xbd0003f6, + 0x0825b604, + 0xb60635b6, + 0x30b60120, + 0x0824b601, + 0xb20834b6, + 0x02687e2f, + 0x002fbb00, + 0x0f003fbb, + 0x8effb23f, + 0xf0501d60, + 0x8f7e01e5, + 0x0c0f0000, + 0xa88effb2, + 0xe5f0501d, + 0x008f7e01, + 0x03147e00, + 0xb23f0f00, + 0x1d608eff, + 0x01e5f050, + 0x00008f7e, + 0xffb2000f, + 0x501d9c8e, + 0x7e01e5f0, + 0x0f00008f, + 0x03147e01, + 0x8effb200, + 0xf0501da8, + 0x8f7e01e5, + 0xff0f0000, + 0x988effb2, + 0xe5f0501d, + 0x008f7e01, + 0xb2020f00, + 0x1da88eff, + 0x01e5f050, + 0x00008f7e, + 0x0003147e, + 0x85050498, + 0x98504000, + 0x64b60406, + 0x0056bb0f, +/* 0x04e0: tpc_strand_init_tpc_loop */ + 0x05705eb8, + 0x00657e00, + 0xbdf6b200, +/* 0x04ed: tpc_strand_init_idx_loop */ + 0x605eb874, + 0x7fb20005, + 0x00008f7e, + 0x05885eb8, + 0x082f9500, + 0x00008f7e, + 0x058c5eb8, + 0x082f9500, + 0x00008f7e, + 0x05905eb8, + 0x00657e00, + 0x06f5b600, + 0xb601f0b6, + 0x2fbb08f4, 0x003fbb00, - 0x98010e98, - 0x207e020f, - 0x0e980001, - 0x00effd05, - 0xbb002ebb, - 0x0e98003e, - 0x030f9802, - 0x0001207e, - 0xfd070e98, - 0x2ebb00ef, - 0x003ebb00, - 0x800235b6, - 0xf601d300, - 0x04bd0003, - 0xb60825b6, - 0x20b60635, - 0x0130b601, - 0xb60824b6, - 0x2fb20834, - 0x0002687e, - 0x80003fbb, - 0xf6020100, - 0x04bd0003, - 0x29f024bd, - 0x3000801f, - 0x0002f602, -/* 0x0436: main */ - 0x31f404bd, - 0x0028f400, - 0x377e240d, - 0x01f40000, - 0x04e4b0f4, - 0xfe1d18f4, - 0x06020181, - 0x12fd20bd, - 0x01e4b604, - 0xfe051efd, - 0x097e0018, - 0x0ef40005, -/* 0x0465: main_not_ctx_xfer */ - 0x10ef94d4, - 0x7e01f5f0, - 0xf40002f8, -/* 0x0472: ih */ - 0x80f9c70e, - 0xf90188fe, - 0xf990f980, - 0xf9b0f9a0, - 0xf9e0f9d0, - 0x4a04bdf0, - 0xaacf0200, - 0x04abc400, - 0x0d1f0bf4, - 0x1a004e24, - 0x4f00eecf, - 0xffcf1900, - 0x00047e00, - 0x40010e00, - 0x0ef61d00, -/* 0x04af: ih_no_fifo */ - 0x4004bd00, - 0x0af60100, - 0xfc04bd00, - 0xfce0fcf0, - 0xfcb0fcd0, - 0xfc90fca0, - 0x0088fe80, - 0x32f480fc, -/* 0x04cf: hub_barrier_done */ - 0x0f01f800, - 0x040e9801, - 0xb204febb, - 0x94188eff, - 0x008f7e40, -/* 0x04e3: ctx_redswitch */ - 0x0f00f800, - 0x85008020, - 0x000ff601, - 0x080e04bd, -/* 0x04f0: ctx_redswitch_delay */ - 0xf401e2b6, - 0xf5f1fd1b, - 0xf5f10800, - 0x00800200, - 0x0ff60185, - 0xf804bd00, -/* 0x0509: ctx_xfer */ - 0x81008000, - 0x000ff602, - 0x11f404bd, - 0x04e37e07, -/* 0x0519: ctx_xfer_not_load */ - 0x02167e00, - 0x8024bd00, - 0xf60247fc, + 0xb60170b6, + 0x1bf40162, + 0x0050b7bf, + 0x0142b608, + 0x0fa81bf4, + 0x8effb23f, + 0xf0501d60, + 0x8f7e01e5, + 0x0d0f0000, + 0xa88effb2, + 0xe5f0501d, + 0x008f7e01, + 0x03147e00, + 0x01008000, + 0x0003f602, + 0x24bd04bd, + 0x801f29f0, + 0xf6023000, 0x04bd0002, - 0xb6012cf0, - 0xfc800320, - 0x02f6024a, +/* 0x0574: main */ + 0xf40031f4, + 0x240d0028, + 0x0000377e, + 0xb0f401f4, + 0x18f404e4, + 0x0181fe1d, + 0x20bd0602, + 0xb60412fd, + 0x1efd01e4, + 0x0018fe05, + 0x0006477e, +/* 0x05a3: main_not_ctx_xfer */ + 0x94d40ef4, + 0xf5f010ef, + 0x02f87e01, + 0xc70ef400, +/* 0x05b0: ih */ + 0x88fe80f9, + 0xf980f901, + 0xf9a0f990, + 0xf9d0f9b0, + 0xbdf0f9e0, + 0x02004a04, + 0xc400aacf, + 0x0bf404ab, + 0x4e240d1f, + 0xeecf1a00, + 0x19004f00, + 0x7e00ffcf, + 0x0e000004, + 0x1d004001, + 0xbd000ef6, +/* 0x05ed: ih_no_fifo */ + 0x01004004, + 0xbd000af6, + 0xfcf0fc04, + 0xfcd0fce0, + 0xfca0fcb0, + 0xfe80fc90, + 0x80fc0088, + 0xf80032f4, +/* 0x060d: hub_barrier_done */ + 0x98010f01, + 0xfebb040e, + 0x8effb204, + 0x7e409418, + 0xf800008f, +/* 0x0621: ctx_redswitch */ + 0x80200f00, + 0xf6018500, + 0x04bd000f, +/* 0x062e: ctx_redswitch_delay */ + 0xe2b6080e, + 0xfd1bf401, + 0x0800f5f1, + 0x0200f5f1, + 0x01850080, + 0xbd000ff6, +/* 0x0647: ctx_xfer */ + 0x8000f804, + 0xf6028100, + 0x04bd000f, + 0xc48effb2, + 0xe5f0501d, + 0x008f7e01, + 0x0711f400, + 0x0006217e, +/* 0x0664: ctx_xfer_not_load */ + 0x0002167e, + 0xfc8024bd, + 0x02f60247, 0xf004bd00, + 0x20b6012c, + 0x4afc8003, + 0x0002f602, + 0x0c0f04bd, + 0xa88effb2, + 0xe5f0501d, + 0x008f7e01, + 0x03147e00, + 0xb23f0f00, + 0x1d608eff, + 0x01e5f050, + 0x00008f7e, + 0xffb2000f, + 0x501d9c8e, + 0x7e01e5f0, + 0x0f00008f, + 0x03147e01, + 0x01fcf000, + 0xb203f0b6, + 0x1da88eff, + 0x01e5f050, + 0x00008f7e, + 0xf001acf0, + 0x008b02a5, + 0x0c985000, + 0x0fc4b604, + 0x9800bcbb, + 0x0d98000c, + 0x7e000e01, + 0xf000013d, + 0x008b01ac, + 0x0c985040, + 0x0fc4b604, + 0x9800bcbb, + 0x0d98010c, + 0x060f9802, + 0x7e08004e, + 0xf000013d, 0xa5f001ac, - 0x00008b02, + 0x30008b04, 0x040c9850, 0xbb0fc4b6, 0x0c9800bc, - 0x010d9800, - 0x3d7e000e, - 0xacf00001, - 0x40008b01, - 0x040c9850, - 0xbb0fc4b6, - 0x0c9800bc, - 0x020d9801, - 0x4e060f98, - 0x3d7e0800, - 0xacf00001, - 0x04a5f001, - 0x5030008b, - 0xb6040c98, - 0xbcbb0fc4, - 0x020c9800, - 0x98030d98, - 0x004e080f, - 0x013d7e02, - 0x020a7e00, - 0x0601f400, -/* 0x05a3: ctx_xfer_post */ - 0x7e0712f4, -/* 0x05a7: ctx_xfer_done */ - 0x7e000227, - 0xf80004cf, + 0x030d9802, + 0x4e080f98, + 0x3d7e0200, + 0x0a7e0001, + 0x147e0002, + 0x01f40003, + 0x1a12f406, +/* 0x073c: ctx_xfer_post */ + 0x0002277e, + 0xffb20d0f, + 0x501da88e, + 0x7e01e5f0, + 0x7e00008f, +/* 0x0753: ctx_xfer_done */ + 0x7e000314, + 0xf800060d, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/macros.fuc b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/macros.fuc index 2a0b0f844299..fa618066441a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/macros.fuc +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/macros.fuc @@ -29,6 +29,7 @@ #define GK100 0xe0 #define GK110 0xf0 #define GK208 0x108 +#define GM107 0x117 #define NV_PGRAPH_TRAPPED_ADDR 0x400704 #define NV_PGRAPH_TRAPPED_DATA_LO 0x400708 @@ -79,7 +80,9 @@ #define NV_PGRAPH_FECS_MMCTX_MULTI_STRIDE 0x409718 #define NV_PGRAPH_FECS_MMCTX_MULTI_MASK 0x40971c #define NV_PGRAPH_FECS_MMCTX_QUEUE 0x409720 +#define NV_PGRAPH_FECS_MMIO_BASE 0x409724 #define NV_PGRAPH_FECS_MMIO_CTRL 0x409728 +#define NV_PGRAPH_FECS_MMIO_CTRL_BASE_ENABLE 0x00000001 #define NV_PGRAPH_FECS_MMIO_RDVAL 0x40972c #define NV_PGRAPH_FECS_MMIO_WRVAL 0x409730 #define NV_PGRAPH_FECS_MMCTX_LOAD_COUNT 0x40974c @@ -147,6 +150,11 @@ #define NV_PGRAPH_GPCX_GPCCS_MYINDEX 0x41a618 #define NV_PGRAPH_GPCX_GPCCS_MMCTX_SAVE_SWBASE 0x41a700 #define NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_SWBASE 0x41a704 +#define NV_PGRAPH_GPCX_GPCCS_MMIO_BASE 0x41a724 +#define NV_PGRAPH_GPCX_GPCCS_MMIO_CTRL 0x41a728 +#define NV_PGRAPH_GPCX_GPCCS_MMIO_CTRL_BASE_ENABLE 0x00000001 +#define NV_PGRAPH_GPCX_GPCCS_MMIO_RDVAL 0x41a72c +#define NV_PGRAPH_GPCX_GPCCS_MMIO_WRVAL 0x41a730 #define NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_COUNT 0x41a74c #if CHIPSET < GK110 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(n) ((n) * 4 + 0x41a800) @@ -164,6 +172,29 @@ #define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE 0x00000003 #define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_LOAD 0x00000004 #define NV_PGRAPH_GPCX_GPCCS_MEM_BASE 0x41aa04 +#define NV_PGRAPH_GPCX_GPCCS_TPC_STATUS 0x41acfc + +#define NV_PGRAPH_GPC0_TPC0 0x504000 +#define NV_PGRAPH_GPC0_TPC0__SIZE 0x000800 + +#define NV_PGRAPH_GPC0_TPCX_STRAND_INDEX 0x501d60 +#define NV_PGRAPH_GPC0_TPCX_STRAND_INDEX_ALL 0x0000003f +#define NV_PGRAPH_GPC0_TPCX_STRAND_DATA 0x501d98 +#define NV_PGRAPH_GPC0_TPCX_STRAND_SELECT 0x501d9c +#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD 0x501da8 +#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_SEEK 0x00000001 +#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_GET_INFO 0x00000002 +#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_SAVE 0x00000003 +#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_LOAD 0x00000004 +#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_ENABLE 0x0000000c +#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_DISABLE 0x0000000d +#define NV_PGRAPH_GPC0_TPCX_STRAND_MEM_BASE 0x501dc4 + +#define NV_TPC_STRAND_INDEX 0x560 +#define NV_TPC_STRAND_CNT 0x570 +#define NV_TPC_STRAND_SAVE_SWBASE 0x588 +#define NV_TPC_STRAND_LOAD_SWBASE 0x58c +#define NV_TPC_STRAND_WORDS 0x590 #define mmctx_data(r,c) .b32 (((c - 1) << 26) | r) #define queue_init .skip 72 // (2 * 4) + ((8 * 4) * 2) @@ -178,6 +209,7 @@ #define T_SAVE 7 #define T_LCHAN 8 #define T_LCTXH 9 +#define T_STRTPC 10 #if CHIPSET < GK208 #define imm32(reg,val) /* diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 1dd482e9da77..5606c25e5d02 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -236,7 +236,7 @@ static int gf100_gr_set_shader_exceptions(struct nvkm_object *object, u32 mthd, void *pdata, u32 size) { - struct gf100_gr_priv *priv = (void *)nv_engine(object); + struct gf100_gr_priv *priv = (void *)object->engine; if (size >= sizeof(u32)) { u32 data = *(u32 *)pdata ? 0xffffffff : 0x00000000; nv_wr32(priv, 0x419e44, data); @@ -260,8 +260,8 @@ gf100_gr_90c0_omthds[] = { struct nvkm_oclass gf100_gr_sclass[] = { - { 0x902d, &nvkm_object_ofuncs }, - { 0x9039, &nvkm_object_ofuncs }, + { FERMI_TWOD_A, &nvkm_object_ofuncs }, + { FERMI_MEMORY_TO_MEMORY_FORMAT_A, &nvkm_object_ofuncs }, { FERMI_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, { FERMI_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, {} @@ -1097,12 +1097,26 @@ gf100_gr_intr(struct nvkm_subdev *subdev) u32 subc = (addr & 0x00070000) >> 16; u32 data = nv_rd32(priv, 0x400708); u32 code = nv_rd32(priv, 0x400110); - u32 class = nv_rd32(priv, 0x404200 + (subc * 4)); + u32 class; int chid; + if (nv_device(priv)->card_type < NV_E0 || subc < 4) + class = nv_rd32(priv, 0x404200 + (subc * 4)); + else + class = 0x0000; + engctx = nvkm_engctx_get(engine, inst); chid = pfifo->chid(pfifo, engctx); + if (stat & 0x00000001) { + /* + * notifier interrupt, only needed for cyclestats + * can be safely ignored + */ + nv_wr32(priv, 0x400100, 0x00000001); + stat &= ~0x00000001; + } + if (stat & 0x00000010) { handle = nvkm_handle_get_class(engctx, class); if (!handle || nv_call(handle->object, mthd, data)) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index aeeca1be9cf0..8af1a89eda84 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -124,10 +124,12 @@ void gf100_gr_dtor(struct nvkm_object *); int gf100_gr_init(struct nvkm_object *); void gf100_gr_zbc_init(struct gf100_gr_priv *); -int gk104_gr_fini(struct nvkm_object *, bool); +int gk104_gr_ctor(struct nvkm_object *, struct nvkm_object *, + struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); int gk104_gr_init(struct nvkm_object *); -int gk110_gr_fini(struct nvkm_object *, bool); +int gm204_gr_init(struct nvkm_object *); extern struct nvkm_ofuncs gf100_fermi_ofuncs; @@ -136,6 +138,7 @@ extern struct nvkm_omthds gf100_gr_9097_omthds[]; extern struct nvkm_omthds gf100_gr_90c0_omthds[]; extern struct nvkm_oclass gf110_gr_sclass[]; extern struct nvkm_oclass gk110_gr_sclass[]; +extern struct nvkm_oclass gm204_gr_sclass[]; struct gf100_gr_init { u32 addr; @@ -247,4 +250,17 @@ extern const struct gf100_gr_init gk110_gr_init_tex_0[]; extern const struct gf100_gr_init gk110_gr_init_sm_0[]; extern const struct gf100_gr_init gk208_gr_init_gpc_unk_0[]; + +extern const struct gf100_gr_init gm107_gr_init_scc_0[]; +extern const struct gf100_gr_init gm107_gr_init_prop_0[]; +extern const struct gf100_gr_init gm107_gr_init_setup_1[]; +extern const struct gf100_gr_init gm107_gr_init_zcull_0[]; +extern const struct gf100_gr_init gm107_gr_init_gpc_unk_1[]; +extern const struct gf100_gr_init gm107_gr_init_tex_0[]; +extern const struct gf100_gr_init gm107_gr_init_l1c_0[]; +extern const struct gf100_gr_init gm107_gr_init_wwdx_0[]; +extern const struct gf100_gr_init gm107_gr_init_cbm_0[]; +void gm107_gr_init_bios(struct gf100_gr_priv *); + +extern const struct gf100_gr_pack gm204_gr_pack_mmio[]; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c index 5362c8176e64..8df73421c78c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c @@ -32,8 +32,8 @@ static struct nvkm_oclass gf108_gr_sclass[] = { - { 0x902d, &nvkm_object_ofuncs }, - { 0x9039, &nvkm_object_ofuncs }, + { FERMI_TWOD_A, &nvkm_object_ofuncs }, + { FERMI_MEMORY_TO_MEMORY_FORMAT_A, &nvkm_object_ofuncs }, { FERMI_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, { FERMI_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, { FERMI_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c index 88beb491b7b8..ef76e2dd1d31 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c @@ -32,8 +32,8 @@ struct nvkm_oclass gf110_gr_sclass[] = { - { 0x902d, &nvkm_object_ofuncs }, - { 0x9039, &nvkm_object_ofuncs }, + { FERMI_TWOD_A, &nvkm_object_ofuncs }, + { FERMI_MEMORY_TO_MEMORY_FORMAT_A, &nvkm_object_ofuncs }, { FERMI_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, { FERMI_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, { FERMI_C, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c index 489fdd94b885..46f7844eca70 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c @@ -34,8 +34,8 @@ static struct nvkm_oclass gk104_gr_sclass[] = { - { 0x902d, &nvkm_object_ofuncs }, - { 0xa040, &nvkm_object_ofuncs }, + { FERMI_TWOD_A, &nvkm_object_ofuncs }, + { KEPLER_INLINE_TO_MEMORY_A, &nvkm_object_ofuncs }, { KEPLER_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, { KEPLER_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, {} @@ -310,6 +310,17 @@ gk104_gr_init(struct nvkm_object *object) return gf100_gr_init_ctxctl(priv); } +int +gk104_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, + struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + struct nvkm_pmu *pmu = nvkm_pmu(parent); + if (pmu) + pmu->pgob(pmu, false); + return gf100_gr_ctor(parent, engine, oclass, data, size, pobject); +} + #include "fuc/hubgk104.fuc3.h" static struct gf100_gr_ucode @@ -334,7 +345,7 @@ struct nvkm_oclass * gk104_gr_oclass = &(struct gf100_gr_oclass) { .base.handle = NV_ENGINE(GR, 0xe4), .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, + .ctor = gk104_gr_ctor, .dtor = gf100_gr_dtor, .init = gk104_gr_init, .fini = _nvkm_gr_fini, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c index 78e03ab1608e..f4cd8e5546af 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c @@ -34,8 +34,8 @@ struct nvkm_oclass gk110_gr_sclass[] = { - { 0x902d, &nvkm_object_ofuncs }, - { 0xa140, &nvkm_object_ofuncs }, + { FERMI_TWOD_A, &nvkm_object_ofuncs }, + { KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs }, { KEPLER_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, { KEPLER_COMPUTE_B, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, {} @@ -173,43 +173,6 @@ gk110_gr_pack_mmio[] = { * PGRAPH engine/subdev functions ******************************************************************************/ -int -gk110_gr_fini(struct nvkm_object *object, bool suspend) -{ - struct gf100_gr_priv *priv = (void *)object; - static const struct { - u32 addr; - u32 data; - } magic[] = { - { 0x020520, 0xfffffffc }, - { 0x020524, 0xfffffffe }, - { 0x020524, 0xfffffffc }, - { 0x020524, 0xfffffff8 }, - { 0x020524, 0xffffffe0 }, - { 0x020530, 0xfffffffe }, - { 0x02052c, 0xfffffffa }, - { 0x02052c, 0xfffffff0 }, - { 0x02052c, 0xffffffc0 }, - { 0x02052c, 0xffffff00 }, - { 0x02052c, 0xfffffc00 }, - { 0x02052c, 0xfffcfc00 }, - { 0x02052c, 0xfff0fc00 }, - { 0x02052c, 0xff80fc00 }, - { 0x020528, 0xfffffffe }, - { 0x020528, 0xfffffffc }, - }; - int i; - - nv_mask(priv, 0x000200, 0x08001000, 0x00000000); - nv_mask(priv, 0x0206b4, 0x00000000, 0x00000000); - for (i = 0; i < ARRAY_SIZE(magic); i++) { - nv_wr32(priv, magic[i].addr, magic[i].data); - nv_wait(priv, magic[i].addr, 0x80000000, 0x00000000); - } - - return nvkm_gr_fini(&priv->base, suspend); -} - #include "fuc/hubgk110.fuc3.h" struct gf100_gr_ucode @@ -234,10 +197,10 @@ struct nvkm_oclass * gk110_gr_oclass = &(struct gf100_gr_oclass) { .base.handle = NV_ENGINE(GR, 0xf0), .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, + .ctor = gk104_gr_ctor, .dtor = gf100_gr_dtor, .init = gk104_gr_init, - .fini = gk110_gr_fini, + .fini = _nvkm_gr_fini, }, .cclass = &gk110_grctx_oclass, .sclass = gk110_gr_sclass, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c index 5292c5a9a38c..9ff9eab0ccaf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c @@ -102,10 +102,10 @@ struct nvkm_oclass * gk110b_gr_oclass = &(struct gf100_gr_oclass) { .base.handle = NV_ENGINE(GR, 0xf1), .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, + .ctor = gk104_gr_ctor, .dtor = gf100_gr_dtor, .init = gk104_gr_init, - .fini = gk110_gr_fini, + .fini = _nvkm_gr_fini, }, .cclass = &gk110b_grctx_oclass, .sclass = gk110_gr_sclass, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c index ae6b853173b6..85f44a3d5d11 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c @@ -34,10 +34,10 @@ static struct nvkm_oclass gk208_gr_sclass[] = { - { 0x902d, &nvkm_object_ofuncs }, - { 0xa140, &nvkm_object_ofuncs }, + { FERMI_TWOD_A, &nvkm_object_ofuncs }, + { KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs }, { KEPLER_B, &gf100_fermi_ofuncs }, - { 0xa1c0, &nvkm_object_ofuncs }, + { KEPLER_COMPUTE_B, &nvkm_object_ofuncs }, {} }; @@ -152,43 +152,6 @@ gk208_gr_pack_mmio[] = { * PGRAPH engine/subdev functions ******************************************************************************/ -static int -gk208_gr_fini(struct nvkm_object *object, bool suspend) -{ - struct gf100_gr_priv *priv = (void *)object; - static const struct { - u32 addr; - u32 data; - } magic[] = { - { 0x020520, 0xfffffffc }, - { 0x020524, 0xfffffffe }, - { 0x020524, 0xfffffffc }, - { 0x020524, 0xfffffff8 }, - { 0x020524, 0xffffffe0 }, - { 0x020530, 0xfffffffe }, - { 0x02052c, 0xfffffffa }, - { 0x02052c, 0xfffffff0 }, - { 0x02052c, 0xffffffc0 }, - { 0x02052c, 0xffffff00 }, - { 0x02052c, 0xfffffc00 }, - { 0x02052c, 0xfffcfc00 }, - { 0x02052c, 0xfff0fc00 }, - { 0x02052c, 0xff80fc00 }, - { 0x020528, 0xfffffffe }, - { 0x020528, 0xfffffffc }, - }; - int i; - - nv_mask(priv, 0x000200, 0x08001000, 0x00000000); - nv_mask(priv, 0x0206b4, 0x00000000, 0x00000000); - for (i = 0; i < ARRAY_SIZE(magic); i++) { - nv_wr32(priv, magic[i].addr, magic[i].data); - nv_wait(priv, magic[i].addr, 0x80000000, 0x00000000); - } - - return nvkm_gr_fini(&priv->base, suspend); -} - #include "fuc/hubgk208.fuc5.h" static struct gf100_gr_ucode @@ -213,10 +176,10 @@ struct nvkm_oclass * gk208_gr_oclass = &(struct gf100_gr_oclass) { .base.handle = NV_ENGINE(GR, 0x08), .base.ofuncs = &(struct nvkm_ofuncs) { - .ctor = gf100_gr_ctor, + .ctor = gk104_gr_ctor, .dtor = gf100_gr_dtor, .init = gk104_gr_init, - .fini = gk208_gr_fini, + .fini = _nvkm_gr_fini, }, .cclass = &gk208_grctx_oclass, .sclass = gk208_gr_sclass, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index 213755534084..40ff5eb9180c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -26,8 +26,8 @@ static struct nvkm_oclass gk20a_gr_sclass[] = { - { 0x902d, &nvkm_object_ofuncs }, - { 0xa040, &nvkm_object_ofuncs }, + { FERMI_TWOD_A, &nvkm_object_ofuncs }, + { KEPLER_INLINE_TO_MEMORY_A, &nvkm_object_ofuncs }, { KEPLER_C, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, { KEPLER_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, {} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c index 124492b8a2d6..a5ebd459bc24 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c @@ -35,8 +35,8 @@ static struct nvkm_oclass gm107_gr_sclass[] = { - { 0x902d, &nvkm_object_ofuncs }, - { 0xa140, &nvkm_object_ofuncs }, + { FERMI_TWOD_A, &nvkm_object_ofuncs }, + { KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs }, { MAXWELL_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, { MAXWELL_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, {} @@ -71,7 +71,7 @@ gm107_gr_init_ds_0[] = { {} }; -static const struct gf100_gr_init +const struct gf100_gr_init gm107_gr_init_scc_0[] = { { 0x40803c, 1, 0x04, 0x00000010 }, {} @@ -85,14 +85,14 @@ gm107_gr_init_sked_0[] = { {} }; -static const struct gf100_gr_init +const struct gf100_gr_init gm107_gr_init_prop_0[] = { { 0x418408, 1, 0x04, 0x00000000 }, { 0x4184a0, 1, 0x04, 0x00000000 }, {} }; -static const struct gf100_gr_init +const struct gf100_gr_init gm107_gr_init_setup_1[] = { { 0x4188c8, 2, 0x04, 0x00000000 }, { 0x4188d0, 1, 0x04, 0x00010000 }, @@ -100,7 +100,7 @@ gm107_gr_init_setup_1[] = { {} }; -static const struct gf100_gr_init +const struct gf100_gr_init gm107_gr_init_zcull_0[] = { { 0x418910, 1, 0x04, 0x00010001 }, { 0x418914, 1, 0x04, 0x00000301 }, @@ -111,7 +111,7 @@ gm107_gr_init_zcull_0[] = { {} }; -static const struct gf100_gr_init +const struct gf100_gr_init gm107_gr_init_gpc_unk_1[] = { { 0x418d00, 1, 0x04, 0x00000000 }, { 0x418f00, 1, 0x04, 0x00000400 }, @@ -134,7 +134,7 @@ gm107_gr_init_tpccs_0[] = { {} }; -static const struct gf100_gr_init +const struct gf100_gr_init gm107_gr_init_tex_0[] = { { 0x419ab0, 1, 0x04, 0x00000000 }, { 0x419ab8, 1, 0x04, 0x000000e7 }, @@ -160,7 +160,7 @@ gm107_gr_init_pe_0[] = { {} }; -static const struct gf100_gr_init +const struct gf100_gr_init gm107_gr_init_l1c_0[] = { { 0x419c98, 1, 0x04, 0x00000000 }, { 0x419cc0, 2, 0x04, 0x00000000 }, @@ -206,14 +206,14 @@ gm107_gr_init_pes_0[] = { {} }; -static const struct gf100_gr_init +const struct gf100_gr_init gm107_gr_init_wwdx_0[] = { { 0x41bfd4, 1, 0x04, 0x00800000 }, { 0x41bfdc, 1, 0x04, 0x00000000 }, {} }; -static const struct gf100_gr_init +const struct gf100_gr_init gm107_gr_init_cbm_0[] = { { 0x41becc, 1, 0x04, 0x00000000 }, {} @@ -291,7 +291,7 @@ gm107_gr_pack_mmio[] = { * PGRAPH engine/subdev functions ******************************************************************************/ -static void +void gm107_gr_init_bios(struct gf100_gr_priv *priv) { static const struct { @@ -464,7 +464,7 @@ gm107_gr_oclass = &(struct gf100_gr_oclass) { .cclass = &gm107_grctx_oclass, .sclass = gm107_gr_sclass, .mmio = gm107_gr_pack_mmio, - .fecs.ucode = 0 ? &gm107_gr_fecs_ucode : NULL, + .fecs.ucode = &gm107_gr_fecs_ucode, .gpccs.ucode = &gm107_gr_gpccs_ucode, .ppc_nr = 2, }.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm204.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm204.c new file mode 100644 index 000000000000..2f5eadd12a9b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm204.c @@ -0,0 +1,387 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * 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. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "gf100.h" +#include "ctxgf100.h" + +#include <nvif/class.h> + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +struct nvkm_oclass +gm204_gr_sclass[] = { + { FERMI_TWOD_A, &nvkm_object_ofuncs }, + { KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs }, + { MAXWELL_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds }, + { MAXWELL_COMPUTE_B, &nvkm_object_ofuncs, gf100_gr_90c0_omthds }, + {} +}; + +/******************************************************************************* + * PGRAPH register lists + ******************************************************************************/ + +static const struct gf100_gr_init +gm204_gr_init_main_0[] = { + { 0x400080, 1, 0x04, 0x003003e2 }, + { 0x400088, 1, 0x04, 0xe007bfe7 }, + { 0x40008c, 1, 0x04, 0x00060000 }, + { 0x400090, 1, 0x04, 0x00000030 }, + { 0x40013c, 1, 0x04, 0x003901f3 }, + { 0x400140, 1, 0x04, 0x00000100 }, + { 0x400144, 1, 0x04, 0x00000000 }, + { 0x400148, 1, 0x04, 0x00000110 }, + { 0x400138, 1, 0x04, 0x00000000 }, + { 0x400130, 2, 0x04, 0x00000000 }, + { 0x400124, 1, 0x04, 0x00000002 }, + {} +}; + +static const struct gf100_gr_init +gm204_gr_init_fe_0[] = { + { 0x40415c, 1, 0x04, 0x00000000 }, + { 0x404170, 1, 0x04, 0x00000000 }, + { 0x4041b4, 1, 0x04, 0x00000000 }, + { 0x4041b8, 1, 0x04, 0x00000010 }, + {} +}; + +static const struct gf100_gr_init +gm204_gr_init_ds_0[] = { + { 0x40583c, 1, 0x04, 0x00000000 }, + { 0x405844, 1, 0x04, 0x00ffffff }, + { 0x40584c, 1, 0x04, 0x00000001 }, + { 0x405850, 1, 0x04, 0x00000000 }, + { 0x405900, 1, 0x04, 0x00000000 }, + { 0x405908, 1, 0x04, 0x00000000 }, + {} +}; + +static const struct gf100_gr_init +gm204_gr_init_sked_0[] = { + { 0x407010, 1, 0x04, 0x00000000 }, + { 0x407040, 1, 0x04, 0x80440434 }, + { 0x407048, 1, 0x04, 0x00000008 }, + {} +}; + +static const struct gf100_gr_init +gm204_gr_init_tpccs_0[] = { + { 0x419d60, 1, 0x04, 0x0000003f }, + { 0x419d88, 3, 0x04, 0x00000000 }, + { 0x419dc4, 1, 0x04, 0x00000000 }, + { 0x419dc8, 1, 0x04, 0x00000501 }, + { 0x419dd0, 1, 0x04, 0x00000000 }, + { 0x419dd4, 1, 0x04, 0x00000100 }, + { 0x419dd8, 1, 0x04, 0x00000001 }, + { 0x419ddc, 1, 0x04, 0x00000002 }, + { 0x419de0, 1, 0x04, 0x00000001 }, + { 0x419de8, 1, 0x04, 0x000000cc }, + { 0x419dec, 1, 0x04, 0x00000000 }, + { 0x419df0, 1, 0x04, 0x000000cc }, + { 0x419df4, 1, 0x04, 0x00000000 }, + { 0x419d0c, 1, 0x04, 0x00000000 }, + { 0x419d10, 1, 0x04, 0x00000014 }, + {} +}; + +static const struct gf100_gr_init +gm204_gr_init_pe_0[] = { + { 0x419900, 1, 0x04, 0x000000ff }, + { 0x419810, 1, 0x04, 0x00000000 }, + { 0x41980c, 1, 0x04, 0x00000010 }, + { 0x419844, 1, 0x04, 0x00000000 }, + { 0x419838, 1, 0x04, 0x000000ff }, + { 0x419850, 1, 0x04, 0x00000004 }, + { 0x419854, 2, 0x04, 0x00000000 }, + { 0x419894, 3, 0x04, 0x00100401 }, + {} +}; + +static const struct gf100_gr_init +gm204_gr_init_sm_0[] = { + { 0x419e30, 1, 0x04, 0x000000ff }, + { 0x419e00, 1, 0x04, 0x00000000 }, + { 0x419ea0, 1, 0x04, 0x00000000 }, + { 0x419ee4, 1, 0x04, 0x00000000 }, + { 0x419ea4, 1, 0x04, 0x00000100 }, + { 0x419ea8, 1, 0x04, 0x00000000 }, + { 0x419ee8, 1, 0x04, 0x00000091 }, + { 0x419eb4, 1, 0x04, 0x00000000 }, + { 0x419ebc, 2, 0x04, 0x00000000 }, + { 0x419edc, 1, 0x04, 0x000c1810 }, + { 0x419ed8, 1, 0x04, 0x00000000 }, + { 0x419ee0, 1, 0x04, 0x00000000 }, + {} +}; + +static const struct gf100_gr_init +gm204_gr_init_l1c_1[] = { + { 0x419cf8, 2, 0x04, 0x00000000 }, + {} +}; + +static const struct gf100_gr_init +gm204_gr_init_sm_1[] = { + { 0x419f74, 1, 0x04, 0x00055155 }, + { 0x419f80, 4, 0x04, 0x00000000 }, + {} +}; + +static const struct gf100_gr_init +gm204_gr_init_l1c_2[] = { + { 0x419ccc, 2, 0x04, 0x00000000 }, + { 0x419c80, 1, 0x04, 0x3f006022 }, + { 0x419c88, 1, 0x04, 0x00210000 }, + {} +}; + +static const struct gf100_gr_init +gm204_gr_init_pes_0[] = { + { 0x41be50, 1, 0x04, 0x000000ff }, + { 0x41be04, 1, 0x04, 0x00000000 }, + { 0x41be08, 1, 0x04, 0x00000004 }, + { 0x41be0c, 1, 0x04, 0x00000008 }, + { 0x41be10, 1, 0x04, 0x2e3b8bc7 }, + { 0x41be14, 2, 0x04, 0x00000000 }, + { 0x41be3c, 5, 0x04, 0x00100401 }, + {} +}; + +static const struct gf100_gr_init +gm204_gr_init_be_0[] = { + { 0x408890, 1, 0x04, 0x000000ff }, + { 0x40880c, 1, 0x04, 0x00000000 }, + { 0x408850, 1, 0x04, 0x00000004 }, + { 0x408878, 1, 0x04, 0x01b4201c }, + { 0x40887c, 1, 0x04, 0x80004c55 }, + { 0x408880, 1, 0x04, 0x0018c258 }, + { 0x408884, 1, 0x04, 0x0000160f }, + { 0x408974, 1, 0x04, 0x000000ff }, + { 0x408910, 9, 0x04, 0x00000000 }, + { 0x408950, 1, 0x04, 0x00000000 }, + { 0x408954, 1, 0x04, 0x0000ffff }, + { 0x408958, 1, 0x04, 0x00000034 }, + { 0x40895c, 1, 0x04, 0x84b17403 }, + { 0x408960, 1, 0x04, 0x04c1884f }, + { 0x408964, 1, 0x04, 0x04714445 }, + { 0x408968, 1, 0x04, 0x0280802f }, + { 0x40896c, 1, 0x04, 0x04304856 }, + { 0x408970, 1, 0x04, 0x00012800 }, + { 0x408984, 1, 0x04, 0x00000000 }, + { 0x408988, 1, 0x04, 0x08040201 }, + { 0x40898c, 1, 0x04, 0x80402010 }, + {} +}; + +const struct gf100_gr_pack +gm204_gr_pack_mmio[] = { + { gm204_gr_init_main_0 }, + { gm204_gr_init_fe_0 }, + { gf100_gr_init_pri_0 }, + { gf100_gr_init_rstr2d_0 }, + { gf100_gr_init_pd_0 }, + { gm204_gr_init_ds_0 }, + { gm107_gr_init_scc_0 }, + { gm204_gr_init_sked_0 }, + { gk110_gr_init_cwd_0 }, + { gm107_gr_init_prop_0 }, + { gk208_gr_init_gpc_unk_0 }, + { gf100_gr_init_setup_0 }, + { gf100_gr_init_crstr_0 }, + { gm107_gr_init_setup_1 }, + { gm107_gr_init_zcull_0 }, + { gf100_gr_init_gpm_0 }, + { gm107_gr_init_gpc_unk_1 }, + { gf100_gr_init_gcc_0 }, + { gm204_gr_init_tpccs_0 }, + { gm107_gr_init_tex_0 }, + { gm204_gr_init_pe_0 }, + { gm107_gr_init_l1c_0 }, + { gf100_gr_init_mpc_0 }, + { gm204_gr_init_sm_0 }, + { gm204_gr_init_l1c_1 }, + { gm204_gr_init_sm_1 }, + { gm204_gr_init_l1c_2 }, + { gm204_gr_init_pes_0 }, + { gm107_gr_init_wwdx_0 }, + { gm107_gr_init_cbm_0 }, + { gm204_gr_init_be_0 }, + {} +}; + +const struct gf100_gr_pack * +gm204_gr_data[] = { + gm204_gr_pack_mmio, + NULL +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +gm204_gr_init_ctxctl(struct gf100_gr_priv *priv) +{ + return 0; +} + +int +gm204_gr_init(struct nvkm_object *object) +{ + struct gf100_gr_oclass *oclass = (void *)object->oclass; + struct gf100_gr_priv *priv = (void *)object; + const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); + u32 data[TPC_MAX / 8] = {}; + u8 tpcnr[GPC_MAX]; + int gpc, tpc, ppc, rop; + int ret, i; + u32 tmp; + + ret = nvkm_gr_init(&priv->base); + if (ret) + return ret; + + tmp = nv_rd32(priv, 0x100c80); /*XXX: mask? */ + nv_wr32(priv, 0x418880, 0x00001000 | (tmp & 0x00000fff)); + nv_wr32(priv, 0x418890, 0x00000000); + nv_wr32(priv, 0x418894, 0x00000000); + nv_wr32(priv, 0x4188b4, priv->unk4188b4->addr >> 8); + nv_wr32(priv, 0x4188b8, priv->unk4188b8->addr >> 8); + nv_mask(priv, 0x4188b0, 0x00040000, 0x00040000); + + /*XXX: belongs in fb */ + nv_wr32(priv, 0x100cc8, priv->unk4188b4->addr >> 8); + nv_wr32(priv, 0x100ccc, priv->unk4188b8->addr >> 8); + nv_mask(priv, 0x100cc4, 0x00040000, 0x00040000); + + gf100_gr_mmio(priv, oclass->mmio); + + gm107_gr_init_bios(priv); + + nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001); + + memset(data, 0x00, sizeof(data)); + memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); + for (i = 0, gpc = -1; i < priv->tpc_total; i++) { + do { + gpc = (gpc + 1) % priv->gpc_nr; + } while (!tpcnr[gpc]); + tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; + + data[i / 8] |= tpc << ((i % 8) * 4); + } + + nv_wr32(priv, GPC_BCAST(0x0980), data[0]); + nv_wr32(priv, GPC_BCAST(0x0984), data[1]); + nv_wr32(priv, GPC_BCAST(0x0988), data[2]); + nv_wr32(priv, GPC_BCAST(0x098c), data[3]); + + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + nv_wr32(priv, GPC_UNIT(gpc, 0x0914), + priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]); + nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | + priv->tpc_total); + nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); + } + + nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918); + nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); + nv_wr32(priv, GPC_BCAST(0x033c), nv_rd32(priv, 0x100804)); + + nv_wr32(priv, 0x400500, 0x00010001); + nv_wr32(priv, 0x400100, 0xffffffff); + nv_wr32(priv, 0x40013c, 0xffffffff); + nv_wr32(priv, 0x400124, 0x00000002); + nv_wr32(priv, 0x409c24, 0x000e0000); + nv_wr32(priv, 0x405848, 0xc0000000); + nv_wr32(priv, 0x40584c, 0x00000001); + nv_wr32(priv, 0x404000, 0xc0000000); + nv_wr32(priv, 0x404600, 0xc0000000); + nv_wr32(priv, 0x408030, 0xc0000000); + nv_wr32(priv, 0x404490, 0xc0000000); + nv_wr32(priv, 0x406018, 0xc0000000); + nv_wr32(priv, 0x407020, 0x40000000); + nv_wr32(priv, 0x405840, 0xc0000000); + nv_wr32(priv, 0x405844, 0x00ffffff); + nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); + + for (gpc = 0; gpc < priv->gpc_nr; gpc++) { + printk(KERN_ERR "ppc %d %d\n", gpc, priv->ppc_nr[gpc]); + for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++) + nv_wr32(priv, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); + nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); + for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x430), 0xc0000000); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x00dffffe); + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x00000005); + } + nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); + nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); + } + + for (rop = 0; rop < priv->rop_nr; rop++) { + nv_wr32(priv, ROP_UNIT(rop, 0x144), 0x40000000); + nv_wr32(priv, ROP_UNIT(rop, 0x070), 0x40000000); + nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); + nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); + } + + nv_wr32(priv, 0x400108, 0xffffffff); + nv_wr32(priv, 0x400138, 0xffffffff); + nv_wr32(priv, 0x400118, 0xffffffff); + nv_wr32(priv, 0x400130, 0xffffffff); + nv_wr32(priv, 0x40011c, 0xffffffff); + nv_wr32(priv, 0x400134, 0xffffffff); + + nv_wr32(priv, 0x400054, 0x2c350f63); + + gf100_gr_zbc_init(priv); + + return gm204_gr_init_ctxctl(priv); +} + +struct nvkm_oclass * +gm204_gr_oclass = &(struct gf100_gr_oclass) { + .base.handle = NV_ENGINE(GR, 0x24), + .base.ofuncs = &(struct nvkm_ofuncs) { + .ctor = gf100_gr_ctor, + .dtor = gf100_gr_dtor, + .init = gm204_gr_init, + .fini = _nvkm_gr_fini, + }, + .cclass = &gm204_grctx_oclass, + .sclass = gm204_gr_sclass, + .mmio = gm204_gr_pack_mmio, + .ppc_nr = 2, +}.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm206.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm206.c new file mode 100644 index 000000000000..04b9733d146a --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm206.c @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * 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. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "gf100.h" +#include "ctxgf100.h" + +struct nvkm_oclass * +gm206_gr_oclass = &(struct gf100_gr_oclass) { + .base.handle = NV_ENGINE(GR, 0x26), + .base.ofuncs = &(struct nvkm_ofuncs) { + .ctor = gf100_gr_ctor, + .dtor = gf100_gr_dtor, + .init = gm204_gr_init, + .fini = _nvkm_gr_fini, + }, + .cclass = &gm206_grctx_oclass, + .sclass = gm204_gr_sclass, + .mmio = gm204_gr_pack_mmio, + .ppc_nr = 2, +}.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c index 1fbd93bbb561..f9d0eb5647fa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c @@ -52,7 +52,7 @@ acpi_read_fast(void *data, u32 offset, u32 length, struct nvkm_bios *bios) u32 start = offset & ~0x00000fff; u32 fetch = limit - start; - if (nvbios_extend(bios, limit) > 0) { + if (nvbios_extend(bios, limit) >= 0) { int ret = nouveau_acpi_get_bios_chunk(bios->data, start, fetch); if (ret == fetch) return fetch; @@ -73,7 +73,7 @@ acpi_read_slow(void *data, u32 offset, u32 length, struct nvkm_bios *bios) u32 start = offset & ~0xfff; u32 fetch = 0; - if (nvbios_extend(bios, limit) > 0) { + if (nvbios_extend(bios, limit) >= 0) { while (start + fetch < limit) { int ret = nouveau_acpi_get_bios_chunk(bios->data, start + fetch, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c index b8853bf16b23..7622b41619a0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c @@ -29,7 +29,7 @@ struct nvkm_hwsq { u32 data; struct { u8 data[512]; - u8 size; + u16 size; } c; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h index 3394a5ea8a9f..ebf709c27e3a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h @@ -11,17 +11,34 @@ struct hwsq { struct hwsq_reg { int sequence; bool force; - u32 addr[2]; + u32 addr; + u32 stride; /* in bytes */ + u32 mask; u32 data; }; static inline struct hwsq_reg +hwsq_stride(u32 addr, u32 stride, u32 mask) +{ + return (struct hwsq_reg) { + .sequence = 0, + .force = 0, + .addr = addr, + .stride = stride, + .mask = mask, + .data = 0xdeadbeef, + }; +} + +static inline struct hwsq_reg hwsq_reg2(u32 addr1, u32 addr2) { return (struct hwsq_reg) { .sequence = 0, .force = 0, - .addr = { addr1, addr2 }, + .addr = addr1, + .stride = addr2 - addr1, + .mask = 0x3, .data = 0xdeadbeef, }; } @@ -29,7 +46,14 @@ hwsq_reg2(u32 addr1, u32 addr2) static inline struct hwsq_reg hwsq_reg(u32 addr) { - return hwsq_reg2(addr, addr); + return (struct hwsq_reg) { + .sequence = 0, + .force = 0, + .addr = addr, + .stride = 0, + .mask = 0x1, + .data = 0xdeadbeef, + }; } static inline int @@ -62,18 +86,24 @@ static inline u32 hwsq_rd32(struct hwsq *ram, struct hwsq_reg *reg) { if (reg->sequence != ram->sequence) - reg->data = nv_rd32(ram->subdev, reg->addr[0]); + reg->data = nv_rd32(ram->subdev, reg->addr); return reg->data; } static inline void hwsq_wr32(struct hwsq *ram, struct hwsq_reg *reg, u32 data) { + u32 mask, off = 0; + reg->sequence = ram->sequence; reg->data = data; - if (reg->addr[0] != reg->addr[1]) - nvkm_hwsq_wr32(ram->hwsq, reg->addr[1], reg->data); - nvkm_hwsq_wr32(ram->hwsq, reg->addr[0], reg->data); + + for (mask = reg->mask; mask > 0; mask = (mask & ~1) >> 1) { + if (mask & 1) + nvkm_hwsq_wr32(ram->hwsq, reg->addr+off, reg->data); + + off += reg->stride; + } } static inline void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c index b24a9cc04b73..39a83d82e0cd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c @@ -184,7 +184,7 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei) nv_debug(clk, "setting performance state %d\n", pstatei); clk->pstate = pstatei; - if (pfb->ram->calc) { + if (pfb->ram && pfb->ram->calc) { int khz = pstate->base.domain[nv_clk_src_mem]; do { ret = pfb->ram->calc(pfb, khz); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h index 14a51a9ff7d0..7c63abf11e22 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h @@ -5,7 +5,7 @@ struct nvkm_pll_vals; struct nv04_devinit_priv { struct nvkm_devinit base; - u8 owner; + int owner; }; int nv04_devinit_ctor(struct nvkm_object *, struct nvkm_object *, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild index 904d601e8a50..d6be4c6c5408 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild @@ -37,7 +37,6 @@ nvkm-y += nvkm/subdev/fb/ramgt215.o nvkm-y += nvkm/subdev/fb/rammcp77.o nvkm-y += nvkm/subdev/fb/ramgf100.o nvkm-y += nvkm/subdev/fb/ramgk104.o -nvkm-y += nvkm/subdev/fb/ramgk20a.o nvkm-y += nvkm/subdev/fb/ramgm107.o nvkm-y += nvkm/subdev/fb/sddr2.o nvkm-y += nvkm/subdev/fb/sddr3.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index 16589fa613cd..61fde43dab71 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c @@ -55,9 +55,11 @@ _nvkm_fb_fini(struct nvkm_object *object, bool suspend) struct nvkm_fb *pfb = (void *)object; int ret; - ret = nv_ofuncs(pfb->ram)->fini(nv_object(pfb->ram), suspend); - if (ret && suspend) - return ret; + if (pfb->ram) { + ret = nv_ofuncs(pfb->ram)->fini(nv_object(pfb->ram), suspend); + if (ret && suspend) + return ret; + } return nvkm_subdev_fini(&pfb->base, suspend); } @@ -72,9 +74,11 @@ _nvkm_fb_init(struct nvkm_object *object) if (ret) return ret; - ret = nv_ofuncs(pfb->ram)->init(nv_object(pfb->ram)); - if (ret) - return ret; + if (pfb->ram) { + ret = nv_ofuncs(pfb->ram)->init(nv_object(pfb->ram)); + if (ret) + return ret; + } for (i = 0; i < pfb->tile.regions; i++) pfb->tile.prog(pfb, i, &pfb->tile.region[i]); @@ -91,9 +95,12 @@ _nvkm_fb_dtor(struct nvkm_object *object) for (i = 0; i < pfb->tile.regions; i++) pfb->tile.fini(pfb, i, &pfb->tile.region[i]); nvkm_mm_fini(&pfb->tags); - nvkm_mm_fini(&pfb->vram); - nvkm_object_ref(NULL, (struct nvkm_object **)&pfb->ram); + if (pfb->ram) { + nvkm_mm_fini(&pfb->vram); + nvkm_object_ref(NULL, (struct nvkm_object **)&pfb->ram); + } + nvkm_subdev_destroy(&pfb->base); } @@ -127,6 +134,9 @@ nvkm_fb_create_(struct nvkm_object *parent, struct nvkm_object *engine, pfb->memtype_valid = impl->memtype; + if (!impl->ram) + return 0; + ret = nvkm_object_ctor(nv_object(pfb), NULL, impl->ram, NULL, 0, &ram); if (ret) { nv_fatal(pfb, "error detecting memory configuration!!\n"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c index 6762847c05e8..a5d7857d3898 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c @@ -65,5 +65,4 @@ gk20a_fb_oclass = &(struct nvkm_fb_impl) { .fini = _nvkm_fb_fini, }, .memtype = gf100_fb_memtype_valid, - .ram = &gk20a_ram_oclass, }.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h index d82da02daa1f..485c4b64819a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h @@ -32,7 +32,6 @@ extern struct nvkm_oclass gt215_ram_oclass; extern struct nvkm_oclass mcp77_ram_oclass; extern struct nvkm_oclass gf100_ram_oclass; extern struct nvkm_oclass gk104_ram_oclass; -extern struct nvkm_oclass gk20a_ram_oclass; extern struct nvkm_oclass gm107_ram_oclass; int nvkm_sddr2_calc(struct nvkm_ram *ram); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk20a.c deleted file mode 100644 index 5f30db140b47..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk20a.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. - * - * 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ -#include "priv.h" - -#include <core/device.h> - -struct gk20a_mem { - struct nvkm_mem base; - void *cpuaddr; - dma_addr_t handle; -}; -#define to_gk20a_mem(m) container_of(m, struct gk20a_mem, base) - -static void -gk20a_ram_put(struct nvkm_fb *pfb, struct nvkm_mem **pmem) -{ - struct device *dev = nv_device_base(nv_device(pfb)); - struct gk20a_mem *mem = to_gk20a_mem(*pmem); - - *pmem = NULL; - if (unlikely(mem == NULL)) - return; - - if (likely(mem->cpuaddr)) - dma_free_coherent(dev, mem->base.size << PAGE_SHIFT, - mem->cpuaddr, mem->handle); - - kfree(mem->base.pages); - kfree(mem); -} - -static int -gk20a_ram_get(struct nvkm_fb *pfb, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nvkm_mem **pmem) -{ - struct device *dev = nv_device_base(nv_device(pfb)); - struct gk20a_mem *mem; - u32 type = memtype & 0xff; - u32 npages, order; - int i; - - nv_debug(pfb, "%s: size: %llx align: %x, ncmin: %x\n", __func__, size, - align, ncmin); - - npages = size >> PAGE_SHIFT; - if (npages == 0) - npages = 1; - - if (align == 0) - align = PAGE_SIZE; - align >>= PAGE_SHIFT; - - /* round alignment to the next power of 2, if needed */ - order = fls(align); - if ((align & (align - 1)) == 0) - order--; - align = BIT(order); - - /* ensure returned address is correctly aligned */ - npages = max(align, npages); - - mem = kzalloc(sizeof(*mem), GFP_KERNEL); - if (!mem) - return -ENOMEM; - - mem->base.size = npages; - mem->base.memtype = type; - - mem->base.pages = kzalloc(sizeof(dma_addr_t) * npages, GFP_KERNEL); - if (!mem->base.pages) { - kfree(mem); - return -ENOMEM; - } - - *pmem = &mem->base; - - mem->cpuaddr = dma_alloc_coherent(dev, npages << PAGE_SHIFT, - &mem->handle, GFP_KERNEL); - if (!mem->cpuaddr) { - nv_error(pfb, "%s: cannot allocate memory!\n", __func__); - gk20a_ram_put(pfb, pmem); - return -ENOMEM; - } - - align <<= PAGE_SHIFT; - - /* alignment check */ - if (unlikely(mem->handle & (align - 1))) - nv_warn(pfb, "memory not aligned as requested: %pad (0x%x)\n", - &mem->handle, align); - - nv_debug(pfb, "alloc size: 0x%x, align: 0x%x, paddr: %pad, vaddr: %p\n", - npages << PAGE_SHIFT, align, &mem->handle, mem->cpuaddr); - - for (i = 0; i < npages; i++) - mem->base.pages[i] = mem->handle + (PAGE_SIZE * i); - - mem->base.offset = (u64)mem->base.pages[0]; - return 0; -} - -static int -gk20a_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 datasize, - struct nvkm_object **pobject) -{ - struct nvkm_ram *ram; - int ret; - - ret = nvkm_ram_create(parent, engine, oclass, &ram); - *pobject = nv_object(ram); - if (ret) - return ret; - ram->type = NV_MEM_TYPE_STOLEN; - ram->size = get_num_physpages() << PAGE_SHIFT; - - ram->get = gk20a_ram_get; - ram->put = gk20a_ram_put; - return 0; -} - -struct nvkm_oclass -gk20a_ram_oclass = { - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = gk20a_ram_ctor, - .dtor = _nvkm_ram_dtor, - .init = _nvkm_ram_init, - .fini = _nvkm_ram_fini, - }, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c index ba19158a5912..0b256aa4960f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c @@ -45,10 +45,8 @@ gm107_fuse_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ret = nvkm_fuse_create(parent, engine, oclass, &priv); *pobject = nv_object(priv); - if (ret) - return ret; - return 0; + return ret; } struct nvkm_oclass diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/Kbuild index e6f35abe7879..13bb7fc0a569 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/Kbuild @@ -2,3 +2,4 @@ nvkm-y += nvkm/subdev/instmem/base.o nvkm-y += nvkm/subdev/instmem/nv04.o nvkm-y += nvkm/subdev/instmem/nv40.o nvkm-y += nvkm/subdev/instmem/nv50.o +nvkm-y += nvkm/subdev/instmem/gk20a.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c new file mode 100644 index 000000000000..dd0994d9ebfc --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * + * 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 AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +/* + * GK20A does not have dedicated video memory, and to accurately represent this + * fact Nouveau will not create a RAM device for it. Therefore its instmem + * implementation must be done directly on top of system memory, while providing + * coherent read and write operations. + * + * Instmem can be allocated through two means: + * 1) If an IOMMU mapping has been probed, the IOMMU API is used to make memory + * pages contiguous to the GPU. This is the preferred way. + * 2) If no IOMMU mapping is probed, the DMA API is used to allocate physically + * contiguous memory. + * + * In both cases CPU read and writes are performed using PRAMIN (i.e. using the + * GPU path) to ensure these operations are coherent for the GPU. This allows us + * to use more "relaxed" allocation parameters when using the DMA API, since we + * never need a kernel mapping. + */ + +#include <subdev/fb.h> +#include <core/mm.h> +#include <core/device.h> + +#ifdef __KERNEL__ +#include <linux/dma-attrs.h> +#include <linux/iommu.h> +#include <nouveau_platform.h> +#endif + +#include "priv.h" + +struct gk20a_instobj_priv { + struct nvkm_instobj base; + /* Must be second member here - see nouveau_gpuobj_map_vm() */ + struct nvkm_mem *mem; + /* Pointed by mem */ + struct nvkm_mem _mem; +}; + +/* + * Used for objects allocated using the DMA API + */ +struct gk20a_instobj_dma { + struct gk20a_instobj_priv base; + + void *cpuaddr; + dma_addr_t handle; + struct nvkm_mm_node r; +}; + +/* + * Used for objects flattened using the IOMMU API + */ +struct gk20a_instobj_iommu { + struct gk20a_instobj_priv base; + + /* array of base.mem->size pages */ + struct page *pages[]; +}; + +struct gk20a_instmem_priv { + struct nvkm_instmem base; + spinlock_t lock; + u64 addr; + + /* Only used if IOMMU if present */ + struct mutex *mm_mutex; + struct nvkm_mm *mm; + struct iommu_domain *domain; + unsigned long iommu_pgshift; + + /* Only used by DMA API */ + struct dma_attrs attrs; +}; + +/* + * Use PRAMIN to read/write data and avoid coherency issues. + * PRAMIN uses the GPU path and ensures data will always be coherent. + * + * A dynamic mapping based solution would be desirable in the future, but + * the issue remains of how to maintain coherency efficiently. On ARM it is + * not easy (if possible at all?) to create uncached temporary mappings. + */ + +static u32 +gk20a_instobj_rd32(struct nvkm_object *object, u64 offset) +{ + struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(object); + struct gk20a_instobj_priv *node = (void *)object; + unsigned long flags; + u64 base = (node->mem->offset + offset) & 0xffffff00000ULL; + u64 addr = (node->mem->offset + offset) & 0x000000fffffULL; + u32 data; + + spin_lock_irqsave(&priv->lock, flags); + if (unlikely(priv->addr != base)) { + nv_wr32(priv, 0x001700, base >> 16); + priv->addr = base; + } + data = nv_rd32(priv, 0x700000 + addr); + spin_unlock_irqrestore(&priv->lock, flags); + return data; +} + +static void +gk20a_instobj_wr32(struct nvkm_object *object, u64 offset, u32 data) +{ + struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(object); + struct gk20a_instobj_priv *node = (void *)object; + unsigned long flags; + u64 base = (node->mem->offset + offset) & 0xffffff00000ULL; + u64 addr = (node->mem->offset + offset) & 0x000000fffffULL; + + spin_lock_irqsave(&priv->lock, flags); + if (unlikely(priv->addr != base)) { + nv_wr32(priv, 0x001700, base >> 16); + priv->addr = base; + } + nv_wr32(priv, 0x700000 + addr, data); + spin_unlock_irqrestore(&priv->lock, flags); +} + +static void +gk20a_instobj_dtor_dma(struct gk20a_instobj_priv *_node) +{ + struct gk20a_instobj_dma *node = (void *)_node; + struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(node); + struct device *dev = nv_device_base(nv_device(priv)); + + if (unlikely(!node->cpuaddr)) + return; + + dma_free_attrs(dev, _node->mem->size << PAGE_SHIFT, node->cpuaddr, + node->handle, &priv->attrs); +} + +static void +gk20a_instobj_dtor_iommu(struct gk20a_instobj_priv *_node) +{ + struct gk20a_instobj_iommu *node = (void *)_node; + struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(node); + struct nvkm_mm_node *r; + int i; + + if (unlikely(list_empty(&_node->mem->regions))) + return; + + r = list_first_entry(&_node->mem->regions, struct nvkm_mm_node, + rl_entry); + + /* clear bit 34 to unmap pages */ + r->offset &= ~BIT(34 - priv->iommu_pgshift); + + /* Unmap pages from GPU address space and free them */ + for (i = 0; i < _node->mem->size; i++) { + iommu_unmap(priv->domain, + (r->offset + i) << priv->iommu_pgshift, PAGE_SIZE); + __free_page(node->pages[i]); + } + + /* Release area from GPU address space */ + mutex_lock(priv->mm_mutex); + nvkm_mm_free(priv->mm, &r); + mutex_unlock(priv->mm_mutex); +} + +static void +gk20a_instobj_dtor(struct nvkm_object *object) +{ + struct gk20a_instobj_priv *node = (void *)object; + struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(node); + + if (priv->domain) + gk20a_instobj_dtor_iommu(node); + else + gk20a_instobj_dtor_dma(node); + + nvkm_instobj_destroy(&node->base); +} + +static int +gk20a_instobj_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine, + struct nvkm_oclass *oclass, u32 npages, u32 align, + struct gk20a_instobj_priv **_node) +{ + struct gk20a_instobj_dma *node; + struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(parent); + struct device *dev = nv_device_base(nv_device(parent)); + int ret; + + ret = nvkm_instobj_create_(parent, engine, oclass, sizeof(*node), + (void **)&node); + *_node = &node->base; + if (ret) + return ret; + + node->cpuaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT, + &node->handle, GFP_KERNEL, + &priv->attrs); + if (!node->cpuaddr) { + nv_error(priv, "cannot allocate DMA memory\n"); + return -ENOMEM; + } + + /* alignment check */ + if (unlikely(node->handle & (align - 1))) + nv_warn(priv, "memory not aligned as requested: %pad (0x%x)\n", + &node->handle, align); + + /* present memory for being mapped using small pages */ + node->r.type = 12; + node->r.offset = node->handle >> 12; + node->r.length = (npages << PAGE_SHIFT) >> 12; + + node->base._mem.offset = node->handle; + + INIT_LIST_HEAD(&node->base._mem.regions); + list_add_tail(&node->r.rl_entry, &node->base._mem.regions); + + return 0; +} + +static int +gk20a_instobj_ctor_iommu(struct nvkm_object *parent, struct nvkm_object *engine, + struct nvkm_oclass *oclass, u32 npages, u32 align, + struct gk20a_instobj_priv **_node) +{ + struct gk20a_instobj_iommu *node; + struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(parent); + struct nvkm_mm_node *r; + int ret; + int i; + + ret = nvkm_instobj_create_(parent, engine, oclass, + sizeof(*node) + sizeof(node->pages[0]) * npages, + (void **)&node); + *_node = &node->base; + if (ret) + return ret; + + /* Allocate backing memory */ + for (i = 0; i < npages; i++) { + struct page *p = alloc_page(GFP_KERNEL); + + if (p == NULL) { + ret = -ENOMEM; + goto free_pages; + } + node->pages[i] = p; + } + + mutex_lock(priv->mm_mutex); + /* Reserve area from GPU address space */ + ret = nvkm_mm_head(priv->mm, 0, 1, npages, npages, + align >> priv->iommu_pgshift, &r); + mutex_unlock(priv->mm_mutex); + if (ret) { + nv_error(priv, "virtual space is full!\n"); + goto free_pages; + } + + /* Map into GPU address space */ + for (i = 0; i < npages; i++) { + struct page *p = node->pages[i]; + u32 offset = (r->offset + i) << priv->iommu_pgshift; + + ret = iommu_map(priv->domain, offset, page_to_phys(p), + PAGE_SIZE, IOMMU_READ | IOMMU_WRITE); + if (ret < 0) { + nv_error(priv, "IOMMU mapping failure: %d\n", ret); + + while (i-- > 0) { + offset -= PAGE_SIZE; + iommu_unmap(priv->domain, offset, PAGE_SIZE); + } + goto release_area; + } + } + + /* Bit 34 tells that an address is to be resolved through the IOMMU */ + r->offset |= BIT(34 - priv->iommu_pgshift); + + node->base._mem.offset = ((u64)r->offset) << priv->iommu_pgshift; + + INIT_LIST_HEAD(&node->base._mem.regions); + list_add_tail(&r->rl_entry, &node->base._mem.regions); + + return 0; + +release_area: + mutex_lock(priv->mm_mutex); + nvkm_mm_free(priv->mm, &r); + mutex_unlock(priv->mm_mutex); + +free_pages: + for (i = 0; i < npages && node->pages[i] != NULL; i++) + __free_page(node->pages[i]); + + return ret; +} + +static int +gk20a_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, + struct nvkm_oclass *oclass, void *data, u32 _size, + struct nvkm_object **pobject) +{ + struct nvkm_instobj_args *args = data; + struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(parent); + struct gk20a_instobj_priv *node; + u32 size, align; + int ret; + + nv_debug(parent, "%s (%s): size: %x align: %x\n", __func__, + priv->domain ? "IOMMU" : "DMA", args->size, args->align); + + /* Round size and align to page bounds */ + size = max(roundup(args->size, PAGE_SIZE), PAGE_SIZE); + align = max(roundup(args->align, PAGE_SIZE), PAGE_SIZE); + + if (priv->domain) + ret = gk20a_instobj_ctor_iommu(parent, engine, oclass, + size >> PAGE_SHIFT, align, &node); + else + ret = gk20a_instobj_ctor_dma(parent, engine, oclass, + size >> PAGE_SHIFT, align, &node); + *pobject = nv_object(node); + if (ret) + return ret; + + node->mem = &node->_mem; + + /* present memory for being mapped using small pages */ + node->mem->size = size >> 12; + node->mem->memtype = 0; + node->mem->page_shift = 12; + + node->base.addr = node->mem->offset; + node->base.size = size; + + nv_debug(parent, "alloc size: 0x%x, align: 0x%x, gaddr: 0x%llx\n", + size, align, node->mem->offset); + + return 0; +} + +static struct nvkm_instobj_impl +gk20a_instobj_oclass = { + .base.ofuncs = &(struct nvkm_ofuncs) { + .ctor = gk20a_instobj_ctor, + .dtor = gk20a_instobj_dtor, + .init = _nvkm_instobj_init, + .fini = _nvkm_instobj_fini, + .rd32 = gk20a_instobj_rd32, + .wr32 = gk20a_instobj_wr32, + }, +}; + + + +static int +gk20a_instmem_fini(struct nvkm_object *object, bool suspend) +{ + struct gk20a_instmem_priv *priv = (void *)object; + priv->addr = ~0ULL; + return nvkm_instmem_fini(&priv->base, suspend); +} + +static int +gk20a_instmem_ctor(struct nvkm_object *parent, struct nvkm_object *engine, + struct nvkm_oclass *oclass, void *data, u32 size, + struct nvkm_object **pobject) +{ + struct gk20a_instmem_priv *priv; + struct nouveau_platform_device *plat; + int ret; + + ret = nvkm_instmem_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + spin_lock_init(&priv->lock); + + plat = nv_device_to_platform(nv_device(parent)); + if (plat->gpu->iommu.domain) { + priv->domain = plat->gpu->iommu.domain; + priv->mm = plat->gpu->iommu.mm; + priv->iommu_pgshift = plat->gpu->iommu.pgshift; + priv->mm_mutex = &plat->gpu->iommu.mutex; + + nv_info(priv, "using IOMMU\n"); + } else { + init_dma_attrs(&priv->attrs); + /* + * We will access instmem through PRAMIN and thus do not need a + * consistent CPU pointer or kernel mapping + */ + dma_set_attr(DMA_ATTR_NON_CONSISTENT, &priv->attrs); + dma_set_attr(DMA_ATTR_WEAK_ORDERING, &priv->attrs); + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &priv->attrs); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &priv->attrs); + + nv_info(priv, "using DMA API\n"); + } + + return 0; +} + +struct nvkm_oclass * +gk20a_instmem_oclass = &(struct nvkm_instmem_impl) { + .base.handle = NV_SUBDEV(INSTMEM, 0xea), + .base.ofuncs = &(struct nvkm_ofuncs) { + .ctor = gk20a_instmem_ctor, + .dtor = _nvkm_instmem_dtor, + .init = _nvkm_instmem_init, + .fini = gk20a_instmem_fini, + }, + .instobj = &gk20a_instobj_oclass.base, +}.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c index 8e7cc6200d60..7fb5ea0314cb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c @@ -136,7 +136,8 @@ gf100_ltc_dtor(struct nvkm_object *object) struct nvkm_ltc_priv *priv = (void *)object; nvkm_mm_fini(&priv->tags); - nvkm_mm_free(&pfb->vram, &priv->tag_ram); + if (pfb->ram) + nvkm_mm_free(&pfb->vram, &priv->tag_ram); nvkm_ltc_destroy(priv); } @@ -149,6 +150,12 @@ gf100_ltc_init_tag_ram(struct nvkm_fb *pfb, struct nvkm_ltc_priv *priv) u32 tag_size, tag_margin, tag_align; int ret; + /* No VRAM, no tags for now. */ + if (!pfb->ram) { + priv->num_tags = 0; + goto mm_init; + } + /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */ priv->num_tags = (pfb->ram->size >> 17) / 4; if (priv->num_tags > (1 << 17)) @@ -183,6 +190,7 @@ gf100_ltc_init_tag_ram(struct nvkm_fb *pfb, struct nvkm_ltc_priv *priv) priv->tag_base = tag_base; } +mm_init: ret = nvkm_mm_init(&priv->tags, 0, priv->num_tags, 1); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c index 42cac13ca629..f20e4ca87e17 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c @@ -182,7 +182,7 @@ mxm_show_unmatched(struct nvkm_mxm *mxm, u8 *data, void *info) { u64 desc = *(u64 *)data; if ((desc & 0xf0) != 0xf0) - nv_info(mxm, "unmatched output device 0x%016llx\n", desc); + nv_info(mxm, "unmatched output device 0x%016llx\n", desc); return true; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild index 9a150d520225..7081d6a9b95f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild @@ -4,5 +4,6 @@ nvkm-y += nvkm/subdev/pmu/gt215.o nvkm-y += nvkm/subdev/pmu/gf100.o nvkm-y += nvkm/subdev/pmu/gf110.o nvkm-y += nvkm/subdev/pmu/gk104.o +nvkm-y += nvkm/subdev/pmu/gk110.o nvkm-y += nvkm/subdev/pmu/gk208.o nvkm-y += nvkm/subdev/pmu/gk20a.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c new file mode 100644 index 000000000000..89bb94b0af8b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c @@ -0,0 +1,95 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * 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. + * + * Authors: Ben Skeggs + */ +#define gf110_pmu_code gk110_pmu_code +#define gf110_pmu_data gk110_pmu_data +#include "priv.h" +#include "fuc/gf110.fuc4.h" + +#include <subdev/timer.h> + +void +gk110_pmu_pgob(struct nvkm_pmu *pmu, bool enable) +{ + static const struct { + u32 addr; + u32 data; + } magic[] = { + { 0x020520, 0xfffffffc }, + { 0x020524, 0xfffffffe }, + { 0x020524, 0xfffffffc }, + { 0x020524, 0xfffffff8 }, + { 0x020524, 0xffffffe0 }, + { 0x020530, 0xfffffffe }, + { 0x02052c, 0xfffffffa }, + { 0x02052c, 0xfffffff0 }, + { 0x02052c, 0xffffffc0 }, + { 0x02052c, 0xffffff00 }, + { 0x02052c, 0xfffffc00 }, + { 0x02052c, 0xfffcfc00 }, + { 0x02052c, 0xfff0fc00 }, + { 0x02052c, 0xff80fc00 }, + { 0x020528, 0xfffffffe }, + { 0x020528, 0xfffffffc }, + }; + int i; + + nv_mask(pmu, 0x000200, 0x00001000, 0x00000000); + nv_rd32(pmu, 0x000200); + nv_mask(pmu, 0x000200, 0x08000000, 0x08000000); + msleep(50); + + nv_mask(pmu, 0x10a78c, 0x00000002, 0x00000002); + nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000001); + nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000000); + + nv_mask(pmu, 0x0206b4, 0x00000000, 0x00000000); + for (i = 0; i < ARRAY_SIZE(magic); i++) { + nv_wr32(pmu, magic[i].addr, magic[i].data); + nv_wait(pmu, magic[i].addr, 0x80000000, 0x00000000); + } + + nv_mask(pmu, 0x10a78c, 0x00000002, 0x00000000); + nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000001); + nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000000); + + nv_mask(pmu, 0x000200, 0x08000000, 0x00000000); + nv_mask(pmu, 0x000200, 0x00001000, 0x00001000); + nv_rd32(pmu, 0x000200); +} + +struct nvkm_oclass * +gk110_pmu_oclass = &(struct nvkm_pmu_impl) { + .base.handle = NV_SUBDEV(PMU, 0xf0), + .base.ofuncs = &(struct nvkm_ofuncs) { + .ctor = _nvkm_pmu_ctor, + .dtor = _nvkm_pmu_dtor, + .init = _nvkm_pmu_init, + .fini = _nvkm_pmu_fini, + }, + .code.data = gk110_pmu_code, + .code.size = sizeof(gk110_pmu_code), + .data.data = gk110_pmu_data, + .data.size = sizeof(gk110_pmu_data), + .pgob = gk110_pmu_pgob, +}.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c index 6f9c09af1a49..b14134ef9ea5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c @@ -37,4 +37,5 @@ gk208_pmu_oclass = &(struct nvkm_pmu_impl) { .code.size = sizeof(gk208_pmu_code), .data.data = gk208_pmu_data, .data.size = sizeof(gk208_pmu_data), + .pgob = gk110_pmu_pgob, }.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c index a49934bbe637..594f746e68f2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c @@ -159,7 +159,7 @@ resched: nvkm_timer_alarm(priv, 100000000, alarm); } -int +static int gk20a_pmu_fini(struct nvkm_object *object, bool suspend) { struct nvkm_pmu *pmu = (void *)object; @@ -170,7 +170,7 @@ gk20a_pmu_fini(struct nvkm_object *object, bool suspend) return nvkm_subdev_fini(&pmu->base, suspend); } -int +static int gk20a_pmu_init(struct nvkm_object *object) { struct nvkm_pmu *pmu = (void *)object; @@ -192,7 +192,8 @@ gk20a_pmu_init(struct nvkm_object *object) return ret; } -struct gk20a_pmu_dvfs_data gk20a_dvfs_data= { +static struct gk20a_pmu_dvfs_data +gk20a_dvfs_data= { .p_load_target = 70, .p_load_max = 90, .p_smooth = 1, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index 998410563bfd..799e7c8b88f5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -40,4 +40,6 @@ struct nvkm_pmu_impl { void (*pgob)(struct nvkm_pmu *, bool); }; + +void gk110_pmu_pgob(struct nvkm_pmu *, bool); #endif diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index fb052bca574f..93117f159a3b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -509,7 +509,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu, enum rcar_du_encoder_type enc_type = RCAR_DU_ENCODER_NONE; struct device_node *connector = NULL; struct device_node *encoder = NULL; - struct device_node *prev = NULL; + struct device_node *ep_node = NULL; struct device_node *entity_ep_node; struct device_node *entity; int ret; @@ -527,16 +527,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu, entity_ep_node = of_parse_phandle(ep->local_node, "remote-endpoint", 0); - while (1) { - struct device_node *ep_node; - - ep_node = of_graph_get_next_endpoint(entity, prev); - of_node_put(prev); - prev = ep_node; - - if (!ep_node) - break; - + for_each_endpoint_of_node(entity, ep_node) { if (ep_node == entity_ep_node) continue; @@ -603,27 +594,19 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu, static int rcar_du_encoders_init(struct rcar_du_device *rcdu) { struct device_node *np = rcdu->dev->of_node; - struct device_node *prev = NULL; + struct device_node *ep_node; unsigned int num_encoders = 0; /* * Iterate over the endpoints and create one encoder for each output * pipeline. */ - while (1) { - struct device_node *ep_node; + for_each_endpoint_of_node(np, ep_node) { enum rcar_du_output output; struct of_endpoint ep; unsigned int i; int ret; - ep_node = of_graph_get_next_endpoint(np, prev); - of_node_put(prev); - prev = ep_node; - - if (ep_node == NULL) - break; - ret = of_graph_parse_endpoint(ep_node, &ep); if (ret < 0) { of_node_put(ep_node); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 30da7813d53e..3962176ee713 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -385,7 +385,7 @@ static const struct dev_pm_ops rockchip_drm_pm_ops = { int rockchip_drm_encoder_get_mux_id(struct device_node *node, struct drm_encoder *encoder) { - struct device_node *ep = NULL; + struct device_node *ep; struct drm_crtc *crtc = encoder->crtc; struct of_endpoint endpoint; struct device_node *port; @@ -394,18 +394,15 @@ int rockchip_drm_encoder_get_mux_id(struct device_node *node, if (!node || !crtc) return -EINVAL; - do { - ep = of_graph_get_next_endpoint(node, ep); - if (!ep) - break; - + for_each_endpoint_of_node(node, ep) { port = of_graph_get_remote_port(ep); of_node_put(port); if (port == crtc->port) { ret = of_graph_parse_endpoint(ep, &endpoint); + of_node_put(ep); return ret ?: endpoint.id; } - } while (ep); + } return -EINVAL; } diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c index 4864f8300797..9ef2e1f54ca4 100644 --- a/drivers/gpu/ipu-v3/ipu-dc.c +++ b/drivers/gpu/ipu-v3/ipu-dc.c @@ -147,20 +147,20 @@ static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand, writel(reg2, priv->dc_tmpl_reg + word * 8 + 4); } -static int ipu_pixfmt_to_map(u32 fmt) +static int ipu_bus_format_to_map(u32 fmt) { switch (fmt) { - case V4L2_PIX_FMT_RGB24: + case MEDIA_BUS_FMT_RGB888_1X24: return IPU_DC_MAP_RGB24; - case V4L2_PIX_FMT_RGB565: + case MEDIA_BUS_FMT_RGB565_1X16: return IPU_DC_MAP_RGB565; - case IPU_PIX_FMT_GBR24: + case MEDIA_BUS_FMT_GBR888_1X24: return IPU_DC_MAP_GBR24; - case V4L2_PIX_FMT_BGR666: + case MEDIA_BUS_FMT_RGB666_1X18: return IPU_DC_MAP_BGR666; - case v4l2_fourcc('L', 'V', 'D', '6'): + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: return IPU_DC_MAP_LVDS666; - case V4L2_PIX_FMT_BGR24: + case MEDIA_BUS_FMT_BGR888_1X24: return IPU_DC_MAP_BGR24; default: return -EINVAL; @@ -168,7 +168,7 @@ static int ipu_pixfmt_to_map(u32 fmt) } int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced, - u32 pixel_fmt, u32 width) + u32 bus_format, u32 width) { struct ipu_dc_priv *priv = dc->priv; u32 reg = 0; @@ -176,7 +176,7 @@ int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced, dc->di = ipu_di_get_num(di); - map = ipu_pixfmt_to_map(pixel_fmt); + map = ipu_bus_format_to_map(bus_format); if (map < 0) { dev_dbg(priv->dev, "IPU_DISP: No MAP\n"); return map; diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index 56a5cb0d2152..0d07fca756fe 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -2504,7 +2504,6 @@ vpfe_get_pdata(struct platform_device *pdev) GFP_KERNEL); pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_OF; pdata->asd[i]->match.of.node = rem; - of_node_put(endpoint); of_node_put(rem); } diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index cee7b56f8404..f2a3d960b1a6 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -1694,7 +1694,6 @@ static void scan_of_host(struct soc_camera_host *ici) if (!i) soc_of_bind(ici, epn, ren->parent); - of_node_put(epn); of_node_put(ren); if (i) { @@ -1702,6 +1701,8 @@ static void scan_of_host(struct soc_camera_host *ici) break; } } + + of_node_put(epn); } #else diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 7563f36c71db..fcacb186a67b 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -6,8 +6,7 @@ obj-$(CONFIG_OF_PROMTREE) += pdt.o obj-$(CONFIG_OF_ADDRESS) += address.o obj-$(CONFIG_OF_IRQ) += irq.o obj-$(CONFIG_OF_NET) += of_net.o -obj-$(CONFIG_OF_UNITTEST) += of_unittest.o -of_unittest-objs := unittest.o unittest-data/testcases.dtb.o +obj-$(CONFIG_OF_UNITTEST) += unittest.o obj-$(CONFIG_OF_MDIO) += of_mdio.o obj-$(CONFIG_OF_PCI) += of_pci.o obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o @@ -16,5 +15,7 @@ obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o obj-$(CONFIG_OF_RESOLVE) += resolver.o obj-$(CONFIG_OF_OVERLAY) += overlay.o +obj-$(CONFIG_OF_UNITTEST) += unittest-data/ + CFLAGS_fdt.o = -I$(src)/../../scripts/dtc/libfdt CFLAGS_fdt_address.o = -I$(src)/../../scripts/dtc/libfdt diff --git a/drivers/of/base.c b/drivers/of/base.c index 8f165b112e03..69566b6a876d 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2083,13 +2083,44 @@ int of_graph_parse_endpoint(const struct device_node *node, EXPORT_SYMBOL(of_graph_parse_endpoint); /** + * of_graph_get_port_by_id() - get the port matching a given id + * @parent: pointer to the parent device node + * @id: id of the port + * + * Return: A 'port' node pointer with refcount incremented. The caller + * has to use of_node_put() on it when done. + */ +struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id) +{ + struct device_node *node, *port; + + node = of_get_child_by_name(parent, "ports"); + if (node) + parent = node; + + for_each_child_of_node(parent, port) { + u32 port_id = 0; + + if (of_node_cmp(port->name, "port") != 0) + continue; + of_property_read_u32(port, "reg", &port_id); + if (id == port_id) + break; + } + + of_node_put(node); + + return port; +} +EXPORT_SYMBOL(of_graph_get_port_by_id); + +/** * of_graph_get_next_endpoint() - get next endpoint node * @parent: pointer to the parent device node * @prev: previous endpoint node, or NULL to get first * * Return: An 'endpoint' node pointer with refcount incremented. Refcount - * of the passed @prev node is not decremented, the caller have to use - * of_node_put() on it when done. + * of the passed @prev node is decremented. */ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *prev) @@ -2125,12 +2156,6 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, if (WARN_ONCE(!port, "%s(): endpoint %s has no parent node\n", __func__, prev->full_name)) return NULL; - - /* - * Avoid dropping prev node refcount to 0 when getting the next - * child below. - */ - of_node_get(prev); } while (1) { diff --git a/drivers/of/unittest-data/.gitignore b/drivers/of/unittest-data/.gitignore new file mode 100644 index 000000000000..4b3cf8b16de2 --- /dev/null +++ b/drivers/of/unittest-data/.gitignore @@ -0,0 +1,2 @@ +testcases.dtb +testcases.dtb.S diff --git a/drivers/of/unittest-data/Makefile b/drivers/of/unittest-data/Makefile new file mode 100644 index 000000000000..1ac5cc01d627 --- /dev/null +++ b/drivers/of/unittest-data/Makefile @@ -0,0 +1,7 @@ +obj-y += testcases.dtb.o + +targets += testcases.dtb testcases.dtb.S + +.SECONDARY: \ + $(obj)/testcases.dtb.S \ + $(obj)/testcases.dtb diff --git a/drivers/of/unittest-data/tests-overlay.dtsi b/drivers/of/unittest-data/tests-overlay.dtsi index 244226cbb5a3..02ba56c20fe1 100644 --- a/drivers/of/unittest-data/tests-overlay.dtsi +++ b/drivers/of/unittest-data/tests-overlay.dtsi @@ -4,94 +4,94 @@ overlay-node { /* test bus */ - selftestbus: test-bus { + unittestbus: test-bus { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <0>; - selftest100: test-selftest100 { - compatible = "selftest"; + unittest100: test-unittest100 { + compatible = "unittest"; status = "okay"; reg = <100>; }; - selftest101: test-selftest101 { - compatible = "selftest"; + unittest101: test-unittest101 { + compatible = "unittest"; status = "disabled"; reg = <101>; }; - selftest0: test-selftest0 { - compatible = "selftest"; + unittest0: test-unittest0 { + compatible = "unittest"; status = "disabled"; reg = <0>; }; - selftest1: test-selftest1 { - compatible = "selftest"; + unittest1: test-unittest1 { + compatible = "unittest"; status = "okay"; reg = <1>; }; - selftest2: test-selftest2 { - compatible = "selftest"; + unittest2: test-unittest2 { + compatible = "unittest"; status = "disabled"; reg = <2>; }; - selftest3: test-selftest3 { - compatible = "selftest"; + unittest3: test-unittest3 { + compatible = "unittest"; status = "okay"; reg = <3>; }; - selftest5: test-selftest5 { - compatible = "selftest"; + unittest5: test-unittest5 { + compatible = "unittest"; status = "disabled"; reg = <5>; }; - selftest6: test-selftest6 { - compatible = "selftest"; + unittest6: test-unittest6 { + compatible = "unittest"; status = "disabled"; reg = <6>; }; - selftest7: test-selftest7 { - compatible = "selftest"; + unittest7: test-unittest7 { + compatible = "unittest"; status = "disabled"; reg = <7>; }; - selftest8: test-selftest8 { - compatible = "selftest"; + unittest8: test-unittest8 { + compatible = "unittest"; status = "disabled"; reg = <8>; }; i2c-test-bus { - compatible = "selftest-i2c-bus"; + compatible = "unittest-i2c-bus"; status = "okay"; reg = <50>; #address-cells = <1>; #size-cells = <0>; - test-selftest12 { + test-unittest12 { reg = <8>; - compatible = "selftest-i2c-dev"; + compatible = "unittest-i2c-dev"; status = "disabled"; }; - test-selftest13 { + test-unittest13 { reg = <9>; - compatible = "selftest-i2c-dev"; + compatible = "unittest-i2c-dev"; status = "okay"; }; - test-selftest14 { + test-unittest14 { reg = <10>; - compatible = "selftest-i2c-mux"; + compatible = "unittest-i2c-mux"; status = "okay"; #address-cells = <1>; @@ -104,7 +104,7 @@ test-mux-dev { reg = <32>; - compatible = "selftest-i2c-dev"; + compatible = "unittest-i2c-dev"; status = "okay"; }; }; @@ -116,7 +116,7 @@ /* test enable using absolute target path */ overlay0 { fragment@0 { - target-path = "/testcase-data/overlay-node/test-bus/test-selftest0"; + target-path = "/testcase-data/overlay-node/test-bus/test-unittest0"; __overlay__ { status = "okay"; }; @@ -126,7 +126,7 @@ /* test disable using absolute target path */ overlay1 { fragment@0 { - target-path = "/testcase-data/overlay-node/test-bus/test-selftest1"; + target-path = "/testcase-data/overlay-node/test-bus/test-unittest1"; __overlay__ { status = "disabled"; }; @@ -136,7 +136,7 @@ /* test enable using label */ overlay2 { fragment@0 { - target = <&selftest2>; + target = <&unittest2>; __overlay__ { status = "okay"; }; @@ -146,7 +146,7 @@ /* test disable using label */ overlay3 { fragment@0 { - target = <&selftest3>; + target = <&unittest3>; __overlay__ { status = "disabled"; }; @@ -156,15 +156,15 @@ /* test insertion of a full node */ overlay4 { fragment@0 { - target = <&selftestbus>; + target = <&unittestbus>; __overlay__ { /* suppress DTC warning */ #address-cells = <1>; #size-cells = <0>; - test-selftest4 { - compatible = "selftest"; + test-unittest4 { + compatible = "unittest"; status = "okay"; reg = <4>; }; @@ -175,7 +175,7 @@ /* test overlay apply revert */ overlay5 { fragment@0 { - target-path = "/testcase-data/overlay-node/test-bus/test-selftest5"; + target-path = "/testcase-data/overlay-node/test-bus/test-unittest5"; __overlay__ { status = "okay"; }; @@ -185,7 +185,7 @@ /* test overlays application and removal in sequence */ overlay6 { fragment@0 { - target-path = "/testcase-data/overlay-node/test-bus/test-selftest6"; + target-path = "/testcase-data/overlay-node/test-bus/test-unittest6"; __overlay__ { status = "okay"; }; @@ -193,7 +193,7 @@ }; overlay7 { fragment@0 { - target-path = "/testcase-data/overlay-node/test-bus/test-selftest7"; + target-path = "/testcase-data/overlay-node/test-bus/test-unittest7"; __overlay__ { status = "okay"; }; @@ -203,7 +203,7 @@ /* test overlays application and removal in bad sequence */ overlay8 { fragment@0 { - target-path = "/testcase-data/overlay-node/test-bus/test-selftest8"; + target-path = "/testcase-data/overlay-node/test-bus/test-unittest8"; __overlay__ { status = "okay"; }; @@ -211,7 +211,7 @@ }; overlay9 { fragment@0 { - target-path = "/testcase-data/overlay-node/test-bus/test-selftest8"; + target-path = "/testcase-data/overlay-node/test-bus/test-unittest8"; __overlay__ { property-foo = "bar"; }; @@ -227,16 +227,16 @@ #address-cells = <1>; #size-cells = <0>; - test-selftest10 { - compatible = "selftest"; + test-unittest10 { + compatible = "unittest"; status = "okay"; reg = <10>; #address-cells = <1>; #size-cells = <0>; - test-selftest101 { - compatible = "selftest"; + test-unittest101 { + compatible = "unittest"; status = "okay"; reg = <1>; }; @@ -255,16 +255,16 @@ #address-cells = <1>; #size-cells = <0>; - test-selftest11 { - compatible = "selftest"; + test-unittest11 { + compatible = "unittest"; status = "okay"; reg = <11>; #address-cells = <1>; #size-cells = <0>; - test-selftest111 { - compatible = "selftest"; + test-unittest111 { + compatible = "unittest"; status = "okay"; reg = <1>; }; @@ -277,7 +277,7 @@ /* test enable using absolute target path (i2c) */ overlay12 { fragment@0 { - target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-selftest12"; + target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest12"; __overlay__ { status = "okay"; }; @@ -287,7 +287,7 @@ /* test disable using absolute target path (i2c) */ overlay13 { fragment@0 { - target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-selftest13"; + target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest13"; __overlay__ { status = "disabled"; }; @@ -301,9 +301,9 @@ __overlay__ { #address-cells = <1>; #size-cells = <0>; - test-selftest15 { + test-unittest15 { reg = <11>; - compatible = "selftest-i2c-mux"; + compatible = "unittest-i2c-mux"; status = "okay"; #address-cells = <1>; @@ -316,7 +316,7 @@ test-mux-dev { reg = <32>; - compatible = "selftest-i2c-dev"; + compatible = "unittest-i2c-dev"; status = "okay"; }; }; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 52c45c7df07f..fdb597766be9 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -25,115 +25,115 @@ #include "of_private.h" -static struct selftest_results { +static struct unittest_results { int passed; int failed; -} selftest_results; +} unittest_results; -#define selftest(result, fmt, ...) ({ \ +#define unittest(result, fmt, ...) ({ \ bool failed = !(result); \ if (failed) { \ - selftest_results.failed++; \ + unittest_results.failed++; \ pr_err("FAIL %s():%i " fmt, __func__, __LINE__, ##__VA_ARGS__); \ } else { \ - selftest_results.passed++; \ + unittest_results.passed++; \ pr_debug("pass %s():%i\n", __func__, __LINE__); \ } \ failed; \ }) -static void __init of_selftest_find_node_by_name(void) +static void __init of_unittest_find_node_by_name(void) { struct device_node *np; const char *options; np = of_find_node_by_path("/testcase-data"); - selftest(np && !strcmp("/testcase-data", np->full_name), + unittest(np && !strcmp("/testcase-data", np->full_name), "find /testcase-data failed\n"); of_node_put(np); /* Test if trailing '/' works */ np = of_find_node_by_path("/testcase-data/"); - selftest(!np, "trailing '/' on /testcase-data/ should fail\n"); + unittest(!np, "trailing '/' on /testcase-data/ should fail\n"); np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); - selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name), + unittest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name), "find /testcase-data/phandle-tests/consumer-a failed\n"); of_node_put(np); np = of_find_node_by_path("testcase-alias"); - selftest(np && !strcmp("/testcase-data", np->full_name), + unittest(np && !strcmp("/testcase-data", np->full_name), "find testcase-alias failed\n"); of_node_put(np); /* Test if trailing '/' works on aliases */ np = of_find_node_by_path("testcase-alias/"); - selftest(!np, "trailing '/' on testcase-alias/ should fail\n"); + unittest(!np, "trailing '/' on testcase-alias/ should fail\n"); np = of_find_node_by_path("testcase-alias/phandle-tests/consumer-a"); - selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name), + unittest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name), "find testcase-alias/phandle-tests/consumer-a failed\n"); of_node_put(np); np = of_find_node_by_path("/testcase-data/missing-path"); - selftest(!np, "non-existent path returned node %s\n", np->full_name); + unittest(!np, "non-existent path returned node %s\n", np->full_name); of_node_put(np); np = of_find_node_by_path("missing-alias"); - selftest(!np, "non-existent alias returned node %s\n", np->full_name); + unittest(!np, "non-existent alias returned node %s\n", np->full_name); of_node_put(np); np = of_find_node_by_path("testcase-alias/missing-path"); - selftest(!np, "non-existent alias with relative path returned node %s\n", np->full_name); + unittest(!np, "non-existent alias with relative path returned node %s\n", np->full_name); of_node_put(np); np = of_find_node_opts_by_path("/testcase-data:testoption", &options); - selftest(np && !strcmp("testoption", options), + unittest(np && !strcmp("testoption", options), "option path test failed\n"); of_node_put(np); np = of_find_node_opts_by_path("/testcase-data:test/option", &options); - selftest(np && !strcmp("test/option", options), + unittest(np && !strcmp("test/option", options), "option path test, subcase #1 failed\n"); of_node_put(np); np = of_find_node_opts_by_path("/testcase-data/testcase-device1:test/option", &options); - selftest(np && !strcmp("test/option", options), + unittest(np && !strcmp("test/option", options), "option path test, subcase #2 failed\n"); of_node_put(np); np = of_find_node_opts_by_path("/testcase-data:testoption", NULL); - selftest(np, "NULL option path test failed\n"); + unittest(np, "NULL option path test failed\n"); of_node_put(np); np = of_find_node_opts_by_path("testcase-alias:testaliasoption", &options); - selftest(np && !strcmp("testaliasoption", options), + unittest(np && !strcmp("testaliasoption", options), "option alias path test failed\n"); of_node_put(np); np = of_find_node_opts_by_path("testcase-alias:test/alias/option", &options); - selftest(np && !strcmp("test/alias/option", options), + unittest(np && !strcmp("test/alias/option", options), "option alias path test, subcase #1 failed\n"); of_node_put(np); np = of_find_node_opts_by_path("testcase-alias:testaliasoption", NULL); - selftest(np, "NULL option alias path test failed\n"); + unittest(np, "NULL option alias path test failed\n"); of_node_put(np); options = "testoption"; np = of_find_node_opts_by_path("testcase-alias", &options); - selftest(np && !options, "option clearing test failed\n"); + unittest(np && !options, "option clearing test failed\n"); of_node_put(np); options = "testoption"; np = of_find_node_opts_by_path("/", &options); - selftest(np && !options, "option clearing root node test failed\n"); + unittest(np && !options, "option clearing root node test failed\n"); of_node_put(np); } -static void __init of_selftest_dynamic(void) +static void __init of_unittest_dynamic(void) { struct device_node *np; struct property *prop; @@ -147,7 +147,7 @@ static void __init of_selftest_dynamic(void) /* Array of 4 properties for the purpose of testing */ prop = kzalloc(sizeof(*prop) * 4, GFP_KERNEL); if (!prop) { - selftest(0, "kzalloc() failed\n"); + unittest(0, "kzalloc() failed\n"); return; } @@ -155,20 +155,20 @@ static void __init of_selftest_dynamic(void) prop->name = "new-property"; prop->value = "new-property-data"; prop->length = strlen(prop->value); - selftest(of_add_property(np, prop) == 0, "Adding a new property failed\n"); + unittest(of_add_property(np, prop) == 0, "Adding a new property failed\n"); /* Try to add an existing property - should fail */ prop++; prop->name = "new-property"; prop->value = "new-property-data-should-fail"; prop->length = strlen(prop->value); - selftest(of_add_property(np, prop) != 0, + unittest(of_add_property(np, prop) != 0, "Adding an existing property should have failed\n"); /* Try to modify an existing property - should pass */ prop->value = "modify-property-data-should-pass"; prop->length = strlen(prop->value); - selftest(of_update_property(np, prop) == 0, + unittest(of_update_property(np, prop) == 0, "Updating an existing property should have passed\n"); /* Try to modify non-existent property - should pass*/ @@ -176,11 +176,11 @@ static void __init of_selftest_dynamic(void) prop->name = "modify-property"; prop->value = "modify-missing-property-data-should-pass"; prop->length = strlen(prop->value); - selftest(of_update_property(np, prop) == 0, + unittest(of_update_property(np, prop) == 0, "Updating a missing property should have passed\n"); /* Remove property - should pass */ - selftest(of_remove_property(np, prop) == 0, + unittest(of_remove_property(np, prop) == 0, "Removing a property should have passed\n"); /* Adding very large property - should pass */ @@ -188,13 +188,13 @@ static void __init of_selftest_dynamic(void) prop->name = "large-property-PAGE_SIZEx8"; prop->length = PAGE_SIZE * 8; prop->value = kzalloc(prop->length, GFP_KERNEL); - selftest(prop->value != NULL, "Unable to allocate large buffer\n"); + unittest(prop->value != NULL, "Unable to allocate large buffer\n"); if (prop->value) - selftest(of_add_property(np, prop) == 0, + unittest(of_add_property(np, prop) == 0, "Adding a large property should have passed\n"); } -static int __init of_selftest_check_node_linkage(struct device_node *np) +static int __init of_unittest_check_node_linkage(struct device_node *np) { struct device_node *child; int count = 0, rc; @@ -206,7 +206,7 @@ static int __init of_selftest_check_node_linkage(struct device_node *np) return -EINVAL; } - rc = of_selftest_check_node_linkage(child); + rc = of_unittest_check_node_linkage(child); if (rc < 0) return rc; count += rc; @@ -215,7 +215,7 @@ static int __init of_selftest_check_node_linkage(struct device_node *np) return count + 1; } -static void __init of_selftest_check_tree_linkage(void) +static void __init of_unittest_check_tree_linkage(void) { struct device_node *np; int allnode_count = 0, child_count; @@ -225,10 +225,10 @@ static void __init of_selftest_check_tree_linkage(void) for_each_of_allnodes(np) allnode_count++; - child_count = of_selftest_check_node_linkage(of_root); + child_count = of_unittest_check_node_linkage(of_root); - selftest(child_count > 0, "Device node data structure is corrupted\n"); - selftest(child_count == allnode_count, "allnodes list size (%i) doesn't match" + unittest(child_count > 0, "Device node data structure is corrupted\n"); + unittest(child_count == allnode_count, "allnodes list size (%i) doesn't match" "sibling lists size (%i)\n", allnode_count, child_count); pr_debug("allnodes list size (%i); sibling lists size (%i)\n", allnode_count, child_count); } @@ -239,7 +239,7 @@ struct node_hash { }; static DEFINE_HASHTABLE(phandle_ht, 8); -static void __init of_selftest_check_phandles(void) +static void __init of_unittest_check_phandles(void) { struct device_node *np; struct node_hash *nh; @@ -267,7 +267,7 @@ static void __init of_selftest_check_phandles(void) hash_add(phandle_ht, &nh->node, np->phandle); phandle_count++; } - selftest(dup_count == 0, "Found %i duplicates in %i phandles\n", + unittest(dup_count == 0, "Found %i duplicates in %i phandles\n", dup_count, phandle_count); /* Clean up */ @@ -277,7 +277,7 @@ static void __init of_selftest_check_phandles(void) } } -static void __init of_selftest_parse_phandle_with_args(void) +static void __init of_unittest_parse_phandle_with_args(void) { struct device_node *np; struct of_phandle_args args; @@ -290,7 +290,7 @@ static void __init of_selftest_parse_phandle_with_args(void) } rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells"); - selftest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc); + unittest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc); for (i = 0; i < 8; i++) { bool passed = true; @@ -342,44 +342,44 @@ static void __init of_selftest_parse_phandle_with_args(void) passed = false; } - selftest(passed, "index %i - data error on node %s rc=%i\n", + unittest(passed, "index %i - data error on node %s rc=%i\n", i, args.np->full_name, rc); } /* Check for missing list property */ rc = of_parse_phandle_with_args(np, "phandle-list-missing", "#phandle-cells", 0, &args); - selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); + unittest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); rc = of_count_phandle_with_args(np, "phandle-list-missing", "#phandle-cells"); - selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); + unittest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); /* Check for missing cells property */ rc = of_parse_phandle_with_args(np, "phandle-list", "#phandle-cells-missing", 0, &args); - selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells-missing"); - selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); /* Check for bad phandle in list */ rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle", "#phandle-cells", 0, &args); - selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); rc = of_count_phandle_with_args(np, "phandle-list-bad-phandle", "#phandle-cells"); - selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); /* Check for incorrectly formed argument list */ rc = of_parse_phandle_with_args(np, "phandle-list-bad-args", "#phandle-cells", 1, &args); - selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); rc = of_count_phandle_with_args(np, "phandle-list-bad-args", "#phandle-cells"); - selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); } -static void __init of_selftest_property_string(void) +static void __init of_unittest_property_string(void) { const char *strings[4]; struct device_node *np; @@ -392,79 +392,79 @@ static void __init of_selftest_property_string(void) } rc = of_property_match_string(np, "phandle-list-names", "first"); - selftest(rc == 0, "first expected:0 got:%i\n", rc); + unittest(rc == 0, "first expected:0 got:%i\n", rc); rc = of_property_match_string(np, "phandle-list-names", "second"); - selftest(rc == 1, "second expected:1 got:%i\n", rc); + unittest(rc == 1, "second expected:1 got:%i\n", rc); rc = of_property_match_string(np, "phandle-list-names", "third"); - selftest(rc == 2, "third expected:2 got:%i\n", rc); + unittest(rc == 2, "third expected:2 got:%i\n", rc); rc = of_property_match_string(np, "phandle-list-names", "fourth"); - selftest(rc == -ENODATA, "unmatched string; rc=%i\n", rc); + unittest(rc == -ENODATA, "unmatched string; rc=%i\n", rc); rc = of_property_match_string(np, "missing-property", "blah"); - selftest(rc == -EINVAL, "missing property; rc=%i\n", rc); + unittest(rc == -EINVAL, "missing property; rc=%i\n", rc); rc = of_property_match_string(np, "empty-property", "blah"); - selftest(rc == -ENODATA, "empty property; rc=%i\n", rc); + unittest(rc == -ENODATA, "empty property; rc=%i\n", rc); rc = of_property_match_string(np, "unterminated-string", "blah"); - selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); + unittest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); /* of_property_count_strings() tests */ rc = of_property_count_strings(np, "string-property"); - selftest(rc == 1, "Incorrect string count; rc=%i\n", rc); + unittest(rc == 1, "Incorrect string count; rc=%i\n", rc); rc = of_property_count_strings(np, "phandle-list-names"); - selftest(rc == 3, "Incorrect string count; rc=%i\n", rc); + unittest(rc == 3, "Incorrect string count; rc=%i\n", rc); rc = of_property_count_strings(np, "unterminated-string"); - selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); + unittest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); rc = of_property_count_strings(np, "unterminated-string-list"); - selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc); + unittest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc); /* of_property_read_string_index() tests */ rc = of_property_read_string_index(np, "string-property", 0, strings); - selftest(rc == 0 && !strcmp(strings[0], "foobar"), "of_property_read_string_index() failure; rc=%i\n", rc); + unittest(rc == 0 && !strcmp(strings[0], "foobar"), "of_property_read_string_index() failure; rc=%i\n", rc); strings[0] = NULL; rc = of_property_read_string_index(np, "string-property", 1, strings); - selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); + unittest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); rc = of_property_read_string_index(np, "phandle-list-names", 0, strings); - selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc); + unittest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc); rc = of_property_read_string_index(np, "phandle-list-names", 1, strings); - selftest(rc == 0 && !strcmp(strings[0], "second"), "of_property_read_string_index() failure; rc=%i\n", rc); + unittest(rc == 0 && !strcmp(strings[0], "second"), "of_property_read_string_index() failure; rc=%i\n", rc); rc = of_property_read_string_index(np, "phandle-list-names", 2, strings); - selftest(rc == 0 && !strcmp(strings[0], "third"), "of_property_read_string_index() failure; rc=%i\n", rc); + unittest(rc == 0 && !strcmp(strings[0], "third"), "of_property_read_string_index() failure; rc=%i\n", rc); strings[0] = NULL; rc = of_property_read_string_index(np, "phandle-list-names", 3, strings); - selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); + unittest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); strings[0] = NULL; rc = of_property_read_string_index(np, "unterminated-string", 0, strings); - selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); + unittest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); rc = of_property_read_string_index(np, "unterminated-string-list", 0, strings); - selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc); + unittest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc); strings[0] = NULL; rc = of_property_read_string_index(np, "unterminated-string-list", 2, strings); /* should fail */ - selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); + unittest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); strings[1] = NULL; /* of_property_read_string_array() tests */ rc = of_property_read_string_array(np, "string-property", strings, 4); - selftest(rc == 1, "Incorrect string count; rc=%i\n", rc); + unittest(rc == 1, "Incorrect string count; rc=%i\n", rc); rc = of_property_read_string_array(np, "phandle-list-names", strings, 4); - selftest(rc == 3, "Incorrect string count; rc=%i\n", rc); + unittest(rc == 3, "Incorrect string count; rc=%i\n", rc); rc = of_property_read_string_array(np, "unterminated-string", strings, 4); - selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); + unittest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); /* -- An incorrectly formed string should cause a failure */ rc = of_property_read_string_array(np, "unterminated-string-list", strings, 4); - selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc); + unittest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc); /* -- parsing the correctly formed strings should still work: */ strings[2] = NULL; rc = of_property_read_string_array(np, "unterminated-string-list", strings, 2); - selftest(rc == 2 && strings[2] == NULL, "of_property_read_string_array() failure; rc=%i\n", rc); + unittest(rc == 2 && strings[2] == NULL, "of_property_read_string_array() failure; rc=%i\n", rc); strings[1] = NULL; rc = of_property_read_string_array(np, "phandle-list-names", strings, 1); - selftest(rc == 1 && strings[1] == NULL, "Overwrote end of string array; rc=%i, str='%s'\n", rc, strings[1]); + unittest(rc == 1 && strings[1] == NULL, "Overwrote end of string array; rc=%i, str='%s'\n", rc, strings[1]); } #define propcmp(p1, p2) (((p1)->length == (p2)->length) && \ (p1)->value && (p2)->value && \ !memcmp((p1)->value, (p2)->value, (p1)->length) && \ !strcmp((p1)->name, (p2)->name)) -static void __init of_selftest_property_copy(void) +static void __init of_unittest_property_copy(void) { #ifdef CONFIG_OF_DYNAMIC struct property p1 = { .name = "p1", .length = 0, .value = "" }; @@ -472,20 +472,20 @@ static void __init of_selftest_property_copy(void) struct property *new; new = __of_prop_dup(&p1, GFP_KERNEL); - selftest(new && propcmp(&p1, new), "empty property didn't copy correctly\n"); + unittest(new && propcmp(&p1, new), "empty property didn't copy correctly\n"); kfree(new->value); kfree(new->name); kfree(new); new = __of_prop_dup(&p2, GFP_KERNEL); - selftest(new && propcmp(&p2, new), "non-empty property didn't copy correctly\n"); + unittest(new && propcmp(&p2, new), "non-empty property didn't copy correctly\n"); kfree(new->value); kfree(new->name); kfree(new); #endif } -static void __init of_selftest_changeset(void) +static void __init of_unittest_changeset(void) { #ifdef CONFIG_OF_DYNAMIC struct property *ppadd, padd = { .name = "prop-add", .length = 0, .value = "" }; @@ -495,51 +495,51 @@ static void __init of_selftest_changeset(void) struct of_changeset chgset; n1 = __of_node_dup(NULL, "/testcase-data/changeset/n1"); - selftest(n1, "testcase setup failure\n"); + unittest(n1, "testcase setup failure\n"); n2 = __of_node_dup(NULL, "/testcase-data/changeset/n2"); - selftest(n2, "testcase setup failure\n"); + unittest(n2, "testcase setup failure\n"); n21 = __of_node_dup(NULL, "%s/%s", "/testcase-data/changeset/n2", "n21"); - selftest(n21, "testcase setup failure %p\n", n21); + unittest(n21, "testcase setup failure %p\n", n21); nremove = of_find_node_by_path("/testcase-data/changeset/node-remove"); - selftest(nremove, "testcase setup failure\n"); + unittest(nremove, "testcase setup failure\n"); ppadd = __of_prop_dup(&padd, GFP_KERNEL); - selftest(ppadd, "testcase setup failure\n"); + unittest(ppadd, "testcase setup failure\n"); ppupdate = __of_prop_dup(&pupdate, GFP_KERNEL); - selftest(ppupdate, "testcase setup failure\n"); + unittest(ppupdate, "testcase setup failure\n"); parent = nremove->parent; n1->parent = parent; n2->parent = parent; n21->parent = n2; n2->child = n21; ppremove = of_find_property(parent, "prop-remove", NULL); - selftest(ppremove, "failed to find removal prop"); + unittest(ppremove, "failed to find removal prop"); of_changeset_init(&chgset); - selftest(!of_changeset_attach_node(&chgset, n1), "fail attach n1\n"); - selftest(!of_changeset_attach_node(&chgset, n2), "fail attach n2\n"); - selftest(!of_changeset_detach_node(&chgset, nremove), "fail remove node\n"); - selftest(!of_changeset_attach_node(&chgset, n21), "fail attach n21\n"); - selftest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop\n"); - selftest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n"); - selftest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n"); + unittest(!of_changeset_attach_node(&chgset, n1), "fail attach n1\n"); + unittest(!of_changeset_attach_node(&chgset, n2), "fail attach n2\n"); + unittest(!of_changeset_detach_node(&chgset, nremove), "fail remove node\n"); + unittest(!of_changeset_attach_node(&chgset, n21), "fail attach n21\n"); + unittest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop\n"); + unittest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n"); + unittest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n"); mutex_lock(&of_mutex); - selftest(!of_changeset_apply(&chgset), "apply failed\n"); + unittest(!of_changeset_apply(&chgset), "apply failed\n"); mutex_unlock(&of_mutex); /* Make sure node names are constructed correctly */ - selftest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), + unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), "'%s' not added\n", n21->full_name); of_node_put(np); mutex_lock(&of_mutex); - selftest(!of_changeset_revert(&chgset), "revert failed\n"); + unittest(!of_changeset_revert(&chgset), "revert failed\n"); mutex_unlock(&of_mutex); of_changeset_destroy(&chgset); #endif } -static void __init of_selftest_parse_interrupts(void) +static void __init of_unittest_parse_interrupts(void) { struct device_node *np; struct of_phandle_args args; @@ -560,7 +560,7 @@ static void __init of_selftest_parse_interrupts(void) passed &= (args.args_count == 1); passed &= (args.args[0] == (i + 1)); - selftest(passed, "index %i - data error on node %s rc=%i\n", + unittest(passed, "index %i - data error on node %s rc=%i\n", i, args.np->full_name, rc); } of_node_put(np); @@ -605,13 +605,13 @@ static void __init of_selftest_parse_interrupts(void) default: passed = false; } - selftest(passed, "index %i - data error on node %s rc=%i\n", + unittest(passed, "index %i - data error on node %s rc=%i\n", i, args.np->full_name, rc); } of_node_put(np); } -static void __init of_selftest_parse_interrupts_extended(void) +static void __init of_unittest_parse_interrupts_extended(void) { struct device_node *np; struct of_phandle_args args; @@ -674,7 +674,7 @@ static void __init of_selftest_parse_interrupts_extended(void) passed = false; } - selftest(passed, "index %i - data error on node %s rc=%i\n", + unittest(passed, "index %i - data error on node %s rc=%i\n", i, args.np->full_name, rc); } of_node_put(np); @@ -715,7 +715,7 @@ static struct { { .path = "/testcase-data/match-node/name9", .data = "K", }, }; -static void __init of_selftest_match_node(void) +static void __init of_unittest_match_node(void) { struct device_node *np; const struct of_device_id *match; @@ -724,32 +724,32 @@ static void __init of_selftest_match_node(void) for (i = 0; i < ARRAY_SIZE(match_node_tests); i++) { np = of_find_node_by_path(match_node_tests[i].path); if (!np) { - selftest(0, "missing testcase node %s\n", + unittest(0, "missing testcase node %s\n", match_node_tests[i].path); continue; } match = of_match_node(match_node_table, np); if (!match) { - selftest(0, "%s didn't match anything\n", + unittest(0, "%s didn't match anything\n", match_node_tests[i].path); continue; } if (strcmp(match->data, match_node_tests[i].data) != 0) { - selftest(0, "%s got wrong match. expected %s, got %s\n", + unittest(0, "%s got wrong match. expected %s, got %s\n", match_node_tests[i].path, match_node_tests[i].data, (const char *)match->data); continue; } - selftest(1, "passed"); + unittest(1, "passed"); } } struct device test_bus = { .init_name = "unittest-bus", }; -static void __init of_selftest_platform_populate(void) +static void __init of_unittest_platform_populate(void) { int irq, rc; struct device_node *np, *child, *grandchild; @@ -765,30 +765,30 @@ static void __init of_selftest_platform_populate(void) /* Test that a missing irq domain returns -EPROBE_DEFER */ np = of_find_node_by_path("/testcase-data/testcase-device1"); pdev = of_find_device_by_node(np); - selftest(pdev, "device 1 creation failed\n"); + unittest(pdev, "device 1 creation failed\n"); irq = platform_get_irq(pdev, 0); - selftest(irq == -EPROBE_DEFER, "device deferred probe failed - %d\n", irq); + unittest(irq == -EPROBE_DEFER, "device deferred probe failed - %d\n", irq); /* Test that a parsing failure does not return -EPROBE_DEFER */ np = of_find_node_by_path("/testcase-data/testcase-device2"); pdev = of_find_device_by_node(np); - selftest(pdev, "device 2 creation failed\n"); + unittest(pdev, "device 2 creation failed\n"); irq = platform_get_irq(pdev, 0); - selftest(irq < 0 && irq != -EPROBE_DEFER, "device parsing error failed - %d\n", irq); + unittest(irq < 0 && irq != -EPROBE_DEFER, "device parsing error failed - %d\n", irq); - if (selftest(np = of_find_node_by_path("/testcase-data/platform-tests"), + if (unittest(np = of_find_node_by_path("/testcase-data/platform-tests"), "No testcase data in device tree\n")); return; - if (selftest(!(rc = device_register(&test_bus)), + if (unittest(!(rc = device_register(&test_bus)), "testbus registration failed; rc=%i\n", rc)); return; for_each_child_of_node(np, child) { of_platform_populate(child, match, NULL, &test_bus); for_each_child_of_node(child, grandchild) - selftest(of_find_device_by_node(grandchild), + unittest(of_find_device_by_node(grandchild), "Could not create device for node '%s'\n", grandchild->name); } @@ -796,7 +796,7 @@ static void __init of_selftest_platform_populate(void) of_platform_depopulate(&test_bus); for_each_child_of_node(np, child) { for_each_child_of_node(child, grandchild) - selftest(!of_find_device_by_node(grandchild), + unittest(!of_find_device_by_node(grandchild), "device didn't get destroyed '%s'\n", grandchild->name); } @@ -866,13 +866,13 @@ static int attach_node_and_children(struct device_node *np) } /** - * selftest_data_add - Reads, copies data from + * unittest_data_add - Reads, copies data from * linked tree and attaches it to the live tree */ -static int __init selftest_data_add(void) +static int __init unittest_data_add(void) { - void *selftest_data; - struct device_node *selftest_data_node, *np; + void *unittest_data; + struct device_node *unittest_data_node, *np; extern uint8_t __dtb_testcases_begin[]; extern uint8_t __dtb_testcases_end[]; const int size = __dtb_testcases_end - __dtb_testcases_begin; @@ -885,27 +885,27 @@ static int __init selftest_data_add(void) } /* creating copy */ - selftest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL); + unittest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL); - if (!selftest_data) { - pr_warn("%s: Failed to allocate memory for selftest_data; " + if (!unittest_data) { + pr_warn("%s: Failed to allocate memory for unittest_data; " "not running tests\n", __func__); return -ENOMEM; } - of_fdt_unflatten_tree(selftest_data, &selftest_data_node); - if (!selftest_data_node) { + of_fdt_unflatten_tree(unittest_data, &unittest_data_node); + if (!unittest_data_node) { pr_warn("%s: No tree to attach; not running tests\n", __func__); return -ENODATA; } - of_node_set_flag(selftest_data_node, OF_DETACHED); - rc = of_resolve_phandles(selftest_data_node); + of_node_set_flag(unittest_data_node, OF_DETACHED); + rc = of_resolve_phandles(unittest_data_node); if (rc) { pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc); return -EINVAL; } if (!of_root) { - of_root = selftest_data_node; + of_root = unittest_data_node; for_each_of_allnodes(np) __of_attach_node_sysfs(np); of_aliases = of_find_node_by_path("/aliases"); @@ -914,7 +914,7 @@ static int __init selftest_data_add(void) } /* attach the sub-tree to live tree */ - np = selftest_data_node->child; + np = unittest_data_node->child; while (np) { struct device_node *next = np->sibling; np->parent = of_root; @@ -926,7 +926,7 @@ static int __init selftest_data_add(void) #ifdef CONFIG_OF_OVERLAY -static int selftest_probe(struct platform_device *pdev) +static int unittest_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -944,7 +944,7 @@ static int selftest_probe(struct platform_device *pdev) return 0; } -static int selftest_remove(struct platform_device *pdev) +static int unittest_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -953,18 +953,18 @@ static int selftest_remove(struct platform_device *pdev) return 0; } -static struct of_device_id selftest_match[] = { - { .compatible = "selftest", }, +static struct of_device_id unittest_match[] = { + { .compatible = "unittest", }, {}, }; -static struct platform_driver selftest_driver = { - .probe = selftest_probe, - .remove = selftest_remove, +static struct platform_driver unittest_driver = { + .probe = unittest_probe, + .remove = unittest_remove, .driver = { - .name = "selftest", + .name = "unittest", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(selftest_match), + .of_match_table = of_match_ptr(unittest_match), }, }; @@ -1046,7 +1046,7 @@ static int of_path_device_type_exists(const char *path, return 0; } -static const char *selftest_path(int nr, enum overlay_type ovtype) +static const char *unittest_path(int nr, enum overlay_type ovtype) { const char *base; static char buf[256]; @@ -1062,16 +1062,16 @@ static const char *selftest_path(int nr, enum overlay_type ovtype) buf[0] = '\0'; return buf; } - snprintf(buf, sizeof(buf) - 1, "%s/test-selftest%d", base, nr); + snprintf(buf, sizeof(buf) - 1, "%s/test-unittest%d", base, nr); buf[sizeof(buf) - 1] = '\0'; return buf; } -static int of_selftest_device_exists(int selftest_nr, enum overlay_type ovtype) +static int of_unittest_device_exists(int unittest_nr, enum overlay_type ovtype) { const char *path; - path = selftest_path(selftest_nr, ovtype); + path = unittest_path(unittest_nr, ovtype); switch (ovtype) { case PDEV_OVERLAY: @@ -1095,7 +1095,7 @@ static const char *overlay_path(int nr) static const char *bus_path = "/testcase-data/overlay-node/test-bus"; -static int of_selftest_apply_overlay(int selftest_nr, int overlay_nr, +static int of_unittest_apply_overlay(int unittest_nr, int overlay_nr, int *overlay_id) { struct device_node *np = NULL; @@ -1103,7 +1103,7 @@ static int of_selftest_apply_overlay(int selftest_nr, int overlay_nr, np = of_find_node_by_path(overlay_path(overlay_nr)); if (np == NULL) { - selftest(0, "could not find overlay node @\"%s\"\n", + unittest(0, "could not find overlay node @\"%s\"\n", overlay_path(overlay_nr)); ret = -EINVAL; goto out; @@ -1111,7 +1111,7 @@ static int of_selftest_apply_overlay(int selftest_nr, int overlay_nr, ret = of_overlay_create(np); if (ret < 0) { - selftest(0, "could not create overlay from \"%s\"\n", + unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr)); goto out; } @@ -1129,31 +1129,31 @@ out: } /* apply an overlay while checking before and after states */ -static int of_selftest_apply_overlay_check(int overlay_nr, int selftest_nr, +static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr, int before, int after, enum overlay_type ovtype) { int ret; - /* selftest device must not be in before state */ - if (of_selftest_device_exists(selftest_nr, ovtype) != before) { - selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", + /* unittest device must not be in before state */ + if (of_unittest_device_exists(unittest_nr, ovtype) != before) { + unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n", overlay_path(overlay_nr), - selftest_path(selftest_nr, ovtype), + unittest_path(unittest_nr, ovtype), !before ? "enabled" : "disabled"); return -EINVAL; } - ret = of_selftest_apply_overlay(overlay_nr, selftest_nr, NULL); + ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, NULL); if (ret != 0) { - /* of_selftest_apply_overlay already called selftest() */ + /* of_unittest_apply_overlay already called unittest() */ return ret; } - /* selftest device must be to set to after state */ - if (of_selftest_device_exists(selftest_nr, ovtype) != after) { - selftest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", + /* unittest device must be to set to after state */ + if (of_unittest_device_exists(unittest_nr, ovtype) != after) { + unittest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", overlay_path(overlay_nr), - selftest_path(selftest_nr, ovtype), + unittest_path(unittest_nr, ovtype), !after ? "enabled" : "disabled"); return -EINVAL; } @@ -1162,50 +1162,50 @@ static int of_selftest_apply_overlay_check(int overlay_nr, int selftest_nr, } /* apply an overlay and then revert it while checking before, after states */ -static int of_selftest_apply_revert_overlay_check(int overlay_nr, - int selftest_nr, int before, int after, +static int of_unittest_apply_revert_overlay_check(int overlay_nr, + int unittest_nr, int before, int after, enum overlay_type ovtype) { int ret, ov_id; - /* selftest device must be in before state */ - if (of_selftest_device_exists(selftest_nr, ovtype) != before) { - selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", + /* unittest device must be in before state */ + if (of_unittest_device_exists(unittest_nr, ovtype) != before) { + unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n", overlay_path(overlay_nr), - selftest_path(selftest_nr, ovtype), + unittest_path(unittest_nr, ovtype), !before ? "enabled" : "disabled"); return -EINVAL; } /* apply the overlay */ - ret = of_selftest_apply_overlay(overlay_nr, selftest_nr, &ov_id); + ret = of_unittest_apply_overlay(overlay_nr, unittest_nr, &ov_id); if (ret != 0) { - /* of_selftest_apply_overlay already called selftest() */ + /* of_unittest_apply_overlay already called unittest() */ return ret; } - /* selftest device must be in after state */ - if (of_selftest_device_exists(selftest_nr, ovtype) != after) { - selftest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", + /* unittest device must be in after state */ + if (of_unittest_device_exists(unittest_nr, ovtype) != after) { + unittest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", overlay_path(overlay_nr), - selftest_path(selftest_nr, ovtype), + unittest_path(unittest_nr, ovtype), !after ? "enabled" : "disabled"); return -EINVAL; } ret = of_overlay_destroy(ov_id); if (ret != 0) { - selftest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n", + unittest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n", overlay_path(overlay_nr), - selftest_path(selftest_nr, ovtype)); + unittest_path(unittest_nr, ovtype)); return ret; } - /* selftest device must be again in before state */ - if (of_selftest_device_exists(selftest_nr, PDEV_OVERLAY) != before) { - selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", + /* unittest device must be again in before state */ + if (of_unittest_device_exists(unittest_nr, PDEV_OVERLAY) != before) { + unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n", overlay_path(overlay_nr), - selftest_path(selftest_nr, ovtype), + unittest_path(unittest_nr, ovtype), !before ? "enabled" : "disabled"); return -EINVAL; } @@ -1214,98 +1214,98 @@ static int of_selftest_apply_revert_overlay_check(int overlay_nr, } /* test activation of device */ -static void of_selftest_overlay_0(void) +static void of_unittest_overlay_0(void) { int ret; /* device should enable */ - ret = of_selftest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY); + ret = of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY); if (ret != 0) return; - selftest(1, "overlay test %d passed\n", 0); + unittest(1, "overlay test %d passed\n", 0); } /* test deactivation of device */ -static void of_selftest_overlay_1(void) +static void of_unittest_overlay_1(void) { int ret; /* device should disable */ - ret = of_selftest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY); + ret = of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY); if (ret != 0) return; - selftest(1, "overlay test %d passed\n", 1); + unittest(1, "overlay test %d passed\n", 1); } /* test activation of device */ -static void of_selftest_overlay_2(void) +static void of_unittest_overlay_2(void) { int ret; /* device should enable */ - ret = of_selftest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY); + ret = of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY); if (ret != 0) return; - selftest(1, "overlay test %d passed\n", 2); + unittest(1, "overlay test %d passed\n", 2); } /* test deactivation of device */ -static void of_selftest_overlay_3(void) +static void of_unittest_overlay_3(void) { int ret; /* device should disable */ - ret = of_selftest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY); + ret = of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY); if (ret != 0) return; - selftest(1, "overlay test %d passed\n", 3); + unittest(1, "overlay test %d passed\n", 3); } /* test activation of a full device node */ -static void of_selftest_overlay_4(void) +static void of_unittest_overlay_4(void) { int ret; /* device should disable */ - ret = of_selftest_apply_overlay_check(4, 4, 0, 1, PDEV_OVERLAY); + ret = of_unittest_apply_overlay_check(4, 4, 0, 1, PDEV_OVERLAY); if (ret != 0) return; - selftest(1, "overlay test %d passed\n", 4); + unittest(1, "overlay test %d passed\n", 4); } /* test overlay apply/revert sequence */ -static void of_selftest_overlay_5(void) +static void of_unittest_overlay_5(void) { int ret; /* device should disable */ - ret = of_selftest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY); + ret = of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY); if (ret != 0) return; - selftest(1, "overlay test %d passed\n", 5); + unittest(1, "overlay test %d passed\n", 5); } /* test overlay application in sequence */ -static void of_selftest_overlay_6(void) +static void of_unittest_overlay_6(void) { struct device_node *np; int ret, i, ov_id[2]; - int overlay_nr = 6, selftest_nr = 6; + int overlay_nr = 6, unittest_nr = 6; int before = 0, after = 1; - /* selftest device must be in before state */ + /* unittest device must be in before state */ for (i = 0; i < 2; i++) { - if (of_selftest_device_exists(selftest_nr + i, PDEV_OVERLAY) + if (of_unittest_device_exists(unittest_nr + i, PDEV_OVERLAY) != before) { - selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", + unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n", overlay_path(overlay_nr + i), - selftest_path(selftest_nr + i, + unittest_path(unittest_nr + i, PDEV_OVERLAY), !before ? "enabled" : "disabled"); return; @@ -1317,14 +1317,14 @@ static void of_selftest_overlay_6(void) np = of_find_node_by_path(overlay_path(overlay_nr + i)); if (np == NULL) { - selftest(0, "could not find overlay node @\"%s\"\n", + unittest(0, "could not find overlay node @\"%s\"\n", overlay_path(overlay_nr + i)); return; } ret = of_overlay_create(np); if (ret < 0) { - selftest(0, "could not create overlay from \"%s\"\n", + unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr + i)); return; } @@ -1332,12 +1332,12 @@ static void of_selftest_overlay_6(void) } for (i = 0; i < 2; i++) { - /* selftest device must be in after state */ - if (of_selftest_device_exists(selftest_nr + i, PDEV_OVERLAY) + /* unittest device must be in after state */ + if (of_unittest_device_exists(unittest_nr + i, PDEV_OVERLAY) != after) { - selftest(0, "overlay @\"%s\" failed @\"%s\" %s\n", + unittest(0, "overlay @\"%s\" failed @\"%s\" %s\n", overlay_path(overlay_nr + i), - selftest_path(selftest_nr + i, + unittest_path(unittest_nr + i, PDEV_OVERLAY), !after ? "enabled" : "disabled"); return; @@ -1347,36 +1347,36 @@ static void of_selftest_overlay_6(void) for (i = 1; i >= 0; i--) { ret = of_overlay_destroy(ov_id[i]); if (ret != 0) { - selftest(0, "overlay @\"%s\" failed destroy @\"%s\"\n", + unittest(0, "overlay @\"%s\" failed destroy @\"%s\"\n", overlay_path(overlay_nr + i), - selftest_path(selftest_nr + i, + unittest_path(unittest_nr + i, PDEV_OVERLAY)); return; } } for (i = 0; i < 2; i++) { - /* selftest device must be again in before state */ - if (of_selftest_device_exists(selftest_nr + i, PDEV_OVERLAY) + /* unittest device must be again in before state */ + if (of_unittest_device_exists(unittest_nr + i, PDEV_OVERLAY) != before) { - selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", + unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n", overlay_path(overlay_nr + i), - selftest_path(selftest_nr + i, + unittest_path(unittest_nr + i, PDEV_OVERLAY), !before ? "enabled" : "disabled"); return; } } - selftest(1, "overlay test %d passed\n", 6); + unittest(1, "overlay test %d passed\n", 6); } /* test overlay application in sequence */ -static void of_selftest_overlay_8(void) +static void of_unittest_overlay_8(void) { struct device_node *np; int ret, i, ov_id[2]; - int overlay_nr = 8, selftest_nr = 8; + int overlay_nr = 8, unittest_nr = 8; /* we don't care about device state in this test */ @@ -1385,14 +1385,14 @@ static void of_selftest_overlay_8(void) np = of_find_node_by_path(overlay_path(overlay_nr + i)); if (np == NULL) { - selftest(0, "could not find overlay node @\"%s\"\n", + unittest(0, "could not find overlay node @\"%s\"\n", overlay_path(overlay_nr + i)); return; } ret = of_overlay_create(np); if (ret < 0) { - selftest(0, "could not create overlay from \"%s\"\n", + unittest(0, "could not create overlay from \"%s\"\n", overlay_path(overlay_nr + i)); return; } @@ -1402,9 +1402,9 @@ static void of_selftest_overlay_8(void) /* now try to remove first overlay (it should fail) */ ret = of_overlay_destroy(ov_id[0]); if (ret == 0) { - selftest(0, "overlay @\"%s\" was destroyed @\"%s\"\n", + unittest(0, "overlay @\"%s\" was destroyed @\"%s\"\n", overlay_path(overlay_nr + 0), - selftest_path(selftest_nr, + unittest_path(unittest_nr, PDEV_OVERLAY)); return; } @@ -1413,85 +1413,85 @@ static void of_selftest_overlay_8(void) for (i = 1; i >= 0; i--) { ret = of_overlay_destroy(ov_id[i]); if (ret != 0) { - selftest(0, "overlay @\"%s\" not destroyed @\"%s\"\n", + unittest(0, "overlay @\"%s\" not destroyed @\"%s\"\n", overlay_path(overlay_nr + i), - selftest_path(selftest_nr, + unittest_path(unittest_nr, PDEV_OVERLAY)); return; } } - selftest(1, "overlay test %d passed\n", 8); + unittest(1, "overlay test %d passed\n", 8); } /* test insertion of a bus with parent devices */ -static void of_selftest_overlay_10(void) +static void of_unittest_overlay_10(void) { int ret; char *child_path; /* device should disable */ - ret = of_selftest_apply_overlay_check(10, 10, 0, 1, PDEV_OVERLAY); - if (selftest(ret == 0, + ret = of_unittest_apply_overlay_check(10, 10, 0, 1, PDEV_OVERLAY); + if (unittest(ret == 0, "overlay test %d failed; overlay application\n", 10)) return; - child_path = kasprintf(GFP_KERNEL, "%s/test-selftest101", - selftest_path(10, PDEV_OVERLAY)); - if (selftest(child_path, "overlay test %d failed; kasprintf\n", 10)) + child_path = kasprintf(GFP_KERNEL, "%s/test-unittest101", + unittest_path(10, PDEV_OVERLAY)); + if (unittest(child_path, "overlay test %d failed; kasprintf\n", 10)) return; ret = of_path_device_type_exists(child_path, PDEV_OVERLAY); kfree(child_path); - if (selftest(ret, "overlay test %d failed; no child device\n", 10)) + if (unittest(ret, "overlay test %d failed; no child device\n", 10)) return; } /* test insertion of a bus with parent devices (and revert) */ -static void of_selftest_overlay_11(void) +static void of_unittest_overlay_11(void) { int ret; /* device should disable */ - ret = of_selftest_apply_revert_overlay_check(11, 11, 0, 1, + ret = of_unittest_apply_revert_overlay_check(11, 11, 0, 1, PDEV_OVERLAY); - if (selftest(ret == 0, + if (unittest(ret == 0, "overlay test %d failed; overlay application\n", 11)) return; } #if IS_BUILTIN(CONFIG_I2C) && IS_ENABLED(CONFIG_OF_OVERLAY) -struct selftest_i2c_bus_data { +struct unittest_i2c_bus_data { struct platform_device *pdev; struct i2c_adapter adap; }; -static int selftest_i2c_master_xfer(struct i2c_adapter *adap, +static int unittest_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { - struct selftest_i2c_bus_data *std = i2c_get_adapdata(adap); + struct unittest_i2c_bus_data *std = i2c_get_adapdata(adap); (void)std; return num; } -static u32 selftest_i2c_functionality(struct i2c_adapter *adap) +static u32 unittest_i2c_functionality(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } -static const struct i2c_algorithm selftest_i2c_algo = { - .master_xfer = selftest_i2c_master_xfer, - .functionality = selftest_i2c_functionality, +static const struct i2c_algorithm unittest_i2c_algo = { + .master_xfer = unittest_i2c_master_xfer, + .functionality = unittest_i2c_functionality, }; -static int selftest_i2c_bus_probe(struct platform_device *pdev) +static int unittest_i2c_bus_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct selftest_i2c_bus_data *std; + struct unittest_i2c_bus_data *std; struct i2c_adapter *adap; int ret; @@ -1505,7 +1505,7 @@ static int selftest_i2c_bus_probe(struct platform_device *pdev) std = devm_kzalloc(dev, sizeof(*std), GFP_KERNEL); if (!std) { - dev_err(dev, "Failed to allocate selftest i2c data\n"); + dev_err(dev, "Failed to allocate unittest i2c data\n"); return -ENOMEM; } @@ -1518,7 +1518,7 @@ static int selftest_i2c_bus_probe(struct platform_device *pdev) adap->nr = -1; strlcpy(adap->name, pdev->name, sizeof(adap->name)); adap->class = I2C_CLASS_DEPRECATED; - adap->algo = &selftest_i2c_algo; + adap->algo = &unittest_i2c_algo; adap->dev.parent = dev; adap->dev.of_node = dev->of_node; adap->timeout = 5 * HZ; @@ -1533,11 +1533,11 @@ static int selftest_i2c_bus_probe(struct platform_device *pdev) return 0; } -static int selftest_i2c_bus_remove(struct platform_device *pdev) +static int unittest_i2c_bus_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct selftest_i2c_bus_data *std = platform_get_drvdata(pdev); + struct unittest_i2c_bus_data *std = platform_get_drvdata(pdev); dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); i2c_del_adapter(&std->adap); @@ -1545,21 +1545,21 @@ static int selftest_i2c_bus_remove(struct platform_device *pdev) return 0; } -static struct of_device_id selftest_i2c_bus_match[] = { - { .compatible = "selftest-i2c-bus", }, +static struct of_device_id unittest_i2c_bus_match[] = { + { .compatible = "unittest-i2c-bus", }, {}, }; -static struct platform_driver selftest_i2c_bus_driver = { - .probe = selftest_i2c_bus_probe, - .remove = selftest_i2c_bus_remove, +static struct platform_driver unittest_i2c_bus_driver = { + .probe = unittest_i2c_bus_probe, + .remove = unittest_i2c_bus_remove, .driver = { - .name = "selftest-i2c-bus", - .of_match_table = of_match_ptr(selftest_i2c_bus_match), + .name = "unittest-i2c-bus", + .of_match_table = of_match_ptr(unittest_i2c_bus_match), }, }; -static int selftest_i2c_dev_probe(struct i2c_client *client, +static int unittest_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; @@ -1575,7 +1575,7 @@ static int selftest_i2c_dev_probe(struct i2c_client *client, return 0; }; -static int selftest_i2c_dev_remove(struct i2c_client *client) +static int unittest_i2c_dev_remove(struct i2c_client *client) { struct device *dev = &client->dev; struct device_node *np = client->dev.of_node; @@ -1584,42 +1584,42 @@ static int selftest_i2c_dev_remove(struct i2c_client *client) return 0; } -static const struct i2c_device_id selftest_i2c_dev_id[] = { - { .name = "selftest-i2c-dev" }, +static const struct i2c_device_id unittest_i2c_dev_id[] = { + { .name = "unittest-i2c-dev" }, { } }; -static struct i2c_driver selftest_i2c_dev_driver = { +static struct i2c_driver unittest_i2c_dev_driver = { .driver = { - .name = "selftest-i2c-dev", + .name = "unittest-i2c-dev", .owner = THIS_MODULE, }, - .probe = selftest_i2c_dev_probe, - .remove = selftest_i2c_dev_remove, - .id_table = selftest_i2c_dev_id, + .probe = unittest_i2c_dev_probe, + .remove = unittest_i2c_dev_remove, + .id_table = unittest_i2c_dev_id, }; #if IS_BUILTIN(CONFIG_I2C_MUX) -struct selftest_i2c_mux_data { +struct unittest_i2c_mux_data { int nchans; struct i2c_adapter *adap[]; }; -static int selftest_i2c_mux_select_chan(struct i2c_adapter *adap, +static int unittest_i2c_mux_select_chan(struct i2c_adapter *adap, void *client, u32 chan) { return 0; } -static int selftest_i2c_mux_probe(struct i2c_client *client, +static int unittest_i2c_mux_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret, i, nchans, size; struct device *dev = &client->dev; struct i2c_adapter *adap = to_i2c_adapter(dev->parent); struct device_node *np = client->dev.of_node, *child; - struct selftest_i2c_mux_data *stm; + struct unittest_i2c_mux_data *stm; u32 reg, max_reg; dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); @@ -1643,7 +1643,7 @@ static int selftest_i2c_mux_probe(struct i2c_client *client, return -EINVAL; } - size = offsetof(struct selftest_i2c_mux_data, adap[nchans]); + size = offsetof(struct unittest_i2c_mux_data, adap[nchans]); stm = devm_kzalloc(dev, size, GFP_KERNEL); if (!stm) { dev_err(dev, "Out of memory\n"); @@ -1652,7 +1652,7 @@ static int selftest_i2c_mux_probe(struct i2c_client *client, stm->nchans = nchans; for (i = 0; i < nchans; i++) { stm->adap[i] = i2c_add_mux_adapter(adap, dev, client, - 0, i, 0, selftest_i2c_mux_select_chan, NULL); + 0, i, 0, unittest_i2c_mux_select_chan, NULL); if (!stm->adap[i]) { dev_err(dev, "Failed to register mux #%d\n", i); for (i--; i >= 0; i--) @@ -1666,11 +1666,11 @@ static int selftest_i2c_mux_probe(struct i2c_client *client, return 0; }; -static int selftest_i2c_mux_remove(struct i2c_client *client) +static int unittest_i2c_mux_remove(struct i2c_client *client) { struct device *dev = &client->dev; struct device_node *np = client->dev.of_node; - struct selftest_i2c_mux_data *stm = i2c_get_clientdata(client); + struct unittest_i2c_mux_data *stm = i2c_get_clientdata(client); int i; dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); @@ -1679,166 +1679,166 @@ static int selftest_i2c_mux_remove(struct i2c_client *client) return 0; } -static const struct i2c_device_id selftest_i2c_mux_id[] = { - { .name = "selftest-i2c-mux" }, +static const struct i2c_device_id unittest_i2c_mux_id[] = { + { .name = "unittest-i2c-mux" }, { } }; -static struct i2c_driver selftest_i2c_mux_driver = { +static struct i2c_driver unittest_i2c_mux_driver = { .driver = { - .name = "selftest-i2c-mux", + .name = "unittest-i2c-mux", .owner = THIS_MODULE, }, - .probe = selftest_i2c_mux_probe, - .remove = selftest_i2c_mux_remove, - .id_table = selftest_i2c_mux_id, + .probe = unittest_i2c_mux_probe, + .remove = unittest_i2c_mux_remove, + .id_table = unittest_i2c_mux_id, }; #endif -static int of_selftest_overlay_i2c_init(void) +static int of_unittest_overlay_i2c_init(void) { int ret; - ret = i2c_add_driver(&selftest_i2c_dev_driver); - if (selftest(ret == 0, - "could not register selftest i2c device driver\n")) + ret = i2c_add_driver(&unittest_i2c_dev_driver); + if (unittest(ret == 0, + "could not register unittest i2c device driver\n")) return ret; - ret = platform_driver_register(&selftest_i2c_bus_driver); - if (selftest(ret == 0, - "could not register selftest i2c bus driver\n")) + ret = platform_driver_register(&unittest_i2c_bus_driver); + if (unittest(ret == 0, + "could not register unittest i2c bus driver\n")) return ret; #if IS_BUILTIN(CONFIG_I2C_MUX) - ret = i2c_add_driver(&selftest_i2c_mux_driver); - if (selftest(ret == 0, - "could not register selftest i2c mux driver\n")) + ret = i2c_add_driver(&unittest_i2c_mux_driver); + if (unittest(ret == 0, + "could not register unittest i2c mux driver\n")) return ret; #endif return 0; } -static void of_selftest_overlay_i2c_cleanup(void) +static void of_unittest_overlay_i2c_cleanup(void) { #if IS_BUILTIN(CONFIG_I2C_MUX) - i2c_del_driver(&selftest_i2c_mux_driver); + i2c_del_driver(&unittest_i2c_mux_driver); #endif - platform_driver_unregister(&selftest_i2c_bus_driver); - i2c_del_driver(&selftest_i2c_dev_driver); + platform_driver_unregister(&unittest_i2c_bus_driver); + i2c_del_driver(&unittest_i2c_dev_driver); } -static void of_selftest_overlay_i2c_12(void) +static void of_unittest_overlay_i2c_12(void) { int ret; /* device should enable */ - ret = of_selftest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY); + ret = of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY); if (ret != 0) return; - selftest(1, "overlay test %d passed\n", 12); + unittest(1, "overlay test %d passed\n", 12); } /* test deactivation of device */ -static void of_selftest_overlay_i2c_13(void) +static void of_unittest_overlay_i2c_13(void) { int ret; /* device should disable */ - ret = of_selftest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY); + ret = of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY); if (ret != 0) return; - selftest(1, "overlay test %d passed\n", 13); + unittest(1, "overlay test %d passed\n", 13); } /* just check for i2c mux existence */ -static void of_selftest_overlay_i2c_14(void) +static void of_unittest_overlay_i2c_14(void) { } -static void of_selftest_overlay_i2c_15(void) +static void of_unittest_overlay_i2c_15(void) { int ret; /* device should enable */ - ret = of_selftest_apply_overlay_check(16, 15, 0, 1, I2C_OVERLAY); + ret = of_unittest_apply_overlay_check(16, 15, 0, 1, I2C_OVERLAY); if (ret != 0) return; - selftest(1, "overlay test %d passed\n", 15); + unittest(1, "overlay test %d passed\n", 15); } #else -static inline void of_selftest_overlay_i2c_14(void) { } -static inline void of_selftest_overlay_i2c_15(void) { } +static inline void of_unittest_overlay_i2c_14(void) { } +static inline void of_unittest_overlay_i2c_15(void) { } #endif -static void __init of_selftest_overlay(void) +static void __init of_unittest_overlay(void) { struct device_node *bus_np = NULL; int ret; - ret = platform_driver_register(&selftest_driver); + ret = platform_driver_register(&unittest_driver); if (ret != 0) { - selftest(0, "could not register selftest driver\n"); + unittest(0, "could not register unittest driver\n"); goto out; } bus_np = of_find_node_by_path(bus_path); if (bus_np == NULL) { - selftest(0, "could not find bus_path \"%s\"\n", bus_path); + unittest(0, "could not find bus_path \"%s\"\n", bus_path); goto out; } ret = of_platform_populate(bus_np, of_default_bus_match_table, NULL, NULL); if (ret != 0) { - selftest(0, "could not populate bus @ \"%s\"\n", bus_path); + unittest(0, "could not populate bus @ \"%s\"\n", bus_path); goto out; } - if (!of_selftest_device_exists(100, PDEV_OVERLAY)) { - selftest(0, "could not find selftest0 @ \"%s\"\n", - selftest_path(100, PDEV_OVERLAY)); + if (!of_unittest_device_exists(100, PDEV_OVERLAY)) { + unittest(0, "could not find unittest0 @ \"%s\"\n", + unittest_path(100, PDEV_OVERLAY)); goto out; } - if (of_selftest_device_exists(101, PDEV_OVERLAY)) { - selftest(0, "selftest1 @ \"%s\" should not exist\n", - selftest_path(101, PDEV_OVERLAY)); + if (of_unittest_device_exists(101, PDEV_OVERLAY)) { + unittest(0, "unittest1 @ \"%s\" should not exist\n", + unittest_path(101, PDEV_OVERLAY)); goto out; } - selftest(1, "basic infrastructure of overlays passed"); + unittest(1, "basic infrastructure of overlays passed"); /* tests in sequence */ - of_selftest_overlay_0(); - of_selftest_overlay_1(); - of_selftest_overlay_2(); - of_selftest_overlay_3(); - of_selftest_overlay_4(); - of_selftest_overlay_5(); - of_selftest_overlay_6(); - of_selftest_overlay_8(); - - of_selftest_overlay_10(); - of_selftest_overlay_11(); + of_unittest_overlay_0(); + of_unittest_overlay_1(); + of_unittest_overlay_2(); + of_unittest_overlay_3(); + of_unittest_overlay_4(); + of_unittest_overlay_5(); + of_unittest_overlay_6(); + of_unittest_overlay_8(); + + of_unittest_overlay_10(); + of_unittest_overlay_11(); #if IS_BUILTIN(CONFIG_I2C) - if (selftest(of_selftest_overlay_i2c_init() == 0, "i2c init failed\n")) + if (unittest(of_unittest_overlay_i2c_init() == 0, "i2c init failed\n")) goto out; - of_selftest_overlay_i2c_12(); - of_selftest_overlay_i2c_13(); - of_selftest_overlay_i2c_14(); - of_selftest_overlay_i2c_15(); + of_unittest_overlay_i2c_12(); + of_unittest_overlay_i2c_13(); + of_unittest_overlay_i2c_14(); + of_unittest_overlay_i2c_15(); - of_selftest_overlay_i2c_cleanup(); + of_unittest_overlay_i2c_cleanup(); #endif out: @@ -1846,16 +1846,16 @@ out: } #else -static inline void __init of_selftest_overlay(void) { } +static inline void __init of_unittest_overlay(void) { } #endif -static int __init of_selftest(void) +static int __init of_unittest(void) { struct device_node *np; int res; - /* adding data for selftest */ - res = selftest_data_add(); + /* adding data for unittest */ + res = unittest_data_add(); if (res) return res; if (!of_aliases) @@ -1868,27 +1868,27 @@ static int __init of_selftest(void) } of_node_put(np); - pr_info("start of selftest - you will see error messages\n"); - of_selftest_check_tree_linkage(); - of_selftest_check_phandles(); - of_selftest_find_node_by_name(); - of_selftest_dynamic(); - of_selftest_parse_phandle_with_args(); - of_selftest_property_string(); - of_selftest_property_copy(); - of_selftest_changeset(); - of_selftest_parse_interrupts(); - of_selftest_parse_interrupts_extended(); - of_selftest_match_node(); - of_selftest_platform_populate(); - of_selftest_overlay(); + pr_info("start of unittest - you will see error messages\n"); + of_unittest_check_tree_linkage(); + of_unittest_check_phandles(); + of_unittest_find_node_by_name(); + of_unittest_dynamic(); + of_unittest_parse_phandle_with_args(); + of_unittest_property_string(); + of_unittest_property_copy(); + of_unittest_changeset(); + of_unittest_parse_interrupts(); + of_unittest_parse_interrupts_extended(); + of_unittest_match_node(); + of_unittest_platform_populate(); + of_unittest_overlay(); /* Double check linkage after removing testcase data */ - of_selftest_check_tree_linkage(); + of_unittest_check_tree_linkage(); - pr_info("end of selftest - %i passed, %i failed\n", - selftest_results.passed, selftest_results.failed); + pr_info("end of unittest - %i passed, %i failed\n", + unittest_results.passed, unittest_results.failed); return 0; } -late_initcall(of_selftest); +late_initcall(of_unittest); diff --git a/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c b/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c index 42b87f95267c..8b6f6d5fdd68 100644 --- a/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c +++ b/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c @@ -164,20 +164,15 @@ static void __init omapdss_walk_device(struct device_node *node, bool root) pn = of_graph_get_remote_port_parent(n); - if (!pn) { - of_node_put(n); + if (!pn) continue; - } if (!of_device_is_available(pn) || omapdss_list_contains(pn)) { of_node_put(pn); - of_node_put(n); continue; } omapdss_walk_device(pn, false); - - of_node_put(n); } } diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index befef42e015b..7bc92e050608 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -14,6 +14,8 @@ #ifndef __LINUX_OF_GRAPH_H #define __LINUX_OF_GRAPH_H +#include <linux/types.h> + /** * struct of_endpoint - the OF graph endpoint data structure * @port: identifier (value of reg property) of a port this endpoint belongs to @@ -26,9 +28,21 @@ struct of_endpoint { const struct device_node *local_node; }; +/** + * for_each_endpoint_of_node - iterate over every endpoint in a device node + * @parent: parent device node containing ports and endpoints + * @child: loop variable pointing to the current endpoint node + * + * When breaking out of the loop, of_node_put(child) has to be called manually. + */ +#define for_each_endpoint_of_node(parent, child) \ + for (child = of_graph_get_next_endpoint(parent, NULL); child != NULL; \ + child = of_graph_get_next_endpoint(parent, child)) + #ifdef CONFIG_OF int of_graph_parse_endpoint(const struct device_node *node, struct of_endpoint *endpoint); +struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *previous); struct device_node *of_graph_get_remote_port_parent( @@ -42,6 +56,12 @@ static inline int of_graph_parse_endpoint(const struct device_node *node, return -ENOSYS; } +static inline struct device_node *of_graph_get_port_by_id( + struct device_node *node, u32 id) +{ + return NULL; +} + static inline struct device_node *of_graph_get_next_endpoint( const struct device_node *parent, struct device_node *previous) diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h index 0d7608dc1a34..5507eead5863 100644 --- a/include/uapi/drm/nouveau_drm.h +++ b/include/uapi/drm/nouveau_drm.h @@ -39,6 +39,7 @@ #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) #define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) +#define NOUVEAU_GEM_DOMAIN_COHERENT (1 << 4) #define NOUVEAU_GEM_TILE_COMP 0x00030000 /* nv50-only */ #define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00 diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h index 23b40908be30..83ea46f4be51 100644 --- a/include/uapi/linux/media-bus-format.h +++ b/include/uapi/linux/media-bus-format.h @@ -33,22 +33,30 @@ #define MEDIA_BUS_FMT_FIXED 0x0001 -/* RGB - next is 0x100e */ +/* RGB - next is 0x1016 */ +#define MEDIA_BUS_FMT_RGB444_1X12 0x100e #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002 #define MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE 0x1003 #define MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE 0x1004 +#define MEDIA_BUS_FMT_RGB565_1X16 0x100f #define MEDIA_BUS_FMT_BGR565_2X8_BE 0x1005 #define MEDIA_BUS_FMT_BGR565_2X8_LE 0x1006 #define MEDIA_BUS_FMT_RGB565_2X8_BE 0x1007 #define MEDIA_BUS_FMT_RGB565_2X8_LE 0x1008 #define MEDIA_BUS_FMT_RGB666_1X18 0x1009 +#define MEDIA_BUS_FMT_RGB666_1X24_CPADHI 0x1015 +#define MEDIA_BUS_FMT_RGB666_1X7X3_SPWG 0x1010 +#define MEDIA_BUS_FMT_BGR888_1X24 0x1013 +#define MEDIA_BUS_FMT_GBR888_1X24 0x1014 #define MEDIA_BUS_FMT_RGB888_1X24 0x100a #define MEDIA_BUS_FMT_RGB888_2X12_BE 0x100b #define MEDIA_BUS_FMT_RGB888_2X12_LE 0x100c +#define MEDIA_BUS_FMT_RGB888_1X7X4_SPWG 0x1011 +#define MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA 0x1012 #define MEDIA_BUS_FMT_ARGB8888_1X32 0x100d -/* YUV (including grey) - next is 0x2024 */ +/* YUV (including grey) - next is 0x2025 */ #define MEDIA_BUS_FMT_Y8_1X8 0x2001 #define MEDIA_BUS_FMT_UV8_1X8 0x2015 #define MEDIA_BUS_FMT_UYVY8_1_5X8 0x2002 @@ -74,6 +82,7 @@ #define MEDIA_BUS_FMT_VYUY10_1X20 0x201b #define MEDIA_BUS_FMT_YUYV10_1X20 0x200d #define MEDIA_BUS_FMT_YVYU10_1X20 0x200e +#define MEDIA_BUS_FMT_YUV8_1X24 0x2024 #define MEDIA_BUS_FMT_YUV10_1X30 0x2016 #define MEDIA_BUS_FMT_AYUV8_1X32 0x2017 #define MEDIA_BUS_FMT_UYVY12_2X12 0x201c diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h index 73390c120cad..85dedca3dcfb 100644 --- a/include/video/imx-ipu-v3.h +++ b/include/video/imx-ipu-v3.h @@ -39,7 +39,7 @@ struct ipu_di_signal_cfg { struct videomode mode; - u32 pixel_fmt; + u32 bus_format; u32 v_to_h_sync; #define IPU_DI_CLKMODE_SYNC (1 << 0) diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h index a20e4a3a8b15..0530e5a4c6b1 100644 --- a/include/video/samsung_fimd.h +++ b/include/video/samsung_fimd.h @@ -289,6 +289,11 @@ #define VIDISD14C_ALPHA1_B_LIMIT 0xf #define VIDISD14C_ALPHA1_B(_x) ((_x) << 0) +#define VIDW_ALPHA 0x021c +#define VIDW_ALPHA_R(_x) ((_x) << 16) +#define VIDW_ALPHA_G(_x) ((_x) << 8) +#define VIDW_ALPHA_B(_x) ((_x) << 0) + /* Video buffer addresses */ #define VIDW_BUF_START(_buff) (0xA0 + ((_buff) * 8)) #define VIDW_BUF_START1(_buff) (0xA4 + ((_buff) * 8)) @@ -436,6 +441,12 @@ #define BLENDCON_NEW_8BIT_ALPHA_VALUE (1 << 0) #define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0) +/* Display port clock control */ +#define DP_MIE_CLKCON 0x27c +#define DP_MIE_CLK_DISABLE 0x0 +#define DP_MIE_CLK_DP_ENABLE 0x2 +#define DP_MIE_CLK_MIE_ENABLE 0x3 + /* Notes on per-window bpp settings * * Value Win0 Win1 Win2 Win3 Win 4 |