author | Sundar Raman <a0393242@ti.com> | |
Thu, 25 Jul 2013 20:05:42 +0000 (15:05 -0500) | ||
committer | Sundar Raman <a0393242@ti.com> | |
Thu, 25 Jul 2013 20:05:42 +0000 (15:05 -0500) |
179 files changed:
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
index 374e145c2ef170ceaa32055cf01836bfb3f8c3ef..9bac63e73eb1a8bff5b2dde47f01553b184e429c 100644 (file)
"ti,dm646x-mcasp-audio" : for DM646x platforms
"ti,da830-mcasp-audio" : for both DA830 & DA850 platforms
"ti,omap2-mcasp-audio" : for OMAP2 platforms (TI81xx, AM33xx)
+ "ti,dra7-mcasp-audio" : for DRA7xx platforms
- reg : Should contain McASP registers offset and length
- interrupts : Interrupt number for McASP
- rx-num-evt : FIFO levels.
- sram-size-playback : size of sram to be allocated during playback
- sram-size-capture : size of sram to be allocated during capture
+- ti,tx-inactive-mode : Transmit pin mode while in an inactive slot (0 - Hi-Z,
+ 2 - Low, 3 - High)
+- ti,rx-inactive-mode : Receive pin mode while in an inactive slot (0 - Hi-Z,
+ 2 - Low, 3 - High)
Example:
2 0 0 0 >;
tx-num-evt = <1>;
rx-num-evt = <1>;
+ ti,tx-inactive-mode = <0>; /* 0: Hi-Z, 2: Low, 3: High */
+ ti,rx-inactive-mode = <0>; /* 0: Hi-Z, 2: Low, 3: High */
};
diff --git a/Documentation/devicetree/bindings/sound/dra7-atl.txt b/Documentation/devicetree/bindings/sound/dra7-atl.txt
--- /dev/null
@@ -0,0 +1,42 @@
+* Texas Instruments DRA7 Audio Tracking Logic (ATL)
+
+Required properties:
+- compatible: "ti,dra7-atl"
+- ti,hwmods: Name of the hwmod associated with the ATL module
+
+
+Optional properties:
+- ti,atclk<n>-freq: Output clock frequency for ATL instance n.
+ ATL instance is disabled if this property is not set
+- ti,atl<n>-bws-input: ATL baseband word select input for ATL instance n.
+ Possible inputs are:
+ 0 - McASP1 FSR
+ 1 - McASP1 FSX
+ 2 - McASP2 FSR
+ 3 - McASP2 FSX
+ 4 - McASP3 FSX
+ 5 - McASP4 FSX
+ 6 - McASP5 FSX
+ 7 - McASP6 FSX
+ 8 - McASP7 FSX
+ 9 - McASP8 FSX
+ 10 - McASP8 AHCLKX
+ 11 - XREF_CLK3 input pad
+ 12 - XREF_CLK0 input pad
+ 13 - XREF_CLK1 input pad
+ 14 - XREF_CLK2 input pad
+ 15 - OSC1_X1 input pad
+- ti,atl<n>-aws-input: Audio word select input for ATL instance n.
+ Same inputs than BWS.
+
+
+Example:
+
+atl: atl@0x4843c000 {
+ compatible = "ti,dra7-atl";
+ reg = <0x4843c000 0x3ff>;
+ ti,hwmods = "atl";
+ ti,atclk1-freq = <11289600>; /* 11.2896 MHz */
+ ti,atl1-bws-input = <2>; /* McASP2 FSR */
+ ti,atl1-aws-input = <4>; /* McASP3 FSX */
+};
diff --git a/Documentation/devicetree/bindings/sound/dra7-evm.txt b/Documentation/devicetree/bindings/sound/dra7-evm.txt
--- /dev/null
@@ -0,0 +1,60 @@
+* Texas Instruments DRA7 EVM sound
+
+Required properties:
+- compatible: "ti,dra7-evm-sound"
+- ti,mode: Name of the sound card
+- ti,media-cpu: phandle for the McASP node in media link
+- ti,media-codec: phandle for the analog codec in media link
+- ti,media-mclk-freq: MCLK frequency for the analog codec in media link
+- ti,media-slots: Number of slots
+- ti,audio-routing: List of connections between audio components.
+ Each entry is a pair of strings, the first being the connection's sink,
+ the second being the connection's source.
+
+Available audio endpoints for the audio-routing table:
+
+Board connectors:
+ * Main Mic
+ * Line In
+ * Headphone
+ * Line Out
+
+tlv320aic3x pins:
+ * LLOUT
+ * RLOUT
+ * MONO_LOUT
+ * HPLOUT
+ * HPROUT
+ * HPLCOM
+ * HPCOM
+ * MIC3L
+ * MIC3R
+ * LINE1L
+ * LINE1R
+ * LINE2L
+ * LINE2R
+
+Example:
+
+sound {
+ compatible = "ti,dra7-evm-sound";
+ ti,model = "DRA7-EVM";
+
+ /* Media DAI link */
+ ti,media-cpu = <&mcasp3>;
+ ti,media-codec = <&tlv320aic3106>;
+ ti,media-mclk-freq = <1411200>;
+ ti,media-slots = <2>;
+
+ /* Audio routing */
+ ti,audio-routing =
+ "LINE1L", "Line In",
+ "LINE1R", "Line In",
+ "MIC3L", "Main Mic",
+ "MIC3R", "Main Mic",
+ "Main Mic", "Mic Bias 2V",
+ "Headphone", "HPLOUT",
+ "Headphone", "HPROUT",
+ "Line Out", "LLOUT",
+ "Line Out", "RLOUT";
+};
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
index 7a95c651ceb3b20f82bd0940aed222cc1e3be5c6..2fd123e383bcedc4186db7837e33e71a221669a1 100644 (file)
Optional properties:
- tx-fifo-resize: determines if the FIFO *has* to be reallocated.
-
+ - dr_mode: tells Dual-Role USB controllers that we want to work on a
+ particular mode. Valid arguments are "host",
+ "peripheral" and "otg". In case this attribute isn't
+ passed via DT, USB DRD controllers should default to
+ OTG.
+- maximum-speed: tells USB controllers we want to work up to a certain
+ speed. Valid arguments are "superspeed", "highspeed",
+ "fullspeed" and "lowspeed". In case this isn't passed
+ via DT, USB controllers should default to their maximum
+ HW capability.
This is usually a subnode to DWC3 glue to which it is connected.
dwc3@4a030000 {
diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
index d4769f343d6cfbdaeb5ba16880d450e339145d6b..b5770b49c8ee02313696ec873a87b59dedf5319e 100644 (file)
usb mailbox or usb3 phy power. omap4 has usb mailbox in control module to
notify events to the musb core and omap5 has usb3 phy power register to
power on usb3 phy. Should be "1" if it has mailbox and "2" if it has usb3
- phy power.
+ phy power (usb3 phy power indicates the presense of a usb2 and usb3 phy),
+ should be "3" is it has only usb2 phy power.
omap_control_usb: omap-control-usb@4a002300 {
compatible = "ti,omap-control-usb";
index 101fed319815346ee54a96bae8f30fd0131a9ffa..a5c6e2af6ad85870281dc1ce282fd4a628cb42cc 100644 (file)
omap4-var-som.dtb \
omap4-sdp.dtb \
omap5-uevm.dtb \
- omap5-sevm.dtb \
am335x-evm.dtb \
am335x-evmsk.dtb \
am335x-bone.dtb \
regulator-max-microvolt = <3000000>;
};
+ ion_config {
+ compatible = "ti,ion-omap";
+ ti,omap_ion_heap_secure_input_base = <0xba300000>;
+ ti,omap_ion_heap_tiler_base = <0xb4300000>;
+ ti,omap_ion_heap_nonsecure_tiler_base = <0xf00000>;
+ /*90 MB*/
+ ti,omap_ion_heap_secure_input_size = <0x5A00000>;
+ /*96 MB*/
+ ti,omap_ion_heap_tiler_size = <0x6000000>;
+ /*15 MB*/
+ ti,omap_ion_heap_nonsecure_tiler_size = <0xF00000>;
+ };
+
ocp {
gpu: gpu@0x56000000 {
- gpu-supply = <&avs_gpu>;
+ gpu-supply = <&avs_gpu>;
};
};
+ vaudio_1v8: fixedregulator-vaudio-dig {
+ compatible = "regulator-fixed";
+ regulator-name = "vdac_fixed";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ vaudio_3v3: fixedregulator-vaudio-anlg {
+ compatible = "regulator-fixed";
+ regulator-name = "vdac_fixed";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ sound {
+ compatible = "ti,dra7-evm-sound";
+ ti,model = "dra7evm";
+
+ /* Audio routing */
+ ti,audio-routing =
+ "LINE1L", "Line In",
+ "LINE1R", "Line In",
+ "MIC3L", "Mic Bias 2V",
+ "MIC3R", "Mic Bias 2V",
+ "Mic Bias 2V", "Main Mic",
+ "Headphone", "HPLOUT",
+ "Headphone", "HPROUT",
+ "Line Out", "LLOUT",
+ "Line Out", "RLOUT";
+
+ /* Media DAI link */
+ ti,media-cpu = <&mcasp3>;
+ ti,media-codec = <&tlv320aic3106>;
+ ti,media-mclk-freq = <5644800>;
+ ti,media-slots = <2>;
+ };
+
+ sound_hdmi {
+ compatible = "ti,omap-hdmi-tpd12s015-audio";
+ ti,model = "OMAP5HDMI";
+ ti,hdmi_audio = <&hdmi>;
+ ti,level_shifter = <&tpd12s015>;
+ };
};
&dra7_pmx_core {
pinctrl-names = "default";
pinctrl-0 = <
+ &atl_pins
+ &mcasp3_pins
+ &mcasp6_pins
&vout1_pins
+ &usb_pins
>;
+ atl_pins: pinmux_atl_pins {
+ pinctrl-single,pins = <
+ 0x298 0x00000005 /* xref_clk1.atl_clk1 OUTPUT | MODE5 */
+ 0x29c 0x00000005 /* xref_clk2.atl_clk2 OUTPUT | MODE5 */
+ >;
+ };
+
+ mcasp3_pins: pinmux_mcasp3_pins {
+ pinctrl-single,pins = <
+ 0x324 0x00000000 /* mcasp3_aclkx.mcasp3_aclkx OUTPUT | MODE0 */
+ 0x328 0x00000000 /* mcasp3_fsx.mcasp3_fsx OUTPUT | MODE0 */
+ 0x32c 0x00000000 /* mcasp3_axr0.mcasp3_axr0 OUTPUT | MODE0 */
+ 0x330 0x00040000 /* mcasp3_axr1.mcasp3_axr1 INPUT | MODE0 */
+ >;
+ };
+
+ mcasp6_pins: pinmux_mcasp6_pins {
+ pinctrl-single,pins = <
+ 0x2d4 0x00000001 /* mcasp1_axr8.mcasp6_axr0 OUTPUT | MODE1 */
+ 0x2d8 0x00040001 /* mcasp1_axr9.mcasp6_axr1 INPUT | MODE 1 */
+ 0x2dc 0x00000001 /* mcasp1_axr10.mcasp6_clkx OUTPUT | MODE1 */
+ 0x2e0 0x00000001 /* mcasp1_axr11.mcasp6_fsx OUTPUT | MODE1 */
+ >;
+ };
+
+ usb_pins: pinmux_usb_pins {
+ pinctrl-single,pins = <
+ 0x280 0xc0000 /* DRV1_VBUS SLEW | PULLDEN | MODE0 */
+ 0x284 0xc0000 /* DRV2_VBUS SLEW | PULLDEN | MODE0 */
+ >;
+ };
+
i2c2_pins: pinmux_i2c2_pins {
pinctrl-single,pins = <
0x408 0x60000 /* i2c2_sda INPUT | MODE0 */
0x238 0x0 /* vout1_d23 OUTPUT | MODE0 */
>;
};
+ display_layout {
+ compatible = "ti, omap4-dsscomp";
+ ti,num_displays = <2>;
+ ti,default_display = "lcd";
+ };
};
&i2c1 {
reg = <0x40>;
gpios = <&pcf_lcd 15 0>; /* P15, CON_LCD_PWR_DN */
};
+
+ tlv320aic3106: tlv320aic3106@18 {
+ compatible = "ti,tlv320aic3x";
+ reg = <0x18>;
+ IOVDD-supply = <&vaudio_3v3>;
+ DVDD-supply = <&vaudio_1v8>;
+ AVDD-supply = <&vaudio_3v3>;
+ DRVDD-supply = <&vaudio_3v3>;
+ };
};
/include/ "tps659038.dtsi"
index 7f92247a03fc2b9f0ad120249bf8d2a09c5f2f94..2e9e4b546d4197b2ef24d2f96f7cde3cc3b28fbc 100644 (file)
compatible = "arm,cortex-a15";
operating-points = <
/* kHz uV */
- /* The OPP_HIGH Only for DVFS enabled Samples Hence commenting*/
+ /* The OPP_HIGH Only for DVFS enabled Samples */
1000000 1090000
- /* 1176000 1210000 */
+ 1176000 1210000
>;
- clocks = <&dpll_mpu>;
+ clocks = <&dpll_mpu_ck>;
clock-names = "cpu";
timer {
compatible = "arm,armv7-timer";
pinctrl-single,function-mask = <0x3fffffff>;
};
- dpll_mpu: dpll_mpu {
+ dpll_mpu_ck: dpll_mpu_ck {
#clock-cells = <0>;
compatible = "ti,omap-clock";
};
ti,hwmods = "wd_timer2";
};
+ omap_control_usb1: omap-control-usb@4a002300 {
+ compatible = "ti,omap-control-usb";
+ reg = <0x4a002300 0x4>,
+ <0x4a002370 0x4>;
+ reg-names = "control_dev_conf", "phy_power_usb";
+ ti,type = <2>;
+ };
+
+ omap_dwc31: omap_dwc3@48880000 {
+ compatible = "ti,dwc3";
+ ti,hwmods = "usb_otg_ss1";
+ reg = <0x48880000 0x1ff>;
+ interrupts = <0 77 4>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ utmi-mode = <2>;
+ ranges;
+ dwc3@48890000 {
+ compatible = "synopsys,dwc3";
+ reg = <0x48890000 0xcfff>;
+ interrupts = <0 76 4>;
+ usb-phy = <&usb2_phy1>, <&usb3_phy>;
+ tx-fifo-resize;
+ dr_mode = "peripheral";
+ maximum-speed = "superspeed";
+ };
+ };
+
+ omap_control_usb2: omap-control-usb@4a002e74 {
+ compatible = "ti,omap-control-usb";
+ reg = <0x4a002e74 0x4>,
+ <0x4a0086c0 0x4>;
+ reg-names = "ctrl_core_srcomp_north_side", "dummy_reg";
+ ti,type = <3>;
+ };
+
+ omap_dwc32: omap_dwc3@488c0000 {
+ compatible = "ti,dwc3";
+ ti,hwmods = "usb_otg_ss2";
+ reg = <0x488c0000 0x1ff>;
+ interrupts = <0 92 4>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ utmi-mode = <1>;
+ ranges;
+ dwc3@488d0000 {
+ compatible = "synopsys,dwc3";
+ reg = <0x488d0000 0xcfff>;
+ interrupts = <0 78 4>;
+ usb-phy = <&usb2_phy2>;
+ tx-fifo-resize;
+ dr_mode = "host";
+ maximum-speed = "highspeed";
+ };
+ };
+
+ ocp2scp {
+ compatible = "ti,omap-ocp2scp";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ ti,hwmods = "ocp2scp1";
+ usb2_phy1: usb2_phy1@4a084000 {
+ compatible = "ti,omap-usb2";
+ reg = <0x4a084000 0x7c>;
+ ctrl-module = <&omap_control_usb1>;
+ wkupclk = "usb_phy1_always_on_clk32k";
+ optclk = "usb_otg_ss1_refclk960m";
+ };
+
+ usb3_phy: usb3_phy@4a084400 {
+ compatible = "ti,omap-usb3";
+ reg = <0x4a084400 0x80>,
+ <0x4a084800 0x64>,
+ <0x4a084c00 0x40>;
+ reg-names = "phy_rx", "phy_tx", "pll_ctrl";
+ ctrl-module = <&omap_control_usb1>;
+ wkupclk = "usb_phy1_always_on_clk32k";
+ optclk = "usb_otg_ss1_refclk960m";
+ };
+
+ usb2_phy2: usb2_phy2@4a085000 {
+ compatible = "ti,omap-usb2";
+ reg = <0x4a085000 0x7c>;
+ ctrl-module = <&omap_control_usb2>;
+ wkupclk = "usb_phy2_always_on_clk32k";
+ optclk = "usb_otg_ss2_refclk960m";
+ };
+
+ };
+
+
dmm: dmm@4e000000 {
compatible = "ti,omap5-dmm";
reg = <0x4e000000 0x800>;
efuse-settings = <1090000 8
1210000 12
1280000 16>;
+ voltage-tolerance = <1>;
};
avs_core: regulator-avs@0x4A0025EC {
efuse-settings = <1090000 8
1210000 12
1280000 16>;
+ voltage-tolerance = <1>;
};
avs_dspeve: regulator-avs@0x4A0025D8 {
video-source = <1>;
};
};
+
+ atl: atl@0x4843c000 {
+ compatible = "ti,dra7-atl";
+ reg = <0x4843c000 0x3ff>;
+ ti,hwmods = "atl";
+ ti,atclk1-freq = <11289600>;
+ ti,atl1-bws-input = <3>; /* McASP2 FSX */
+ ti,atl1-aws-input = <15>; /* McASP6 FSX */
+ ti,atclk2-freq = <5644800>;
+ ti,atl2-bws-input = <3>; /* McASP2 FSX */
+ ti,atl2-aws-input = <4>; /* McASP3 FSX */
+ };
+
+ mcasp3: mcasp@48468000 {
+ compatible = "ti,dra7-mcasp-audio";
+ reg = <0x48468000 0x2000>;
+ interrupts = <0 108 0x4>, /* AREVT */
+ <0 109 0x4>; /* TXEVT */
+ ti,hwmods = "mcasp3";
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <2>;
+ num-serializer = <4>;
+ serial-dir = <1 2 0 0>; /* 0:INACTIVE, 1:TX, 2:RX */
+ ti,tx-inactive-mode = <2>; /* 0: Hi-Z, 2: Low, 3: High */
+ ti,rx-inactive-mode = <2>; /* 0: Hi-Z, 2: Low, 3: High */
+ };
+
+ mcasp6: mcasp@48474000 {
+ compatible = "ti,dra7-mcasp-audio";
+ reg = <0x48474000 0x2000>;
+ interrupts = <0 108 0x4>, /* AREVT */
+ <0 109 0x4>; /* TXEVT */
+ ti,hwmods = "mcasp6";
+ op-mode = <0>; /* MCASP_IIS_MODE */
+ tdm-slots = <8>;
+ num-serializer = <4>;
+ serial-dir = <1 2 0 0>; /* 0:INACTIVE, 1:TX, 2:RX */
+ ti,tx-inactive-mode = <2>; /* 0: Hi-Z, 2: Low, 3: High */
+ ti,rx-inactive-mode = <2>; /* 0: Hi-Z, 2: Low, 3: High */
+ };
};
};
diff --git a/arch/arm/boot/dts/omap5-sevm.dts b/arch/arm/boot/dts/omap5-sevm.dts
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-/dts-v1/;
-
-/include/ "omap5.dtsi"
-/include/ "samsung_k3pe0e000b.dtsi"
-
-/ {
- model = "TI OMAP5 sEVM board";
- compatible = "ti,omap5-sevm", "ti,omap5";
-
- cpus {
- cpu@0 {
- cpu0-supply = <&smps123_reg>;
- };
- };
-
- memory {
- device_type = "memory";
- reg = <0x80000000 0x7F000000>; /* 2032 MB */
- };
-
- vmmcsd_fixed: fixedregulator-mmcsd {
- compatible = "regulator-fixed";
- regulator-name = "vmmcsd_fixed";
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- };
-
- /* HS USB Port 2 RESET */
- hsusb2_reset: hsusb2_reset_reg {
- compatible = "regulator-fixed";
- regulator-name = "hsusb2_reset";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- gpio = <&gpio6 13 0>; /* gpio6_173 HUB_NRESET */
- startup-delay-us = <70000>;
- enable-active-high;
- };
-
- /* HS USB Host PHY on PORT 2 */
- hsusb2_phy: hsusb2_phy {
- compatible = "usb-nop-xceiv";
- reset-supply = <&hsusb2_reset>;
- };
-
- /* HS USB Port 3 RESET */
- hsusb3_reset: hsusb3_reset_reg {
- compatible = "regulator-fixed";
- regulator-name = "hsusb3_reset";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- gpio = <&gpio6 12 0>; /* gpio6_172 ETH_NRESET */
- startup-delay-us = <70000>;
- enable-active-high;
- };
-
- /* HS USB Host PHY on PORT 3 */
- hsusb3_phy: hsusb3_phy {
- compatible = "usb-nop-xceiv";
- reset-supply = <&hsusb3_reset>;
- };
-
- sound {
- compatible = "ti,abe-twl6040";
- ti,model = "OMAP5-sEVM";
-
- ti,jack-detection = <1>;
- ti,mclk-freq = <19200000>;
-
- ti,mcpdm = <&mcpdm>;
- ti,dmic = <&dmic>;
- ti,mcasp = <&mcasp>;
- ti,mcbsp1 = <&mcbsp1>;
- ti,mcbsp2 = <&mcbsp2>;
- ti,aess = <&aess>;
-
- ti,twl6040 = <&twl6040>;
-
- /* Audio routing */
- ti,audio-routing =
- "Headset Stereophone", "HSOL",
- "Headset Stereophone", "HSOR",
- "Earphone Spk", "EP",
- "Ext Spk", "HFL",
- "Ext Spk", "HFR",
- "Line Out", "AUXL",
- "Line Out", "AUXR",
- "HSMIC", "Headset Mic",
- "Headset Mic", "Headset Mic Bias",
- "MAINMIC", "Main Handset Mic",
- "Main Handset Mic", "Main Mic Bias",
- "SUBMIC", "Sub Handset Mic",
- "Sub Handset Mic", "Main Mic Bias",
- "AFML", "Line In",
- "AFMR", "Line In",
- "DMic", "Digital Mic",
- "Digital Mic", "Digital Mic1 Bias",
- "Headset Playback", "PDM_DL1",
- "Handsfree Playback", "PDM_DL2",
- "PDM_UL1", "Capture",
- "40122000.mcbsp Playback", "BT_VX_DL",
- "BT_VX_UL", "40122000.mcbsp Capture",
- "40124000.mcbsp Playback", "MM_EXT_DL",
- "MM_EXT_UL", "40124000.mcbsp Capture",
- "DMIC0", "omap-dmic-abe.0 Capture",
- "omap-dmic-abe.0 Capture", "Digital Mic1 Bias",
- "Digital Mic1 Bias", "Digital Mic 0",
- "DMIC1", "omap-dmic-abe.1 Capture",
- "omap-dmic-abe.1 Capture", "Digital Mic1 Bias",
- "Digital Mic1 Bias", "Digital Mic 1",
- "DMIC2", "omap-dmic-abe.2 Capture",
- "omap-dmic-abe.2 Capture", "Digital Mic1 Bias",
- "Digital Mic1 Bias", "Digital Mic 2";
- };
-
- sound_hdmi {
- compatible = "ti,omap-hdmi-tpd12s015-audio";
- ti,model = "OMAP5HDMI";
-
- ti,hdmi_audio = <&hdmi>;
- ti,level_shifter = <&tpd12s015>;
- };
-
-};
-
-&omap5_pmx_core {
- pinctrl-names = "default";
- pinctrl-0 = <
- &twl6040_pins
- &mcpdm_pins
- &dmic_pins
- &mcbsp1_pins
- &mcbsp2_pins
- &usbhost_pins
- &lg4591_pins
- &dss_hdmi_pins
- &tpd12s015_pins
- &tca6424a_pins
- >;
-
- mmc1_pins: pinmux_mmc1_pins {
- pinctrl-single,pins = <
- 0x1a2 0x118 /* sdcard_clk.sdcard_clk INPUT PULLUP | MODE0 */
- 0x1a4 0x118 /* sdcard_cmd.sdcard_cmd INPUT PULLUP | MODE0 */
- 0x1a6 0x118 /* sdcard_data2.sdcard_data2 INPUT PULLUP | MODE0 */
- 0x1a8 0x118 /* sdcard_data3.sdcard_data3 INPUT PULLUP | MODE0 */
- 0x1aa 0x118 /* sdcard_data0.sdcard_data0 INPUT PULLUP | MODE0 */
- 0x1ac 0x118 /* sdcard_data1.sdcard_data1 INPUT PULLUP | MODE0 */
- >;
- };
-
- mmc2_pins: pinmux_mmc2_pins {
- pinctrl-single,pins = <
- 0x0 0x118 /* emmc_clk.emmc_clk INPUT PULLUP | MODE0 */
- 0x2 0x118 /* emmc_cmd.emmc_cmd INPUT PULLUP | MODE0 */
- 0x4 0x118 /* emmc_data0.emmc_data0 INPUT PULLUP | MODE0 */
- 0x6 0x118 /* emmc_data1.emmc_data1 INPUT PULLUP | MODE0 */
- 0x8 0x118 /* emmc_data2.emmc_data2 INPUT PULLUP | MODE0 */
- 0xa 0x118 /* emmc_data3.emmc_data3 INPUT PULLUP | MODE0 */
- 0xc 0x118 /* emmc_data4.emmc_data4 INPUT PULLUP | MODE0 */
- 0xe 0x118 /* emmc_data5.emmc_data5 INPUT PULLUP | MODE0 */
- 0x10 0x118 /* emmc_data6.emmc_data6 INPUT PULLUP | MODE0 */
- 0x12 0x118 /* emmc_data7.emmc_data7 INPUT PULLUP | MODE0 */
- >;
- };
-
- twl6040_pins: pinmux_twl6040_pins {
- pinctrl-single,pins = <
- 0x18a 0x6 /* perslimbus2_clock.gpio5_145 OUTPUT | MODE6 */
- >;
- };
-
- mcpdm_pins: pinmux_mcpdm_pins {
- pinctrl-single,pins = <
- 0x142 0x108 /* abe_clks.abe_clks INPUT PULLDOWN | MODE0 */
- 0x15c 0x108 /* abemcpdm_ul_data.abemcpdm_ul_data INPUT PULLDOWN | MODE0 */
- 0x15e 0x108 /* abemcpdm_dl_data.abemcpdm_dl_data INPUT PULLDOWN | MODE0 */
- 0x160 0x118 /* abemcpdm_frame.abemcpdm_frame INPUT PULLUP | MODE0 */
- 0x162 0x108 /* abemcpdm_lb_clk.abemcpdm_lb_clk INPUT PULLDOWN | MODE0 */
- >;
- };
-
- dmic_pins: pinmux_dmic_pins {
- pinctrl-single,pins = <
- 0x144 0x100 /* abedmic_din1.abedmic_din1 INPUT | MODE0 */
- 0x146 0x100 /* abedmic_din2.abedmic_din2 INPUT | MODE0 */
- 0x148 0x100 /* abedmic_din3.abedmic_din3 INPUT | MODE0 */
- 0x14a 0 /* abedmic_clk1.abedmic_clk1 OUTPUT | MODE0 */
- >;
- };
-
- mcbsp1_pins: pinmux_mcbsp1_pins {
- pinctrl-single,pins = <
- 0x14c 0x101 /* abedmic_clk2.abemcbsp1_fsx INPUT | MODE1 */
- 0x14e 0x9 /* abedmic_clk3.abemcbsp1_dx OUTPUT PULLDOWN | MODE1 */
- 0x150 0x101 /* abeslimbus1_clock.abemcbsp1_clkx INPUT | MODE0 */
- 0x152 0x109 /* abeslimbus1_data.abemcbsp1_dr INPUT PULLDOWN | MODE1 */
- >;
- };
-
- mcbsp2_pins: pinmux_mcbsp2_pins {
- pinctrl-single,pins = <
- 0x154 0x108 /* abemcbsp2_dr.abemcbsp2_dr INPUT PULLDOWN | MODE0 */
- 0x156 0x8 /* abemcbsp2_dx.abemcbsp2_dx OUTPUT PULLDOWN | MODE0 */
- 0x158 0x100 /* abemcbsp2_fsx.abemcbsp2_fsx INPUT | MODE0 */
- 0x15a 0x100 /* abemcbsp2_clkx.abemcbsp2_clkx INPUT | MODE0 */
- >;
- };
-
- usbhost_pins: pinmux_usbhost_pins {
- pinctrl-single,pins = <
- 0x84 0x100 /* usbb2_hsic_strobe INPUT | MODE 0 */
- 0x86 0x100 /* usbb2_hsic_data INPUT | MODE 0 */
-
- 0x19e 0x100 /* usbb3_hsic_strobe INPUT | MODE 0 */
- 0x1a0 0x100 /* usbb3_hsic_data INPUT | MODE 0 */
-
- 0xD4 0x6 /* gpio6_173 OUTPUT | MODE 6 HUB_NRESET */
- 0xD6 0x6 /* gpio6_172 OUTPUT | MODE 6 ETH_NRESET */
- >;
- };
-
- i2c1_pins: pinmux_i2c1_pins {
- pinctrl-single,pins = <
- 0x1b2 0x118 /* i2c1_scl PULLUP | INPUTENABLE | MODE0 */
- 0x1b4 0x118 /* i2c1_sda PULLUP | INPUTENABLE | MODE0 */
- >;
- };
-
- i2c2_pins: pinmux_i2c2_pins {
- pinctrl-single,pins = <
- 0x178 0x100 /* i2c2_scl INPUTENABLE | MODE0 */
- 0x17a 0x100 /* i2c2_sda INPUTENABLE | MODE0 */
- >;
- };
-
- i2c3_pins: pinmux_i2c3_pins {
- pinctrl-single,pins = <
- 0x13a 0x100 /* i2c3_scl INPUTENABLE | MODE0 */
- 0x13c 0x100 /* i2c3_sda INPUTENABLE | MODE0 */
- >;
- };
-
- i2c4_pins: pinmux_i2c4_pins {
- pinctrl-single,pins = <
- 0xb8 0x100 /* i2c4_scl INPUTENABLE | MODE0 */
- 0xba 0x100 /* i2c4_sda INPUTENABLE | MODE0 */
- >;
- };
-
- i2c5_pins: pinmux_i2c5_pins {
- pinctrl-single,pins = <
- 0x184 0x100 /* i2c5_scl INPUTENABLE | MODE0 */
- 0x186 0x100 /* i2c5_sda INPUTENABLE | MODE0 */
- >;
- };
-
- mcspi2_pins: pinmux_mcspi2_pins {
- pinctrl-single,pins = <
- 0xbc 0x100 /* MCSPI2_CLK INPUTENABLE | MODE0 */
- 0xbe 0x100 /* MCSPI2_SIMO INPUTENABLE | MODE0 */
- 0xc0 0x118 /* MCSPI2_SOMI PULLUP | INPUTENABLE | MODE0*/
- 0xc2 0x0 /* MCSPI2_CS MODE0*/
- >;
- };
-
- mcspi3_pins: pinmux_mcspi3_pins {
- pinctrl-single,pins = <
- 0x78 0x101 /* MCSPI2_SOMI INPUTENABLE | MODE1 */
- 0x7a 0x101 /* MCSPI2_CS INPUTENABLE | MODE1 */
- 0x7c 0x101 /* MCSPI2_SIMO INPUTENABLE | MODE1 */
- 0x7e 0x101 /* MCSPI2_CLK INPUTENABLE | MODE1 */
- >;
- };
-
- mcspi4_pins: pinmux_mcspi4_pins {
- pinctrl-single,pins = <
- 0x164 0x101 /* MCSPI2_CLK INPUTENABLE | MODE1 */
- 0x168 0x101 /* MCSPI2_SIMO INPUTENABLE | MODE1 */
- 0x16a 0x101 /* MCSPI2_SOMI INPUTENABLE | MODE1 */
- 0x16c 0x101 /* MCSPI2_CS INPUTENABLE | MODE1 */
- >;
- };
-
- lg4591_pins: pinmux_lg4591_pins {
- pinctrl-single,pins = <
- 0xf2 0x8 /* perslimbus2_clock.gpio6_183 OUTPUT PULLDOWN | MODE0 */
- >;
- };
-
- dss_hdmi_pins: pinmux_dss_hdmi_pins {
- pinctrl-single,pins = <
- 0x0fc 0x118 /* hdmi_cec.hdmi_cec INPUT PULLUP | MODE 0 */
- 0x100 0x118 /* hdmi_scl.hdmi_scl INPUT PULLUP | MODE 0 */
- 0x102 0x118 /* hdmi_sda.hdmi_sda INPUT PULLUP | MODE 0 */
- >;
- };
-
- tpd12s015_pins: pinmux_tpd12s015_pins {
- pinctrl-single,pins = <
- 0x0fe 0x116 /* hdmi_hpd.gpio7_193 INPUT PULLDOWN | MODE6 */
- >;
- };
-
- tca6424a_pins: pinmux_tca6424a_pins {
- pinctrl-single,pins = <
- 0x186 0x100 /* i2c5_scl.i2c5_scl INPUT | MODE0 */
- 0x188 0x100 /* i2c5_sda.i2c5_sda INPUT | MODE0 */
- >;
- };
-
-};
-
-&mmc1 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc1_pins>;
- vmmc-supply = <&vmmcsd_fixed>;
- vmmc-aux-supply = <&ldo9_reg>;
- bus-width = <4>;
- cd-gpios = <&gpio3 3 0>; /* gpio 67 */
-};
-
-&mmc2 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc2_pins>;
- vmmc-supply = <&vmmcsd_fixed>;
- vmmc-aux-supply = <&ldo9_reg>;
- bus-width = <8>;
- ti,non-removable;
-};
-
-&mmc3 {
- bus-width = <4>;
- ti,non-removable;
- status = "disabled";
-};
-
-&mmc4 {
- status = "disabled";
-};
-
-&mmc5 {
- status = "disabled";
-};
-
-&i2c1 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c1_pins>;
-
- clock-frequency = <400000>;
-};
-
-&i2c2 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c2_pins>;
-
- clock-frequency = <400000>;
-
- /* Pressure Sensor */
- bmp085@77 {
- compatible = "bosch,bmp085";
- reg = <0x77>;
- };
-};
-
-&i2c3 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c3_pins>;
-
- clock-frequency = <400000>;
-};
-
-&i2c4 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c4_pins>;
-
- clock-frequency = <400000>;
-
- /* Temperature Sensor */
- tmp102@48{
- compatible = "ti,tmp102";
- reg = <0x48>;
- };
-};
-
-&i2c5 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c5_pins>;
- clock-frequency = <400000>;
-
- tca6424a: tca6424a@22 {
- compatible = "ti,tca6424a";
- reg = <0x22>;
- gpio-controller;
- #gpio-cells = <2>;
- };
-};
-
-&keypad {
- keypad,num-rows = <8>;
- keypad,num-columns = <8>;
- linux,keymap = <0x02020073 /* VOLUP */
- 0x02030072 /* VOLDOWM */
- 0x020400e7 /* SEND */
- 0x02050066 /* HOME */
- 0x0206006b /* END */
- 0x020700d9>; /* SEARCH */
- linux,input-no-autorepeat;
-};
-
-&mcbsp3 {
- status = "disabled";
-};
-
-&emif1 {
- cs1-used;
- device-handle = <&samsung_K3PE0E000B>;
-};
-
-&emif2 {
- cs1-used;
- device-handle = <&samsung_K3PE0E000B>;
-};
-
-&usbhshost {
- port2-mode = "ehci-hsic";
- port3-mode = "ehci-hsic";
-};
-
-&usbhsehci {
- phys = <0 &hsusb2_phy &hsusb3_phy>;
-};
-
-&i2c1 {
- clock-frequency = <400000>;
-
- palmas: palmas@48 {
- reg = <0x48>;
- /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
- interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */
- interrupt-parent = <&gic>;
- };
-
- twl6040: twl@4b {
- compatible = "ti,twl6040";
-
- interrupts = <0 119 4>; /* IRQ_SYS_2N cascaded to gic */
- interrupt-parent = <&gic>;
- ti,audpwron-gpio = <&gpio5 17 0>; /* gpio line 145 */
-
- vio-supply = <&smps7_reg>;
- v2v1-supply = <&smps9_reg>;
- enable-active-high;
- };
-};
-
-/include/ "palmas.dtsi"
-
-&mcspi1 {
-
-};
-
-&mcspi2 {
- pinctrl-names = "default";
- pinctrl-0 = <&mcspi2_pins>;
-};
-
-&mcspi3 {
- pinctrl-names = "default";
- pinctrl-0 = <&mcspi3_pins>;
-};
-
-&mcspi4 {
- pinctrl-names = "default";
- pinctrl-0 = <&mcspi4_pins>;
-};
-
-/include/ "twl6040.dtsi"
-
-&dsi1 {
- lcd {
- compatible = "ti,lg4591";
-
- lanes = <
- 0 /* clk + */
- 1 /* clk - */
- 2 /* data1 + */
- 3 /* data1 - */
- 4 /* data2 + */
- 5 /* data2 - */
- 6 /* data3 + */
- 7 /* data3 - */
- 8 /* data4 + */
- 9 /* data4 - */
- >;
-
- vdds_foo-supply = <&ldo2_reg>;
-
- gpios = <&gpio6 23 0>; /* 183, reset */
- };
-};
-
-&hdmi {
- tpd12s015: tpd12s015 {
- compatible = "ti,tpd12s015";
-
- gpios = <&tca6424a 0 0>, /* TCA6424A P01, CT_CP_HDP */
- <&tca6424a 1 0>, /* TCA6424A P00, LS_OE*/
- <&gpio7 1 0>; /* 193, HPD */
-
- hdmi-monitor {
- compatible = "ti,hdmi_panel";
- };
-
- };
-};
index 7b7b5347ef15df576b93d0c27864171bd8ca1a81..a339f321c2a220e970dd6b6a8b5c8ac1caad6f43 100644 (file)
*/
/dts-v1/;
+/*
+ * Following are the carveout addresses and the sizes. SMC is not reserved for now
+ * C0000000 - SDRAM+1G
+ * BFD00000 - SMC (3MB)
+ * BA300000 - ION (90MB)
+ * B4300000 - TILER SECURE (96 MB)
+ * B3400000 - TILER NONSECURE (15 MB)
+*/
+/memreserve/ 0xba300000 0x5a00000;
+/memreserve/ 0xb4300000 0x6000000;
+/memreserve/ 0xb3400000 0xf00000;
+
/include/ "omap5.dtsi"
/include/ "samsung_k3pe0e000b.dtsi"
+
/ {
model = "TI OMAP5 uEVM board";
compatible = "ti,omap5-uevm", "ti,omap5";
clock-frequency = <19200000>; /* 19.2 MHz */
};
+ ion_config {
+ compatible = "ti,ion-omap";
+ ti,omap_ion_heap_secure_input_base = <0xba300000>;
+ ti,omap_ion_heap_tiler_base = <0xb4300000>;
+ ti,omap_ion_heap_nonsecure_tiler_base = <0xf00000>;
+ /*90 MB*/
+ ti,omap_ion_heap_secure_input_size = <0x5A00000>;
+ /*96 MB*/
+ ti,omap_ion_heap_tiler_size = <0x6000000>;
+ /*15 MB*/
+ ti,omap_ion_heap_nonsecure_tiler_size = <0xF00000>;
+ };
+
sound {
compatible = "ti,abe-twl6040";
ti,model = "PandaBoard5";
index 3f1846ae98a6827208e9bf7b60db6f0dff05187f..2d91a16310aa0ea516a23154b46989ec0ce4f0dd 100644 (file)
1000000 1060000
1500000 1250000
>;
- clocks = <&dpll_mpu>;
+ clocks = <&dpll_mpu_ck>;
clock-names = "cpu";
clock-latency = <300000>; /* From omap-cpufreq driver */
};
ti,hwmods = "counter_32k";
};
- dpll_mpu: dpll_mpu {
+ dpll_mpu_ck: dpll_mpu_ck {
#clock-cells = <0>;
compatible = "ti,omap-clock";
};
compatible = "ti,omap-usb2";
reg = <0x4a084000 0x7c>;
ctrl-module = <&omap_control_usb>;
+ wkupclk = "usb_phy_cm_clk32k";
+ optclk = "usb_otg_ss_refclk960m";
+
};
usb3_phy: usb3phy@4a084400 {
<0x4a084c00 0x40>;
reg-names = "phy_rx", "phy_tx", "pll_ctrl";
ctrl-module = <&omap_control_usb>;
+ wkupclk = "usb_phy_cm_clk32k";
+ optclk = "usb_otg_ss_refclk960m";
};
};
index e952fa9429bcb4792cb5850b8b31c9ff0b10e167..dfda962415567d25d0d38a0ea2ec19d56b43ec0f 100644 (file)
# CONFIG_BLK_DEV_BSG is not set
CONFIG_PARTITION_ADVANCED=y
CONFIG_ARCH_OMAP=y
+CONFIG_ARCH_OMAP2PLUS=y
CONFIG_OMAP_RESET_CLOCKS=y
CONFIG_OMAP_MUX_DEBUG=y
CONFIG_SOC_OMAP5=y
CONFIG_ARM_ERRATA_411920=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO0,115200 init=/init androidboot.console=ttyO0 early_printk"
+CONFIG_CMDLINE="root=/dev/mmcblk0p2 rw rootwait console=ttyO0,115200 androidboot.console=ttyO0 vmalloc=496M init=/init omapfb.fb_opt=-1,-1,-1,1,1280,720 cma=64M no_console_suspend"
CONFIG_CMDLINE_FORCE=y
CONFIG_KEXEC=y
CONFIG_CPU_FREQ=y
CONFIG_REGULATOR_TPS6507X=y
CONFIG_REGULATOR_TPS65217=y
CONFIG_REGULATOR_TPS65910=y
+CONFIG_REGULATOR_TIAVSCLASS0=y
CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_VIDEO_DEV=m
CONFIG_USB_VIDEO_CLASS=m
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
CONFIG_USB_GSPCA=m
-CONFIG_DRM=y
-CONFIG_DRM_OMAP=y
CONFIG_DRM_OMAP_NUM_CRTCS=3
CONFIG_FIRMWARE_EDID=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
+CONFIG_DSSCOMP=y
+CONFIG_DSSCOMP_DEBUG_LOG=y
CONFIG_OMAP2_DSS=y
CONFIG_OMAP2_DSS_DRA7XX_DPI=y
CONFIG_OMAP2_DSS_RFBI=y
CONFIG_OMAP2_DSS_SDI=y
CONFIG_OMAP2_DSS_DSI=y
+CONFIG_FB_OMAP2=y
+CONFIG_OMAPLFB=y
CONFIG_PANEL_GENERIC_DPI=y
CONFIG_PANEL_TFP410=y
CONFIG_PANEL_LGPHILIPS_LB035Q02=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_PLATFORM=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
CONFIG_LOGO=y
-CONFIG_SOUND=m
-CONFIG_SND=m
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_COMPRESS_OFFLOAD=y
CONFIG_SND_DEBUG=y
CONFIG_SND_USB_AUDIO=m
-CONFIG_SND_SOC=m
-CONFIG_SND_OMAP_SOC=m
+CONFIG_SND_SOC=y
+CONFIG_SND_DAVINCI_SOC_MCASP=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_HDMI=y
CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m
CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m
+CONFIG_SND_OMAP_SOC_OMAP_HDMI=y
CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
+CONFIG_SND_DRA7_SOC_ATL=y
+CONFIG_SND_SOC_DRA7_EVM=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+CONFIG_SND_SOC_OMAP_HDMI_CODEC=y
+CONFIG_SND_SOC_TLV320AIC3X=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_SUSPEND=y
CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_DWC3=m
-CONFIG_USB_DWC3_DEBUG=y
-CONFIG_USB_DWC3_VERBOSE=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_DWC3=y
CONFIG_USB_MUSB_HDRC=m
CONFIG_USB_MUSB_OMAP2PLUS=m
CONFIG_USB_MUSB_AM35X=m
CONFIG_USB_STORAGE=y
CONFIG_USB_TEST=y
CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DEBUG=y
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_MASS_STORAGE=m
-CONFIG_USB_G_MULTI=m
-CONFIG_USB_G_MULTI_CDC=y
-CONFIG_USB_ETH=m
-CONFIG_USB_ETH_EEM=y
-CONFIG_OMAP_USB2=m
-CONFIG_OMAP_USB3=m
+CONFIG_OMAP_USB2=y
+CONFIG_OMAP_USB3=y
CONFIG_OMAP_CONTROL_USB=y
CONFIG_TWL4030_USB=m
CONFIG_TWL6030_USB=m
CONFIG_NOP_USB_XCEIV=y
-CONFIG_PALMAS_USB=m
+CONFIG_PALMAS_USB=y
CONFIG_MMC=y
CONFIG_MMC_UNSAFE_RESUME=y
CONFIG_SDIO_UART=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PALMAS=y
CONFIG_RTC_DRV_TWL92330=y
CONFIG_TI_EDMA=y
CONFIG_DMA_OMAP=y
CONFIG_STAGING=y
+CONFIG_FB=y
+CONFIG_DRM=y
+CONFIG_DRM_OMAP=y
+CONFIG_DRM_OMAP_DISPLAY=n
+CONFIG_DRM_OMAP_DMM_TILER=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ASHMEM=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y
CONFIG_ANDROID_INTF_ALARM_DEV=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB_LIBCOMPOSITE=y
CONFIG_TI_SOC_THERMAL=y
CONFIG_TI_THERMAL=y
CONFIG_OMAP4_THERMAL=y
CONFIG_EXT4_FS=y
CONFIG_QUOTA=y
CONFIG_QFMT_V2=y
+CONFIG_FUSE_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_PROVE_LOCKING=y
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_LL=y
-CONFIG_DEBUG_LL_UART_NONE=y
-CONFIG_EARLY_PRINTK=y
CONFIG_SECURITY=y
CONFIG_CRYPTO_MICHAEL_MIC=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRC_ITU_T=y
CONFIG_CRC7=y
CONFIG_LIBCRC32C=y
+CONFIG_ION=y
+CONFIG_ION_OMAP=y
+CONFIG_CMA=y
CONFIG_TI_DAVINCI_MDIO=y
CONFIG_TI_DAVINCI_CPDMA=y
+CONFIG_PM_WAKELOCKS=y
index e3514f7e7c0fc12bd941f7cd90e239015ed32855..3ef11817cf1c93f978b18badefc1cbbb55866e0a 100644 (file)
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
CONFIG_LOGO=y
-CONFIG_SOUND=m
-CONFIG_SND=m
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_COMPRESS_OFFLOAD=y
CONFIG_SND_DEBUG=y
CONFIG_SND_USB_AUDIO=m
-CONFIG_SND_SOC=m
-CONFIG_SND_OMAP_SOC=m
+CONFIG_SND_SOC=y
+CONFIG_SND_DAVINCI_SOC_MCASP=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_HDMI=y
CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m
CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m
+CONFIG_SND_OMAP_SOC_OMAP_HDMI=y
CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
+CONFIG_SND_DRA7_SOC_ATL=y
+CONFIG_SND_SOC_DRA7_EVM=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+CONFIG_SND_SOC_OMAP_HDMI_CODEC=y
+CONFIG_SND_SOC_TLV320AIC3X=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_SUSPEND=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_DWC3=m
-CONFIG_USB_DWC3_DEBUG=y
-CONFIG_USB_DWC3_VERBOSE=y
CONFIG_USB_MUSB_HDRC=m
CONFIG_USB_MUSB_OMAP2PLUS=m
CONFIG_USB_MUSB_AM35X=m
CONFIG_USB_STORAGE=y
CONFIG_USB_TEST=y
CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DEBUG=y
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
CONFIG_USB_ZERO=m
index eca7a77df802bc33cd90ffb19a3ad42ba9c1419e..8af6b54ab66d39730e384f653750f2ab4dee9dac 100644 (file)
NULL,
};
-DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)")
+DT_MACHINE_START(OMAP5_DT, "OMAP5 Panda board")
.reserve = omap_reserve,
.smp = smp_ops(omap4_smp_ops),
.map_io = omap5_map_io,
index 4a17f12caa91336280922b34afdecd5b07046b76..4228e2ba37ad65379d4781cafea5e7738aca6be0 100644 (file)
"dpll_core_h14x2_ck", "dpll_per_h14x2_ck",
};
-DEFINE_CLK_MUX(gpu_core_gclk_mux, gpu_core_gclk_mux_parents, NULL, 0x0,
- OMAP54XX_CM_GPU_GPU_CLKCTRL, OMAP54XX_CLKSEL_GPU_CORE_GCLK_SHIFT,
+DEFINE_CLK_MUX(gpu_core_gclk_mux, gpu_core_gclk_mux_parents, NULL,
+ CLK_SET_RATE_PARENT, OMAP54XX_CM_GPU_GPU_CLKCTRL,
+ OMAP54XX_CLKSEL_GPU_CORE_GCLK_SHIFT,
OMAP54XX_CLKSEL_GPU_CORE_GCLK_WIDTH, 0x0, NULL);
-DEFINE_CLK_MUX(gpu_hyd_gclk_mux, gpu_core_gclk_mux_parents, NULL, 0x0,
- OMAP54XX_CM_GPU_GPU_CLKCTRL, OMAP54XX_CLKSEL_GPU_HYD_GCLK_SHIFT,
+DEFINE_CLK_MUX(gpu_hyd_gclk_mux, gpu_core_gclk_mux_parents, NULL,
+ CLK_SET_RATE_PARENT, OMAP54XX_CM_GPU_GPU_CLKCTRL,
+ OMAP54XX_CLKSEL_GPU_HYD_GCLK_SHIFT,
OMAP54XX_CLKSEL_GPU_HYD_GCLK_WIDTH, 0x0, NULL);
DEFINE_CLK_DIVIDER(hsi_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck, 0x0,
index e77d58771c7c45a15f104887ba6df2358fabfe15..70bbe2c77605d71ef7f40c42693b658c5087ee2a 100644 (file)
#include "prm-regbits-7xx.h"
#include "control.h"
-#define DRA7_DPLL_ABE_DEFFREQ 361267200
+#define DRA7_DPLL_ABE_DEFFREQ 180633600
#define DRA7_DPLL_GMAC_DEFFREQ 1000000000
+#define DRA7_DPLL_USB_DEFFREQ 960000000
/* Root clocks */
DEFINE_CLK_FIXED_RATE(atl_clkin2_ck, CLK_IS_ROOT, 0, 0x0);
-DEFINE_CLK_FIXED_RATE(atlclkin3_ck, CLK_IS_ROOT, 0, 0x0);
+DEFINE_CLK_FIXED_RATE(atl_clkin3_ck, CLK_IS_ROOT, 0, 0x0);
DEFINE_CLK_FIXED_RATE(hdmi_clkin_ck, CLK_IS_ROOT, 0, 0x0);
DEFINE_STRUCT_CLK(hdmi_div_clk, hdmi_dclk_div_parents, apll_pcie_clkvcoldo_ops);
DEFINE_CLK_MUX(hdmi_dpll_clk_mux, abe_dpll_sys_clk_mux_parents, NULL, 0x0,
- DRA7XX_CM_CLKSEL_HDMI_CLK_CLKOUTMUX, DRA7XX_CLKSEL_SHIFT,
+ DRA7XX_CM_CLKSEL_HDMI_PLL_SYS, DRA7XX_CLKSEL_SHIFT,
DRA7XX_CLKSEL_WIDTH, 0x0, NULL);
static struct clk l3_iclk_div;
"dpll_core_h14x2_ck", "dpll_per_h14x2_ck", "dpll_gpu_m2_ck",
};
-DEFINE_CLK_MUX(gpu_core_gclk_mux, gpu_core_gclk_mux_parents, NULL, 0x0,
- DRA7XX_CM_GPU_GPU_CLKCTRL, DRA7XX_CLKSEL_CORE_CLK_SHIFT,
- DRA7XX_CLKSEL_CORE_CLK_WIDTH, 0x0, NULL);
+DEFINE_CLK_MUX(gpu_core_gclk_mux, gpu_core_gclk_mux_parents, NULL,
+ CLK_SET_RATE_PARENT, DRA7XX_CM_GPU_GPU_CLKCTRL,
+ DRA7XX_CLKSEL_CORE_CLK_SHIFT, DRA7XX_CLKSEL_CORE_CLK_WIDTH,
+ 0x0, NULL);
-DEFINE_CLK_MUX(gpu_hyd_gclk_mux, gpu_core_gclk_mux_parents, NULL, 0x0,
- DRA7XX_CM_GPU_GPU_CLKCTRL, DRA7XX_CLKSEL_HYD_CLK_SHIFT,
- DRA7XX_CLKSEL_HYD_CLK_WIDTH, 0x0, NULL);
+DEFINE_CLK_MUX(gpu_hyd_gclk_mux, gpu_core_gclk_mux_parents, NULL,
+ CLK_SET_RATE_PARENT, DRA7XX_CM_GPU_GPU_CLKCTRL,
+ DRA7XX_CLKSEL_HYD_CLK_SHIFT, DRA7XX_CLKSEL_HYD_CLK_WIDTH,
+ 0x0, NULL);
static const char *ipu1_gfclk_mux_parents[] = {
"dpll_abe_m2x2_ck", "dpll_core_h22x2_ck",
static const char *mcasp1_ahclkr_mux_parents[] = {
"abe_24m_fclk", "abe_sys_clk_div", "func_24m_clk",
- "atlclkin3", "atl_clkin2", "atl_clkin1",
- "atl_clkin0", "sys_clkin2", "ref_clkin0",
- "ref_clkin1", "ref_clkin2", "ref_clkin3",
+ "atl_clkin3_ck", "atl_clkin2_ck", "atl_clkin1_ck",
+ "atl_clkin0_ck", "sys_clkin2", "ref_clkin0_ck",
+ "ref_clkin1_ck", "ref_clkin2_ck", "ref_clkin3_ck",
"mlb_clk", "mlbp_clk",
};
static const char *timer10_gfclk_mux_parents[] = {
"timer_sys_clk_div", "sys_32k_ck", "sys_clkin2",
- "ref_clkin0", "ref_clkin1", "ref_clkin2",
- "ref_clkin3", "abe_giclk_div", "video1_div_clk",
+ "ref_clkin0_ck", "ref_clkin1_ck", "ref_clkin2_ck",
+ "ref_clkin3_ck", "abe_giclk_div", "video1_div_clk",
"video2_div_clk", "hdmi_div_clk",
};
static const char *timer5_gfclk_mux_parents[] = {
"timer_sys_clk_div", "sys_32k_ck", "sys_clkin2",
- "ref_clkin0", "ref_clkin1", "ref_clkin2",
- "ref_clkin3", "abe_giclk_div", "video1_div_clk",
+ "ref_clkin0_ck", "ref_clkin1_ck", "ref_clkin2_ck",
+ "ref_clkin3_ck", "abe_giclk_div", "video1_div_clk",
"video2_div_clk", "hdmi_div_clk", "clkoutmux0_clk_mux",
};
CLK(NULL, "atl_clkin0_ck", &atl_clkin0_ck, CK_7XX),
CLK(NULL, "atl_clkin1_ck", &atl_clkin1_ck, CK_7XX),
CLK(NULL, "atl_clkin2_ck", &atl_clkin2_ck, CK_7XX),
- CLK(NULL, "atlclkin3_ck", &atlclkin3_ck, CK_7XX),
+ CLK(NULL, "atl_clkin3_ck", &atl_clkin3_ck, CK_7XX),
CLK(NULL, "hdmi_clkin_ck", &hdmi_clkin_ck, CK_7XX),
CLK(NULL, "mlb_clkin_ck", &mlb_clkin_ck, CK_7XX),
CLK(NULL, "mlbp_clkin_ck", &mlbp_clkin_ck, CK_7XX),
static struct rate_init_clks rate_clks[] = {
{ .name = "dpll_abe_ck", .rate = DRA7_DPLL_ABE_DEFFREQ },
+ { .name = "dpll_abe_m2x2_ck", .rate = DRA7_DPLL_ABE_DEFFREQ * 2 },
{ .name = "dpll_gmac_ck", .rate = DRA7_DPLL_GMAC_DEFFREQ },
+ { .name = "dpll_usb_ck", .rate = DRA7_DPLL_USB_DEFFREQ },
};
int __init dra7xx_clk_init(void)
index 2d4f9c02dccf29cae8b5e322f046fed2ca252cb4..a8f1557a225cb0a10c2db77d1f898f06cbad2c65 100644 (file)
#include <linux/platform_data/omap_ocp2scp.h>
#include <linux/usb/omap_control_usb.h>
#include <linux/platform_data/mailbox-omap.h>
+#include <linux/platform_data/omap_gcx.h>
+#include "omap-pm.h"
#include <asm/mach-types.h>
#include <asm/mach/map.h>
static inline void omap_init_dmic(void) {}
#endif
+static int gcxxx_scale_dev(struct device *dev, unsigned long val);
+static int gcxxx_set_l3_bw(struct device *dev, unsigned long val);
+
+static struct omap_gcx_platform_data omap_gcxxx = {
+ .get_context_loss_count = omap_pm_get_dev_context_loss_count,
+ .scale_dev = gcxxx_scale_dev,
+ .set_bw = gcxxx_set_l3_bw,
+};
+
+struct omap_device_pm_latency omap_gcxxx_latency[] = {
+ {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ }
+};
+
+static int gcxxx_scale_dev(struct device *dev, unsigned long val)
+{
+ /*omap_device_scale(dev, val) is not supported, returning with no-op
+ * for now. */
+ return 0;
+}
+
+static int gcxxx_set_l3_bw(struct device *dev, unsigned long val)
+{
+ return omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, val);
+}
+
+int __init gcxxx_init(void)
+{
+ int retval = 0;
+ struct omap_hwmod *oh;
+ struct platform_device *pdev;
+ /*struct omap_device *od;
+ struct device *dev;*/
+ const char *oh_name = "bb2d";
+ const char *dev_name = "gccore";
+
+ /*
+ * Hwmod lookup will fail in case our platform doesn't support the
+ * hardware spinlock module, so it is safe to run this initcall
+ * on all omaps
+ */
+ oh = omap_hwmod_lookup(oh_name);
+ if (oh == NULL)
+ return -EINVAL;
+
+ omap_gcxxx.regbase = omap_hwmod_get_mpu_rt_va(oh);
+ omap_gcxxx.is_hw_present = (soc_is_omap543x()
+ || soc_is_dra7xx()) ? true : false;
+ pdev = omap_device_build(dev_name, 0, oh, &omap_gcxxx,
+ sizeof(omap_gcxxx), omap_gcxxx_latency,
+ ARRAY_SIZE(omap_gcxxx_latency), false);
+ if (IS_ERR(pdev)) {
+ pr_err("Can't build omap_device for %s:%s\n", dev_name,
+ oh_name);
+ retval = PTR_ERR(pdev);
+ }
+
+ return retval;
+}
+
+
#if defined(CONFIG_SND_OMAP_SOC_ABE) || \
defined(CONFIG_SND_OMAP_SOC_ABE_MODULE)
omap_init_audio();
omap_init_camera();
omap_init_mbox();
+ gcxxx_init();
/* If dtb is there, the devices will be created dynamically */
if (!of_have_populated_dt()) {
omap_init_control_usb();
index 502196efd57f48ac48b0f692319ec5a00b4b822e..fe0dd68f40f89fe917d7ff0fab99350010ff51ea 100644 (file)
struct omap_hwmod *oh;
int r = 0;
- /* create DRM and DMM device */
- if (omap_drm_device != NULL) {
if (!of_find_compatible_node(NULL, NULL, "ti,omap4-dmm") &&
!of_find_compatible_node(NULL, NULL, "ti,omap5-dmm")) {
oh->name);
}
+ /* create DRM and DMM device */
+ if (omap_drm_device != NULL) {
+
platform_drm_data.omaprev = GET_OMAP_TYPE;
r = platform_device_register(omap_drm_device);
return -ENODEV;
}
+ /* create DMM and DRM device */
+ r = omapdrm_init();
+ if (r < 0) {
+ pr_err("Unable to register omapdrm/dmm device\n");
+ return r;
+ }
+
board_data->version = ver;
board_data->dsi_enable_pads = omap_dsi_enable_pads;
board_data->dsi_disable_pads = omap_dsi_disable_pads;
}
- /* create DMM and DRM device */
- r = omapdrm_init();
- if (r < 0) {
- pr_err("Unable to register omapdrm device\n");
- return r;
- }
-
return 0;
}
return -ENODEV;
}
+ /* create omapdrm devices */
+ r = omapdrm_init();
+ if (r < 0) {
+ pr_err("Unable to create omapdrm/dmm device\n");
+ return r;
+ }
+
board_data.version = ver;
/* find the main dss node */
hdmi_init_of();
- /* create omapdrm devices */
- r = omapdrm_init();
- if (r < 0) {
- pr_err("Unable to create omapdrm device\n");
- return r;
- }
-
return 0;
}
index d9bd965f6d073d80f3faee98bd7e00c6b088d12d..14455b824c2c519df72f1147103488f094104506 100644 (file)
--- a/arch/arm/mach-omap2/fb.c
+++ b/arch/arm/mach-omap2/fb.c
.num_resources = 0,
};
+void omapfb_set_platform_data(struct omapfb_platform_data *data)
+{
+ omapfb_config = *data;
+}
+
static int __init omap_init_fb(void)
{
return platform_device_register(&omap_fb_device);
arch_initcall(omap_init_fb);
#endif
+
diff --git a/arch/arm/mach-omap2/include/mach/tiler.h b/arch/arm/mach-omap2/include/mach/tiler.h
--- /dev/null
@@ -0,0 +1,570 @@
+/*
+ * tiler.h
+ *
+ * TILER driver support functions for TI TILER hardware block.
+ *
+ * Authors: Lajos Molnar <molnar@ti.com>
+ * David Sin <davidsin@ti.com>
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TILER_H
+#define TILER_H
+
+#include <linux/mm.h>
+
+/*
+ * ----------------------------- API Definitions -----------------------------
+ */
+
+/* return true if physical address is in the tiler container */
+bool is_tiler_addr(u32 phys);
+
+enum tiler_fmt {
+ TILFMT_MIN = -2,
+ TILFMT_INVALID = -2,
+ TILFMT_NONE = -1,
+ TILFMT_8BIT = 0,
+ TILFMT_16BIT = 1,
+ TILFMT_32BIT = 2,
+ TILFMT_PAGE = 3,
+ TILFMT_MAX = 3,
+ TILFMT_8AND16 = 4, /* used to mark NV12 reserve block */
+};
+
+/* tiler block info */
+struct tiler_block_t {
+ u32 phys; /* system space (L3) tiler addr */
+ u32 width; /* width */
+ u32 height; /* height */
+ u32 key; /* secret key */
+ u32 id; /* unique block ID */
+};
+
+/* tiler (image/video frame) view */
+struct tiler_view_t {
+ u32 tsptr; /* tiler space addr */
+ u32 width; /* width */
+ u32 height; /* height */
+ u32 bpp; /* bytes per pixel */
+ s32 h_inc; /* horizontal increment */
+ s32 v_inc; /* vertical increment */
+};
+
+/* get the tiler format for a physical address or TILFMT_INVALID */
+enum tiler_fmt tiler_fmt(u32 phys);
+
+/* get the modified (1 for page mode) bytes-per-pixel for a tiler block */
+u32 tiler_bpp(const struct tiler_block_t *b);
+
+/* get tiler block physical stride */
+u32 tiler_pstride(const struct tiler_block_t *b);
+
+/* get tiler block virtual stride */
+static inline u32 tiler_vstride(const struct tiler_block_t *b)
+{
+ return PAGE_ALIGN((b->phys & ~PAGE_MASK) + tiler_bpp(b) * b->width);
+}
+
+/* returns the virtual size of the block (for mmap) */
+static inline u32 tiler_size(const struct tiler_block_t *b)
+{
+ return b->height * tiler_vstride(b);
+}
+
+/* Event types */
+#define TILER_DEVICE_CLOSE 0
+
+/**
+ * Registers a notifier block with TILER driver.
+ *
+ * @param nb notifier_block
+ *
+ * @return error status
+ */
+s32 tiler_reg_notifier(struct notifier_block *nb);
+
+/**
+ * Un-registers a notifier block with TILER driver.
+ *
+ * @param nb notifier_block
+ *
+ * @return error status
+ */
+s32 tiler_unreg_notifier(struct notifier_block *nb);
+
+/**
+ * Get the physical address for a given user va.
+ *
+ * @param usr user virtual address
+ *
+ * @return valid pa or 0 for error
+ */
+u32 tiler_virt2phys(u32 usr);
+
+/**
+ * Reserves a 1D or 2D TILER block area and memory for the
+ * current process with group ID 0.
+ *
+ * @param blk pointer to tiler block data. This must be set up ('phys' member
+ * must be 0) with the tiler block information. 'height' must be 1
+ * for 1D block.
+ * @param fmt TILER block format
+ *
+ * @return error status
+ */
+s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt);
+
+/**
+ * Reserves a 1D or 2D TILER block area and memory for a set process and group
+ * ID.
+ *
+ * @param blk pointer to tiler block data. This must be set up ('phys' member
+ * must be 0) with the tiler block information. 'height' must be 1
+ * for 1D block.
+ * @param fmt TILER block format
+ * @param gid group ID
+ * @param pid process ID
+ *
+ * @return error status
+ */
+s32 tiler_allocx(struct tiler_block_t *blk, enum tiler_fmt fmt,
+ u32 gid, pid_t pid);
+
+/**
+ * Mmaps a portion of a tiler block to a virtual address. Use this method in
+ * your driver's mmap function to potentially combine multiple tiler blocks as
+ * one virtual buffer.
+ *
+ * @param blk pointer to tiler block data
+ * @param offs offset from where to map (must be page aligned)
+ * @param size size of area to map (must be page aligned)
+ * @param vma VMM memory area to map to
+ * @param voffs offset (from vm_start) in the VMM memory area to start
+ * mapping at
+ *
+ * @return error status
+ */
+s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
+ struct vm_area_struct *vma, u32 voffs);
+
+/**
+ * Ioremaps a portion of a tiler block. Use this method in your driver instead
+ * of ioremap to potentially combine multiple tiler blocks as one virtual
+ * buffer.
+ *
+ * @param blk pointer to tiler block data
+ * @param offs offset from where to map (must be page aligned)
+ * @param size size of area to map (must be page aligned)
+ * @param addr virtual address
+ * @param mtype ioremap memory type (e.g. MT_DEVICE)
+ *
+ * @return error status
+ */
+s32 tiler_ioremap_blk(struct tiler_block_t *blk, u32 offs, u32 size, u32 addr,
+ u32 mtype);
+
+/**
+ * Maps an existing buffer to a 1D or 2D TILER area for the
+ * current process with group ID 0.
+ *
+ * Currently, only 1D area mapping is supported.
+ *
+ * NOTE: alignment is always PAGE_SIZE and offset is 0 as full pages are mapped
+ * into tiler container.
+ *
+ * @param blk pointer to tiler block data. This must be set up
+ * ('phys' member must be 0) with the tiler block
+ * information. 'height' must be 1 for 1D block.
+ * @param fmt TILER format
+ * @param usr_addr user space address of existing buffer.
+ *
+ * @return error status
+ */
+s32 tiler_map(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 usr_addr);
+
+/**
+ * Maps an existing buffer to a 1D or 2D TILER area for a set process and group
+ * ID.
+ *
+ * Currently, only 1D area mapping is supported.
+ *
+ * NOTE: alignment is always PAGE_SIZE and offset is 0 as full pages are mapped
+ * into tiler container.
+ *
+ * @param blk pointer to tiler block data. This must be set up
+ * ('phys' member must be 0) with the tiler block
+ * information. 'height' must be 1 for 1D block.
+ * @param fmt TILER format
+ * @param gid group ID
+ * @param pid process ID
+ * @param usr_addr user space address of existing buffer.
+ *
+ * @return error status
+ */
+s32 tiler_mapx(struct tiler_block_t *blk, enum tiler_fmt fmt,
+ u32 gid, pid_t pid, u32 usr_addr);
+
+/**
+ * Frees TILER memory. Since there may be multiple references for the same area
+ * if duplicated by tiler_dup, the area is only actually freed if all references
+ * have been freed.
+ *
+ * @param blk pointer to a tiler block data as filled by tiler_alloc,
+ * tiler_map or tiler_dup. 'phys' and 'id' members will be set to
+ * 0 on success.
+ */
+void tiler_free(struct tiler_block_t *blk);
+
+/**
+ * Reserves tiler area for n identical blocks for the current process. Use this
+ * method to get optimal placement of multiple identical tiler blocks; however,
+ * it may not reserve area if tiler_alloc is equally efficient.
+ *
+ * @param n number of identical set of blocks
+ * @param fmt TILER format
+ * @param width block width
+ * @param height block height (must be 1 for 1D)
+ */
+void tiler_reserve(u32 n, enum tiler_fmt fmt, u32 width, u32 height);
+
+/**
+ * Reserves tiler area for n identical blocks. Use this method to get optimal
+ * placement of multiple identical tiler blocks; however, it may not reserve
+ * area if tiler_alloc is equally efficient.
+ *
+ * @param n number of identical set of blocks
+ * @param fmt TILER bit mode
+ * @param width block width
+ * @param height block height (must be 1 for 1D)
+ * @param gid group ID
+ * @param pid process ID
+ */
+void tiler_reservex(u32 n, enum tiler_fmt fmt, u32 width, u32 height,
+ u32 gid, pid_t pid);
+
+/**
+ * Reserves tiler area for n identical NV12 blocks for the current process. Use
+ * this method to get optimal placement of multiple identical NV12 tiler blocks;
+ * however, it may not reserve area if tiler_alloc is equally efficient.
+ *
+ * @param n number of identical set of blocks
+ * @param width block width (Y)
+ * @param height block height (Y)
+ */
+void tiler_reserve_nv12(u32 n, u32 width, u32 height);
+
+/**
+ * Reserves tiler area for n identical NV12 blocks. Use this method to get
+ * optimal placement of multiple identical NV12 tiler blocks; however, it may
+ * not reserve area if tiler_alloc is equally efficient.
+ *
+ * @param n number of identical set of blocks
+ * @param width block width (Y)
+ * @param height block height (Y)
+ * @param gid group ID
+ * @param pid process ID
+ */
+void tiler_reservex_nv12(u32 n, u32 width, u32 height, u32 gid, pid_t pid);
+
+/**
+ * Create a view based on a tiler address and width and height
+ *
+ * This method should only be used as a last resort, e.g. if tilview object
+ * cannot be passed because of incoherence with other view 2D objects that must
+ * be supported.
+ *
+ * @param view Pointer to a view where the information will be stored
+ * @param ssptr MUST BE a tiler address
+ * @param width view width
+ * @param height view height
+ */
+void tilview_create(struct tiler_view_t *view, u32 phys, u32 width, u32 height);
+
+/**
+ * Obtains the view information for a tiler block
+ *
+ * @param view Pointer to a view where the information will be stored
+ * @param blk Pointer to an existing allocated tiler block
+ */
+void tilview_get(struct tiler_view_t *view, struct tiler_block_t *blk);
+
+/**
+ * Crops a tiler view to a rectangular portion. Crop area must be fully within
+ * the orginal tiler view: 0 <= left <= left + width <= view->width, also:
+ * 0 <= top <= top + height <= view->height.
+ *
+ * @param view Pointer to tiler view to be cropped
+ * @param left x of top-left corner
+ * @param top y of top-left corner
+ * @param width crop width
+ * @param height crop height
+ *
+ * @return error status. The view will be reduced to the crop region if the
+ * crop region is correct. Otherwise, no modifications are made.
+ */
+s32 tilview_crop(struct tiler_view_t *view, u32 left, u32 top, u32 width,
+ u32 height);
+
+/**
+ * Rotates a tiler view clockwise by a specified degree.
+ *
+ * @param view Pointer to tiler view to be cropped
+ * @param rotate Degree of rotation (clockwise). Must be a multiple of
+ * 90.
+ * @return error status. View is not modified on error; otherwise, it is
+ * updated in place.
+ */
+s32 tilview_rotate(struct tiler_view_t *view, s32 rotation);
+
+/**
+ * Mirrors a tiler view horizontally and/or vertically.
+ *
+ * @param view Pointer to tiler view to be cropped
+ * @param flip_x Mirror horizontally (left-to-right)
+ * @param flip_y Mirror vertically (top-to-bottom)
+ *
+ * @return error status. View is not modified on error; otherwise, it is
+ * updated in place.
+ */
+s32 tilview_flip(struct tiler_view_t *view, bool flip_x, bool flip_y);
+
+/*
+ * -------------------- TILER hooks for ION/HWC migration --------------------
+ */
+
+/* type of tiler memory */
+enum tiler_memtype {
+ TILER_MEM_ALLOCED, /* tiler allocated the memory */
+ TILER_MEM_GOT_PAGES, /* tiler used get_user_pages */
+ TILER_MEM_USING, /* tiler is using the pages */
+};
+
+/* physical pages to pin - mem must be kmalloced */
+struct tiler_pa_info {
+ u32 num_pg; /* number of pages in page-list */
+ u32 *mem; /* list of phys page addresses */
+ enum tiler_memtype memtype; /* how we got physical pages */
+};
+
+typedef struct mem_info *tiler_blk_handle;
+
+/**
+ * Allocate a 1D area of container space in the Tiler
+ *
+ * @param pa ptr to tiler_pa_info structure
+ *
+ * @return handle Handle to tiler block information. NULL on error.
+ *
+ * NOTE: this will take ownership pa->mem (will free it)
+ *
+ */
+tiler_blk_handle tiler_map_1d_block(struct tiler_pa_info *pa);
+
+/**
+ * Allocate an area of container space in the Tiler
+ *
+ * @param fmt Tiler bpp mode
+ * @param width Width in pixels
+ * @param height Height in pixels
+ * @param ssptr Value of tiler physical address of allocation
+ * @param virt_array Array of physical address for the start of each virtual
+ page
+ *
+ * @return handle Handle to tiler block information. NULL on error.
+ *
+ * NOTE: For 1D allocations, specify the full size in the width field, and
+ * specify a height of 1.
+ */
+tiler_blk_handle tiler_alloc_block_area(enum tiler_fmt fmt, u32 width,
+ u32 height, u32 *ssptr,
+ u32 *virt_array);
+
+/**
+ * Allocate an area of container space in the Tiler with a specific alignment
+ * and user specified security token
+ *
+ * @param fmt Tiler bpp mode
+ * @param width Width in pixels
+ * @param height Height in pixels
+ * @param ssptr Value of tiler physical address of allocation
+ * @param virt_array Array of physical address for the start of each virtual
+ page
+ * @align Alignment in bytes
+ * @offset Offset into 4KiB
+ * @token Security token
+ *
+ * @return handle Handle to tiler block information. NULL on error.
+ *
+ * NOTE: For 1D allocations, specify the full size in the width field, and
+ * specify a height of 1.
+ */
+tiler_blk_handle tiler_alloc_block_area_aligned(enum tiler_fmt fmt, u32 width,
+ u32 height, u32 *ssptr, u32 *virt_array, u32 align,
+ u32 offset, u32 token);
+
+/**
+ * Free a reserved area in the Tiler
+ *
+ * @param handle Handle to tiler block information
+ *
+ */
+void tiler_free_block_area(tiler_blk_handle block);
+
+/**
+ * Pins a set of physical pages into the Tiler using the area defined in a
+ * handle
+ *
+ * @param handle Handle to tiler block information
+ * @param addr_array Array of addresses
+ * @param nents Number of addresses in array
+ *
+ * @return error status.
+ */
+s32 tiler_pin_block(tiler_blk_handle handle, u32 *addr_array, u32 nents);
+
+/**
+ * Unpins a set of physical pages from the Tiler
+ *
+ * @param handle Handle to tiler block information
+ *
+ */
+void tiler_unpin_block(tiler_blk_handle handle);
+
+/**
+ * Gives memory requirements for a given container allocation
+ *
+ * @param fmt Tiler bpp mode
+ * @param width Width in pixels
+ * @param height Height in pixels
+ * @param alloc_pages Number of pages required to back tiler container
+ * @param virt_pages Number of pages required to back the virtual address space
+ *
+ * @return 0 for success. Non zero for error
+ */
+s32 tiler_memsize(enum tiler_fmt fmt, u32 width, u32 height, u32 *alloc_pages,
+ u32 *virt_pages);
+
+/**
+ * Gives back page memory requirements for a given container
+ * allocation
+ *
+ * @param fmt Tiler bpp mode
+ * @param width Width in pixels
+ * @param height Height in pixels
+ *
+ * @return Number of pages required to back tiler container.
+ * Returns 0 for error
+ */
+u32 tiler_backpages(enum tiler_fmt fmt, u32 width, u32 height);
+
+/**
+ * Returns virtual stride of a tiler block
+ *
+ * @param handle Handle to tiler block allocation
+ *
+ * @return Size of virtual stride
+ */
+u32 tiler_block_vstride(tiler_blk_handle handle);
+
+/**
+ * Fills an array virtual size of a tiler block
+ *
+ * @param handle Handle to tiler block allocation
+ * @param virt_array Array of physical address for the start of each virtual
+ * page
+ * @param handle Pointer to the size of the virt_array array
+ * @return 0 for success. Non zero for error
+ */
+s32 tiler_fill_virt_array(tiler_blk_handle handle, u32 *virt_array,
+ u32 *array_size);
+
+/**
+ * Returns virtual size of a tiler block
+ *
+ * @param handle Handle to tiler block allocation
+ *
+ * @return Size of buffer
+ */
+u32 tiler_block_vsize(tiler_blk_handle handle);
+
+struct tiler_pa_info *user_block_to_pa(u32 usr_addr, u32 num_pg);
+void tiler_pa_free(struct tiler_pa_info *pa);
+
+/*
+ * ---------------------------- IOCTL Definitions ----------------------------
+ */
+
+/* ioctls */
+#define TILIOC_GBLK _IOWR('z', 100, struct tiler_block_info)
+#define TILIOC_FBLK _IOW('z', 101, struct tiler_block_info)
+#define TILIOC_GSSP _IOWR('z', 102, u32)
+#define TILIOC_MBLK _IOWR('z', 103, struct tiler_block_info)
+#define TILIOC_UMBLK _IOW('z', 104, struct tiler_block_info)
+#define TILIOC_QBUF _IOWR('z', 105, struct tiler_buf_info)
+#define TILIOC_RBUF _IOWR('z', 106, struct tiler_buf_info)
+#define TILIOC_URBUF _IOWR('z', 107, struct tiler_buf_info)
+#define TILIOC_QBLK _IOWR('z', 108, struct tiler_block_info)
+#define TILIOC_PRBLK _IOW('z', 109, struct tiler_block_info)
+#define TILIOC_URBLK _IOW('z', 110, u32)
+
+struct area {
+ u16 width;
+ u16 height;
+};
+
+/* userspace tiler block info */
+struct tiler_block_info {
+ enum tiler_fmt fmt;
+ union {
+ struct area area;
+ u32 len;
+ } dim;
+ u32 stride; /* stride is not maintained for 1D blocks */
+ void *ptr; /* userspace address for mapping existing buffer */
+ u32 id;
+ u32 key;
+ u32 group_id;
+ u32 ssptr; /* physical address, may not exposed by default */
+};
+
+#define TILER_MAX_NUM_BLOCKS 16
+
+/* userspace tiler buffer info */
+struct tiler_buf_info {
+ u32 num_blocks;
+ struct tiler_block_info blocks[TILER_MAX_NUM_BLOCKS];
+ u32 offset;
+ u32 length; /* also used as number of buffers for reservation */
+};
+
+#endif
index 1976fc952c506c39cb29902792f8d55002a7b5ce..ed3c35f9990c335d1422a3a97c0f4a3cd450a58b 100644 (file)
/* dss_hdmi */
static struct omap_hwmod_irq_info dra7xx_dss_hdmi_irqs[] = {
- { .irq = 101 + DRA7XX_IRQ_GIC_START },
+ { .irq = 96 + DRA7XX_IRQ_GIC_START },
{ .irq = -1 }
};
.class = &dra7xx_mcasp_hwmod_class,
.clkdm_name = "ipu_clkdm",
.main_clk = "mcasp1_ahclkx_mux",
+ .flags = HWMOD_SWSUP_SIDLE,
.prcm = {
.omap4 = {
.clkctrl_offs = DRA7XX_CM_IPU_MCASP1_CLKCTRL_OFFSET,
.class = &dra7xx_mcasp_hwmod_class,
.clkdm_name = "l4per2_clkdm",
.main_clk = "mcasp2_ahclkr_mux",
+ .flags = HWMOD_SWSUP_SIDLE,
.prcm = {
.omap4 = {
.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP2_CLKCTRL_OFFSET,
},
};
+/* HACK: Taken from UART6 since they're not used in dra7-evm */
+static struct omap_hwmod_dma_info dra7xx_mcasp3_sdma_reqs[] = {
+ { .name = "tx", .dma_req = 78 + DRA7XX_DMA_REQ_START },
+ { .name = "rx", .dma_req = 79 + DRA7XX_DMA_REQ_START },
+ { .dma_req = -1 }
+};
+
/* mcasp3 */
static struct omap_hwmod dra7xx_mcasp3_hwmod = {
.name = "mcasp3",
.class = &dra7xx_mcasp_hwmod_class,
.clkdm_name = "l4per2_clkdm",
.main_clk = "mcasp3_ahclkx_mux",
+ .sdma_reqs = dra7xx_mcasp3_sdma_reqs,
+ .flags = HWMOD_SWSUP_SIDLE,
.prcm = {
.omap4 = {
.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP3_CLKCTRL_OFFSET,
.class = &dra7xx_mcasp_hwmod_class,
.clkdm_name = "l4per2_clkdm",
.main_clk = "mcasp4_ahclkx_mux",
+ .flags = HWMOD_SWSUP_SIDLE,
.prcm = {
.omap4 = {
.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP4_CLKCTRL_OFFSET,
.class = &dra7xx_mcasp_hwmod_class,
.clkdm_name = "l4per2_clkdm",
.main_clk = "mcasp5_ahclkx_mux",
+ .flags = HWMOD_SWSUP_SIDLE,
.prcm = {
.omap4 = {
.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP5_CLKCTRL_OFFSET,
},
};
+/* HACK: Taken from UART5 since they're not used in dra7-evm */
+static struct omap_hwmod_dma_info dra7xx_mcasp6_sdma_reqs[] = {
+ { .name = "tx", .dma_req = 62 + DRA7XX_DMA_REQ_START },
+ { .name = "rx", .dma_req = 63 + DRA7XX_DMA_REQ_START },
+ { .dma_req = -1 }
+};
+
/* mcasp6 */
static struct omap_hwmod dra7xx_mcasp6_hwmod = {
.name = "mcasp6",
.class = &dra7xx_mcasp_hwmod_class,
.clkdm_name = "l4per2_clkdm",
.main_clk = "mcasp6_ahclkx_mux",
+ .sdma_reqs = dra7xx_mcasp6_sdma_reqs,
+ .flags = HWMOD_SWSUP_SIDLE,
.prcm = {
.omap4 = {
.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP6_CLKCTRL_OFFSET,
.class = &dra7xx_mcasp_hwmod_class,
.clkdm_name = "l4per2_clkdm",
.main_clk = "mcasp7_ahclkx_mux",
+ .flags = HWMOD_SWSUP_SIDLE,
.prcm = {
.omap4 = {
.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP7_CLKCTRL_OFFSET,
.class = &dra7xx_mcasp_hwmod_class,
.clkdm_name = "l4per2_clkdm",
.main_clk = "mcasp8_ahclk_mux",
+ .flags = HWMOD_SWSUP_SIDLE,
.prcm = {
.omap4 = {
.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP8_CLKCTRL_OFFSET,
index 4077d23a8603af0525ce648940b71087ddfcfdd9..1877b54ad7f4d7a2263de2dd50df9717ed2c7a84 100644 (file)
i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
obj-y += $(i2c-omap-m) $(i2c-omap-y)
+obj-$(CONFIG_DSSCOMP) += omap_dsscomp.o
+obj-$(CONFIG_ION_OMAP) += sgx_omaplfb.o
+obj-$(CONFIG_ION_OMAP) += android-display.o
diff --git a/arch/arm/plat-omap/android-display.c b/arch/arm/plat-omap/android-display.c
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Android display memory setup for OMAP4+ displays
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author: Lajos Molnar
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+
+#include <video/omapdss.h>
+
+#include <plat/android-display.h>
+#include <plat/dsscomp.h>
+//#include <plat/vram.h>
+
+struct omap_android_display_data {
+ /* members with default values */
+ u32 width;
+ u32 height;
+ u32 bpp; /* must be 2 or 4 */
+
+ /* members with no default value */
+ u32 tiler1d_mem;
+};
+
+/*
+ * We need to peek at omapdss settings so that we have enough memory for swap
+ * chain and vram. While this could be done by omapdss, omapdss could be
+ * compiled as a module, which is too late to get this information.
+ */
+static char default_display[16];
+static int __init get_default_display(char *str)
+{
+ strncpy(default_display, str, sizeof(default_display));
+ if (strlen(str) >= sizeof(default_display))
+ pr_warn("android_display: cannot set default display larger "
+ "than %d characters", sizeof(default_display) - 1);
+ default_display[sizeof(default_display) - 1] = '\0';
+ return 0;
+}
+early_param("omapdss.def_disp", get_default_display);
+
+static unsigned int hdmi_width, hdmi_height;
+static int __init get_hdmi_options(char *str)
+{
+ unsigned int width, height;
+ char dummy;
+ if (sscanf(str, "%ux%u%c", &width, &height, &dummy) == 2) {
+ hdmi_width = width;
+ hdmi_height = height;
+ }
+ return 0;
+}
+early_param("omapdss.hdmi_options", get_hdmi_options);
+
+static void get_display_size(struct omap_dss_device *device,
+ struct omap_android_display_data *mem)
+{
+ if (!device)
+ goto done;
+
+ if (device->type == OMAP_DISPLAY_TYPE_HDMI &&
+ hdmi_width && hdmi_height) {
+ mem->width = hdmi_width;
+ mem->height = hdmi_height;
+ } else if (device->panel.timings.x_res && device->panel.timings.y_res) {
+ mem->width = device->panel.timings.x_res;
+ mem->height = device->panel.timings.y_res;
+ }
+ if (device->ctrl.pixel_size)
+ mem->bpp = ALIGN(device->ctrl.pixel_size, 16) >> 3;
+
+ pr_info("android_display: setting %s resolution to %u*%u, bpp=%u\n",
+ device->name, mem->width, mem->height, mem->bpp);
+done:
+ return;
+}
+
+static void set_tiler1d_slot_size(struct dsscomp_platform_data *dsscomp,
+ struct omap_android_display_data *mem)
+{
+ struct dsscomp_platform_data data = {
+ .tiler1d_slotsz = 0,
+ };
+
+ if (dsscomp)
+ data = *dsscomp;
+
+ /* do not change board specified value if given */
+ if (data.tiler1d_slotsz)
+ goto done;
+
+ /*
+ * 4 bytes per pixel, and ICS factor of 4. The ICS factor
+ * is chosen somewhat arbitrarily to support the home screen layers
+ * to be displayed by DSS. The size of the home screen layers is
+ * roughly (1 + 2.5 + 0.1 + 0.1) * size_of_the_screen
+ * for the icons, wallpaper, status bar and navigation bar. Boards
+ * that wish to use a different factor should supply their tiler1D
+ * slot size directly.
+ */
+ data.tiler1d_slotsz =
+ PAGE_ALIGN(mem->width * mem->height * 4 * 4);
+
+done:
+ if (dsscomp)
+ *dsscomp = data;
+ //dsscomp_set_platform_data(&data);
+
+ /* remember setting for ion carveouts */
+ mem->tiler1d_mem =
+ NUM_ANDROID_TILER1D_SLOTS * data.tiler1d_slotsz;
+ pr_info("android_display: tiler1d %u\n", mem->tiler1d_mem);
+}
+
+static u32 vram_size(struct omap_android_display_data *mem)
+{
+ /* calculate required VRAM */
+ return PAGE_ALIGN(ALIGN(mem->width, 64) * mem->height * mem->bpp);
+}
+
+static void set_vram_sizes(struct sgx_omaplfb_config *sgx_config,
+ struct omapfb_mem_region *region,
+ struct omap_android_display_data *mem,
+ unsigned fbnum)
+{
+ u32 num_vram_buffers;
+ u32 vram = 0;
+
+ if (!sgx_config || !region || !mem)
+ return;
+
+ /* Need at least 1 VRAM buffer for fb0 */
+ num_vram_buffers = max(sgx_config->vram_buffers, 1u);
+
+ vram += sgx_config->vram_reserve;
+ vram += num_vram_buffers * vram_size(mem);
+
+ /* set fb vram needs */
+ region->size = vram;
+ pr_info("android_display: setting fb%u.vram to %u\n", fbnum, vram);
+}
+
+/* coordinate between sgx, omapdss, dsscomp and ion needs */
+void omap_android_display_setup(struct omap_dss_board_info *dss,
+ struct dsscomp_platform_data *dsscomp,
+ struct sgx_omaplfb_platform_data *sgx,
+ struct omapfb_platform_data *fb)
+{
+ struct sgx_omaplfb_config *p_sgx_config = NULL;
+ int i = 0;
+ u32 omapfb_vram = 0;
+ u32 num_configs = 1;
+
+ if (sgx)
+ num_configs = sgx->num_configs;
+
+ for (i = 0; i < num_configs; ++i) {
+ if (!sgx || !sgx->configs)
+ p_sgx_config = sgx_omaplfb_get(i);
+ else
+ p_sgx_config = &(sgx->configs[i]);
+
+ struct omap_android_display_data mem = {
+ .bpp = 4,
+ .width = 1280,
+ .height = 720,
+ };
+
+ if (i == 0 && i < dss->num_devices)
+ get_display_size(dss->devices[i], &mem);
+
+ if (dsscomp)
+ set_tiler1d_slot_size(dsscomp, &mem);
+
+ /* skip region if no sgx_config associated with it
+ * or it has size pre-set by board configuration
+ */
+ if (i < fb->mem_desc.region_cnt &&
+ !fb->mem_desc.region[i].size)
+ set_vram_sizes(p_sgx_config, &fb->mem_desc.region[i],
+ &mem, i);
+ sgx_omaplfb_set(i, p_sgx_config);
+ }
+
+ /* set global vram needs incl. additional regions specified */
+ for (i = 0; i < fb->mem_desc.region_cnt; i++)
+ if (!fb->mem_desc.region[i].paddr)
+ omapfb_vram += fb->mem_desc.region[i].size;
+
+ pr_info("android_display: setting vram to %u\n", omapfb_vram);
+ //omap_vram_set_sdram_vram(omapfb_vram, 0);
+}
diff --git a/arch/arm/plat-omap/include/plat/android-display.h b/arch/arm/plat-omap/include/plat/android-display.h
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * arch/arm/mach-omap2/android_display.h
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author: Lajos Molnar
+ *
+ * OMAP2 platform device setup/initialization
+ *
+ * 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 __ARCH_ARM_MACH_OMAP_ANDROID_DISPLAY_H
+#define __ARCH_ARM_MACH_OMAP_ANDROID_DISPLAY_H
+
+#include <linux/omapfb.h>
+#include <video/omapdss.h>
+#include <plat/sgx_omaplfb.h>
+#include <plat/dsscomp.h>
+
+#define NUM_ANDROID_TILER1D_SLOTS 2
+
+void omap_android_display_setup(struct omap_dss_board_info *dss,
+ struct dsscomp_platform_data *dsscomp,
+ struct sgx_omaplfb_platform_data *sgx,
+ struct omapfb_platform_data *fb);
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/board.h b/arch/arm/plat-omap/include/plat/board.h
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * arch/arm/plat-omap/include/mach/board.h
+ *
+ * Information structures for board-specific data
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Written by Juha Yrjölä <juha.yrjola@nokia.com>
+ */
+
+#ifndef _OMAP_BOARD_H
+#define _OMAP_BOARD_H
+
+#include <linux/types.h>
+
+#include <plat/gpio-switch.h>
+
+/*
+ * OMAP35x EVM revision
+ * Run time detection of EVM revision is done by reading Ethernet
+ * PHY ID -
+ * GEN_1 = 0x01150000
+ * GEN_2 = 0x92200000
+ */
+enum {
+ OMAP3EVM_BOARD_GEN_1 = 0, /* EVM Rev between A - D */
+ OMAP3EVM_BOARD_GEN_2, /* EVM Rev >= Rev E */
+};
+
+/* Different peripheral ids */
+#define OMAP_TAG_CLOCK 0x4f01
+#define OMAP_TAG_GPIO_SWITCH 0x4f06
+#define OMAP_TAG_STI_CONSOLE 0x4f09
+#define OMAP_TAG_CAMERA_SENSOR 0x4f0a
+
+#define OMAP_TAG_BOOT_REASON 0x4f80
+#define OMAP_TAG_FLASH_PART 0x4f81
+#define OMAP_TAG_VERSION_STR 0x4f82
+
+struct omap_clock_config {
+ /* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
+ u8 system_clock_type;
+};
+
+struct omap_serial_console_config {
+ u8 console_uart;
+ u32 console_speed;
+};
+
+struct omap_sti_console_config {
+ unsigned enable:1;
+ u8 channel;
+};
+
+struct omap_camera_sensor_config {
+ u16 reset_gpio;
+ int (*power_on)(void * data);
+ int (*power_off)(void * data);
+};
+
+struct omap_usb_config {
+ /* Configure drivers according to the connectors on your board:
+ * - "A" connector (rectagular)
+ * ... for host/OHCI use, set "register_host".
+ * - "B" connector (squarish) or "Mini-B"
+ * ... for device/gadget use, set "register_dev".
+ * - "Mini-AB" connector (very similar to Mini-B)
+ * ... for OTG use as device OR host, initialize "otg"
+ */
+ unsigned register_host:1;
+ unsigned register_dev:1;
+ u8 otg; /* port number, 1-based: usb1 == 2 */
+
+ u8 hmc_mode;
+
+ /* implicitly true if otg: host supports remote wakeup? */
+ u8 rwc;
+
+ /* signaling pins used to talk to transceiver on usbN:
+ * 0 == usbN unused
+ * 2 == usb0-only, using internal transceiver
+ * 3 == 3 wire bidirectional
+ * 4 == 4 wire bidirectional
+ * 6 == 6 wire unidirectional (or TLL)
+ */
+ u8 pins[3];
+
+ struct platform_device *udc_device;
+ struct platform_device *ohci_device;
+ struct platform_device *otg_device;
+
+ u32 (*usb0_init)(unsigned nwires, unsigned is_device);
+ u32 (*usb1_init)(unsigned nwires);
+ u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup);
+};
+
+struct omap_lcd_config {
+ char panel_name[16];
+ char ctrl_name[16];
+ s16 nreset_gpio;
+ u8 data_lines;
+};
+
+struct device;
+struct fb_info;
+struct omap_backlight_config {
+ int default_intensity;
+ int (*set_power)(struct device *dev, int state);
+};
+
+struct omap_fbmem_config {
+ u32 start;
+ u32 size;
+};
+
+struct omap_pwm_led_platform_data {
+ const char *name;
+ int intensity_timer;
+ int blink_timer;
+ void (*set_power)(struct omap_pwm_led_platform_data *self, int on_off);
+};
+
+struct omap_uart_config {
+ /* Bit field of UARTs present; bit 0 --> UART1 */
+ unsigned int enabled_uarts;
+};
+
+
+struct omap_flash_part_config {
+ char part_table[0];
+};
+
+struct omap_boot_reason_config {
+ char reason_str[12];
+};
+
+struct omap_version_config {
+ char component[12];
+ char version[12];
+};
+
+struct omap_board_config_entry {
+ u16 tag;
+ u16 len;
+ u8 data[0];
+};
+
+struct omap_board_config_kernel {
+ u16 tag;
+ const void *data;
+};
+
+extern const void *__init __omap_get_config(u16 tag, size_t len, int nr);
+
+#define omap_get_config(tag, type) \
+ ((const type *) __omap_get_config((tag), sizeof(type), 0))
+#define omap_get_nr_config(tag, type, nr) \
+ ((const type *) __omap_get_config((tag), sizeof(type), (nr)))
+
+extern const void *__init omap_get_var_config(u16 tag, size_t *len);
+
+extern struct omap_board_config_kernel *omap_board_config;
+extern int omap_board_config_size;
+
+
+/* for TI reference platforms sharing the same debug card */
+extern int debug_card_init(u32 addr, unsigned gpio);
+
+/* OMAP3EVM revision */
+#if defined(CONFIG_MACH_OMAP3EVM)
+u8 get_omap3_evm_rev(void);
+#else
+#define get_omap3_evm_rev() (-EINVAL)
+#endif
+#endif
diff --git a/arch/arm/plat-omap/include/plat/dsscomp.h b/arch/arm/plat-omap/include/plat/dsscomp.h
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * arch/arm/plat-omap/include/plat/dsscomp.h
+ *
+ * DSS Composition platform specific header
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _ARCH_ARM_PLAT_OMAP_DSSCOMP_H
+#define _ARCH_ARM_PLAT_OMAP_DSSCOMP_H
+
+#include <video/omapdss.h>
+#include <video/dsscomp.h>
+
+struct dsscomp_platform_data {
+ unsigned int tiler1d_slotsz;
+};
+
+/* queuing operations */
+struct dsscomp;
+struct dsscomp *dsscomp_new(struct omap_overlay_manager *mgr);
+u32 dsscomp_get_ovls(struct dsscomp *comp);
+int dsscomp_set_ovl(struct dsscomp *comp, struct dss2_ovl_info *ovl);
+int dsscomp_get_ovl(struct dsscomp *comp, u32 ix, struct dss2_ovl_info *ovl);
+int dsscomp_set_mgr(struct dsscomp *comp, struct dss2_mgr_info *mgr);
+int dsscomp_get_mgr(struct dsscomp *comp, struct dss2_mgr_info *mgr);
+int dsscomp_setup(struct dsscomp *comp, enum dsscomp_setup_mode mode,
+ struct dss2_rect_t win);
+int dsscomp_delayed_apply(struct dsscomp *comp);
+void dsscomp_drop(struct dsscomp *c);
+
+struct tiler_pa_info;
+int dsscomp_gralloc_queue(struct dsscomp_setup_dispc_data *d,
+ struct tiler_pa_info **pas,
+ bool early_callback,
+ void (*cb_fn)(void *, int), void *cb_arg);
+
+void dsscomp_set_platform_data(struct dsscomp_platform_data *data);
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/gpio-switch.h b/arch/arm/plat-omap/include/plat/gpio-switch.h
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * GPIO switch definitions
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPIO_SWITCH_H
+#define __ASM_ARCH_OMAP_GPIO_SWITCH_H
+
+#include <linux/types.h>
+
+/* Cover:
+ * high -> closed
+ * low -> open
+ * Connection:
+ * high -> connected
+ * low -> disconnected
+ * Activity:
+ * high -> active
+ * low -> inactive
+ *
+ */
+#define OMAP_GPIO_SWITCH_TYPE_COVER 0x0000
+#define OMAP_GPIO_SWITCH_TYPE_CONNECTION 0x0001
+#define OMAP_GPIO_SWITCH_TYPE_ACTIVITY 0x0002
+#define OMAP_GPIO_SWITCH_FLAG_INVERTED 0x0001
+#define OMAP_GPIO_SWITCH_FLAG_OUTPUT 0x0002
+
+struct omap_gpio_switch {
+ const char *name;
+ s16 gpio;
+ unsigned flags:4;
+ unsigned type:4;
+
+ /* Time in ms to debounce when transitioning from
+ * inactive state to active state. */
+ u16 debounce_rising;
+ /* Same for transition from active to inactive state. */
+ u16 debounce_falling;
+
+ /* notify board-specific code about state changes */
+ void (* notify)(void *data, int state);
+ void *notify_data;
+};
+
+/* Call at init time only */
+extern void omap_register_gpio_switches(const struct omap_gpio_switch *tbl,
+ int count);
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/sgx_omaplfb.h b/arch/arm/plat-omap/include/plat/sgx_omaplfb.h
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * SGX display class driver platform resources
+ *
+ * Copyright (C) 2012 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ARCH_ARM_PLAT_OMAP_SGX_OMAPLFB_H
+#define _ARCH_ARM_PLAT_OMAP_SGX_OMAPLFB_H
+
+enum sgx_omaplfb_flags {
+ /*
+ * This flag should be set when we do not want the primary display
+ * swap chain buffers to be used with an external display.
+ *
+ * The number of tiler2d and vram buffers need to be set appropriately
+ */
+ SGX_OMAPLFB_FLAGS_SDMA_TO_TILER2D_EXTERNAL = 0x00000001,
+};
+
+/*
+ * The settings this platform data entry will determine the type and number of
+ * buffers to use by omaplfb.
+ */
+struct sgx_omaplfb_config {
+ /*
+ * Number of tiler2d buffers required for display rendering,
+ * the number of buffers indicated by swap_chain_length will be used
+ * for the swap chain unless flags indicate otherwise
+ */
+ u32 tiler2d_buffers;
+ /*
+ * Number of vram buffers required for display rendering, if no tiler
+ * buffers are required or flags indicate then the number of buffers
+ * indicated by swap_chain_length will be used for the swap chain.
+ */
+ u32 vram_buffers;
+ /*
+ * Indicate any additional vram that needs to be reserved
+ */
+ u32 vram_reserve;
+ /*
+ * Tells omaplfb the number of buffers in the primary swapchain,
+ * if not set it defaults to 2.
+ */
+ u32 swap_chain_length;
+ enum sgx_omaplfb_flags flags;
+};
+
+struct sgx_omaplfb_platform_data {
+ u32 num_configs;
+ struct sgx_omaplfb_config *configs;
+};
+
+int sgx_omaplfb_set(unsigned int fbix, struct sgx_omaplfb_config *data);
+struct sgx_omaplfb_config *sgx_omaplfb_get(unsigned int fbix);
+
+#endif
diff --git a/arch/arm/plat-omap/omap_dsscomp.c b/arch/arm/plat-omap/omap_dsscomp.c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * File: arch/arm/plat-omap/omap_dsscomp.c
+ *
+ * dsscomp resources registration for TI OMAP platforms
+ *
+ * Copyright (C) 2012 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <plat/board.h>
+
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+
+static struct dsscomp_platform_data dsscomp_config = {
+ .tiler1d_slotsz = SZ_16M,
+};
+
+static struct platform_device omap_dsscomp_device = {
+ .name = "dsscomp",
+ .id = -1,
+ .dev = {
+ .platform_data = &dsscomp_config,
+ },
+ .num_resources = 0,
+};
+
+void dsscomp_set_platform_data(struct dsscomp_platform_data *data)
+{
+ dsscomp_config = *data;
+}
+
+static int __init omap_init_dsscomp(void)
+{
+ return platform_device_register(&omap_dsscomp_device);
+}
+
+arch_initcall(omap_init_dsscomp);
+
diff --git a/arch/arm/plat-omap/sgx_omaplfb.c b/arch/arm/plat-omap/sgx_omaplfb.c
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * SGX display class driver platform resources
+ *
+ * Copyright (C) 2012 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <plat/board.h>
+
+#include <plat/sgx_omaplfb.h>
+
+#if defined(CONFIG_FB_OMAP2_NUM_FBS)
+#define OMAPLFB_NUM_DEV CONFIG_FB_OMAP2_NUM_FBS
+#else
+#define OMAPLFB_NUM_DEV 1
+#endif
+
+static struct sgx_omaplfb_config omaplfb_config[OMAPLFB_NUM_DEV] = {
+ {
+ .vram_buffers = 4,
+ .swap_chain_length = 2,
+ },
+ {
+ .tiler2d_buffers = 0,
+ .vram_buffers = 4,
+ .swap_chain_length = 2,
+ }
+};
+
+static struct sgx_omaplfb_platform_data omaplfb_plat_data = {
+ .num_configs = OMAPLFB_NUM_DEV,
+ .configs = omaplfb_config,
+};
+
+static struct platform_device omaplfb_plat_device = {
+ .name = "omaplfb",
+ .id = -1,
+ .dev = {
+ .platform_data = &omaplfb_plat_data,
+ },
+ .num_resources = 0,
+};
+
+int sgx_omaplfb_set(unsigned int fbix, struct sgx_omaplfb_config *data)
+{
+ if (fbix >= OMAPLFB_NUM_DEV) {
+ WARN(1, "Invalid FB device index");
+ return -ENOENT;
+ }
+ omaplfb_config[fbix] = *data;
+ return 0;
+}
+
+struct sgx_omaplfb_config *sgx_omaplfb_get(unsigned int fbix)
+{
+ if (fbix >= OMAPLFB_NUM_DEV) {
+ WARN(1, "Invalid FB device index");
+ return NULL;
+ }
+ return &omaplfb_config[fbix];
+}
+
+static int __init omap_init_omaplfb(void)
+{
+ return platform_device_register(&omaplfb_plat_device);
+}
+
+arch_initcall(omap_init_omaplfb);
index 50b2831e027d633d2b9d045c919a0dd70e76f64d..32ee0fc7ea54587241f7f3ac22ffc679e0b371de 100644 (file)
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
return v;
}
-EXPORT_SYMBOL(opp_get_voltage);
+EXPORT_SYMBOL_GPL(opp_get_voltage);
/**
* opp_get_freq() - Gets the frequency corresponding to an available opp
return f;
}
-EXPORT_SYMBOL(opp_get_freq);
+EXPORT_SYMBOL_GPL(opp_get_freq);
/**
* opp_get_opp_count() - Get number of opps available in the opp list
return count;
}
-EXPORT_SYMBOL(opp_get_opp_count);
+EXPORT_SYMBOL_GPL(opp_get_opp_count);
/**
* opp_find_freq_exact() - search for an exact frequency
return opp;
}
-EXPORT_SYMBOL(opp_find_freq_exact);
+EXPORT_SYMBOL_GPL(opp_find_freq_exact);
/**
* opp_find_freq_ceil() - Search for an rounded ceil freq
return opp;
}
-EXPORT_SYMBOL(opp_find_freq_ceil);
+EXPORT_SYMBOL_GPL(opp_find_freq_ceil);
/**
* opp_find_freq_floor() - Search for a rounded floor freq
return opp;
}
-EXPORT_SYMBOL(opp_find_freq_floor);
+EXPORT_SYMBOL_GPL(opp_find_freq_floor);
/**
* opp_add() - Add an OPP table from a table definitions
{
return opp_set_availability(dev, freq, true);
}
-EXPORT_SYMBOL(opp_enable);
+EXPORT_SYMBOL_GPL(opp_enable);
/**
* opp_disable() - Disable a specific OPP
{
return opp_set_availability(dev, freq, false);
}
-EXPORT_SYMBOL(opp_disable);
+EXPORT_SYMBOL_GPL(opp_disable);
#ifdef CONFIG_CPU_FREQ
/**
return 0;
}
+EXPORT_SYMBOL_GPL(opp_init_cpufreq_table);
/**
* opp_free_cpufreq_table() - free the cpufreq table
kfree(*table);
*table = NULL;
}
+EXPORT_SYMBOL_GPL(opp_free_cpufreq_table);
#endif /* CONFIG_CPU_FREQ */
/**
return 0;
}
+EXPORT_SYMBOL_GPL(of_init_opp_table);
#endif
diff --git a/drivers/clk/omap/clk.c b/drivers/clk/omap/clk.c
index 5a3c6d9b5a99a26a3076a6c33c35ce13b3817bc9..fdeeeb3b23f7fbf23a1c1895adf6727222c82c61 100644 (file)
--- a/drivers/clk/omap/clk.c
+++ b/drivers/clk/omap/clk.c
* @data: unused
*
* REVISIT: We assume the following:
- * 1. omap clock names end with _ck
- * 2. omap clock names are under 32 characters in length
+ * 1. omap clock names are under 32 characters in length
*/
static struct clk *omap_clk_src_get(struct of_phandle_args *clkspec, void *data)
{
char clk_name[32];
struct device_node *np = clkspec->np;
- snprintf(clk_name, 32, "%s_ck", np->name);
+ snprintf(clk_name, 32, "%s", np->name);
clk = clk_get(NULL, clk_name);
if (IS_ERR(clk))
pr_err("%s: could not get clock %s(%ld)\n", __func__,
index 09f65dc3d2c85397e4147e51291c1b7510450d03..cdc887dc3bf275f2df604ca53d7b37d31a443bbd 100644 (file)
-config DRM_OMAP
+menuconfig DRM_OMAP
tristate "OMAP DRM"
- depends on DRM && !CONFIG_FB_OMAP2
- depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM
- depends on OMAP2_DSS
+ depends on ARCH_OMAP2PLUS && DRM
+ default n
+ help
+ If you want to use the OMAP DRM Display driver and/or DMM/Tiler
+ driver, enable this.
+
+config DRM_OMAP_DISPLAY
+ tristate "OMAP DRM Display Driver"
+ depends on DRM_OMAP && !CONFIG_FB_OMAP2
select DRM_KMS_HELPER
+ select OMAP2_DSS
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
select FB_SYS_FOPS
- default n
+ select DRM_OMAP_DMM_TILER
+ default y
help
DRM display driver for OMAP2/3/4 based boards.
config DRM_OMAP_NUM_CRTCS
+ depends on DRM_OMAP_DISPLAY
int "Number of CRTCs"
range 1 10
default 1 if ARCH_OMAP2 || ARCH_OMAP3
default 2 if ARCH_OMAP4
- depends on DRM_OMAP
help
Select the number of video overlays which can be used as framebuffers.
The remaining overlays are reserved for video.
+config DRM_OMAP_DMM_TILER
+ tristate "OMAP DMM TILER"
+ depends on DRM_OMAP
+ default y
+ help
+ Enable the DMM/Tiler driver for OMAP4+ boards.
index a6bddd858eb8531914f600c3199eb8b693f41d23..24ffdaea9778a6eb6e2c3e128527763fa5ab6cbc 100644 (file)
omap_fbdev.o \
omap_gem.o \
omap_gem_dmabuf.o \
- omap_dmm_tiler.o \
- sita.o
# temporary:
omapdrm-y += omap_gem_helpers.o
-obj-$(CONFIG_DRM_OMAP) += omapdrm.o
+omap-dmm-tiler-y := omap_dmm_tiler.o \
+ sita.o
+
+obj-$(CONFIG_DRM_OMAP_DMM_TILER) += omap-dmm-tiler.o
+obj-$(CONFIG_DRM_OMAP_DISPLAY) += omapdrm.o
index 58bcd6ae0255dace4ae845c366af35cf62be4f20..92345cb91ea5ad944540fecba753c54702d3fe41 100644 (file)
struct list_head alloc_head;
};
+enum mem_type {
+ MEMTYPE_PAGES = 0,
+ MEMTYPE_CARVEOUT,
+};
+
+struct mem_info {
+ enum mem_type type;
+ union {
+ struct page **pages;
+ uint32_t *phys_addrs;
+ };
+};
+
#endif
index fdf8e98fcf36d959b59051f9bb9c35fb51c183ad..8c0a1f873eccd0568177652975cbecbe29210b3d 100644 (file)
* corresponding slot is cleared (ie. dummy_pa is programmed)
*/
static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
- struct page **pages, uint32_t npages, uint32_t roll)
+ struct mem_info *mem, uint32_t npages, uint32_t roll, uint32_t y_offset)
{
dma_addr_t pat_pa = 0;
uint32_t *data;
int n = i + roll;
if (n >= npages)
n -= npages;
- data[i] = (pages && pages[n]) ?
- page_to_phys(pages[n]) : engine->dmm->dummy_pa;
+ if (!mem)
+ data[i] = engine->dmm->dummy_pa;
+ else{
+ if (mem->type == MEMTYPE_PAGES) {
+ data[i] = (mem->pages && mem->pages[n]) ?
+ page_to_phys(mem->pages[n]) :
+ engine->dmm->dummy_pa;
+ } else {
+ data[i] = mem->phys_addrs ? mem->phys_addrs[n] :
+ engine->dmm->dummy_pa;
+ }
+ }
+
}
txn->last_pat = pat;
/*
* DMM programming
*/
-static int fill(struct tcm_area *area, struct page **pages,
- uint32_t npages, uint32_t roll, bool wait)
+static int fill(struct tcm_area *area, struct mem_info *mem, uint32_t npages,
+ uint32_t roll, bool wait)
{
int ret = 0;
struct tcm_area slice, area_s;
struct dmm_txn *txn;
+ u32 y_offset = 0;
txn = dmm_txn_init(omap_dmm, area->tcm);
if (IS_ERR_OR_NULL(txn))
.x1 = slice.p1.x, .y1 = slice.p1.y,
};
- dmm_txn_append(txn, &p_area, pages, npages, roll);
+ dmm_txn_append(txn, &p_area, mem, npages, roll,
+ y_offset);
+
+ if (ret)
+ goto fail;
roll += tcm_sizeof(slice);
}
ret = dmm_txn_commit(txn, wait);
+fail:
return ret;
}
uint32_t npages, uint32_t roll, bool wait)
{
int ret;
+ struct mem_info mem;
+ mem.type = MEMTYPE_PAGES;
+ mem.pages = pages;
- ret = fill(&block->area, pages, npages, roll, wait);
+ ret = fill(&block->area, &mem, npages, roll, wait);
if (ret)
tiler_unpin(block);
return ret;
}
+EXPORT_SYMBOL(tiler_pin);
int tiler_unpin(struct tiler_block *block)
{
return fill(&block->area, NULL, 0, 0, false);
}
+EXPORT_SYMBOL(tiler_unpin);
+
+int tiler_pin_phys(struct tiler_block *block, u32 *phys_addrs,
+ u32 num_pages)
+{
+ int ret;
+ struct mem_info mem;
+
+ mem.type = MEMTYPE_CARVEOUT;
+ mem.phys_addrs = phys_addrs;
+
+ ret = fill(&block->area, &mem, num_pages, 0, true);
+ return ret;
+}
+EXPORT_SYMBOL(tiler_pin_phys);
/*
* Reserve/release
struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w,
uint16_t h, uint16_t align)
{
- struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
+ struct tiler_block *block;
u32 min_align = 128;
int ret;
unsigned long flags;
size_t slot_bytes;
- BUG_ON(!validfmt(fmt));
+ /* check for valid format and overflow for w/h */
+ if (!validfmt(fmt) || !w || !h ||
+ (w > USHRT_MAX - geom[fmt].slot_w) ||
+ (h > USHRT_MAX - geom[fmt].slot_h))
+ return ERR_PTR(-EINVAL);
- /* convert width/height to slots */
- w = DIV_ROUND_UP(w, geom[fmt].slot_w);
- h = DIV_ROUND_UP(h, geom[fmt].slot_h);
+ block = kzalloc(sizeof(*block), GFP_KERNEL);
+ if (!block)
+ return ERR_PTR(-ENOMEM);
+
+ block->fmt = fmt;
+ block->stride = round_up(geom[fmt].cpp * w, PAGE_SIZE);
/* convert alignment to slots */
slot_bytes = geom[fmt].slot_w * geom[fmt].cpp;
align = (align > min_align) ? ALIGN(align, min_align) : min_align;
align /= slot_bytes;
- block->fmt = fmt;
+ /* convert width/height to slots */
+ w = DIV_ROUND_UP(w, geom[fmt].slot_w);
+ h = DIV_ROUND_UP(h, geom[fmt].slot_h);
ret = tcm_reserve_2d(containers[fmt], w, h, align, -1, slot_bytes,
&block->area);
return block;
}
+EXPORT_SYMBOL(tiler_reserve_2d);
struct tiler_block *tiler_reserve_1d(size_t size)
{
return ERR_PTR(-ENOMEM);
block->fmt = TILFMT_PAGE;
+ block->stride = round_up(size, PAGE_SIZE);
if (tcm_reserve_1d(containers[TILFMT_PAGE], num_pages,
&block->area)) {
return block;
}
+EXPORT_SYMBOL(tiler_reserve_1d);
/* note: if you have pin'd pages, you should have already unpin'd first! */
int tiler_release(struct tiler_block *block)
kfree(block);
return ret;
}
+EXPORT_SYMBOL(tiler_release);
/*
* Utils
block->area.p0.x * geom[block->fmt].slot_w,
block->area.p0.y * geom[block->fmt].slot_h);
}
+EXPORT_SYMBOL(tiler_ssptr);
dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient,
uint32_t x, uint32_t y)
void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h)
{
- BUG_ON(!validfmt(fmt));
+ BUG_ON(!validfmt(fmt) || fmt == TILFMT_PAGE);
*w = round_up(*w, geom[fmt].slot_w);
*h = round_up(*h, geom[fmt].slot_h);
}
+EXPORT_SYMBOL(tiler_align);
uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient)
{
else
return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
}
+EXPORT_SYMBOL(tiler_stride);
size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h)
{
tiler_align(fmt, &w, &h);
return geom[fmt].cpp * w * h;
}
+EXPORT_SYMBOL(tiler_size);
size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h)
{
- BUG_ON(!validfmt(fmt));
+ BUG_ON(!validfmt(fmt) || fmt == TILFMT_PAGE);
return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h;
}
+EXPORT_SYMBOL(tiler_vsize);
bool dmm_is_available(void)
{
return omap_dmm ? true : false;
}
+EXPORT_SYMBOL(dmm_is_available);
+
+/* rotation APIs */
+bool is_tiler_addr(uint32_t phys)
+{
+ return phys >= TILVIEW_8BIT && phys < TILVIEW_END;
+}
+EXPORT_SYMBOL(is_tiler_addr);
+
+int tiler_get_fmt(uint32_t phys, enum tiler_fmt *fmt)
+{
+ if (!is_tiler_addr(phys))
+ return 0;
+
+ *fmt = TILER_FMT(phys);
+ return 1;
+}
+EXPORT_SYMBOL(tiler_get_fmt);
+
+void tilview_create(struct tiler_view_t *view, u32 phys, u32 width, u32 height)
+{
+ enum tiler_fmt fmt = TILER_FMT(view->tsptr);
+ BUG_ON(!is_tiler_addr(phys));
+
+ view->tsptr = phys & ~MASK_VIEW;
+ view->bpp = geom[TILER_FMT(phys)].cpp;
+ view->width = width;
+ view->height = height;
+ view->h_inc = view->bpp;
+ view->v_inc = tiler_stride(fmt, view->tsptr);
+}
+EXPORT_SYMBOL(tilview_create);
+
+void tilview_get(struct tiler_view_t *view, struct tiler_block *blk)
+{
+ enum tiler_fmt fmt = TILER_FMT(view->tsptr);
+
+ view->tsptr = tiler_ssptr(blk);
+ view->bpp = geom[TILER_FMT(view->tsptr)].cpp;
+ view->width = blk->width;
+ view->height = blk->height;
+ view->h_inc = view->bpp;
+ view->v_inc = tiler_stride(fmt, view->tsptr);
+}
+EXPORT_SYMBOL(tilview_get);
+
+int tilview_crop(struct tiler_view_t *view, u32 left, u32 top, u32 width,
+ u32 height)
+{
+ /* check for valid crop */
+ if (left + width < left || left + width > view->width ||
+ top + height < top || top + height > view->height)
+ return -EINVAL;
+
+ view->tsptr += left * view->h_inc + top * view->v_inc;
+ view->width = width;
+ view->height = height;
+ return 0;
+}
+EXPORT_SYMBOL(tilview_crop);
static int omap_dmm_remove(struct platform_device *dev)
{
return 0;
}
+EXPORT_SYMBOL(tiler_map_show);
#endif
#ifdef CONFIG_PM
},
};
+static int __init omap_dmm_init(void)
+{
+ return platform_driver_register(&omap_dmm_driver);
+}
+
+static void __exit omap_dmm_exit(void)
+{
+ platform_driver_unregister(&omap_dmm_driver);
+}
+
+#ifdef MODULE
+module_init(omap_dmm_init);
+module_exit(omap_dmm_exit);
+#else
+core_initcall(omap_dmm_init);
+#endif
+
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Andy Gross <andy.gross@ti.com>");
MODULE_DESCRIPTION("OMAP DMM/Tiler Driver");
index 4fdd61e54bd28abce8aef29c03e62c6596d31aab..68eec2a3065ec5da78208664c4946e6e2cfd6a97 100644 (file)
struct list_head alloc_node; /* node for global block list */
struct tcm_area area; /* area */
enum tiler_fmt fmt; /* format */
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride; /* 2D: length of one line in pages
+ 1D: length of buffer rounded to
+ PAGE_SIZE */
};
/* bits representing the same slot in DMM-TILER hw-block */
#define SHIFT_ACC_MODE 27
#define MASK_ACC_MODE 3
+#define VIEW_SIZE (1u << (CONT_WIDTH_BITS + CONT_HEIGHT_BITS))
+#define VIEW_MASK (VIEW_SIZE - 1u)
+
+#define MASK_VIEW (MASK_X_INVERT | MASK_Y_INVERT | MASK_XY_FLIP)
+
+#define TILER_FMT(x) ((enum tiler_fmt) \
+ ((x >> SHIFT_ACC_MODE) & MASK_ACC_MODE))
+
#define MASK(bits) ((1 << (bits)) - 1)
#define TILVIEW_8BIT 0x60000000u
/* pin/unpin */
int tiler_pin(struct tiler_block *block, struct page **pages,
uint32_t npages, uint32_t roll, bool wait);
+int tiler_pin_phys(struct tiler_block *block, u32 *phys_addrs, u32 num_pages);
int tiler_unpin(struct tiler_block *block);
/* reserve/release */
void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h);
bool dmm_is_available(void);
+/* rotation */
+/* tiler (image/video frame) view */
+struct tiler_view_t {
+ uint32_t tsptr; /* tiler space addr */
+ uint32_t width; /* width */
+ uint32_t height; /* height */
+ uint32_t bpp; /* bytes per pixel */
+ int h_inc; /* horizontal increment */
+ int v_inc; /* vertical increment */
+};
+
+bool is_tiler_addr(uint32_t phys);
+int tiler_get_fmt(uint32_t phys, enum tiler_fmt *fmt);
+void tilview_create(struct tiler_view_t *view, u32 phys, u32 width, u32 height);
+void tilview_get(struct tiler_view_t *view, struct tiler_block *blk);
+int tilview_crop(struct tiler_view_t *view, u32 left, u32 top, u32 width,
+ u32 height);
+int tilview_rotate(struct tiler_view_t *view, int rotation);
+int tilview_flip(struct tiler_view_t *view, bool flip_x, bool flip_y);
+
extern struct platform_driver omap_dmm_driver;
/* GEM bo flags -> tiler fmt */
index fa38267a46f05bd232c179f6c322c57d074f29c3..29e98c26fca8cc577f15bada54bb74ac12bccb71 100644 (file)
{
DBG("");
drm_platform_exit(&omap_drm_driver, device);
-
- platform_driver_unregister(&omap_dmm_driver);
return 0;
}
static int __init omap_drm_init(void)
{
DBG("init");
- if (platform_driver_register(&omap_dmm_driver)) {
- /* we can continue on without DMM.. so not fatal */
- dev_err(NULL, "DMM registration failed\n");
- }
return platform_driver_register(&pdev);
}
index b5bfdb47fd0957a55ce1780d928f06b3ed2e2f72..0587741e0e257daef868893802c8929ba228192e 100644 (file)
--- a/drivers/gpu/ion/Kconfig
+++ b/drivers/gpu/ion/Kconfig
help
Choose this option if you wish to use ion on an nVidia Tegra.
+config ION_OMAP
+ tristate "Ion for OMAP"
+ depends on (ARCH_OMAP5 || ARCH_OMAP4) && ION && DRM_OMAP
+ help
+ Choose this option if you wish to use ion on OMAP4/5.
+ This option shall be chosen if ion carveout is required
+ for OMAP4/5. The corresponding board file shall also have
+ the ion carveout implementation.
index 306fff970de49c04b6ebe032362b14d5e01123e8..63ab1472c3ec44c95ee743b6299d2706e31e140a 100644 (file)
--- a/drivers/gpu/ion/Makefile
+++ b/drivers/gpu/ion/Makefile
obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \
ion_carveout_heap.o ion_chunk_heap.o
obj-$(CONFIG_ION_TEGRA) += tegra/
+obj-$(CONFIG_ION_OMAP) += omap/
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 34264edc6ee6fc1e5d25ce00c4eb488e879a0d6a..8f477880f040fe5985617acedd617bce7c988a7c 100644 (file)
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
#include "ion_priv.h"
-/**
- * struct ion_device - the metadata of the ion device node
- * @dev: the actual misc device
- * @buffers: an rb tree of all the existing buffers
- * @buffer_lock: lock protecting the tree of buffers
- * @lock: rwsem protecting the tree of heaps and clients
- * @heaps: list of all the heaps in the system
- * @user_clients: list of all the clients created from userspace
- */
-struct ion_device {
- struct miscdevice dev;
- struct rb_root buffers;
- struct mutex buffer_lock;
- struct rw_semaphore lock;
- struct plist_head heaps;
- long (*custom_ioctl) (struct ion_client *client, unsigned int cmd,
- unsigned long arg);
- struct rb_root clients;
- struct dentry *debug_root;
-};
-
-/**
- * struct ion_client - a process/hw block local address space
- * @node: node in the tree of all clients
- * @dev: backpointer to ion device
- * @handles: an rb tree of all the handles in this client
- * @lock: lock protecting the tree of handles
- * @name: used for debugging
- * @task: used for debugging
- *
- * A client represents a list of buffers this client may access.
- * The mutex stored here is used to protect both handles tree
- * as well as the handles themselves, and should be held while modifying either.
- */
-struct ion_client {
- struct rb_node node;
- struct ion_device *dev;
- struct rb_root handles;
- struct mutex lock;
- const char *name;
- struct task_struct *task;
- pid_t pid;
- struct dentry *debug_root;
-};
-
-/**
- * ion_handle - a client local reference to a buffer
- * @ref: reference count
- * @client: back pointer to the client the buffer resides in
- * @buffer: pointer to the buffer
- * @node: node in the client's handle rbtree
- * @kmap_cnt: count of times this client has mapped to kernel
- * @dmap_cnt: count of times this client has mapped for dma
- *
- * Modifications to node, map_cnt or mapping should be protected by the
- * lock in the client. Other fields are never changed after initialization.
- */
-struct ion_handle {
- struct kref ref;
- struct ion_client *client;
- struct ion_buffer *buffer;
- struct rb_node node;
- unsigned int kmap_cnt;
-};
-
bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer)
{
return ((buffer->flags & ION_FLAG_CACHED) &&
index c116921651948851c74a2cc11a3faa2715c393ee..015c7f7b635d812e137c42fcab69e5e76d1bdd7d 100644 (file)
#include <linux/sched.h>
#include <linux/shrinker.h>
#include <linux/types.h>
+#include <linux/miscdevice.h>
+
+
+
+/**
+ * struct ion_device - the metadata of the ion device node
+ * @dev: the actual misc device
+ * @buffers: an rb tree of all the existing buffers
+ * @buffer_lock: lock protecting the tree of buffers
+ * @lock: rwsem protecting the tree of heaps and clients
+ * @heaps: list of all the heaps in the system
+ * @user_clients: list of all the clients created from userspace
+ */
+struct ion_device {
+ struct miscdevice dev;
+ struct rb_root buffers;
+ struct mutex buffer_lock;
+ struct rw_semaphore lock;
+ struct plist_head heaps;
+ long (*custom_ioctl) (struct ion_client *client, unsigned int cmd,
+ unsigned long arg);
+ struct rb_root clients;
+ struct dentry *debug_root;
+};
+
+/**
+ * struct ion_client - a process/hw block local address space
+ * @node: node in the tree of all clients
+ * @dev: backpointer to ion device
+ * @handles: an rb tree of all the handles in this client
+ * @lock: lock protecting the tree of handles
+ * @name: used for debugging
+ * @task: used for debugging
+ *
+ * A client represents a list of buffers this client may access.
+ * The mutex stored here is used to protect both handles tree
+ * as well as the handles themselves, and should be held while modifying either.
+ */
+struct ion_client {
+ struct rb_node node;
+ struct ion_device *dev;
+ struct rb_root handles;
+ struct mutex lock;
+ const char *name;
+ struct task_struct *task;
+ pid_t pid;
+ struct dentry *debug_root;
+};
+
+/**
+ * ion_handle - a client local reference to a buffer
+ * @ref: reference count
+ * @client: back pointer to the client the buffer resides in
+ * @buffer: pointer to the buffer
+ * @node: node in the client's handle rbtree
+ * @kmap_cnt: count of times this client has mapped to kernel
+ * @dmap_cnt: count of times this client has mapped for dma
+ *
+ * Modifications to node, map_cnt or mapping should be protected by the
+ * lock in the client. Other fields are never changed after initialization.
+ */
+struct ion_handle {
+ struct kref ref;
+ struct ion_client *client;
+ struct ion_buffer *buffer;
+ struct rb_node node;
+ unsigned int kmap_cnt;
+};
+
struct ion_buffer *ion_handle_buffer(struct ion_handle *handle);
diff --git a/drivers/gpu/ion/omap/Makefile b/drivers/gpu/ion/omap/Makefile
--- /dev/null
@@ -0,0 +1 @@
+obj-y += omap_tiler_heap.o omap_ion.o
diff --git a/drivers/gpu/ion/omap/omap_ion.c b/drivers/gpu/ion/omap/omap_ion.c
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * drivers/gpu/omap/omap_ion.c
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include "../ion_priv.h"
+#include "omap_ion_priv.h"
+#include <linux/module.h>
+#include <linux/of.h>
+
+
+struct ion_device *omap_ion_device;
+EXPORT_SYMBOL(omap_ion_device);
+
+static int num_heaps;
+static struct ion_heap **heaps;
+static struct ion_heap *tiler_heap;
+static struct ion_heap *nonsecure_tiler_heap;
+
+static struct ion_platform_data omap_ion_data = {
+ .nr = 5,
+ .heaps = {
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .id = OMAP_ION_HEAP_SECURE_INPUT,
+ .name = "secure_input",
+ },
+ { .type = OMAP_ION_HEAP_TYPE_TILER,
+ .id = OMAP_ION_HEAP_TILER,
+ .name = "tiler",
+ },
+ {
+ .type = OMAP_ION_HEAP_TYPE_TILER,
+ .id = OMAP_ION_HEAP_NONSECURE_TILER,
+ .name = "nonsecure_tiler",
+ },
+ {
+ .type = ION_HEAP_TYPE_SYSTEM,
+ .id = OMAP_ION_HEAP_SYSTEM,
+ .name = "system",
+ },
+ {
+ .type = OMAP_ION_HEAP_TYPE_TILER_RESERVATION,
+ .id = OMAP_ION_HEAP_TILER_RESERVATION,
+ .name = "tiler_reservation",
+ },
+ },
+};
+
+
+int omap_ion_tiler_alloc(struct ion_client *client,
+ struct omap_ion_tiler_alloc_data *data)
+{
+ return omap_tiler_alloc(tiler_heap, client, data);
+}
+EXPORT_SYMBOL(omap_ion_tiler_alloc);
+
+int omap_ion_nonsecure_tiler_alloc(struct ion_client *client,
+ struct omap_ion_tiler_alloc_data *data)
+{
+ if (!nonsecure_tiler_heap)
+ return -ENOMEM;
+ return omap_tiler_alloc(nonsecure_tiler_heap, client, data);
+}
+EXPORT_SYMBOL(omap_ion_nonsecure_tiler_alloc);
+
+static long omap_ion_ioctl(struct ion_client *client, unsigned int cmd,
+ unsigned long arg)
+{
+ switch (cmd) {
+ case OMAP_ION_TILER_ALLOC:
+ {
+ struct omap_ion_tiler_alloc_data data;
+ int ret;
+
+ if (!tiler_heap) {
+ pr_err("%s: Tiler heap requested but no tiler heap "
+ "exists on this platform\n", __func__);
+ return -EINVAL;
+ }
+ if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
+ return -EFAULT;
+ ret = omap_ion_tiler_alloc(client, &data);
+ if (ret)
+ return ret;
+ if (copy_to_user((void __user *)arg, &data,
+ sizeof(data)))
+ return -EFAULT;
+ break;
+ }
+ default:
+ pr_err("%s: Unknown custom ioctl\n", __func__);
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int omap_ion_probe(struct platform_device *pdev)
+{
+ int err;
+ int i;
+ struct device_node *node = pdev->dev.of_node;
+ uint omap_ion_heap_secure_input_base = 0;
+ uint omap_ion_heap_tiler_base = 0;
+ uint omap_ion_heap_nonsecure_tiler_base = 0;
+ uint omap_ion_heap_secure_input_size = 0;
+ uint omap_ion_heap_tiler_size = 0;
+ uint omap_ion_heap_nonsecure_tiler_size = 0;
+
+ omap_ion_device = ion_device_create(omap_ion_ioctl);
+ if (IS_ERR_OR_NULL(omap_ion_device)) {
+ kfree(heaps);
+ return PTR_ERR(omap_ion_device);
+ }
+
+ if (node) {
+ of_property_read_u32(node, "ti,omap_ion_heap_secure_input_base",
+ &omap_ion_heap_secure_input_base);
+ of_property_read_u32(node, "ti,omap_ion_heap_tiler_base",
+ &omap_ion_heap_tiler_size);
+ of_property_read_u32(node, "ti,omap_ion_heap_nonsecure_tiler_base",
+ &omap_ion_heap_nonsecure_tiler_base);
+
+ of_property_read_u32(node, "ti,omap_ion_heap_secure_input_size",
+ &omap_ion_heap_secure_input_size);
+ of_property_read_u32(node, "ti,omap_ion_heap_tiler_size",
+ &omap_ion_heap_tiler_size);
+ of_property_read_u32(node, "ti,omap_ion_heap_nonsecure_tiler_size",
+ &omap_ion_heap_nonsecure_tiler_size);
+ }
+
+ num_heaps = omap_ion_data.nr;
+
+ heaps = kzalloc(sizeof(struct ion_heap *)*num_heaps, GFP_KERNEL);
+
+
+ for (i = 0; i < num_heaps; i++) {
+ struct ion_platform_heap *heap_data = &omap_ion_data.heaps[i];
+ if (heap_data->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER) {
+ if (heap_data->id == OMAP_ION_HEAP_NONSECURE_TILER) {
+ heap_data->base = omap_ion_heap_nonsecure_tiler_base;
+ heap_data->size = omap_ion_heap_nonsecure_tiler_size;
+ } else {
+ heap_data->base = omap_ion_heap_tiler_base;
+ heap_data->size = omap_ion_heap_tiler_size;
+ }
+ } else if (heap_data->type ==
+ ION_HEAP_TYPE_CARVEOUT && heap_data->id == OMAP_ION_HEAP_SECURE_INPUT) {
+ heap_data->base = omap_ion_heap_secure_input_base;
+ heap_data->size = omap_ion_heap_secure_input_size;
+ }
+ }
+
+ /* create the heaps as specified in the board file */
+ for (i = 0; i < num_heaps; i++) {
+ struct ion_platform_heap *heap_data = &omap_ion_data.heaps[i];
+ if (heap_data->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER) {
+ heaps[i] = omap_tiler_heap_create(heap_data);
+ if (heap_data->id == OMAP_ION_HEAP_NONSECURE_TILER)
+ nonsecure_tiler_heap = heaps[i];
+ else
+ tiler_heap = heaps[i];
+ } else if (heap_data->type ==
+ (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER_RESERVATION) {
+ heaps[i] = omap_tiler_heap_create(heap_data);
+ } else {
+ heap_data->size = omap_ion_heap_secure_input_size;
+ heaps[i] = ion_heap_create(heap_data);
+ }
+ if (IS_ERR_OR_NULL(heaps[i])) {
+ err = PTR_ERR(heaps[i]);
+ goto err;
+ }
+ ion_device_add_heap(omap_ion_device, heaps[i]);
+ pr_info("%s: adding heap %s of type %d with %lx@%x\n",
+ __func__, heap_data->name, heap_data->type,
+ heap_data->base, heap_data->size);
+
+ }
+
+ platform_set_drvdata(pdev, omap_ion_device);
+ return 0;
+err:
+ for (i = 0; i < num_heaps; i++) {
+ if (heaps[i]) {
+ if (heaps[i]->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER)
+ omap_tiler_heap_destroy(heaps[i]);
+ else
+ ion_heap_destroy(heaps[i]);
+ }
+ }
+ kfree(heaps);
+ return err;
+}
+
+static int omap_ion_remove(struct platform_device *pdev)
+{
+ struct ion_device *idev = platform_get_drvdata(pdev);
+ int i;
+
+ ion_device_destroy(idev);
+ for (i = 0; i < num_heaps; i++)
+ if (heaps[i]->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER)
+ omap_tiler_heap_destroy(heaps[i]);
+ else
+ ion_heap_destroy(heaps[i]);
+ kfree(heaps);
+ return 0;
+}
+
+static void (*export_fd_to_ion_handles)(int fd,
+ struct ion_client **client,
+ struct ion_handle **handles,
+ int *num_handles);
+
+void omap_ion_register_pvr_export(void *pvr_export_fd)
+{
+ export_fd_to_ion_handles = pvr_export_fd;
+}
+EXPORT_SYMBOL(omap_ion_register_pvr_export);
+
+int omap_ion_share_fd_to_buffers(int fd, struct ion_buffer **buffers,
+ int *num_handles)
+{
+ struct ion_handle **handles;
+ struct ion_client *client;
+ int i = 0, ret = 0;
+
+ handles = kzalloc(*num_handles * sizeof(struct ion_handle *),
+ GFP_KERNEL);
+ if (!handles)
+ return -ENOMEM;
+
+ if (export_fd_to_ion_handles) {
+ export_fd_to_ion_handles(fd,
+ &client,
+ handles,
+ num_handles);
+ } else {
+ pr_err("%s: export_fd_to_ion_handles not initialized",
+ __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ for (i = 0; i < *num_handles; i++) {
+ if (handles[i])
+ buffers[i] = ion_share_dma_buf(client, handles[i]);
+ }
+
+exit:
+ kfree(handles);
+ return ret;
+}
+EXPORT_SYMBOL(omap_ion_share_fd_to_buffers);
+
+static const struct of_device_id omap_ion_of_match[] = {
+ {.compatible = "ti,ion-omap", },
+ { },
+};
+
+
+static struct platform_driver ion_driver = {
+ .probe = omap_ion_probe,
+ .remove = omap_ion_remove,
+ .driver = { .name = "ion-omap",
+ .of_match_table = omap_ion_of_match
+ }
+};
+
+static int __init ion_init(void)
+{
+ return platform_driver_register(&ion_driver);
+}
+
+static void __exit ion_exit(void)
+{
+ platform_driver_unregister(&ion_driver);
+}
+
+module_init(ion_init);
+module_exit(ion_exit);
diff --git a/drivers/gpu/ion/omap/omap_ion_priv.h b/drivers/gpu/ion/omap/omap_ion_priv.h
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * include/linux/omap/omap_ion_priv.h
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_OMAP_ION_PRIV_H
+#define _LINUX_OMAP_ION_PRIV_H
+
+#include <linux/types.h>
+
+int omap_tiler_alloc(struct ion_heap *heap,
+ struct ion_client *client,
+ struct omap_ion_tiler_alloc_data *data);
+struct ion_heap *omap_tiler_heap_create(struct ion_platform_heap *heap_data);
+void omap_tiler_heap_destroy(struct ion_heap *heap);
+
+#endif /* _LINUX_OMAP_ION_PRIV_H */
diff --git a/drivers/gpu/ion/omap/omap_tiler_heap.c b/drivers/gpu/ion/omap/omap_tiler_heap.c
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ * drivers/gpu/ion/omap_tiler_heap.c
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/genalloc.h>
+#include <linux/io.h>
+#include <linux/ion.h>
+#include <linux/mm.h>
+#include <linux/omap_ion.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include "../../../drivers/gpu/drm/omapdrm/omap_dmm_tiler.h"
+#include <asm/mach/map.h>
+#include <asm/page.h>
+#include "../../../arch/arm/mach-omap2/soc.h"
+
+
+
+#include "../ion_priv.h"
+#include "omap_ion_priv.h"
+#include <asm/cacheflush.h>
+
+struct omap_ion_heap {
+ struct ion_heap heap;
+ struct gen_pool *pool;
+ ion_phys_addr_t base;
+};
+
+struct omap_tiler_info {
+ struct tiler_block *tiler_handle; /* handle of the allocation
+ intiler */
+ bool lump; /* true for a single lump allocation */
+ u32 n_phys_pages; /* number of physical pages */
+ u32 *phys_addrs; /* array addrs of pages */
+ u32 n_tiler_pages; /* number of tiler pages */
+ u32 *tiler_addrs; /* array of addrs of tiler pages */
+ int fmt; /* tiler buffer format */
+ u32 tiler_start; /* start addr in tiler -- if not page
+ aligned this may not equal the
+ first entry onf tiler_addrs */
+ u32 vsize; /* virtual stride of buffer */
+ u32 vstride; /* virtual size of buffer */
+ u32 phys_stride; /* Physical stride of the buffer */
+};
+
+static int omap_tiler_heap_allocate(struct ion_heap *heap,
+ struct ion_buffer *buffer,
+ unsigned long size, unsigned long align,
+ unsigned long flags)
+{
+ /* This means the buffer is already allocated and populated, we're getting here because
+ * of dummy handle creation, so simply return*/
+ if (size == 0) {
+ /*
+ * Store the pointer to struct omap_tiler_info * into buffer here.
+ * This will be used later on inside map_dma function to create
+ * the sg list for tiler buffer
+ */
+ buffer->priv_virt = (void *)flags;
+ return 0;
+ }
+
+ pr_err("%s: This should never be called directly -- use the "
+ "OMAP_ION_TILER_ALLOC flag to the ION_IOC_CUSTOM "
+ "instead\n", __func__);
+ return -EINVAL;
+}
+
+static int omap_tiler_alloc_carveout(struct ion_heap *heap,
+ struct omap_tiler_info *info)
+{
+ struct omap_ion_heap *omap_heap = (struct omap_ion_heap *)heap;
+ int i;
+ int ret;
+ ion_phys_addr_t addr;
+
+ addr = gen_pool_alloc(omap_heap->pool, info->n_phys_pages * PAGE_SIZE);
+ if (addr) {
+ info->lump = true;
+ for (i = 0; i < info->n_phys_pages; i++)
+ info->phys_addrs[i] = addr + i * PAGE_SIZE;
+ return 0;
+ }
+
+ for (i = 0; i < info->n_phys_pages; i++) {
+ addr = gen_pool_alloc(omap_heap->pool, PAGE_SIZE);
+
+ if (addr == 0) {
+ ret = -ENOMEM;
+ pr_err("%s: failed to allocate pages to back "
+ "tiler address space\n", __func__);
+ goto err;
+ }
+ info->phys_addrs[i] = addr;
+ }
+ return 0;
+
+err:
+ for (i -= 1; i >= 0; i--)
+ gen_pool_free(omap_heap->pool, info->phys_addrs[i], PAGE_SIZE);
+ return ret;
+}
+
+static void omap_tiler_free_carveout(struct ion_heap *heap,
+ struct omap_tiler_info *info)
+{
+ struct omap_ion_heap *omap_heap = (struct omap_ion_heap *)heap;
+ int i;
+
+ if (info->lump) {
+ gen_pool_free(omap_heap->pool,
+ info->phys_addrs[0],
+ info->n_phys_pages * PAGE_SIZE);
+ return;
+ }
+
+ for (i = 0; i < info->n_phys_pages; i++)
+ gen_pool_free(omap_heap->pool, info->phys_addrs[i], PAGE_SIZE);
+}
+
+int omap_tiler_alloc(struct ion_heap *heap,
+ struct ion_client *client,
+ struct omap_ion_tiler_alloc_data *data)
+{
+ struct ion_handle *handle;
+ struct ion_buffer *buffer;
+ struct omap_tiler_info *info = NULL;
+ u32 n_phys_pages;
+ u32 n_tiler_pages;
+ int i = 0, ret;
+ uint32_t remainder;
+ dma_addr_t ssptr;
+
+ if (data->fmt == TILFMT_PAGE && data->h != 1) {
+ pr_err("%s: Page mode (1D) allocations must have a height of "
+ "one\n", __func__);
+ return -EINVAL;
+ }
+
+ if (data->fmt == TILFMT_PAGE) {
+ /* calculate required pages the usual way */
+ n_phys_pages = round_up(data->w, PAGE_SIZE) >> PAGE_SHIFT;
+ n_tiler_pages = n_phys_pages;
+ } else {
+ /* call APIs to calculate 2D buffer page requirements */
+ n_phys_pages = tiler_size(data->fmt, data->w, data->h) >>
+ PAGE_SHIFT;
+ n_tiler_pages = tiler_vsize(data->fmt, data->w, data->h) >>
+ PAGE_SHIFT;
+ }
+
+ info = kzalloc(sizeof(struct omap_tiler_info) +
+ sizeof(u32) * n_phys_pages +
+ sizeof(u32) * n_tiler_pages, GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->n_phys_pages = n_phys_pages;
+ info->n_tiler_pages = n_tiler_pages;
+ info->phys_addrs = (u32 *)(info + 1);
+ info->tiler_addrs = info->phys_addrs + n_phys_pages;
+ info->fmt = data->fmt;
+
+ /* Allocate tiler space
+ FIXME: we only support PAGE_SIZE alignment right now. */
+ if (data->fmt == TILFMT_PAGE)
+ info->tiler_handle = tiler_reserve_1d(data->w);
+ else
+ info->tiler_handle = tiler_reserve_2d(data->fmt, data->w,
+ data->h, PAGE_SIZE);
+
+ info->tiler_handle->width = data->w;
+ info->tiler_handle->height = data->h;
+
+ if (IS_ERR_OR_NULL(info->tiler_handle)) {
+ ret = PTR_ERR(info->tiler_handle);
+ pr_err("%s: failure to allocate address space from tiler\n",
+ __func__);
+ goto err_got_mem;
+ }
+
+ /* get physical address of tiler buffer */
+ info->tiler_start = tiler_ssptr(info->tiler_handle);
+
+ /* fill in tiler pages by using ssptr and stride */
+ info->vstride = info->tiler_handle->stride;
+ info->vsize = n_tiler_pages << PAGE_SHIFT;
+ info->phys_stride = (data->fmt == TILFMT_PAGE) ? info->vstride :
+ tiler_stride(data->fmt, 0);
+ ssptr = info->tiler_start;
+ remainder = info->vstride;
+
+ for (i = 0; i < n_tiler_pages; i++) {
+ info->tiler_addrs[i] = PAGE_ALIGN(ssptr);
+ ssptr += PAGE_SIZE;
+ remainder -= PAGE_SIZE;
+
+ /* see if we are done with this line. If so, go to the next
+ line */
+ if (!remainder) {
+ remainder = info->vstride;
+ ssptr += info->phys_stride - info->vstride;
+ }
+ }
+
+ if ((heap->id == OMAP_ION_HEAP_TILER) ||
+ (heap->id == OMAP_ION_HEAP_NONSECURE_TILER)) {
+ ret = omap_tiler_alloc_carveout(heap, info);
+ if (ret)
+ goto err_got_tiler;
+
+ ret = tiler_pin_phys(info->tiler_handle, info->phys_addrs,
+ info->n_phys_pages);
+
+ if (ret) {
+ pr_err("%s: failure to pin pages to tiler\n",
+ __func__);
+ goto err_got_carveout;
+ }
+ }
+
+ data->stride = info->vstride;
+
+ /* create an ion handle for the allocation */
+ handle = ion_alloc(client, -1, 0, 1 << OMAP_ION_HEAP_TILER, (unsigned int) info);
+ if (IS_ERR_OR_NULL(handle)) {
+ ret = PTR_ERR(handle);
+ pr_err("%s: failure to allocate handle to manage "
+ "tiler allocation\n", __func__);
+ goto err;
+ }
+
+ buffer = ion_handle_buffer(handle);
+ buffer->size = n_tiler_pages * PAGE_SIZE;
+ data->handle = handle;
+ data->offset = (size_t)(info->tiler_start & ~PAGE_MASK);
+
+ return 0;
+
+err:
+ tiler_unpin(info->tiler_handle);
+err_got_carveout:
+ if ((heap->id == OMAP_ION_HEAP_TILER) ||
+ (heap->id == OMAP_ION_HEAP_NONSECURE_TILER)) {
+ omap_tiler_free_carveout(heap, info);
+ }
+err_got_tiler:
+ tiler_release(info->tiler_handle);
+err_got_mem:
+ kfree(info);
+ return ret;
+}
+
+static void omap_tiler_heap_free(struct ion_buffer *buffer)
+{
+ struct omap_tiler_info *info = buffer->priv_virt;
+
+ tiler_unpin(info->tiler_handle);
+ tiler_release(info->tiler_handle);
+
+ if ((buffer->heap->id == OMAP_ION_HEAP_TILER) ||
+ (buffer->heap->id == OMAP_ION_HEAP_NONSECURE_TILER))
+ omap_tiler_free_carveout(buffer->heap, info);
+
+ kfree(info);
+}
+
+static int omap_tiler_phys(struct ion_heap *heap,
+ struct ion_buffer *buffer,
+ ion_phys_addr_t *addr, size_t *len)
+{
+ struct omap_tiler_info *info = buffer->priv_virt;
+
+ *addr = info->tiler_start;
+ *len = buffer->size;
+ return 0;
+}
+
+int omap_tiler_pages(struct ion_client *client, struct ion_handle *handle,
+ int *n, u32 **tiler_addrs)
+{
+ ion_phys_addr_t addr;
+ size_t len;
+ int ret;
+ struct omap_tiler_info *info = ion_handle_buffer(handle)->priv_virt;
+
+ /* validate that the handle exists in this client */
+ ret = ion_phys(client, handle, &addr, &len);
+ if (ret)
+ return ret;
+
+ *n = info->n_tiler_pages;
+ *tiler_addrs = info->tiler_addrs;
+ return 0;
+}
+EXPORT_SYMBOL(omap_tiler_pages);
+
+int omap_tiler_vinfo(struct ion_client *client, struct ion_handle *handle,
+ unsigned int *vstride, unsigned int *vsize)
+{
+ struct omap_tiler_info *info = ion_handle_buffer(handle)->priv_virt;
+
+ *vstride = info->vstride;
+ *vsize = info->vsize;
+
+ return 0;
+}
+
+static int omap_tiler_heap_map_user(struct ion_heap *heap,
+ struct ion_buffer *buffer, struct vm_area_struct *vma)
+{
+ struct omap_tiler_info *info = buffer->priv_virt;
+ unsigned long addr = vma->vm_start;
+ u32 vma_pages = (vma->vm_end - vma->vm_start) / PAGE_SIZE;
+ int n_pages = min(vma_pages, info->n_tiler_pages);
+ int i, ret = 0;
+ pgprot_t vm_page_prot;
+
+ /* Use writecombined mappings unless on OMAP5. If OMAP5, use
+ shared device due to h/w issue. */
+ if (soc_is_omap54xx())
+ vm_page_prot = __pgprot_modify(vma->vm_page_prot, L_PTE_MT_MASK,
+ L_PTE_MT_DEV_SHARED);
+ else
+ vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ if (TILER_PIXEL_FMT_PAGE == info->fmt) {
+ /* Since 1D buffer is linear, map whole buffer in one shot */
+ ret = remap_pfn_range(vma, addr,
+ __phys_to_pfn(info->tiler_addrs[0]),
+ (vma->vm_end - vma->vm_start),
+ vm_page_prot);
+ } else {
+ for (i = vma->vm_pgoff; i < n_pages; i++, addr += PAGE_SIZE) {
+ ret = remap_pfn_range(vma, addr,
+ __phys_to_pfn(info->tiler_addrs[i]),
+ PAGE_SIZE,
+ vm_page_prot);
+ if (ret)
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static struct scatterlist *sg_alloc(unsigned int nents, gfp_t gfp_mask)
+{
+ return kmalloc(nents * sizeof(struct scatterlist), gfp_mask);
+}
+
+static void sg_free(struct scatterlist *sg, unsigned int nents)
+{
+ kfree(sg);
+}
+
+
+
+struct sg_table *omap_tiler_heap_map_dma(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ int ret, i;
+ struct sg_table *table = NULL;
+ struct scatterlist *sg;
+ struct omap_tiler_info *info = NULL;
+ static phys_addr_t paddr;
+
+
+ info = buffer->priv_virt;
+
+ if(!info)
+ return table;
+
+ table = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
+ if (!table)
+ return ERR_PTR(-ENOMEM);
+ /* sg_alloc_table can only allocate multi-page scatter-gather list tables
+ * if the architecture supports scatter-gather lists chaining. ARM doesn't
+ * fit in that category.
+ * Use __sg_alloc_table instead of sg_alloc_table and allocate all entries
+ * in one go. Otherwise trying to allocate beyond SG_MAX_SINGLE_ALLOC
+ * when height > SG_MAX_SINGLE_ALLOC will hit a BUG_ON in __sg_alloc_table.
+ */
+
+ ret = __sg_alloc_table(table, info->tiler_handle->height, -1, GFP_KERNEL, sg_alloc);
+ if (ret) {
+ kfree(table);
+ return ERR_PTR(ret);
+ }
+
+ sg = table->sgl;
+ for (i = 0; i < info->tiler_handle->height; i++) {
+ paddr = info->tiler_start+ (i * info->phys_stride);
+ sg_set_page(sg, phys_to_page(paddr), info->vstride, 0);
+ sg = sg_next(sg);
+ }
+
+ return table;
+}
+
+void omap_tiler_heap_unmap_dma(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ __sg_free_table(buffer->sg_table, -1, sg_free);
+}
+
+void *ion_tiler_heap_map_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ /* todo: Need to see how to implement this api. Seems like it is
+ * mandatory to implement in new ION
+ */
+ return NULL;
+}
+
+void ion_tiler_heap_unmap_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ /* todo: Need to see how to implement this api. Seems like it is
+ * mandatory to implement in new ION
+ */
+ return;
+
+}
+static struct ion_heap_ops omap_tiler_ops = {
+ .allocate = omap_tiler_heap_allocate,
+ .free = omap_tiler_heap_free,
+ .phys = omap_tiler_phys,
+ .map_user = omap_tiler_heap_map_user,
+ .map_dma = omap_tiler_heap_map_dma,
+ .unmap_dma = omap_tiler_heap_unmap_dma,
+ .map_kernel = ion_tiler_heap_map_kernel,
+ .unmap_kernel = ion_tiler_heap_unmap_kernel,
+};
+
+struct ion_heap *omap_tiler_heap_create(struct ion_platform_heap *data)
+{
+ struct omap_ion_heap *heap;
+
+ heap = kzalloc(sizeof(struct omap_ion_heap), GFP_KERNEL);
+ if (!heap)
+ return ERR_PTR(-ENOMEM);
+
+ if ((data->id == OMAP_ION_HEAP_TILER) ||
+ (data->id == OMAP_ION_HEAP_NONSECURE_TILER)) {
+ heap->pool = gen_pool_create(12, -1);
+ if (!heap->pool) {
+ kfree(heap);
+ return ERR_PTR(-ENOMEM);
+ }
+ heap->base = data->base;
+ gen_pool_add(heap->pool, heap->base, data->size, -1);
+ }
+ heap->heap.ops = &omap_tiler_ops;
+ heap->heap.type = OMAP_ION_HEAP_TYPE_TILER;
+ heap->heap.name = data->name;
+ heap->heap.id = data->id;
+ return &heap->heap;
+}
+
+void omap_tiler_heap_destroy(struct ion_heap *heap)
+{
+ struct omap_ion_heap *omap_ion_heap = (struct omap_ion_heap *)heap;
+ if (omap_ion_heap->pool)
+ gen_pool_destroy(omap_ion_heap->pool);
+ kfree(heap);
+}
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 29818b28925f759a1551e60419853614ff1c3e7f..cd68921b36e4297b3b2c9f445308b6bf9dc3699a 100644 (file)
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
source "drivers/misc/ti-st/Kconfig"
source "drivers/misc/lis3lv02d/Kconfig"
source "drivers/misc/carma/Kconfig"
+source "drivers/misc/gcx/gccore/Kconfig"
+source "drivers/misc/gcx/gcioctl/Kconfig"
+source "drivers/misc/gcx/gcbv/Kconfig"
+source "drivers/misc/cache-2dmanager/Kconfig"
source "drivers/misc/altera-stapl/Kconfig"
source "drivers/misc/mei/Kconfig"
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f547db387dd745ac5440fa1719c71de76352277d..a43854760d2b61e05c42f0a2ddee3f51fe6447e5 100644 (file)
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
obj-$(CONFIG_INTEL_MEI) += mei/
+obj-$(CONFIG_GCCORE) += gcx/gccore/
+obj-$(CONFIG_GCBV) += gcx/gcbv/
+obj-$(CONFIG_GCIOCTL) += gcx/gcioctl/
+obj-$(CONFIG_CACHE2DMANAGER) += cache-2dmanager/
diff --git a/drivers/misc/cache-2dmanager/Kconfig b/drivers/misc/cache-2dmanager/Kconfig
--- /dev/null
@@ -0,0 +1,5 @@
+config CACHE2DMANAGER
+ tristate "2D Cache operation driver"
+ default y
+ help
+ Enable 2D Cache operation support
diff --git a/drivers/misc/cache-2dmanager/Makefile b/drivers/misc/cache-2dmanager/Makefile
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_CACHE2DMANAGER) += cache2d.o
+
+cache2d-y := \
+ cache-2dmanager.o \
diff --git a/drivers/misc/cache-2dmanager/cache-2dmanager.c b/drivers/misc/cache-2dmanager/cache-2dmanager.c
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * cache-2dmanager.c
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <asm/cacheflush.h>
+#include <linux/sched.h>
+#include <linux/cache-2dmanager.h>
+
+static void per_cpu_cache_flush_arm(void *arg)
+{
+ flush_cache_all();
+}
+
+void c2dm_l1cache(int count, /* number of regions */
+ struct c2dmrgn rgns[], /* array of regions */
+ int dir) /* cache operation */
+{
+ unsigned long size = 0;
+ int rgn;
+ for (rgn = 0; rgn < count; rgn++)
+ size += rgns[rgn].span * rgns[rgn].lines;
+
+ /* If the total size of the caller's request exceeds the threshold,
+ * we can perform the operation on the entire cache instead.
+ *
+ * If the caller requests a clean larger than the threshold, we want
+ * to clean all. But this function does not exist in the L1 cache
+ * routines. So we use flush all.
+ *
+ * If the caller requests an invalidate larger than the threshold, we
+ * want to invalidate all. However, if the client does not fill the
+ * cache, an invalidate all will lose data from other processes, which
+ * can be catastrophic. So we must clean the entire cache before we
+ * invalidate it. Flush all cleans and invalidates in one operation.
+ */
+ if (size >= L1THRESHOLD) {
+ switch (dir) {
+ case DMA_TO_DEVICE:
+ /* Use clean all when available */
+ /* Fall through for now */
+ case DMA_BIDIRECTIONAL:
+ /* Can't invalidate all without cleaning, so fall
+ * through to flush all to do both. */
+ case DMA_FROM_DEVICE:
+ on_each_cpu(per_cpu_cache_flush_arm, NULL, 1);
+ break;
+ }
+ } else {
+ int rgn;
+ for (rgn = 0; rgn < count; rgn++) {
+ int line;
+ char *start = rgns[rgn].start;
+ for (line = 0; line < rgns[rgn].lines; line++) {
+ if (dir == DMA_BIDIRECTIONAL)
+ cpu_cache.dma_flush_range(
+ start,
+ start + rgns[rgn].span);
+ else
+ cpu_cache.dma_map_area(
+ start,
+ rgns[rgn].span,
+ dir);
+ start += rgns[rgn].stride;
+ }
+ }
+ }
+}
+EXPORT_SYMBOL(c2dm_l1cache);
+
+static u32 virt2phys(u32 usr)
+{
+ pmd_t *pmd;
+ pte_t *ptep;
+ pgd_t *pgd = pgd_offset(current->mm, usr);
+
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ return 0;
+
+ pmd = pmd_offset((pud_t *)pgd, usr);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ return 0;
+
+ ptep = pte_offset_map(pmd, usr);
+ if (ptep && pte_present(*ptep))
+ return (*ptep & PAGE_MASK) | (~PAGE_MASK & usr);
+
+ return 0;
+}
+
+void c2dm_l2cache(int count, /* number of regions */
+ struct c2dmrgn rgns[], /* array of regions */
+ int dir) /* cache operation */
+{
+
+ unsigned long size = 0;
+ int rgn;
+
+ for (rgn = 0; rgn < count; rgn++)
+ size += rgns[rgn].span * rgns[rgn].lines;
+
+ if (size >= L2THRESHOLD) {
+ switch (dir) {
+ case DMA_TO_DEVICE:
+ /* Use clean all when available */
+ /* Fall through for now */
+ case DMA_BIDIRECTIONAL:
+ /* Can't invalidate all without cleaning, so fall
+ * through to flush all to do both. */
+ case DMA_FROM_DEVICE:
+ outer_flush_all();
+ break;
+ }
+ return;
+ }
+
+ for (rgn = 0; rgn < count; rgn++) {
+ int i, j;
+ unsigned long linestart, start;
+ unsigned long page_begin, end, offset,
+ pageremain, lineremain;
+ unsigned long phys, opsize;
+ int page_num;
+
+ /* beginning virtual address of each line */
+ start = (unsigned long)rgns[rgn].start;
+
+ for (i = 0; i < rgns[rgn].lines; i++) {
+
+ linestart = start + (i * rgns[rgn].stride);
+
+ /* beginning of the page for the new line */
+ page_begin = linestart & PAGE_MASK;
+
+ /* end of the new line */
+ end = (unsigned long)linestart +
+ rgns[rgn].span;
+
+ page_num = DIV_ROUND_UP(
+ end-page_begin, PAGE_SIZE);
+
+ /* offset of the new line from page begin */
+ offset = linestart - page_begin;
+
+ /* track how long it is to the end of
+ the current page */
+ pageremain = PAGE_SIZE - offset;
+
+ /* keep track of how much of the line remains
+ to be copied */
+ lineremain = rgns[rgn].span;
+
+ for (j = 0; j < page_num; j++) {
+
+ opsize = (lineremain < pageremain) ?
+ lineremain : pageremain;
+
+ phys = virt2phys(page_begin);
+ if (phys) {
+ phys = phys + offset;
+ switch (dir) {
+ case DMA_TO_DEVICE:
+ outer_clean_range(
+ phys, phys + opsize);
+ break;
+ case DMA_FROM_DEVICE:
+ outer_inv_range(
+ phys, phys + opsize);
+ break;
+ case DMA_BIDIRECTIONAL:
+ outer_flush_range(
+ phys, phys + opsize);
+ break;
+ }
+ }
+
+ lineremain -= opsize;
+ /* Move to next page */
+ page_begin += PAGE_SIZE;
+
+ /* After first page, start address
+ * will be page aligned so offset
+ * is 0 */
+ offset = 0;
+
+ if (!lineremain)
+ break;
+
+ pageremain -= opsize;
+ if (!pageremain)
+ pageremain = PAGE_SIZE;
+
+ }
+ }
+ }
+}
+EXPORT_SYMBOL(c2dm_l2cache);
diff --git a/drivers/misc/gcx/gcbv/Kconfig b/drivers/misc/gcx/gcbv/Kconfig
--- /dev/null
@@ -0,0 +1,6 @@
+config GCBV
+ tristate "Vivante BLTsville library"
+ default y
+ depends on GCCORE
+ help
+ Vivante BLTsville library.
diff --git a/drivers/misc/gcx/gcbv/Makefile b/drivers/misc/gcx/gcbv/Makefile
--- /dev/null
@@ -0,0 +1,12 @@
+obj-$(CONFIG_GCBV) += gcbv2d.o
+
+gcbv2d-y := \
+ gcmain.o \
+ gcbv.o \
+ gcparser.o \
+ gcmap.o \
+ gcbuffer.o \
+ gcfill.o \
+ gcblit.o \
+ gcfilter.o \
+ gcbvdebug.o
diff --git a/drivers/misc/gcx/gcbv/gcblit.c b/drivers/misc/gcx/gcbv/gcblit.c
--- /dev/null
@@ -0,0 +1,783 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Vivante Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_BLEND (1 << 0)
+#define GCZONE_SURF (1 << 1)
+#define GCZONE_BLIT (1 << 2)
+
+GCDBG_FILTERDEF(blit, GCZONE_NONE,
+ "blend",
+ "surf",
+ "blit")
+
+
+static enum bverror do_blit_end(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch)
+{
+ enum bverror bverror;
+ struct gcblit *gcblit;
+ struct gcmobltconfig *gcmobltconfig;
+ struct gcmostartde *gcmostartde;
+
+ GCENTER(GCZONE_BLIT);
+
+ /* Get a shortcut to the operation specific data. */
+ gcblit = &batch->op.blit;
+
+ GCDBG(GCZONE_BLIT, "finalizing the blit, scrcount = %d\n",
+ gcblit->srccount);
+
+ /***********************************************************************
+ * Configure the operation.
+ */
+
+ /* Allocate command buffer. */
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmobltconfig),
+ (void **) &gcmobltconfig);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Configure multi-source control. */
+ gcmobltconfig->multisource_ldst = gcmobltconfig_multisource_ldst;
+ gcmobltconfig->multisource.raw = 0;
+ gcmobltconfig->multisource.reg.srccount = gcblit->srccount - 1;
+
+ GCDBG(GCZONE_BLIT, "blockenable = %d\n", gcblit->blockenable);
+ if (gcblit->blockenable) {
+ gcmobltconfig->multisource.reg.horblock
+ = GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL16;
+ gcmobltconfig->multisource.reg.verblock
+ = GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE64;
+ } else {
+ gcmobltconfig->multisource.reg.horblock
+ = GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL128;
+ gcmobltconfig->multisource.reg.verblock
+ = GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE1;
+ }
+
+ /* Set destination configuration. */
+ GCDBG(GCZONE_BLIT, " swizzle code = %d\n", gcblit->swizzle);
+ GCDBG(GCZONE_BLIT, " format code = %d\n", gcblit->format);
+
+ gcmobltconfig->dstconfig_ldst = gcmobltconfig_dstconfig_ldst;
+ gcmobltconfig->dstconfig.raw = 0;
+ gcmobltconfig->dstconfig.reg.swizzle = gcblit->swizzle;
+ gcmobltconfig->dstconfig.reg.format = gcblit->format;
+ gcmobltconfig->dstconfig.reg.endian = gcblit->endian;
+ gcmobltconfig->dstconfig.reg.command = gcblit->multisrc
+ ? GCREG_DEST_CONFIG_COMMAND_MULTI_SOURCE_BLT
+ : GCREG_DEST_CONFIG_COMMAND_BIT_BLT;
+
+ /***********************************************************************
+ * Start the operation.
+ */
+
+ /* Allocate command buffer. */
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmostartde),
+ (void **) &gcmostartde);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Set START_DE command. */
+ gcmostartde->startde.cmd.fld = gcfldstartde;
+
+ /* Set destination rectangle. */
+ gcmostartde->rect.left = gcblit->dstrect.left;
+ gcmostartde->rect.top = gcblit->dstrect.top;
+ gcmostartde->rect.right = gcblit->dstrect.right;
+ gcmostartde->rect.bottom = gcblit->dstrect.bottom;
+
+ GCDBG(GCZONE_BLIT, "dstrect = (%d,%d)-(%d,%d)\n",
+ gcmostartde->rect.left, gcmostartde->rect.top,
+ gcmostartde->rect.right, gcmostartde->rect.bottom);
+
+ /* Reset the finalizer. */
+ batch->batchend = do_end;
+
+ gcbv_debug_blt(gcblit->srccount,
+ abs(gcblit->dstrect.right - gcblit->dstrect.left),
+ abs(gcblit->dstrect.bottom - gcblit->dstrect.top));
+
+exit:
+ GCEXITARG(GCZONE_BLIT, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+enum bverror do_blit(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gccontext *gccontext = get_context();
+
+ struct gcmosrc0 *gcmosrc0;
+ struct gcmosrc *gcmosrc;
+ struct gcblit *gcblit;
+
+ unsigned int index;
+ struct bvbuffmap *dstmap = NULL;
+ struct bvbuffmap *srcmap = NULL;
+
+ struct gcsurface *dstinfo;
+ int dstshiftX, dstshiftY;
+ int dstpixalign, dstbyteshift;
+ int dstoffsetX, dstoffsetY;
+
+ int adjust, srcshiftX, srcshiftY;
+ unsigned int physwidth, physheight;
+ bool orthogonal;
+ bool multisrc;
+ unsigned int batchfinalize;
+
+ int srcleftedge, srctopedge;
+ int dstleftedge, dsttopedge;
+
+ struct gcrect *srcorig, *srcclip, *srcadj;
+ struct gcrect *dstorig, *dstclip, *dstadj;
+
+ GCENTER(GCZONE_BLIT);
+
+ /* 3-plane source not supported. */
+ if ((srcinfo->format.type == BVFMT_YUV) &&
+ (srcinfo->format.cs.yuv.planecount == 3)) {
+ BVSETBLTERROR((srcinfo->index == 0)
+ ? BVERR_SRC1GEOM_FORMAT
+ : BVERR_SRC2GEOM_FORMAT,
+ "unsupported source%d format.",
+ srcinfo->index + 1);
+ goto exit;
+ }
+
+ /* Zero-fill for source is not supported. */
+ if (srcinfo->format.zerofill) {
+ BVSETBLTERROR((srcinfo->index == 0)
+ ? BVERR_SRC1GEOM_FORMAT
+ : BVERR_SRC2GEOM_FORMAT,
+ "0 filling is not supported.");
+ goto exit;
+ }
+
+ /***********************************************************************
+ * Parse destination.
+ */
+
+ /* Get a shortcut to the destination surface. */
+ dstinfo = &batch->dstinfo;
+
+ /* Get destination rectangle shortcuts. */
+ dstorig = &dstinfo->rect.orig;
+ dstclip = &dstinfo->rect.clip;
+ dstadj = &dstinfo->rect.adj;
+
+ /* Parse destination parameters. */
+ bverror = parse_destination(bvbltparams, batch);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Ignore the blit if destination rectangle is empty. */
+ if (null_rect(dstclip)) {
+ GCDBG(GCZONE_SURF, "empty destination rectangle.\n");
+ goto exit;
+ }
+
+ /* Adjust surface angles if necessary. */
+ adjust_angle(srcinfo, dstinfo);
+
+
+ /***********************************************************************
+ * Determine source surface alignment offset.
+ */
+
+ /* Assume multi-source is possible. */
+ multisrc = true;
+
+ /* Assume no additional shift is necessary. */
+ srcshiftX = 0;
+ srcshiftY = 0;
+
+ /* Get source rectangle shortcuts. */
+ srcorig = &srcinfo->rect.orig;
+ srcclip = &srcinfo->rect.clip;
+ srcadj = &srcinfo->rect.adj;
+
+ /* Determine whether the source and the destination are orthogonal
+ * to each other. */
+ orthogonal = (srcinfo->angle % 2) != (dstinfo->angle % 2);
+
+ /* Compute clipped source rectangle. */
+ srcclip->left = srcorig->left + batch->clipdelta.left;
+ srcclip->top = srcorig->top + batch->clipdelta.top;
+ srcclip->right = srcorig->right + batch->clipdelta.right;
+ srcclip->bottom = srcorig->bottom + batch->clipdelta.bottom;
+ GCPRINT_RECT(GCZONE_SURF, "clipped source", srcclip);
+
+ /* Validate the source rectangle. */
+ if (!valid_rect(srcinfo, srcclip)) {
+ BVSETBLTERROR((srcinfo->index == 0)
+ ? BVERR_SRC1RECT
+ : BVERR_SRC2RECT,
+ "invalid source rectangle.");
+ goto exit;
+ }
+
+ /* Ignore the blit if source rectangle is empty. */
+ if (null_rect(srcclip)) {
+ GCDBG(GCZONE_SURF, "empty source rectangle.\n");
+ goto exit;
+ }
+
+ /* Determine source and destination physical origin. */
+ switch (srcinfo->angle) {
+ case ROT_ANGLE_0:
+ srcleftedge = srcclip->left;
+ srctopedge = srcclip->top;
+ dstleftedge = dstadj->left;
+ dsttopedge = dstadj->top;
+ break;
+
+ case ROT_ANGLE_90:
+ srcleftedge = srcclip->top;
+ srctopedge = srcinfo->width - srcclip->left;
+ dstleftedge = dstadj->top;
+ dsttopedge = dstinfo->adjwidth - dstadj->left;
+ break;
+
+ case ROT_ANGLE_180:
+ srcleftedge = srcinfo->width - srcclip->left;
+ srctopedge = srcinfo->height - srcclip->top;
+ dstleftedge = dstinfo->adjwidth - dstadj->left;
+ dsttopedge = dstinfo->adjheight - dstadj->top;
+ break;
+
+ case ROT_ANGLE_270:
+ srcleftedge = srcinfo->height - srcclip->top;
+ srctopedge = srcclip->left;
+ dstleftedge = dstinfo->adjheight - dstadj->top;
+ dsttopedge = dstadj->left;
+ break;
+
+ default:
+ srcleftedge = 0;
+ srctopedge = 0;
+ dstleftedge = 0;
+ dsttopedge = 0;
+ }
+
+ /* Compute the source surface shift. */
+ srcinfo->xpixalign = srcleftedge - dstleftedge;
+ srcinfo->ypixalign = srctopedge - dsttopedge;
+
+ /* Compute the source surface offset in bytes. */
+ srcinfo->bytealign1
+ = srcinfo->ypixalign * (int) srcinfo->stride1
+ + srcinfo->xpixalign * (int) srcinfo->format.bitspp / 8;
+
+ GCDBG(GCZONE_SURF, "source surface %d:\n", srcinfo->index + 1);
+ GCDBG(GCZONE_SURF, " surface offset (pixels) = %d,%d\n",
+ srcinfo->xpixalign, srcinfo->ypixalign);
+ GCDBG(GCZONE_SURF, " surface offset (bytes) = 0x%08X\n",
+ srcinfo->bytealign1);
+
+ /* Compute the source offset in pixels needed to compensate
+ * for the surface base address misalignment if any. */
+ adjust = get_pixel_offset(srcinfo, srcinfo->bytealign1);
+
+ /* Account for the newly created misalignment if any. */
+ srcinfo->bytealign1 += adjust * (int) srcinfo->format.bitspp / 8;
+ srcinfo->xpixalign += adjust;
+ srcshiftX += adjust;
+
+ GCDBG(GCZONE_SURF, " horizontal alignment adjustment (pixels) = %d\n",
+ adjust);
+ GCDBG(GCZONE_SURF, " adjusted surface offset (pixels) = %d,%d\n",
+ srcinfo->xpixalign, srcinfo->ypixalign);
+ GCDBG(GCZONE_SURF, " additional surface offset (pixels) = %d,%d\n",
+ srcshiftX, srcshiftY);
+ GCDBG(GCZONE_SURF, " adjusted surface offset (bytes) = 0x%08X\n",
+ srcinfo->bytealign1);
+
+ /* Compute U/V plane offsets. */
+ if ((srcinfo->format.type == BVFMT_YUV) &&
+ (srcinfo->format.cs.yuv.planecount > 1))
+ set_computeyuv(srcinfo, srcinfo->xpixalign, srcinfo->ypixalign);
+
+ /* Set precomputed destination adjustments based on the destination
+ * base address misalignment only. */
+ dstshiftX = dstinfo->xpixalign;
+ dstshiftY = dstinfo->ypixalign;
+
+ /* Apply source adjustemnts. */
+ if (srcinfo->angle == dstinfo->angle) {
+ dstshiftX += srcshiftX;
+ dstshiftY += srcshiftY;
+ } else if (((srcinfo->angle + 3) % 4) == dstinfo->angle) {
+ dstshiftY += srcshiftX;
+ } else if (((srcinfo->angle + 1) % 4) == dstinfo->angle) {
+ dstshiftX += srcshiftY;
+ }
+
+ /* Compute the destination surface offset in bytes. */
+ dstbyteshift = dstshiftY * (int) dstinfo->stride1
+ + dstshiftX * (int) dstinfo->format.bitspp / 8;
+
+ /* Compute the destination offset in pixels needed to compensate
+ * for the surface base address misalignment if any. If dstpixalign
+ * comes out anything other than zero, multisource blit cannot be
+ * performed. */
+ dstpixalign = get_pixel_offset(dstinfo, dstbyteshift);
+ if (dstpixalign != 0) {
+ GCDBG(GCZONE_SURF,
+ " disabling multi-source, "
+ "destination needs to be realigned again.\n");
+ multisrc = false;
+ }
+
+ GCDBG(GCZONE_SURF, "destination surface:\n");
+ GCDBG(GCZONE_SURF, " surface offset (pixels) = %d,%d\n",
+ dstshiftX, dstshiftY);
+ GCDBG(GCZONE_SURF, " surface offset (bytes) = 0x%08X\n",
+ dstbyteshift);
+ GCDBG(GCZONE_SURF, " realignment = %d\n",
+ dstpixalign);
+
+ if (multisrc) {
+ GCDBG(GCZONE_SURF, "multi-source enabled.\n");
+
+ /* Source origin is not used in multi-source setup. */
+ srcadj->left = 0;
+ srcadj->top = 0;
+
+ /* Set new surface shift. */
+ if (dstinfo->bytealign1 != dstbyteshift) {
+ GCDBG(GCZONE_SURF,
+ "destination alignment changed.\n");
+ dstinfo->bytealign1 = dstbyteshift;
+ dstinfo->surfdirty = true;
+ }
+
+ /* Adjust the destination to match the source geometry. */
+ switch (srcinfo->angle) {
+ case ROT_ANGLE_0:
+ /* Adjust the destination horizontally. */
+ dstoffsetX = srcshiftX;
+ dstoffsetY = srcshiftY;
+
+ /* Apply the source alignment. */
+ if ((dstinfo->angle % 2) == 0) {
+ physwidth = dstinfo->physwidth - srcshiftX;
+ physheight = dstinfo->physheight - srcshiftY;
+ } else {
+ physwidth = dstinfo->physwidth - srcshiftY;
+ physheight = dstinfo->physheight - srcshiftX;
+ }
+ break;
+
+ case ROT_ANGLE_90:
+ /* Adjust the destination vertically. */
+ dstoffsetX = srcshiftY;
+ dstoffsetY = srcshiftX;
+
+ /* Apply the source alignment. */
+ if ((dstinfo->angle % 2) == 0) {
+ physwidth = dstinfo->physwidth - srcshiftY;
+ physheight = dstinfo->physheight - srcshiftX;
+ } else {
+ physwidth = dstinfo->physwidth - srcshiftX;
+ physheight = dstinfo->physheight - srcshiftY;
+ }
+ break;
+
+ case ROT_ANGLE_180:
+ /* No adjustment necessary. */
+ dstoffsetX = 0;
+ dstoffsetY = 0;
+
+ /* Apply the source alignment. */
+ if ((dstinfo->angle % 2) == 0) {
+ physwidth = dstinfo->physwidth - srcshiftX;
+ physheight = dstinfo->physheight - srcshiftY;
+ } else {
+ physwidth = dstinfo->physwidth - srcshiftY;
+ physheight = dstinfo->physheight - srcshiftX;
+ }
+ break;
+
+ case ROT_ANGLE_270:
+ /* No adjustment necessary. */
+ dstoffsetX = 0;
+ dstoffsetY = 0;
+
+ /* Apply the source alignment. */
+ if ((dstinfo->angle % 2) == 0) {
+ physwidth = dstinfo->physwidth - srcshiftY;
+ physheight = dstinfo->physheight - srcshiftX;
+ } else {
+ physwidth = dstinfo->physwidth - srcshiftX;
+ physheight = dstinfo->physheight - srcshiftY;
+ }
+ break;
+
+ default:
+ physwidth = 0;
+ physheight = 0;
+ dstoffsetX = 0;
+ dstoffsetY = 0;
+ }
+
+ /* Source geometry is now the same as the destination. */
+ if (orthogonal) {
+ srcinfo->physwidth = physheight;
+ srcinfo->physheight = physwidth;
+ } else {
+ srcinfo->physwidth = physwidth;
+ srcinfo->physheight = physheight;
+ }
+
+ /* Set new surface size. */
+ if ((physwidth != dstinfo->physwidth) ||
+ (physheight != dstinfo->physheight)) {
+ dstinfo->physwidth = physwidth;
+ dstinfo->physheight = physheight;
+ dstinfo->surfdirty = true;
+ }
+
+ /* Set new offset. */
+ if ((batch->dstoffsetX != dstoffsetX) ||
+ (batch->dstoffsetY != dstoffsetY)) {
+ batch->dstoffsetX = dstoffsetX;
+ batch->dstoffsetY = dstoffsetY;
+ dstinfo->surfdirty = true;
+ }
+ } else {
+ GCDBG(GCZONE_SURF, "multi-source disabled.\n");
+
+ /* Determine surface size and render rectangle. */
+ process_rotation(srcinfo);
+
+ /* No adjustment necessary for single-source. */
+ dstoffsetX = 0;
+ dstoffsetY = 0;
+ }
+
+ batchfinalize = 0;
+
+ /* Reached maximum number of sources? */
+ if (batch->op.blit.srccount == gccontext->gccaps.maxsource)
+ batchfinalize |= GCBV_BATCH_FINALIZE_SRCCOUNT;
+
+ /* Previous operation was not blit? */
+ if (batch->batchend != do_blit_end)
+ batchfinalize |= GCBV_BATCH_FINALIZE_OPERATION;
+
+ /* Previous blit was not multi-sourced? */
+ else if (!batch->op.blit.multisrc)
+ batchfinalize |= GCBV_BATCH_FINALIZE_MULTISRC;
+
+ /* Current blit is not multi-sourced? */
+ if (!multisrc)
+ batchfinalize |= GCBV_BATCH_FINALIZE_ALIGN;
+
+ /* Destination has changed? */
+ if (dstinfo->surfdirty)
+ batchfinalize |= GCBV_BATCH_FINALIZE_FLAGS_DST;
+
+ if (dstinfo->cliprectdirty)
+ batchfinalize |= GCBV_BATCH_FINALIZE_FLAGS_CLIPRECT;
+
+ if (dstinfo->destrectdirty)
+ batchfinalize |= GCBV_BATCH_FINALIZE_FLAGS_DESTRECT;
+
+ /* Check if we need to finalize existing batch. */
+ if (batchfinalize) {
+ if (batch->batchend == do_blit_end)
+ gcbv_debug_finalize_batch(batchfinalize);
+
+ /* Finalize existing batch if any. */
+ bverror = batch->batchend(bvbltparams, batch);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Blit batch. */
+ batch->batchend = do_blit_end;
+
+ /* Initialize the new batch. */
+ gcblit = &batch->op.blit;
+ gcblit->blockenable = false;
+ gcblit->srccount = 0;
+ gcblit->multisrc = multisrc;
+
+ /* Set the destination format. */
+ gcblit->format = dstinfo->format.format;
+ gcblit->swizzle = dstinfo->format.swizzle;
+ gcblit->endian = dstinfo->format.endian;
+
+ /* Set the destination coordinates. */
+ gcblit->dstrect.left = dstadj->left - dstoffsetX;
+ gcblit->dstrect.top = dstadj->top - dstoffsetY;
+ gcblit->dstrect.right = dstadj->right - dstoffsetX;
+ gcblit->dstrect.bottom = dstadj->bottom - dstoffsetY;
+ }
+
+ if (dstinfo->surfdirty) {
+ /* Map the destination. */
+ bverror = do_map(dstinfo->buf.desc, batch, &dstmap);
+ if (bverror != BVERR_NONE) {
+ bvbltparams->errdesc = gccontext->bverrorstr;
+ goto exit;
+ }
+
+ /* Set the new destination. */
+ bverror = set_dst(bvbltparams, batch, dstmap);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ }
+
+ /* Map the source. */
+ bverror = do_map(srcinfo->buf.desc, batch, &srcmap);
+ if (bverror != BVERR_NONE) {
+ bvbltparams->errdesc = gccontext->bverrorstr;
+ goto exit;
+ }
+
+ /***********************************************************************
+ ** Configure source.
+ */
+
+ /* We need to walk in blocks if the source and the destination
+ * surfaces are orthogonal to each other. */
+ if (orthogonal)
+ batch->op.blit.blockenable = true;
+
+ /* Shortcut to the register index. */
+ index = batch->op.blit.srccount;
+
+ /* Set surface parameters. */
+ if (index == 0) {
+ /* Allocate command buffer. */
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmosrc0),
+ (void **) &gcmosrc0);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ add_fixup(bvbltparams, batch, &gcmosrc0->address,
+ srcinfo->bytealign1);
+
+ gcmosrc0->config_ldst = gcmosrc0_config_ldst;
+ gcmosrc0->address = GET_MAP_HANDLE(srcmap);
+ gcmosrc0->stride = srcinfo->stride1;
+ gcmosrc0->rotation.raw = 0;
+ gcmosrc0->rotation.reg.surf_width = srcinfo->physwidth;
+ gcmosrc0->config.raw = 0;
+ gcmosrc0->config.reg.swizzle = srcinfo->format.swizzle;
+ gcmosrc0->config.reg.format = srcinfo->format.format;
+ gcmosrc0->config.reg.endian = srcinfo->format.endian;
+ gcmosrc0->origin.reg.x = srcadj->left;
+ gcmosrc0->origin.reg.y = srcadj->top;
+ gcmosrc0->size.reg = gcregsrcsize_max;
+
+ gcmosrc0->rotation_ldst = gcmosrc0_rotation_ldst;
+ gcmosrc0->rotationheight.reg.height = srcinfo->physheight;
+ gcmosrc0->rotationangle.raw = 0;
+ gcmosrc0->rotationangle.reg.src = rotencoding[srcinfo->angle];
+ gcmosrc0->rotationangle.reg.dst = rotencoding[dstinfo->angle];
+ gcmosrc0->rotationangle.reg.src_mirror = srcinfo->mirror;
+ gcmosrc0->rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE;
+
+ gcmosrc0->rop_ldst = gcmosrc0_rop_ldst;
+ gcmosrc0->rop.raw = 0;
+ gcmosrc0->rop.reg.type = GCREG_ROP_TYPE_ROP3;
+ gcmosrc0->rop.reg.fg = (unsigned char) srcinfo->rop;
+
+ gcmosrc0->mult_ldst = gcmosrc0_mult_ldst;
+ gcmosrc0->mult.raw = 0;
+ gcmosrc0->mult.reg.srcglobalpremul = srcinfo->srcglobalpremul;
+
+ if (srcinfo->format.premultiplied)
+ gcmosrc0->mult.reg.srcpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+ else
+ gcmosrc0->mult.reg.srcpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+ if (dstinfo->format.premultiplied) {
+ gcmosrc0->mult.reg.dstpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+
+ gcmosrc0->mult.reg.dstdemul
+ = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE;
+ } else {
+ gcmosrc0->mult.reg.dstpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+ gcmosrc0->mult.reg.dstdemul
+ = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE;
+ }
+
+ /* Program blending. */
+ bverror = set_blending(bvbltparams, batch, srcinfo);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Program YUV source. */
+ if (srcinfo->format.type == BVFMT_YUV) {
+ bverror = set_yuvsrc(bvbltparams, batch,
+ srcinfo, srcmap);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ }
+ } else {
+ /* Allocate command buffer. */
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmosrc),
+ (void **) &gcmosrc);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ add_fixup(bvbltparams, batch, &gcmosrc->address,
+ srcinfo->bytealign1);
+
+ gcmosrc->address_ldst = gcmosrc_address_ldst[index];
+ gcmosrc->address = GET_MAP_HANDLE(srcmap);
+ gcmosrc->stride_ldst = gcmosrc_stride_ldst[index];
+ gcmosrc->stride = srcinfo->stride1;
+
+ gcmosrc->rotation_ldst = gcmosrc_rotation_ldst[index];
+ gcmosrc->rotation.raw = 0;
+ gcmosrc->rotation.reg.surf_width = srcinfo->physwidth;
+
+ gcmosrc->config_ldst = gcmosrc_config_ldst[index];
+ gcmosrc->config.raw = 0;
+ gcmosrc->config.reg.swizzle = srcinfo->format.swizzle;
+ gcmosrc->config.reg.format = srcinfo->format.format;
+ gcmosrc->config.reg.endian = srcinfo->format.endian;
+
+ gcmosrc->origin_ldst = gcmosrc_origin_ldst[index];
+ gcmosrc->origin.reg.x = srcadj->left;
+ gcmosrc->origin.reg.y = srcadj->top;
+
+ gcmosrc->size_ldst = gcmosrc_size_ldst[index];
+ gcmosrc->size.reg = gcregsrcsize_max;
+
+ gcmosrc->rotationheight_ldst
+ = gcmosrc_rotationheight_ldst[index];
+ gcmosrc->rotationheight.reg.height = srcinfo->physheight;
+
+ gcmosrc->rotationangle_ldst
+ = gcmosrc_rotationangle_ldst[index];
+ gcmosrc->rotationangle.raw = 0;
+ gcmosrc->rotationangle.reg.src = rotencoding[srcinfo->angle];
+ gcmosrc->rotationangle.reg.dst = rotencoding[dstinfo->angle];
+ gcmosrc->rotationangle.reg.src_mirror = srcinfo->mirror;
+ gcmosrc->rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE;
+
+ gcmosrc->rop_ldst = gcmosrc_rop_ldst[index];
+ gcmosrc->rop.raw = 0;
+ gcmosrc->rop.reg.type = GCREG_ROP_TYPE_ROP3;
+ gcmosrc->rop.reg.fg = (unsigned char) srcinfo->rop;
+
+ gcmosrc->mult_ldst = gcmosrc_mult_ldst[index];
+ gcmosrc->mult.raw = 0;
+ gcmosrc->mult.reg.srcglobalpremul = srcinfo->srcglobalpremul;
+
+ if (srcinfo->format.premultiplied)
+ gcmosrc->mult.reg.srcpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+ else
+ gcmosrc->mult.reg.srcpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+ if (dstinfo->format.premultiplied) {
+ gcmosrc->mult.reg.dstpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+
+ gcmosrc->mult.reg.dstdemul
+ = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE;
+ } else {
+ gcmosrc->mult.reg.dstpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+ gcmosrc->mult.reg.dstdemul
+ = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE;
+ }
+
+ /* Program blending. */
+ bverror = set_blending_index(bvbltparams, batch,
+ srcinfo, index);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Program YUV source. */
+ if (srcinfo->format.type == BVFMT_YUV) {
+ bverror = set_yuvsrc_index(bvbltparams, batch,
+ srcinfo, srcmap, index);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ }
+ }
+
+ batch->op.blit.srccount += 1;
+
+exit:
+ GCEXITARG(GCZONE_BLIT, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
diff --git a/drivers/misc/gcx/gcbv/gcbuffer.c b/drivers/misc/gcx/gcbv/gcbuffer.c
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Vivante Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_BATCH_ALLOC (1 << 0)
+#define GCZONE_BUFFER_ALLOC (1 << 1)
+#define GCZONE_FIXUP_ALLOC (1 << 2)
+#define GCZONE_FIXUP (1 << 3)
+
+GCDBG_FILTERDEF(buffer, GCZONE_NONE,
+ "batchalloc",
+ "bufferalloc"
+ "fixupalloc",
+ "fixup")
+
+
+/*******************************************************************************
+** Miscellaneous defines and macros.
+*/
+
+#define GC_BUFFER_INIT_SIZE \
+( \
+ GC_BUFFER_SIZE - max(sizeof(struct gcbuffer), GC_BUFFER_RESERVE) \
+)
+
+#define GC_BUFFER_RESERVE \
+( \
+ sizeof(struct gcmopipesel) + \
+ sizeof(struct gcmommumaster) + \
+ sizeof(struct gcmommuflush) + \
+ sizeof(struct gcmosignal) + \
+ sizeof(struct gccmdend) \
+)
+
+
+/*******************************************************************************
+ * Batch/command buffer management.
+ */
+
+enum bverror do_end(struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch)
+{
+ return BVERR_NONE;
+}
+
+enum bverror allocate_batch(struct bvbltparams *bvbltparams,
+ struct gcbatch **gcbatch)
+{
+ enum bverror bverror;
+ struct gccontext *gccontext = get_context();
+ struct gcbatch *temp;
+ struct gcbuffer *gcbuffer;
+
+ GCENTER(GCZONE_BATCH_ALLOC);
+
+ /* Lock access to batch management. */
+ GCLOCK(&gccontext->batchlock);
+
+ if (list_empty(&gccontext->batchvac)) {
+ temp = gcalloc(struct gcbatch, sizeof(struct gcbatch));
+ if (temp == NULL) {
+ BVSETBLTERROR(BVERR_OOM,
+ "batch header allocation failed");
+ goto exit;
+ }
+
+ GCDBG(GCZONE_BATCH_ALLOC, "allocated new batch = 0x%08X\n",
+ (unsigned int) temp);
+ } else {
+ struct list_head *head;
+ head = gccontext->batchvac.next;
+ temp = list_entry(head, struct gcbatch, link);
+ list_del(head);
+
+ GCDBG(GCZONE_BATCH_ALLOC, "reusing batch = 0x%08X\n",
+ (unsigned int) temp);
+ }
+
+ memset(temp, 0, sizeof(struct gcbatch));
+ temp->structsize = sizeof(struct gcbatch);
+ temp->batchend = do_end;
+ INIT_LIST_HEAD(&temp->buffer);
+ INIT_LIST_HEAD(&temp->unmap);
+ INIT_LIST_HEAD(&temp->link);
+
+ bverror = append_buffer(bvbltparams, temp, &gcbuffer);
+ if (bverror != BVERR_NONE) {
+ free_batch(temp);
+ goto exit;
+ }
+
+ *gcbatch = temp;
+
+ GCDBG(GCZONE_BATCH_ALLOC, "batch allocated = 0x%08X\n",
+ (unsigned int) temp);
+
+exit:
+ /* Unlock access to batch management. */
+ GCUNLOCK(&gccontext->batchlock);
+
+ GCEXITARG(GCZONE_BATCH_ALLOC, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+void free_batch(struct gcbatch *gcbatch)
+{
+ struct list_head *head;
+ struct gccontext *gccontext = get_context();
+ struct gcbuffer *gcbuffer;
+
+ GCENTERARG(GCZONE_BATCH_ALLOC, "batch = 0x%08X\n",
+ (unsigned int) gcbatch);
+
+ /* Lock access. */
+ GCLOCK(&gccontext->batchlock);
+ GCLOCK(&gccontext->bufferlock);
+ GCLOCK(&gccontext->fixuplock);
+ GCLOCK(&gccontext->maplock);
+
+ /* Free implicit unmappings. */
+ list_splice_init(&gcbatch->unmap, &gccontext->unmapvac);
+
+ /* Free command buffers. */
+ while (!list_empty(&gcbatch->buffer)) {
+ head = gcbatch->buffer.next;
+ gcbuffer = list_entry(head, struct gcbuffer, link);
+
+ /* Free fixups. */
+ list_splice_init(&gcbuffer->fixup, &gccontext->fixupvac);
+
+ /* Free the command buffer. */
+ list_move(&gcbuffer->link, &gccontext->buffervac);
+ }
+
+ /* Free the batch. */
+ list_add(&gcbatch->link, &gccontext->batchvac);
+
+ /* Unlock access. */
+ GCUNLOCK(&gccontext->maplock);
+ GCUNLOCK(&gccontext->fixuplock);
+ GCUNLOCK(&gccontext->bufferlock);
+ GCUNLOCK(&gccontext->batchlock);
+
+ GCEXIT(GCZONE_BATCH_ALLOC);
+}
+
+enum bverror append_buffer(struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch,
+ struct gcbuffer **gcbuffer)
+{
+ enum bverror bverror;
+ struct gccontext *gccontext = get_context();
+ struct gcbuffer *temp;
+
+ GCENTERARG(GCZONE_BUFFER_ALLOC, "batch = 0x%08X\n",
+ (unsigned int) gcbatch);
+
+ /* Lock access to buffer management. */
+ GCLOCK(&gccontext->bufferlock);
+
+ if (list_empty(&gccontext->buffervac)) {
+ temp = gcalloc(struct gcbuffer, GC_BUFFER_SIZE);
+ if (temp == NULL) {
+ BVSETBLTERROR(BVERR_OOM,
+ "command buffer allocation failed");
+ goto exit;
+ }
+
+ list_add_tail(&temp->link, &gcbatch->buffer);
+
+ GCDBG(GCZONE_BUFFER_ALLOC, "allocated new buffer = 0x%08X\n",
+ (unsigned int) temp);
+ } else {
+ struct list_head *head;
+ head = gccontext->buffervac.next;
+ temp = list_entry(head, struct gcbuffer, link);
+
+ list_move_tail(&temp->link, &gcbatch->buffer);
+
+ GCDBG(GCZONE_BUFFER_ALLOC, "reusing buffer = 0x%08X\n",
+ (unsigned int) temp);
+ }
+
+ INIT_LIST_HEAD(&temp->fixup);
+ temp->pixelcount = 0;
+ temp->head = temp->tail = (unsigned int *) (temp + 1);
+ temp->available = GC_BUFFER_INIT_SIZE;
+
+ GCDBG(GCZONE_BUFFER_ALLOC, "new buffer appended = 0x%08X\n",
+ (unsigned int) temp);
+
+ *gcbuffer = temp;
+ bverror = BVERR_NONE;
+
+exit:
+ /* Unlock access to buffer management. */
+ GCUNLOCK(&gccontext->bufferlock);
+
+ GCEXITARG(GCZONE_BUFFER_ALLOC, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+static enum bverror allocate_fixup(struct bvbltparams *bvbltparams,
+ struct gcbuffer *gcbuffer,
+ struct gcfixup **gcfixup)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gccontext *gccontext = get_context();
+ struct gcfixup *temp;
+
+ if (list_empty(&gccontext->fixupvac)) {
+ temp = gcalloc(struct gcfixup, sizeof(struct gcfixup));
+ if (temp == NULL) {
+ BVSETBLTERROR(BVERR_OOM, "fixup allocation failed");
+ goto exit;
+ }
+
+ list_add_tail(&temp->link, &gcbuffer->fixup);
+
+ GCDBG(GCZONE_FIXUP_ALLOC,
+ "new fixup struct allocated = 0x%08X\n",
+ (unsigned int) temp);
+ } else {
+ struct list_head *head;
+ head = gccontext->fixupvac.next;
+ temp = list_entry(head, struct gcfixup, link);
+
+ list_move_tail(&temp->link, &gcbuffer->fixup);
+
+ GCDBG(GCZONE_FIXUP_ALLOC, "fixup struct reused = 0x%08X\n",
+ (unsigned int) temp);
+ }
+
+ temp->count = 0;
+ *gcfixup = temp;
+
+exit:
+ return bverror;
+}
+
+enum bverror add_fixup(struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch,
+ unsigned int *ptr,
+ unsigned int surfoffset)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gccontext *gccontext = get_context();
+ struct list_head *head;
+ struct gcbuffer *buffer;
+ struct gcfixup *gcfixup;
+
+ GCENTERARG(GCZONE_FIXUP, "batch = 0x%08X, fixup ptr = 0x%08X\n",
+ (unsigned int) gcbatch, (unsigned int) ptr);
+
+ /* Lock access to fixup management. */
+ GCLOCK(&gccontext->fixuplock);
+
+ /* Get the current command buffer. */
+ if (list_empty(&gcbatch->buffer)) {
+ GCERR("no command buffers are allocated");
+ goto exit;
+ }
+ head = gcbatch->buffer.prev;
+ buffer = list_entry(head, struct gcbuffer, link);
+
+ /* No fixups? Allocate one. */
+ if (list_empty(&buffer->fixup)) {
+ GCDBG(GCZONE_FIXUP_ALLOC, "no fixups allocated.\n");
+ bverror = allocate_fixup(bvbltparams, buffer, &gcfixup);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ } else {
+ /* Get the current fixup. */
+ head = buffer->fixup.prev;
+ gcfixup = list_entry(head, struct gcfixup, link);
+
+ /* No more room? */
+ if (gcfixup->count == GC_FIXUP_MAX) {
+ GCDBG(GCZONE_FIXUP_ALLOC,
+ "out of room, allocating new.\n");
+ bverror = allocate_fixup(bvbltparams, buffer, &gcfixup);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ }
+ }
+
+ GCDBG(GCZONE_FIXUP, "buffer = 0x%08X, fixup struct = 0x%08X\n",
+ (unsigned int) buffer, (unsigned int) gcfixup);
+
+ gcfixup->fixup[gcfixup->count].dataoffset = ptr - buffer->head;
+ gcfixup->fixup[gcfixup->count].surfoffset = surfoffset;
+ gcfixup->count += 1;
+
+ GCDBG(GCZONE_FIXUP, "fixup offset = 0x%08X\n", ptr - buffer->head);
+ GCDBG(GCZONE_FIXUP, "surface offset = 0x%08X\n", surfoffset);
+
+exit:
+ /* Unlock access to fixup management. */
+ GCUNLOCK(&gccontext->fixuplock);
+
+ GCEXITARG(GCZONE_FIXUP, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+enum bverror claim_buffer(struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch,
+ unsigned int size,
+ void **buffer)
+{
+ enum bverror bverror;
+ struct list_head *head;
+ struct gcbuffer *gcbuffer;
+
+ GCENTERARG(GCZONE_BUFFER_ALLOC, "batch = 0x%08X, size = %d\n",
+ (unsigned int) gcbatch, size);
+
+ if (size > GC_BUFFER_INIT_SIZE) {
+ GCERR("requested size is too big.\n");
+ BVSETBLTERROR(BVERR_OOM,
+ "command buffer allocation failed");
+ goto exit;
+ }
+
+ /* Get the current command buffer. */
+ head = gcbatch->buffer.prev;
+ gcbuffer = list_entry(head, struct gcbuffer, link);
+
+ GCDBG(GCZONE_BUFFER_ALLOC, "buffer = 0x%08X, available = %d\n",
+ (unsigned int) gcbuffer, gcbuffer->available);
+
+ if (gcbuffer->available < size) {
+ bverror = append_buffer(bvbltparams, gcbatch, &gcbuffer);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ }
+
+ *buffer = gcbuffer->tail;
+ gcbuffer->tail = (unsigned int *)
+ ((unsigned char *) gcbuffer->tail + size);
+ gcbuffer->available -= size;
+ gcbatch->size += size;
+ bverror = BVERR_NONE;
+
+exit:
+ GCEXITARG(GCZONE_BUFFER_ALLOC, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
diff --git a/drivers/misc/gcx/gcbv/gcbv.c b/drivers/misc/gcx/gcbv/gcbv.c
--- /dev/null
@@ -0,0 +1,2178 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Vivante Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_INIT (1 << 0)
+#define GCZONE_MAPPING (1 << 1)
+#define GCZONE_BUFFER (1 << 2)
+#define GCZONE_DEST (1 << 3)
+#define GCZONE_SRC (1 << 4)
+#define GCZONE_MASK (1 << 5)
+#define GCZONE_BATCH (1 << 6)
+#define GCZONE_BLIT (1 << 7)
+#define GCZONE_CACHE (1 << 8)
+#define GCZONE_CALLBACK (1 << 9)
+#define GCZONE_TEMP (1 << 10)
+#define GCZONE_BLEND (1 << 11)
+
+GCDBG_FILTERDEF(bv, GCZONE_NONE,
+ "init",
+ "mapping",
+ "buffer",
+ "dest",
+ "source",
+ "mask",
+ "batch",
+ "blit",
+ "cache",
+ "callback",
+ "tempbuffer",
+ "blending")
+
+
+/*******************************************************************************
+** Global driver data access.
+*/
+
+struct gccontext *get_context(void)
+{
+ static struct gccontext gccontext;
+ return &gccontext;
+}
+
+
+/*******************************************************************************
+ * Debugging.
+ */
+
+#if GCDEBUG_ENABLE
+#define GCDUMPBATCH(batch) \
+ dumpbatch(batch)
+
+#define GCVERIFYBATCH(changeflags, prevrect, currrect) \
+ verify_batch(changeflags, prevrect, currrect)
+
+static void dumpbatch(struct gcbatch *gcbatch)
+{
+ struct list_head *gcbufferhead;
+ struct gcbuffer *gcbuffer;
+ struct list_head *gcfixuphead;
+ struct gcfixup *gcfixup;
+ unsigned int i, size;
+
+ if ((GCDBGFILTER.zone & (GCZONE_BUFFER)) == 0)
+ return;
+
+ GCDBG(GCZONE_BUFFER, "BATCH DUMP (0x%08X)\n",
+ (unsigned int) gcbatch);
+
+ list_for_each(gcbufferhead, &gcbatch->buffer) {
+ gcbuffer = list_entry(gcbufferhead, struct gcbuffer, link);
+
+ list_for_each(gcfixuphead, &gcbuffer->fixup) {
+ gcfixup = list_entry(gcfixuphead, struct gcfixup, link);
+
+ GCDBG(GCZONE_BUFFER,
+ " Fixup table @ 0x%08X, count = %d:\n",
+ (unsigned int) gcfixup, gcfixup->count);
+
+ for (i = 0; i < gcfixup->count; i += 1) {
+ GCDBG(GCZONE_BUFFER, " [%02d]"
+ " buffer offset = 0x%08X,"
+ " surface offset = 0x%08X\n",
+ i,
+ gcfixup->fixup[i].dataoffset * 4,
+ gcfixup->fixup[i].surfoffset);
+ }
+ }
+
+ size = (unsigned char *) gcbuffer->tail
+ - (unsigned char *) gcbuffer->head;
+ GCDUMPBUFFER(GCZONE_BUFFER, gcbuffer->head, 0, size);
+ }
+}
+
+static void verify_batch(unsigned int changeflags,
+ struct bvrect *prevrect,
+ struct bvrect *currrect)
+{
+ if ((changeflags & 1) == 0) {
+ /* Origin did not change. */
+ if ((prevrect->left != currrect->left) ||
+ (prevrect->top != currrect->top)) {
+ GCERR("origin changed\n");
+ GCERR(" previous = %d,%d\n",
+ prevrect->left, prevrect->top);
+ GCERR(" current = %d,%d\n",
+ currrect->left, currrect->top);
+ }
+ }
+
+ if ((changeflags & 2) == 0) {
+ /* Size did not change. */
+ if ((prevrect->width != currrect->width) ||
+ (prevrect->height != currrect->height)) {
+ GCERR("size changed\n");
+ GCERR(" previous = %dx%d\n",
+ prevrect->width, prevrect->height);
+ GCERR(" current = %dx%d\n",
+ currrect->width, currrect->height);
+ }
+ }
+
+ prevrect->left = currrect->left;
+ prevrect->top = currrect->top;
+ prevrect->width = currrect->width;
+ prevrect->height = currrect->height;
+}
+#else
+#define GCDUMPBATCH(...)
+#define GCVERIFYBATCH(...)
+#endif
+
+
+/*******************************************************************************
+ * Error handling.
+ */
+
+#define BVSETBLTSURFERROR(errorid, errordesc) \
+do { \
+ struct gccontext *tmpcontext = get_context(); \
+ snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \
+ g_surferr[errorid].message, errordesc.id); \
+ GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \
+ tmpcontext->bverrorstr); \
+ bverror = errordesc.base + g_surferr[errorid].offset; \
+ bvbltparams->errdesc = tmpcontext->bverrorstr; \
+} while (0)
+
+#define GCBVERR_DESC 0
+#define GCBVERR_DESC_VERS 1
+#define GCBVERR_DESC_VIRTADDR 2
+#define GCBVERR_TILE 3
+#define GCBVERR_TILE_VERS 4
+#define GCBVERR_TILE_VIRTADDR 5
+#define GCBVERR_GEOM 6
+#define GCBVERR_GEOM_VERS 7
+#define GCBVERR_GEOM_FORMAT 8
+
+struct bvsurferrorid {
+ char *id;
+ enum bverror base;
+};
+
+struct bvsurferror {
+ unsigned int offset;
+ char *message;
+};
+
+static struct bvsurferror g_surferr[] = {
+ /* GCBVERR_DESC */
+ { 0, "%s desc structure is not set" },
+
+ /* GCBVERR_DESC_VERS */
+ { 100, "%s desc structure has invalid size" },
+
+ /* GCBVERR_DESC_VIRTADDR */
+ { 200, "%s desc virtual pointer is not set" },
+
+ /* GCBVERR_TILE: FIXME/TODO define error code */
+ { 0, "%s tileparams structure is not set" },
+
+ /* GCBVERR_TILE_VERS */
+ { 3000, "%s tileparams structure has invalid size" },
+
+ /* GCBVERR_TILE_VIRTADDR: FIXME/TODO define error code */
+ { 200, "%s tileparams virtual pointer is not set" },
+
+ /* GCBVERR_GEOM */
+ { 1000, "%s geom structure is not set" },
+
+ /* GCBVERR_GEOM_VERS */
+ { 1100, "%s geom structure has invalid size" },
+
+ /* GCBVERR_GEOM_FORMAT */
+ { 1200, "%s invalid format specified" },
+};
+
+static struct bvsurferrorid g_destsurferr = { "dst", BVERR_DSTDESC };
+static struct bvsurferrorid g_src1surferr = { "src1", BVERR_SRC1DESC };
+static struct bvsurferrorid g_src2surferr = { "src2", BVERR_SRC2DESC };
+static struct bvsurferrorid g_masksurferr = { "mask", BVERR_MASKDESC };
+
+
+/*******************************************************************************
+ * Callback info management.
+ */
+
+/* BLTsville callback function. */
+struct gccallbackbltsville {
+ /* Function pointer. */
+ void (*fn) (struct bvcallbackerror *err, unsigned long callbackdata);
+
+ /* Callback data. */
+ unsigned long data;
+};
+
+/* Information for freeing a surface. */
+struct gccallbackfreesurface {
+ /* Pointer to the buffer descriptor. */
+ struct bvbuffdesc *desc;
+
+ /* Pointer to the buffer. */
+ void *ptr;
+};
+
+/* Callback information. */
+struct gccallbackinfo {
+ union {
+ /* BLTsville callback function. */
+ struct gccallbackbltsville callback;
+
+ /* Information for freeing a surface. */
+ struct gccallbackfreesurface freesurface;
+ } info;
+
+ /* Previous/next callback information. */
+ struct list_head link;
+};
+
+static enum bverror get_callbackinfo(struct gccallbackinfo **gccallbackinfo)
+{
+ enum bverror bverror;
+ struct gccontext *gccontext = get_context();
+ struct gccallbackinfo *temp;
+
+ /* Lock access to callback info lists. */
+ GCLOCK(&gccontext->callbacklock);
+
+ if (list_empty(&gccontext->callbackvac)) {
+ temp = gcalloc(struct gccallbackinfo,
+ sizeof(struct gccallbackinfo));
+ if (temp == NULL) {
+ bverror = BVERR_OOM;
+ goto exit;
+ }
+ list_add(&temp->link, &gccontext->callbacklist);
+ } else {
+ struct list_head *head;
+ head = gccontext->callbackvac.next;
+ temp = list_entry(head, struct gccallbackinfo, link);
+ list_move(head, &gccontext->callbacklist);
+ }
+
+ *gccallbackinfo = temp;
+ bverror = BVERR_NONE;
+
+exit:
+ /* Unlock access to callback info lists. */
+ GCUNLOCK(&gccontext->callbacklock);
+
+ return bverror;
+}
+
+static void free_callback(struct gccallbackinfo *gccallbackinfo)
+{
+ struct gccontext *gccontext = get_context();
+
+ /* Lock access to callback info lists. */
+ GCLOCK(&gccontext->callbacklock);
+
+ list_move(&gccallbackinfo->link, &gccontext->callbackvac);
+
+ /* Unlock access to callback info lists. */
+ GCUNLOCK(&gccontext->callbacklock);
+}
+
+void callbackbltsville(void *callbackinfo)
+{
+ struct gccallbackinfo *gccallbackinfo;
+
+ GCENTER(GCZONE_CALLBACK);
+
+ gccallbackinfo = (struct gccallbackinfo *) callbackinfo;
+ GCDBG(GCZONE_CALLBACK, "bltsville_callback = 0x%08X\n",
+ (unsigned int) gccallbackinfo->info.callback.fn);
+ GCDBG(GCZONE_CALLBACK, "bltsville_param = 0x%08X\n",
+ (unsigned int) gccallbackinfo->info.callback.data);
+
+ gccallbackinfo->info.callback.fn(NULL,
+ gccallbackinfo->info.callback.data);
+ free_callback(gccallbackinfo);
+
+ GCEXIT(GCZONE_CALLBACK);
+}
+
+void callbackfreesurface(void *callbackinfo)
+{
+ struct gccallbackinfo *gccallbackinfo;
+
+ GCENTER(GCZONE_CALLBACK);
+
+ gccallbackinfo = (struct gccallbackinfo *) callbackinfo;
+ GCDBG(GCZONE_CALLBACK, "freeing descriptir @ 0x%08X\n",
+ (unsigned int) gccallbackinfo->info.freesurface.desc);
+ GCDBG(GCZONE_CALLBACK, "freeing memory @ 0x%08X\n",
+ (unsigned int) gccallbackinfo->info.freesurface.ptr);
+
+ free_surface(gccallbackinfo->info.freesurface.desc,
+ gccallbackinfo->info.freesurface.ptr);
+ free_callback(gccallbackinfo);
+
+ GCEXIT(GCZONE_CALLBACK);
+}
+
+
+/*******************************************************************************
+ * Temporary buffer management.
+ */
+
+enum bverror allocate_temp(struct bvbltparams *bvbltparams,
+ unsigned int size)
+{
+ enum bverror bverror;
+ struct gccontext *gccontext = get_context();
+
+ GCENTER(GCZONE_TEMP);
+
+ /* Existing buffer too small? */
+ if ((gccontext->tmpbuffdesc != NULL) &&
+ (gccontext->tmpbuffdesc->length < size)) {
+ GCDBG(GCZONE_TEMP, "freeing current buffer.\n");
+ bverror = free_temp(true);
+ if (bverror != BVERR_NONE) {
+ bvbltparams->errdesc = gccontext->bverrorstr;
+ goto exit;
+ }
+ }
+
+ /* Allocate new buffer if necessary. */
+ if ((size > 0) && (gccontext->tmpbuffdesc == NULL)) {
+ /* Allocate temporary surface. */
+ bverror = allocate_surface(&gccontext->tmpbuffdesc,
+ &gccontext->tmpbuff,
+ size);
+ if (bverror != BVERR_NONE) {
+ bvbltparams->errdesc = gccontext->bverrorstr;
+ goto exit;
+ }
+
+ GCDBG(GCZONE_TEMP, "buffdesc @ 0x%08X\n",
+ gccontext->tmpbuffdesc);
+ GCDBG(GCZONE_TEMP, "allocated @ 0x%08X\n",
+ gccontext->tmpbuff);
+ GCDBG(GCZONE_TEMP, "size = %d\n",
+ size);
+
+ /* Map the buffer explicitly. */
+ bverror = bv_map(gccontext->tmpbuffdesc);
+ if (bverror != BVERR_NONE) {
+ bvbltparams->errdesc = gccontext->bverrorstr;
+ goto exit;
+ }
+ }
+
+ /* Success. */
+ bverror = BVERR_NONE;
+
+exit:
+ GCEXIT(GCZONE_TEMP);
+ return bverror;
+}
+
+enum bverror free_temp(bool schedule)
+{
+ enum bverror bverror;
+ struct gccontext *gccontext = get_context();
+ struct gccallbackinfo *gccallbackinfo;
+ struct gcicallbackarm gcicallbackarm;
+
+ /* Is the buffer allocated? */
+ if (gccontext->tmpbuffdesc == NULL) {
+ bverror = BVERR_NONE;
+ goto exit;
+ }
+
+ /* Unmap the buffer. */
+ bverror = bv_unmap(gccontext->tmpbuffdesc);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Cannot be mapped. */
+ if (gccontext->tmpbuffdesc->map != NULL) {
+ BVSETERROR(BVERR_OOM, "temporary buffer is still mapped");
+ goto exit;
+ }
+
+ /* Free the buffer. */
+ if (schedule) {
+ bverror = get_callbackinfo(&gccallbackinfo);
+ if (bverror != BVERR_NONE) {
+ BVSETERROR(BVERR_OOM,
+ "callback allocation failed");
+ goto exit;
+ }
+
+ gccallbackinfo->info.freesurface.desc = gccontext->tmpbuffdesc;
+ gccallbackinfo->info.freesurface.ptr = gccontext->tmpbuff;
+ gcicallbackarm.callback = callbackfreesurface;
+ gcicallbackarm.callbackparam = gccallbackinfo;
+
+ /* Schedule to free the buffer. */
+ gc_callback_wrapper(&gcicallbackarm);
+
+ /* Error? */
+ if (gcicallbackarm.gcerror != GCERR_NONE) {
+ BVSETERROR(BVERR_OOM, "unable to schedule callback");
+ goto exit;
+ }
+ } else {
+ /* Free the buffer immediately. */
+ free_surface(gccontext->tmpbuffdesc, gccontext->tmpbuff);
+ }
+
+ /* Reset the buffer descriptor. */
+ gccontext->tmpbuffdesc = NULL;
+ gccontext->tmpbuff = NULL;
+
+exit:
+ return bverror;
+}
+
+
+/*******************************************************************************
+ * Program the destination.
+ */
+
+enum bverror set_dst(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct bvbuffmap *dstmap)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gcsurface *dstinfo;
+ struct gcmodst *gcmodst;
+
+ GCENTER(GCZONE_DEST);
+
+ /* Get a shortcut to the destination surface descriptor. */
+ dstinfo = &batch->dstinfo;
+
+ /* Did destination surface change? */
+ if (dstinfo->surfdirty) {
+ /* Allocate command buffer. */
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmodst),
+ (void **) &gcmodst);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Add the address fixup. */
+ add_fixup(bvbltparams, batch, &gcmodst->address,
+ dstinfo->bytealign1);
+
+ /* Set surface parameters. */
+ gcmodst->config_ldst = gcmodst_config_ldst;
+ gcmodst->address = GET_MAP_HANDLE(dstmap);
+ gcmodst->stride = dstinfo->stride1;
+
+ /* Set surface width and height. */
+ gcmodst->rotation.raw = 0;
+ gcmodst->rotation.reg.surf_width = dstinfo->physwidth;
+ gcmodst->rotationheight_ldst = gcmodst_rotationheight_ldst;
+ gcmodst->rotationheight.raw = 0;
+ gcmodst->rotationheight.reg.height = dstinfo->physheight;
+
+ /* Disable hardware clipping. */
+ gcmodst->clip_ldst = gcmodst_clip_ldst;
+ gcmodst->cliplt.raw = 0;
+ gcmodst->cliprb.raw = 0;
+ gcmodst->cliprb.reg.right = GC_CLIP_RESET_RIGHT;
+ gcmodst->cliprb.reg.bottom = GC_CLIP_RESET_BOTTOM;
+ }
+
+exit:
+ GCEXITARG(GCZONE_DEST, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+
+/*******************************************************************************
+ * Program blending.
+ */
+
+enum bverror set_blending(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gcmoalphaoff *gcmoalphaoff;
+ struct gcmoalpha *gcmoalpha;
+ struct gcmoglobal *gcmoglobal;
+ struct gcalpha *gca;
+
+ GCENTER(GCZONE_BLEND);
+
+ gca = srcinfo->gca;
+ if (gca == NULL) {
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoalphaoff),
+ (void **) &gcmoalphaoff);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ gcmoalphaoff->control_ldst = gcmoalphaoff_control_ldst[0];
+ gcmoalphaoff->control.reg = gcregalpha_off;
+
+ GCDBG(GCZONE_BLEND, "blending disabled.\n");
+ } else {
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoalpha),
+ (void **) &gcmoalpha);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ gcmoalpha->config_ldst = gcmoalpha_config_ldst;
+ gcmoalpha->control.reg = gcregalpha_on;
+
+ gcmoalpha->mode.raw = 0;
+ gcmoalpha->mode.reg.src_global_alpha_mode
+ = srcinfo->srcglobalmode;
+ gcmoalpha->mode.reg.dst_global_alpha_mode
+ = srcinfo->dstglobalmode;
+
+ gcmoalpha->mode.reg.src_blend
+ = gca->srcconfig->factor_mode;
+ gcmoalpha->mode.reg.src_color_reverse
+ = gca->srcconfig->color_reverse;
+
+ gcmoalpha->mode.reg.dst_blend
+ = gca->dstconfig->factor_mode;
+ gcmoalpha->mode.reg.dst_color_reverse
+ = gca->dstconfig->color_reverse;
+
+ GCDBG(GCZONE_BLEND, "dst blend:\n");
+ GCDBG(GCZONE_BLEND, " factor = %d\n",
+ gcmoalpha->mode.reg.dst_blend);
+ GCDBG(GCZONE_BLEND, " inverse = %d\n",
+ gcmoalpha->mode.reg.dst_color_reverse);
+
+ GCDBG(GCZONE_BLEND, "src blend:\n");
+ GCDBG(GCZONE_BLEND, " factor = %d\n",
+ gcmoalpha->mode.reg.src_blend);
+ GCDBG(GCZONE_BLEND, " inverse = %d\n",
+ gcmoalpha->mode.reg.src_color_reverse);
+ }
+
+ if (srcinfo->globalcolorenable) {
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoglobal),
+ (void **) &gcmoglobal);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ gcmoglobal->color_ldst = gcmoglobal_color_ldst;
+ gcmoglobal->srcglobal.raw = srcinfo->globalcolor;
+ gcmoglobal->dstglobal.raw = srcinfo->globalcolor;
+ }
+
+exit:
+ GCEXITARG(GCZONE_BLEND, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+enum bverror set_blending_index(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo,
+ unsigned int index)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gcmoalphaoff *gcmoalphaoff;
+ struct gcmoxsrcalpha *gcmoxsrcalpha;
+ struct gcmoxsrcglobal *gcmoxsrcglobal;
+ struct gcalpha *gca;
+
+ GCENTER(GCZONE_BLEND);
+
+ gca = srcinfo->gca;
+ if (gca == NULL) {
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoalphaoff),
+ (void **) &gcmoalphaoff);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ gcmoalphaoff->control_ldst = gcmoalphaoff_control_ldst[index];
+ gcmoalphaoff->control.reg = gcregalpha_off;
+
+ GCDBG(GCZONE_BLEND, "blending disabled.\n");
+ } else {
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoxsrcalpha),
+ (void **) &gcmoxsrcalpha);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ gcmoxsrcalpha->control_ldst = gcmoxsrcalpha_control_ldst[index];
+ gcmoxsrcalpha->control.reg = gcregalpha_on;
+
+ gcmoxsrcalpha->mode_ldst = gcmoxsrcalpha_mode_ldst[index];
+ gcmoxsrcalpha->mode.raw = 0;
+ gcmoxsrcalpha->mode.reg.src_global_alpha_mode
+ = srcinfo->srcglobalmode;
+ gcmoxsrcalpha->mode.reg.dst_global_alpha_mode
+ = srcinfo->dstglobalmode;
+
+ gcmoxsrcalpha->mode.reg.src_blend
+ = gca->srcconfig->factor_mode;
+ gcmoxsrcalpha->mode.reg.src_color_reverse
+ = gca->srcconfig->color_reverse;
+
+ gcmoxsrcalpha->mode.reg.dst_blend
+ = gca->dstconfig->factor_mode;
+ gcmoxsrcalpha->mode.reg.dst_color_reverse
+ = gca->dstconfig->color_reverse;
+
+ GCDBG(GCZONE_BLEND, "dst blend:\n");
+ GCDBG(GCZONE_BLEND, " factor = %d\n",
+ gcmoxsrcalpha->mode.reg.dst_blend);
+ GCDBG(GCZONE_BLEND, " inverse = %d\n",
+ gcmoxsrcalpha->mode.reg.dst_color_reverse);
+
+ GCDBG(GCZONE_BLEND, "src blend:\n");
+ GCDBG(GCZONE_BLEND, " factor = %d\n",
+ gcmoxsrcalpha->mode.reg.src_blend);
+ GCDBG(GCZONE_BLEND, " inverse = %d\n",
+ gcmoxsrcalpha->mode.reg.src_color_reverse);
+ }
+
+ if (srcinfo->globalcolorenable) {
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoxsrcglobal),
+ (void **) &gcmoxsrcglobal);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ gcmoxsrcglobal->srcglobal_ldst
+ = gcmoxsrcglobal_srcglobal_ldst[index];
+ gcmoxsrcglobal->srcglobal.raw = srcinfo->globalcolor;
+
+ gcmoxsrcglobal->dstglobal_ldst
+ = gcmoxsrcglobal_dstglobal_ldst[index];
+ gcmoxsrcglobal->dstglobal.raw = srcinfo->globalcolor;
+ }
+
+exit:
+ GCEXITARG(GCZONE_BLEND, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+/*******************************************************************************
+ * Program YUV source.
+ */
+
+void set_computeyuv(struct gcsurface *srcinfo, int x, int y)
+{
+ int pixalign, bytealign;
+ unsigned int height1, size1;
+ unsigned int height2, size2;
+ unsigned int origin;
+ int ssX, ssY;
+
+ GCENTER(GCZONE_SRC);
+
+ /* Compute base address alignment. */
+ pixalign = get_pixel_offset(srcinfo, 0);
+ bytealign = (pixalign * (int) srcinfo->format.bitspp) / 8;
+
+ /* Determine the physical height of the first plane. */
+ height1 = ((srcinfo->angle % 2) == 0)
+ ? srcinfo->height
+ : srcinfo->width;
+
+ /* Determine the size of the first plane. */
+ size1 = srcinfo->stride1 * height1;
+
+ /* Determine the stride of the second plane. */
+ srcinfo->stride2 = srcinfo->stride1
+ / srcinfo->format.cs.yuv.xsample;
+
+ /* Determine subsample pixel position. */
+ ssX = x / srcinfo->format.cs.yuv.xsample;
+ ssY = y / srcinfo->format.cs.yuv.ysample;
+
+ switch (srcinfo->format.cs.yuv.planecount) {
+ case 2:
+ /* U and V are interleaved in one plane. */
+ ssX *= 2;
+ srcinfo->stride2 *= 2;
+
+ /* Determnine the origin offset. */
+ origin = ssY * srcinfo->stride2 + ssX;
+
+ /* Compute the alignment of the second plane. */
+ srcinfo->bytealign2 = bytealign + size1 + origin;
+
+ GCDBG(GCZONE_SRC, "plane2 offset (bytes) = 0x%08X\n",
+ srcinfo->bytealign2);
+ GCDBG(GCZONE_SRC, "plane2 stride = %d\n",
+ srcinfo->stride2);
+ break;
+
+ case 3:
+ /* Determine the physical height of the U/V planes. */
+ height2 = height1 / srcinfo->format.cs.yuv.ysample;
+
+ /* Determine the size of the U/V planes. */
+ size2 = srcinfo->stride2 * height2;
+
+ /* Determnine the origin offset. */
+ origin = ssY * srcinfo->stride2 + ssX;
+
+ /* Compute the alignment of the U/V planes. */
+ srcinfo->bytealign2 = bytealign + size1 + origin;
+ srcinfo->bytealign3 = bytealign + size1 + size2 + origin;
+
+ /* Determine the stride of the U/V planes. */
+ srcinfo->stride3 = srcinfo->stride2;
+
+ GCDBG(GCZONE_SRC, "plane2 offset (bytes) = 0x%08X\n",
+ srcinfo->bytealign2);
+ GCDBG(GCZONE_SRC, "plane2 stride = %d\n",
+ srcinfo->stride2);
+ GCDBG(GCZONE_SRC, "plane3 offset (bytes) = 0x%08X\n",
+ srcinfo->bytealign3);
+ GCDBG(GCZONE_SRC, "plane3 stride = %d\n",
+ srcinfo->stride3);
+ break;
+ }
+
+ GCEXIT(GCZONE_SRC);
+}
+
+enum bverror set_yuvsrc(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo,
+ struct bvbuffmap *srcmap)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gcmoyuv1 *gcmoyuv1;
+ struct gcmoyuv2 *gcmoyuv2;
+ struct gcmoyuv3 *gcmoyuv3;
+
+ GCENTER(GCZONE_SRC);
+
+ GCDBG(GCZONE_SRC, "plane count %d.\n",
+ srcinfo->format.cs.yuv.planecount);
+
+ switch (srcinfo->format.cs.yuv.planecount) {
+ case 1:
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoyuv1),
+ (void **) &gcmoyuv1);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Set YUV parameters. */
+ gcmoyuv1->pectrl_ldst = gcmoyuv_pectrl_ldst;
+ gcmoyuv1->pectrl.raw = 0;
+ gcmoyuv1->pectrl.reg.standard
+ = srcinfo->format.cs.yuv.std;
+ gcmoyuv1->pectrl.reg.swizzle
+ = srcinfo->format.swizzle;
+ gcmoyuv1->pectrl.reg.convert
+ = GCREG_PE_CONTROL_YUVRGB_DISABLED;
+ break;
+
+ case 2:
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoyuv2),
+ (void **) &gcmoyuv2);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Set YUV parameters. */
+ gcmoyuv2->pectrl_ldst = gcmoyuv_pectrl_ldst;
+ gcmoyuv2->pectrl.raw = 0;
+ gcmoyuv2->pectrl.reg.standard
+ = srcinfo->format.cs.yuv.std;
+ gcmoyuv2->pectrl.reg.swizzle
+ = srcinfo->format.swizzle;
+ gcmoyuv2->pectrl.reg.convert
+ = GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+ /* Program U/V plane. */
+ add_fixup(bvbltparams, batch, &gcmoyuv2->uplaneaddress,
+ srcinfo->bytealign2);
+ gcmoyuv2->plane_ldst = gcmoyuv2_plane_ldst;
+ gcmoyuv2->uplaneaddress = GET_MAP_HANDLE(srcmap);
+ gcmoyuv2->uplanestride = srcinfo->stride2;
+ break;
+
+ case 3:
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoyuv3),
+ (void **) &gcmoyuv3);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Set YUV parameters. */
+ gcmoyuv3->pectrl_ldst = gcmoyuv_pectrl_ldst;
+ gcmoyuv3->pectrl.raw = 0;
+ gcmoyuv3->pectrl.reg.standard
+ = srcinfo->format.cs.yuv.std;
+ gcmoyuv3->pectrl.reg.swizzle
+ = srcinfo->format.swizzle;
+ gcmoyuv3->pectrl.reg.convert
+ = GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+ /* Program U/V planes. */
+ add_fixup(bvbltparams, batch, &gcmoyuv3->uplaneaddress,
+ srcinfo->bytealign2);
+ add_fixup(bvbltparams, batch, &gcmoyuv3->vplaneaddress,
+ srcinfo->bytealign3);
+ gcmoyuv3->plane_ldst = gcmoyuv3_plane_ldst;
+ gcmoyuv3->uplaneaddress = GET_MAP_HANDLE(srcmap);
+ gcmoyuv3->uplanestride = srcinfo->stride2;
+ gcmoyuv3->vplaneaddress = GET_MAP_HANDLE(srcmap);
+ gcmoyuv3->vplanestride = srcinfo->stride3;
+ break;
+
+ default:
+ GCERR("invlaid plane count %d.\n",
+ srcinfo->format.cs.yuv.planecount);
+ }
+
+exit:
+ GCEXITARG(GCZONE_SRC, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo,
+ struct bvbuffmap *srcmap,
+ unsigned int index)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gcmoxsrcyuv1 *gcmoxsrcyuv1;
+ struct gcmoxsrcyuv2 *gcmoxsrcyuv2;
+ struct gcmoxsrcyuv3 *gcmoxsrcyuv3;
+
+ GCENTER(GCZONE_SRC);
+
+ GCDBG(GCZONE_SRC, "plane count %d.\n",
+ srcinfo->format.cs.yuv.planecount);
+
+ switch (srcinfo->format.cs.yuv.planecount) {
+ case 1:
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoxsrcyuv1),
+ (void **) &gcmoxsrcyuv1);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Set YUV parameters. */
+ gcmoxsrcyuv1->pectrl_ldst
+ = gcmoxsrcyuv_pectrl_ldst[index];
+ gcmoxsrcyuv1->pectrl.raw = 0;
+ gcmoxsrcyuv1->pectrl.reg.standard
+ = srcinfo->format.cs.yuv.std;
+ gcmoxsrcyuv1->pectrl.reg.swizzle
+ = srcinfo->format.swizzle;
+ gcmoxsrcyuv1->pectrl.reg.convert
+ = GCREG_PE_CONTROL_YUVRGB_DISABLED;
+ break;
+
+ case 2:
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoxsrcyuv2),
+ (void **) &gcmoxsrcyuv2);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Set YUV parameters. */
+ gcmoxsrcyuv2->pectrl_ldst
+ = gcmoxsrcyuv_pectrl_ldst[index];
+ gcmoxsrcyuv2->pectrl.raw = 0;
+ gcmoxsrcyuv2->pectrl.reg.standard
+ = srcinfo->format.cs.yuv.std;
+ gcmoxsrcyuv2->pectrl.reg.swizzle
+ = srcinfo->format.swizzle;
+ gcmoxsrcyuv2->pectrl.reg.convert
+ = GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+ /* Program U/V plane. */
+ add_fixup(bvbltparams, batch, &gcmoxsrcyuv2->uplaneaddress,
+ srcinfo->bytealign2);
+ gcmoxsrcyuv2->uplaneaddress_ldst
+ = gcmoxsrcyuv_uplaneaddress_ldst[index];
+ gcmoxsrcyuv2->uplaneaddress = GET_MAP_HANDLE(srcmap);
+ gcmoxsrcyuv2->uplanestride_ldst
+ = gcmoxsrcyuv_uplanestride_ldst[index];
+ gcmoxsrcyuv2->uplanestride = srcinfo->stride2;
+ break;
+
+ case 3:
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmoxsrcyuv3),
+ (void **) &gcmoxsrcyuv3);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Set YUV parameters. */
+ gcmoxsrcyuv3->pectrl_ldst
+ = gcmoxsrcyuv_pectrl_ldst[index];
+ gcmoxsrcyuv3->pectrl.raw = 0;
+ gcmoxsrcyuv3->pectrl.reg.standard
+ = srcinfo->format.cs.yuv.std;
+ gcmoxsrcyuv3->pectrl.reg.swizzle
+ = srcinfo->format.swizzle;
+ gcmoxsrcyuv3->pectrl.reg.convert
+ = GCREG_PE_CONTROL_YUVRGB_DISABLED;
+
+ /* Program U/V planes. */
+ add_fixup(bvbltparams, batch, &gcmoxsrcyuv3->uplaneaddress,
+ srcinfo->bytealign2);
+ add_fixup(bvbltparams, batch, &gcmoxsrcyuv3->vplaneaddress,
+ srcinfo->bytealign3);
+ gcmoxsrcyuv3->uplaneaddress_ldst
+ = gcmoxsrcyuv_uplaneaddress_ldst[index];
+ gcmoxsrcyuv3->uplaneaddress = GET_MAP_HANDLE(srcmap);
+ gcmoxsrcyuv3->uplanestride_ldst
+ = gcmoxsrcyuv_uplanestride_ldst[index];
+ gcmoxsrcyuv3->uplanestride = srcinfo->stride2;
+ gcmoxsrcyuv3->vplaneaddress_ldst
+ = gcmoxsrcyuv_vplaneaddress_ldst[index];
+ gcmoxsrcyuv3->vplaneaddress = GET_MAP_HANDLE(srcmap);
+ gcmoxsrcyuv3->vplanestride_ldst
+ = gcmoxsrcyuv_vplanestride_ldst[index];
+ gcmoxsrcyuv3->vplanestride = srcinfo->stride3;
+ break;
+
+ default:
+ GCERR("invlaid plane count %d.\n",
+ srcinfo->format.cs.yuv.planecount);
+ }
+
+exit:
+ GCEXITARG(GCZONE_SRC, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+
+/*******************************************************************************
+ * Surface compare and validation.
+ */
+
+static inline bool equal_rects(struct bvrect *rect1, struct bvrect *rect2)
+{
+ if (rect1->left != rect2->left)
+ return false;
+
+ if (rect1->top != rect2->top)
+ return false;
+
+ if (rect1->width != rect2->width)
+ return false;
+
+ if (rect1->height != rect2->height)
+ return false;
+
+ return true;
+}
+
+/* The function verifies whether the two buffer descriptors and rectangles
+ define the same physical area. */
+static bool same_phys_area(struct bvbuffdesc *surf1, struct bvrect *rect1,
+ struct bvbuffdesc *surf2, struct bvrect *rect2)
+{
+ struct bvphysdesc *physdesc1;
+ struct bvphysdesc *physdesc2;
+
+ /* If pointers are the same, things are much easier. */
+ if (surf1 == surf2)
+ /* Compare the rectangles. For simplicity we don't consider
+ cases with partially overlapping rectangles at this time. */
+ return equal_rects(rect1, rect2);
+
+ /* Assume diffrent areas if the types are different. */
+ if (surf1->auxtype != surf2->auxtype)
+ return false;
+
+ if (surf1->auxtype == BVAT_PHYSDESC) {
+ physdesc1 = (struct bvphysdesc *) surf1->auxptr;
+ physdesc2 = (struct bvphysdesc *) surf2->auxptr;
+
+ /* Same physical descriptor? */
+ if (physdesc1 == physdesc2)
+ return equal_rects(rect1, rect2);
+
+ /* Same page array? */
+ if (physdesc1->pagearray == physdesc2->pagearray)
+ return equal_rects(rect1, rect2);
+
+ /* Pageoffsets must match since different buffers
+ * can share the same first page (eg nv12).
+ */
+ if (physdesc1->pageoffset != physdesc2->pageoffset)
+ return false;
+
+ /* Assume the same surface if first pages match. */
+ if (physdesc1->pagearray[0] == physdesc2->pagearray[0])
+ return equal_rects(rect1, rect2);
+
+ } else {
+ if (surf1->virtaddr == surf2->virtaddr)
+ return equal_rects(rect1, rect2);
+ }
+
+ return false;
+}
+
+static int verify_surface(unsigned int tile,
+ union bvinbuff *surf,
+ struct bvsurfgeom *geom)
+{
+ if (tile) {
+ if (surf->tileparams == NULL)
+ return GCBVERR_TILE;
+
+ if (surf->tileparams->structsize <
+ STRUCTSIZE(surf->tileparams, srcheight))
+ return GCBVERR_TILE_VERS;
+
+ /* FIXME/TODO */
+ return GCBVERR_TILE;
+ } else {
+ if (surf->desc == NULL)
+ return GCBVERR_DESC;
+
+ if (surf->desc->structsize < STRUCTSIZE(surf->desc, map))
+ return GCBVERR_DESC_VERS;
+ }
+
+ if (geom == NULL)
+ return GCBVERR_GEOM;
+
+ if (geom->structsize < STRUCTSIZE(geom, palette))
+ return GCBVERR_GEOM_VERS;
+
+ /* Validation successful. */
+ return -1;
+}
+
+
+/*******************************************************************************
+ * Operation.
+ */
+
+static enum bverror do_op(struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch,
+ int srccount,
+ struct gcsurface *srcinfo,
+ struct gcalpha *gca)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gcsurface *dstinfo;
+ int sw, sh, dw, dh;
+
+ GCDBG(GCZONE_BLIT, "processing source %d.\n", srcinfo->index + 1);
+
+ if (gca == NULL) {
+ GCDBG(GCZONE_BLIT,
+ " blending disabled.\n");
+
+ srcinfo->gca = NULL;
+ srcinfo->globalcolorenable = false;
+ srcinfo->srcglobalpremul = GCREG_SRC_GLOBAL_PREMULTIPLY_DISABLE;
+ srcinfo->srcglobalmode = GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+ srcinfo->dstglobalmode = GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+ } else {
+ if (srcinfo->index == 0) {
+ /* First source. */
+
+ if (srccount == 1) {
+ /* Only one source. */
+ GCDBG(GCZONE_BLIT,
+ " enabling blending.\n");
+
+ srcinfo->gca = gca;
+ gca->srcconfig = gca->k1;
+ gca->dstconfig = gca->k2;
+
+ } else {
+ /* Two sources. */
+ GCDBG(GCZONE_BLIT,
+ " disabling blending for src1.\n");
+
+ srcinfo->gca = NULL;
+ }
+
+ if (gca->globalcolorenable) {
+ srcinfo->globalcolorenable = true;
+ srcinfo->globalcolor = gca->globalcolor;
+ srcinfo->srcglobalpremul
+ = GCREG_SRC_GLOBAL_PREMULTIPLY_ALPHA;
+ srcinfo->srcglobalmode
+ = GCREG_GLOBAL_ALPHA_MODE_SCALED;
+ srcinfo->dstglobalmode
+ = GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+ } else {
+ srcinfo->globalcolorenable = false;
+ srcinfo->srcglobalpremul
+ = GCREG_SRC_GLOBAL_PREMULTIPLY_DISABLE;
+ srcinfo->srcglobalmode
+ = GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+ srcinfo->dstglobalmode
+ = GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+ }
+ } else {
+ /* Second source. */
+ GCDBG(GCZONE_BLIT,
+ " enabling blending.\n");
+
+ srcinfo->gca = gca;
+ gca->srcconfig = gca->k2;
+ gca->dstconfig = gca->k1;
+
+ if (gca->globalcolorenable) {
+ srcinfo->globalcolorenable = true;
+ srcinfo->globalcolor = gca->globalcolor;
+ srcinfo->srcglobalpremul
+ = GCREG_SRC_GLOBAL_PREMULTIPLY_DISABLE;
+ srcinfo->srcglobalmode
+ = GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+ srcinfo->dstglobalmode
+ = GCREG_GLOBAL_ALPHA_MODE_SCALED;
+ } else {
+ srcinfo->globalcolorenable = false;
+ srcinfo->srcglobalpremul
+ = GCREG_SRC_GLOBAL_PREMULTIPLY_DISABLE;
+ srcinfo->srcglobalmode
+ = GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+ srcinfo->dstglobalmode
+ = GCREG_GLOBAL_ALPHA_MODE_NORMAL;
+ }
+ }
+ }
+
+ sw = srcinfo->rect.orig.right - srcinfo->rect.orig.left;
+ sh = srcinfo->rect.orig.bottom - srcinfo->rect.orig.top;
+
+ dw = bvbltparams->dstrect.width;
+ dh = bvbltparams->dstrect.height;
+
+ GCDBG(GCZONE_BLIT, " srcsize %dx%d.\n", sw, sh);
+ GCDBG(GCZONE_BLIT, " dstsize %dx%d.\n", dw, dh);
+
+ if ((sw == 0) || (sh == 0)) {
+ GCDBG(GCZONE_BLIT, " empty source, skipping.\n");
+ } else if ((dw == 0) || (dh == 0)) {
+ GCDBG(GCZONE_BLIT, " empty destination, skipping.\n");
+ } else if ((sw == 1) && (sh == 1) && (srcinfo->buf.desc->virtaddr)) {
+ GCDBG(GCZONE_BLIT, " op: fill.\n");
+ bverror = do_fill(bvbltparams, gcbatch, srcinfo);
+ } else if ((sw == dw) && (sh == dh)) {
+ GCDBG(GCZONE_BLIT, " op: bitblit.\n");
+ bverror = do_blit(bvbltparams, gcbatch, srcinfo);
+ } else {
+ GCDBG(GCZONE_BLIT, " op: filter.\n");
+ bverror = do_filter(bvbltparams, gcbatch, srcinfo);
+ }
+
+ /* Reset dirty flags. */
+ dstinfo = &gcbatch->dstinfo;
+ dstinfo->surfdirty = false;
+ dstinfo->rectdirty = false;
+ dstinfo->cliprectdirty = false;
+ dstinfo->destrectdirty = false;
+
+ return bverror;
+}
+
+
+/*******************************************************************************
+ * Library constructor and destructor.
+ */
+
+void bv_init(void)
+{
+ struct gccontext *gccontext = get_context();
+ struct gcicaps gcicaps;
+ unsigned i, j;
+
+ GCDBG_REGISTER(bv, ~GCZONE_BUFFER);
+ GCDBG_REGISTER(parser, GCZONE_ALL);
+ GCDBG_REGISTER(map, GCZONE_NONE);
+ GCDBG_REGISTER(buffer, GCZONE_NONE);
+ GCDBG_REGISTER(fill, GCZONE_ALL);
+ GCDBG_REGISTER(blit, GCZONE_ALL);
+ GCDBG_REGISTER(filter, GCZONE_ALL);
+
+ gcbv_debug_init();
+
+ GCLOCK_INIT(&gccontext->batchlock);
+ GCLOCK_INIT(&gccontext->bufferlock);
+ GCLOCK_INIT(&gccontext->fixuplock);
+ GCLOCK_INIT(&gccontext->maplock);
+ GCLOCK_INIT(&gccontext->callbacklock);
+
+ INIT_LIST_HEAD(&gccontext->unmapvac);
+ INIT_LIST_HEAD(&gccontext->buffervac);
+ INIT_LIST_HEAD(&gccontext->fixupvac);
+ INIT_LIST_HEAD(&gccontext->batchvac);
+ INIT_LIST_HEAD(&gccontext->callbacklist);
+ INIT_LIST_HEAD(&gccontext->callbackvac);
+
+ /* Initialize the filter cache. */
+ for (i = 0; i < GC_FILTER_COUNT; i += 1)
+ for (j = 0; j < GC_TAP_COUNT; j += 1)
+ INIT_LIST_HEAD(&gccontext->filtercache[i][j].list);
+
+ /* Query hardware caps. */
+ gc_getcaps_wrapper(&gcicaps);
+ if (gcicaps.gcerror == GCERR_NONE) {
+ gccontext->gcmodel = gcicaps.gcmodel;
+ gccontext->gcrevision = gcicaps.gcrevision;
+ gccontext->gcdate = gcicaps.gcdate;
+ gccontext->gctime = gcicaps.gctime;
+
+ gccontext->gccaps.l2cachefor420
+ = (gcicaps.gcfeatures2.reg.l2cachefor420 != 0);
+
+ if (gcicaps.gcfeatures3.reg.newfeatures0) {
+ gccontext->gccaps.maxsource = 8;
+ gccontext->gccaps.strictalign = false;
+ } else {
+ gccontext->gccaps.maxsource = 4;
+ gccontext->gccaps.strictalign = true;
+ }
+
+ gccontext->gccaps.swizzlefixed
+ = (gcicaps.gcfeatures3.reg.deenhancements1 != 0);
+
+ GCDBG(GCZONE_INIT, "chip model: %X\n",
+ gccontext->gcmodel);
+ GCDBG(GCZONE_INIT, "chip revision: %X\n",
+ gccontext->gcrevision);
+ GCDBG(GCZONE_INIT, "chip date: %X\n",
+ gccontext->gcdate);
+ GCDBG(GCZONE_INIT, "chip time: %X\n",
+ gccontext->gctime);
+ GCDBG(GCZONE_INIT, "max source: %d\n",
+ gccontext->gccaps.maxsource);
+ GCDBG(GCZONE_INIT, "strict alignment: %d\n",
+ gccontext->gccaps.strictalign);
+ GCDBG(GCZONE_INIT, "swizzle fixed: %d\n",
+ gccontext->gccaps.swizzlefixed);
+ } else {
+ GCERR("failed to get chip caps.\n");
+ gccontext->gccaps.l2cachefor420 = false;
+ gccontext->gccaps.maxsource = 4;
+ gccontext->gccaps.strictalign = true;
+ gccontext->gccaps.swizzlefixed = false;
+ }
+}
+
+void bv_exit(void)
+{
+ struct gccontext *gccontext = get_context();
+ struct bvbuffmap *bvbuffmap;
+ struct list_head *head;
+ struct gcschedunmap *gcschedunmap;
+ struct gcbuffer *gcbuffer;
+ struct gcfixup *gcfixup;
+ struct gcbatch *gcbatch;
+ struct gccallbackinfo *gccallbackinfo;
+
+ while (gccontext->buffmapvac != NULL) {
+ bvbuffmap = gccontext->buffmapvac;
+ gccontext->buffmapvac = bvbuffmap->nextmap;
+ gcfree(bvbuffmap);
+ }
+
+ while (!list_empty(&gccontext->unmapvac)) {
+ head = gccontext->unmapvac.next;
+ gcschedunmap = list_entry(head, struct gcschedunmap, link);
+ list_del(head);
+ gcfree(gcschedunmap);
+ }
+
+ while (!list_empty(&gccontext->buffervac)) {
+ head = gccontext->buffervac.next;
+ gcbuffer = list_entry(head, struct gcbuffer, link);
+ list_del(head);
+ gcfree(gcbuffer);
+ }
+
+ while (!list_empty(&gccontext->fixupvac)) {
+ head = gccontext->fixupvac.next;
+ gcfixup = list_entry(head, struct gcfixup, link);
+ list_del(head);
+ gcfree(gcfixup);
+ }
+
+ while (!list_empty(&gccontext->batchvac)) {
+ head = gccontext->batchvac.next;
+ gcbatch = list_entry(head, struct gcbatch, link);
+ list_del(head);
+ gcfree(gcbatch);
+ }
+
+ while (!list_empty(&gccontext->callbacklist)) {
+ head = gccontext->callbacklist.next;
+ list_move(head, &gccontext->callbackvac);
+ }
+
+ while (!list_empty(&gccontext->callbackvac)) {
+ head = gccontext->callbackvac.next;
+ gccallbackinfo = list_entry(head, struct gccallbackinfo, link);
+ list_del(head);
+ gcfree(gccallbackinfo);
+ }
+
+ free_temp(false);
+
+ gcbv_debug_shutdown();
+}
+
+
+/*******************************************************************************
+ * Library API.
+ */
+
+enum bverror bv_map(struct bvbuffdesc *bvbuffdesc)
+{
+ enum bverror bverror;
+ struct bvbuffmap *bvbuffmap;
+
+ GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n",
+ (unsigned int) bvbuffdesc);
+
+ if (bvbuffdesc == NULL) {
+ BVSETERROR(BVERR_BUFFERDESC, "bvbuffdesc is NULL");
+ goto exit;
+ }
+
+ if (bvbuffdesc->structsize < STRUCTSIZE(bvbuffdesc, map)) {
+ BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size");
+ goto exit;
+ }
+
+ bverror = do_map(bvbuffdesc, NULL, &bvbuffmap);
+
+exit:
+ GCEXITARG(GCZONE_MAPPING, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+enum bverror bv_unmap(struct bvbuffdesc *bvbuffdesc)
+{
+ enum bverror bverror = BVERR_NONE;
+ enum bverror otherbverror = BVERR_NONE;
+ struct gccontext *gccontext = get_context();
+ struct bvbuffmap *prev = NULL;
+ struct bvbuffmap *bvbuffmap;
+ struct bvbuffmapinfo *bvbuffmapinfo;
+ struct gcimap gcimap;
+
+ GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n",
+ (unsigned int) bvbuffdesc);
+
+ /* Lock access to the mapping list. */
+ GCLOCK(&gccontext->maplock);
+
+ if (bvbuffdesc == NULL) {
+ BVSETERROR(BVERR_BUFFERDESC, "bvbuffdesc is NULL");
+ goto exit;
+ }
+
+ if (bvbuffdesc->structsize < STRUCTSIZE(bvbuffdesc, map)) {
+ BVSETERROR(BVERR_BUFFERDESC_VERS, "argument has invalid size");
+ goto exit;
+ }
+
+ /* Is the buffer mapped? */
+ bvbuffmap = bvbuffdesc->map;
+ if (bvbuffmap == NULL) {
+ GCDBG(GCZONE_MAPPING, "buffer isn't mapped.\n");
+ goto exit;
+ }
+
+ /* Try to find our mapping. */
+ while (bvbuffmap != NULL) {
+ if (bvbuffmap->bv_unmap == bv_unmap)
+ break;
+ prev = bvbuffmap;
+ bvbuffmap = bvbuffmap->nextmap;
+ }
+
+ /* Are there other implementations? */
+ if ((prev != NULL) || (bvbuffmap->nextmap != NULL)) {
+ GCDBG(GCZONE_MAPPING,
+ "have mappings from other implementations.\n");
+
+ /* Was our mapping found? */
+ if (bvbuffmap == NULL) {
+ GCDBG(GCZONE_MAPPING,
+ "no mapping from our implementation.\n");
+
+ /* No, call other implementations. */
+ bverror = bvbuffdesc->map->bv_unmap(bvbuffdesc);
+ goto exit;
+ }
+
+ if (bvbuffmap->structsize
+ < STRUCTSIZE(bvbuffmap, nextmap)) {
+ BVSETERROR(BVERR_BUFFERDESC_VERS,
+ "unsupported bvbuffdesc version");
+ goto exit;
+ }
+
+ /* Remove our mapping. */
+ if (prev == NULL)
+ bvbuffdesc->map = bvbuffmap->nextmap;
+ else
+ prev->nextmap = bvbuffmap->nextmap;
+
+ /* Call other implementation. */
+ otherbverror = bvbuffdesc->map->bv_unmap(bvbuffdesc);
+
+ /* Add our mapping back. */
+ bvbuffmap->nextmap = bvbuffdesc->map;
+ bvbuffdesc->map = bvbuffmap;
+ prev = NULL;
+ } else {
+ GCDBG(GCZONE_MAPPING,
+ "no mappings from other implementations.\n");
+ }
+
+ /* Get the info structure. */
+ bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle;
+
+ GCDBG(GCZONE_MAPPING, "bvbuffmap = 0x%08X\n", (unsigned int) bvbuffmap);
+ GCDBG(GCZONE_MAPPING, "handle = 0x%08X\n", bvbuffmapinfo->handle);
+
+ /* Explicit unmapping. */
+ if (bvbuffmapinfo->usermap == 0)
+ GCERR("explicit count is already zero.\n");
+ bvbuffmapinfo->usermap = 0;
+
+ GCDBG(GCZONE_MAPPING, "explicit count = %d\n",
+ bvbuffmapinfo->usermap);
+ GCDBG(GCZONE_MAPPING, "implicit count = %d\n",
+ bvbuffmapinfo->automap);
+
+ /* Do we have implicit mappings? */
+ if (bvbuffmapinfo->automap > 0) {
+ GCDBG(GCZONE_MAPPING, "have implicit unmappings.\n");
+ goto exit;
+ }
+
+ /* Unmap the buffer. */
+ memset(&gcimap, 0, sizeof(gcimap));
+ gcimap.handle = bvbuffmapinfo->handle;
+ gc_unmap_wrapper(&gcimap);
+ if (gcimap.gcerror != GCERR_NONE) {
+ BVSETERROR(BVERR_OOM, "unable to free gccore memory");
+ goto exit;
+ }
+
+ /* Remove from the buffer descriptor list. */
+ if (prev == NULL)
+ bvbuffdesc->map = bvbuffmap->nextmap;
+ else
+ prev->nextmap = bvbuffmap->nextmap;
+
+ /* Invalidate the record. */
+ bvbuffmap->structsize = 0;
+
+ /* Add to the vacant list. */
+ bvbuffmap->nextmap = gccontext->buffmapvac;
+ gccontext->buffmapvac = bvbuffmap;
+
+exit:
+ /* Unlock access to the mapping list. */
+ GCUNLOCK(&gccontext->maplock);
+
+ GCEXITARG(GCZONE_MAPPING, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+enum bverror bv_blt(struct bvbltparams *bvbltparams)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gccontext *gccontext = get_context();
+ struct gcalpha *gca = NULL;
+ struct gcalpha _gca;
+ unsigned int op, type, blend, format;
+ unsigned int batchexec = 0;
+ bool nop = false;
+ struct gcbatch *gcbatch;
+ struct gcsurface *dstinfo;
+ struct bvrect *dstrect;
+ bool dstonly, src1used, src2used, maskused;
+ struct gcsurface srcinfo[2];
+ unsigned short rop;
+ struct gcicommit gcicommit;
+ int i, srccount, res;
+
+ GCENTERARG(GCZONE_BLIT, "bvbltparams = 0x%08X\n",
+ (unsigned int) bvbltparams);
+
+ /* Verify blt parameters structure. */
+ if (bvbltparams == NULL) {
+ BVSETERROR(BVERR_BLTPARAMS_VERS, "bvbltparams is NULL");
+ goto exit;
+ }
+
+ if (bvbltparams->structsize < STRUCTSIZE(bvbltparams, callbackdata)) {
+ BVSETERROR(BVERR_BLTPARAMS_VERS, "argument has invalid size");
+ goto exit;
+ }
+
+ /* Reset the error message. */
+ bvbltparams->errdesc = NULL;
+
+ /* Verify the destination parameters structure. */
+ res = verify_surface(0, (union bvinbuff *) &bvbltparams->dstdesc,
+ bvbltparams->dstgeom);
+ if (res != -1) {
+ BVSETBLTSURFERROR(res, g_destsurferr);
+ goto exit;
+ }
+
+ /* Extract the operation flags. */
+ op = (bvbltparams->flags & BVFLAG_OP_MASK) >> BVFLAG_OP_SHIFT;
+ type = (bvbltparams->flags & BVFLAG_BATCH_MASK) >> BVFLAG_BATCH_SHIFT;
+ GCDBG(GCZONE_BLIT, "op = %d\n", op);
+ GCDBG(GCZONE_BLIT, "type = %d\n", type);
+
+ switch (type) {
+ case (BVFLAG_BATCH_NONE >> BVFLAG_BATCH_SHIFT):
+ bverror = allocate_batch(bvbltparams, &gcbatch);
+ if (bverror != BVERR_NONE) {
+ bvbltparams->errdesc = gccontext->bverrorstr;
+ goto exit;
+ }
+
+ batchexec = 1;
+ gcbatch->batchflags = 0x7FFFFFFF;
+
+ GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_NONE(0x%08X)\n",
+ (unsigned int) gcbatch);
+ break;
+
+ case (BVFLAG_BATCH_BEGIN >> BVFLAG_BATCH_SHIFT):
+ bverror = allocate_batch(bvbltparams, &gcbatch);
+ if (bverror != BVERR_NONE) {
+ bvbltparams->errdesc = gccontext->bverrorstr;
+ goto exit;
+ }
+
+ bvbltparams->batch = (struct bvbatch *) gcbatch;
+
+ batchexec = 0;
+ bvbltparams->batchflags =
+ gcbatch->batchflags = 0x7FFFFFFF;
+
+ GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_BEGIN(0x%08X)\n",
+ (unsigned int) gcbatch);
+ break;
+
+ case (BVFLAG_BATCH_CONTINUE >> BVFLAG_BATCH_SHIFT):
+ gcbatch = (struct gcbatch *) bvbltparams->batch;
+ if (gcbatch == NULL) {
+ BVSETBLTERROR(BVERR_BATCH, "batch is not initialized");
+ goto exit;
+ }
+
+ if (gcbatch->structsize < STRUCTSIZE(gcbatch, unmap)) {
+ BVSETBLTERROR(BVERR_BATCH, "invalid batch");
+ goto exit;
+ }
+
+ batchexec = 0;
+ gcbatch->batchflags = bvbltparams->batchflags;
+
+ GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_CONTINUE(0x%08X)\n",
+ (unsigned int) gcbatch);
+ break;
+
+ case (BVFLAG_BATCH_END >> BVFLAG_BATCH_SHIFT):
+ gcbatch = (struct gcbatch *) bvbltparams->batch;
+ if (gcbatch == NULL) {
+ BVSETBLTERROR(BVERR_BATCH, "batch is not initialized");
+ goto exit;
+ }
+
+ if (gcbatch->structsize < STRUCTSIZE(gcbatch, unmap)) {
+ BVSETBLTERROR(BVERR_BATCH, "invalid batch");
+ goto exit;
+ }
+
+ batchexec = 1;
+ nop = (bvbltparams->batchflags & BVBATCH_ENDNOP) != 0;
+ gcbatch->batchflags = bvbltparams->batchflags;
+
+ GCDBG(GCZONE_BATCH, "BVFLAG_BATCH_END(0x%08X)\n",
+ (unsigned int) gcbatch);
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_BATCH, "unrecognized batch type");
+ goto exit;
+ }
+
+ GCDBG(GCZONE_BATCH, "batchflags=0x%08X\n",
+ (unsigned int) gcbatch->batchflags);
+
+ if (!nop) {
+ /* Get a shortcut to the destination rectangle. */
+ dstrect = &bvbltparams->dstrect;
+
+ /* Verify the batch change flags. */
+ GCVERIFYBATCH(gcbatch->batchflags >> 12,
+ &gcbatch->prevdstrect, dstrect);
+
+ switch (op) {
+ case (BVFLAG_ROP >> BVFLAG_OP_SHIFT):
+ GCDBG(GCZONE_BLIT, "BVFLAG_ROP\n");
+
+ rop = bvbltparams->op.rop;
+ dstonly = (rop == 0x0000) | (rop == 0x5555)
+ | (rop == 0xAAAA) | (rop == 0xFFFF);
+ src1used = ((((rop & 0xCCCC) >> 2)
+ ^ (rop & 0x3333)) != 0);
+ src2used = ((((rop & 0xF0F0) >> 4)
+ ^ (rop & 0x0F0F)) != 0);
+ maskused = ((((rop & 0xFF00) >> 8)
+ ^ (rop & 0x00FF)) != 0);
+ break;
+
+ case (BVFLAG_BLEND >> BVFLAG_OP_SHIFT):
+ GCDBG(GCZONE_BLIT, "BVFLAG_BLEND\n");
+
+ blend = bvbltparams->op.blend;
+ format = blend & BVBLENDDEF_FORMAT_MASK;
+ maskused = (blend & BVBLENDDEF_REMOTE) != 0;
+ rop = 0xCCCC;
+
+ GCDBG(GCZONE_BLIT, "blend = 0x%08X (%s)\n",
+ blend, gc_bvblend_name(blend));
+
+ if (format != BVBLENDDEF_FORMAT_CLASSIC) {
+ BVSETBLTERROR(BVERR_BLEND,
+ "unrecognized blend format");
+ goto exit;
+ }
+
+ if (blend == BVBLEND_CLEAR) {
+ dstonly = true;
+ src1used = false;
+ src2used = false;
+ } else {
+ bverror = parse_blend(bvbltparams, blend,
+ &_gca);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ gca = &_gca;
+
+ dstonly = false;
+ src1used = gca->src1used;
+ src2used = gca->src2used;
+ }
+ break;
+
+ case (BVFLAG_FILTER >> BVFLAG_OP_SHIFT):
+ GCDBG(GCZONE_BLIT, "BVFLAG_FILTER\n");
+ BVSETBLTERROR(BVERR_OP,
+ "filter operation not supported");
+ goto exit;
+
+ default:
+ BVSETBLTERROR(BVERR_OP, "unrecognized operation");
+ goto exit;
+ }
+
+ /* Reset the number of sources. */
+ srccount = 0;
+
+ /* Determine what's changed in the destination. */
+ dstinfo = &gcbatch->dstinfo;
+ dstinfo->surfdirty
+ = ((gcbatch->batchflags & BVBATCH_DST) != 0);
+ dstinfo->cliprectdirty
+ = ((gcbatch->batchflags & BVBATCH_CLIPRECT) != 0);
+ dstinfo->destrectdirty
+ = ((gcbatch->batchflags & BVBATCH_DESTRECT) != 0);
+ dstinfo->rectdirty
+ = dstinfo->cliprectdirty || dstinfo->destrectdirty;
+
+ /* Verify the src1 parameters structure. */
+ if (src1used) {
+ GCDBG(GCZONE_SRC, "source #1: used\n");
+ res = verify_surface(
+ bvbltparams->flags & BVBATCH_TILE_SRC1,
+ &bvbltparams->src1, bvbltparams->src1geom);
+ if (res != -1) {
+ BVSETBLTSURFERROR(res, g_src1surferr);
+ goto exit;
+ }
+
+ /* Verify the batch change flags. */
+ GCVERIFYBATCH(gcbatch->batchflags >> 14,
+ &gcbatch->prevsrc1rect,
+ &bvbltparams->src1rect);
+
+ /* Same as the destination? */
+ if (same_phys_area(bvbltparams->src1.desc,
+ &bvbltparams->src1rect,
+ bvbltparams->dstdesc,
+ dstrect)) {
+ GCDBG(GCZONE_BLIT,
+ " src1 same as destination\n");
+ } else {
+ bverror = parse_source(bvbltparams,
+ gcbatch,
+ &srcinfo[srccount],
+ 0, rop);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ srccount += 1;
+ }
+ }
+
+ /* Verify the src2 parameters structure. */
+ if (src2used) {
+ GCDBG(GCZONE_SRC, "source #2: used\n");
+ res = verify_surface(
+ bvbltparams->flags & BVBATCH_TILE_SRC2,
+ &bvbltparams->src2, bvbltparams->src2geom);
+ if (res != -1) {
+ BVSETBLTSURFERROR(res, g_src2surferr);
+ goto exit;
+ }
+
+ /* Verify the batch change flags. */
+ GCVERIFYBATCH(gcbatch->batchflags >> 16,
+ &gcbatch->prevsrc2rect,
+ &bvbltparams->src2rect);
+
+ /* Same as the destination? */
+ if (same_phys_area(bvbltparams->src2.desc,
+ &bvbltparams->src2rect,
+ bvbltparams->dstdesc,
+ dstrect)) {
+ GCDBG(GCZONE_BLIT,
+ " src2 same as destination\n");
+ } else {
+ bverror = parse_source(bvbltparams,
+ gcbatch,
+ &srcinfo[srccount],
+ 1, rop);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ srccount += 1;
+ }
+ }
+
+ /* Verify the mask parameters structure. */
+ if (maskused) {
+ GCDBG(GCZONE_MASK, "mask: used\n");
+ res = verify_surface(
+ bvbltparams->flags & BVBATCH_TILE_MASK,
+ &bvbltparams->mask, bvbltparams->maskgeom);
+ if (res != -1) {
+ BVSETBLTSURFERROR(res, g_masksurferr);
+ goto exit;
+ }
+
+ /* Verify the batch change flags. */
+ GCVERIFYBATCH(gcbatch->batchflags >> 18,
+ &gcbatch->prevmaskrect,
+ &bvbltparams->maskrect);
+
+ BVSETBLTERROR(BVERR_OP,
+ "operation with mask not supported");
+ goto exit;
+ }
+
+ /* Destination only? */
+ if (dstonly) {
+ static unsigned int pixel[8];
+ static struct bvbuffdesc dummysrcdesc;
+ static struct gcsurface dummysrcinfo;
+ static bool dummyinit;
+
+ GCDBG(GCZONE_BLIT, "target only operation.\n");
+
+ if (!dummyinit) {
+ GCDBG(GCZONE_BLIT,
+ "initializing dummy source.\n");
+
+ dummysrcdesc.structsize
+ = sizeof(struct bvbuffdesc);
+ dummysrcdesc.virtaddr = pixel;
+ dummysrcdesc.length = sizeof(pixel);
+
+ dummysrcinfo.buf.desc = &dummysrcdesc;
+ dummysrcinfo.width = 1;
+ dummysrcinfo.height = 1;
+ dummysrcinfo.stride1 = sizeof(pixel);
+ dummysrcinfo.rect.orig.right = 1;
+ dummysrcinfo.rect.orig.bottom = 1;
+
+ parse_format(bvbltparams, OCDFMT_RGBA24,
+ &dummysrcinfo.format);
+
+ dummyinit = true;
+ }
+
+ dummysrcinfo.rop = rop;
+ bverror = do_op(bvbltparams, gcbatch,
+ 1, &dummysrcinfo, NULL);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ } else {
+ GCDBG(GCZONE_BLIT, "srccount = %d\n", srccount);
+
+ if (srccount == 0) {
+ BVSETBLTERROR(BVERR_OP,
+ "operation not supported");
+ goto exit;
+ }
+
+ for (i = 0; i < srccount; i += 1) {
+ bverror = do_op(bvbltparams, gcbatch,
+ srccount, &srcinfo[i], gca);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ }
+ }
+ }
+
+ if (batchexec) {
+ struct gcmoflush *flush;
+
+ GCDBG(GCZONE_BLIT, "preparing to submit the batch.\n");
+
+ /* Finalize the current operation. */
+ bverror = gcbatch->batchend(bvbltparams, gcbatch);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Add PE flush. */
+ GCDBG(GCZONE_BLIT, "appending the flush.\n");
+ bverror = claim_buffer(bvbltparams, gcbatch,
+ sizeof(struct gcmoflush),
+ (void **) &flush);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ flush->flush_ldst = gcmoflush_flush_ldst;
+ flush->flush.reg = gcregflush_pe2D;
+
+ /* Process asynchronous operation. */
+ if ((bvbltparams->flags & BVFLAG_ASYNC) == 0) {
+ GCDBG(GCZONE_BLIT, "synchronous batch.\n");
+ gcicommit.callback = NULL;
+ gcicommit.callbackparam = NULL;
+ gcicommit.asynchronous = false;
+ } else {
+ struct gccallbackinfo *gccallbackinfo;
+
+ GCDBG(GCZONE_BLIT, "asynchronous batch (0x%08X):\n",
+ bvbltparams->flags);
+
+ if (bvbltparams->callbackfn == NULL) {
+ GCDBG(GCZONE_BLIT, "no callback given.\n");
+ gcicommit.callback = NULL;
+ gcicommit.callbackparam = NULL;
+ } else {
+ bverror = get_callbackinfo(&gccallbackinfo);
+ if (bverror != BVERR_NONE) {
+ BVSETBLTERROR(BVERR_OOM,
+ "callback allocation "
+ "failed");
+ goto exit;
+ }
+
+ gccallbackinfo->info.callback.fn
+ = bvbltparams->callbackfn;
+ gccallbackinfo->info.callback.data
+ = bvbltparams->callbackdata;
+
+ gcicommit.callback = callbackbltsville;
+ gcicommit.callbackparam = gccallbackinfo;
+
+ GCDBG(GCZONE_BLIT,
+ "gcbv_callback = 0x%08X\n",
+ (unsigned int) gcicommit.callback);
+ GCDBG(GCZONE_BLIT,
+ "gcbv_param = 0x%08X\n",
+ (unsigned int) gcicommit.callbackparam);
+ GCDBG(GCZONE_BLIT,
+ "bltsville_callback = 0x%08X\n",
+ (unsigned int)
+ gccallbackinfo->info.callback.fn);
+ GCDBG(GCZONE_BLIT,
+ "bltsville_param = 0x%08X\n",
+ (unsigned int)
+ gccallbackinfo->info.callback.data);
+ }
+
+ gcicommit.asynchronous = true;
+ }
+
+ /* Process scheduled unmappings. */
+ do_unmap_implicit(gcbatch);
+
+ INIT_LIST_HEAD(&gcicommit.unmap);
+ list_splice_init(&gcbatch->unmap, &gcicommit.unmap);
+
+ /* Pass the batch for execution. */
+ GCDUMPBATCH(gcbatch);
+
+ gcicommit.gcerror = GCERR_NONE;
+ gcicommit.entrypipe = GCPIPE_2D;
+ gcicommit.exitpipe = GCPIPE_2D;
+
+ INIT_LIST_HEAD(&gcicommit.buffer);
+ list_splice_init(&gcbatch->buffer, &gcicommit.buffer);
+
+ GCDBG(GCZONE_BLIT, "submitting the batch.\n");
+ gc_commit_wrapper(&gcicommit);
+
+ /* Move the lists back to the batch. */
+ list_splice_init(&gcicommit.buffer, &gcbatch->buffer);
+ list_splice_init(&gcicommit.unmap, &gcbatch->unmap);
+
+ /* Error? */
+ if (gcicommit.gcerror != GCERR_NONE) {
+ switch (gcicommit.gcerror) {
+ case GCERR_OODM:
+ case GCERR_CTX_ALLOC:
+ BVSETBLTERROR(BVERR_OOM,
+ "unable to allocate gccore "
+ "memory");
+ goto exit;
+ default:
+ BVSETBLTERROR(BVERR_RSRC,
+ "gccore error");
+
+ goto exit;
+ }
+ }
+
+ GCDBG(GCZONE_BLIT, "batch is submitted.\n");
+ }
+
+exit:
+ if ((gcbatch != NULL) && batchexec) {
+ free_batch(gcbatch);
+ bvbltparams->batch = NULL;
+ }
+
+ GCEXITARG(GCZONE_BLIT, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+enum bverror bv_cache(struct bvcopparams *copparams)
+{
+ enum bverror bverror = BVERR_NONE;
+ unsigned int bytespp = 0; /* bytes per pixel */
+ unsigned long vert_offset, horiz_offset;
+ unsigned int true_width, true_height;
+
+ struct c2dmrgn rgn[3];
+ int container_size = 0;
+
+ unsigned long subsample;
+ unsigned long vendor;
+ unsigned long layout;
+ unsigned long size;
+ unsigned long container;
+
+ subsample = copparams->geom->format & OCDFMTDEF_SUBSAMPLE_MASK;
+ vendor = copparams->geom->format & OCDFMTDEF_VENDOR_MASK;
+ layout = copparams->geom->format & OCDFMTDEF_LAYOUT_MASK;
+ size = copparams->geom->format & OCDFMTDEF_COMPONENTSIZEMINUS1_MASK;
+ container = copparams->geom->format & OCDFMTDEF_CONTAINER_MASK;
+
+ if (vendor != OCDFMTDEF_VENDOR_ALL) {
+ bverror = BVERR_FORMAT;
+ goto exit;
+ }
+
+ if (copparams->geom->orientation % 180 != 0) {
+ true_width = copparams->rect->height;
+ true_height = copparams->rect->width;
+ } else {
+ true_width = copparams->rect->width;
+ true_height = copparams->rect->height;
+ }
+
+ switch (container) {
+ case OCDFMTDEF_CONTAINER_8BIT:
+ container_size = 8;
+ break;
+
+ case OCDFMTDEF_CONTAINER_16BIT:
+ container_size = 16;
+ break;
+
+ case OCDFMTDEF_CONTAINER_24BIT:
+ container_size = 24;
+ break;
+
+ case OCDFMTDEF_CONTAINER_32BIT:
+ container_size = 32;
+ break;
+
+ case OCDFMTDEF_CONTAINER_48BIT:
+ container_size = 48;
+ break;
+
+ case OCDFMTDEF_CONTAINER_64BIT:
+ container_size = 64;
+ break;
+ }
+
+ switch (layout) {
+ case OCDFMTDEF_PACKED:
+ switch (subsample) {
+ case OCDFMTDEF_SUBSAMPLE_NONE:
+ if (size >= 8) {
+ bytespp = container_size / 8;
+ } else {
+ GCERR("format not supported.\n");
+ bverror = BVERR_FORMAT;
+ goto exit;
+ }
+ break;
+
+ case OCDFMTDEF_SUBSAMPLE_422_YCbCr:
+ bytespp = (container_size / 2) / 8;
+ break;
+
+ default:
+ bverror = BVERR_FORMAT;
+ goto exit;
+ }
+
+ rgn[0].span = true_width * bytespp;
+ rgn[0].lines = true_height;
+ rgn[0].stride = copparams->geom->virtstride;
+ horiz_offset = copparams->rect->left * bytespp;
+ vert_offset = copparams->rect->top;
+
+ rgn[0].start = (void *) ((unsigned long)
+ copparams->desc->virtaddr +
+ vert_offset * rgn[0].stride +
+ horiz_offset);
+
+ gcbvcacheop(1, rgn, copparams->cacheop);
+ break;
+
+ case OCDFMTDEF_2_PLANE_YCbCr:
+ /* 1 byte per pixel */
+ rgn[0].span = true_width;
+ rgn[0].lines = true_height;
+ rgn[0].stride = copparams->geom->virtstride;
+ rgn[0].start = (void *)
+ ((unsigned long) copparams->desc->virtaddr +
+ copparams->rect->top * rgn[0].stride +
+ copparams->rect->left);
+
+ rgn[1].span = true_width;
+ rgn[1].lines = true_height / 2;
+ rgn[1].stride = copparams->geom->virtstride;
+ rgn[1].start = rgn[0].start +
+ copparams->geom->height * rgn[0].stride;
+
+ GCDBG(GCZONE_CACHE,
+ "virtaddr %p start[0] 0x%08x start[1] 0x%08x\n",
+ copparams->desc->virtaddr, rgn[0].start, rgn[1].start);
+
+ gcbvcacheop(2, rgn, copparams->cacheop);
+ break;
+
+ default:
+ GCERR("format 0x%x (%d) not supported.\n",
+ copparams->geom->format, copparams->geom->format);
+ bverror = BVERR_FORMAT;
+ break;
+ }
+
+exit:
+ if (bverror != BVERR_NONE)
+ GCERR("bverror = %d\n", bverror);
+
+ return bverror;
+}
diff --git a/drivers/misc/gcx/gcbv/gcbv.h b/drivers/misc/gcx/gcbv/gcbv.h
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Vivante Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GCBV_H
+#define GCBV_H
+
+#include "gcmain.h"
+
+/*******************************************************************************
+ * Miscellaneous defines and macros.
+ */
+
+#define GC_MAX_BASE_ALIGN 64
+
+#define GCBV_BATCH_FINALIZE_SRCCOUNT (1 << 0)
+#define GCBV_BATCH_FINALIZE_MULTISRC (1 << 1)
+#define GCBV_BATCH_FINALIZE_ALIGN (1 << 2)
+#define GCBV_BATCH_FINALIZE_FLAGS_DST (1 << 3)
+#define GCBV_BATCH_FINALIZE_FLAGS_DESTRECT (1 << 4)
+#define GCBV_BATCH_FINALIZE_FLAGS_CLIPRECT (1 << 5)
+#define GCBV_BATCH_FINALIZE_OPERATION (1 << 6)
+
+#if !defined(BVBATCH_DESTRECT)
+#define BVBATCH_DESTRECT (BVBATCH_DSTRECT_ORIGIN | BVBATCH_DSTRECT_SIZE)
+#endif
+
+#if !defined(BVBATCH_SRC1RECT)
+#define BVBATCH_SRC1RECT (BVBATCH_SRC1RECT_ORIGIN | BVBATCH_SRC1RECT_SIZE)
+#endif
+
+#if !defined(BVBATCH_SRC2RECT)
+#define BVBATCH_SRC2RECT (BVBATCH_SRC2RECT_ORIGIN | BVBATCH_SRC2RECT_SIZE)
+#endif
+
+#define STRUCTSIZE(structptr, lastmember) \
+( \
+ (size_t) &structptr->lastmember + \
+ sizeof(structptr->lastmember) - \
+ (size_t) structptr \
+)
+
+#define GET_MAP_HANDLE(map) \
+( \
+ ((struct bvbuffmapinfo *) map->handle)->handle \
+)
+
+#define GC_CLIP_RESET_LEFT ((unsigned short) 0)
+#define GC_CLIP_RESET_TOP ((unsigned short) 0)
+#define GC_CLIP_RESET_RIGHT ((unsigned short) ((1 << 15) - 1))
+#define GC_CLIP_RESET_BOTTOM ((unsigned short) ((1 << 15) - 1))
+
+#define BVSETERROR(error, message, ...) \
+do { \
+ struct gccontext *tmpcontext = get_context(); \
+ snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \
+ message, ##__VA_ARGS__); \
+ GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \
+ tmpcontext->bverrorstr); \
+ bverror = error; \
+} while (0)
+
+#define BVSETBLTERROR(error, message, ...) \
+do { \
+ struct gccontext *tmpcontext = get_context(); \
+ snprintf(tmpcontext->bverrorstr, sizeof(tmpcontext->bverrorstr), \
+ message, ##__VA_ARGS__); \
+ GCDUMPSTRING("%s(%d): [ERROR] %s\n", __func__, __LINE__, \
+ tmpcontext->bverrorstr); \
+ bvbltparams->errdesc = tmpcontext->bverrorstr; \
+ bverror = error; \
+} while (0)
+
+#define GCPRINT_RECT(zone, name, rect) \
+{ \
+ GCDBG(zone, \
+ name " = (%d,%d)-(%d,%d), %dx%d\n", \
+ (rect)->left, (rect)->top, \
+ (rect)->right, (rect)->bottom, \
+ (rect)->right - (rect)->left, \
+ (rect)->bottom - (rect)->top); \
+}
+
+
+/*******************************************************************************
+ * Kernel table definitions.
+ */
+
+#define GC_TAP_COUNT 9
+#define GC_PHASE_BITS 5
+#define GC_PHASE_MAX_COUNT (1 << GC_PHASE_BITS)
+#define GC_PHASE_LOAD_COUNT (GC_PHASE_MAX_COUNT / 2 + 1)
+#define GC_COEFFICIENT_COUNT (GC_PHASE_LOAD_COUNT * GC_TAP_COUNT)
+#define GC_FILTER_CACHE_MAX 10
+
+enum gcfiltertype {
+ GC_FILTER_SYNC,
+ GC_FILTER_BLUR,
+
+ /* Number of supported filter types. */
+ GC_FILTER_COUNT
+};
+
+struct gcfilterkernel {
+ enum gcfiltertype type;
+ unsigned int kernelsize;
+ unsigned int srcsize;
+ unsigned int dstsize;
+ unsigned int scalefactor;
+ short kernelarray[GC_COEFFICIENT_COUNT];
+ struct list_head link;
+};
+
+struct gcfiltercache {
+ unsigned int count;
+ struct list_head list; /* gcfilterkernel */
+};
+
+
+/*******************************************************************************
+ * Global data structure.
+ */
+
+struct gccaps {
+ bool l2cachefor420;
+ unsigned int maxsource;
+ bool strictalign;
+ bool swizzlefixed;
+};
+
+struct gccontext {
+ /* Last generated error message. */
+ char bverrorstr[128];
+
+ /* Capabilities and characteristics. */
+ unsigned int gcmodel;
+ unsigned int gcrevision;
+ unsigned int gcdate;
+ unsigned int gctime;
+ struct gccaps gccaps;
+
+ /* Dynamically allocated structure cache. */
+ struct bvbuffmap *buffmapvac; /* bvbuffmap */
+ struct list_head unmapvac; /* gcschedunmap */
+ struct list_head buffervac; /* gcbuffer */
+ struct list_head fixupvac; /* gcfixup */
+ struct list_head batchvac; /* gcbatch */
+
+ /* Callback lists. */
+ struct list_head callbacklist; /* gccallbackinfo */
+ struct list_head callbackvac; /* gccallbackinfo */
+
+ /* Access locks. */
+ GCLOCK_TYPE batchlock;
+ GCLOCK_TYPE bufferlock;
+ GCLOCK_TYPE fixuplock;
+ GCLOCK_TYPE maplock;
+ GCLOCK_TYPE callbacklock;
+
+ /* Kernel table cache. */
+ struct gcfilterkernel *loadedfilter; /* gcfilterkernel */
+ struct gcfiltercache filtercache[GC_FILTER_COUNT][GC_TAP_COUNT];
+
+ /* Temporary buffer descriptor. */
+ struct bvbuffdesc *tmpbuffdesc;
+ void *tmpbuff;
+};
+
+
+/*******************************************************************************
+ * Mapping structures.
+ */
+
+/* bvbuffmap struct attachment. */
+struct bvbuffmapinfo {
+ /* Mapped handle for the buffer. */
+ unsigned long handle;
+
+ /* Number of times the client explicitly mapped this buffer. */
+ int usermap;
+
+ /* Number of times implicit mapping happened. */
+ int automap;
+};
+
+
+/*******************************************************************************
+ * Color format.
+ */
+
+#define BVFMT_RGB 1
+#define BVFMT_YUV 2
+
+struct bvcomponent {
+ unsigned int shift;
+ unsigned int size;
+ unsigned int mask;
+};
+
+struct bvcsrgb {
+ struct bvcomponent r;
+ struct bvcomponent g;
+ struct bvcomponent b;
+ struct bvcomponent a;
+};
+
+struct bvformatxlate {
+ unsigned int type;
+ unsigned int bitspp;
+ unsigned int allocbitspp;
+ unsigned int format;
+ unsigned int swizzle;
+ unsigned int endian;
+ bool premultiplied;
+ bool zerofill;
+
+ union {
+ struct {
+ const struct bvcsrgb *comp;
+ } rgb;
+
+ struct {
+ unsigned int std;
+ unsigned int planecount;
+ unsigned int xsample;
+ unsigned int ysample;
+ } yuv;
+ } cs;
+};
+
+
+/*******************************************************************************
+ * Alpha blending.
+ */
+
+/* Alpha blending hardware configuration. */
+struct gcblendconfig {
+ unsigned char factor_mode;
+ unsigned char color_reverse;
+
+ bool src1used;
+ bool src2used;
+};
+
+/* Alpha blending descriptor. */
+struct gcalpha {
+ bool globalcolorenable;
+ unsigned int globalcolor;
+
+ struct gcblendconfig *k1;
+ struct gcblendconfig *k2;
+
+ struct gcblendconfig *srcconfig;
+ struct gcblendconfig *dstconfig;
+
+ bool src1used;
+ bool src2used;
+};
+
+
+/*******************************************************************************
+ * Rotation and mirror defines.
+ */
+
+#define GCREG_ROT_ANGLE_ROT0 0x0
+#define GCREG_ROT_ANGLE_ROT90 0x4
+#define GCREG_ROT_ANGLE_ROT180 0x5
+#define GCREG_ROT_ANGLE_ROT270 0x6
+
+#define ROT_ANGLE_INVALID -1
+#define ROT_ANGLE_0 0
+#define ROT_ANGLE_90 1
+#define ROT_ANGLE_180 2
+#define ROT_ANGLE_270 3
+
+#define GCREG_MIRROR_NONE 0x0
+#define GCREG_MIRROR_X 0x1
+#define GCREG_MIRROR_Y 0x2
+#define GCREG_MIRROR_XY 0x3
+
+extern const unsigned int rotencoding[];
+
+
+/*******************************************************************************
+ * Surface descriptor.
+ */
+
+struct gcrectset {
+ /* Render rectangle as specified by the client. */
+ struct gcrect orig;
+
+ /* Clipped rectangle. */
+ struct gcrect clip;
+
+ /* Clipped rectangle adjusted for base address misalignment. */
+ struct gcrect adj;
+};
+
+struct gcsurface {
+ /* Surface change flags. */
+ bool surfdirty;
+ bool rectdirty;
+ bool destrectdirty;
+ bool cliprectdirty;
+
+ /* BLTsville source index (-1 for dst, 0 for src1 and 1 for src2). */
+ int index;
+
+ /* Surface buffer descriptor. */
+ union bvinbuff buf;
+
+ /* Geometry size as specified by the client. */
+ unsigned int width;
+ unsigned int height;
+
+ /* Geometry size adjusted for base address misalignment. */
+ unsigned int adjwidth;
+ unsigned int adjheight;
+
+ /* Physical size of the surface (adjusted and 0 degree rotated). */
+ unsigned int physwidth;
+ unsigned int physheight;
+
+ /* Plane strides. */
+ long stride1;
+ long stride2;
+ long stride3;
+
+ /* Base address alignment in pixels. */
+ int xpixalign;
+ int ypixalign;
+
+ /* Base address alignment in bytes. */
+ int bytealign1;
+ int bytealign2;
+ int bytealign3;
+
+ /* Surface format. */
+ struct bvformatxlate format;
+
+ /* Rotation angle. */
+ int angle;
+ int adjangle;
+
+ /* Render rectangles. */
+ struct gcrectset rect;
+
+ /* Aux render rectangles. */
+ bool haveaux;
+ struct gcrectset auxrect;
+
+ /* Mirror setting. */
+ unsigned int mirror;
+
+ /* ROP. */
+ unsigned short rop;
+
+ /* Blending info. */
+ struct gcalpha *gca;
+ bool globalcolorenable;
+ unsigned int globalcolor;
+ unsigned char srcglobalpremul;
+ unsigned char srcglobalmode;
+ unsigned char dstglobalmode;
+};
+
+
+/*******************************************************************************
+ * Batch structures.
+ */
+
+/* Operation finalization call. */
+struct gcbatch;
+typedef enum bverror (*gcbatchend) (struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch);
+
+/* Blit states. */
+struct gcblit {
+ /* Number of sources in the operation. */
+ unsigned int srccount;
+
+ /* Multi source enable flag. */
+ bool multisrc;
+
+ /* Computed destination rectangle coordinates; in multi-source
+ * setup can be modified to match new destination and source
+ * geometry. */
+ struct gcrect dstrect;
+
+ /* Block walker enable. */
+ bool blockenable;
+
+ /* Destination format and swizzle. */
+ unsigned int format;
+ unsigned int swizzle;
+ unsigned int endian;
+};
+
+/* Filter states. */
+struct gcfilter {
+ /* Kernel size. */
+ unsigned int horkernelsize;
+ unsigned int verkernelsize;
+
+ /* Scale factors. */
+ unsigned int horscalefactor;
+ unsigned int verscalefactor;
+};
+
+/* Batch header. */
+struct gcbatch {
+ /* Used to ID structure version. */
+ unsigned int structsize;
+
+ /* Batch change flags. */
+ unsigned long batchflags;
+
+ /* Pointer to the function to finalize the current operation. */
+ gcbatchend batchend;
+
+ /* State of the current operation. */
+ struct {
+ struct gcblit blit;
+ struct gcfilter filter;
+ } op;
+
+ /* Destination surface. */
+ struct gcsurface dstinfo;
+
+ /* Clipping deltas; used to correct the source coordinates for
+ * single source blits. */
+ struct gcrect clipdelta;
+
+ /* Destination rectangle adjustment offsets. */
+ int dstoffsetX;
+ int dstoffsetY;
+
+#if GCDEBUG_ENABLE
+ /* Rectangle validation storage. */
+ struct bvrect prevdstrect;
+ struct bvrect prevsrc1rect;
+ struct bvrect prevsrc2rect;
+ struct bvrect prevmaskrect;
+#endif
+
+ /* Total size of the command buffer. */
+ unsigned int size;
+
+ /* Command buffer list (gcbuffer). */
+ struct list_head buffer;
+
+ /* Scheduled implicit unmappings (gcschedunmap). */
+ struct list_head unmap;
+
+ /* Batch linked list (gcbatch). */
+ struct list_head link;
+};
+
+
+/*******************************************************************************
+ * Internal API entries.
+ */
+
+/* Get the pointer to the context. */
+struct gccontext *get_context(void);
+
+/* Validation. */
+bool null_rect(struct gcrect *gcrect);
+bool valid_rect(struct gcsurface *gcsurface, struct gcrect *gcrect);
+
+/* Rotation processing. */
+void rotate_rect(int angle,
+ struct gcsurface *gcsurface, struct gcrect *rect);
+void rotate_geom(int angle, struct gcsurface *gcsurface);
+void adjust_angle(struct gcsurface *srcinfo, struct gcsurface *dstinfo);
+void process_rotation(struct gcsurface *gcsurface);
+
+/* Parsers. */
+enum bverror parse_format(struct bvbltparams *bvbltparams,
+ enum ocdformat ocdformat,
+ struct bvformatxlate *format);
+enum bverror parse_blend(struct bvbltparams *bvbltparams,
+ enum bvblend blend,
+ struct gcalpha *gca);
+enum bverror parse_destination(struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch);
+enum bverror parse_source(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo,
+ unsigned int index,
+ unsigned short rop);
+enum bverror parse_scalemode(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch);
+
+/* Return surface alignment offset. */
+int get_pixel_offset(struct gcsurface *gcsurface, int offset);
+
+/* Buffer mapping. */
+enum bverror do_map(struct bvbuffdesc *bvbuffdesc,
+ struct gcbatch *gcbatch,
+ struct bvbuffmap **map);
+void do_unmap_implicit(struct gcbatch *gcbatch);
+
+/* Batch/command buffer management. */
+enum bverror do_end(struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch);
+enum bverror allocate_batch(struct bvbltparams *bvbltparams,
+ struct gcbatch **gcbatch);
+void free_batch(struct gcbatch *gcbatch);
+enum bverror append_buffer(struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch,
+ struct gcbuffer **gcbuffer);
+
+enum bverror add_fixup(struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch,
+ unsigned int *fixup,
+ unsigned int surfoffset);
+enum bverror claim_buffer(struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch,
+ unsigned int size,
+ void **buffer);
+
+/* Temporary buffer management. */
+enum bverror allocate_temp(struct bvbltparams *bvbltparams,
+ unsigned int size);
+enum bverror free_temp(bool schedule);
+
+/* Program the destination. */
+enum bverror set_dst(struct bvbltparams *bltparams,
+ struct gcbatch *batch,
+ struct bvbuffmap *dstmap);
+
+/* Program blending. */
+enum bverror set_blending(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo);
+enum bverror set_blending_index(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo,
+ unsigned int index);
+
+/* Program YUV source. */
+void set_computeyuv(struct gcsurface *srcinfo, int x, int y);
+enum bverror set_yuvsrc(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo,
+ struct bvbuffmap *srcmap);
+enum bverror set_yuvsrc_index(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo,
+ struct bvbuffmap *srcmap,
+ unsigned int index);
+
+/* Rendering entry points. */
+enum bverror do_fill(struct bvbltparams *bltparams,
+ struct gcbatch *gcbatch,
+ struct gcsurface *srcinfo);
+enum bverror do_blit(struct bvbltparams *bltparams,
+ struct gcbatch *gcbatch,
+ struct gcsurface *srcinfo);
+enum bverror do_filter(struct bvbltparams *bvbltparams,
+ struct gcbatch *gcbatch,
+ struct gcsurface *srcinfo);
+
+#endif
diff --git a/drivers/misc/gcx/gcbv/gcbvdebug.c b/drivers/misc/gcx/gcbv/gcbvdebug.c
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * gcbvdebug.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include "gcbv.h"
+
+static struct dentry *debug_root;
+
+/*****************************************************************************/
+
+static struct {
+ unsigned int srccount;
+ unsigned int multisrc;
+ unsigned int align;
+ unsigned int flags_dst;
+ unsigned int flags_destrect;
+ unsigned int flags_cliprect;
+
+} finalize_batch_reason;
+
+static int bfr_show(struct seq_file *s, void *data)
+{
+ seq_printf(s, " srccount: %d\n",
+ finalize_batch_reason.srccount);
+ seq_printf(s, " multisrc: %d\n",
+ finalize_batch_reason.multisrc);
+ seq_printf(s, " align: %d\n",
+ finalize_batch_reason.align);
+ seq_printf(s, " flags_dst: %d\n",
+ finalize_batch_reason.flags_dst);
+ seq_printf(s, "flags_destrect: %d\n",
+ finalize_batch_reason.flags_destrect);
+ seq_printf(s, "flags_cliprect: %d\n",
+ finalize_batch_reason.flags_cliprect);
+
+ memset(&finalize_batch_reason, 0, sizeof(finalize_batch_reason));
+
+ return 0;
+}
+
+static int bfr_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, bfr_show, 0);
+}
+
+static const struct file_operations fops_bfr = {
+ .open = bfr_open,
+ .write = NULL,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+void gcbv_debug_finalize_batch(unsigned int reason)
+{
+ if (reason & GCBV_BATCH_FINALIZE_SRCCOUNT)
+ finalize_batch_reason.srccount++;
+
+ if (reason & GCBV_BATCH_FINALIZE_MULTISRC)
+ finalize_batch_reason.multisrc++;
+
+ if (reason & GCBV_BATCH_FINALIZE_ALIGN)
+ finalize_batch_reason.align++;
+
+ if (reason & GCBV_BATCH_FINALIZE_FLAGS_DST)
+ finalize_batch_reason.flags_dst++;
+
+ if (reason & GCBV_BATCH_FINALIZE_FLAGS_CLIPRECT)
+ finalize_batch_reason.flags_cliprect++;
+
+ if (reason & GCBV_BATCH_FINALIZE_FLAGS_DESTRECT)
+ finalize_batch_reason.flags_destrect++;
+}
+
+/*****************************************************************************/
+
+#define MAX_BLT_SOURCES 8
+
+static struct gc_blt_status {
+ int totalCount;
+ long long int totalPixels;
+ int srcCount[MAX_BLT_SOURCES + 1];
+ long long int srcCountPixels[MAX_BLT_SOURCES + 1];
+
+ int two_dim_one_pass;
+ int two_dim_two_pass;
+ int one_dim;
+
+} blt_stats;
+
+void gcbv_debug_blt(int srccount, int dstWidth, int dstHeight)
+{
+ int pixels;
+
+ if (srccount > MAX_BLT_SOURCES)
+ return;
+
+ pixels = dstWidth * dstHeight;
+
+ blt_stats.srcCount[srccount]++;
+ blt_stats.srcCountPixels[srccount] += pixels;
+
+ blt_stats.totalPixels += pixels;
+ blt_stats.totalCount++;
+}
+
+void gcbv_debug_scaleblt(bool scalex, bool scaley, bool singlepass)
+{
+ if (scalex && scaley) {
+ if (singlepass)
+ blt_stats.two_dim_one_pass++;
+ else
+ blt_stats.two_dim_two_pass++;
+ } else
+ blt_stats.one_dim++;
+}
+
+static void blt_stats_reset(void)
+{
+ int i;
+
+ for (i = 1; i <= MAX_BLT_SOURCES; i++) {
+ blt_stats.srcCount[i] = 0;
+ blt_stats.srcCountPixels[i] = 0;
+ }
+
+ blt_stats.totalCount = 0;
+ blt_stats.totalPixels = 0;
+
+ blt_stats.two_dim_one_pass = 0;
+ blt_stats.two_dim_two_pass = 0;
+ blt_stats.one_dim = 0;
+}
+
+static int blt_stats_show(struct seq_file *s, void *data)
+{
+ int i;
+
+ seq_printf(s, "total blts: %d\n", blt_stats.totalCount);
+
+ if (blt_stats.totalCount) {
+ for (i = 1; i <= MAX_BLT_SOURCES; i++) {
+ int count = blt_stats.srcCount[i];
+
+ seq_printf(s, " %d src: %d (%d%%)\n",
+ i,
+ count,
+ count * 100 / blt_stats.totalCount);
+ }
+ }
+
+ seq_printf(s, "total dst pixels: %lld\n", blt_stats.totalPixels);
+
+ if (blt_stats.totalPixels) {
+ for (i = 1; i <= MAX_BLT_SOURCES; i++) {
+ long long int count = blt_stats.srcCountPixels[i];
+ long long int total = blt_stats.totalPixels;
+
+ seq_printf(s, " %d src: %lld (%lld%%)\n",
+ i,
+ count,
+ div64_s64(count * 100, total));
+ }
+ }
+
+ seq_printf(s, "scaled 2x2: %d\n", blt_stats.two_dim_two_pass);
+ seq_printf(s, "scaled 2x1: %d\n", blt_stats.two_dim_one_pass);
+ seq_printf(s, "scaled 1x1: %d\n", blt_stats.one_dim);
+
+ blt_stats_reset();
+
+ return 0;
+}
+
+static int blt_stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, blt_stats_show, 0);
+}
+
+static const struct file_operations fops_blt_stats = {
+ .open = blt_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*****************************************************************************/
+
+void gcbv_debug_init(void)
+{
+ debug_root = debugfs_create_dir("gcbv", NULL);
+ if (!debug_root)
+ return;
+
+ debugfs_create_file("blt_stats", 0664, debug_root, NULL,
+ &fops_blt_stats);
+ debugfs_create_file("batch_finalize_reason", 0664, debug_root, NULL,
+ &fops_bfr);
+}
+
+void gcbv_debug_shutdown(void)
+{
+ if (debug_root)
+ debugfs_remove_recursive(debug_root);
+}
diff --git a/drivers/misc/gcx/gcbv/gcbvdebug.h b/drivers/misc/gcx/gcbv/gcbvdebug.h
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * gcbvdebug.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCBVDEBUG_H
+#define GCBVDEBUG_H
+
+void gcbv_debug_init(void);
+void gcbv_debug_shutdown(void);
+
+void gcbv_debug_finalize_batch(unsigned int reason);
+
+void gcbv_debug_blt(int srccount, int dstWidth, int dstHeight);
+void gcbv_debug_scaleblt(bool scalex, bool scaley, bool singlepass);
+
+#endif
diff --git a/drivers/misc/gcx/gcbv/gcfill.c b/drivers/misc/gcx/gcbv/gcfill.c
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Vivante Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_COLOR (1 << 0)
+#define GCZONE_FILL (1 << 1)
+
+GCDBG_FILTERDEF(fill, GCZONE_NONE,
+ "color",
+ "fill")
+
+
+static inline unsigned int extract_component(unsigned int pixel,
+ const struct bvcomponent *desc,
+ bool zerofill)
+{
+ unsigned int component;
+ unsigned int component8;
+
+ component = (pixel & desc->mask) >> desc->shift;
+ GCDBG(GCZONE_COLOR, "mask=0x%08X, shift=%d, component=0x%08X\n",
+ desc->mask, desc->shift, component);
+
+ switch (desc->size) {
+ case 0:
+ component8 = zerofill ? 0x00 : 0xFF;
+ GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+ break;
+
+ case 1:
+ component8 = component ? 0xFF : 0x00;
+ GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+ break;
+
+ case 4:
+ component8 = component | (component << 4);
+ GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+ break;
+
+ case 5:
+ component8 = (component << 3) | (component >> 2);
+ GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+ break;
+
+ case 6:
+ component8 = (component << 2) | (component >> 4);
+ GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+ break;
+
+ default:
+ component8 = component;
+ GCDBG(GCZONE_COLOR, "component8=0x%08X\n", component8);
+ }
+
+ return component8;
+}
+
+static unsigned int getinternalcolor(void *ptr, struct bvformatxlate *format)
+{
+ unsigned int srcpixel, dstpixel;
+ unsigned int r, g, b, a;
+
+ switch (format->bitspp) {
+ case 16:
+ srcpixel = *(unsigned short *) ptr;
+ GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel);
+ break;
+
+ case 32:
+ srcpixel = *(unsigned int *) ptr;
+ GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel);
+ break;
+
+ default:
+ srcpixel = 0;
+ GCDBG(GCZONE_COLOR, "srcpixel=0x%08X\n", srcpixel);
+ }
+
+ r = extract_component(srcpixel, &format->cs.rgb.comp->r,
+ format->zerofill);
+ g = extract_component(srcpixel, &format->cs.rgb.comp->g,
+ format->zerofill);
+ b = extract_component(srcpixel, &format->cs.rgb.comp->b,
+ format->zerofill);
+ a = extract_component(srcpixel, &format->cs.rgb.comp->a,
+ format->zerofill);
+
+ GCDBG(GCZONE_COLOR, "(r,g,b,a)=0x%02X,0x%02X,0x%02X,0x%02X\n",
+ r, g, b, a);
+
+ dstpixel = (a << 24) | (r << 16) | (g << 8) | b;
+
+ GCDBG(GCZONE_COLOR, "dstpixel=0x%08X\n", dstpixel);
+
+ return dstpixel;
+}
+
+enum bverror do_fill(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo)
+{
+ enum bverror bverror;
+ struct gccontext *gccontext = get_context();
+ struct gcsurface *dstinfo;
+ struct gcmofill *gcmofill;
+ unsigned char *fillcolorptr;
+ struct bvbuffmap *dstmap = NULL;
+ int physleft, phystop;
+ struct gcrect *srcorig;
+ struct gcrect *dstadj;
+
+ GCENTER(GCZONE_FILL);
+
+ /* Get a shortcut to the destination surface descriptor. */
+ dstinfo = &batch->dstinfo;
+
+ /* Only RGB source is supported. */
+ if (srcinfo->format.type != BVFMT_RGB) {
+ BVSETBLTERROR((srcinfo->index == 0)
+ ? BVERR_SRC1GEOM_FORMAT
+ : BVERR_SRC2GEOM_FORMAT,
+ "only RGB source is supported for fill.");
+ goto exit;
+ }
+
+ /* Finish previous batch if any. */
+ bverror = batch->batchend(bvbltparams, batch);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Parse destination parameters. */
+ bverror = parse_destination(bvbltparams, batch);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Ignore the blit if destination rectangle is empty. */
+ if (null_rect(&dstinfo->rect.clip)) {
+ GCDBG(GCZONE_FILL, "empty destination rectangle.\n");
+ goto exit;
+ }
+
+ /* Map the destination. */
+ bverror = do_map(bvbltparams->dstdesc, batch, &dstmap);
+ if (bverror != BVERR_NONE) {
+ bvbltparams->errdesc = gccontext->bverrorstr;
+ goto exit;
+ }
+
+ /* Set the new destination. */
+ bverror = set_dst(bvbltparams, batch, dstmap);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /***********************************************************************
+ ** Allocate command buffer.
+ */
+
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmofill),
+ (void **) &gcmofill);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /***********************************************************************
+ ** Set dummy source.
+ */
+
+ /* Set surface dummy width and height. */
+ gcmofill->src.rotation_ldst = gcmofillsrc_rotation_ldst;
+ gcmofill->src.rotation.raw = 0;
+ gcmofill->src.rotation.reg.surf_width = 1;
+ gcmofill->src.config.raw = 0;
+
+ gcmofill->src.rotationheight_ldst = gcmofillsrc_rotationheight_ldst;
+ gcmofill->src.rotationheight.reg.height = 1;
+ gcmofill->src.rotationangle.raw = 0;
+ gcmofill->src.rotationangle.reg.dst = rotencoding[dstinfo->angle];
+ gcmofill->src.rotationangle.reg.dst_mirror = GCREG_MIRROR_NONE;
+
+ /* Disable alpha blending. */
+ gcmofill->src.alphacontrol_ldst = gcmofillsrc_alphacontrol_ldst;
+ gcmofill->src.alphacontrol.raw = 0;
+ gcmofill->src.alphacontrol.reg.enable = GCREG_ALPHA_CONTROL_ENABLE_OFF;
+
+ /***********************************************************************
+ ** Set fill color.
+ */
+
+ /* Get source rectangle shortcut. */
+ srcorig = &srcinfo->rect.orig;
+
+ switch (srcinfo->angle) {
+ case ROT_ANGLE_0:
+ physleft = srcorig->left;
+ phystop = srcorig->top;
+ break;
+
+ case ROT_ANGLE_90:
+ physleft = srcorig->top;
+ phystop = srcinfo->width - srcorig->left - 1;
+ break;
+
+ case ROT_ANGLE_180:
+ physleft = srcinfo->width - srcorig->left - 1;
+ phystop = srcinfo->height - srcorig->top - 1;
+ break;
+
+ case ROT_ANGLE_270:
+ physleft = srcinfo->height - srcorig->top - 1;
+ phystop = srcorig->left;
+ break;
+
+ default:
+ physleft = 0;
+ phystop = 0;
+ GCERR("invalid source angle %d.\n", srcinfo->angle);
+ }
+
+ fillcolorptr
+ = (unsigned char *) srcinfo->buf.desc->virtaddr
+ + phystop * srcinfo->stride1
+ + physleft * srcinfo->format.bitspp / 8;
+
+ gcmofill->clearcolor_ldst = gcmofill_clearcolor_ldst;
+ gcmofill->clearcolor.raw = getinternalcolor(fillcolorptr,
+ &srcinfo->format);
+
+ /***********************************************************************
+ ** Configure and start fill.
+ */
+
+ /* Set destination configuration. */
+ gcmofill->dstconfig_ldst = gcmofill_dstconfig_ldst;
+ gcmofill->dstconfig.raw = 0;
+ gcmofill->dstconfig.reg.swizzle = dstinfo->format.swizzle;
+ gcmofill->dstconfig.reg.format = dstinfo->format.format;
+ gcmofill->dstconfig.reg.endian = dstinfo->format.endian;
+ gcmofill->dstconfig.reg.command = GCREG_DEST_CONFIG_COMMAND_CLEAR;
+
+ /* Set ROP3. */
+ gcmofill->rop_ldst = gcmofill_rop_ldst;
+ gcmofill->rop.raw = 0;
+ gcmofill->rop.reg.type = GCREG_ROP_TYPE_ROP3;
+ gcmofill->rop.reg.fg = srcinfo->rop;
+
+ /* Set START_DE command. */
+ gcmofill->startde.cmd.fld = gcfldstartde;
+
+ /* Set destination rectangle. */
+ dstadj = &dstinfo->rect.adj;
+ gcmofill->rect.left = dstadj->left;
+ gcmofill->rect.top = dstadj->top;
+ gcmofill->rect.right = dstadj->right;
+ gcmofill->rect.bottom = dstadj->bottom;
+
+exit:
+ GCEXITARG(GCZONE_FILL, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
diff --git a/drivers/misc/gcx/gcbv/gcfilter.c b/drivers/misc/gcx/gcbv/gcfilter.c
--- /dev/null
@@ -0,0 +1,1490 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Vivante Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_KERNEL (1 << 0)
+#define GCZONE_FILTER (1 << 1)
+#define GCZONE_BLEND (1 << 2)
+#define GCZONE_TYPE (1 << 3)
+#define GCZONE_SRC (1 << 4)
+#define GCZONE_DEST (1 << 5)
+#define GCZONE_SURF (1 << 6)
+
+GCDBG_FILTERDEF(filter, GCZONE_NONE,
+ "kernel",
+ "filter",
+ "blend",
+ "type",
+ "src",
+ "dest",
+ "surf")
+
+
+/*******************************************************************************
+ * Miscellaneous defines.
+ */
+
+#define GC_BYTES_PER_CACHELINE (64)
+#define GC_BITS_PER_CACHELINE (GC_BYTES_PER_CACHELINE * 8)
+#define GC_CACHELINE_ALIGN_16 (GC_BITS_PER_CACHELINE / 16 - 1)
+#define GC_CACHELINE_ALIGN_32 (GC_BITS_PER_CACHELINE / 32 - 1)
+
+enum gcscaletype {
+ GC_SCALE_OPF,
+ GC_SCALE_HOR,
+ GC_SCALE_VER,
+ GC_SCALE_HOR_FLIPPED,
+ GC_SCALE_VER_FLIPPED
+};
+
+/*******************************************************************************
+ * Scale factor format: unsigned 1.31 fixed point.
+ */
+
+#define GC_SCALE_TYPE unsigned int
+#define GC_SCALE_FRACTION 31
+#define GC_SCALE_ONE ((GC_SCALE_TYPE) (1 << GC_SCALE_FRACTION))
+
+
+/*******************************************************************************
+ * X coordinate format: signed 4.28 fixed point.
+ */
+
+#define GC_COORD_TYPE int
+#define GC_COORD_FRACTION 28
+#define GC_COORD_PI ((GC_COORD_TYPE) 0x3243F6C0)
+#define GC_COORD_2OVERPI ((GC_COORD_TYPE) 0x0A2F9832)
+#define GC_COORD_PIOVER2 ((GC_COORD_TYPE) 0x1921FB60)
+#define GC_COORD_ZERO ((GC_COORD_TYPE) 0)
+#define GC_COORD_HALF ((GC_COORD_TYPE) (1 << (GC_COORD_FRACTION - 1)))
+#define GC_COORD_ONE ((GC_COORD_TYPE) (1 << GC_COORD_FRACTION))
+#define GC_COORD_NEGONE ((GC_COORD_TYPE) (~GC_COORD_ONE + 1))
+#define GC_COORD_SUBPIX_STEP ((GC_COORD_TYPE) \
+ (1 << (GC_COORD_FRACTION - GC_PHASE_BITS)))
+
+
+/*******************************************************************************
+ * Hardware coefficient format: signed 2.14 fixed point.
+ */
+
+#define GC_COEF_TYPE short
+#define GC_COEF_FRACTION 14
+#define GC_COEF_ZERO ((GC_COEF_TYPE) 0)
+#define GC_COEF_ONE ((GC_COEF_TYPE) (1 << GC_COEF_FRACTION))
+#define GC_COEF_NEGONE ((GC_COEF_TYPE) (~GC_COEF_ONE + 1))
+
+
+/*******************************************************************************
+ * Weight sum format: x.28 fixed point.
+ */
+
+#define GC_SUM_TYPE long long
+#define GC_SUM_FRACTION GC_COORD_FRACTION
+
+
+/*******************************************************************************
+ * Math shortcuts.
+ */
+
+#define computescale(dstsize, srcsize) ((GC_SCALE_TYPE) \
+ div_u64(((u64) (dstsize)) << GC_SCALE_FRACTION, (srcsize)) \
+)
+
+#define normweight(weight, sum) ((GC_COORD_TYPE) \
+ div64_s64(((s64) (weight)) << GC_COORD_FRACTION, (sum)) \
+)
+
+#define convertweight(weight) ((GC_COEF_TYPE) \
+ ((weight) >> (GC_COORD_FRACTION - GC_COEF_FRACTION)) \
+)
+
+
+/*******************************************************************************
+ * Fixed point SINE function. Takes a positive value in range [0..pi/2].
+ */
+
+static GC_COORD_TYPE sine(GC_COORD_TYPE x)
+{
+ static const GC_COORD_TYPE sinetable[] = {
+ 0x00000000, 0x001FFFEB, 0x003FFF55, 0x005FFDC0,
+ 0x007FFAAB, 0x009FF596, 0x00BFEE01, 0x00DFE36C,
+ 0x00FFD557, 0x011FC344, 0x013FACB2, 0x015F9120,
+ 0x017F7010, 0x019F4902, 0x01BF1B78, 0x01DEE6F2,
+ 0x01FEAAEE, 0x021E66F0, 0x023E1A7C, 0x025DC50C,
+ 0x027D6624, 0x029CFD48, 0x02BC89F8, 0x02DC0BB8,
+ 0x02FB8204, 0x031AEC64, 0x033A4A5C, 0x03599B64,
+ 0x0378DF08, 0x039814CC, 0x03B73C2C, 0x03D654B0,
+ 0x03F55DDC, 0x04145730, 0x04334030, 0x04521868,
+ 0x0470DF58, 0x048F9488, 0x04AE3770, 0x04CCC7A8,
+ 0x04EB44A8, 0x0509ADF8, 0x05280328, 0x054643B0,
+ 0x05646F28, 0x05828508, 0x05A084E0, 0x05BE6E38,
+ 0x05DC4098, 0x05F9FB80, 0x06179E88, 0x06352928,
+ 0x06529AF8, 0x066FF380, 0x068D3248, 0x06AA56D8,
+ 0x06C760C0, 0x06E44F90, 0x070122C8, 0x071DD9F8,
+ 0x073A74B8, 0x0756F290, 0x07735308, 0x078F95B0,
+ 0x07ABBA20, 0x07C7BFD8, 0x07E3A678, 0x07FF6D88,
+ 0x081B14A0, 0x08369B40, 0x08520110, 0x086D4590,
+ 0x08886860, 0x08A36910, 0x08BE4730, 0x08D90250,
+ 0x08F39A20, 0x090E0E10, 0x09285DD0, 0x094288E0,
+ 0x095C8EF0, 0x09766F90, 0x09902A60, 0x09A9BEE0,
+ 0x09C32CC0, 0x09DC7390, 0x09F592F0, 0x0A0E8A70,
+ 0x0A2759C0, 0x0A400070, 0x0A587E20, 0x0A70D270,
+ 0x0A88FD00, 0x0AA0FD60, 0x0AB8D350, 0x0AD07E50,
+ 0x0AE7FE10, 0x0AFF5230, 0x0B167A50, 0x0B2D7610,
+ 0x0B444520, 0x0B5AE730, 0x0B715BC0, 0x0B87A290,
+ 0x0B9DBB40, 0x0BB3A580, 0x0BC960F0, 0x0BDEED30,
+ 0x0BF44A00, 0x0C0976F0, 0x0C1E73D0, 0x0C334020,
+ 0x0C47DBB0, 0x0C5C4620, 0x0C707F20, 0x0C848660,
+ 0x0C985B80, 0x0CABFE50, 0x0CBF6E60, 0x0CD2AB80,
+ 0x0CE5B550, 0x0CF88B80, 0x0D0B2DE0, 0x0D1D9C10,
+ 0x0D2FD5C0, 0x0D41DAB0, 0x0D53AAA0, 0x0D654540,
+ 0x0D76AA40, 0x0D87D970, 0x0D98D280, 0x0DA99530,
+ 0x0DBA2140, 0x0DCA7650, 0x0DDA9450, 0x0DEA7AD0,
+ 0x0DFA29B0, 0x0E09A0B0, 0x0E18DF80, 0x0E27E5F0,
+ 0x0E36B3C0, 0x0E4548B0, 0x0E53A490, 0x0E61C720,
+ 0x0E6FB020, 0x0E7D5F70, 0x0E8AD4C0, 0x0E980FF0,
+ 0x0EA510B0, 0x0EB1D6F0, 0x0EBE6260, 0x0ECAB2D0,
+ 0x0ED6C810, 0x0EE2A200, 0x0EEE4070, 0x0EF9A310,
+ 0x0F04C9E0, 0x0F0FB490, 0x0F1A6300, 0x0F24D510,
+ 0x0F2F0A80, 0x0F390340, 0x0F42BF10, 0x0F4C3DE0,
+ 0x0F557F70, 0x0F5E83C0, 0x0F674A80, 0x0F6FD3B0,
+ 0x0F781F20, 0x0F802CB0, 0x0F87FC40, 0x0F8F8DA0,
+ 0x0F96E0D0, 0x0F9DF5B0, 0x0FA4CC00, 0x0FAB63D0,
+ 0x0FB1BCF0, 0x0FB7D740, 0x0FBDB2B0, 0x0FC34F30,
+ 0x0FC8ACA0, 0x0FCDCAF0, 0x0FD2AA10, 0x0FD749E0,
+ 0x0FDBAA50, 0x0FDFCB50, 0x0FE3ACD0, 0x0FE74EC0,
+ 0x0FEAB110, 0x0FEDD3C0, 0x0FF0B6B0, 0x0FF359F0,
+ 0x0FF5BD50, 0x0FF7E0E0, 0x0FF9C490, 0x0FFB6850,
+ 0x0FFCCC30, 0x0FFDF010, 0x0FFED400, 0x0FFF77F0,
+ 0x0FFFDBF0, 0x0FFFFFE0, 0x0FFFE3D0, 0x0FFF87D0,
+ 0x0FFEEBC0, 0x0FFE0FC0, 0x0FFCF3D0, 0x0FFB97E0
+ };
+
+ enum {
+ indexwidth = 8,
+ intwidth = 1,
+ indexshift = intwidth
+ + GC_COORD_FRACTION
+ - indexwidth
+ };
+
+ unsigned int p1, p2;
+ GC_COORD_TYPE p1x, p2x;
+ GC_COORD_TYPE p1y, p2y;
+ GC_COORD_TYPE dx, dy;
+ GC_COORD_TYPE a, b;
+ GC_COORD_TYPE result;
+
+ /* Determine the indices of two closest points in the table. */
+ p1 = ((unsigned int) x) >> indexshift;
+ p2 = p1 + 1;
+
+ if ((p1 >= countof(sinetable)) || (p2 >= countof(sinetable))) {
+ GCERR("invalid table index.\n");
+ return GC_COORD_ZERO;
+ }
+
+ /* Determine the coordinates of the two closest points. */
+ p1x = p1 << indexshift;
+ p2x = p2 << indexshift;
+
+ p1y = sinetable[p1];
+ p2y = sinetable[p2];
+
+ /* Determine the deltas. */
+ dx = p2x - p1x;
+ dy = p2y - p1y;
+
+ /* Find the slope and the y-intercept. */
+ b = (GC_COORD_TYPE) div64_s64(((s64) dy) << GC_COORD_FRACTION, dx);
+ a = p1y - (GC_COORD_TYPE) (((s64) b * p1x) >> GC_COORD_FRACTION);
+
+ /* Compute the result. */
+ result = a + (GC_COORD_TYPE) (((s64) b * x) >> GC_COORD_FRACTION);
+ return result;
+}
+
+
+/*******************************************************************************
+ * SINC function used in filter kernel generation.
+ */
+
+static GC_COORD_TYPE sinc_filter(GC_COORD_TYPE x, int radius)
+{
+ GC_COORD_TYPE result;
+ s64 radius64;
+ s64 pit, pitd;
+ s64 normpit, normpitd;
+ int negpit, negpitd;
+ int quadpit, quadpitd;
+ GC_COORD_TYPE sinpit, sinpitd;
+ GC_COORD_TYPE f1, f2;
+
+ if (x == GC_COORD_ZERO)
+ return GC_COORD_ONE;
+
+ radius64 = abs(radius) << GC_COORD_FRACTION;
+ if (x > radius64)
+ return GC_COORD_ZERO;
+
+ pit = (((s64) GC_COORD_PI) * x) >> GC_COORD_FRACTION;
+ pitd = div_s64(pit, radius);
+
+ /* Sine table only has values for the first positive quadrant,
+ * remove the sign here. */
+ if (pit < 0) {
+ normpit = -pit;
+ negpit = 1;
+ } else {
+ normpit = pit;
+ negpit = 0;
+ }
+
+ if (pitd < 0) {
+ normpitd = -pitd;
+ negpitd = 1;
+ } else {
+ normpitd = pitd;
+ negpitd = 0;
+ }
+
+ /* Determine which quadrant we are in. */
+ quadpit = (int) ((normpit * GC_COORD_2OVERPI)
+ >> (2 * GC_COORD_FRACTION));
+ quadpitd = (int) ((normpitd * GC_COORD_2OVERPI)
+ >> (2 * GC_COORD_FRACTION));
+
+ /* Move coordinates to the first quadrant. */
+ normpit -= (s64) GC_COORD_PIOVER2 * quadpit;
+ normpitd -= (s64) GC_COORD_PIOVER2 * quadpitd;
+
+ /* Normalize the quadrant numbers. */
+ quadpit %= 4;
+ quadpitd %= 4;
+
+ /* Flip the coordinates if necessary. */
+ if ((quadpit == 1) || (quadpit == 3))
+ normpit = GC_COORD_PIOVER2 - normpit;
+
+ if ((quadpitd == 1) || (quadpitd == 3))
+ normpitd = GC_COORD_PIOVER2 - normpitd;
+
+ sinpit = sine((GC_COORD_TYPE) normpit);
+ sinpitd = sine((GC_COORD_TYPE) normpitd);
+
+ /* Negate depending on the quadrant. */
+ if (negpit) {
+ if ((quadpit == 0) || (quadpit == 1))
+ sinpit = -sinpit;
+ } else {
+ if ((quadpit == 2) || (quadpit == 3))
+ sinpit = -sinpit;
+ }
+
+ if (negpitd) {
+ if ((quadpitd == 0) || (quadpitd == 1))
+ sinpitd = -sinpitd;
+ } else {
+ if ((quadpitd == 2) || (quadpitd == 3))
+ sinpitd = -sinpitd;
+ }
+
+ f1 = (GC_COORD_TYPE)
+ div64_s64(((s64) sinpit) << GC_COORD_FRACTION, pit);
+ f2 = (GC_COORD_TYPE)
+ div64_s64(((s64) sinpitd) << GC_COORD_FRACTION, pitd);
+
+ result = (GC_COORD_TYPE) ((((s64) f1) * f2)
+ >> GC_COORD_FRACTION);
+
+ return result;
+}
+
+
+/*******************************************************************************
+ * Filter kernel generator based on SINC function.
+ */
+
+static void calculate_sync_filter(struct gcfilterkernel *gcfilterkernel)
+{
+ GC_SCALE_TYPE scale;
+ GC_COORD_TYPE subpixset[GC_TAP_COUNT];
+ GC_COORD_TYPE subpixeloffset;
+ GC_COORD_TYPE x, weight;
+ GC_SUM_TYPE weightsum;
+ short convweightsum;
+ int kernelhalf, padding;
+ int subpixpos, kernelpos;
+ short *kernelarray;
+ short count, adjustfrom, adjustment;
+ int index;
+
+ /* Compute the scale factor. */
+ scale = (gcfilterkernel->dstsize >= gcfilterkernel->srcsize)
+ ? GC_SCALE_ONE
+ : computescale(gcfilterkernel->dstsize, gcfilterkernel->srcsize);
+
+ /* Calculate the kernel half. */
+ kernelhalf = (int) (gcfilterkernel->kernelsize >> 1);
+
+ /* Init the subpixel offset. */
+ subpixeloffset = GC_COORD_HALF;
+
+ /* Determine kernel padding size. */
+ padding = (GC_TAP_COUNT - gcfilterkernel->kernelsize) / 2;
+
+ /* Set initial kernel array pointer. */
+ kernelarray = gcfilterkernel->kernelarray;
+
+ /* Loop through each subpixel. */
+ for (subpixpos = 0; subpixpos < GC_PHASE_LOAD_COUNT; subpixpos += 1) {
+ /* Compute weights. */
+ weightsum = GC_COORD_ZERO;
+ for (kernelpos = 0; kernelpos < GC_TAP_COUNT; kernelpos += 1) {
+ /* Determine the current index. */
+ index = kernelpos - padding;
+
+ /* Pad with zeros left side. */
+ if (index < 0) {
+ subpixset[kernelpos] = GC_COORD_ZERO;
+ continue;
+ }
+
+ /* Pad with zeros right side. */
+ if (index >= (int) gcfilterkernel->kernelsize) {
+ subpixset[kernelpos] = GC_COORD_ZERO;
+ continue;
+ }
+
+ /* "Filter off" case. */
+ if (gcfilterkernel->kernelsize == 1) {
+ subpixset[kernelpos] = GC_COORD_ONE;
+
+ /* Update the sum of the weights. */
+ weightsum += GC_COORD_ONE;
+ continue;
+ }
+
+ /* Compute X coordinate. */
+ x = ((index - kernelhalf) << GC_COORD_FRACTION)
+ + subpixeloffset;
+
+ /* Scale the coordinate. */
+ x = (GC_COORD_TYPE)
+ ((((s64) x) * scale) >> GC_SCALE_FRACTION);
+
+ /* Compute the weight. */
+ subpixset[kernelpos] = sinc_filter(x, kernelhalf);
+
+ /* Update the sum of the weights. */
+ weightsum += subpixset[kernelpos];
+ }
+
+ /* Convert the weights to the hardware format. */
+ convweightsum = 0;
+ for (kernelpos = 0; kernelpos < GC_TAP_COUNT; kernelpos += 1) {
+ /* Normalize the current weight. */
+ weight = normweight(subpixset[kernelpos], weightsum);
+
+ /* Convert the weight to fixed point. */
+ if (weight == GC_COORD_ZERO)
+ kernelarray[kernelpos] = GC_COEF_ZERO;
+ else if (weight >= GC_COORD_ONE)
+ kernelarray[kernelpos] = GC_COEF_ONE;
+ else if (weight <= GC_COORD_NEGONE)
+ kernelarray[kernelpos] = GC_COEF_NEGONE;
+ else
+ kernelarray[kernelpos] = convertweight(weight);
+
+ /* Compute the sum of all coefficients. */
+ convweightsum += kernelarray[kernelpos];
+ }
+
+ /* Adjust the fixed point coefficients so that the sum is 1. */
+ count = GC_COEF_ONE - convweightsum;
+ if (count < 0) {
+ count = -count;
+ adjustment = -1;
+ } else {
+ adjustment = 1;
+ }
+
+ if (count > GC_TAP_COUNT) {
+ GCERR("adjust count is too high = %d\n", count);
+ } else {
+ adjustfrom = (GC_TAP_COUNT - count) / 2;
+ for (kernelpos = 0; kernelpos < count; kernelpos += 1)
+ kernelarray[adjustfrom + kernelpos]
+ += adjustment;
+ }
+
+ /* Advance the array pointer. */
+ kernelarray += GC_TAP_COUNT;
+
+ /* Advance to the next subpixel. */
+ subpixeloffset -= GC_COORD_SUBPIX_STEP;
+ }
+}
+
+
+/*******************************************************************************
+ * Loads a filter into the GPU.
+ */
+
+static enum bverror load_filter(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ enum gcfiltertype type,
+ unsigned int kernelsize,
+ unsigned int scalefactor,
+ unsigned int srcsize,
+ unsigned int dstsize,
+ struct gccmdldstate arraystate)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gccontext *gccontext = get_context();
+ struct gcfiltercache *filtercache;
+ struct list_head *filterlist;
+ struct list_head *filterhead;
+ struct gcfilterkernel *gcfilterkernel;
+ struct gcmofilterkernel *gcmofilterkernel;
+
+ GCDBG(GCZONE_KERNEL, "kernelsize = %d\n", kernelsize);
+ GCDBG(GCZONE_KERNEL, "srcsize = %d\n", srcsize);
+ GCDBG(GCZONE_KERNEL, "dstsize = %d\n", dstsize);
+ GCDBG(GCZONE_KERNEL, "scalefactor = 0x%08X\n", scalefactor);
+
+ /* Is the filter already loaded? */
+ if ((gccontext->loadedfilter != NULL) &&
+ (gccontext->loadedfilter->type == type) &&
+ (gccontext->loadedfilter->kernelsize == kernelsize) &&
+ (gccontext->loadedfilter->scalefactor == scalefactor)) {
+ GCDBG(GCZONE_KERNEL, "filter already computed.\n");
+ gcfilterkernel = gccontext->loadedfilter;
+ goto load;
+ }
+
+ /* Get the proper filter cache. */
+ filtercache = &gccontext->filtercache[type][kernelsize];
+ filterlist = &filtercache->list;
+
+ /* Try to find existing filter. */
+ GCDBG(GCZONE_KERNEL, "scanning for existing filter.\n");
+ list_for_each(filterhead, filterlist) {
+ gcfilterkernel = list_entry(filterhead,
+ struct gcfilterkernel,
+ link);
+ if (gcfilterkernel->scalefactor == scalefactor) {
+ GCDBG(GCZONE_KERNEL, "filter found @ 0x%08X.\n",
+ (unsigned int) gcfilterkernel);
+ break;
+ }
+ }
+
+ /* Found the filter? */
+ if (filterhead != filterlist) {
+ /* Move the filter to the head of the list. */
+ if (filterlist->next != filterhead) {
+ GCDBG(GCZONE_KERNEL, "moving to the head.\n");
+ list_move(filterhead, filterlist);
+ }
+ } else {
+ GCDBG(GCZONE_KERNEL, "filter not found.\n");
+ if (filtercache->count == GC_FILTER_CACHE_MAX) {
+ GCDBG(GCZONE_KERNEL,
+ "reached the maximum number of filters.\n");
+ filterhead = filterlist->prev;
+ list_move(filterhead, filterlist);
+
+ gcfilterkernel = list_entry(filterhead,
+ struct gcfilterkernel,
+ link);
+ } else {
+ GCDBG(GCZONE_KERNEL, "allocating new filter.\n");
+ gcfilterkernel = gcalloc(struct gcfilterkernel,
+ sizeof(struct gcfilterkernel));
+ if (gcfilterkernel == NULL) {
+ BVSETBLTERROR(BVERR_OOM,
+ "filter allocation failed");
+ goto exit;
+ }
+
+ list_add(&gcfilterkernel->link, filterlist);
+ }
+
+ /* Update the number of filters. */
+ filtercache->count += 1;
+
+ /* Initialize the filter. */
+ gcfilterkernel->type = type;
+ gcfilterkernel->kernelsize = kernelsize;
+ gcfilterkernel->srcsize = srcsize;
+ gcfilterkernel->dstsize = dstsize;
+ gcfilterkernel->scalefactor = scalefactor;
+
+ /* Compute the coefficients. */
+ calculate_sync_filter(gcfilterkernel);
+ }
+
+load:
+ GCDBG(GCZONE_KERNEL, "loading filter.\n");
+
+ /* Load the filter. */
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmofilterkernel),
+ (void **) &gcmofilterkernel);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ gcmofilterkernel->kernelarray_ldst = arraystate;
+ memcpy(&gcmofilterkernel->kernelarray,
+ gcfilterkernel->kernelarray,
+ sizeof(gcfilterkernel->kernelarray));
+
+ /* Set the filter. */
+ gccontext->loadedfilter = gcfilterkernel;
+
+exit:
+ return bverror;
+}
+
+
+/*******************************************************************************
+ * Compute the scale factor.
+ */
+
+static inline unsigned int get_scale_factor(unsigned int srcsize,
+ unsigned int dstsize)
+{
+ if ((srcsize <= 1) || (dstsize <= 1))
+ return 0;
+
+ return ((srcsize - 1) << 16) / (dstsize - 1);
+}
+
+
+/*******************************************************************************
+ * Rasterizer setup.
+ */
+
+static enum bverror startvr(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct bvbuffmap *srcmap,
+ struct bvbuffmap *dstmap,
+ struct gcsurface *srcinfo,
+ struct gcsurface *dstinfo,
+ unsigned int srcx,
+ unsigned int srcy,
+ struct gcrect *dstrect,
+ int srcangle,
+ int dstangle,
+ enum gcscaletype scaletype)
+{
+ enum bverror bverror;
+ struct gccontext *gccontext = get_context();
+ struct gcfilter *gcfilter;
+
+ struct gcmovrdst *gcmovrdst;
+ struct gcmovrsrc *gcmovrsrc;
+ struct gcmostartvr *gcmostartvr;
+
+ struct gcrect srcorig;
+
+ GCENTERARG(GCZONE_FILTER, "scaletype = %d\n", scaletype);
+
+ /* Get a shortcut to the filter properties. */
+ gcfilter = &batch->op.filter;
+
+ /***********************************************************************
+ * Program the destination.
+ */
+
+ GCDBG(GCZONE_FILTER, "destination:\n");
+ GCDBG(GCZONE_FILTER, " angle = %d\n", dstangle);
+ GCDBG(GCZONE_FILTER, " pixalign = %d,%d\n",
+ dstinfo->xpixalign, dstinfo->ypixalign);
+ GCDBG(GCZONE_FILTER, " bytealign = %d\n", dstinfo->bytealign1);
+ GCDBG(GCZONE_FILTER, " virtstride = %d\n", dstinfo->stride1);
+ GCDBG(GCZONE_FILTER, " format = %d\n", dstinfo->format.format);
+ GCDBG(GCZONE_FILTER, " swizzle = %d\n", dstinfo->format.swizzle);
+ GCDBG(GCZONE_FILTER, " endian = %d\n", dstinfo->format.endian);
+ GCDBG(GCZONE_FILTER, " premul = %d\n", dstinfo->format.premultiplied);
+ GCDBG(GCZONE_FILTER, " physwidth = %d\n", dstinfo->physwidth);
+ GCDBG(GCZONE_FILTER, " physheight = %d\n", dstinfo->physheight);
+ GCPRINT_RECT(GCZONE_FILTER, " rect", dstrect);
+
+ /* Allocate command buffer. */
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmovrdst),
+ (void **) &gcmovrdst);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Add the address fixup. */
+ add_fixup(bvbltparams, batch, &gcmovrdst->address, dstinfo->bytealign1);
+
+ /* Set surface parameters. */
+ gcmovrdst->config_ldst = gcmovrdst_config_ldst;
+ gcmovrdst->address = GET_MAP_HANDLE(dstmap);
+ gcmovrdst->stride = dstinfo->stride1;
+ gcmovrdst->config.raw = 0;
+ gcmovrdst->config.reg.swizzle = dstinfo->format.swizzle;
+ gcmovrdst->config.reg.format = dstinfo->format.format;
+ gcmovrdst->config.reg.endian = dstinfo->format.endian;
+
+ /* Set surface width and height. */
+ gcmovrdst->rotation.raw = 0;
+ gcmovrdst->rotation.reg.surf_width = dstinfo->physwidth;
+ gcmovrdst->rotationheight_ldst = gcmovrdst_rotationheight_ldst;
+ gcmovrdst->rotationheight.raw = 0;
+ gcmovrdst->rotationheight.reg.height = dstinfo->physheight;
+
+ /***********************************************************************
+ * Program the source.
+ */
+
+ /* Determine adjusted source bounding rectangle and origin. */
+ srcorig = srcinfo->rect.orig;
+ srcorig.left -= srcinfo->xpixalign;
+ srcorig.right -= srcinfo->xpixalign;
+ srcx -= (srcinfo->xpixalign << 16);
+
+ GCDBG(GCZONE_FILTER, "source:\n");
+ GCDBG(GCZONE_FILTER, " angle = %d\n", srcangle);
+ GCDBG(GCZONE_FILTER, " pixalign = %d,%d\n",
+ srcinfo->xpixalign, srcinfo->ypixalign);
+ GCDBG(GCZONE_FILTER, " bytealign = %d\n", srcinfo->bytealign1);
+ GCDBG(GCZONE_FILTER, " virtstride = %d\n", srcinfo->stride1);
+ GCDBG(GCZONE_FILTER, " format = %d\n", srcinfo->format.format);
+ GCDBG(GCZONE_FILTER, " swizzle = %d\n", srcinfo->format.swizzle);
+ GCDBG(GCZONE_FILTER, " endian = %d\n", srcinfo->format.endian);
+ GCDBG(GCZONE_FILTER, " premul = %d\n", srcinfo->format.premultiplied);
+ GCDBG(GCZONE_FILTER, " physwidth = %d\n", srcinfo->physwidth);
+ GCDBG(GCZONE_FILTER, " physheight = %d\n", srcinfo->physheight);
+ GCPRINT_RECT(GCZONE_FILTER, " rect", &srcorig);
+
+ GCDBG(GCZONE_FILTER, "src origin: 0x%08X,0x%08X\n", srcx, srcy);
+
+ /* Allocate command buffer. */
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmovrsrc),
+ (void **) &gcmovrsrc);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ add_fixup(bvbltparams, batch, &gcmovrsrc->address, srcinfo->bytealign1);
+
+ gcmovrsrc->config_ldst = gcmovrsrc_config_ldst;
+
+ gcmovrsrc->address = GET_MAP_HANDLE(srcmap);
+ gcmovrsrc->stride = srcinfo->stride1;
+
+ gcmovrsrc->rotation.raw = 0;
+ gcmovrsrc->rotation.reg.surf_width = srcinfo->physwidth;
+
+ gcmovrsrc->config.raw = 0;
+ gcmovrsrc->config.reg.swizzle = srcinfo->format.swizzle;
+ gcmovrsrc->config.reg.format = srcinfo->format.format;
+ gcmovrsrc->config.reg.endian = srcinfo->format.endian;
+
+ if (gccontext->gccaps.l2cachefor420 &&
+ (srcinfo->format.type == BVFMT_YUV) &&
+ (srcinfo->format.cs.yuv.planecount > 1) &&
+ ((srcinfo->angle & 1) != 0))
+ gcmovrsrc->config.reg.disable420L2cache
+ = GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_DISABLED;
+
+ gcmovrsrc->pos_ldst = gcmovrsrc_pos_ldst;
+
+ /* Source image bounding box. */
+ gcmovrsrc->lt.reg.left = srcorig.left;
+ gcmovrsrc->lt.reg.top = srcorig.top;
+ gcmovrsrc->rb.reg.right = srcorig.right;
+ gcmovrsrc->rb.reg.bottom = srcorig.bottom;
+
+ /* Fractional origin. */
+ gcmovrsrc->x = srcx;
+ gcmovrsrc->y = srcy;
+
+ /* Program rotation. */
+ gcmovrsrc->rotation_ldst = gcmovrsrc_rotation_ldst;
+ gcmovrsrc->rotationheight.reg.height = srcinfo->physheight;
+ gcmovrsrc->rotationangle.raw = 0;
+ gcmovrsrc->rotationangle.reg.src = rotencoding[srcangle];
+ gcmovrsrc->rotationangle.reg.dst = rotencoding[dstangle];
+ gcmovrsrc->rotationangle.reg.src_mirror = srcinfo->mirror;
+ gcmovrsrc->rotationangle.reg.dst_mirror = dstinfo->mirror;
+
+ gcmovrsrc->rop_ldst = gcmovrsrc_rop_ldst;
+ gcmovrsrc->rop.raw = 0;
+ gcmovrsrc->rop.reg.type = GCREG_ROP_TYPE_ROP3;
+ gcmovrsrc->rop.reg.fg = 0xCC;
+
+ /* Program multiply modes. */
+ gcmovrsrc->mult_ldst = gcmovrsrc_mult_ldst;
+ gcmovrsrc->mult.raw = 0;
+ gcmovrsrc->mult.reg.srcglobalpremul = srcinfo->srcglobalpremul;
+
+ if (srcinfo->format.premultiplied)
+ gcmovrsrc->mult.reg.srcpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+ else
+ gcmovrsrc->mult.reg.srcpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+ if (dstinfo->format.premultiplied) {
+ gcmovrsrc->mult.reg.dstpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE;
+
+ gcmovrsrc->mult.reg.dstdemul
+ = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE;
+ } else {
+ gcmovrsrc->mult.reg.dstpremul
+ = GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE;
+
+ gcmovrsrc->mult.reg.dstdemul
+ = GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE;
+ }
+
+ /* Program YUV source. */
+ if (srcinfo->format.type == BVFMT_YUV) {
+ bverror = set_yuvsrc(bvbltparams, batch, srcinfo, srcmap);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ }
+
+ /***********************************************************************
+ * Program blending.
+ */
+
+ bverror = set_blending(bvbltparams, batch, srcinfo);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /***********************************************************************
+ * Start the operation.
+ */
+
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmostartvr),
+ (void **) &gcmostartvr);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ switch (scaletype) {
+ case GC_SCALE_OPF:
+ gcmostartvr->scalex = gcfilter->horscalefactor;
+ gcmostartvr->scaley = gcfilter->verscalefactor;
+ gcmostartvr->config = gcregvrconfig_onepass;
+ break;
+
+ case GC_SCALE_HOR:
+ gcmostartvr->scalex = gcfilter->horscalefactor;
+ gcmostartvr->scaley = 0;
+ gcmostartvr->config = gcregvrconfig_horizontal;
+ break;
+
+ case GC_SCALE_VER:
+ gcmostartvr->scalex = 0;
+ gcmostartvr->scaley = gcfilter->verscalefactor;
+ gcmostartvr->config = gcregvrconfig_vertical;
+ break;
+
+ case GC_SCALE_HOR_FLIPPED:
+ gcmostartvr->scalex = 0;
+ gcmostartvr->scaley = gcfilter->horscalefactor;
+ gcmostartvr->config = gcregvrconfig_vertical;
+ break;
+
+ case GC_SCALE_VER_FLIPPED:
+ gcmostartvr->scalex = gcfilter->verscalefactor;
+ gcmostartvr->scaley = 0;
+ gcmostartvr->config = gcregvrconfig_horizontal;
+ break;
+ }
+
+ gcmostartvr->scale_ldst = gcmostartvr_scale_ldst;
+ gcmostartvr->rect_ldst = gcmostartvr_rect_ldst;
+ gcmostartvr->config_ldst = gcmostartvr_config_ldst;
+
+ gcmostartvr->lt.left = dstrect->left;
+ gcmostartvr->lt.top = dstrect->top;
+ gcmostartvr->rb.right = dstrect->right;
+ gcmostartvr->rb.bottom = dstrect->bottom;
+
+exit:
+ GCEXITARG(GCZONE_FILTER, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+
+/*******************************************************************************
+ * Main fiter entry.
+ */
+
+enum bverror do_filter(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gccontext *gccontext = get_context();
+
+ struct gcfilter *gcfilter;
+ struct gcsurface *dstinfo;
+
+ bool scalex, scaley;
+ bool singlepass, twopass;
+
+ struct gcrect *tmporig;
+ struct gcrect *srcorig, *srcclip;
+ struct gcrect *dstorig, *dstclip, *dstadj;
+
+ struct gcrect dstdelta;
+ struct gcrect srcdelta;
+
+ struct bvbuffmap *srcmap = NULL;
+ struct bvbuffmap *tmpmap = NULL;
+ struct bvbuffmap *dstmap = NULL;
+
+ struct gcmovrconfigex *gcmovrconfigex;
+
+ unsigned int srcx, srcy;
+ unsigned int srcwidth, srcheight;
+ unsigned int dstwidth, dstheight;
+ unsigned int horscalefactor, verscalefactor;
+ unsigned int kernelsize;
+ int angle;
+
+ GCENTER(GCZONE_FILTER);
+
+ /* Get some shortcuts. */
+ dstinfo = &batch->dstinfo;
+ gcfilter = &batch->op.filter;
+
+ /* Finish previous batch if any. */
+ bverror = batch->batchend(bvbltparams, batch);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* ROP is not supported by the filters. */
+ if ((srcinfo->rop & 0xFF) != 0xCC) {
+ BVSETBLTERROR(BVERR_ROP,
+ "only copy ROP is supported in scaling mode");
+ goto exit;
+ }
+
+ /* Zero-fill for source is not supported. */
+ if (srcinfo->format.zerofill) {
+ BVSETBLTERROR((srcinfo->index == 0)
+ ? BVERR_SRC1GEOM_FORMAT
+ : BVERR_SRC2GEOM_FORMAT,
+ "0 filling is not supported.");
+ goto exit;
+ }
+
+ /* Parse the scale mode. */
+ bverror = parse_scalemode(bvbltparams, batch);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Parse destination parameters. */
+ bverror = parse_destination(bvbltparams, batch);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Ignore the blit if destination rectangle is empty. */
+ if (null_rect(&dstinfo->rect.clip)) {
+ GCDBG(GCZONE_DEST, "empty destination rectangle.\n");
+ goto exit;
+ }
+
+ /* Get rectangle shortcuts. */
+ srcorig = &srcinfo->rect.orig;
+ srcclip = &srcinfo->rect.clip;
+
+ if ((srcinfo->index == 1) && dstinfo->haveaux) {
+ GCDBG(GCZONE_FILTER, "picking aux set");
+ dstorig = &dstinfo->auxrect.orig;
+ dstclip = &dstinfo->auxrect.clip;
+ dstadj = &dstinfo->auxrect.adj;
+ } else {
+ GCDBG(GCZONE_FILTER, "picking main set");
+ dstorig = &dstinfo->rect.orig;
+ dstclip = &dstinfo->rect.clip;
+ dstadj = &dstinfo->rect.adj;
+ }
+
+ GCPRINT_RECT(GCZONE_FILTER, "original src", srcorig);
+ GCPRINT_RECT(GCZONE_FILTER, "original dst", dstorig);
+ GCPRINT_RECT(GCZONE_FILTER, "clipped dst", dstclip);
+ GCPRINT_RECT(GCZONE_FILTER, "adjusted dst", dstadj);
+
+ /* Compute the source alignments needed to compensate
+ * for the surface base address misalignment if any. */
+ srcinfo->xpixalign = get_pixel_offset(srcinfo, 0);
+ srcinfo->ypixalign = 0;
+ srcinfo->bytealign1 = (srcinfo->xpixalign
+ * (int) srcinfo->format.bitspp) / 8;
+ GCDBG(GCZONE_SRC, "source surface offset (pixels) = %d,%d\n",
+ srcinfo->xpixalign, srcinfo->ypixalign);
+ GCDBG(GCZONE_SRC, "source surface offset (bytes) = %d\n",
+ srcinfo->bytealign1);
+
+ /* Determine physical size. */
+ if ((srcinfo->angle % 2) == 0) {
+ srcinfo->physwidth = srcinfo->width
+ - srcinfo->xpixalign;
+ srcinfo->physheight = srcinfo->height
+ - srcinfo->ypixalign;
+ } else {
+ srcinfo->physwidth = srcinfo->height
+ - srcinfo->xpixalign;
+ srcinfo->physheight = srcinfo->width
+ - srcinfo->ypixalign;
+ }
+ GCDBG(GCZONE_SRC, "source physical size = %dx%d\n",
+ srcinfo->physwidth, srcinfo->physheight);
+
+ /* OPF does not support source rotation, which can be compensated by
+ * using destination rotation. Compute the adjustment angle.
+ * For simplicity use the same algorythm for both OPF and TPF. */
+ srcinfo->adjangle = (4 - srcinfo->angle) % 4;
+ adjust_angle(srcinfo, dstinfo);
+
+ /* Set rotation angle. */
+ angle = dstinfo->angle;
+
+ /* Compute U/V plane offsets. */
+ if ((srcinfo->format.type == BVFMT_YUV) &&
+ (srcinfo->format.cs.yuv.planecount > 1))
+ set_computeyuv(srcinfo, 0, 0);
+
+ /* Determine the source and destination rectangles. */
+ srcwidth = srcorig->right - srcorig->left;
+ srcheight = srcorig->bottom - srcorig->top;
+ dstwidth = dstorig->right - dstorig->left;
+ dstheight = dstorig->bottom - dstorig->top;
+
+ GCDBG(GCZONE_FILTER, "adjusted input src size: %dx%d\n",
+ srcwidth, srcheight);
+ GCDBG(GCZONE_FILTER, "adjusted input dst size: %dx%d\n",
+ dstwidth, dstheight);
+
+ /* Determine the data path. */
+ scalex = (srcwidth != dstwidth);
+ scaley = (srcheight != dstheight);
+
+ twopass = scalex && scaley;
+ if (twopass) {
+ if (((gcfilter->horkernelsize == 3) ||
+ (gcfilter->horkernelsize == 5)) &&
+ ((gcfilter->verkernelsize == 3) ||
+ (gcfilter->verkernelsize == 5))) {
+ singlepass = true;
+ twopass = false;
+ } else {
+ singlepass = false;
+ }
+ } else {
+ /* Two pass filter in one pass mode. */
+ if (!scalex && !scaley)
+ GCERR("no scaling needed.\n");
+
+ GCDBG(GCZONE_FILTER, "only %s scaling needed.\n",
+ scalex ? "horizontal" : "vertical");
+
+ singlepass = false;
+ }
+
+ gcbv_debug_scaleblt(scalex, scaley, singlepass);
+
+ /* Compute the scale factors. */
+ gcfilter->horscalefactor =
+ horscalefactor = get_scale_factor(srcwidth, dstwidth);
+ GCDBG(GCZONE_FILTER, "horscalefactor = 0x%08X\n", horscalefactor);
+
+ gcfilter->verscalefactor =
+ verscalefactor = get_scale_factor(srcheight, dstheight);
+ GCDBG(GCZONE_FILTER, "verscalefactor = 0x%08X\n", verscalefactor);
+
+ /* Compute the destination offsets. */
+ dstdelta.left = dstclip->left - dstorig->left;
+ dstdelta.top = dstclip->top - dstorig->top;
+ dstdelta.right = dstclip->right - dstorig->left;
+ dstdelta.bottom = dstclip->bottom - dstorig->top;
+ GCDBG(GCZONE_FILTER, "dst deltas = (%d,%d)-(%d,%d)\n",
+ dstdelta.left, dstdelta.top, dstdelta.right, dstdelta.bottom);
+
+ /* Compute the source offsets. */
+ srcdelta.left = dstdelta.left * horscalefactor;
+ srcdelta.top = dstdelta.top * verscalefactor;
+ srcdelta.right = (dstdelta.right - 1) * horscalefactor + (1 << 16);
+ srcdelta.bottom = (dstdelta.bottom - 1) * verscalefactor + (1 << 16);
+
+ /* Before rendering each destination pixel, the HW will select the
+ * corresponding source center pixel to apply the kernel around.
+ * To make this process precise we need to add 0.5 to source initial
+ * coordinates here; this will make HW pick the next source pixel if
+ * the fraction is equal or greater then 0.5. */
+ srcdelta.left += 0x00008000;
+ srcdelta.top += 0x00008000;
+ srcdelta.right += 0x00008000;
+ srcdelta.bottom += 0x00008000;
+ GCDBG(GCZONE_FILTER, "src deltas = "
+ "(0x%08X,0x%08X)-(0x%08X,0x%08X)\n",
+ srcdelta.left, srcdelta.top, srcdelta.right, srcdelta.bottom);
+ GCDBG(GCZONE_FILTER, "src deltas (int) = (%d,%d)-(%d,%d)\n",
+ srcdelta.left >> 16, srcdelta.top >> 16,
+ srcdelta.right >> 16, srcdelta.bottom >> 16);
+
+ /* Determine clipped source rectangle. */
+ srcclip->left = srcorig->left + (srcdelta.left >> 16);
+ srcclip->top = srcorig->top + (srcdelta.top >> 16);
+ srcclip->right = srcorig->left + (srcdelta.right >> 16);
+ srcclip->bottom = srcorig->top + (srcdelta.bottom >> 16);
+
+ GCDBG(GCZONE_FILTER, "source:\n");
+ GCDBG(GCZONE_FILTER, " stride = %d, geom = %dx%d\n",
+ srcinfo->stride1, srcinfo->width, srcinfo->height);
+ GCDBG(GCZONE_FILTER, " rotation = %d\n", srcinfo->angle);
+ GCPRINT_RECT(GCZONE_FILTER, " clipped rect", srcclip);
+
+ GCDBG(GCZONE_FILTER, "destination:\n");
+ GCDBG(GCZONE_FILTER, " stride = %d, geom size = %dx%d\n",
+ dstinfo->stride1, dstinfo->width, dstinfo->height);
+ GCDBG(GCZONE_FILTER, " rotation = %d\n", dstinfo->angle);
+ GCPRINT_RECT(GCZONE_FILTER, " clipped rect", dstclip);
+
+ /* Validate the source rectangle. */
+ if (!valid_rect(srcinfo, srcclip)) {
+ BVSETBLTERROR((srcinfo->index == 0)
+ ? BVERR_SRC1RECT
+ : BVERR_SRC2RECT,
+ "invalid source rectangle.");
+ goto exit;
+ }
+
+ /* Ignore the blit if source rectangle is empty. */
+ if (null_rect(srcclip)) {
+ GCDBG(GCZONE_SURF, "empty source rectangle.\n");
+ goto exit;
+ }
+
+ /* Map the source. */
+ bverror = do_map(srcinfo->buf.desc, batch, &srcmap);
+ if (bverror != BVERR_NONE) {
+ bvbltparams->errdesc = gccontext->bverrorstr;
+ goto exit;
+ }
+
+ /* Map the destination. */
+ bverror = do_map(dstinfo->buf.desc, batch, &dstmap);
+ if (bverror != BVERR_NONE) {
+ bvbltparams->errdesc = gccontext->bverrorstr;
+ goto exit;
+ }
+
+ /* Do single pass filter if we can. */
+ if (singlepass) {
+ GCDBG(GCZONE_TYPE, "single pass\n");
+
+ /* Determine the kernel size to use. */
+ kernelsize = max(gcfilter->horkernelsize,
+ gcfilter->verkernelsize);
+
+ /* Set kernel size. */
+ bverror = claim_buffer(bvbltparams, batch,
+ sizeof(struct gcmovrconfigex),
+ (void **) &gcmovrconfigex);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ gcmovrconfigex->config_ldst = gcmovrconfigex_config_ldst;
+ gcmovrconfigex->config.raw = ~0U;
+ gcmovrconfigex->config.reg.kernelsize = kernelsize;
+ gcmovrconfigex->config.reg.mask_kernelsize
+ = GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_ENABLED;
+
+ /* Setup single pass. */
+ srcx = (srcorig->left << 16) + srcdelta.left;
+ srcy = (srcorig->top << 16) + srcdelta.top;
+ GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy);
+
+ /* Load the horizontal filter. */
+ bverror = load_filter(bvbltparams, batch,
+ GC_FILTER_SYNC,
+ gcfilter->horkernelsize,
+ gcfilter->horscalefactor,
+ srcwidth, dstwidth,
+ gcmofilterkernel_horizontal_ldst);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Load the vertical filter. */
+ bverror = load_filter(bvbltparams, batch,
+ GC_FILTER_SYNC,
+ gcfilter->verkernelsize,
+ gcfilter->verscalefactor,
+ srcheight, dstheight,
+ gcmofilterkernel_vertical_ldst);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Start the operation. */
+ bverror = startvr(bvbltparams, batch,
+ srcmap, dstmap, srcinfo, dstinfo,
+ srcx, srcy, dstadj,
+ ROT_ANGLE_0, angle,
+ GC_SCALE_OPF);
+ } else if (twopass) {
+ unsigned int horkernelhalf;
+ unsigned int leftextra, rightextra;
+ unsigned int tmprectwidth, tmprectheight;
+ unsigned int tmpalignmask, dstalignmask;
+ unsigned int tmpsize;
+ struct gcsurface tmpinfo;
+
+ GCDBG(GCZONE_TYPE, "two pass\n");
+
+ /* Initialize the temporaty surface descriptor. */
+ tmpinfo.index = -1;
+ tmpinfo.angle = angle;
+ tmpinfo.mirror = GCREG_MIRROR_NONE;
+ tmpinfo.rop = 0;
+ GCDBG(GCZONE_FILTER, "tmp angle = %d\n", tmpinfo.angle);
+
+ /* Transfer blending parameters from the source to the
+ * temporary buffer so that the blending would happen
+ * on the second pass. */
+ tmpinfo.gca = srcinfo->gca;
+ srcinfo->gca = NULL;
+
+ /* Determine temporary surface format. */
+ if (srcinfo->format.type == BVFMT_YUV) {
+ if (tmpinfo.angle == ROT_ANGLE_0) {
+ GCDBG(GCZONE_FILTER,
+ "tmp format = 4:2:2\n");
+ parse_format(bvbltparams, OCDFMT_YUYV,
+ &tmpinfo.format);
+ } else {
+ GCDBG(GCZONE_FILTER,
+ "tmp format = dst format\n");
+ tmpinfo.format = dstinfo->format;
+ }
+ } else {
+ GCDBG(GCZONE_FILTER,
+ "tmp format = src format\n");
+ tmpinfo.format = srcinfo->format;
+ }
+
+ /* Determine pixel alignment masks. */
+ tmpalignmask = GC_BITS_PER_CACHELINE
+ / tmpinfo.format.bitspp - 1;
+ dstalignmask = GC_BITS_PER_CACHELINE
+ / dstinfo->format.bitspp - 1;
+
+ /* In partial filter blit cases, the vertical pass has to render
+ * more pixel information to the left and to the right of the
+ * temporary image so that the next pass has its necessary
+ * kernel information on the edges of the image. */
+ horkernelhalf = gcfilter->horkernelsize >> 1;
+
+ leftextra = srcdelta.left >> 16;
+ rightextra = srcwidth - (srcdelta.right >> 16);
+
+ if (leftextra > horkernelhalf)
+ leftextra = horkernelhalf;
+
+ if (rightextra > horkernelhalf)
+ rightextra = horkernelhalf;
+
+ GCDBG(GCZONE_FILTER, "leftextra = %d, rightextra = %d\n",
+ leftextra, rightextra);
+
+ /* Determine the source origin. */
+ srcx = ((srcorig->left - leftextra) << 16) + srcdelta.left;
+ srcy = (srcorig->top << 16) + srcdelta.top;
+ GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy);
+ GCDBG(GCZONE_SRC, "src origin (int): %d,%d\n",
+ srcx >> 16, srcy >> 16);
+
+ /* Determine the size of the temporary rectangle. */
+ tmprectwidth = leftextra + rightextra
+ + ((srcdelta.right >> 16) - (srcdelta.left >> 16));
+ tmprectheight = dstadj->bottom - dstadj->top;
+ GCDBG(GCZONE_FILTER, "tmp rect size: %dx%d\n",
+ tmprectwidth, tmprectheight);
+
+ /* Shortcut to temporary rectangle. */
+ tmporig = &tmpinfo.rect.orig;
+
+ /* Determine the temporary destination coordinates. */
+ switch (angle) {
+ case ROT_ANGLE_0:
+ case ROT_ANGLE_180:
+ tmporig->left = (srcx >> 16) & tmpalignmask;
+ tmporig->top = 0;
+ tmporig->right = tmporig->left + tmprectwidth;
+ tmporig->bottom = tmprectheight;
+
+ tmpinfo.width = (tmporig->right + tmpalignmask)
+ & ~tmpalignmask;
+ tmpinfo.height = tmprectheight;
+
+ tmpinfo.physwidth = tmpinfo.width;
+ tmpinfo.physheight = tmpinfo.height;
+ break;
+
+ case ROT_ANGLE_90:
+ tmporig->left = 0;
+ tmporig->top = dstadj->left & dstalignmask;
+ tmporig->right = tmprectwidth;
+ tmporig->bottom = tmporig->top + tmprectheight;
+
+ tmpinfo.width = tmprectwidth;
+ tmpinfo.height = (tmporig->bottom + tmpalignmask)
+ & ~tmpalignmask;
+
+ tmpinfo.physwidth = tmpinfo.height;
+ tmpinfo.physheight = tmpinfo.width;
+ break;
+
+ case ROT_ANGLE_270:
+ tmporig->left = 0;
+ tmporig->right = tmprectwidth;
+ tmporig->bottom = dstadj->left & dstalignmask;
+
+ tmpinfo.width = tmprectwidth;
+ tmpinfo.height = (tmporig->bottom + tmprectheight
+ + tmpalignmask) & ~tmpalignmask;
+
+ tmporig->bottom = tmpinfo.height - tmporig->bottom;
+ tmporig->top = tmporig->bottom - tmprectheight;
+
+ tmpinfo.physwidth = tmpinfo.height;
+ tmpinfo.physheight = tmpinfo.width;
+ break;
+ }
+
+ GCPRINT_RECT(GCZONE_DEST, "tmp dest", tmporig);
+ GCDBG(GCZONE_FILTER, "tmp geometry size = %dx%d\n",
+ tmpinfo.width, tmpinfo.height);
+ GCDBG(GCZONE_FILTER, "tmp physical size = %dx%d\n",
+ tmpinfo.physwidth, tmpinfo.physheight);
+
+ /* Determine the size of the temporaty surface. */
+ tmpinfo.stride1 = (tmpinfo.physwidth
+ * tmpinfo.format.bitspp) / 8;
+ tmpsize = tmpinfo.stride1 * tmpinfo.physheight;
+ tmpsize += GC_BYTES_PER_CACHELINE;
+ tmpsize = (tmpsize + ~PAGE_MASK) & PAGE_MASK;
+ GCDBG(GCZONE_FILTER, "tmp stride = %d\n", tmpinfo.stride1);
+ GCDBG(GCZONE_FILTER, "tmp size (bytes) = %d\n", tmpsize);
+
+ /* Allocate the temporary buffer. */
+ bverror = allocate_temp(bvbltparams, tmpsize);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Map the temporary buffer. */
+ tmpinfo.buf.desc = gccontext->tmpbuffdesc;
+ bverror = do_map(tmpinfo.buf.desc, batch, &tmpmap);
+ if (bverror != BVERR_NONE) {
+ bvbltparams->errdesc = gccontext->bverrorstr;
+ goto exit;
+ }
+
+ /* Compute the temp buffer alignments needed to compensate
+ * for the surface base address misalignment if any. */
+ tmpinfo.xpixalign = 0;
+ tmpinfo.ypixalign = 0;
+ tmpinfo.bytealign1 = (get_pixel_offset(&tmpinfo, 0)
+ * (int) tmpinfo.format.bitspp) / 8;
+ GCDBG(GCZONE_SRC, "tmp offset (pixels) = %d,%d\n",
+ tmpinfo.xpixalign, tmpinfo.ypixalign);
+ GCDBG(GCZONE_SRC, "tmp offset (bytes) = %d\n",
+ tmpinfo.bytealign1);
+
+ /* Load the vertical filter. */
+ bverror = load_filter(bvbltparams, batch,
+ GC_FILTER_SYNC,
+ gcfilter->verkernelsize,
+ gcfilter->verscalefactor,
+ srcheight, dstheight,
+ gcmofilterkernel_shared_ldst);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Start the operation. */
+ GCDBG(GCZONE_TYPE, "vertical pass\n");
+ bverror = startvr(bvbltparams, batch,
+ srcmap, tmpmap, srcinfo, &tmpinfo,
+ srcx, srcy, tmporig,
+ ROT_ANGLE_0, angle,
+ GC_SCALE_VER);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Rotation is done in the first pass. */
+ tmpinfo.adjangle = (4 - angle) % 4;
+ adjust_angle(&tmpinfo, dstinfo);
+
+ /* Determine the source origin. */
+ switch (angle) {
+ case ROT_ANGLE_0:
+ srcx = ((tmporig->left + leftextra) << 16)
+ + (srcdelta.left & 0xFFFF);
+ srcy = tmporig->top << 16;
+ break;
+
+ case ROT_ANGLE_90:
+ srcx = tmporig->left << 16;
+ srcy = ((tmporig->top + rightextra) << 16)
+ + ((~srcdelta.right + 1) & 0xFFFF);
+ break;
+
+ case ROT_ANGLE_180:
+ srcx = ((tmporig->left + rightextra) << 16)
+ + ((~srcdelta.right + 1) & 0xFFFF);
+ srcy = tmporig->top << 16;
+ break;
+
+ case ROT_ANGLE_270:
+ srcx = tmporig->left << 16;
+ srcy = ((tmporig->top + leftextra) << 16)
+ + (srcdelta.left & 0xFFFF);
+ break;
+ }
+
+ GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy);
+
+ /* Load the horizontal filter. */
+ bverror = load_filter(bvbltparams, batch,
+ GC_FILTER_SYNC,
+ gcfilter->horkernelsize,
+ gcfilter->horscalefactor,
+ srcwidth, dstwidth,
+ gcmofilterkernel_shared_ldst);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Start the operation. */
+ GCDBG(GCZONE_TYPE, "horizontal pass\n");
+ bverror = startvr(bvbltparams, batch,
+ tmpmap, dstmap, &tmpinfo, dstinfo,
+ srcx, srcy, dstadj,
+ ROT_ANGLE_0, ROT_ANGLE_0,
+ ((angle % 2) == 0)
+ ? GC_SCALE_HOR
+ : GC_SCALE_HOR_FLIPPED);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ } else {
+ GCDBG(GCZONE_TYPE, "two pass (%s pass config).\n",
+ scalex ? "horizontal" : "vertical");
+
+ /* Setup single pass. */
+ srcx = (srcorig->left << 16) + srcdelta.left;
+ srcy = (srcorig->top << 16) + srcdelta.top;
+ GCDBG(GCZONE_SRC, "src origin: 0x%08X,0x%08X\n", srcx, srcy);
+
+ if (scalex) {
+ /* Load the horizontal filter. */
+ bverror = load_filter(bvbltparams, batch,
+ GC_FILTER_SYNC,
+ gcfilter->horkernelsize,
+ gcfilter->horscalefactor,
+ srcwidth, dstwidth,
+ gcmofilterkernel_shared_ldst);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Start the operation. */
+ bverror = startvr(bvbltparams, batch,
+ srcmap, dstmap, srcinfo, dstinfo,
+ srcx, srcy, dstadj,
+ ROT_ANGLE_0, angle,
+ GC_SCALE_HOR);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ } else {
+ /* Load the vertical filter. */
+ bverror = load_filter(bvbltparams, batch,
+ GC_FILTER_SYNC,
+ gcfilter->verkernelsize,
+ gcfilter->verscalefactor,
+ srcheight, dstheight,
+ gcmofilterkernel_shared_ldst);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Start the operation. */
+ bverror = startvr(bvbltparams, batch,
+ srcmap, dstmap, srcinfo, dstinfo,
+ srcx, srcy, dstadj,
+ ROT_ANGLE_0, angle,
+ GC_SCALE_VER);
+ if (bverror != BVERR_NONE)
+ goto exit;
+ }
+ }
+
+exit:
+ GCEXITARG(GCZONE_FILTER, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
diff --git a/drivers/misc/gcx/gcbv/gcmain.c b/drivers/misc/gcx/gcbv/gcmain.c
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * gcmain.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "gcbv.h"
+
+/*******************************************************************************
+ * BLTsville interface exposure.
+ */
+
+static struct bventry ops = {
+ .structsize = sizeof(struct bventry),
+};
+
+static void gcbv_clear(void)
+{
+ ops.bv_map = NULL;
+ ops.bv_unmap = NULL;
+ ops.bv_blt = NULL;
+ ops.bv_cache = NULL;
+}
+
+static void gcbv_assign(void)
+{
+ ops.bv_map = bv_map;
+ ops.bv_unmap = bv_unmap;
+ ops.bv_blt = bv_blt;
+ ops.bv_cache = bv_cache;
+}
+
+void gcbv_init(struct bventry *entry)
+{
+ *entry = ops;
+}
+EXPORT_SYMBOL(gcbv_init);
+
+
+/*******************************************************************************
+ * Convert floating point in 0..1 range to an 8-bit value in range 0..255.
+ */
+
+union gcfp {
+ struct {
+ unsigned int mantissa:23;
+ unsigned int exponent:8;
+ unsigned int sign:1;
+ } comp;
+
+ float value;
+};
+
+unsigned char gcfp2norm8(float value)
+{
+ union gcfp gcfp;
+ int exponent;
+ unsigned int mantissa;
+ int shift;
+
+ /* Get access to components. */
+ gcfp.value = value;
+
+ /* Clamp negatives. */
+ if (gcfp.comp.sign)
+ return 0;
+
+ /* Get unbiased exponent. */
+ exponent = (int) gcfp.comp.exponent - 127;
+
+ /* Clamp if too large. */
+ if (exponent >= 0)
+ return 255;
+
+ /* Clamp if too small. */
+ if (exponent < -8)
+ return 0;
+
+ /* Determine the shift value. */
+ shift = (23 - 8) - exponent;
+
+ /* Compute the mantissa. */
+ mantissa = (gcfp.comp.mantissa | 0x00800000) >> shift;
+
+ /* Normalize. */
+ mantissa = (mantissa * 255) >> 8;
+
+ return (unsigned char) mantissa;
+}
+
+
+/*******************************************************************************
+ * Surface allocation.
+ */
+
+enum bverror allocate_surface(struct bvbuffdesc **bvbuffdesc,
+ void **buffer,
+ unsigned int size)
+{
+ enum bverror bverror;
+ struct bvbuffdesc *tempbuffdesc = NULL;
+ void *tempbuff = NULL;
+ unsigned long *temparray = NULL;
+ struct bvphysdesc *tempphysdesc = NULL;
+ unsigned char *pageaddr;
+ unsigned int i;
+
+ /* Allocate surface buffer descriptor. */
+ tempbuffdesc = vmalloc(sizeof(struct bvbuffdesc));
+ if (tempbuffdesc == NULL) {
+ BVSETERROR(BVERR_OOM, "failed to allocate surface");
+ goto exit;
+ }
+
+ /* Initialize buffer descriptor. */
+ tempbuffdesc->structsize = sizeof(struct bvbuffdesc);
+ tempbuffdesc->virtaddr = NULL;
+ tempbuffdesc->length = size;
+ tempbuffdesc->map = NULL;
+ tempbuffdesc->auxtype = BVAT_PHYSDESC;
+ tempbuffdesc->auxptr = NULL;
+
+ /* Allocate the surface. */
+ tempbuff = vmalloc(size);
+ if (tempbuff == NULL) {
+ BVSETERROR(BVERR_OOM, "failed to allocate surface");
+ goto exit;
+ }
+ tempbuffdesc->virtaddr = tempbuff;
+
+ /* Allocate the physical descriptor. */
+ tempphysdesc = vmalloc(sizeof(struct bvphysdesc));
+ if (tempphysdesc == NULL) {
+ BVSETERROR(BVERR_OOM, "failed to allocate surface");
+ goto exit;
+ }
+ tempbuffdesc->auxptr = tempphysdesc;
+
+ /* Initialize physical descriptor. */
+ tempphysdesc->structsize = sizeof(struct bvphysdesc);
+ tempphysdesc->pagesize = PAGE_SIZE;
+ tempphysdesc->pagearray = NULL;
+ tempphysdesc->pagecount = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+ tempphysdesc->pageoffset = 0;
+
+ /* Allocate array of pages. */
+ temparray = vmalloc(tempphysdesc->pagecount * sizeof(unsigned long));
+ if (temparray == NULL) {
+ BVSETERROR(BVERR_OOM, "failed to allocate surface");
+ goto exit;
+ }
+ tempphysdesc->pagearray = temparray;
+
+ /* Initialize the array. */
+ pageaddr = (unsigned char *) tempbuff;
+ for (i = 0; i < tempphysdesc->pagecount; i += 1) {
+ temparray[i] = PFN_PHYS(vmalloc_to_pfn(pageaddr));
+ pageaddr += PAGE_SIZE;
+ }
+
+ /* Set return pointers. */
+ *bvbuffdesc = tempbuffdesc;
+ *buffer = tempbuff;
+ return BVERR_NONE;
+
+exit:
+ free_surface(tempbuffdesc, tempbuff);
+ return bverror;
+}
+
+void free_surface(struct bvbuffdesc *bvbuffdesc,
+ void *buffer)
+{
+ if (bvbuffdesc != NULL) {
+ if (bvbuffdesc->virtaddr != NULL)
+ vfree(bvbuffdesc->virtaddr);
+
+ if (bvbuffdesc->auxptr != NULL) {
+ struct bvphysdesc *bvphysdesc;
+
+ bvphysdesc = (struct bvphysdesc *) bvbuffdesc->auxptr;
+ if (bvphysdesc->pagearray != NULL)
+ vfree(bvphysdesc->pagearray);
+
+ vfree(bvphysdesc);
+ }
+
+ vfree(bvbuffdesc);
+ }
+}
+
+
+/*******************************************************************************
+ * Cache operation wrapper.
+ */
+
+enum bverror gcbvcacheop(int count, struct c2dmrgn rgn[],
+ enum bvcacheop cacheop)
+{
+ enum bverror err = BVERR_NONE;
+
+ switch (cacheop) {
+
+ case DMA_FROM_DEVICE:
+ c2dm_l2cache(count, rgn, cacheop);
+ c2dm_l1cache(count, rgn, cacheop);
+ break;
+
+ case DMA_TO_DEVICE:
+ c2dm_l1cache(count, rgn, cacheop);
+ c2dm_l2cache(count, rgn, cacheop);
+ break;
+
+ case DMA_BIDIRECTIONAL:
+ c2dm_l1cache(count, rgn, cacheop);
+ c2dm_l2cache(count, rgn, cacheop);
+ break;
+
+ default:
+ err = BVERR_CACHEOP;
+ break;
+ }
+
+ return err;
+}
+
+
+/*******************************************************************************
+ * Device init/cleanup.
+ */
+
+static int __init mod_init(void)
+{
+ bv_init();
+
+ if (gc_is_hw_present())
+ gcbv_assign();
+ else
+ GCERR("gcx hardware is not present\n");
+
+ return 0;
+}
+
+static void __exit mod_exit(void)
+{
+ gcbv_clear();
+ bv_exit();
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("www.vivantecorp.com");
+MODULE_AUTHOR("www.ti.com");
+module_init(mod_init);
+module_exit(mod_exit);
diff --git a/drivers/misc/gcx/gcbv/gcmain.h b/drivers/misc/gcx/gcbv/gcmain.h
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * gcmain.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCMAIN_H
+#define GCMAIN_H
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/list.h>
+#include <linux/gcx.h>
+#include <linux/gcioctl.h>
+#include <linux/gccore.h>
+#include <linux/bltsville.h>
+#include <linux/bvinternal.h>
+#include "gcbvdebug.h"
+
+#define GC_DEV_NAME "gc2d"
+
+
+/*******************************************************************************
+ * Miscellaneous macros.
+ */
+
+#define gcalloc(type, size) \
+ kmalloc(size, GFP_KERNEL)
+
+#define gcfree(ptr) \
+ kfree(ptr)
+
+
+/*******************************************************************************
+ * Core driver API definitions.
+ */
+
+#define gc_getcaps_wrapper(gcicaps) \
+ gc_caps(gcicaps)
+
+#define gc_commit_wrapper(gcicommit) \
+ gc_commit(gcicommit, false)
+
+#define gc_map_wrapper(gcimap) \
+ gc_map(gcimap, false)
+
+#define gc_unmap_wrapper(gcimap) \
+ gc_unmap(gcimap, false)
+
+#define gc_callback_wrapper(gcicallbackarm) \
+ gc_callback(gcicallbackarm, false)
+
+
+/*******************************************************************************
+ * Surface allocation.
+ */
+
+enum bverror allocate_surface(struct bvbuffdesc **bvbuffdesc,
+ void **buffer,
+ unsigned int size);
+
+void free_surface(struct bvbuffdesc *bvbuffdesc,
+ void *buffer);
+
+
+/*******************************************************************************
+ * Floating point conversions.
+ */
+
+unsigned char gcfp2norm8(float value);
+
+
+/*******************************************************************************
+ * Cache operation wrapper.
+ */
+
+enum bverror gcbvcacheop(int count, struct c2dmrgn rgn[],
+ enum bvcacheop cacheop);
+
+
+/*******************************************************************************
+ * BLTsville API.
+ */
+
+void bv_init(void);
+void bv_exit(void);
+
+enum bverror bv_map(struct bvbuffdesc *buffdesc);
+enum bverror bv_unmap(struct bvbuffdesc *buffdesc);
+enum bverror bv_blt(struct bvbltparams *bltparams);
+enum bverror bv_cache(struct bvcopparams *copparams);
+
+#endif
diff --git a/drivers/misc/gcx/gcbv/gcmap.c b/drivers/misc/gcx/gcbv/gcmap.c
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Vivante Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_MAPPING (1 << 0)
+
+GCDBG_FILTERDEF(map, GCZONE_NONE,
+ "mapping")
+
+
+/*******************************************************************************
+ * Memory management.
+ */
+
+enum bverror do_map(struct bvbuffdesc *bvbuffdesc,
+ struct gcbatch *batch,
+ struct bvbuffmap **map)
+{
+ static const int mapsize
+ = sizeof(struct bvbuffmap)
+ + sizeof(struct bvbuffmapinfo);
+
+ enum bverror bverror;
+ struct gccontext *gccontext = get_context();
+ struct bvbuffmap *bvbuffmap;
+ struct bvbuffmapinfo *bvbuffmapinfo;
+ struct bvphysdesc *bvphysdesc;
+ bool mappedbyothers;
+ struct gcimap gcimap;
+ struct gcschedunmap *gcschedunmap;
+
+ GCENTERARG(GCZONE_MAPPING, "bvbuffdesc = 0x%08X\n",
+ (unsigned int) bvbuffdesc);
+
+ /* Lock access to the mapping list. */
+ GCLOCK(&gccontext->maplock);
+
+ /* Try to find existing mapping. */
+ bvbuffmap = bvbuffdesc->map;
+ while (bvbuffmap != NULL) {
+ if (bvbuffmap->bv_unmap == bv_unmap)
+ break;
+ bvbuffmap = bvbuffmap->nextmap;
+ }
+
+ /* Not mapped yet? */
+ if (bvbuffmap == NULL) {
+ /* New mapping, allocate a record. */
+ if (gccontext->buffmapvac == NULL) {
+ bvbuffmap = gcalloc(struct bvbuffmap, mapsize);
+ if (bvbuffmap == NULL) {
+ BVSETERROR(BVERR_OOM,
+ "failed to allocate mapping record");
+ goto fail;
+ }
+
+ bvbuffmap->structsize = sizeof(struct bvbuffmap);
+ bvbuffmap->bv_unmap = bv_unmap;
+ bvbuffmap->handle = (unsigned long) (bvbuffmap + 1);
+ } else {
+ bvbuffmap = gccontext->buffmapvac;
+ gccontext->buffmapvac = bvbuffmap->nextmap;
+ }
+
+ /* Setup buffer mapping. Here we need to check and make sure
+ * that the buffer starts at a location that is supported by
+ * the hw. If it is not, offset is computed and the buffer is
+ * extended by the value of the offset. */
+ gcimap.gcerror = GCERR_NONE;
+ gcimap.handle = 0;
+
+ if (bvbuffdesc->auxtype == BVAT_PHYSDESC) {
+ bvphysdesc = (struct bvphysdesc *) bvbuffdesc->auxptr;
+
+ if (bvphysdesc->structsize <
+ STRUCTSIZE(bvphysdesc, pageoffset)) {
+ BVSETERROR(BVERR_BUFFERDESC_VERS,
+ "unsupported bvphysdesc version");
+ goto fail;
+ }
+
+ gcimap.buf.offset = bvphysdesc->pageoffset;
+ gcimap.pagesize = bvphysdesc->pagesize;
+ gcimap.pagearray = bvphysdesc->pagearray;
+ gcimap.size = bvbuffdesc->length;
+
+ GCDBG(GCZONE_MAPPING, "new mapping (%s):\n",
+ (batch == NULL) ? "explicit" : "implicit");
+ GCDBG(GCZONE_MAPPING, "pagesize = %lu\n",
+ bvphysdesc->pagesize);
+ GCDBG(GCZONE_MAPPING, "pagearray = 0x%08X\n",
+ (unsigned int) bvphysdesc->pagearray);
+ GCDBG(GCZONE_MAPPING, "pageoffset = %lu\n",
+ bvphysdesc->pageoffset);
+ GCDBG(GCZONE_MAPPING, "mapping size = %d\n",
+ gcimap.size);
+ } else {
+ gcimap.buf.logical = bvbuffdesc->virtaddr;
+ gcimap.pagesize = 0;
+ gcimap.pagearray = NULL;
+ gcimap.size = bvbuffdesc->length;
+
+ GCDBG(GCZONE_MAPPING, "new mapping (%s):\n",
+ (batch == NULL) ? "explicit" : "implicit");
+ GCDBG(GCZONE_MAPPING, "specified virtaddr = 0x%08X\n",
+ (unsigned int) bvbuffdesc->virtaddr);
+ GCDBG(GCZONE_MAPPING, "aligned virtaddr = 0x%08X\n",
+ (unsigned int) gcimap.buf.logical);
+ GCDBG(GCZONE_MAPPING, "mapping size = %d\n",
+ gcimap.size);
+ }
+
+ gc_map_wrapper(&gcimap);
+ if (gcimap.gcerror != GCERR_NONE) {
+ BVSETERROR(BVERR_OOM,
+ "unable to allocate gccore memory");
+ goto fail;
+ }
+
+ /* Set map handle. */
+ bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle;
+ bvbuffmapinfo->handle = gcimap.handle;
+
+ /* Initialize reference counters. */
+ if (batch == NULL) {
+ /* Explicit mapping. */
+ bvbuffmapinfo->usermap = 1;
+ bvbuffmapinfo->automap = 0;
+ } else {
+ /* Implicit mapping; if there are existing mappings
+ * from other implementations, mark this an explicit
+ * mapping as well. */
+ mappedbyothers = (bvbuffdesc->map != NULL);
+ GCDBG(GCZONE_MAPPING, "%smapped by others.\n",
+ mappedbyothers ? "" : "not ");
+
+ bvbuffmapinfo->usermap = mappedbyothers ? 1 : 0;
+ bvbuffmapinfo->automap = 1;
+ }
+
+ /* Add the record to the list of mappings. */
+ bvbuffmap->nextmap = bvbuffdesc->map;
+ bvbuffdesc->map = bvbuffmap;
+ } else {
+ /* Mapping already exists. */
+ bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle;
+
+ /* Advance reference counters. */
+ if (batch == NULL) {
+ /* Explicit mapping. */
+ GCDBG(GCZONE_MAPPING, "explicit map.\n");
+ bvbuffmapinfo->usermap += 1;
+ } else {
+ /* Implicit mapping. */
+ GCDBG(GCZONE_MAPPING, "implicit map.\n");
+ bvbuffmapinfo->automap += 1;
+ }
+
+ GCDBG(GCZONE_MAPPING, "mapping exists.\n");
+ }
+
+ GCDBG(GCZONE_MAPPING, "bvbuffmap = 0x%08X\n",
+ (unsigned int) bvbuffmap);
+ GCDBG(GCZONE_MAPPING, "explicit count = %d\n",
+ bvbuffmapinfo->usermap);
+ GCDBG(GCZONE_MAPPING, "implicit count = %d\n",
+ bvbuffmapinfo->automap);
+
+ /* Schedule for unmapping. */
+ if (batch != NULL) {
+ if (list_empty(&gccontext->unmapvac)) {
+ gcschedunmap = gcalloc(struct gcschedunmap,
+ sizeof(struct gcschedunmap));
+ if (gcschedunmap == NULL) {
+ BVSETERROR(BVERR_OOM,
+ "failed to schedule unmapping");
+ goto fail;
+ }
+ list_add(&gcschedunmap->link, &batch->unmap);
+ } else {
+ struct list_head *head;
+ head = gccontext->unmapvac.next;
+ gcschedunmap = list_entry(head,
+ struct gcschedunmap,
+ link);
+ list_move(&gcschedunmap->link, &batch->unmap);
+ }
+
+ gcschedunmap->handle = (unsigned long) bvbuffdesc;
+
+ GCDBG(GCZONE_MAPPING, "scheduled for unmapping.\n");
+ }
+
+ /* Set the map pointer. */
+ *map = bvbuffmap;
+
+ /* Unlock access to the mapping list. */
+ GCUNLOCK(&gccontext->maplock);
+
+ GCEXITARG(GCZONE_MAPPING, "handle = 0x%08X\n",
+ bvbuffmapinfo->handle);
+ return BVERR_NONE;
+
+fail:
+ if (bvbuffmap != NULL) {
+ bvbuffmap->nextmap = gccontext->buffmapvac;
+ gccontext->buffmapvac = bvbuffmap;
+ }
+
+ /* Unlock access to the mapping list. */
+ GCUNLOCK(&gccontext->maplock);
+
+ GCEXITARG(GCZONE_MAPPING, "bverror = %d\n", bverror);
+ return bverror;
+}
+
+void do_unmap_implicit(struct gcbatch *batch)
+{
+ struct gccontext *gccontext = get_context();
+ struct list_head *head, *temphead;
+ struct gcschedunmap *gcschedunmap;
+ struct bvbuffdesc *bvbuffdesc;
+ struct bvbuffmap *prev, *bvbuffmap;
+ struct bvbuffmapinfo *bvbuffmapinfo;
+
+ GCENTER(GCZONE_MAPPING);
+
+ /* Lock access to the mapping list. */
+ GCLOCK(&gccontext->maplock);
+
+ /* Scan scheduled unmappings and remove the ones that are still
+ * in use. */
+ list_for_each_safe(head, temphead, &batch->unmap) {
+ gcschedunmap = list_entry(head, struct gcschedunmap, link);
+
+ /* Cast the handle. */
+ bvbuffdesc = (struct bvbuffdesc *) gcschedunmap->handle;
+
+ /* Find our mapping. */
+ prev = NULL;
+ bvbuffmap = bvbuffdesc->map;
+ while (bvbuffmap != NULL) {
+ if (bvbuffmap->bv_unmap == bv_unmap)
+ break;
+ prev = bvbuffmap;
+ bvbuffmap = bvbuffmap->nextmap;
+ }
+
+ /* Not found? */
+ if (bvbuffmap == NULL) {
+ GCERR("mapping not found for bvbuffdesc 0x%08X.\n",
+ (unsigned int) bvbuffdesc);
+
+ /* Remove scheduled unmapping. */
+ list_move(head, &gccontext->unmapvac);
+ continue;
+ }
+
+ /* Get the info structure. */
+ bvbuffmapinfo = (struct bvbuffmapinfo *) bvbuffmap->handle;
+
+ GCDBG(GCZONE_MAPPING, "head = 0x%08X\n",
+ (unsigned int) gcschedunmap);
+ GCDBG(GCZONE_MAPPING, " bvbuffmap = 0x%08X\n",
+ (unsigned int) bvbuffmap);
+ GCDBG(GCZONE_MAPPING, " handle = 0x%08X\n",
+ bvbuffmapinfo->handle);
+
+ /* Implicit unmapping. */
+ bvbuffmapinfo->automap -= 1;
+ if (bvbuffmapinfo->automap < 0) {
+ GCERR("implicit count negative.\n");
+ bvbuffmapinfo->automap = 0;
+ }
+
+ GCDBG(GCZONE_MAPPING, " explicit count = %d\n",
+ bvbuffmapinfo->usermap);
+ GCDBG(GCZONE_MAPPING, " implicit count = %d\n",
+ bvbuffmapinfo->automap);
+
+ /* Still referenced? */
+ if (bvbuffmapinfo->usermap || bvbuffmapinfo->automap) {
+ GCDBG(GCZONE_MAPPING, " still referenced.\n");
+
+ /* Remove scheduled unmapping. */
+ list_move(head, &gccontext->unmapvac);
+ continue;
+ }
+
+ GCDBG(GCZONE_MAPPING, " ready for unmapping.\n");
+
+ /* Set the handle. */
+ gcschedunmap->handle = bvbuffmapinfo->handle;
+
+ /* Remove from the buffer descriptor. */
+ if (prev == NULL)
+ bvbuffdesc->map = bvbuffmap->nextmap;
+ else
+ prev->nextmap = bvbuffmap->nextmap;
+
+ /* Add to the vacant list. */
+ bvbuffmap->nextmap = gccontext->buffmapvac;
+ gccontext->buffmapvac = bvbuffmap;
+ }
+
+ /* Unlock access to the mapping list. */
+ GCUNLOCK(&gccontext->maplock);
+
+ GCEXIT(GCZONE_MAPPING);
+}
diff --git a/drivers/misc/gcx/gcbv/gcparser.c b/drivers/misc/gcx/gcbv/gcparser.c
--- /dev/null
@@ -0,0 +1,2416 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 Vivante Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Vivante Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gcbv.h"
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_FORMAT (1 << 0)
+#define GCZONE_FORMAT_VERBOSE (1 << 1)
+#define GCZONE_BLEND (1 << 2)
+#define GCZONE_OFFSET (1 << 3)
+#define GCZONE_DEST (1 << 4)
+#define GCZONE_SRC (1 << 5)
+#define GCZONE_SCALING (1 << 6)
+#define GCZONE_SURF (1 << 7)
+
+GCDBG_FILTERDEF(parser, GCZONE_NONE,
+ "format",
+ "formatverbose",
+ "blend",
+ "offset",
+ "dest",
+ "src",
+ "scaling",
+ "surface")
+
+
+/*******************************************************************************
+ * Internal macros.
+ */
+
+#define GCCONVERT_RECT(zone, name, bvrect, gcrect) \
+{ \
+ (gcrect)->left = (bvrect)->left; \
+ (gcrect)->top = (bvrect)->top; \
+ (gcrect)->right = (bvrect)->left + (bvrect)->width; \
+ (gcrect)->bottom = (bvrect)->top + (bvrect)->height; \
+ \
+ GCPRINT_RECT(zone, name, gcrect); \
+}
+
+
+/*******************************************************************************
+ * Pixel format parser.
+ */
+
+#define OCDFMTDEF_PLACEMENT_SHIFT 9
+#define OCDFMTDEF_PLACEMENT_MASK (3 << OCDFMTDEF_PLACEMENT_SHIFT)
+
+#define BVCOMP(Shift, Size) \
+ { Shift, Size, ((1 << Size) - 1) << Shift }
+
+#define BVRED(Shift, Size) \
+ BVCOMP(Shift, Size)
+
+#define BVGREEN(Shift, Size) \
+ BVCOMP(Shift, Size)
+
+#define BVBLUE(Shift, Size) \
+ BVCOMP(Shift, Size)
+
+#define BVALPHA(Shift, Size) \
+ BVCOMP(Shift, Size)
+
+static const unsigned int rgba16swizzle[] = {
+ GCREG_DE_SWIZZLE_ARGB,
+ GCREG_DE_SWIZZLE_RGBA,
+ GCREG_DE_SWIZZLE_ABGR,
+ GCREG_DE_SWIZZLE_BGRA
+};
+
+static const unsigned int rgb16swizzle[] = {
+ GCREG_DE_SWIZZLE_ARGB,
+ GCREG_DE_SWIZZLE_ARGB,
+ GCREG_DE_SWIZZLE_ABGR,
+ GCREG_DE_SWIZZLE_ABGR
+};
+
+static const unsigned int rgba32swizzle[] = {
+ GCREG_DE_SWIZZLE_ARGB,
+ GCREG_DE_SWIZZLE_ABGR,
+ GCREG_DE_SWIZZLE_ABGR,
+ GCREG_DE_SWIZZLE_ARGB
+};
+
+static const struct bvcsrgb xrgb4444_bits[] = {
+ { BVRED(8, 4), BVGREEN(4, 4), BVBLUE(0, 4), BVALPHA(12, 0) },
+ { BVRED(12, 4), BVGREEN(8, 4), BVBLUE(4, 4), BVALPHA(0, 0) },
+ { BVRED(0, 4), BVGREEN(4, 4), BVBLUE(8, 4), BVALPHA(12, 0) },
+ { BVRED(4, 4), BVGREEN(8, 4), BVBLUE(12, 4), BVALPHA(0, 0) }
+};
+
+static const struct bvcsrgb argb4444_bits[] = {
+ { BVRED(8, 4), BVGREEN(4, 4), BVBLUE(0, 4), BVALPHA(12, 4) },
+ { BVRED(12, 4), BVGREEN(8, 4), BVBLUE(4, 4), BVALPHA(0, 4) },
+ { BVRED(0, 4), BVGREEN(4, 4), BVBLUE(8, 4), BVALPHA(12, 4) },
+ { BVRED(4, 4), BVGREEN(8, 4), BVBLUE(12, 4), BVALPHA(0, 4) }
+};
+
+static const struct bvcsrgb xrgb1555_bits[] = {
+ { BVRED(10, 5), BVGREEN(5, 5), BVBLUE(0, 5), BVALPHA(15, 0) },
+ { BVRED(11, 5), BVGREEN(6, 5), BVBLUE(1, 5), BVALPHA(0, 0) },
+ { BVRED(0, 5), BVGREEN(5, 5), BVBLUE(10, 5), BVALPHA(15, 0) },
+ { BVRED(1, 5), BVGREEN(6, 5), BVBLUE(11, 5), BVALPHA(0, 0) }
+};
+
+static const struct bvcsrgb argb1555_bits[] = {
+ { BVRED(10, 5), BVGREEN(5, 5), BVBLUE(0, 5), BVALPHA(15, 1) },
+ { BVRED(11, 5), BVGREEN(6, 5), BVBLUE(1, 5), BVALPHA(0, 1) },
+ { BVRED(0, 5), BVGREEN(5, 5), BVBLUE(10, 5), BVALPHA(15, 1) },
+ { BVRED(1, 5), BVGREEN(6, 5), BVBLUE(11, 5), BVALPHA(0, 1) }
+};
+
+static const struct bvcsrgb rgb565_bits[] = {
+ { BVRED(11, 5), BVGREEN(5, 6), BVBLUE(0, 5), BVALPHA(0, 0) },
+ { BVRED(11, 5), BVGREEN(5, 6), BVBLUE(0, 5), BVALPHA(0, 0) },
+ { BVRED(0, 5), BVGREEN(5, 6), BVBLUE(11, 5), BVALPHA(0, 0) },
+ { BVRED(0, 5), BVGREEN(5, 6), BVBLUE(11, 5), BVALPHA(0, 0) }
+};
+
+static const struct bvcsrgb xrgb8888_bits[] = {
+ { BVRED(8, 8), BVGREEN(16, 8), BVBLUE(24, 8), BVALPHA(0, 0) },
+ { BVRED(0, 8), BVGREEN(8, 8), BVBLUE(16, 8), BVALPHA(24, 0) },
+ { BVRED(24, 8), BVGREEN(16, 8), BVBLUE(8, 8), BVALPHA(0, 0) },
+ { BVRED(16, 8), BVGREEN(8, 8), BVBLUE(0, 8), BVALPHA(24, 0) }
+};
+
+static const struct bvcsrgb argb8888_bits[] = {
+ { BVRED(8, 8), BVGREEN(16, 8), BVBLUE(24, 8), BVALPHA(0, 8) },
+ { BVRED(0, 8), BVGREEN(8, 8), BVBLUE(16, 8), BVALPHA(24, 8) },
+ { BVRED(24, 8), BVGREEN(16, 8), BVBLUE(8, 8), BVALPHA(0, 8) },
+ { BVRED(16, 8), BVGREEN(8, 8), BVBLUE(0, 8), BVALPHA(24, 8) }
+};
+
+static const unsigned int container[] = {
+ 8, /* OCDFMTDEF_CONTAINER_8BIT */
+ 16, /* OCDFMTDEF_CONTAINER_16BIT */
+ 24, /* OCDFMTDEF_CONTAINER_24BIT */
+ 32, /* OCDFMTDEF_CONTAINER_32BIT */
+ ~0U, /* reserved */
+ 48, /* OCDFMTDEF_CONTAINER_48BIT */
+ ~0U, /* reserved */
+ 64 /* OCDFMTDEF_CONTAINER_64BIT */
+};
+
+enum bverror parse_format(struct bvbltparams *bvbltparams,
+ enum ocdformat ocdformat,
+ struct bvformatxlate *format)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gccontext *gccontext = get_context();
+ unsigned int cs, std, alpha, subsample, layout;
+ unsigned int reversed, leftjust, swizzle, cont, bits;
+
+ GCENTERARG(GCZONE_FORMAT, "ocdformat = 0x%08X\n", ocdformat);
+
+ cs = (ocdformat & OCDFMTDEF_CS_MASK)
+ >> OCDFMTDEF_CS_SHIFT;
+ std = (ocdformat & OCDFMTDEF_STD_MASK)
+ >> OCDFMTDEF_STD_SHIFT;
+ alpha = ocdformat & OCDFMTDEF_ALPHA;
+ subsample = (ocdformat & OCDFMTDEF_SUBSAMPLE_MASK)
+ >> OCDFMTDEF_SUBSAMPLE_SHIFT;
+ layout = (ocdformat & OCDFMTDEF_LAYOUT_MASK)
+ >> OCDFMTDEF_LAYOUT_SHIFT;
+ cont = (ocdformat & OCDFMTDEF_CONTAINER_MASK)
+ >> OCDFMTDEF_CONTAINER_SHIFT;
+ bits = ((ocdformat & OCDFMTDEF_COMPONENTSIZEMINUS1_MASK)
+ >> OCDFMTDEF_COMPONENTSIZEMINUS1_SHIFT) + 1;
+
+ GCDBG(GCZONE_FORMAT_VERBOSE, "std = %d\n", std);
+ GCDBG(GCZONE_FORMAT_VERBOSE, "cs = %d\n", cs);
+ GCDBG(GCZONE_FORMAT_VERBOSE, "alpha = %d\n", alpha ? 1 : 0);
+ GCDBG(GCZONE_FORMAT_VERBOSE, "subsample = %d\n", subsample);
+ GCDBG(GCZONE_FORMAT_VERBOSE, "layout = %d\n", layout);
+ GCDBG(GCZONE_FORMAT_VERBOSE, "cont = %d\n", cont);
+ GCDBG(GCZONE_FORMAT_VERBOSE, "bits = %d\n", bits);
+
+ format->endian
+ = GCREG_DEST_CONFIG_ENDIAN_CONTROL_NO_SWAP;
+
+ switch (cs) {
+ case (OCDFMTDEF_CS_RGB >> OCDFMTDEF_CS_SHIFT):
+ GCDBG(GCZONE_FORMAT, "OCDFMTDEF_CS_RGB\n");
+
+ /* Determine the swizzle. */
+ swizzle = (ocdformat & OCDFMTDEF_PLACEMENT_MASK)
+ >> OCDFMTDEF_PLACEMENT_SHIFT;
+ GCDBG(GCZONE_FORMAT, "swizzle = %d\n", swizzle);
+
+ /* RGB color space. */
+ format->type = BVFMT_RGB;
+
+ /* Has to be 0 for RGB. */
+ if (std != 0) {
+ BVSETBLTERROR(BVERR_UNK,
+ "unsupported standard");
+ goto exit;
+ }
+
+ /* Determine premultuplied or not. */
+ if (alpha == OCDFMTDEF_ALPHA) {
+ format->premultiplied
+ = ((ocdformat & OCDFMTDEF_NON_PREMULT) == 0);
+ format->zerofill = false;
+ } else {
+ format->premultiplied = true;
+ format->zerofill
+ = ((ocdformat & OCDFMTDEF_FILL_EMPTY_0) != 0);
+ }
+ GCDBG(GCZONE_FORMAT, "premultiplied = %d\n",
+ format->premultiplied);
+
+ /* No subsample support. */
+ if (subsample !=
+ (OCDFMTDEF_SUBSAMPLE_NONE >> OCDFMTDEF_SUBSAMPLE_SHIFT)) {
+ BVSETBLTERROR(BVERR_UNK,
+ "subsampling for RGB is not supported");
+ goto exit;
+ }
+
+ /* Only packed RGB is supported. */
+ if (layout !=
+ (OCDFMTDEF_PACKED >> OCDFMTDEF_LAYOUT_SHIFT)) {
+ BVSETBLTERROR(BVERR_UNK,
+ "only packed RGBA formats are supported");
+ goto exit;
+ }
+
+ /* Determine the format. */
+ switch (bits) {
+ case 12:
+ format->bitspp = 16;
+ format->allocbitspp = 16;
+ format->swizzle = rgba16swizzle[swizzle];
+
+ if (alpha == OCDFMTDEF_ALPHA) {
+ format->format = GCREG_DE_FORMAT_A4R4G4B4;
+ format->cs.rgb.comp = &argb4444_bits[swizzle];
+ } else {
+ format->format = gccontext->gccaps.swizzlefixed
+ ? GCREG_DE_FORMAT_X4R4G4B4
+ : GCREG_DE_FORMAT_A4R4G4B4;
+ format->cs.rgb.comp = &xrgb4444_bits[swizzle];
+ }
+ break;
+
+ case 15:
+ format->bitspp = 16;
+ format->allocbitspp = 16;
+ format->swizzle = rgba16swizzle[swizzle];
+
+ if (alpha == OCDFMTDEF_ALPHA) {
+ format->format = GCREG_DE_FORMAT_A1R5G5B5;
+ format->cs.rgb.comp = &argb1555_bits[swizzle];
+ } else {
+ format->format = GCREG_DE_FORMAT_X1R5G5B5;
+ format->cs.rgb.comp = &xrgb1555_bits[swizzle];
+ }
+ break;
+
+ case 16:
+ if (alpha == OCDFMTDEF_ALPHA) {
+ BVSETBLTERROR(BVERR_UNK,
+ "alpha component is not supported"
+ "for this format.");
+ goto exit;
+ }
+
+ format->bitspp = 16;
+ format->allocbitspp = 16;
+ format->swizzle = rgb16swizzle[swizzle];
+ format->format = GCREG_DE_FORMAT_R5G6B5;
+ format->cs.rgb.comp = &rgb565_bits[swizzle];
+ break;
+
+ case 24:
+ format->bitspp = 32;
+ format->allocbitspp = 32;
+ format->swizzle = rgba32swizzle[swizzle];
+
+ if (alpha == OCDFMTDEF_ALPHA) {
+ format->format = GCREG_DE_FORMAT_A8R8G8B8;
+ format->cs.rgb.comp = &argb8888_bits[swizzle];
+ } else {
+ format->format = GCREG_DE_FORMAT_X8R8G8B8;
+ format->cs.rgb.comp = &xrgb8888_bits[swizzle];
+ }
+
+ format->endian = ((swizzle & 1) == 0)
+ ? GCREG_DEST_CONFIG_ENDIAN_CONTROL_SWAP_DWORD
+ : GCREG_DEST_CONFIG_ENDIAN_CONTROL_NO_SWAP;
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_UNK,
+ "unsupported bit width %d", bits);
+ goto exit;
+ }
+
+ if (format->allocbitspp != container[cont]) {
+ BVSETBLTERROR(BVERR_UNK,
+ "unsupported container");
+ goto exit;
+ }
+ break;
+
+ case (OCDFMTDEF_CS_YCbCr >> OCDFMTDEF_CS_SHIFT):
+ GCDBG(GCZONE_FORMAT, "OCDFMTDEF_CS_YCbCr\n");
+
+ /* YUV color space. */
+ format->type = BVFMT_YUV;
+
+ /* Determine the swizzle. */
+ reversed = ocdformat & OCDFMTDEF_REVERSED;
+ leftjust = ocdformat & OCDFMTDEF_LEFT_JUSTIFIED;
+ GCDBG(GCZONE_FORMAT_VERBOSE, "reversed = %d\n",
+ reversed ? 1 : 0);
+ GCDBG(GCZONE_FORMAT_VERBOSE, "leftjust = %d\n",
+ leftjust ? 1 : 0);
+
+ /* Parse the standard. */
+ switch (std) {
+ case OCDFMTDEF_STD_ITUR_601_YCbCr >> OCDFMTDEF_STD_SHIFT:
+ GCDBG(GCZONE_FORMAT, "OCDFMTDEF_STD_ITUR_601_YCbCr\n");
+ format->cs.yuv.std = GCREG_PE_CONTROL_YUV_601;
+ break;
+
+ case OCDFMTDEF_STD_ITUR_709_YCbCr >> OCDFMTDEF_STD_SHIFT:
+ GCDBG(GCZONE_FORMAT, "OCDFMTDEF_STD_ITUR_709_YCbCr\n");
+ format->cs.yuv.std = GCREG_PE_CONTROL_YUV_709;
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_UNK,
+ "unsupported color standard");
+ goto exit;
+ }
+
+ /* Alpha is not supported. */
+ if (alpha == OCDFMTDEF_ALPHA) {
+ BVSETBLTERROR(BVERR_UNK,
+ "alpha channel is not supported");
+ goto exit;
+ }
+
+ format->premultiplied = true;
+ format->zerofill = false;
+
+ /* Parse subsampling. */
+ switch (subsample) {
+ case OCDFMTDEF_SUBSAMPLE_422_YCbCr >> OCDFMTDEF_SUBSAMPLE_SHIFT:
+ GCDBG(GCZONE_FORMAT, "OCDFMTDEF_SUBSAMPLE_422_YCbCr\n");
+
+ /* Parse layout. */
+ switch (layout) {
+ case OCDFMTDEF_PACKED >> OCDFMTDEF_LAYOUT_SHIFT:
+ GCDBG(GCZONE_FORMAT, "OCDFMTDEF_PACKED\n");
+
+ if (container[cont] != 32) {
+ BVSETBLTERROR(BVERR_UNK,
+ "unsupported container");
+ goto exit;
+ }
+
+ format->bitspp = 16;
+ format->allocbitspp = 16;
+ format->format = leftjust
+ ? GCREG_DE_FORMAT_YUY2
+ : GCREG_DE_FORMAT_UYVY;
+ format->swizzle = reversed
+ ? GCREG_PE_CONTROL_UV_SWIZZLE_VU
+ : GCREG_PE_CONTROL_UV_SWIZZLE_UV;
+ format->cs.yuv.planecount = 1;
+ format->cs.yuv.xsample = 2;
+ format->cs.yuv.ysample = 1;
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_UNK,
+ "specified 4:2:2 layout "
+ "is not supported");
+ goto exit;
+ }
+ break;
+
+ case OCDFMTDEF_SUBSAMPLE_420_YCbCr >> OCDFMTDEF_SUBSAMPLE_SHIFT:
+
+ /* Parse layout. */
+ switch (layout) {
+ case OCDFMTDEF_2_PLANE_YCbCr
+ >> OCDFMTDEF_LAYOUT_SHIFT:
+ GCDBG(GCZONE_FORMAT,
+ "OCDFMTDEF_2_PLANE_YCbCr\n");
+
+ if (container[cont] != 48) {
+ BVSETBLTERROR(BVERR_UNK,
+ "unsupported container");
+ goto exit;
+ }
+
+ format->bitspp = 8;
+ format->allocbitspp = 12;
+ format->format = GCREG_DE_FORMAT_NV12;
+ format->swizzle = reversed
+ ? GCREG_PE_CONTROL_UV_SWIZZLE_VU
+ : GCREG_PE_CONTROL_UV_SWIZZLE_UV;
+ format->cs.yuv.planecount = 2;
+ format->cs.yuv.xsample = 2;
+ format->cs.yuv.ysample = 2;
+ break;
+
+ case OCDFMTDEF_3_PLANE_STACKED
+ >> OCDFMTDEF_LAYOUT_SHIFT:
+ GCDBG(GCZONE_FORMAT,
+ "OCDFMTDEF_3_PLANE_STACKED\n");
+
+ if (container[cont] != 48) {
+ BVSETBLTERROR(BVERR_UNK,
+ "unsupported container");
+ goto exit;
+ }
+
+ format->bitspp = 8;
+ format->allocbitspp = 12;
+ format->format = GCREG_DE_FORMAT_YV12;
+ format->swizzle = reversed
+ ? GCREG_PE_CONTROL_UV_SWIZZLE_VU
+ : GCREG_PE_CONTROL_UV_SWIZZLE_UV;
+ format->cs.yuv.planecount = 3;
+ format->cs.yuv.xsample = 2;
+ format->cs.yuv.ysample = 2;
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_UNK,
+ "specified 4:2:2 layout "
+ "is not supported");
+ goto exit;
+ }
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_UNK,
+ "specified subsampling is not supported");
+ goto exit;
+ }
+
+ if (format->allocbitspp != bits) {
+ BVSETBLTERROR(BVERR_UNK,
+ "unsupported bit width %d", bits);
+ goto exit;
+ }
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_UNK,
+ "unsupported color space %d", cs);
+ goto exit;
+ }
+
+ GCDBG(GCZONE_FORMAT, "bpp = %d\n", format->bitspp);
+ GCDBG(GCZONE_FORMAT, "gcformat = %d\n", format->format);
+ GCDBG(GCZONE_FORMAT, "gcswizzle = %d\n", format->swizzle);
+
+ bverror = BVERR_NONE;
+
+exit:
+ GCEXITARG(GCZONE_FORMAT, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+
+/*******************************************************************************
+ * Alpha blending parser.
+ */
+
+#define BVBLENDMATCH(Mode, Inverse, Normal) \
+( \
+ BVBLENDDEF_ ## Mode | \
+ BVBLENDDEF_ ## Inverse | \
+ BVBLENDDEF_ ## Normal \
+)
+
+#define BVSRC1USE(Use) \
+ Use
+
+#define BVSRC2USE(Use) \
+ Use
+
+#define BVBLENDUNDEFINED() \
+ { ~0, ~0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }
+
+struct bvblendxlate {
+ unsigned char match1;
+ unsigned char match2;
+
+ struct gcblendconfig k1;
+ struct gcblendconfig k2;
+};
+
+static struct bvblendxlate blendxlate[64] = {
+ /**********************************************************************/
+ /* #0: color factor: 00 00 00 A:(1-C1,C1)=zero
+ alpha factor: zero ==> 00 00 00 */
+ {
+ 0x00,
+ 0x00,
+
+ {
+ GCREG_BLENDING_MODE_ZERO,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(false), BVSRC2USE(false)
+ },
+
+ {
+ GCREG_BLENDING_MODE_ZERO,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(false), BVSRC2USE(false)
+ }
+ },
+
+ /* #1: color factor: 00 00 01 A:(1-C1,A1)=A1
+ alpha factor: A1 ==> 00 00 01 or 00 10 01 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1),
+ BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1),
+
+ {
+ GCREG_BLENDING_MODE_NORMAL,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(true), BVSRC2USE(false)
+ },
+
+ {
+ GCREG_BLENDING_MODE_NORMAL,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ }
+ },
+
+ /* #2: color factor: 00 00 10 A:(1-C1,C2)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #3: color factor: 00 00 11 A:(1-C1,A2)=A2
+ alpha factor: A2 ==> 00 00 11 or 00 10 11 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2),
+ BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2),
+
+ {
+ GCREG_BLENDING_MODE_NORMAL,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ },
+
+ {
+ GCREG_BLENDING_MODE_NORMAL,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(false), BVSRC2USE(true)
+ }
+ },
+
+ /* #4: color factor: 00 01 00 A:(1-A1,C1)=1-A1
+ alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1),
+ BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2),
+
+ {
+ GCREG_BLENDING_MODE_INVERSED,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(true), BVSRC2USE(false)
+ },
+
+ {
+ GCREG_BLENDING_MODE_INVERSED,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ }
+ },
+
+ /* #5: color factor: 00 01 01 A:(1-A1,A1)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #6: color factor: 00 01 10 A:(1-A1,C2)=1-A1
+ alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1),
+ BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2),
+
+ {
+ GCREG_BLENDING_MODE_INVERSED,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(true), BVSRC2USE(false)
+ },
+
+ {
+ GCREG_BLENDING_MODE_INVERSED,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ }
+ },
+
+ /* #7: color factor: 00 01 11 A:(1-A1,A2)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #8: color factor: 00 10 00 A:(1-C2,C1)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #9: color factor: 00 10 01 A:(1-C2,A1)=A1
+ alpha factor: A1 ==> 00 00 01 or 00 10 01 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1),
+ BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1),
+
+ {
+ GCREG_BLENDING_MODE_NORMAL,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(true), BVSRC2USE(false)
+ },
+
+ {
+ GCREG_BLENDING_MODE_NORMAL,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ }
+ },
+
+ /* #10: color factor: 00 10 10 A:(1-C2,C2)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #11: color factor: 00 10 11 A:(1-C2,A2)=A2
+ alpha factor: A2 ==> 00 00 11 or 00 10 11 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2),
+ BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2),
+
+ {
+ GCREG_BLENDING_MODE_NORMAL,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ },
+
+ {
+ GCREG_BLENDING_MODE_NORMAL,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(false), BVSRC2USE(true)
+ }
+ },
+
+ /* #12: color factor: 00 11 00 A:(1-A2,C1)=1-A2
+ alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1),
+ BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2),
+
+ {
+ GCREG_BLENDING_MODE_INVERSED,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ },
+
+ {
+ GCREG_BLENDING_MODE_INVERSED,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(false), BVSRC2USE(true)
+ }
+ },
+
+ /* #13: color factor: 00 11 01 A:(1-A2,A1)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #14: color factor: 00 11 10 A:(1-A2,C2)=1-A2
+ alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1),
+ BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2),
+
+ {
+ GCREG_BLENDING_MODE_INVERSED,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ },
+
+ {
+ GCREG_BLENDING_MODE_INVERSED,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(false), BVSRC2USE(true)
+ }
+ },
+
+ /* #15: color factor: 00 11 11 A:(1-A2,A2)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /**********************************************************************/
+ /* #16: color factor: 01 00 00 MIN:(1-C1,C1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #17: color factor: 01 00 01 MIN:(1-C1,A1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #18: color factor: 01 00 10 MIN:(1-C1,C2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #19: color factor: 01 00 11 MIN:(1-C1,A2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #20: color factor: 01 01 00 MIN:(1-A1,C1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #21: color factor: 01 01 01 MIN:(1-A1,A1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #22: color factor: 01 01 10 MIN:(1-A1,C2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #23: color factor: 01 01 11 MIN:(1-A1,A2)
+ alpha factor: one ==> 11 11 11 */
+ {
+ 0x3F,
+ 0x3F,
+
+ {
+ GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ },
+
+ {
+ GCREG_BLENDING_MODE_SATURATED_ALPHA,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ }
+ },
+
+ /* #24: color factor: 01 10 00 MIN:(1-C2,C1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #25: color factor: 01 10 01 MIN:(1-C2,A1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #26: color factor: 01 10 10 MIN:(1-C2,C2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #27: color factor: 01 10 11 MIN:(1-C2,A2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #28: color factor: 01 11 00 MIN:(1-A2,C1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #29: color factor: 01 11 01 MIN:(1-A2,A1)
+ alpha factor: one ==> 11 11 11 */
+ {
+ 0x3F,
+ 0x3F,
+
+ {
+ GCREG_BLENDING_MODE_SATURATED_ALPHA,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ },
+
+ {
+ GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ }
+ },
+
+ /* #30: color factor: 01 11 10 MIN:(1-A2,C2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #31: color factor: 01 11 11 MIN:(1-A2,A2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /**********************************************************************/
+ /* #32: color factor: 10 00 00 MAX:(1-C1,C1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #33: color factor: 10 00 01 MAX:(1-C1,A1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #34: color factor: 10 00 10 MAX:(1-C1,C2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #35: color factor: 10 00 11 MAX:(1-C1,A2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #36: color factor: 10 01 00 MAX:(1-A1,C1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #37: color factor: 10 01 01 MAX:(1-A1,A1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #38: color factor: 10 01 10 MAX:(1-A1,C2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #39: color factor: 10 01 11 MAX:(1-A1,A2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #40: color factor: 10 10 00 MAX:(1-C2,C1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #41: color factor: 10 10 01 MAX:(1-C2,A1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #42: color factor: 10 10 10 MAX:(1-C2,C2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #43: color factor: 10 10 11 MAX:(1-C2,A2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #44: color factor: 10 11 00 MAX:(1-A2,C1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #45: color factor: 10 11 01 MAX:(1-A2,A1) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #46: color factor: 10 11 10 MAX:(1-A2,C2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #47: color factor: 10 11 11 MAX:(1-A2,A2) ==> not supported
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /**********************************************************************/
+ /* #48: color factor: 11 00 00 C:(1-C1,C1)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #49: color factor: 11 00 01 C:(1-C1,A1)=1-C1
+ alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1),
+ BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2),
+
+ {
+ GCREG_BLENDING_MODE_COLOR_INVERSED,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(true), BVSRC2USE(false)
+ },
+
+ {
+ GCREG_BLENDING_MODE_COLOR_INVERSED,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ }
+ },
+
+ /* #50: color factor: 11 00 10 C:(1-C1,C2)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #51: color factor: 11 00 11 C:(1-C1,A2)=1-C1
+ alpha factor: 1-A1 ==> 00 01 00 or 00 01 10 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_A1, NORM_C1),
+ BVBLENDMATCH(ONLY_A, INV_A1, NORM_C2),
+
+ {
+ GCREG_BLENDING_MODE_COLOR_INVERSED,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(true), BVSRC2USE(false)
+ },
+
+ {
+ GCREG_BLENDING_MODE_COLOR_INVERSED,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ }
+ },
+
+ /* #52: color factor: 11 01 00 C:(1-A1,C1)=C1
+ alpha factor: A1 ==> 00 00 01 or 00 10 01 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1),
+ BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1),
+
+ {
+ GCREG_BLENDING_MODE_COLOR,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(true), BVSRC2USE(false)
+ },
+
+ {
+ GCREG_BLENDING_MODE_COLOR,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ }
+ },
+
+ /* #53: color factor: 11 01 01 C:(1-A1,A1)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #54: color factor: 11 01 10 C:(1-A1,C2)=C2
+ alpha factor: A2 ==> 00 00 11 or 00 10 11 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2),
+ BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2),
+
+ {
+ GCREG_BLENDING_MODE_COLOR,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ },
+
+ {
+ GCREG_BLENDING_MODE_COLOR,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(false), BVSRC2USE(true)
+ }
+ },
+
+ /* #55: color factor: 11 01 11 C:(1-A1,A2)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #56: color factor: 11 10 00 C:(1-C2,C1)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #57: color factor: 11 10 01 C:(1-C2,A1)=1-C2
+ alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1),
+ BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2),
+
+ {
+ GCREG_BLENDING_MODE_COLOR_INVERSED,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ },
+
+ {
+ GCREG_BLENDING_MODE_COLOR_INVERSED,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(false), BVSRC2USE(true)
+ }
+ },
+
+ /* #58: color factor: 11 10 10 C:(1-C2,C2)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #59: color factor: 11 10 11 C:(1-C2,A2)=1-C2
+ alpha factor: 1-A2 ==> 00 11 00 or 00 11 10 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_A2, NORM_C1),
+ BVBLENDMATCH(ONLY_A, INV_A2, NORM_C2),
+
+ {
+ GCREG_BLENDING_MODE_COLOR_INVERSED,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ },
+
+ {
+ GCREG_BLENDING_MODE_COLOR_INVERSED,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(false), BVSRC2USE(false)
+ }
+ },
+
+ /* #60: color factor: 11 11 00 C:(1-A2,C1)=C1
+ alpha factor: A1 ==> 00 00 01 or 00 10 01 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_C1, NORM_A1),
+ BVBLENDMATCH(ONLY_A, INV_C2, NORM_A1),
+
+ {
+ GCREG_BLENDING_MODE_COLOR,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(true), BVSRC2USE(false)
+ },
+
+ {
+ GCREG_BLENDING_MODE_COLOR,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ }
+ },
+
+ /* #61: color factor: 11 11 01 C:(1-A2,A1)=undefined
+ alpha factor: N/A */
+ BVBLENDUNDEFINED(),
+
+ /* #62: color factor: 11 11 10 C:(1-A2,C2)=C2
+ alpha factor: A2 ==> 00 00 11 or 00 10 11 */
+ {
+ BVBLENDMATCH(ONLY_A, INV_C1, NORM_A2),
+ BVBLENDMATCH(ONLY_A, INV_C2, NORM_A2),
+
+ {
+ GCREG_BLENDING_MODE_COLOR,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(true)
+ },
+
+ {
+ GCREG_BLENDING_MODE_COLOR,
+ GCREG_FACTOR_INVERSE_ENABLE,
+ BVSRC1USE(false), BVSRC2USE(true)
+ }
+ },
+
+ /* #63: color factor: 11 11 11 C:(1-A2,A2)=one
+ alpha factor: one ==> 11 11 11 */
+ {
+ 0x3F,
+ 0x3F,
+
+ {
+ GCREG_BLENDING_MODE_ONE,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(true), BVSRC2USE(false)
+ },
+
+ {
+ GCREG_BLENDING_MODE_ONE,
+ GCREG_FACTOR_INVERSE_DISABLE,
+ BVSRC1USE(false), BVSRC2USE(true)
+ }
+ }
+};
+
+enum bverror parse_blend(struct bvbltparams *bvbltparams,
+ enum bvblend blend,
+ struct gcalpha *gca)
+{
+ enum bverror bverror;
+ unsigned int global;
+ unsigned int k1, k2, k3, k4;
+ struct bvblendxlate *k1_xlate;
+ struct bvblendxlate *k2_xlate;
+ unsigned int alpha;
+
+ GCENTER(GCZONE_BLEND);
+
+ if ((blend & BVBLENDDEF_REMOTE) != 0) {
+ BVSETBLTERROR(BVERR_BLEND, "remote alpha not supported");
+ goto exit;
+ }
+
+ global = (blend & BVBLENDDEF_GLOBAL_MASK) >> BVBLENDDEF_GLOBAL_SHIFT;
+
+ switch (global) {
+ case (BVBLENDDEF_GLOBAL_NONE >> BVBLENDDEF_GLOBAL_SHIFT):
+ GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_NONE\n");
+
+ gca->globalcolor = 0;
+ gca->globalcolorenable = false;
+ break;
+
+ case (BVBLENDDEF_GLOBAL_UCHAR >> BVBLENDDEF_GLOBAL_SHIFT):
+ GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_UCHAR (0x%02X)\n",
+ bvbltparams->globalalpha.size8);
+
+ gca->globalcolor
+ = ((unsigned int) bvbltparams->globalalpha.size8) << 24;
+ gca->globalcolorenable = true;
+ break;
+
+ case (BVBLENDDEF_GLOBAL_FLOAT >> BVBLENDDEF_GLOBAL_SHIFT):
+ GCDBG(GCZONE_BLEND, "BVBLENDDEF_GLOBAL_FLOAT (0x%08X)\n",
+ *(unsigned int *) &bvbltparams->globalalpha.fp);
+
+ alpha = gcfp2norm8(bvbltparams->globalalpha.fp);
+ GCDBG(GCZONE_BLEND, "converted alpha = 0x%02X\n", alpha);
+
+ gca->globalcolor = alpha << 24;
+ gca->globalcolorenable = true;
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_BLEND, "invalid global alpha mode");
+ goto exit;
+ }
+
+ /*
+ Co = k1 x C1 + k2 x C2
+ Ao = k3 x A1 + k4 x A2
+ */
+
+ k1 = (blend >> 18) & 0x3F;
+ k2 = (blend >> 12) & 0x3F;
+ k3 = (blend >> 6) & 0x3F;
+ k4 = blend & 0x3F;
+
+ GCDBG(GCZONE_BLEND, "k1 = %d\n", k1);
+ GCDBG(GCZONE_BLEND, "k2 = %d\n", k2);
+ GCDBG(GCZONE_BLEND, "k3 = %d\n", k3);
+ GCDBG(GCZONE_BLEND, "k4 = %d\n", k4);
+
+ k1_xlate = &blendxlate[k1];
+ k2_xlate = &blendxlate[k2];
+
+ if (((k3 != k1_xlate->match1) && (k3 != k1_xlate->match2)) ||
+ ((k4 != k2_xlate->match1) && (k4 != k2_xlate->match2))) {
+ BVSETBLTERROR(BVERR_BLEND,
+ "not supported coefficient combination");
+ goto exit;
+ }
+
+ gca->k1 = &k1_xlate->k1;
+ gca->k2 = &k2_xlate->k2;
+
+ gca->src1used = gca->k1->src1used | gca->k2->src1used;
+ gca->src2used = gca->k1->src2used | gca->k2->src2used;
+
+ bverror = BVERR_NONE;
+
+exit:
+ GCEXITARG(BVERR_BLEND, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+
+/*******************************************************************************
+ * Rotation and mirror.
+ */
+
+#define BVFLAG_FLIP_MASK 0x00000003
+
+#define BVFLAG_FLIP_SRC1_SHIFT 14
+#define BVFLAG_FLIP_SRC2_SHIFT 16
+#define BVFLAG_FLIP_MASK_SHIFT 18
+
+#define GCREG_MIRROR_NONE 0x0
+#define GCREG_MIRROR_X 0x1
+#define GCREG_MIRROR_Y 0x2
+#define GCREG_MIRROR_XY 0x3
+
+#define GCREG_ROT_ANGLE_ROT0 0x0
+#define GCREG_ROT_ANGLE_ROT90 0x4
+#define GCREG_ROT_ANGLE_ROT180 0x5
+#define GCREG_ROT_ANGLE_ROT270 0x6
+
+#define ROT_ANGLE_INVALID -1
+#define ROT_ANGLE_0 0
+#define ROT_ANGLE_90 1
+#define ROT_ANGLE_180 2
+#define ROT_ANGLE_270 3
+
+/* NOTE: BLTsville rotation is defined conunter clock wise. */
+const unsigned int rotencoding[] = {
+ GCREG_ROT_ANGLE_ROT0, /* ROT_ANGLE_0 */
+ GCREG_ROT_ANGLE_ROT270, /* ROT_ANGLE_90 */
+ GCREG_ROT_ANGLE_ROT180, /* ROT_ANGLE_180 */
+ GCREG_ROT_ANGLE_ROT90 /* ROT_ANGLE_270 */
+};
+
+static inline int get_angle(int orientation)
+{
+ int angle;
+
+ /* Normalize the angle. */
+ angle = orientation % 360;
+
+ /* Flip to positive. */
+ if (angle < 0)
+ angle = 360 + angle;
+
+ /* Translate the angle. */
+ switch (angle) {
+ case 0: return ROT_ANGLE_0;
+ case 90: return ROT_ANGLE_90;
+ case 180: return ROT_ANGLE_180;
+ case 270: return ROT_ANGLE_270;
+ }
+
+ /* Not supported angle. */
+ return ROT_ANGLE_INVALID;
+}
+
+
+/*******************************************************************************
+ * Surface compare and validation.
+ */
+
+bool null_rect(struct gcrect *gcrect)
+{
+ return (gcrect->left == gcrect->right) &&
+ (gcrect->top == gcrect->bottom);
+}
+
+bool valid_rect(struct gcsurface *gcsurface, struct gcrect *gcrect)
+{
+ int width, height;
+
+ if ((gcrect->left < 0) || (gcrect->top < 0)) {
+ GCERR("invalid rectangle origin: %d,%d.\n",
+ gcrect->left, gcrect->top);
+ return false;
+ }
+
+ width = gcrect->right - gcrect->left;
+ height = gcrect->bottom - gcrect->top;
+ if ((width < 0) || (height < 0)) {
+ GCERR("invalid rectangle size: %d,%d.\n",
+ width, height);
+ return false;
+ }
+
+ if (gcrect->right > (int) gcsurface->width) {
+ GCERR("right coordinate (%d) exceeds surface width (%d).\n",
+ gcrect->right, gcsurface->width);
+ return false;
+ }
+
+ if (gcrect->bottom > (int) gcsurface->height) {
+ GCERR("bottom coordinate (%d) exceeds surface height (%d).\n",
+ gcrect->bottom, gcsurface->height);
+ return false;
+ }
+
+ return true;
+}
+
+static bool valid_geom(struct gcsurface *gcsurface)
+{
+ unsigned int size;
+ unsigned int height;
+
+ /* Compute the size of the surface. */
+ size = (gcsurface->width * gcsurface->height *
+ gcsurface->format.allocbitspp) / 8;
+
+ /* Make sure the size is not greater then the surface. */
+ if (size > gcsurface->buf.desc->length) {
+ GCERR("invalid geometry detected:\n");
+ GCERR(" specified dimensions: %dx%d, %d bitspp\n",
+ gcsurface->width,
+ gcsurface->height,
+ gcsurface->format.bitspp);
+ GCERR(" surface size based on the dimensions: %d\n",
+ size);
+ GCERR(" specified surface size: %lu\n",
+ gcsurface->buf.desc->length);
+ return false;
+ }
+
+ /* Determine the height of the image. */
+ height = ((gcsurface->angle % 2) == 0)
+ ? gcsurface->height
+ : gcsurface->width;
+
+ /* Compute the size using the stide. */
+ size = gcsurface->stride1 * height;
+
+ /* Make sure the size is not greater then the surface. */
+ if (size > gcsurface->buf.desc->length) {
+ GCERR("invalid geometry detected:\n");
+ GCERR(" specified dimensions: %dx%d, %d bitspp\n",
+ gcsurface->width,
+ gcsurface->height,
+ gcsurface->format.bitspp);
+ GCERR(" physical image height = %d\n", height);
+ GCERR(" image stride = %d\n", gcsurface->stride1);
+ GCERR(" computed surface size = %d\n", size);
+ GCERR(" specified surface size: %lu\n",
+ gcsurface->buf.desc->length);
+ return false;
+ }
+
+ return true;
+}
+
+enum bverror valid_stride(struct bvbltparams *bvbltparams,
+ struct gcsurface *gcsurface)
+{
+ enum bverror bverror;
+ struct gccontext *gccontext = get_context();
+ struct bvformatxlate *format = &gcsurface->format;
+ bool srcsurface;
+ unsigned int alignment;
+
+ /* Is this the source? */
+ srcsurface = (gcsurface->index >= 0);
+
+ if (gccontext->gccaps.strictalign) {
+ if (format->type == BVFMT_YUV) {
+ if (srcsurface) {
+ alignment = (format->cs.yuv.planecount == 1)
+ ? 16 - 1
+ : 8 - 1;
+ } else {
+ alignment = ~0U;
+ }
+ } else {
+ alignment = 16 - 1;
+ }
+ } else {
+ if (format->type == BVFMT_YUV) {
+ if (format->cs.yuv.planecount == 1) {
+ alignment = 4 - 1;
+ } else {
+ alignment = (srcsurface)
+ ? 8 - 1
+ : ~0U;
+ }
+ } else {
+ alignment = (format->bitspp / 8) - 1;
+ }
+ }
+
+ if (alignment == ~0U) {
+ if (srcsurface) {
+ BVSETBLTERROR((gcsurface->index == 0)
+ ? BVERR_SRC1GEOM_FORMAT
+ : BVERR_SRC2GEOM_FORMAT,
+ "source %d format unsupported",
+ gcsurface->index);
+ } else {
+ BVSETBLTERROR(BVERR_DSTGEOM_FORMAT,
+ "destination format unsupported");
+ }
+
+ return bverror;
+ }
+
+ if ((gcsurface->stride1 & alignment) != 0) {
+ if (srcsurface) {
+ BVSETBLTERROR((gcsurface->index == 0)
+ ? BVERR_SRC1GEOM_STRIDE
+ : BVERR_SRC2GEOM_STRIDE,
+ "source %d stride must be "
+ "%d pixel aligned.",
+ gcsurface->index,
+ alignment + 1);
+ } else {
+ BVSETBLTERROR(BVERR_DSTGEOM_FORMAT,
+ "destination format unsupported");
+ }
+
+ return bverror;
+ }
+
+ return BVERR_NONE;
+}
+
+int get_pixel_offset(struct gcsurface *gcsurface, int offset)
+{
+ struct gccontext *gccontext = get_context();
+ unsigned int alignment;
+ int byteoffset;
+ unsigned int alignedoffset;
+ int pixeloffset;
+
+ GCENTERARG(GCZONE_OFFSET, "gcsurface=0x%08X, offset=%d\n",
+ gcsurface, offset);
+
+ if (gccontext->gccaps.strictalign) {
+ if ((gcsurface->format.type == BVFMT_YUV) &&
+ (gcsurface->format.cs.yuv.planecount > 1))
+ alignment = 64 - 1;
+ else
+ alignment = 16 - 1;
+ } else {
+ if (gcsurface->format.type == BVFMT_YUV) {
+ if (gcsurface->format.cs.yuv.planecount == 1)
+ alignment = 4 - 1;
+ else
+ alignment = 64 - 1;
+ } else {
+ alignment = (gcsurface->format.bitspp / 8) - 1;
+ }
+ }
+
+ GCDBG(GCZONE_OFFSET, "bpp = %d\n", gcsurface->format.bitspp);
+ GCDBG(GCZONE_OFFSET, "alignment = %d\n", alignment);
+
+ /* Determine offset in bytes from the base modified by the
+ * given offset. */
+ if (gcsurface->buf.desc->auxtype == BVAT_PHYSDESC) {
+ struct bvphysdesc *bvphysdesc;
+ bvphysdesc = (struct bvphysdesc *)
+ gcsurface->buf.desc->auxptr;
+ GCDBG(GCZONE_OFFSET, "physical descriptor = 0x%08X\n",
+ bvphysdesc);
+ GCDBG(GCZONE_OFFSET, "first page = 0x%08X\n",
+ bvphysdesc->pagearray[0]);
+ GCDBG(GCZONE_OFFSET, "page offset = 0x%08X\n",
+ bvphysdesc->pageoffset);
+
+ byteoffset = bvphysdesc->pageoffset + offset;
+ } else {
+ GCDBG(GCZONE_OFFSET, "no physical descriptor.\n");
+ byteoffset = (unsigned int)
+ gcsurface->buf.desc->virtaddr + offset;
+ }
+
+ GCDBG(GCZONE_OFFSET, "byteoffset = %d\n", byteoffset);
+
+ /* Compute the aligned offset. */
+ alignedoffset = byteoffset & alignment;
+
+ /* Convert to pixels. */
+ pixeloffset = alignedoffset * 8 / gcsurface->format.bitspp;
+
+ GCDBG(GCZONE_OFFSET, "alignedoffset = %d\n", alignedoffset);
+ GCDBG(GCZONE_OFFSET, "pixeloffset = %d\n", -pixeloffset);
+
+ GCEXIT(GCZONE_OFFSET);
+ return -pixeloffset;
+}
+
+void rotate_rect(int angle,
+ struct gcsurface *gcsurface, struct gcrect *rect)
+{
+ unsigned int width, height;
+ struct gcrect temprect;
+
+ GCENTER(GCZONE_SURF);
+
+ GCDBG(GCZONE_SURF, "adjustment angle = %d\n",
+ angle);
+ GCDBG(GCZONE_SURF, "geom size = %dx%d\n",
+ gcsurface->width, gcsurface->height);
+
+ switch (angle) {
+ case ROT_ANGLE_0:
+ break;
+
+ case ROT_ANGLE_90:
+ width = gcsurface->width;
+ height = gcsurface->height;
+
+ temprect.left = height - rect->bottom;
+ temprect.top = rect->left;
+ temprect.right = height - rect->top;
+ temprect.bottom = rect->right;
+
+ *rect = temprect;
+ break;
+
+ case ROT_ANGLE_180:
+ width = gcsurface->width;
+ height = gcsurface->height;
+
+ temprect.left = width - rect->right;
+ temprect.top = height - rect->bottom;
+ temprect.right = width - rect->left;
+ temprect.bottom = height - rect->top;
+
+ *rect = temprect;
+ break;
+
+ case ROT_ANGLE_270:
+ width = gcsurface->width;
+ height = gcsurface->height;
+
+ temprect.left = rect->top;
+ temprect.top = width - rect->right;
+ temprect.right = rect->bottom;
+ temprect.bottom = width - rect->left;
+
+ *rect = temprect;
+ break;
+ }
+
+ GCEXIT(GCZONE_SURF);
+}
+
+void rotate_geom(int angle, struct gcsurface *gcsurface)
+{
+ GCENTER(GCZONE_SURF);
+
+ GCDBG(GCZONE_SURF, "adjustment angle = %d\n",
+ angle);
+ GCDBG(GCZONE_SURF, "geom angle = %d\n",
+ gcsurface->angle);
+ GCDBG(GCZONE_SURF, "geom size = %dx%d\n",
+ gcsurface->width, gcsurface->height);
+
+ if ((angle % 2) != 0) {
+ unsigned int width, height;
+
+ width = gcsurface->width;
+ height = gcsurface->height;
+
+ gcsurface->width = height;
+ gcsurface->height = width;
+ }
+
+ gcsurface->angle = (gcsurface->angle + angle) % 4;
+ GCDBG(GCZONE_SURF, "new geom angle = %d\n",
+ gcsurface->angle);
+ GCDBG(GCZONE_SURF, "new geom size = %dx%d\n",
+ gcsurface->width, gcsurface->height);
+
+ GCEXIT(GCZONE_SURF);
+}
+
+void adjust_angle(struct gcsurface *srcinfo, struct gcsurface *dstinfo)
+{
+ int srcangle, dstangle;
+ struct gcrect *srcorig;
+ struct gcrect *dstorig, *dstclip, *dstadj;
+ struct gcrect *dstorigaux, *dstclipaux, *dstadjaux;
+
+ GCENTER(GCZONE_SURF);
+
+ /* Determine adjustment angles. */
+ srcangle = srcinfo->adjangle;
+ dstangle = (4 - (dstinfo->adjangle - srcangle)) % 4;
+
+ GCDBG(GCZONE_SURF, "source adjustment = %d deg.\n", srcangle * 90);
+ GCDBG(GCZONE_SURF, "destination adjusment = %d deg.\n", dstangle * 90);
+
+ /* Adjust the source. */
+ if (srcangle != 0) {
+ srcorig = &srcinfo->rect.orig;
+
+ rotate_rect(srcangle, srcinfo, srcorig);
+ rotate_geom(srcangle, srcinfo);
+
+ GCPRINT_RECT(GCZONE_SURF, "original src (rot)", srcorig);
+ }
+
+ /* Adjust the destination. */
+ if (dstangle != 0) {
+ dstorig = &dstinfo->rect.orig;
+ dstclip = &dstinfo->rect.clip;
+ dstadj = &dstinfo->rect.adj;
+
+ rotate_rect(dstangle, dstinfo, dstorig);
+ rotate_rect(dstangle, dstinfo, dstclip);
+ rotate_rect(dstangle, dstinfo, dstadj);
+
+ GCPRINT_RECT(GCZONE_SURF, "original dst (rot)", dstorig);
+ GCPRINT_RECT(GCZONE_SURF, "clipped dst (rot)", dstclip);
+ GCPRINT_RECT(GCZONE_SURF, "adjusted dst (rot)", dstadj);
+
+ if (dstinfo->haveaux) {
+ dstorigaux = &dstinfo->auxrect.orig;
+ dstclipaux = &dstinfo->auxrect.clip;
+ dstadjaux = &dstinfo->auxrect.adj;
+
+ rotate_rect(dstangle, dstinfo, dstorigaux);
+ rotate_rect(dstangle, dstinfo, dstclipaux);
+ rotate_rect(dstangle, dstinfo, dstadjaux);
+
+ GCPRINT_RECT(GCZONE_SURF, "original aux dst (rot)",
+ dstorigaux);
+ GCPRINT_RECT(GCZONE_SURF, "clipped aux dst (rot)",
+ dstclipaux);
+ GCPRINT_RECT(GCZONE_SURF, "adjusted aux dst (rot)",
+ dstadjaux);
+ }
+
+ rotate_geom(dstangle, dstinfo);
+
+ /* Make sure the new destination is programmed. */
+ dstinfo->surfdirty = true;
+ }
+
+ GCEXIT(GCZONE_SURF);
+}
+
+void process_rotation(struct gcsurface *gcsurface)
+{
+ int offsetX, offsetY;
+ struct gcrect *clip;
+ struct gcrect *adj;
+ struct gcrect *clipaux;
+ struct gcrect *adjaux;
+
+ GCENTER(GCZONE_SURF);
+
+ switch (gcsurface->angle) {
+ case ROT_ANGLE_0:
+ /* Determine the origin offset. */
+ offsetX = gcsurface->xpixalign;
+ offsetY = gcsurface->ypixalign;
+
+ /* Determine geometry size. */
+ gcsurface->adjwidth = gcsurface->width
+ - gcsurface->xpixalign;
+ gcsurface->adjheight = gcsurface->height
+ - gcsurface->ypixalign;
+
+ /* Determine the physical size. */
+ gcsurface->physwidth = gcsurface->adjwidth;
+ gcsurface->physheight = gcsurface->adjheight;
+ break;
+
+ case ROT_ANGLE_90:
+ /* Determine the origin offset. */
+ offsetX = gcsurface->ypixalign;
+ offsetY = gcsurface->xpixalign;
+
+ /* Determine geometry size. */
+ gcsurface->adjwidth = gcsurface->width
+ - gcsurface->ypixalign;
+ gcsurface->adjheight = gcsurface->height
+ - gcsurface->xpixalign;
+
+ /* Determine the physical size. */
+ gcsurface->physwidth = gcsurface->adjheight;
+ gcsurface->physheight = gcsurface->adjwidth;
+ break;
+
+ case ROT_ANGLE_180:
+ /* Determine the origin offset. */
+ offsetX = 0;
+ offsetY = 0;
+
+ /* Determine geometry size. */
+ gcsurface->adjwidth = gcsurface->width
+ - gcsurface->xpixalign;
+ gcsurface->adjheight = gcsurface->height
+ - gcsurface->ypixalign;
+
+ /* Determine the physical size. */
+ gcsurface->physwidth = gcsurface->adjwidth;
+ gcsurface->physheight = gcsurface->adjheight;
+ break;
+
+ case ROT_ANGLE_270:
+ /* Determine the origin offset. */
+ offsetX = 0;
+ offsetY = 0;
+
+ /* Determine geometry size. */
+ gcsurface->adjwidth = gcsurface->width
+ - gcsurface->ypixalign;
+ gcsurface->adjheight = gcsurface->height
+ - gcsurface->xpixalign;
+
+ /* Determine the physical size. */
+ gcsurface->physwidth = gcsurface->adjheight;
+ gcsurface->physheight = gcsurface->adjwidth;
+ break;
+
+ default:
+ offsetX = 0;
+ offsetY = 0;
+ }
+
+ /* Get shortcuts to the destination rectangles. */
+ clip = &gcsurface->rect.clip;
+ adj = &gcsurface->rect.adj;
+
+ /* Compute adjusted destination rectangle. */
+ adj->left = clip->left - offsetX;
+ adj->top = clip->top - offsetY;
+ adj->right = clip->right - offsetX;
+ adj->bottom = clip->bottom - offsetY;
+
+ GCPRINT_RECT(GCZONE_SURF, "adjusted", adj);
+
+ if (gcsurface->haveaux) {
+ /* Get shortcuts to the destination aux rectangles. */
+ clipaux = &gcsurface->auxrect.clip;
+ adjaux = &gcsurface->auxrect.adj;
+
+ /* Compute adjusted destination rectangle. */
+ adjaux->left = clipaux->left - offsetX;
+ adjaux->top = clipaux->top - offsetY;
+ adjaux->right = clipaux->right - offsetX;
+ adjaux->bottom = clipaux->bottom - offsetY;
+
+ GCPRINT_RECT(GCZONE_SURF, "adjusted aux", adjaux);
+ }
+
+ GCDBG(GCZONE_SURF, "aligned geometry size = %dx%d\n",
+ gcsurface->adjwidth, gcsurface->adjheight);
+ GCDBG(GCZONE_SURF, "aligned physical size = %dx%d\n",
+ gcsurface->physwidth, gcsurface->physheight);
+ GCDBG(GCZONE_SURF, "origin offset (pixels) = %d,%d\n",
+ offsetX, offsetY);
+
+ GCEXIT(GCZONE_SURF);
+}
+
+enum bverror parse_destination(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct gcsurface *dstinfo;
+ struct gcrect *dstorig;
+ struct gcrect *dstclip;
+ struct gcrect *dstorigaux = NULL;
+ struct gcrect *dstclipaux = NULL;
+
+ GCENTER(GCZONE_DEST);
+
+ GCDBG(GCZONE_DEST, "parsing destination\n");
+
+ /* Get a shortcut to the destination surface descriptor. */
+ dstinfo = &batch->dstinfo;
+
+ /* Did the destination surface change? */
+ if (dstinfo->surfdirty) {
+ struct bvsurfgeom *dstgeom;
+
+ /* Shortcut to the geometry. */
+ dstgeom = bvbltparams->dstgeom;
+
+ /* Initialize the destination descriptor. */
+ dstinfo->index = -1;
+ dstinfo->buf.desc = bvbltparams->dstdesc;
+ dstinfo->width = dstgeom->width;
+ dstinfo->height = dstgeom->height;
+ dstinfo->stride1 = dstgeom->virtstride;
+
+ /* Parse the destination format. */
+ if (parse_format(bvbltparams, dstgeom->format,
+ &dstinfo->format) != BVERR_NONE) {
+ bverror = BVERR_DSTGEOM_FORMAT;
+ goto exit;
+ }
+
+ /* Parse orientation. */
+ dstinfo->angle = get_angle(dstgeom->orientation);
+ if (dstinfo->angle == ROT_ANGLE_INVALID) {
+ BVSETBLTERROR(BVERR_DSTGEOM,
+ "unsupported destination orientation %d.",
+ dstgeom->orientation);
+ goto exit;
+ }
+
+ /* If angle has been modified previosuly, it means that
+ * the rectangles have been rotated, make sure they are
+ * reset back to the original ones. */
+ if (dstinfo->adjangle != 0) {
+ dstinfo->rectdirty = true;
+
+ /* Reset destination adjust angle. */
+ dstinfo->adjangle = 0;
+ }
+
+ /* Compute the destination alignments needed to compensate
+ * for the surface base address misalignment if any. */
+ dstinfo->xpixalign = get_pixel_offset(dstinfo, 0);
+ dstinfo->ypixalign = 0;
+ dstinfo->bytealign1 = (dstinfo->xpixalign
+ * (int) dstinfo->format.bitspp) / 8;
+
+ GCDBG(GCZONE_DEST, " buffer length = %d\n",
+ dstinfo->buf.desc->length);
+ GCDBG(GCZONE_DEST, " rotation %d degrees.\n",
+ dstinfo->angle * 90);
+
+ if (dstinfo->buf.desc->auxtype == BVAT_PHYSDESC) {
+ struct bvphysdesc *bvphysdesc;
+ bvphysdesc = (struct bvphysdesc *)
+ dstinfo->buf.desc->auxptr;
+ GCDBG(GCZONE_DEST, " physical descriptor = 0x%08X\n",
+ bvphysdesc);
+ GCDBG(GCZONE_DEST, " first page = 0x%08X\n",
+ bvphysdesc->pagearray[0]);
+ GCDBG(GCZONE_DEST, " page offset = 0x%08X\n",
+ bvphysdesc->pageoffset);
+ } else {
+ GCDBG(GCZONE_DEST, " virtual address = 0x%08X\n",
+ (unsigned int) dstinfo->buf.desc->virtaddr);
+ }
+
+ GCDBG(GCZONE_DEST, " stride = %ld\n",
+ dstinfo->stride1);
+ GCDBG(GCZONE_DEST, " geometry size = %dx%d\n",
+ dstinfo->width, dstinfo->height);
+ GCDBG(GCZONE_DEST, " surface offset (pixels) = %d,%d\n",
+ dstinfo->xpixalign, dstinfo->ypixalign);
+ GCDBG(GCZONE_DEST, " surface offset (bytes) = %d\n",
+ dstinfo->bytealign1);
+
+ /* Check for unsupported dest formats. */
+ if ((dstinfo->format.type == BVFMT_YUV) &&
+ (dstinfo->format.cs.yuv.planecount > 1)) {
+ BVSETBLTERROR(BVERR_DSTGEOM_FORMAT,
+ "destination format unsupported");
+ goto exit;
+ }
+
+ /* Zero-fill for destination is not supported. */
+ if (dstinfo->format.zerofill) {
+ BVSETBLTERROR(BVERR_DSTGEOM_FORMAT,
+ "0 filling is not supported.");
+ goto exit;
+ }
+
+ /* Validate the stride. */
+ bverror = valid_stride(bvbltparams, dstinfo);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Validate geometry. */
+ if (!valid_geom(dstinfo)) {
+ BVSETBLTERROR(BVERR_DSTGEOM,
+ "destination geom exceeds surface size");
+ goto exit;
+ }
+ }
+
+ /* Did clipping/destination rects change? */
+ if (dstinfo->rectdirty) {
+ struct gcrect cliprect;
+ struct gcrect *clipdelta;
+
+ /* Get shortcuts to the destination rectangles. */
+ clipdelta = &batch->clipdelta;
+ dstorig = &dstinfo->rect.orig;
+ dstclip = &dstinfo->rect.clip;
+
+ /* Determine destination rectangle. */
+ GCCONVERT_RECT(GCZONE_DEST,
+ " rect",
+ &bvbltparams->dstrect,
+ dstorig);
+
+ /* Determine whether aux destination is specified. */
+ dstinfo->haveaux
+ = ((bvbltparams->flags & BVFLAG_SRC2_AUXDSTRECT) != 0);
+ GCDBG(GCZONE_DEST, " have aux dest = %d\n", dstinfo->haveaux);
+
+ if (dstinfo->haveaux) {
+ dstorigaux = &dstinfo->auxrect.orig;
+ dstclipaux = &dstinfo->auxrect.clip;
+
+ /* Convert the aux rectangle. */
+ GCCONVERT_RECT(GCZONE_DEST,
+ " aux rect",
+ &bvbltparams->src2auxdstrect,
+ dstorigaux);
+ }
+
+ /* Is clipping rectangle specified? */
+ if ((bvbltparams->flags & BVFLAG_CLIP) == BVFLAG_CLIP) {
+ /* Convert the clipping rectangle. */
+ GCCONVERT_RECT(GCZONE_DEST,
+ " clipping",
+ &bvbltparams->cliprect,
+ &cliprect);
+
+ if ((cliprect.left < GC_CLIP_RESET_LEFT) ||
+ (cliprect.top < GC_CLIP_RESET_TOP) ||
+ (cliprect.right > GC_CLIP_RESET_RIGHT) ||
+ (cliprect.bottom > GC_CLIP_RESET_BOTTOM)) {
+ BVSETERROR(BVERR_CLIP_RECT,
+ "clip rect is invalid");
+ goto exit;
+ }
+
+ /* Compute clipping deltas and the adjusted
+ * destination rect. */
+ if (cliprect.left <= dstorig->left) {
+ clipdelta->left = 0;
+ dstclip->left = dstorig->left;
+ } else {
+ clipdelta->left
+ = cliprect.left - dstorig->left;
+ dstclip->left = cliprect.left;
+ }
+
+ if (cliprect.top <= dstorig->top) {
+ clipdelta->top = 0;
+ dstclip->top = dstorig->top;
+ } else {
+ clipdelta->top
+ = cliprect.top - dstorig->top;
+ dstclip->top = cliprect.top;
+ }
+
+ if (cliprect.right >= dstorig->right) {
+ clipdelta->right = 0;
+ dstclip->right = dstorig->right;
+ } else {
+ clipdelta->right
+ = cliprect.right - dstorig->right;
+ dstclip->right = cliprect.right;
+ }
+
+ if (cliprect.bottom >= dstorig->bottom) {
+ clipdelta->bottom = 0;
+ dstclip->bottom = dstorig->bottom;
+ } else {
+ clipdelta->bottom
+ = cliprect.bottom - dstorig->bottom;
+ dstclip->bottom = cliprect.bottom;
+ }
+
+ /* Clip the aux destination. */
+ if (dstinfo->haveaux) {
+ dstclipaux->left =
+ (cliprect.left <= dstorigaux->left)
+ ? dstorigaux->left
+ : cliprect.left;
+
+ dstclipaux->top =
+ (cliprect.top <= dstorigaux->top)
+ ? dstorigaux->top
+ : cliprect.top;
+
+ dstclipaux->right =
+ (cliprect.right >= dstorigaux->right)
+ ? dstorigaux->right
+ : cliprect.right;
+
+ dstclipaux->bottom =
+ (cliprect.bottom >= dstorigaux->bottom)
+ ? dstorigaux->bottom
+ : cliprect.bottom;
+ }
+ } else {
+ clipdelta->left =
+ clipdelta->top =
+ clipdelta->right =
+ clipdelta->bottom = 0;
+
+ *dstclip = *dstorig;
+
+ if (dstinfo->haveaux)
+ *dstclipaux = *dstorigaux;
+ }
+
+ GCPRINT_RECT(GCZONE_DEST, " clipped dest", dstclip);
+
+ /* Validate the destination rectangle. */
+ if (!valid_rect(dstinfo, dstclip)) {
+ BVSETBLTERROR(BVERR_DSTRECT,
+ "invalid destination rectangle.");
+ goto exit;
+ }
+
+ if (dstinfo->haveaux) {
+ GCPRINT_RECT(GCZONE_DEST, " clipped aux dest",
+ dstclipaux);
+
+ /* Validate the aux destination rectangle. */
+ if (!valid_rect(dstinfo, dstclipaux)) {
+ BVSETBLTERROR(BVERR_DSTRECT,
+ "invalid aux destination "
+ "rectangle.");
+ goto exit;
+ }
+
+ /* Disable aux rectangle if empty. */
+ if (null_rect(dstclipaux)) {
+ GCDBG(GCZONE_DEST, " empty aux dest.\n");
+ dstinfo->haveaux = false;
+ }
+ }
+
+ GCDBG(GCZONE_DEST,
+ " clipping delta = (%d,%d)-(%d,%d)\n",
+ clipdelta->left,
+ clipdelta->top,
+ clipdelta->right,
+ clipdelta->bottom);
+ }
+
+ /* Did clipping/destination rects change? */
+ if (dstinfo->surfdirty || dstinfo->rectdirty)
+ process_rotation(dstinfo);
+
+exit:
+ GCEXITARG(GCZONE_DEST, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+enum bverror parse_source(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch,
+ struct gcsurface *srcinfo,
+ unsigned int index,
+ unsigned short rop)
+{
+ enum bverror bverror = BVERR_NONE;
+ struct bvsurfgeom *srcgeom;
+ struct bvrect *srcrect;
+
+ GCENTER(GCZONE_SRC);
+ GCDBG(GCZONE_SRC, "parsing source #%d\n", index);
+
+ if (index == 0) {
+ /* Set source index. */
+ srcinfo->index = 0;
+
+ /* Determine change flags. */
+ srcinfo->surfdirty = ((batch->batchflags
+ & BVBATCH_SRC1) != 0);
+ srcinfo->rectdirty = ((batch->batchflags
+ & BVBATCH_SRC1RECT) != 0);
+
+ /* Set buffer descriptor. */
+ srcinfo->buf = bvbltparams->src1;
+
+ /* Fetch proper structures. */
+ srcgeom = bvbltparams->src1geom;
+ srcrect = &bvbltparams->src1rect;
+ } else {
+ /* Set source index. */
+ srcinfo->index = 1;
+
+ /* Determine change flags. */
+ srcinfo->surfdirty = ((batch->batchflags
+ & BVBATCH_SRC2) != 0);
+ srcinfo->rectdirty = ((batch->batchflags
+ & BVBATCH_SRC2RECT) != 0);
+
+ /* Set buffer descriptor. */
+ srcinfo->buf = bvbltparams->src2;
+
+ /* Fetch proper structures. */
+ srcgeom = bvbltparams->src2geom;
+ srcrect = &bvbltparams->src2rect;
+ }
+
+ /* Set parameters. */
+ srcinfo->width = srcgeom->width;
+ srcinfo->height = srcgeom->height;
+ srcinfo->stride1 = srcgeom->virtstride;
+ srcinfo->rop = rop;
+ srcinfo->haveaux = false;
+
+ /* Parse the source format. */
+ if (parse_format(bvbltparams, srcgeom->format,
+ &srcinfo->format) != BVERR_NONE) {
+ bverror = (index == 0)
+ ? BVERR_SRC1GEOM_FORMAT
+ : BVERR_SRC2GEOM_FORMAT;
+ goto exit;
+ }
+
+ /* Parse orientation. */
+ srcinfo->angle = get_angle(srcgeom->orientation);
+ if (srcinfo->angle == ROT_ANGLE_INVALID) {
+ BVSETBLTERROR((index == 0)
+ ? BVERR_SRC1GEOM
+ : BVERR_SRC2GEOM,
+ "unsupported source%d orientation %d.",
+ index + 1,
+ srcgeom->orientation);
+ goto exit;
+ }
+
+ /* Assume that the source rotation is supported and the source
+ * does not need to be software rotared. */
+ srcinfo->adjangle = 0;
+
+ /* Determine source mirror. */
+ srcinfo->mirror = (index == 0)
+ ? (bvbltparams->flags >> BVFLAG_FLIP_SRC1_SHIFT)
+ & BVFLAG_FLIP_MASK
+ : (bvbltparams->flags >> BVFLAG_FLIP_SRC2_SHIFT)
+ & BVFLAG_FLIP_MASK;
+
+ GCDBG(GCZONE_SRC, " buffer length = %d\n", srcinfo->buf.desc->length);
+ GCDBG(GCZONE_SRC, " rotation %d degrees.\n", srcinfo->angle * 90);
+
+ if (srcinfo->buf.desc->auxtype == BVAT_PHYSDESC) {
+ struct bvphysdesc *bvphysdesc;
+ bvphysdesc = (struct bvphysdesc *) srcinfo->buf.desc->auxptr;
+ GCDBG(GCZONE_SRC, " physical descriptor = 0x%08X\n",
+ bvphysdesc);
+ GCDBG(GCZONE_SRC, " first page = 0x%08X\n",
+ bvphysdesc->pagearray[0]);
+ GCDBG(GCZONE_SRC, " page offset = 0x%08X\n",
+ bvphysdesc->pageoffset);
+ } else {
+ GCDBG(GCZONE_SRC, " virtual address = 0x%08X\n",
+ (unsigned int) srcinfo->buf.desc->virtaddr);
+ }
+
+ GCDBG(GCZONE_SRC, " stride = %ld\n",
+ srcinfo->stride1);
+ GCDBG(GCZONE_SRC, " geometry size = %dx%d\n",
+ srcinfo->width, srcinfo->height);
+ GCDBG(GCZONE_SRC, " mirror = %d\n", srcinfo->mirror);
+
+ /* Convert the rectangle. */
+ GCCONVERT_RECT(GCZONE_SRC,
+ " rect", srcrect, &srcinfo->rect.orig);
+
+ /* Planar YUV? */
+ if ((srcinfo->format.type == BVFMT_YUV) &&
+ (srcinfo->format.cs.yuv.planecount > 1)) {
+ int xpixalign;
+
+ /* Source rotation is not supported. */
+ if (srcinfo->angle != ROT_ANGLE_0) {
+ srcinfo->adjangle = (4 - srcinfo->angle) % 4;
+ GCDBG(GCZONE_SRC, " rotation adjustment angle %d.\n",
+ srcinfo->adjangle * 90);
+ }
+
+ /* Check base address alignment. */
+ xpixalign = get_pixel_offset(srcinfo, 0);
+ if (xpixalign != 0) {
+ BVSETBLTERROR((index == 0)
+ ? BVERR_SRC1DESC_ALIGNMENT
+ : BVERR_SRC2DESC_ALIGNMENT,
+ "planar YUV base address must be "
+ "64 byte aligned.");
+ goto exit;
+ }
+ }
+
+ /* Validate the stride. */
+ bverror = valid_stride(bvbltparams, srcinfo);
+ if (bverror != BVERR_NONE)
+ goto exit;
+
+ /* Validate source geometry. */
+ if (!valid_geom(srcinfo)) {
+ BVSETBLTERROR((index == 0)
+ ? BVERR_SRC1GEOM
+ : BVERR_SRC2GEOM,
+ "source%d geom exceeds surface size.",
+ index + 1);
+ goto exit;
+ }
+
+exit:
+ GCEXITARG(GCZONE_SRC, "bv%s = %d\n",
+ (bverror == BVERR_NONE) ? "result" : "error", bverror);
+ return bverror;
+}
+
+static enum bverror parse_implicitscale(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch)
+{
+ enum bverror bverror = BVERR_NONE;
+ unsigned int quality;
+ unsigned int technique;
+ unsigned int imagetype;
+
+ GCENTER(GCZONE_SCALING);
+
+ quality = (bvbltparams->scalemode & BVSCALEDEF_QUALITY_MASK)
+ >> BVSCALEDEF_QUALITY_SHIFT;
+ technique = (bvbltparams->scalemode & BVSCALEDEF_TECHNIQUE_MASK)
+ >> BVSCALEDEF_TECHNIQUE_SHIFT;
+ imagetype = (bvbltparams->scalemode & BVSCALEDEF_TYPE_MASK)
+ >> BVSCALEDEF_TYPE_SHIFT;
+
+ GCDBG(GCZONE_SCALING, "quality = %d\n", quality);
+ GCDBG(GCZONE_SCALING, "technique = %d\n", technique);
+ GCDBG(GCZONE_SCALING, "imagetype = %d\n", imagetype);
+
+ switch (quality) {
+ case BVSCALEDEF_FASTEST >> BVSCALEDEF_QUALITY_SHIFT:
+ batch->op.filter.horkernelsize = 3;
+ batch->op.filter.verkernelsize = 3;
+ break;
+
+ case BVSCALEDEF_GOOD >> BVSCALEDEF_QUALITY_SHIFT:
+ batch->op.filter.horkernelsize = 5;
+ batch->op.filter.verkernelsize = 5;
+ break;
+
+ case BVSCALEDEF_BETTER >> BVSCALEDEF_QUALITY_SHIFT:
+ batch->op.filter.horkernelsize = 7;
+ batch->op.filter.verkernelsize = 7;
+ break;
+
+ case BVSCALEDEF_BEST >> BVSCALEDEF_QUALITY_SHIFT:
+ batch->op.filter.horkernelsize = 9;
+ batch->op.filter.verkernelsize = 9;
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_SCALE_MODE,
+ "unsupported scale quality 0x%02X", quality);
+ goto exit;
+ }
+
+ switch (technique) {
+ case BVSCALEDEF_DONT_CARE >> BVSCALEDEF_TECHNIQUE_SHIFT:
+ case BVSCALEDEF_NOT_NEAREST_NEIGHBOR >> BVSCALEDEF_TECHNIQUE_SHIFT:
+ break;
+
+ case BVSCALEDEF_POINT_SAMPLE >> BVSCALEDEF_TECHNIQUE_SHIFT:
+ batch->op.filter.horkernelsize = 1;
+ batch->op.filter.verkernelsize = 1;
+ break;
+
+ case BVSCALEDEF_INTERPOLATED >> BVSCALEDEF_TECHNIQUE_SHIFT:
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_SCALE_MODE,
+ "unsupported scale technique %d", technique);
+ goto exit;
+ }
+
+ switch (imagetype) {
+ case 0:
+ case BVSCALEDEF_PHOTO >> BVSCALEDEF_TYPE_SHIFT:
+ case BVSCALEDEF_DRAWING >> BVSCALEDEF_TYPE_SHIFT:
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_SCALE_MODE,
+ "unsupported image type %d", imagetype);
+ goto exit;
+ }
+
+ GCDBG(GCZONE_SCALING, "kernel size = %dx%d\n",
+ batch->op.filter.horkernelsize,
+ batch->op.filter.verkernelsize);
+
+exit:
+ GCEXIT(GCZONE_SCALING);
+ return bverror;
+}
+
+static enum bverror parse_explicitscale(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch)
+{
+ enum bverror bverror = BVERR_NONE;
+ unsigned int horsize;
+ unsigned int versize;
+
+ GCENTER(GCZONE_SCALING);
+
+ horsize = (bvbltparams->scalemode & BVSCALEDEF_HORZ_MASK)
+ >> BVSCALEDEF_HORZ_SHIFT;
+ versize = (bvbltparams->scalemode & BVSCALEDEF_VERT_MASK)
+ >> BVSCALEDEF_VERT_SHIFT;
+
+ GCDBG(GCZONE_SCALING, "horsize = %d\n", horsize);
+ GCDBG(GCZONE_SCALING, "versize = %d\n", versize);
+
+ switch (horsize) {
+ case BVSCALEDEF_NEAREST_NEIGHBOR:
+ batch->op.filter.horkernelsize = 1;
+ break;
+
+ case BVSCALEDEF_LINEAR:
+ case BVSCALEDEF_CUBIC:
+ case BVSCALEDEF_3_TAP:
+ batch->op.filter.horkernelsize = 3;
+ break;
+
+ case BVSCALEDEF_5_TAP:
+ batch->op.filter.horkernelsize = 5;
+ break;
+
+ case BVSCALEDEF_7_TAP:
+ batch->op.filter.horkernelsize = 7;
+ break;
+
+ case BVSCALEDEF_9_TAP:
+ batch->op.filter.horkernelsize = 9;
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_SCALE_MODE,
+ "unsupported horizontal kernel size %d", horsize);
+ goto exit;
+ }
+
+ switch (versize) {
+ case BVSCALEDEF_NEAREST_NEIGHBOR:
+ batch->op.filter.verkernelsize = 1;
+ break;
+
+ case BVSCALEDEF_LINEAR:
+ case BVSCALEDEF_CUBIC:
+ case BVSCALEDEF_3_TAP:
+ batch->op.filter.verkernelsize = 3;
+ break;
+
+ case BVSCALEDEF_5_TAP:
+ batch->op.filter.verkernelsize = 5;
+ break;
+
+ case BVSCALEDEF_7_TAP:
+ batch->op.filter.verkernelsize = 7;
+ break;
+
+ case BVSCALEDEF_9_TAP:
+ batch->op.filter.verkernelsize = 9;
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_SCALE_MODE,
+ "unsupported vertical kernel size %d", versize);
+ goto exit;
+ }
+
+ GCDBG(GCZONE_SCALING, "kernel size = %dx%d\n",
+ batch->op.filter.horkernelsize,
+ batch->op.filter.verkernelsize);
+
+exit:
+ GCEXIT(GCZONE_SCALING);
+ return bverror;
+}
+
+enum bverror parse_scalemode(struct bvbltparams *bvbltparams,
+ struct gcbatch *batch)
+{
+ enum bverror bverror;
+ unsigned int scaleclass;
+
+ GCENTER(GCZONE_SCALING);
+
+ scaleclass = (bvbltparams->scalemode & BVSCALEDEF_CLASS_MASK)
+ >> BVSCALEDEF_CLASS_SHIFT;
+
+ GCDBG(GCZONE_SCALING, "scaleclass = %d\n", scaleclass);
+
+ switch (scaleclass) {
+ case BVSCALEDEF_IMPLICIT >> BVSCALEDEF_CLASS_SHIFT:
+ bverror = parse_implicitscale(bvbltparams, batch);
+ break;
+
+ case BVSCALEDEF_EXPLICIT >> BVSCALEDEF_CLASS_SHIFT:
+ bverror = parse_explicitscale(bvbltparams, batch);
+ break;
+
+ default:
+ BVSETBLTERROR(BVERR_SCALE_MODE,
+ "unsupported scale class %d", scaleclass);
+ goto exit;
+ }
+
+exit:
+ GCEXIT(GCZONE_SCALING);
+ return bverror;
+}
diff --git a/drivers/misc/gcx/gccore/Kconfig b/drivers/misc/gcx/gccore/Kconfig
--- /dev/null
@@ -0,0 +1,5 @@
+config GCCORE
+ tristate "Vivante Core Driver"
+ default y
+ help
+ Vivante Core Driver.
diff --git a/drivers/misc/gcx/gccore/Makefile b/drivers/misc/gcx/gccore/Makefile
--- /dev/null
@@ -0,0 +1,9 @@
+obj-$(CONFIG_GCCORE) += gccore.o
+
+gccore-y := \
+ gcmain.o \
+ gcmem.o \
+ gcmmu.o \
+ gcqueue.o \
+ gcdebug.o \
+ gcdbglog.o
diff --git a/drivers/misc/gcx/gccore/gcdbglog.c b/drivers/misc/gcx/gccore/gcdbglog.c
--- /dev/null
@@ -0,0 +1,2325 @@
+/*
+ * gcdbglog.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/ioctl.h>
+#include <linux/clk.h>
+#include <linux/seq_file.h>
+#include <linux/kernel.h>
+#include <stdarg.h>
+#include <linux/gcreg.h>
+#include <linux/gcx.h>
+#include "gcmain.h"
+
+#if GCDEBUG_ENABLE
+
+/*******************************************************************************
+ * Debug switches.
+ */
+
+/* Dumping enable default state. */
+#define GC_DUMP_ENABLE 0
+
+/* Ignore all zones as if they were all enabled in all modules. */
+#define GC_IGNORE_ZONES 0
+
+/* When enabled, all output is collected into a buffer with a predefined size.
+ * GC_DUMP_BUFFER_SIZE determines the size of the buffer and GC_ENABLE_OVERFLOW
+ * controls what happens when the buffer gets full. */
+#define GC_BUFFERED_OUTPUT 0
+
+/* Debug output buffer size. */
+#define GC_DUMP_BUFFER_SIZE (400 * 1024)
+
+/* If disabled, the contents of the buffer will be dumped to the console when
+ * the buffer gets full.
+ * If enabled, wrap around mode is enabled where when the buffer gets full,
+ * the oldest entries are overwritten with the new entrie. To dump the buffer
+ * to the console gc_dump_flush must be called explicitly. */
+#define GC_ENABLE_OVERFLOW 1
+
+/* Specifies how many prints are accumulated in the buffer before the buffer is
+ * flushed. Set to zero to disable auto dumping mode. */
+#define GC_FLUSH_COUNT 0
+
+/* Specifies the maximum number of threads that will be tracked in an attempt
+ * to visually separate messages from different threads. To disable thread
+ * tracking, set to 0 or 1. */
+#define GC_THREAD_COUNT 20
+
+/* Specifies spacing for thread messages. */
+#define GC_THREAD_INDENT 0
+
+/* Print the timestamp. */
+#define GC_SHOW_TIME 1
+
+/* When set to non-zero, specifies how many prints are accumulated in the
+ * buffer before the buffer is flushed. */
+#define GC_SHOW_DUMP_LINE 1
+
+/* If enabled, each print statement will be preceeded with the current
+ * process ID. */
+#define GC_SHOW_PID 1
+
+/* If enabled, internal logging validation code is turned on. */
+#define GC_DEBUG_SELF 0
+
+/* Maximum length of a dump string. */
+#define GC_MAXSTR_LENGTH 256
+
+/* Print buffers like C arrays. */
+#define GC_C_BUFFER 0
+
+
+/*******************************************************************************
+ * Miscellaneous macros.
+ */
+
+#define GC_PTRALIGNMENT(p, alignment) \
+( \
+ GC_ALIGN(GC_PTR2INT(p), alignment) - GC_PTR2INT(p) \
+)
+
+#define GC_VARARG_ALIGNMENT sizeof(unsigned long long)
+
+#if defined(GCDBGFILTER)
+#undef GCDBGFILTER
+#endif
+
+#define GCDBGFILTER \
+ (*filter)
+
+#if GC_IGNORE_ZONES
+#define GC_VERIFY_ENABLE(filter, zone) \
+ (g_initdone)
+#else
+#define GC_VERIFY_ENABLE(filter, zone) \
+ (g_initdone && ((filter == NULL) || ((filter->zone & zone) != 0)))
+#endif
+
+#if GC_SHOW_TIME
+#define GC_TIME_FORMAT "[%5ld.%10ld] "
+#endif
+
+#if GC_SHOW_DUMP_LINE
+#define GC_DUMPLINE_FORMAT "[%12d] "
+#endif
+
+#if GC_SHOW_PID
+#define GC_PID_FORMAT "[pid=%04X] "
+#endif
+
+#define GC_EOL_RESERVE 1
+
+/*******************************************************************************
+ * Dump item header definition.
+ */
+
+enum itemtype {
+ GC_BUFITEM_NONE,
+ GC_BUFITEM_STRING,
+ GC_BUFITEM_BUFFER
+};
+
+/* Common item head/buffer terminator. */
+struct itemhead {
+ enum itemtype type;
+};
+
+
+/*******************************************************************************
+ * Supported dump items.
+ */
+
+/* GC_BUFITEM_STRING: buffered string. */
+struct itemstring {
+ enum itemtype itemtype;
+ int indent;
+
+#if GC_SHOW_TIME
+ struct timespec timestamp;
+#endif
+
+#if GC_SHOW_DUMP_LINE
+ unsigned int dumpline;
+#endif
+
+#if GC_SHOW_PID
+ struct task_struct *task;
+#endif
+
+ const char *message;
+ va_list messagedata;
+ unsigned int datasize;
+};
+
+/* GC_BUFITEM_BUFFER: buffered memory. */
+enum buffertype {
+ GC_BUFTYPE_GENERIC,
+ GC_BUFTYPE_COMMAND,
+ GC_BUFTYPE_SURFACE
+};
+
+#define GC_GENERIC_DATA_COUNT 32
+#define GC_SURFACE_DATA_COUNT 64
+
+struct itembuffer {
+ enum itemtype itemtype;
+ enum buffertype buffertype;
+ int indent;
+
+ unsigned int surfwidth;
+ unsigned int surfheight;
+ unsigned int surfbpp;
+ unsigned int x1, y1;
+ unsigned int x2, y2;
+
+ unsigned int datasize;
+ unsigned int gpuaddr;
+};
+
+
+/*******************************************************************************
+ * Debug output buffer.
+ */
+
+struct threadinfo {
+ struct task_struct *task;
+ int msgindent;
+ int threadindent;
+};
+
+struct buffout {
+ int enable;
+
+#if GC_THREAD_COUNT > 1
+ unsigned int threadcount;
+ struct threadinfo threadinfo[1 + GC_THREAD_COUNT];
+#else
+ struct threadinfo threadinfo[1];
+#endif
+
+#if GC_SHOW_DUMP_LINE
+ unsigned int dumpline;
+#endif
+
+#if GC_BUFFERED_OUTPUT
+ int start;
+ int index;
+ int count;
+ unsigned char *buffer;
+#endif
+};
+
+static struct buffout g_outputbuffer = {
+ .enable = GC_DUMP_ENABLE
+};
+
+
+/*******************************************************************************
+ * Internal structures.
+ */
+
+struct copypos {
+ struct gcmmustlb *slave;
+ union gcmmuloc pos;
+ unsigned int physical;
+ unsigned char *logical;
+};
+
+
+/*******************************************************************************
+ * Globals.
+ */
+
+static bool g_initdone;
+static DEFINE_MUTEX(g_lockmutex);
+static struct list_head gc_filterlist = LIST_HEAD_INIT(gc_filterlist);
+
+
+/*******************************************************************************
+ * Item size functions.
+ */
+
+#if GC_BUFFERED_OUTPUT
+static int get_item_size_terminator(struct itemhead *item)
+{
+ return sizeof(struct itemhead);
+}
+
+static int get_item_size_string(struct itemhead *item)
+{
+ struct itemstring *itemstring = (struct itemstring *) item;
+ unsigned int vlen = *((unsigned char **) &itemstring->messagedata)
+ - ((unsigned char *) itemstring);
+ return vlen + itemstring->datasize;
+}
+
+static int get_item_size_buffer(struct itemhead *item)
+{
+ struct itembuffer *itembuffer = (struct itembuffer *) item;
+ return sizeof(struct itembuffer) + itembuffer->datasize;
+}
+
+#if GC_ENABLE_OVERFLOW
+typedef int (*getitemsize) (struct itemhead *item);
+
+static getitemsize g_itemsize[] = {
+ get_item_size_terminator,
+ get_item_size_string,
+ get_item_size_buffer
+};
+#endif
+#endif
+
+
+/*******************************************************************************
+ * Printing functions.
+ */
+
+#define GC_PRINTK(s, fmt, ...) \
+do { \
+ if (s) \
+ seq_printf(s, fmt, ##__VA_ARGS__); \
+ else \
+ printk(KERN_INFO fmt, ##__VA_ARGS__); \
+} while (0)
+
+#if GC_DEBUG_SELF
+# define GC_DEBUGMSG(fmt, ...) \
+ GC_PRINTK(NULL, "[%s:%d] " fmt, __func__, __LINE__, \
+ ##__VA_ARGS__)
+#else
+# define GC_DEBUGMSG(...)
+#endif
+
+static struct threadinfo *get_threadinfo(struct buffout *buffout)
+{
+#if GC_THREAD_COUNT > 1
+ struct threadinfo *threadinfo;
+ struct task_struct *task;
+ unsigned int i, count;
+
+ /* Get current task. */
+ task = current;
+
+ /* Try to locate task record. */
+ count = buffout->threadcount + 1;
+ for (i = 1; i < count; i += 1)
+ if (buffout->threadinfo[i].task == task)
+ return &buffout->threadinfo[i];
+
+ /* Not found, still have room? */
+ if (buffout->threadcount < GC_THREAD_COUNT) {
+ threadinfo = &buffout->threadinfo[count];
+ threadinfo->task = task;
+ threadinfo->msgindent = 0;
+ threadinfo->threadindent = buffout->threadcount
+ * GC_THREAD_INDENT;
+ buffout->threadcount += 1;
+ return threadinfo;
+ }
+
+ /* Too many threads, use the common entry. */
+ GC_PRINTK(NULL, "%s(%d) [ERROR] reached the maximum thread number.\n",
+ __func__, __LINE__);
+ threadinfo = buffout->threadinfo;
+ threadinfo->task = task;
+ return threadinfo;
+#else
+ struct threadinfo *threadinfo;
+ threadinfo = buffout->threadinfo;
+
+#if GC_SHOW_PID
+ threadinfo->task = current;
+#else
+ threadinfo->task = NULL;
+#endif
+
+ return threadinfo;
+#endif
+}
+
+static int gc_get_indent(int indent, char *buffer, int buffersize)
+{
+ static const int MAX_INDENT = 80;
+ int len, _indent;
+
+ _indent = indent % MAX_INDENT;
+ if (_indent > buffersize)
+ _indent = buffersize - 1;
+
+ for (len = 0; len < _indent; len += 1)
+ buffer[len] = ' ';
+
+ buffer[len] = '\0';
+ return len;
+}
+
+static void gc_print_string(struct seq_file *s, struct itemstring *str)
+{
+ int len = 0;
+ char buffer[GC_MAXSTR_LENGTH];
+
+#if GC_SHOW_TIME
+ len += snprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE,
+ GC_TIME_FORMAT,
+ str->timestamp.tv_sec,
+ str->timestamp.tv_nsec);
+#endif
+
+#if GC_SHOW_DUMP_LINE
+ len += snprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE,
+ GC_DUMPLINE_FORMAT, str->dumpline);
+#endif
+
+#if GC_SHOW_PID
+ len += snprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE,
+ GC_PID_FORMAT, task_pid_vnr(str->task));
+#endif
+
+ /* Append the indent string. */
+ len += gc_get_indent(str->indent, buffer + len,
+ sizeof(buffer) - len - GC_EOL_RESERVE);
+
+ /* Format the string. */
+ len += vsnprintf(buffer + len, sizeof(buffer) - len - GC_EOL_RESERVE,
+ str->message, str->messagedata);
+
+ /* Add end-of-line if missing. */
+ if (buffer[len - 1] != '\n')
+ buffer[len++] = '\n';
+ buffer[len] = '\0';
+
+ /* Print the string. */
+ GC_PRINTK(s, "%s", buffer);
+
+ /* Notify the OS that we are still alive. */
+ touch_softlockup_watchdog();
+}
+
+static void gc_print_generic(struct seq_file *s, struct itembuffer *item,
+ unsigned char *data)
+{
+ char buffer[GC_MAXSTR_LENGTH];
+ unsigned int i, indent, len;
+
+ /* Append the indent string. */
+ indent = gc_get_indent(item->indent, buffer, sizeof(buffer));
+
+ /* Print the title. */
+ GC_PRINTK(s, "%sBUFFER @ 0x%08X (0x%08X)\n",
+ buffer, item->gpuaddr, (unsigned int) data);
+
+ /* Notify the OS that we are still alive. */
+ touch_softlockup_watchdog();
+
+ /* Print the buffer. */
+ for (i = 0, len = indent; i < item->datasize; i += 4) {
+ if ((i % GC_GENERIC_DATA_COUNT) == 0) {
+ if (i != 0) {
+ /* Print the string. */
+ GC_PRINTK(s, "%s\n", buffer);
+
+ /* Notify the OS that we are still alive. */
+ touch_softlockup_watchdog();
+
+ /* Reset the line. */
+ len = indent;
+ }
+
+ len += snprintf(buffer + len, sizeof(buffer) - len,
+ "0x%08X: ", item->gpuaddr + i);
+ }
+
+ /* Append the data value. */
+ len += snprintf(buffer + len, sizeof(buffer) - len,
+ " 0x%08X", *(unsigned int *) (data + i));
+ }
+
+ /* Print the last partial string. */
+ if ((i % GC_SURFACE_DATA_COUNT) != 0)
+ GC_PRINTK(s, "%s\n", buffer);
+}
+
+static char *gc_module_name(unsigned int index)
+{
+ switch (index) {
+ case GCREG_COMMAND_STALL_STALL_SOURCE_FRONT_END:
+ return "FE";
+
+ case GCREG_COMMAND_STALL_STALL_SOURCE_PIXEL_ENGINE:
+ return "PE";
+
+ case GCREG_COMMAND_STALL_STALL_SOURCE_DRAWING_ENGINE:
+ return "DE";
+
+ default:
+ return "*INVALID*";
+ }
+}
+
+static void gc_print_command(struct seq_file *s, struct itembuffer *item,
+ unsigned char *data)
+{
+ char buffer[GC_MAXSTR_LENGTH];
+ unsigned int *data32;
+ unsigned int i, j, datacount;
+ unsigned int command, count, addr;
+ unsigned int delay, src, dst;
+ unsigned int x1, y1, x2, y2;
+
+ /* Append the indent string. */
+ gc_get_indent(item->indent, buffer, sizeof(buffer));
+
+ /* Print the title. */
+ GC_PRINTK(s, "%sCOMMAND BUFFER @ 0x%08X\n", buffer, item->gpuaddr);
+ GC_PRINTK(s, "%s size = %d\n", buffer, item->datasize);
+
+ datacount = (item->datasize + 3) / 4;
+ data32 = (unsigned int *) data;
+ for (i = 0; i < datacount;) {
+#if GC_C_BUFFER
+ GC_PRINTK(s, "%s\t0x%08X,\n", buffer, data32[i++]);
+#else
+ command = (data32[i] >> 27) & 0x1F;
+
+ switch (command) {
+ case GCREG_COMMAND_OPCODE_LOAD_STATE:
+ count = (data32[i] >> 16) & 0x3FF;
+ addr = data32[i] & 0xFFFF;
+ GC_PRINTK(s, "%s 0x%08X: 0x%08X STATE(0x%04X, %d)\n",
+ buffer, item->gpuaddr + (i << 2),
+ data32[i], addr, count);
+ i += 1;
+
+ count |= 1;
+ for (j = 0; j < count; i += 1, j += 1)
+ GC_PRINTK(s, "%s%14c0x%08X\n",
+ buffer, ' ', data32[i]);
+ break;
+
+ case GCREG_COMMAND_OPCODE_END:
+ GC_PRINTK(s, "%s 0x%08X: 0x%08X END()\n",
+ buffer, item->gpuaddr + (i << 2),
+ data32[i]);
+ i += 1;
+
+ GC_PRINTK(s, "%s%14c0x%08X\n",
+ buffer, ' ', data32[i]);
+ i += 1;
+ break;
+
+ case GCREG_COMMAND_OPCODE_NOP:
+ GC_PRINTK(s, "%s 0x%08X: 0x%08X NOP()\n",
+ buffer, item->gpuaddr + (i << 2),
+ data32[i]);
+ i += 1;
+
+ GC_PRINTK(s, "%s" "%14c0x%08X\n",
+ buffer, ' ', data32[i]);
+ i += 1;
+ break;
+
+ case GCREG_COMMAND_OPCODE_STARTDE:
+ count = (data32[i] >> 8) & 0xFF;
+ GC_PRINTK(s, "%s 0x%08X: 0x%08X STARTDE(%d)\n",
+ buffer, item->gpuaddr + (i << 2),
+ data32[i], count);
+ i += 1;
+
+ GC_PRINTK(s, "%s" "%14c0x%08X\n",
+ buffer, ' ', data32[i]);
+ i += 1;
+
+ for (j = 0; j < count; j += 1) {
+ x1 = data32[i] & 0xFFFF;
+ y1 = (data32[i] >> 16) & 0xFFFF;
+ GC_PRINTK(s, "%s%14c0x%08X LT(%d,%d)\n",
+ buffer, ' ', data32[i], x1, y1);
+ i += 1;
+
+ x2 = data32[i] & 0xFFFF;
+ y2 = (data32[i] >> 16) & 0xFFFF;
+ GC_PRINTK(s, "%s%14c0x%08X RB(%d,%d)\n",
+ buffer, ' ', data32[i], x2, y2);
+ i += 1;
+ }
+ break;
+
+ case GCREG_COMMAND_OPCODE_WAIT:
+ delay = data32[i] & 0xFFFF;
+ GC_PRINTK(s, "%s 0x%08X: 0x%08X WAIT(%d)\n",
+ buffer, item->gpuaddr + (i << 2),
+ data32[i], delay);
+ i += 1;
+
+ GC_PRINTK(s, "%s%14c0x%08X\n", buffer, ' ', data32[i]);
+ i += 1;
+ break;
+
+ case GCREG_COMMAND_OPCODE_LINK:
+ count = data32[i] & 0xFFFF;
+ addr = data32[i + 1];
+ GC_PRINTK(s, "%s 0x%08X: 0x%08X "
+ "LINK(0x%08X-0x%08X, %d)\n",
+ buffer, item->gpuaddr + (i << 2),
+ data32[i], addr, addr + count * 8,
+ count);
+ i += 1;
+
+ GC_PRINTK(s, "%s%14c0x%08X\n", buffer, ' ', data32[i]);
+ i += 1;
+ break;
+
+ case GCREG_COMMAND_OPCODE_STALL:
+ src = data32[i + 1] & 0x1F;
+ dst = (data32[i + 1] >> 8) & 0x1F;
+
+ GC_PRINTK(s, "%s 0x%08X: 0x%08X STALL(%s-%s)\n",
+ buffer, item->gpuaddr + (i << 2),
+ data32[i],
+ gc_module_name(src),
+ gc_module_name(dst));
+ i += 1;
+
+ GC_PRINTK(s, "%s" "%14c0x%08X\n",
+ buffer, ' ', data32[i]);
+ i += 1;
+ break;
+
+ default:
+ GC_PRINTK(s, "%s 0x%08X: 0x%08X UNKNOWN COMMAND\n",
+ buffer, item->gpuaddr + (i << 2),
+ data32[i]);
+ i += 2;
+ }
+#endif
+ }
+}
+
+static void gc_flush_line(struct seq_file *s, char *buffer,
+ unsigned int indent, unsigned int *len,
+ unsigned int count, unsigned char checksum)
+{
+ unsigned int _len;
+ char countstr[10];
+
+ /* Correct data count. */
+ count %= GC_SURFACE_DATA_COUNT;
+ if (count == 0)
+ count = GC_SURFACE_DATA_COUNT;
+
+ snprintf(countstr, sizeof(countstr), "%02X", count);
+ buffer[indent + 1] = countstr[0];
+ buffer[indent + 2] = countstr[1];
+
+ /* Append the checksum. */
+ _len = *len;
+ _len += snprintf(buffer + _len, sizeof(buffer) - _len,
+ "%02X", checksum);
+
+ /* Print the string. */
+ GC_PRINTK(s, "%s\n", buffer);
+
+ /* Notify the OS that we are still alive. */
+ touch_softlockup_watchdog();
+
+ /* Reset the length. */
+ *len = indent;
+}
+
+static void gc_print_surface(struct seq_file *s, struct itembuffer *itembuffer,
+ unsigned char *data)
+{
+ char buffer[GC_MAXSTR_LENGTH];
+ unsigned int i, indent, len;
+ unsigned int prevupper32 = ~0U;
+ unsigned int currupper32;
+ unsigned int offset, address;
+ unsigned int width, height;
+
+ /* Append the indent string. */
+ indent = gc_get_indent(itembuffer->indent, buffer, sizeof(buffer));
+
+ /* Print the title. */
+ GC_PRINTK(s, "%sIMAGE SURFACE @ 0x%08X\n",
+ buffer, itembuffer->gpuaddr);
+
+ GC_PRINTK(s, "%s surface size = %dx%d\n",
+ buffer, itembuffer->surfwidth, itembuffer->surfheight);
+
+ GC_PRINTK(s, "%s surface colordepth = %d\n",
+ buffer, itembuffer->surfbpp);
+
+ GC_PRINTK(s, "%s dumping rectangle = (%d,%d)-(%d,%d)\n",
+ buffer, itembuffer->x1, itembuffer->y1,
+ itembuffer->x2, itembuffer->y2);
+
+ /* Notify the OS that we are still alive. */
+ touch_softlockup_watchdog();
+
+ /* Add TGA header. */
+ width = itembuffer->x2 - itembuffer->x1;
+ height = itembuffer->y2 - itembuffer->y1;
+ GC_PRINTK(s, ":12000000000002000000000000000000"
+ "%02X%02X%02X%02X%02X2000\n",
+ (width & 0xFF), ((width >> 8) & 0xFF),
+ (height & 0xFF), ((height >> 8) & 0xFF),
+ itembuffer->surfbpp * 8);
+
+ /* TGA skip header. */
+ offset = 18;
+
+ /* Print the buffer. */
+ for (i = 0, len = indent; i < itembuffer->datasize; i += 1) {
+ /* Determine the current address. */
+ address = offset + i;
+
+ /* Determine the current higher 16 bits of the address. */
+ currupper32 = address >> 16;
+
+ /* Did it change? */
+ if (currupper32 != prevupper32) {
+ /* Print the previous data if any. */
+ if ((i % GC_SURFACE_DATA_COUNT) != 0)
+ gc_flush_line(s, buffer, indent, &len, i, 0);
+
+ /* Set new upper address. */
+ prevupper32 = currupper32;
+ GC_PRINTK(s, ":02000004%04X00\n", prevupper32);
+
+ /* Add the line prefix. */
+ len += snprintf(buffer + len,
+ sizeof(buffer) - len - 2,
+ ":xx%04X00", address & 0xFFFF);
+ } else if ((i % GC_SURFACE_DATA_COUNT) == 0) {
+ len += snprintf(buffer + len,
+ sizeof(buffer) - len - 2,
+ ":xx%04X00", address & 0xFFFF);
+ }
+
+ /* Append the data value. */
+ len += snprintf(buffer + len,
+ sizeof(buffer) - len - 2,
+ "%02X", data[i]);
+
+ /* End of line? */
+ if (((i + 1) % GC_SURFACE_DATA_COUNT) == 0)
+ gc_flush_line(s, buffer, indent, &len, i + 1, 0);
+ }
+
+ /* Print the last partial string. */
+ if ((i % GC_SURFACE_DATA_COUNT) != 0)
+ gc_flush_line(s, buffer, indent, &len, i, 0);
+
+ /* End of dump. */
+ GC_PRINTK(s, ":00000001FF\n");
+}
+
+typedef void (*printbuffer) (struct seq_file *s, struct itembuffer *itembuffer,
+ unsigned char *data);
+
+static printbuffer g_printbuffer[] = {
+ gc_print_generic,
+ gc_print_command,
+ gc_print_surface
+};
+
+static void gc_print_buffer(struct seq_file *s, struct itembuffer *itembuffer,
+ unsigned char *data)
+{
+ if ((itembuffer->buffertype < 0) ||
+ (itembuffer->buffertype >= countof(g_printbuffer))) {
+ GC_PRINTK(s, "BUFFER ENTRY 0x%08X\n",
+ (unsigned int) itembuffer);
+ GC_PRINTK(s, "INVALID BUFFER TYPE %d\n",
+ itembuffer->buffertype);
+ } else {
+ g_printbuffer[itembuffer->buffertype](s, itembuffer, data);
+ }
+}
+
+
+/*******************************************************************************
+ * Print function wrappers.
+ */
+
+#if GC_BUFFERED_OUTPUT
+static unsigned int gc_print_none(struct seq_file *s, struct buffout *buffout,
+ struct itemhead *item)
+{
+ /* Return the size of the node. */
+ return get_item_size_terminator(item);
+}
+
+static unsigned int gc_print_string_wrapper(struct seq_file *s,
+ struct buffout *buffout,
+ struct itemhead *item)
+{
+ /* Print the message. */
+ gc_print_string(s, (struct itemstring *) item);
+
+ /* Return the size of the node. */
+ return get_item_size_string(item);
+}
+
+static unsigned int gc_print_buffer_wrapper(struct seq_file *s,
+ struct buffout *buffout,
+ struct itemhead *item)
+{
+ unsigned char *data;
+ struct itembuffer *itembuffer = (struct itembuffer *) item;
+
+ /* Compute data address. */
+ data = (unsigned char *) (itembuffer + 1);
+
+ /* Print the message. */
+ gc_print_buffer(s, (struct itembuffer *) item, data);
+
+ /* Return the size of the node. */
+ return get_item_size_buffer(item);
+}
+
+typedef unsigned int (*printitem) (struct seq_file *s, struct buffout *buffout,
+ struct itemhead *item);
+
+static printitem g_printarray[] = {
+ gc_print_none,
+ gc_print_string_wrapper,
+ gc_print_buffer_wrapper
+};
+#endif
+
+
+/*******************************************************************************
+ * Private functions.
+ */
+
+unsigned int gc_get_bpp(unsigned int format)
+{
+ unsigned int bpp;
+
+ switch (format) {
+ case GCREG_DE_FORMAT_INDEX8:
+ case GCREG_DE_FORMAT_A8:
+ bpp = 1;
+ break;
+
+ case GCREG_DE_FORMAT_X4R4G4B4:
+ case GCREG_DE_FORMAT_A4R4G4B4:
+ case GCREG_DE_FORMAT_X1R5G5B5:
+ case GCREG_DE_FORMAT_A1R5G5B5:
+ case GCREG_DE_FORMAT_R5G6B5:
+ case GCREG_DE_FORMAT_YUY2:
+ case GCREG_DE_FORMAT_UYVY:
+ case GCREG_DE_FORMAT_RG16:
+ bpp = 2;
+ break;
+
+ case GCREG_DE_FORMAT_X8R8G8B8:
+ case GCREG_DE_FORMAT_A8R8G8B8:
+ bpp = 4;
+ break;
+
+ default:
+ bpp = 0;
+ }
+
+ return bpp;
+}
+
+static void *gc_map_data(struct copypos *copypos,
+ unsigned int gpuaddr)
+{
+ union gcmmuloc pos;
+ unsigned int offset;
+ unsigned int physical;
+ unsigned int *stlblogical;
+ void *cpuaddr;
+
+ /* Determine MMU table position. */
+ pos.loc.mtlb = (gpuaddr & GCMMU_MTLB_MASK) >> GCMMU_MTLB_SHIFT;
+ pos.loc.stlb = (gpuaddr & GCMMU_STLB_MASK) >> GCMMU_STLB_SHIFT;
+ offset = gpuaddr & GCMMU_OFFSET_MASK;
+
+ /* Map if not yet mapped. */
+ if (pos.absolute != copypos->pos.absolute) {
+ if (copypos->logical != NULL) {
+ iounmap(copypos->logical);
+ copypos->logical = NULL;
+ }
+
+ if (copypos->physical != ~0U) {
+ release_mem_region(copypos->physical, PAGE_SIZE);
+ copypos->physical = ~0U;
+ }
+
+ stlblogical = copypos->slave[pos.loc.mtlb].logical;
+ if (stlblogical == NULL) {
+ gc_dump_string(NULL, 0,
+ "stlb table %d is not allocated.\n",
+ pos.loc.mtlb);
+ goto exit;
+ }
+
+ physical = stlblogical[pos.loc.stlb] & GCMMU_STLB_ADDRESS_MASK;
+
+ if (!request_mem_region(physical, PAGE_SIZE, "dumpbuffer")) {
+ gc_dump_string(NULL, 0,
+ "request_mem_region failed.\n");
+ goto exit;
+ }
+
+ copypos->physical = physical;
+ copypos->logical = (unsigned char *)
+ ioremap_nocache(copypos->physical, PAGE_SIZE);
+
+ if (copypos->logical == NULL) {
+ gc_dump_string(NULL, 0,
+ "ioremap failed.\n");
+ goto exit;
+ }
+
+ copypos->pos.absolute = pos.absolute;
+ }
+
+ /* Compute the CPU virtual address. */
+ cpuaddr = copypos->logical + offset;
+ return cpuaddr;
+
+exit:;
+ gc_dump_string(NULL, 0, "gpuaddr = 0x%08X\n", gpuaddr);
+ gc_dump_string(NULL, 0, "mtlb = %d\n", pos.loc.mtlb);
+ gc_dump_string(NULL, 0, "stlb = %d\n", pos.loc.stlb);
+ gc_dump_string(NULL, 0, "offset = 0x%08X\n", offset);
+ return NULL;
+}
+
+static void gc_copy_generic_buffer(struct gcmmucontext *gcmmucontext,
+ void *dest,
+ struct itembuffer *itembuffer)
+{
+ unsigned int gpuaddr, lastaddr;
+ struct copypos copypos;
+ void *cpuaddr;
+
+ /* Reset memory position structure. */
+ copypos.slave = gcmmucontext->slave;
+ copypos.pos.absolute = ~0U;
+ copypos.physical = ~0U;
+ copypos.logical = NULL;
+
+ /* Compute the last address. */
+ lastaddr = itembuffer->gpuaddr + itembuffer->datasize;
+
+ for (gpuaddr = itembuffer->gpuaddr; gpuaddr < lastaddr; gpuaddr += 4) {
+ cpuaddr = gc_map_data(©pos, gpuaddr);
+ if (cpuaddr == NULL) {
+ gc_dump_mmu(NULL, 0, gcmmucontext);
+ goto exit;
+ }
+
+ memcpy(dest, cpuaddr, 4);
+ dest = (unsigned char *) dest + 4;
+ }
+
+exit:
+ if (copypos.logical != NULL)
+ iounmap(copypos.logical);
+
+ if (copypos.physical != ~0U)
+ release_mem_region(copypos.physical, PAGE_SIZE);
+}
+
+static void gc_copy_surface(struct gcmmucontext *gcmmucontext, void *dest,
+ struct itembuffer *itembuffer)
+{
+ unsigned int stride;
+ unsigned int x, y;
+ unsigned int lineoffset;
+ unsigned int gpuaddr;
+ struct copypos copypos;
+ void *cpuaddr;
+
+ /* Reset memory position structure. */
+ copypos.slave = gcmmucontext->slave;
+ copypos.pos.absolute = ~0U;
+ copypos.physical = ~0U;
+ copypos.logical = NULL;
+
+ /* Compute the srtride. */
+ stride = itembuffer->surfwidth * itembuffer->surfbpp;
+
+ for (y = itembuffer->y1; y < itembuffer->y2; y += 1) {
+ lineoffset = y * stride;
+
+ for (x = itembuffer->x1; x < itembuffer->x2; x += 1) {
+ /* Compute the address. */
+ gpuaddr = itembuffer->gpuaddr + lineoffset
+ + x * itembuffer->surfbpp;
+
+ cpuaddr = gc_map_data(©pos, gpuaddr);
+ if (cpuaddr == NULL) {
+ gc_dump_mmu(NULL, 0, gcmmucontext);
+ goto exit;
+ }
+
+ memcpy(dest, cpuaddr, itembuffer->surfbpp);
+ dest = (unsigned char *) dest + itembuffer->surfbpp;
+ }
+ }
+
+exit:
+ if (copypos.logical != NULL)
+ iounmap(copypos.logical);
+
+ if (copypos.physical != ~0U)
+ release_mem_region(copypos.physical, PAGE_SIZE);
+}
+
+#if GC_BUFFERED_OUTPUT
+static void gc_buffer_flush(struct seq_file *s, struct buffout *buffout)
+{
+ int i, skip;
+ struct itemhead *item;
+
+ if (buffout->count == 0)
+ return;
+
+ GC_PRINTK(s, "****************************************"
+ "****************************************\n");
+ GC_PRINTK(s, "FLUSHING DEBUG OUTPUT BUFFER (%d elements).\n",
+ buffout->count);
+
+#if !GC_ENABLE_OVERFLOW
+ {
+ int occupied = (100 * (buffout->index - buffout->start))
+ / GC_DUMP_BUFFER_SIZE;
+ if (buffout->start != 0)
+ GC_PRINTK(s, " START = %d\n", buffout->start);
+ GC_PRINTK(s, " INDEX = %d\n", buffout->index);
+ GC_PRINTK(s, " BUFFER USE = %d%%\n", occupied);
+ }
+#endif
+
+ GC_PRINTK(s, "****************************************"
+ "****************************************\n");
+
+ item = (struct itemhead *) &buffout->buffer[buffout->start];
+ GC_DEBUGMSG("start=%d.\n", buffout->start);
+
+ /* Notify the OS that we are still alive. */
+ touch_softlockup_watchdog();
+
+ for (i = 0; i < buffout->count; i += 1) {
+ GC_DEBUGMSG("printing item %d of type %d @ 0x%08X.\n",
+ i, item->type, (unsigned int) item);
+ skip = (*g_printarray[item->type]) (s, buffout, item);
+
+ item = (struct itemhead *) ((unsigned char *) item + skip);
+ GC_DEBUGMSG("next item @ 0x%08X.\n", (unsigned int) item);
+
+ if (item->type == GC_BUFITEM_NONE) {
+ GC_DEBUGMSG("reached the end of buffer.\n");
+ item = (struct itemhead *) buffout->buffer;
+ }
+ }
+
+ GC_DEBUGMSG("resetting the buffer.\n");
+ buffout->start = 0;
+ buffout->index = 0;
+ buffout->count = 0;
+
+ /* Notify the OS that we are still alive. */
+ touch_softlockup_watchdog();
+}
+
+static struct itemhead *gc_allocate_item(struct buffout *buffout, int size)
+{
+ struct itemhead *item, *next;
+ int endofbuffer = (buffout->index + size
+ >= GC_DUMP_BUFFER_SIZE - sizeof(struct itemhead));
+
+#if GC_ENABLE_OVERFLOW
+ int skip, bufferoverflow;
+
+ bufferoverflow = (buffout->index < buffout->start) &&
+ (buffout->index + size >= buffout->start);
+
+ if (endofbuffer || bufferoverflow) {
+ if (endofbuffer) {
+ if (buffout->index < buffout->start) {
+ item = (struct itemhead *)
+ &buffout->buffer[buffout->start];
+
+ while (item->type != GC_BUFITEM_NONE) {
+ skip = (*g_itemsize[item->type]) (item);
+
+ buffout->start += skip;
+ buffout->count -= 1;
+
+ item->type = GC_BUFITEM_NONE;
+ item = (struct itemhead *)
+ ((unsigned char *) item + skip);
+ }
+
+ buffout->start = 0;
+ }
+
+ buffout->index = 0;
+ }
+
+ item = (struct itemhead *) &buffout->buffer[buffout->start];
+
+ while (buffout->start - buffout->index <= size) {
+ skip = (*g_itemsize[item->type]) (item);
+
+ buffout->start += skip;
+ buffout->count -= 1;
+
+ item->type = GC_BUFITEM_NONE;
+ item = (struct itemhead *)
+ ((unsigned char *) item + skip);
+
+ if (item->type == GC_BUFITEM_NONE) {
+ buffout->start = 0;
+ break;
+ }
+ }
+ }
+#else
+ if (endofbuffer) {
+ GC_PRINTK(NULL, "message buffer full; "
+ "forcing message flush.\n\n");
+ gc_buffer_flush(NULL, buffout);
+ }
+#endif
+
+ item = (struct itemhead *) &buffout->buffer[buffout->index];
+
+ buffout->index += size;
+ buffout->count += 1;
+
+ next = (struct itemhead *) ((unsigned char *) item + size);
+ next->type = GC_BUFITEM_NONE;
+
+ return item;
+}
+
+static void gc_append_string(struct buffout *buffout,
+ struct itemstring *itemstring)
+{
+ unsigned char *messagedata;
+ struct itemstring *item;
+ unsigned int alignment;
+ int size, freesize;
+ int allocsize;
+
+ /* Determine the maximum item size. */
+ allocsize = sizeof(struct itemstring) + itemstring->datasize
+ + GC_VARARG_ALIGNMENT;
+
+ /* Allocate the item. */
+ item = (struct itemstring *) gc_allocate_item(buffout, allocsize);
+ GC_DEBUGMSG("allocated %d bytes @ 0x%08X.\n",
+ allocsize, (unsigned int) item);
+
+ /* Compute the initial message data pointer. */
+ messagedata = (unsigned char *) (item + 1);
+
+ /* Align the data pointer as necessary. */
+ alignment = GC_PTRALIGNMENT(messagedata, GC_VARARG_ALIGNMENT);
+ messagedata += alignment;
+ GC_DEBUGMSG("messagedata @ 0x%08X.\n", (unsigned int) messagedata);
+
+ /* Set item data. */
+ item->itemtype = GC_BUFITEM_STRING;
+ item->indent = itemstring->indent;
+ item->message = itemstring->message;
+ item->messagedata = *(va_list *) &messagedata;
+ item->datasize = itemstring->datasize;
+
+#if GC_SHOW_TIME
+ item->timestamp = itemstring->timestamp;
+#endif
+
+#if GC_SHOW_DUMP_LINE
+ item->dumpline = itemstring->dumpline;
+#endif
+
+#if GC_SHOW_PID
+ item->task = itemstring->task;
+#endif
+
+ /* Copy argument value. */
+ if (itemstring->datasize != 0) {
+ GC_DEBUGMSG("copying %d bytes of messagedata.\n",
+ itemstring->datasize);
+ memcpy(messagedata,
+ *(unsigned char **) &itemstring->messagedata,
+ itemstring->datasize);
+ }
+
+ /* Compute the actual node size. */
+ size = sizeof(struct itemstring) + itemstring->datasize + alignment;
+ GC_DEBUGMSG("adjusted item size=%d.\n", size);
+
+ /* Free extra memory if any. */
+ freesize = allocsize - size;
+ GC_DEBUGMSG("freesize=%d.\n", freesize);
+
+ if (freesize != 0) {
+ struct itemhead *next;
+ buffout->index -= freesize;
+ next = (struct itemhead *) ((unsigned char *) item + size);
+ next->type = GC_BUFITEM_NONE;
+ }
+
+#if GC_BUFFERED_OUTPUT && GC_FLUSH_COUNT
+ if (buffout->count >= GC_FLUSH_COUNT) {
+ GC_PRINTK(NULL, "reached %d message count; "
+ "forcing message flush.\n\n", buffout->count);
+ gc_buffer_flush(NULL, buffout);
+ }
+#endif
+}
+
+static void gc_append_buffer(struct gcmmucontext *gcmmucontext,
+ struct buffout *buffout,
+ struct itembuffer *itembuffer,
+ unsigned int *data)
+{
+ struct itembuffer *item;
+ int allocsize;
+
+ /* Determine the item size. */
+ allocsize = sizeof(struct itembuffer) + itembuffer->datasize;
+
+ /* Allocate the item. */
+ item = (struct itembuffer *) gc_allocate_item(buffout, allocsize);
+ GC_DEBUGMSG("allocated %d bytes @ 0x%08X.\n",
+ allocsize, (unsigned int) item);
+
+ /* Set item data. */
+ *item = *itembuffer;
+
+ /* Copy data. */
+ if (data != NULL) {
+ memcpy(item + 1, data, itembuffer->datasize);
+ } else {
+ switch (itembuffer->buffertype) {
+ case GC_BUFTYPE_GENERIC:
+ case GC_BUFTYPE_COMMAND:
+ gc_copy_generic_buffer(gcmmucontext, item + 1,
+ itembuffer);
+ break;
+
+ case GC_BUFTYPE_SURFACE:
+ gc_copy_surface(gcmmucontext, item + 1, itembuffer);
+ break;
+ }
+ }
+
+#if GC_BUFFERED_OUTPUT && GC_FLUSH_COUNT
+ if (buffout->count >= GC_FLUSH_COUNT) {
+ GC_PRINTK(NULL, "reached %d message count; "
+ "forcing message flush.\n\n", buffout->count);
+ gc_buffer_flush(NULL, buffout);
+ }
+#endif
+}
+#endif
+
+static void gc_print(struct buffout *buffout, unsigned int argsize,
+ const char *message, va_list args)
+{
+ struct itemstring itemstring;
+ struct threadinfo *threadinfo;
+
+ mutex_lock(&g_lockmutex);
+
+ /* Locate thead entry. */
+ threadinfo = get_threadinfo(buffout);
+
+ /* Form the indent string. */
+ if (strncmp(message, "--", 2) == 0)
+ threadinfo->msgindent -= 2;
+
+ /* Fill in the sructure. */
+ itemstring.itemtype = GC_BUFITEM_STRING;
+ itemstring.indent = threadinfo->msgindent
+ + threadinfo->threadindent;
+ itemstring.message = message;
+ itemstring.messagedata = args;
+ itemstring.datasize = argsize;
+
+#if GC_SHOW_TIME
+ ktime_get_ts(&itemstring.timestamp);
+#endif
+
+#if GC_SHOW_DUMP_LINE
+ itemstring.dumpline = ++buffout->dumpline;
+#endif
+
+#if GC_SHOW_PID
+ itemstring.task = threadinfo->task;
+#endif
+
+ /* Print the message. */
+#if GC_BUFFERED_OUTPUT
+ gc_append_string(buffout, &itemstring);
+#else
+ gc_print_string(NULL, &itemstring);
+#endif
+
+ /* Check increasing indent. */
+ if (strncmp(message, "++", 2) == 0)
+ threadinfo->msgindent += 2;
+
+ mutex_unlock(&g_lockmutex);
+}
+
+
+/*******************************************************************************
+ * Dumping functions.
+ */
+
+void gc_dump_string(struct gcdbgfilter *filter, unsigned int zone,
+ const char *message, ...)
+{
+ va_list args;
+ unsigned int i, count, argsize;
+
+ if (!g_outputbuffer.enable)
+ return;
+
+ if (message == NULL)
+ GC_DEBUGMSG("message is NULL.\n");
+
+ if (GC_VERIFY_ENABLE(filter, zone)) {
+ for (i = 0, count = 0; message[i]; i += 1)
+ if (message[i] == '%')
+ count += 1;
+
+ argsize = count * sizeof(unsigned int);
+ GC_DEBUGMSG("argsize=%d.\n", argsize);
+
+ va_start(args, message);
+ gc_print(&g_outputbuffer, argsize, message, args);
+ va_end(args);
+ }
+}
+EXPORT_SYMBOL(gc_dump_string);
+
+void gc_dump_string_sized(struct gcdbgfilter *filter, unsigned int zone,
+ unsigned int argsize, const char *message, ...)
+{
+ va_list args;
+
+ if (!g_outputbuffer.enable)
+ return;
+
+ if (GC_VERIFY_ENABLE(filter, zone)) {
+ va_start(args, message);
+ gc_print(&g_outputbuffer, argsize, message, args);
+ va_end(args);
+ }
+}
+EXPORT_SYMBOL(gc_dump_string_sized);
+
+void gc_dump_cmd_buffer(struct gcdbgfilter *filter, unsigned int zone,
+ void *ptr, unsigned int gpuaddr, unsigned int datasize)
+{
+ struct itembuffer itembuffer;
+ struct threadinfo *threadinfo;
+
+ if (!g_outputbuffer.enable)
+ return;
+
+ if (GC_VERIFY_ENABLE(filter, zone)) {
+ mutex_lock(&g_lockmutex);
+
+ /* Locate thead entry. */
+ threadinfo = get_threadinfo(&g_outputbuffer);
+
+ /* Fill in the sructure. */
+ itembuffer.itemtype = GC_BUFITEM_BUFFER;
+ itembuffer.buffertype = GC_BUFTYPE_COMMAND;
+ itembuffer.indent = threadinfo->msgindent
+ + threadinfo->threadindent;
+ itembuffer.datasize = datasize;
+ itembuffer.gpuaddr = gpuaddr;
+
+ /* Print the message. */
+#if GC_BUFFERED_OUTPUT
+ gc_append_buffer(NULL, &g_outputbuffer, &itembuffer,
+ (unsigned int *) ptr);
+#else
+ gc_print_buffer(NULL, &itembuffer,
+ (unsigned char *) ptr);
+#endif
+
+ mutex_unlock(&g_lockmutex);
+ }
+}
+EXPORT_SYMBOL(gc_dump_cmd_buffer);
+
+void gc_dump_buffer(struct gcdbgfilter *filter, unsigned int zone,
+ void *ptr, unsigned int gpuaddr,
+ unsigned int datasize)
+{
+ struct itembuffer itembuffer;
+ struct threadinfo *threadinfo;
+
+ if (!g_outputbuffer.enable)
+ return;
+
+ if (GC_VERIFY_ENABLE(filter, zone)) {
+ mutex_lock(&g_lockmutex);
+
+ /* Locate thead entry. */
+ threadinfo = get_threadinfo(&g_outputbuffer);
+
+ /* Fill in the sructure. */
+ itembuffer.itemtype = GC_BUFITEM_BUFFER;
+ itembuffer.buffertype = GC_BUFTYPE_GENERIC;
+ itembuffer.indent = threadinfo->msgindent
+ + threadinfo->threadindent;
+ itembuffer.datasize = datasize;
+ itembuffer.gpuaddr = gpuaddr;
+
+ /* Print the message. */
+#if GC_BUFFERED_OUTPUT
+ gc_append_buffer(NULL, &g_outputbuffer, &itembuffer,
+ (unsigned int *) ptr);
+#else
+ gc_print_buffer(NULL, &itembuffer,
+ (unsigned char *) ptr);
+#endif
+
+ mutex_unlock(&g_lockmutex);
+ }
+}
+EXPORT_SYMBOL(gc_dump_buffer);
+
+void gc_dump_phys_buffer(struct gcdbgfilter *filter, unsigned int zone,
+ struct gcmmucontext *gcmmucontext,
+ unsigned int gpuaddr,
+ unsigned int datasize)
+{
+ struct itembuffer itembuffer;
+ struct threadinfo *threadinfo;
+
+#if !GC_BUFFERED_OUTPUT
+ void *data;
+#endif
+
+ if (!g_outputbuffer.enable)
+ return;
+
+ if (GC_VERIFY_ENABLE(filter, zone)) {
+ mutex_lock(&g_lockmutex);
+
+ /* Locate thead entry. */
+ threadinfo = get_threadinfo(&g_outputbuffer);
+
+ /* Fill in the sructure. */
+ itembuffer.itemtype = GC_BUFITEM_BUFFER;
+ itembuffer.buffertype = GC_BUFTYPE_GENERIC;
+ itembuffer.indent = threadinfo->msgindent
+ + threadinfo->threadindent;
+ itembuffer.datasize = datasize;
+ itembuffer.gpuaddr = gpuaddr;
+
+ /* Print the message. */
+#if GC_BUFFERED_OUTPUT
+ gc_append_buffer(gcmmucontext, &g_outputbuffer,
+ &itembuffer, NULL);
+#else
+ data = kmalloc(datasize, GFP_KERNEL);
+ if (data != NULL) {
+ gc_copy_generic_buffer(gcmmucontext, data, &itembuffer);
+ gc_print_buffer(NULL, &itembuffer,
+ (unsigned char *) data);
+ kfree(data);
+ }
+#endif
+
+ mutex_unlock(&g_lockmutex);
+ }
+}
+EXPORT_SYMBOL(gc_dump_phys_buffer);
+
+void gc_dump_surface(struct gcdbgfilter *filter, unsigned int zone,
+ void *ptr, unsigned int surfwidth,
+ unsigned int surfheight, unsigned int surfbpp,
+ unsigned int x1, unsigned int y1,
+ unsigned int x2, unsigned int y2,
+ unsigned int gpuaddr)
+{
+ struct itembuffer itembuffer;
+ struct threadinfo *threadinfo;
+ unsigned int datasize;
+
+ if (!g_outputbuffer.enable)
+ return;
+
+ if (GC_VERIFY_ENABLE(filter, zone)) {
+ mutex_lock(&g_lockmutex);
+
+ /* Locate thead entry. */
+ threadinfo = get_threadinfo(&g_outputbuffer);
+
+ /* Compute data size. */
+ datasize = (x2 - x1) * (y2 - y1) * surfbpp;
+
+ /* Fill in the sructure. */
+ itembuffer.itemtype = GC_BUFITEM_BUFFER;
+ itembuffer.buffertype = GC_BUFTYPE_SURFACE;
+ itembuffer.indent = threadinfo->msgindent
+ + threadinfo->threadindent;
+ itembuffer.surfwidth = surfwidth;
+ itembuffer.surfheight = surfheight;
+ itembuffer.surfbpp = surfbpp;
+ itembuffer.x1 = x1;
+ itembuffer.y1 = y1;
+ itembuffer.x2 = x2;
+ itembuffer.y2 = y2;
+ itembuffer.datasize = datasize;
+ itembuffer.gpuaddr = gpuaddr;
+
+ /* Print the message. */
+#if GC_BUFFERED_OUTPUT
+ gc_append_buffer(NULL, &g_outputbuffer, &itembuffer,
+ (unsigned int *) ptr);
+#else
+ gc_print_buffer(NULL, &itembuffer,
+ (unsigned char *) ptr);
+#endif
+
+ mutex_unlock(&g_lockmutex);
+ }
+}
+EXPORT_SYMBOL(gc_dump_surface);
+
+void gc_dump_phys_surface(struct gcdbgfilter *filter, unsigned int zone,
+ struct gcmmucontext *gcmmucontext,
+ unsigned int surfwidth, unsigned int surfheight,
+ unsigned int surfbpp,
+ unsigned int x1, unsigned int y1,
+ unsigned int x2, unsigned int y2,
+ unsigned int gpuaddr)
+{
+ struct itembuffer itembuffer;
+ struct threadinfo *threadinfo;
+ unsigned int datasize;
+
+#if !GC_BUFFERED_OUTPUT
+ void *data;
+#endif
+
+ if (!g_outputbuffer.enable)
+ return;
+
+ if (GC_VERIFY_ENABLE(filter, zone)) {
+ mutex_lock(&g_lockmutex);
+
+ /* Locate thead entry. */
+ threadinfo = get_threadinfo(&g_outputbuffer);
+
+ /* Compute data size. */
+ datasize = (x2 - x1) * (y2 - y1) * surfbpp;
+
+ /* Fill in the sructure. */
+ itembuffer.itemtype = GC_BUFITEM_BUFFER;
+ itembuffer.buffertype = GC_BUFTYPE_SURFACE;
+ itembuffer.indent = threadinfo->msgindent
+ + threadinfo->threadindent;
+ itembuffer.surfwidth = surfwidth;
+ itembuffer.surfheight = surfheight;
+ itembuffer.surfbpp = surfbpp;
+ itembuffer.x1 = x1;
+ itembuffer.y1 = y1;
+ itembuffer.x2 = x2;
+ itembuffer.y2 = y2;
+ itembuffer.datasize = datasize;
+ itembuffer.gpuaddr = gpuaddr;
+
+ /* Print the message. */
+#if GC_BUFFERED_OUTPUT
+ gc_append_buffer(gcmmucontext, &g_outputbuffer,
+ &itembuffer, NULL);
+#else
+ data = kmalloc(datasize, GFP_KERNEL);
+ if (data != NULL) {
+ gc_copy_surface(gcmmucontext, data, &itembuffer);
+ gc_print_buffer(NULL, &itembuffer,
+ (unsigned char *) data);
+ kfree(data);
+ }
+#endif
+
+ mutex_unlock(&g_lockmutex);
+ }
+}
+EXPORT_SYMBOL(gc_dump_phys_surface);
+
+
+/*******************************************************************************
+ * MMU dumping functions.
+ */
+
+struct gcmmuentry {
+ unsigned int entry;
+ bool exception;
+ bool present;
+
+ union {
+ struct gcmmumaster {
+ unsigned int slaveaddr;
+ unsigned int pagesize;
+ } mtlb;
+
+ struct gcmmuslave {
+ unsigned int pageaddr;
+ bool writable;
+ } stlb;
+ } u;
+};
+
+typedef void (*pfn_get_entry) (unsigned int entry,
+ struct gcmmuentry *gcmmuentry);
+typedef void (*pfn_print_entry) (struct gcdbgfilter *filter,
+ unsigned int zone,
+ unsigned int index,
+ struct gcmmuentry *gcmmuentry);
+
+struct gcmmutable {
+ char *name;
+ bool master;
+ unsigned int entry_count;
+ unsigned int vacant_entry;
+ pfn_get_entry get_entry;
+ pfn_print_entry print_entry;
+};
+
+static void get_mtlb_entry(unsigned int entry,
+ struct gcmmuentry *gcmmuentry)
+{
+ static const unsigned int pagesize[] = {
+ 1024 * 4,
+ 1024 * 64,
+ 1024 * 1024,
+ 1024 * 1024 * 16
+ };
+
+ gcmmuentry->entry = entry;
+ gcmmuentry->exception = ((entry & GCMMU_MTLB_EXCEPTION_MASK) != 0);
+ gcmmuentry->present = ((entry & GCMMU_MTLB_PRESENT_MASK) != 0);
+ gcmmuentry->u.mtlb.slaveaddr = entry & GCMMU_MTLB_SLAVE_MASK;
+ gcmmuentry->u.mtlb.pagesize =
+ pagesize[(entry & GCMMU_MTLB_PAGE_SIZE_MASK) >> 2];
+}
+
+static void get_stlb_entry(unsigned int entry,
+ struct gcmmuentry *gcmmuentry)
+{
+ gcmmuentry->entry = entry;
+ gcmmuentry->exception = ((entry & GCMMU_STLB_EXCEPTION_MASK) != 0);
+ gcmmuentry->present = ((entry & GCMMU_STLB_PRESENT_MASK) != 0);
+ gcmmuentry->u.stlb.pageaddr = entry & GCMMU_STLB_ADDRESS_MASK;
+ gcmmuentry->u.stlb.writable =
+ ((entry & GCMMU_STLB_WRITEABLE_MASK) != 0);
+}
+
+static void print_mtlb_entry(struct gcdbgfilter *filter,
+ unsigned int zone,
+ unsigned int index,
+ struct gcmmuentry *gcmmuentry)
+{
+ gc_dump_string(filter, zone,
+ " entry[%04d]: 0x%08X "
+ "(stlbaddr=0x%08X, pagesize=%d, "
+ "exception=%d, present=%d)\n",
+ index, gcmmuentry->entry,
+ gcmmuentry->u.mtlb.slaveaddr,
+ gcmmuentry->u.mtlb.pagesize,
+ gcmmuentry->exception,
+ gcmmuentry->present);
+}
+
+static void print_stlb_entry(struct gcdbgfilter *filter,
+ unsigned int zone,
+ unsigned int index,
+ struct gcmmuentry *gcmmuentry)
+{
+ gc_dump_string(filter, zone,
+ " entry[%04d]: 0x%08X "
+ "(pageaddr=0x%08X, writable=%d, "
+ "exception=%d, present=%d)\n",
+ index, gcmmuentry->entry,
+ gcmmuentry->u.stlb.pageaddr,
+ gcmmuentry->u.stlb.writable,
+ gcmmuentry->exception,
+ gcmmuentry->present);
+}
+
+static void finalize_vacant(struct gcdbgfilter *filter, unsigned int zone,
+ int index, int *vacant, int skipped)
+{
+ if (*vacant == -1)
+ return;
+
+ skipped = index - *vacant;
+ *vacant = -1;
+ gc_dump_string(filter, zone, "%15cskipped %d vacant entries\n",
+ ' ', skipped);
+}
+
+static void finalize_allocated(struct gcdbgfilter *filter, unsigned int zone,
+ int index, int *allocated, int skipped,
+ struct gcmmuentry *gcmmuentry,
+ unsigned int pagesize)
+{
+ unsigned int start, end;
+ int i;
+
+ if (*allocated == -1)
+ return;
+
+ skipped = index - *allocated;
+ *allocated = -1;
+ start = gcmmuentry->u.stlb.pageaddr - skipped * pagesize;
+ end = gcmmuentry->u.stlb.pageaddr + pagesize;
+
+ if (skipped > 5) {
+ gc_dump_string(filter, zone,
+ "%15cskipped %d allocated entries\n",
+ ' ', skipped);
+ gc_dump_string(filter, zone,
+ "%17callocated address range 0x%08X - 0x%08X\n",
+ ' ', start, end);
+ gc_dump_string(filter, zone,
+ "%17ctotal pages = %d\n",
+ ' ', skipped + 1);
+ gc_dump_string(filter, zone,
+ "%17ctotal buffer size = %d\n",
+ ' ', (skipped + 1) * pagesize);
+ } else {
+ gcmmuentry->u.stlb.pageaddr = start + pagesize;
+ gcmmuentry->entry = (start + pagesize)
+ & GCMMU_STLB_ADDRESS_MASK;
+
+ if (gcmmuentry->u.stlb.writable)
+ gcmmuentry->entry |= GCMMU_STLB_WRITEABLE_MASK;
+
+ if (gcmmuentry->exception)
+ gcmmuentry->entry |= GCMMU_STLB_EXCEPTION_MASK;
+
+ if (gcmmuentry->present)
+ gcmmuentry->entry |= GCMMU_STLB_PRESENT_MASK;
+
+ for (i = 0; i < skipped; i += 1) {
+ print_stlb_entry(filter, zone, index - skipped + i,
+ gcmmuentry);
+ gcmmuentry->u.stlb.pageaddr += pagesize;
+ }
+ }
+}
+
+static void dump_mmu_table(struct gcdbgfilter *filter, unsigned int zone,
+ struct gcmmutable *desc, unsigned int physical,
+ unsigned int *logical, unsigned int pagesize)
+{
+ int vacant, allocated, skipped = 0;
+ bool sequential;
+ unsigned int entry, i;
+ struct gcmmuentry prev;
+ struct gcmmuentry curr;
+
+ gc_dump_string(filter, zone, "%s table:\n", desc->name);
+ gc_dump_string(filter, zone, " physical=0x%08X\n", physical);
+
+ vacant = -1;
+ allocated = -1;
+ curr.present = false;
+
+ for (i = 0; i < desc->entry_count; i += 1) {
+ entry = logical[i];
+ prev = curr;
+ desc->get_entry(entry, &curr);
+
+ if (!curr.present) {
+ finalize_allocated(filter, zone,
+ i, &allocated, skipped,
+ &prev, pagesize);
+
+ if (entry == desc->vacant_entry) {
+ if (vacant == -1)
+ vacant = i;
+ } else {
+ finalize_vacant(filter, zone,
+ i, &vacant, skipped);
+
+ gc_dump_string(filter, zone,
+ " entry[%03d]: "
+ "invalid entry (0x%08X)\n",
+ i, entry);
+ }
+
+ continue;
+ }
+
+ finalize_vacant(filter, zone, i, &vacant, skipped);
+
+ sequential
+ = (!desc->master
+ && (curr.present == prev.present)
+ && (curr.exception == prev.exception)
+ && (curr.u.stlb.writable == prev.u.stlb.writable)
+ && (curr.u.stlb.pageaddr == prev.u.stlb.pageaddr
+ + pagesize));
+
+ if (sequential) {
+ if (allocated == -1)
+ allocated = i;
+
+ continue;
+ }
+
+ finalize_allocated(filter, zone, i, &allocated, skipped,
+ &prev, pagesize);
+
+ desc->print_entry(filter, zone, i, &curr);
+ }
+
+ finalize_vacant(filter, zone, i, &vacant, skipped);
+ finalize_allocated(filter, zone, i, &allocated, skipped,
+ &prev, pagesize);
+}
+
+void gc_dump_mmu(struct gcdbgfilter *filter, unsigned int zone,
+ struct gcmmucontext *gcmmucontext)
+{
+ static struct gcmmutable mtlb_desc = {
+ "Master",
+ true,
+ GCMMU_MTLB_ENTRY_NUM,
+ GCMMU_MTLB_ENTRY_VACANT,
+ get_mtlb_entry,
+ print_mtlb_entry
+ };
+
+ static struct gcmmutable stlb_desc = {
+ "Slave",
+ false,
+ GCMMU_STLB_ENTRY_NUM,
+ GCMMU_STLB_ENTRY_VACANT,
+ get_stlb_entry,
+ print_stlb_entry
+ };
+
+ unsigned int i;
+ struct gcmmuentry master;
+
+ GCDUMPARENAS(zone, "vacant arenas", &gcmmucontext->vacant);
+ GCDUMPARENAS(zone, "allocated arenas", &gcmmucontext->allocated);
+
+ gc_dump_string(filter, zone,
+ "*** MMU DUMP ***\n");
+
+ dump_mmu_table(filter, zone, &mtlb_desc,
+ gcmmucontext->master.physical,
+ gcmmucontext->master.logical, 0);
+
+ for (i = 0; i < GCMMU_MTLB_ENTRY_NUM; i += 1) {
+ if (gcmmucontext->slave[i].logical == NULL)
+ continue;
+
+ get_mtlb_entry(gcmmucontext->master.logical[i], &master);
+ dump_mmu_table(filter, zone, &stlb_desc,
+ gcmmucontext->slave[i].physical,
+ gcmmucontext->slave[i].logical,
+ master.u.mtlb.pagesize);
+ }
+}
+EXPORT_SYMBOL(gc_dump_mmu);
+
+
+/*******************************************************************************
+ * Dumping control functions.
+ */
+
+void gc_dump_enable(void)
+{
+ mutex_lock(&g_lockmutex);
+
+ g_outputbuffer.enable = 1;
+ GC_PRINTK(NULL, "gcx dumping is enabled.\n");
+
+ mutex_unlock(&g_lockmutex);
+}
+EXPORT_SYMBOL(gc_dump_enable);
+
+void gc_dump_disable(void)
+{
+ mutex_lock(&g_lockmutex);
+
+ g_outputbuffer.enable = 0;
+ GC_PRINTK(NULL, "gcx dumping is disabled.\n");
+
+ mutex_unlock(&g_lockmutex);
+}
+EXPORT_SYMBOL(gc_dump_disable);
+
+void gc_dump_show_enabled(struct seq_file *s)
+{
+ struct list_head *filterhead;
+ struct gcdbgfilter *filter;
+ unsigned int i, zone;
+
+ mutex_lock(&g_lockmutex);
+
+ GC_PRINTK(s, "gcx logging is %s\n", g_outputbuffer.enable
+ ? "enabled" : "disabled");
+
+ list_for_each(filterhead, &gc_filterlist) {
+ filter = list_entry(filterhead, struct gcdbgfilter,
+ link);
+
+ GC_PRINTK(s, "gcx filter '%s':\n", filter->filtername);
+ GC_PRINTK(s, " zone mask = 0x%08X%s\n", filter->zone,
+ (filter->zone == 0)
+ ? " (all disabled)" : "");
+
+ for (i = 0; filter->zonename[i] != NULL; i++) {
+ zone = 1 << i;
+ GC_PRINTK(s, " 0x%08X: %10s%s\n",
+ zone, filter->zonename[i],
+ ((filter->zone & zone) != 0)
+ ? " (enabled)" : "");
+ }
+ }
+
+ mutex_unlock(&g_lockmutex);
+}
+EXPORT_SYMBOL(gc_dump_show_enabled);
+
+void gc_dump_filter_enable(const char *filtername, int zone)
+{
+ struct list_head *filterhead;
+ struct gcdbgfilter *filter;
+ bool filterfound = false;
+ bool havesetzones = false;
+
+ mutex_lock(&g_lockmutex);
+
+ GC_PRINTK(NULL, "modifying zone mask for filter %s:\n", filtername);
+
+ list_for_each(filterhead, &gc_filterlist) {
+ filter = list_entry(filterhead, struct gcdbgfilter,
+ link);
+
+ if (strcasecmp(filtername, filter->filtername) == 0) {
+ GC_PRINTK(NULL, " 0x%08X --> 0x%08X\n",
+ filter->zone, zone);
+ filter->zone = zone;
+ filterfound = true;
+ }
+
+ if (filter->zone != 0)
+ havesetzones = true;
+ }
+
+ mutex_unlock(&g_lockmutex);
+
+ if (!filterfound)
+ GC_PRINTK(NULL, " couldn't find filter %s.\n", filtername);
+
+ if (havesetzones && !g_outputbuffer.enable)
+ gc_dump_enable();
+ else if (!havesetzones && g_outputbuffer.enable)
+ gc_dump_disable();
+}
+EXPORT_SYMBOL(gc_dump_filter_enable);
+
+void gc_dbg_add_client(struct gcdbgfilter *filter)
+{
+ list_add(&filter->link, &gc_filterlist);
+}
+EXPORT_SYMBOL(gc_dbg_add_client);
+
+void gc_dump_flush(struct seq_file *s)
+{
+#if GC_BUFFERED_OUTPUT
+ mutex_lock(&g_lockmutex);
+
+ /*
+ * Not dumping through debugfs for now because we have
+ * too much data and it'd require us to implement the
+ * seq_file iterator interface.
+ */
+ gc_buffer_flush(NULL, &g_outputbuffer);
+
+ mutex_unlock(&g_lockmutex);
+#endif
+}
+EXPORT_SYMBOL(gc_dump_flush);
+
+void gc_dump_reset(void)
+{
+#if GC_BUFFERED_OUTPUT
+ mutex_lock(&g_lockmutex);
+
+ g_outputbuffer.start = 0;
+ g_outputbuffer.index = 0;
+ g_outputbuffer.count = 0;
+
+ GC_PRINTK(NULL, "gcx logging buffer is reset.\n");
+
+ mutex_unlock(&g_lockmutex);
+#endif
+}
+EXPORT_SYMBOL(gc_dump_reset);
+
+
+/*******************************************************************************
+ * Command buffer parser.
+ */
+
+int gc_parse_command_buffer(unsigned int *buffer, unsigned int size,
+ struct gccommandinfo *info)
+{
+ int res;
+ unsigned int i, j, itemcount, index, oldsrc;
+ unsigned int command, count, addr;
+
+ memset(info, 0, sizeof(struct gccommandinfo));
+ info->command = ~0U;
+
+ oldsrc = 0;
+
+ itemcount = (size + 3) / 4;
+ for (i = 0; i < itemcount;) {
+ command = (buffer[i] >> 27) & 0x1F;
+
+ switch (command) {
+ case GCREG_COMMAND_OPCODE_LOAD_STATE:
+ count = (buffer[i] >> 16) & 0x3F;
+ addr = buffer[i] & 0xFFFF;
+ i += 1;
+
+ for (j = 0; j < count; j += 1) {
+ switch (addr) {
+ case gcregDestAddressRegAddrs:
+ info->dst.surf.address = buffer[i];
+ break;
+
+ case gcregDestStrideRegAddrs:
+ info->dst.surf.stride = buffer[i];
+ break;
+
+ case gcregDestRotationConfigRegAddrs:
+ info->dst.surf.width
+ = buffer[i] & 0xFFFF;
+ break;
+
+ case gcregDstRotationHeightRegAddrs:
+ info->dst.surf.height
+ = buffer[i] & 0xFFFF;
+ break;
+
+ case gcregDestConfigRegAddrs:
+ info->command
+ = (buffer[i] >> 12) & 0xF;
+
+ info->dst.surf.swizzle
+ = (buffer[i] >> 16) & 0x3;
+
+ info->dst.surf.format
+ = buffer[i] & 0x1F;
+
+ info->dst.surf.bpp = gc_get_bpp(
+ info->dst.surf.format);
+ break;
+
+ case gcregSrcAddressRegAddrs:
+ info->src[0].surf.address = buffer[i];
+ oldsrc = 1;
+ break;
+
+ case gcregSrcStrideRegAddrs:
+ info->src[0].surf.stride = buffer[i];
+ break;
+
+ case gcregSrcRotationConfigRegAddrs:
+ info->src[0].surf.width
+ = buffer[i] & 0xFFFF;
+ break;
+
+ case gcregSrcRotationHeightRegAddrs:
+ info->src[0].surf.height
+ = buffer[i] & 0xFFFF;
+ break;
+
+ case gcregSrcConfigRegAddrs:
+ info->src[0].surf.swizzle
+ = (buffer[i] >> 20) & 0x3;
+
+ info->src[0].surf.format
+ = (buffer[i] >> 24) & 0x1F;
+
+ info->src[0].surf.bpp = gc_get_bpp(
+ info->src[0].surf.format);
+ break;
+
+ case gcregSrcOriginRegAddrs:
+ info->src[0].rect.left
+ = buffer[i] & 0xFFFF;
+
+ info->src[0].rect.top
+ = (buffer[i] >> 16) & 0xFFFF;
+ break;
+
+ case gcregSrcSizeRegAddrs:
+ info->src[0].rect.right
+ = buffer[i] & 0xFFFF;
+
+ info->src[0].rect.bottom
+ = (buffer[i] >> 16) & 0xFFFF;
+ break;
+
+ case gcregBlock4SrcAddressRegAddrs:
+ case gcregBlock4SrcAddressRegAddrs + 1:
+ case gcregBlock4SrcAddressRegAddrs + 2:
+ case gcregBlock4SrcAddressRegAddrs + 3:
+ index = addr & 3;
+ info->src[index].surf.address
+ = buffer[i];
+ break;
+
+ case gcregBlock4SrcStrideRegAddrs:
+ case gcregBlock4SrcStrideRegAddrs + 1:
+ case gcregBlock4SrcStrideRegAddrs + 2:
+ case gcregBlock4SrcStrideRegAddrs + 3:
+ index = addr & 3;
+ info->src[index].surf.stride
+ = buffer[i];
+ break;
+
+ case gcregBlock4SrcRotationConfigRegAddrs:
+ case gcregBlock4SrcRotationConfigRegAddrs + 1:
+ case gcregBlock4SrcRotationConfigRegAddrs + 2:
+ case gcregBlock4SrcRotationConfigRegAddrs + 3:
+ index = addr & 3;
+ info->src[index].surf.width
+ = buffer[i] & 0xFFFF;
+ break;
+
+ case gcregBlock4SrcRotationHeightRegAddrs:
+ case gcregBlock4SrcRotationHeightRegAddrs + 1:
+ case gcregBlock4SrcRotationHeightRegAddrs + 2:
+ case gcregBlock4SrcRotationHeightRegAddrs + 3:
+ index = addr & 3;
+ info->src[0].surf.height
+ = buffer[i] & 0xFFFF;
+ break;
+
+ case gcregBlock4SrcConfigRegAddrs:
+ case gcregBlock4SrcConfigRegAddrs + 1:
+ case gcregBlock4SrcConfigRegAddrs + 2:
+ case gcregBlock4SrcConfigRegAddrs + 3:
+ index = addr & 3;
+ info->src[index].surf.swizzle
+ = (buffer[i] >> 20) & 0x3;
+
+ info->src[index].surf.format
+ = (buffer[i] >> 24) & 0x1F;
+
+ info->src[index].surf.bpp = gc_get_bpp(
+ info->src[index].surf.format);
+ break;
+
+ case gcregBlock4SrcOriginRegAddrs:
+ case gcregBlock4SrcOriginRegAddrs + 1:
+ case gcregBlock4SrcOriginRegAddrs + 2:
+ case gcregBlock4SrcOriginRegAddrs + 3:
+ index = addr & 3;
+ info->src[index].rect.left
+ = buffer[i] & 0xFFFF;
+
+ info->src[index].rect.top
+ = (buffer[i] >> 16) & 0xFFFF;
+ break;
+
+ case gcregBlock4SrcSizeRegAddrs:
+ case gcregBlock4SrcSizeRegAddrs + 1:
+ case gcregBlock4SrcSizeRegAddrs + 2:
+ case gcregBlock4SrcSizeRegAddrs + 3:
+ index = addr & 3;
+ info->src[index].rect.right
+ = buffer[i] & 0xFFFF;
+
+ info->src[index].rect.bottom
+ = (buffer[i] >> 16) & 0xFFFF;
+ break;
+
+ case gcregDEMultiSourceRegAddrs:
+ info->srccount = (buffer[i] & 0x7) + 1;
+ break;
+ }
+
+ addr += 1;
+ i += 1;
+ }
+
+ i += ((~count) & 1);
+ break;
+
+ case GCREG_COMMAND_OPCODE_END:
+ case GCREG_COMMAND_OPCODE_NOP:
+ case GCREG_COMMAND_OPCODE_WAIT:
+ case GCREG_COMMAND_OPCODE_LINK:
+ case GCREG_COMMAND_OPCODE_STALL:
+ i += 2;
+ break;
+
+ case GCREG_COMMAND_OPCODE_STARTDE:
+ info->dst.rectcount = (buffer[i] >> 8) & 0xFF;
+ i += 2;
+
+ for (j = 0; j < info->dst.rectcount; j += 1) {
+ info->dst.rect[j].left
+ = buffer[i] & 0xFFFF;
+ info->dst.rect[j].top
+ = (buffer[i] >> 16) & 0xFFFF;
+ i += 1;
+
+ info->dst.rect[j].right
+ = buffer[i] & 0xFFFF;
+ info->dst.rect[j].bottom
+ = (buffer[i] >> 16) & 0xFFFF;
+ i += 1;
+ }
+ break;
+
+ default:
+ res = 0;
+ gc_dump_string(NULL, 0,
+ "bad command (%d) "
+ "while parsing the command stream",
+ command);
+ goto exit;
+ }
+
+ }
+
+ /* Enable old source. */
+ if ((info->srccount == 0) && oldsrc)
+ info->srccount = 1;
+
+ /* Success. */
+ res = 1;
+
+exit:
+ return res;
+}
+EXPORT_SYMBOL(gc_parse_command_buffer);
+
+/*******************************************************************************
+ * Bltsville debugging.
+ */
+
+char *gc_bvblend_name(enum bvblend blend)
+{
+ switch (blend) {
+ case BVBLEND_CLEAR: return "BVBLEND_CLEAR";
+ case BVBLEND_SRC1: return "BVBLEND_SRC1";
+ case BVBLEND_SRC2: return "BVBLEND_SRC2";
+ case BVBLEND_SRC1OVER: return "BVBLEND_SRC1OVER";
+ case BVBLEND_SRC2OVER: return "BVBLEND_SRC2OVER";
+ case BVBLEND_SRC1IN: return "BVBLEND_SRC1IN";
+ case BVBLEND_SRC2IN: return "BVBLEND_SRC2IN";
+ case BVBLEND_SRC1OUT: return "BVBLEND_SRC1OUT";
+ case BVBLEND_SRC2OUT: return "BVBLEND_SRC2OUT";
+ case BVBLEND_SRC1ATOP: return "BVBLEND_SRC1ATOP";
+ case BVBLEND_SRC2ATOP: return "BVBLEND_SRC2ATOP";
+ case BVBLEND_XOR: return "BVBLEND_XOR";
+ case BVBLEND_PLUS: return "BVBLEND_PLUS";
+ case BVBLEND_NORMAL: return "BVBLEND_NORMAL";
+ case BVBLEND_LIGHTEN: return "BVBLEND_LIGHTEN";
+ case BVBLEND_DARKEN: return "BVBLEND_DARKEN";
+ case BVBLEND_MULTIPLY: return "BVBLEND_MULTIPLY";
+ case BVBLEND_AVERAGE: return "BVBLEND_AVERAGE";
+ case BVBLEND_ADD: return "BVBLEND_ADD";
+ case BVBLEND_SUBTRACT: return "BVBLEND_SUBTRACT";
+ case BVBLEND_DIFFERENCE: return "BVBLEND_DIFFERENCE";
+ case BVBLEND_NEGATE: return "BVBLEND_NEGATE";
+ case BVBLEND_SCREEN: return "BVBLEND_SCREEN";
+ case BVBLEND_EXCLUSION: return "BVBLEND_EXCLUSION";
+ case BVBLEND_OVERLAY: return "BVBLEND_OVERLAY";
+ case BVBLEND_SOFT_LIGHT: return "BVBLEND_SOFT_LIGHT";
+ case BVBLEND_HARD_LIGHT: return "BVBLEND_HARD_LIGHT";
+ case BVBLEND_COLOR_DODGE: return "BVBLEND_COLOR_DODGE";
+ case BVBLEND_COLOR_BURN: return "BVBLEND_COLOR_BURN";
+ case BVBLEND_LINEAR_LIGHT: return "BVBLEND_LINEAR_LIGHT";
+ case BVBLEND_VIVID_LIGHT: return "BVBLEND_VIVID_LIGHT";
+ case BVBLEND_PIN_LIGHT: return "BVBLEND_PIN_LIGHT";
+ case BVBLEND_HARD_MIX: return "BVBLEND_HARD_MIX";
+ case BVBLEND_REFLECT: return "BVBLEND_REFLECT";
+ case BVBLEND_GLOW: return "BVBLEND_GLOW";
+ case BVBLEND_PHOENIX: return "BVBLEND_PHOENIX";
+ default: return "[UNKNOWN]";
+ }
+}
+EXPORT_SYMBOL(gc_bvblend_name);
+
+
+/*******************************************************************************
+ * Initialization/cleanup.
+ */
+
+void gcdbg_init(void)
+{
+#if GC_BUFFERED_OUTPUT
+ /* Allocate the debug buffer. */
+ g_outputbuffer.buffer = kmalloc(GC_DUMP_BUFFER_SIZE, GFP_KERNEL);
+ if (g_outputbuffer.buffer == NULL) {
+ GC_PRINTK(NULL, "failed to allocate dump buffer.\n");
+ return;
+ }
+#endif
+
+ g_initdone = true;
+}
+
+void gcdbg_exit(void)
+{
+#if GC_BUFFERED_OUTPUT
+ if (g_outputbuffer.buffer != NULL) {
+ kfree(g_outputbuffer.buffer);
+ g_outputbuffer.buffer = NULL;
+ }
+#endif
+
+ g_initdone = false;
+}
+
+#endif /* GCDEBUG_ENABLE */
diff --git a/drivers/misc/gcx/gccore/gcdebug.c b/drivers/misc/gcx/gccore/gcdebug.c
--- /dev/null
@@ -0,0 +1,555 @@
+/*
+ * gcdebug.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/gcx.h>
+#include <linux/gccore.h>
+#include "gcmain.h"
+
+#define MMU_UNITS 4
+#define MMU_ERROR(irq_ack) ((irq_ack & 0x40000000) != 0)
+
+#if GCDEBUG_ENABLE
+#define STATUS_DUMP(s, msg, ...) \
+ do { \
+ if (s) \
+ seq_printf(s, msg, __VA_ARGS__); \
+ else \
+ gc_dump_string(NULL, 0, msg, __VA_ARGS__); \
+ } while (0)
+#else
+#define STATUS_DUMP(s, msg, ...) \
+ do { \
+ if (s) \
+ seq_printf(s, msg, __VA_ARGS__); \
+ else \
+ printk(KERN_ERR msg, __VA_ARGS__); \
+ } while (0)
+#endif
+
+enum gc_debug_when {
+ GC_DEBUG_USER_REQUEST,
+ GC_DEBUG_DRIVER_POWEROFF,
+ GC_DEBUG_DRIVER_IRQ,
+ GC_DEBUG_DRIVER_REQUEST,
+};
+
+struct gc_gpu_id {
+ bool valid;
+ unsigned int chipModel;
+ unsigned int chipRevision;
+ unsigned int chipDate;
+ unsigned int chipTime;
+ unsigned int chipFeatures;
+ unsigned int chipMinorFeatures;
+};
+
+static struct gc_gpu_id g_gcGpuId;
+static struct dentry *debug_root;
+
+void gc_debug_cache_gpu_id(void)
+{
+ if (g_gcGpuId.valid) {
+ /* only cached once */
+ return;
+ }
+
+ g_gcGpuId.chipModel = gc_read_reg(GC_CHIP_ID_Address);
+ g_gcGpuId.chipRevision = gc_read_reg(GC_CHIP_REV_Address);
+ g_gcGpuId.chipDate = gc_read_reg(GC_CHIP_DATE_Address);
+ g_gcGpuId.chipTime = gc_read_reg(GC_CHIP_TIME_Address);
+ g_gcGpuId.chipFeatures = gc_read_reg(GC_FEATURES_Address);
+ g_gcGpuId.chipMinorFeatures = gc_read_reg(GC_FEATURES0_Address);
+ g_gcGpuId.valid = 1;
+}
+
+static int gc_debug_show_gpu_id(struct seq_file *s, void *unused)
+{
+ if (!g_gcGpuId.valid) {
+ seq_printf(s, "GC gpu id cache not valid. "
+ "GC must be powered on once.\n");
+ return 0;
+ }
+
+ seq_printf(s, "model=%X\n", g_gcGpuId.chipModel);
+ seq_printf(s, "revision=%X\n", g_gcGpuId.chipRevision);
+ seq_printf(s, "date=%X\n", g_gcGpuId.chipDate);
+ seq_printf(s, "time=%X\n", g_gcGpuId.chipTime);
+ seq_printf(s, "chipFeatures=0x%08X\n", g_gcGpuId.chipFeatures);
+
+ return 0;
+}
+
+static int gc_debug_open_gpu_id(struct inode *inode, struct file *file)
+{
+ return single_open(file, gc_debug_show_gpu_id, inode->i_private);
+}
+
+static const struct file_operations gc_debug_fops_gpu_id = {
+ .open = gc_debug_open_gpu_id,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+struct gc_gpu_status {
+ bool valid;
+ bool dma_addr_changing;
+ const char *name;
+ unsigned int idle;
+ unsigned int dma_state;
+ unsigned int dma_addr;
+ unsigned int dma_low_data;
+ unsigned int dma_high_data;
+ unsigned int total_reads;
+ unsigned int total_writes;
+ unsigned int total_read_bursts;
+ unsigned int total_write_bursts;
+ unsigned int total_read_reqs;
+ unsigned int total_write_reqs;
+ unsigned int irq_acknowledge;
+ unsigned int mmu_status;
+ unsigned int exception_address[MMU_UNITS];
+};
+
+enum gc_debug_when gc_gpu_status_when;
+
+struct gc_gpu_status gc_gpu_status = {
+ .name = "GPU status"
+};
+struct gc_gpu_status gc_gpu_status_last_error = {
+ .name = "GPU last error status"
+};
+
+/* By default we don't cache the status on every irq */
+static int gc_cache_status_every_irq;
+
+
+static bool gc_dma_addr_changing(void)
+{
+ static const unsigned int detectcount = 1000;
+ unsigned int address1, address2;
+ unsigned int i;
+
+ address1 = gc_read_reg(GCREG_FE_DEBUG_CUR_CMD_ADR_Address);
+ for (i = 0; i < detectcount; i += 1) {
+ address2 = gc_read_reg(GCREG_FE_DEBUG_CUR_CMD_ADR_Address);
+ if (address1 != address2)
+ break;
+ }
+
+ return i < detectcount;
+}
+
+void gc_debug_cache_gpu_status(
+ struct gc_gpu_status *status,
+ unsigned int acknowledge)
+{
+ int i;
+
+ if (!status) {
+ status = &gc_gpu_status;
+ gc_gpu_status_when = GC_DEBUG_DRIVER_REQUEST;
+ }
+
+ status->dma_addr_changing = gc_dma_addr_changing();
+
+ status->idle =
+ gc_read_reg(GCREG_HI_IDLE_Address);
+ status->dma_state =
+ gc_read_reg(GCREG_FE_DEBUG_STATE_Address);
+ status->dma_addr =
+ gc_read_reg(GCREG_FE_DEBUG_CUR_CMD_ADR_Address);
+ status->dma_low_data =
+ gc_read_reg(GCREG_FE_DEBUG_CMD_LOW_REG_Address);
+ status->dma_high_data =
+ gc_read_reg(GCREG_FE_DEBUG_CMD_HI_REG_Address);
+ status->total_reads =
+ gc_read_reg(GC_TOTAL_READS_Address);
+ status->total_writes =
+ gc_read_reg(GC_TOTAL_WRITES_Address);
+ status->total_read_bursts =
+ gc_read_reg(GC_TOTAL_READ_BURSTS_Address);
+ status->total_write_bursts =
+ gc_read_reg(GC_TOTAL_WRITE_BURSTS_Address);
+ status->total_read_reqs =
+ gc_read_reg(GC_TOTAL_READ_REQS_Address);
+ status->total_write_reqs =
+ gc_read_reg(GC_TOTAL_WRITE_REQS_Address);
+ status->irq_acknowledge = acknowledge;
+
+ /* Is it valid/useful to read the mmu registers for
+ * other error conditions? */
+ if (MMU_ERROR(acknowledge)) {
+ status->mmu_status =
+ gc_read_reg(GCREG_MMU_STATUS_Address);
+
+ for (i = 0; i < MMU_UNITS; i++)
+ status->exception_address[i] =
+ gc_read_reg(GCREG_MMU_EXCEPTION_Address + i);
+ } else {
+ status->mmu_status = 0;
+
+ for (i = 0; i < MMU_UNITS; i++)
+ status->exception_address[i] = 0;
+ }
+
+ status->valid = true;
+}
+
+void gc_debug_cache_gpu_status_from_irq(unsigned int acknowledge)
+{
+ bool haveError = (acknowledge & 0xC0000000) != 0;
+
+ if (!gc_cache_status_every_irq && !haveError) {
+ /* called from irq, no error, not caching every irq */
+ return;
+ }
+
+ gc_debug_cache_gpu_status(&gc_gpu_status, acknowledge);
+ gc_gpu_status_when = GC_DEBUG_DRIVER_IRQ;
+
+ if (haveError)
+ memcpy(&gc_gpu_status_last_error, &gc_gpu_status,
+ sizeof(struct gc_gpu_status));
+}
+
+static const char *gc_power_string(enum gcpower power)
+{
+ switch (power) {
+ case GCPWR_UNKNOWN:
+ return "GCPWR_UNKNOWN";
+ case GCPWR_OFF:
+ return "GCPWR_OFF";
+ case GCPWR_ON:
+ return "GCPWR_ON";
+ case GCPWR_LOW:
+ return "GCPWR_LOW";
+ }
+
+ return "unknown";
+}
+
+static const char *gc_when_string(enum gc_debug_when when)
+{
+ switch (when) {
+ case GC_DEBUG_USER_REQUEST:
+ return "GC_DEBUG_USER_REQUEST";
+ case GC_DEBUG_DRIVER_POWEROFF:
+ return "GC_DEBUG_DRIVER_POWEROFF";
+ case GC_DEBUG_DRIVER_REQUEST:
+ return "GC_DEBUG_DRIVER_REQUEST";
+ case GC_DEBUG_DRIVER_IRQ:
+ return "GC_DEBUG_DRIVER_IRQ";
+ }
+
+ return "unknown";
+}
+
+
+static void gc_dump_status_internal(struct seq_file *s,
+ struct gc_gpu_status *status)
+{
+ if (!status->valid) {
+ STATUS_DUMP(s, "%s: not valid.\n", status->name);
+ return;
+ }
+
+ STATUS_DUMP(s, " idle = 0x%08X\n", status->idle);
+ STATUS_DUMP(s, " DMA state = 0x%08X\n", status->dma_state);
+ STATUS_DUMP(s, " DMA address = 0x%08X (%s)\n", status->dma_addr,
+ status->dma_addr_changing ? "running" : "not running");
+ STATUS_DUMP(s, " DMA low data = 0x%08X\n", status->dma_low_data);
+ STATUS_DUMP(s, " DMA high data = 0x%08X\n", status->dma_high_data);
+ STATUS_DUMP(s, " Total memory reads = %d\n", status->total_reads);
+ STATUS_DUMP(s, " Total memory writes = %d\n", status->total_writes);
+ STATUS_DUMP(s, " Total memory read 64-bit bursts = %d\n",
+ status->total_read_bursts);
+ STATUS_DUMP(s, " Total memory write 64-bit bursts = %d\n",
+ status->total_write_bursts);
+ STATUS_DUMP(s, " Total memory read requests = %d\n",
+ status->total_read_reqs);
+ STATUS_DUMP(s, " Total memory write requests = %d\n",
+ status->total_write_reqs);
+
+ if (MMU_ERROR(status->irq_acknowledge)) {
+ int i;
+
+ STATUS_DUMP(s, "mmu status = 0x%08X\n", status->mmu_status);
+
+ for (i = 0; i < MMU_UNITS; i++)
+ STATUS_DUMP(s, "exception address %d = 0x%08X\n",
+ i, status->exception_address[i]);
+ }
+}
+
+void gc_debug_dump_status(const char *function, int line)
+{
+ STATUS_DUMP(NULL, "Current GC gpu status requested from %s(%d).\n",
+ function, line);
+
+ gc_debug_cache_gpu_status(&gc_gpu_status, 0);
+ gc_gpu_status_when = GC_DEBUG_DRIVER_REQUEST;
+
+ gc_dump_status_internal(NULL, &gc_gpu_status);
+
+ GCDBG_FLUSHDUMP(NULL);
+}
+
+static int gc_debug_show_gpu_status(struct seq_file *s, void *data)
+{
+ const char *powerString = gc_power_string(gcpwr_get());
+
+ struct gc_gpu_status *status = (struct gc_gpu_status *)s->private;
+
+ if (!status) {
+ printk(KERN_ERR "%s: null status\n", __func__);
+ return 0;
+ }
+
+ seq_printf(s, "GC gpu current power status: %s\n", powerString);
+
+ if (gcpwr_get() == GCPWR_ON) {
+ /* update the gpu status now */
+ gc_debug_cache_gpu_status(&gc_gpu_status, 0);
+ gc_gpu_status_when = GC_DEBUG_USER_REQUEST;
+ }
+
+ seq_printf(s, "%s: cached at: %s\n", status->name,
+ gc_when_string(gc_gpu_status_when));
+
+ gc_dump_status_internal(s, status);
+
+ return 0;
+}
+
+static int gc_debug_open_gpu_status(struct inode *inode, struct file *file)
+{
+ return single_open(file, gc_debug_show_gpu_status, &gc_gpu_status);
+}
+
+static const struct file_operations gc_debug_fops_gpu_status = {
+ .open = gc_debug_open_gpu_status,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int gc_debug_open_gpu_last_error(struct inode *inode, struct file *file)
+{
+ return single_open(file,
+ gc_debug_show_gpu_status,
+ &gc_gpu_status_last_error);
+}
+
+static const struct file_operations gc_debug_fops_gpu_last_error = {
+ .open = gc_debug_open_gpu_last_error,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*****************************************************************************/
+
+static int gc_debug_show_log_dump(struct seq_file *s, void *data)
+{
+ GCDBG_FLUSHDUMP(s);
+ return 0;
+}
+
+static int gc_debug_open_log_dump(struct inode *inode, struct file *file)
+{
+ return single_open(file, gc_debug_show_log_dump, 0);
+}
+
+static const struct file_operations gc_debug_fops_log_dump = {
+ .open = gc_debug_open_log_dump,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*****************************************************************************/
+
+static int gc_debug_show_log_enable(struct seq_file *s, void *data)
+{
+ GCDBG_SHOWENABLED(s);
+ return 0;
+}
+
+static int gc_debug_open_log_enable(struct inode *inode, struct file *file)
+{
+ return single_open(file, gc_debug_show_log_enable, 0);
+}
+
+static ssize_t gc_debug_write_log_enable(
+ struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char buf[256];
+ size_t len;
+ unsigned long val;
+ int ret;
+ char *name = 0;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret < 0) {
+ int i;
+ for (i = 0; i < len - 1; i++) {
+ if (buf[i] == ' ') {
+ buf[i] = 0;
+
+ ret = kstrtoul(&buf[i+1], 0, &val);
+ if (ret < 0)
+ return -EINVAL;
+
+ name = &buf[0];
+ break;
+ }
+ }
+
+ if (!name)
+ return -EINVAL;
+ }
+
+ if (name)
+ GCDBG_SETFILTER(name, val);
+ else if (val)
+ GCDBG_ENABLEDUMP();
+ else
+ GCDBG_DISABLEDUMP();
+
+ return count;
+}
+
+static const struct file_operations gc_debug_fops_log_enable = {
+ .open = gc_debug_open_log_enable,
+ .write = gc_debug_write_log_enable,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*****************************************************************************/
+
+static int gc_debug_show_log_reset(struct seq_file *s, void *data)
+{
+ GCDBG_RESETDUMP();
+ return 0;
+}
+
+static int gc_debug_open_log_reset(struct inode *inode, struct file *file)
+{
+ return single_open(file, gc_debug_show_log_reset, 0);
+}
+
+static ssize_t gc_debug_write_log_reset(
+ struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ GCDBG_RESETDUMP();
+ return count;
+}
+
+static const struct file_operations gc_debug_fops_log_reset = {
+ .open = gc_debug_open_log_reset,
+ .write = gc_debug_write_log_reset,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*****************************************************************************/
+
+static int gc_debug_show_cur_freq(struct seq_file *s, void *data)
+{
+ unsigned mhz = gcpwr_get_speed();
+ if (mhz)
+ seq_printf(s, "cur freq: %d mhz\n", mhz);
+ else
+ seq_printf(s, "unable to read cur freq\n");
+
+ return 0;
+}
+
+static int gc_debug_open_cur_freq(struct inode *inode, struct file *file)
+{
+ return single_open(file, gc_debug_show_cur_freq, 0);
+}
+
+static const struct file_operations gc_debug_fops_cur_freq = {
+ .open = gc_debug_open_cur_freq,
+ .write = NULL,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*****************************************************************************/
+
+void gc_debug_init(void)
+{
+ struct dentry *logDir;
+
+ debug_root = debugfs_create_dir("gcx", NULL);
+ if (!debug_root)
+ return;
+
+ debugfs_create_file("id", 0664, debug_root, NULL,
+ &gc_debug_fops_gpu_id);
+ debugfs_create_file("status", 0664, debug_root, NULL,
+ &gc_debug_fops_gpu_status);
+ debugfs_create_file("last_error", 0664, debug_root, NULL,
+ &gc_debug_fops_gpu_last_error);
+ debugfs_create_bool("cache_status_every_irq", 0664, debug_root,
+ &gc_cache_status_every_irq);
+ debugfs_create_file("cur_freq", 0664, debug_root, NULL,
+ &gc_debug_fops_cur_freq);
+
+ logDir = debugfs_create_dir("log", debug_root);
+ if (!logDir)
+ return;
+
+ debugfs_create_file("enable", 0664, logDir, NULL,
+ &gc_debug_fops_log_enable);
+ debugfs_create_file("reset", 0664, logDir, NULL,
+ &gc_debug_fops_log_reset);
+ debugfs_create_file("dump", 0664, logDir, NULL,
+ &gc_debug_fops_log_dump);
+}
+
+void gc_debug_shutdown(void)
+{
+ if (debug_root)
+ debugfs_remove_recursive(debug_root);
+}
+
+/* called just BEFORE powering off */
+void gc_debug_poweroff_cache(void)
+{
+ /* gpu id is read only once */
+ gc_debug_cache_gpu_id();
+}
diff --git a/drivers/misc/gcx/gccore/gcmain.c b/drivers/misc/gcx/gccore/gcmain.c
--- /dev/null
@@ -0,0 +1,1119 @@
+/*
+ * gcmain.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/opp.h>
+#include <linux/io.h>
+#include <linux/platform_data/omap_gcx.h>
+#include "gcmain.h"
+
+
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_INIT (1 << 0)
+#define GCZONE_CONTEXT (1 << 1)
+#define GCZONE_POWER (1 << 2)
+#define GCZONE_COMMIT (1 << 3)
+#define GCZONE_MAPPING (1 << 4)
+#define GCZONE_PROBE (1 << 5)
+#define GCZONE_CALLBACK (1 << 6)
+#define GCZONE_FREQSCALE (1 << 7)
+
+GCDBG_FILTERDEF(core, GCZONE_NONE,
+ "init",
+ "context",
+ "power",
+ "commit",
+ "mapping",
+ "probe",
+ "callback",
+ "freqscale")
+
+
+#if !defined(GC_ENABLE_SUSPEND)
+#define GC_ENABLE_SUSPEND 1
+#endif
+
+#if !defined(CONFIG_HAS_EARLYSUSPEND)
+#define CONFIG_HAS_EARLYSUSPEND 0
+#endif
+
+/* Driver private data. */
+static struct gccorecontext g_context;
+
+
+/*******************************************************************************
+ * Context management.
+ */
+
+static enum gcerror find_context(struct gccorecontext *gccorecontext,
+ bool fromuser,
+ struct gcmmucontext **gcmmucontext)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct list_head *ctxhead;
+ struct gcmmucontext *temp = NULL;
+ pid_t pid;
+
+ GCENTER(GCZONE_CONTEXT);
+
+ /* Get current PID. */
+ pid = fromuser ? current->tgid : 0;
+
+ /* Search the list. */
+ GCDBG(GCZONE_CONTEXT, "scanning context records for pid %d.\n", pid);
+
+ /* Try to locate the record. */
+ list_for_each(ctxhead, &gccorecontext->mmuctxlist) {
+ temp = list_entry(ctxhead, struct gcmmucontext, link);
+ if (temp->pid == pid) {
+ /* Success. */
+ GCDBG(GCZONE_CONTEXT, "context is found @ 0x%08X\n",
+ (unsigned int) temp);
+
+ goto exit;
+ }
+ }
+
+ /* Get new record. */
+ if (list_empty(&gccorecontext->mmuctxvac)) {
+ GCDBG(GCZONE_CONTEXT, "not found, allocating.\n");
+
+ temp = kmalloc(sizeof(struct gcmmucontext), GFP_KERNEL);
+ if (temp == NULL) {
+ GCERR("out of memory.\n");
+ gcerror = GCERR_SETGRP(GCERR_OODM,
+ GCERR_IOCTL_CTX_ALLOC);
+ goto fail;
+ }
+
+ GCDBG(GCZONE_CONTEXT, "allocated @ 0x%08X\n",
+ (unsigned int) temp);
+ } else {
+ ctxhead = gccorecontext->mmuctxvac.next;
+ temp = list_entry(ctxhead, struct gcmmucontext, link);
+ list_del(ctxhead);
+
+ GCDBG(GCZONE_CONTEXT, "not found, reusing vacant @ 0x%08X\n",
+ (unsigned int) temp);
+ }
+
+ gcerror = gcmmu_create_context(gccorecontext, temp, pid);
+ if (gcerror != GCERR_NONE)
+ goto fail;
+
+ /* Add the context to the list. */
+ list_add(&temp->link, &gccorecontext->mmuctxlist);
+
+exit:
+ *gcmmucontext = temp;
+
+ GCEXIT(GCZONE_CONTEXT);
+ return GCERR_NONE;
+
+fail:
+ if (temp != NULL) {
+ gcmmu_destroy_context(gccorecontext, temp);
+ list_add(&temp->link, &gccorecontext->mmuctxvac);
+ }
+
+ GCEXITARG(GCZONE_CONTEXT, "gcerror = 0x%08X\n", gcerror);
+ return gcerror;
+}
+
+static void destroy_mmu_context(struct gccorecontext *gccorecontext)
+{
+ struct list_head *head;
+ struct gcmmucontext *temp;
+
+ /* Free vacant entry list. */
+ while (!list_empty(&gccorecontext->mmuctxvac)) {
+ head = gccorecontext->mmuctxvac.next;
+ temp = list_entry(head, struct gcmmucontext, link);
+ list_del(head);
+ kfree(temp);
+ }
+
+ /* Free active contexts. */
+ while (!list_empty(&gccorecontext->mmuctxlist)) {
+ head = gccorecontext->mmuctxlist.next;
+ temp = list_entry(head, struct gcmmucontext, link);
+ gcmmu_destroy_context(gccorecontext, temp);
+ list_del(head);
+ kfree(temp);
+ }
+}
+
+struct device *gc_get_dev(void)
+{
+ return g_context.device;
+}
+EXPORT_SYMBOL(gc_get_dev);
+
+
+/*******************************************************************************
+** Register access.
+*/
+
+unsigned int gc_read_reg(unsigned int address)
+{
+ return readl((unsigned char *) g_context.regbase + address);
+}
+
+void gc_write_reg(unsigned int address, unsigned int data)
+{
+ writel(data, (unsigned char *) g_context.regbase + address);
+}
+
+
+/*******************************************************************************
+ * Power management.
+ */
+
+static void gcpwr_enable_clock(struct gccorecontext *gccorecontext)
+{
+ int ctxlost;
+
+ GCENTER(GCZONE_POWER);
+
+ ctxlost = gccorecontext->plat->get_context_loss_count(gccorecontext->device);
+ GCDBG(GCZONE_POWER, "lost count = %d\n", ctxlost);
+
+ if (!gccorecontext->clockenabled) {
+ /* Enable the clock. */
+ pm_runtime_get_sync(gccorecontext->device);
+
+ /* Signal software not idle. */
+ gc_write_reg(GC_GP_OUT0_Address, 0);
+
+ /* Clock enabled. */
+ gccorecontext->clockenabled = true;
+ } else if (ctxlost) {
+ GCDBG(GCZONE_POWER, "hardware context lost.\n");
+ if (gc_read_reg(GC_GP_OUT0_Address)) {
+ GCDBG(GCZONE_POWER, "reset idle register.\n");
+ gc_write_reg(GC_GP_OUT0_Address, 0);
+ }
+ }
+
+ GCDBG(GCZONE_POWER, "clock %s.\n",
+ gccorecontext->clockenabled ? "enabled" : "disabled");
+
+ if (ctxlost || (gccorecontext->gcpower == GCPWR_UNKNOWN))
+ gcpwr_reset(gccorecontext);
+
+
+ GCEXIT(GCZONE_POWER);
+}
+
+static void gcpwr_disable_clock(struct gccorecontext *gccorecontext)
+{
+ GCENTER(GCZONE_POWER);
+
+ if (gccorecontext->clockenabled) {
+ gc_debug_poweroff_cache();
+
+ /* Signal software idle. */
+ gc_write_reg(GC_GP_OUT0_Address, 1);
+
+ /* Disable the clock. */
+ pm_runtime_put_sync(gccorecontext->device);
+
+ /* Clock disabled. */
+ gccorecontext->clockenabled = false;
+
+ /* Reset the current pipe. */
+ gccorecontext->gcpipe = GCPWR_UNKNOWN;
+ }
+
+ GCDBG(GCZONE_POWER, "clock %s.\n",
+ gccorecontext->clockenabled ? "enabled" : "disabled");
+
+ GCEXIT(GCZONE_POWER);
+}
+
+static void gcpwr_scale(struct gccorecontext *gccorecontext, int index)
+{
+ int ret;
+
+ GCENTERARG(GCZONE_FREQSCALE, "index=%d\n", index);
+
+ if (gccorecontext->opp_count == 0)
+ goto exit;
+
+ if ((index < 0) || (index >= gccorecontext->opp_count)) {
+ GCERR("invalid index %d.\n", index);
+ goto exit;
+ }
+
+ if ((gccorecontext->plat == NULL) ||
+ (gccorecontext->plat->scale_dev == NULL)) {
+ GCERR("scale interface is not initialized.\n");
+ goto exit;
+ }
+
+
+ if (gccorecontext->cur_freq == gccorecontext->opp_freqs[index])
+ goto exit;
+
+ ret = gccorecontext->plat->scale_dev(gccorecontext->bb2ddevice,
+ gccorecontext->opp_freqs[index]);
+ if (ret != 0) {
+ GCERR("failed to scale the device.\n");
+ goto exit;
+ }
+
+ gccorecontext->cur_freq = gccorecontext->opp_freqs[index];
+ GCDBG(GCZONE_FREQSCALE, "frequency set to %dMHz\n",
+ gccorecontext->cur_freq / 1000 / 1000);
+
+exit:
+ GCEXIT(GCZONE_FREQSCALE);
+}
+
+static void gcpwr_set_pulse_skipping(unsigned int pulsecount)
+{
+ union gcclockcontrol gcclockcontrol;
+
+ GCENTER(GCZONE_POWER);
+
+ /* Set the pulse skip value. */
+ gcclockcontrol.raw = 0;
+ gcclockcontrol.reg.pulsecount = pulsecount;
+
+ /* Initiate loading. */
+ gcclockcontrol.reg.pulseset = 1;
+ GCDBG(GCZONE_POWER, "pulse skip = 0x%08X\n", gcclockcontrol.raw);
+ gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address, gcclockcontrol.raw);
+
+ /* Lock the value. */
+ gcclockcontrol.reg.pulseset = 0;
+ GCDBG(GCZONE_POWER, "pulse skip = 0x%08X\n", gcclockcontrol.raw);
+ gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address, gcclockcontrol.raw);
+
+ GCEXIT(GCZONE_POWER);
+}
+
+static void gcpwr_enable_pulse_skipping(struct gccorecontext *gccorecontext)
+{
+ GCENTER(GCZONE_POWER);
+
+ if (!gccorecontext->clockenabled)
+ goto exit;
+
+ if (gccorecontext->pulseskipping != 1) {
+ /* Set the lowest frequency. */
+ gcpwr_scale(gccorecontext, 0);
+
+ /* Set 1 clock pulse for every 64 clocks. */
+ gcpwr_set_pulse_skipping(1);
+
+ /* Pulse skipping enabled. */
+ gccorecontext->pulseskipping = 1;
+ }
+
+ GCDBG(GCZONE_POWER, "pulse skipping %s.\n",
+ gccorecontext->pulseskipping ? "enabled" : "disabled");
+
+exit:
+ GCEXIT(GCZONE_POWER);
+}
+
+static void gcpwr_disable_pulse_skipping(struct gccorecontext *gccorecontext)
+{
+ GCENTER(GCZONE_POWER);
+
+ if (!gccorecontext->clockenabled)
+ goto exit;
+
+ if (gccorecontext->pulseskipping != 0) {
+ /* Set the maximum frequency. */
+ gcpwr_scale(gccorecontext, gccorecontext->opp_count - 1);
+
+ /* Set full speed. */
+ gcpwr_set_pulse_skipping(64);
+
+ /* Pulse skipping disabled. */
+ gccorecontext->pulseskipping = 0;
+ }
+
+ GCDBG(GCZONE_POWER, "pulse skipping %s.\n",
+ gccorecontext->pulseskipping ? "enabled" : "disabled");
+
+exit:
+ GCEXIT(GCZONE_POWER);
+}
+
+void gcpwr_set(struct gccorecontext *gccorecontext, enum gcpower gcpower)
+{
+ GCENTER(GCZONE_POWER);
+
+ GCLOCK(&gccorecontext->powerlock);
+
+ if (gcpower != gccorecontext->gcpower) {
+ switch (gcpower) {
+ case GCPWR_ON:
+ gcpwr_enable_clock(gccorecontext);
+ gcpwr_disable_pulse_skipping(gccorecontext);
+ break;
+
+ case GCPWR_LOW:
+ gcpwr_enable_clock(gccorecontext);
+ gcpwr_enable_pulse_skipping(gccorecontext);
+ break;
+
+ case GCPWR_OFF:
+ gcpwr_enable_pulse_skipping(gccorecontext);
+ gcpwr_disable_clock(gccorecontext);
+ break;
+
+ default:
+ GCERR("unsupported power mode %d.\n", gcpower);
+ goto exit;
+ }
+
+ GCDBG(GCZONE_POWER, "power state %d --> %d\n",
+ gccorecontext->gcpower, gcpower);
+
+ /* Set new power state. */
+ gccorecontext->gcpower = gcpower;
+ }
+
+exit:
+ GCUNLOCK(&gccorecontext->powerlock);
+
+ GCEXIT(GCZONE_POWER);
+}
+
+enum gcpower gcpwr_get(void)
+{
+ return g_context.gcpower;
+}
+
+void gcpwr_reset(struct gccorecontext *gccorecontext)
+{
+ union gcclockcontrol gcclockcontrol;
+ union gcidle gcidle;
+
+ GCENTER(GCZONE_POWER);
+
+ GCLOCK(&gccorecontext->resetlock);
+
+ /* Read current clock control value. */
+ gcclockcontrol.raw
+ = gc_read_reg(GCREG_HI_CLOCK_CONTROL_Address);
+
+ while (true) {
+ /* Isolate the GPU. */
+ gcclockcontrol.reg.isolate = 1;
+ gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address,
+ gcclockcontrol.raw);
+
+ /* Set soft reset. */
+ gcclockcontrol.reg.reset = 1;
+ gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address,
+ gcclockcontrol.raw);
+
+ /* Wait for reset. */
+ msleep(1);
+
+ /* Reset soft reset bit. */
+ gcclockcontrol.reg.reset = 0;
+ gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address,
+ gcclockcontrol.raw);
+
+ /* Reset GPU isolation. */
+ gcclockcontrol.reg.isolate = 0;
+ gc_write_reg(GCREG_HI_CLOCK_CONTROL_Address,
+ gcclockcontrol.raw);
+
+ /* Read idle register. */
+ gcidle.raw = gc_read_reg(GCREG_HI_IDLE_Address);
+
+ /* Try resetting again if FE not idle. */
+ if (!gcidle.reg.fe) {
+ GCERR("FE NOT IDLE\n");
+ continue;
+ }
+
+ /* Read reset register. */
+ gcclockcontrol.raw
+ = gc_read_reg(GCREG_HI_CLOCK_CONTROL_Address);
+
+ /* Try resetting again if 2D is not idle. */
+ if (!gcclockcontrol.reg.idle2d) {
+ GCERR("2D NOT IDLE\n");
+ continue;
+ }
+
+ /* GPU is idle. */
+ break;
+ }
+
+ /* Pulse skipping disabled. */
+ gccorecontext->pulseskipping = false;
+
+ GCUNLOCK(&gccorecontext->resetlock);
+
+ GCEXIT(GCZONE_POWER);
+}
+
+unsigned int gcpwr_get_speed(void)
+{
+ struct gccorecontext *gccorecontext = &g_context;
+ static const int seccount = 2;
+ unsigned int cyclecount;
+ unsigned int speedmhz = 0;
+
+ GCLOCK(&gccorecontext->powerlock);
+
+ if (gccorecontext->gcpower == GCPWR_ON) {
+ /* Reset cycle counter and sleep. */
+ gc_write_reg(GC_TOTAL_CYCLES_Address, 0);
+ msleep(seccount * 1000);
+
+ /* Read the cycle counter and compute the speed. */
+ cyclecount = gc_read_reg(GC_TOTAL_CYCLES_Address);
+ speedmhz = cyclecount / 1000 / 1000 / seccount;
+ }
+
+ GCUNLOCK(&gccorecontext->powerlock);
+
+ return speedmhz;
+}
+
+/*******************************************************************************
+ * Public API.
+ */
+
+bool gc_is_hw_present(void)
+{
+ struct gccorecontext *gccorecontext = &g_context;
+ return gccorecontext->plat->is_hw_present;
+}
+
+
+void gc_caps(struct gcicaps *gcicaps)
+{
+ struct gccorecontext *gccorecontext = &g_context;
+
+ /* Copy capabilities. */
+ gcicaps->gcmodel = gccorecontext->gcmodel;
+ gcicaps->gcrevision = gccorecontext->gcrevision;
+ gcicaps->gcdate = gccorecontext->gcdate;
+ gcicaps->gctime = gccorecontext->gctime;
+ gcicaps->gcfeatures = gccorecontext->gcfeatures;
+ gcicaps->gcfeatures0 = gccorecontext->gcfeatures0;
+ gcicaps->gcfeatures1 = gccorecontext->gcfeatures1;
+ gcicaps->gcfeatures2 = gccorecontext->gcfeatures2;
+ gcicaps->gcfeatures3 = gccorecontext->gcfeatures3;
+
+ /* Success. */
+ gcicaps->gcerror = GCERR_NONE;
+}
+
+void gc_commit(struct gcicommit *gcicommit, bool fromuser)
+{
+ struct gccorecontext *gccorecontext = &g_context;
+ struct gcmmucontext *gcmmucontext;
+ struct gcbuffer *gcbuffer;
+ unsigned int buffersize;
+ unsigned int *logical;
+ unsigned int address;
+ struct gcmopipesel *gcmopipesel;
+ struct gcschedunmap *gcschedunmap;
+ struct list_head *head;
+
+ GCENTER(GCZONE_COMMIT);
+
+ GCLOCK(&gccorecontext->mmucontextlock);
+
+ /* Validate pipe values. */
+ if ((gcicommit->entrypipe != GCPIPE_2D) &&
+ (gcicommit->entrypipe != GCPIPE_3D)) {
+ gcicommit->gcerror = GCERR_CMD_ENTRY_PIPE;
+ goto exit;
+ }
+
+ if ((gcicommit->exitpipe != GCPIPE_2D) &&
+ (gcicommit->exitpipe != GCPIPE_3D)) {
+ gcicommit->gcerror = GCERR_CMD_EXIT_PIPE;
+ goto exit;
+ }
+
+ /* Locate the client entry. */
+ gcicommit->gcerror = find_context(gccorecontext, fromuser,
+ &gcmmucontext);
+ if (gcicommit->gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Set the master table. */
+ gcicommit->gcerror = gcmmu_set_master(gccorecontext, gcmmucontext);
+ if (gcicommit->gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Set the correct graphics pipe. */
+ if (gccorecontext->gcpipe != gcicommit->entrypipe) {
+ static struct gcregpipeselect gcregpipeselect[] = {
+ /* GCPIPE_UNKNOWN */
+ { 0, 0 },
+
+ /* GCPIPE_2D */
+ { GCREG_PIPE_SELECT_PIPE_PIPE2D, 0 },
+
+ /* GCPIPE_2D */
+ { GCREG_PIPE_SELECT_PIPE_PIPE2D, 0 }
+ };
+
+ GCDBG(GCZONE_COMMIT, "allocating space for pipe switch.\n");
+ gcicommit->gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+ sizeof(struct gcmopipesel),
+ (void **) &gcmopipesel, NULL);
+ if (gcicommit->gcerror != GCERR_NONE)
+ goto exit;
+
+ gcmopipesel->pipesel_ldst = gcmopipesel_pipesel_ldst;
+ gcmopipesel->pipesel.reg
+ = gcregpipeselect[gcicommit->entrypipe];
+ }
+
+ /* Update the current pipe. */
+ gccorecontext->gcpipe = gcicommit->exitpipe;
+
+ /* Go through all buffers one at a time. */
+ list_for_each(head, &gcicommit->buffer) {
+ gcbuffer = list_entry(head, struct gcbuffer, link);
+ GCDBG(GCZONE_COMMIT, "gcbuffer = 0x%08X\n",
+ (unsigned int) gcbuffer);
+
+ /* Flush MMU. */
+ gcmmu_flush(gccorecontext, gcmmucontext);
+
+ /* Compute the size of the command buffer. */
+ buffersize
+ = (unsigned char *) gcbuffer->tail
+ - (unsigned char *) gcbuffer->head;
+
+ GCDBG(GCZONE_COMMIT, "buffersize = %d\n", buffersize);
+
+ /* Reserve command buffer space. */
+ GCDBG(GCZONE_COMMIT, "allocating command buffer space.\n");
+ gcicommit->gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+ buffersize,
+ (void **) &logical,
+ &address);
+ if (gcicommit->gcerror != GCERR_NONE)
+ goto exit;
+
+ if (fromuser) {
+ /* Copy command buffer. */
+ if (copy_from_user(logical, gcbuffer->head,
+ buffersize)) {
+ GCERR("failed to read data.\n");
+ gcicommit->gcerror = GCERR_USER_READ;
+ goto exit;
+ }
+ } else {
+ memcpy(logical, gcbuffer->head, buffersize);
+ }
+
+ /* Process fixups. */
+ gcicommit->gcerror = gcmmu_fixup(&gcbuffer->fixup, logical);
+ if (gcicommit->gcerror != GCERR_NONE)
+ goto exit;
+ }
+
+ /* Add the callback. */
+ if (gcicommit->callback != NULL) {
+ gcicommit->gcerror = gcqueue_callback(gccorecontext,
+ gcmmucontext,
+ gcicommit->callback,
+ gcicommit->callbackparam);
+ if (gcicommit->gcerror != GCERR_NONE)
+ goto exit;
+ }
+
+ /* Process unmappings. */
+ list_for_each(head, &gcicommit->unmap) {
+ gcschedunmap = list_entry(head, struct gcschedunmap, link);
+ gcicommit->gcerror = gcqueue_schedunmap(gccorecontext,
+ gcmmucontext,
+ gcschedunmap->handle);
+ if (gcicommit->gcerror != GCERR_NONE)
+ goto exit;
+ }
+
+ /* Execute the buffer. */
+ gcicommit->gcerror = gcqueue_execute(gccorecontext, false,
+ gcicommit->asynchronous);
+
+exit:
+ GCUNLOCK(&gccorecontext->mmucontextlock);
+
+ GCEXITARG(GCZONE_COMMIT, "gc%s = 0x%08X\n",
+ (gcicommit->gcerror == GCERR_NONE) ? "result" : "error",
+ gcicommit->gcerror);
+}
+EXPORT_SYMBOL(gc_commit);
+
+void gc_map(struct gcimap *gcimap, bool fromuser)
+{
+ struct gccorecontext *gccorecontext = &g_context;
+ struct gcmmucontext *gcmmucontext;
+ struct gcmmuphysmem mem;
+ struct gcmmuarena *mapped = NULL;
+
+ GCENTER(GCZONE_MAPPING);
+
+ GCLOCK(&gccorecontext->mmucontextlock);
+
+ /* Locate the client entry. */
+ gcimap->gcerror = find_context(gccorecontext,
+ fromuser,
+ &gcmmucontext);
+ if (gcimap->gcerror != GCERR_NONE)
+ goto exit;
+
+ GCDBG(GCZONE_MAPPING, "map client buffer\n");
+
+ /* Initialize the mapping parameters. */
+ if (gcimap->pagearray == NULL) {
+ mem.base = ((u32) gcimap->buf.logical) & ~(PAGE_SIZE - 1);
+ mem.offset = ((u32) gcimap->buf.logical) & (PAGE_SIZE - 1);
+ mem.pages = NULL;
+
+ GCDBG(GCZONE_MAPPING, " logical = 0x%08X\n",
+ (unsigned int) gcimap->buf.logical);
+ } else {
+ mem.base = 0;
+ mem.offset = gcimap->buf.offset;
+ mem.pages = (pte_t *)gcimap->pagearray;
+
+ GCDBG(GCZONE_MAPPING, " pagearray = 0x%08X\n",
+ (unsigned int) gcimap->pagearray);
+ }
+
+ GCDBG(GCZONE_MAPPING, " size = %d\n", gcimap->size);
+
+ mem.count = DIV_ROUND_UP(gcimap->size + mem.offset, PAGE_SIZE);
+ mem.pagesize = gcimap->pagesize ? gcimap->pagesize : PAGE_SIZE;
+
+ /* Map the buffer. */
+ gcimap->gcerror = gcmmu_map(gccorecontext, gcmmucontext, &mem, &mapped);
+ if (gcimap->gcerror != GCERR_NONE)
+ goto exit;
+
+ gcimap->handle = (unsigned int) mapped;
+
+ GCDBG(GCZONE_MAPPING, " mapped address = 0x%08X\n", mapped->address);
+ GCDBG(GCZONE_MAPPING, " handle = 0x%08X\n", (unsigned int) mapped);
+
+exit:
+ GCUNLOCK(&gccorecontext->mmucontextlock);
+
+ GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
+ (gcimap->gcerror == GCERR_NONE) ? "result" : "error",
+ gcimap->gcerror);
+}
+EXPORT_SYMBOL(gc_map);
+
+void gc_unmap(struct gcimap *gcimap, bool fromuser)
+{
+ struct gccorecontext *gccorecontext = &g_context;
+ struct gcmmucontext *gcmmucontext;
+
+ GCENTER(GCZONE_MAPPING);
+
+ GCLOCK(&gccorecontext->mmucontextlock);
+
+ /* Locate the client entry. */
+ gcimap->gcerror = find_context(gccorecontext,
+ fromuser,
+ &gcmmucontext);
+ if (gcimap->gcerror != GCERR_NONE)
+ goto exit;
+
+ GCDBG(GCZONE_MAPPING, "unmap client buffer\n");
+ GCDBG(GCZONE_MAPPING, " handle = 0x%08X\n", gcimap->handle);
+
+ /* Schedule unmapping. */
+ gcimap->gcerror = gcqueue_schedunmap(gccorecontext, gcmmucontext,
+ gcimap->handle);
+ if (gcimap->gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Execute the buffer. */
+ gcimap->gcerror = gcqueue_execute(gccorecontext, false, false);
+ if (gcimap->gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Invalidate the handle. */
+ gcimap->handle = ~0U;
+
+exit:
+ GCUNLOCK(&gccorecontext->mmucontextlock);
+
+ GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
+ (gcimap->gcerror == GCERR_NONE) ? "result" : "error",
+ gcimap->gcerror);
+}
+EXPORT_SYMBOL(gc_unmap);
+
+void gc_callback(struct gcicallbackarm *gcicallbackarm, bool fromuser)
+{
+ struct gccorecontext *gccorecontext = &g_context;
+ struct gcmmucontext *gcmmucontext;
+
+ GCENTER(GCZONE_CALLBACK);
+
+ GCLOCK(&gccorecontext->mmucontextlock);
+
+ /* Locate the client entry. */
+ gcicallbackarm->gcerror = find_context(gccorecontext, fromuser,
+ &gcmmucontext);
+ if (gcicallbackarm->gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Schedule callback. */
+ gcicallbackarm->gcerror
+ = gcqueue_callback(gccorecontext,
+ gcmmucontext,
+ gcicallbackarm->callback,
+ gcicallbackarm->callbackparam);
+ if (gcicallbackarm->gcerror != GCERR_NONE)
+ goto exit;
+
+exit:
+ GCUNLOCK(&gccorecontext->mmucontextlock);
+
+ GCEXITARG(GCZONE_CALLBACK, "gc%s = 0x%08X\n",
+ (gcicallbackarm->gcerror == GCERR_NONE) ? "result" : "error",
+ gcicallbackarm->gcerror);
+}
+EXPORT_SYMBOL(gc_callback);
+
+void gc_release(void)
+{
+ struct gccorecontext *gccorecontext = &g_context;
+ struct list_head *ctxhead;
+ struct gcmmucontext *temp = NULL;
+ pid_t pid;
+
+ GCENTER(GCZONE_CONTEXT);
+
+ GCLOCK(&gccorecontext->mmucontextlock);
+
+ pid = current->tgid;
+ GCDBG(GCZONE_CONTEXT, "scanning context records for pid %d.\n", pid);
+
+ list_for_each(ctxhead, &gccorecontext->mmuctxlist) {
+ temp = list_entry(ctxhead, struct gcmmucontext, link);
+ if (temp->pid == pid) {
+ GCDBG(GCZONE_CONTEXT, "context is found @ 0x%08X\n",
+ (unsigned int) temp);
+
+ gcmmu_destroy_context(gccorecontext, temp);
+ list_move(ctxhead, &gccorecontext->mmuctxvac);
+ break;
+ }
+ }
+
+ GCUNLOCK(&gccorecontext->mmucontextlock);
+
+ GCEXIT(GCZONE_CONTEXT);
+}
+EXPORT_SYMBOL(gc_release);
+
+static int gc_probe_opp(struct platform_device *pdev)
+{
+ int i;
+ unsigned int size;
+ unsigned long freq = 0;
+ struct gccorecontext *gccorecontext = &g_context;
+
+ /* Query supported OPPs. */
+ rcu_read_lock();
+
+ gccorecontext->opp_count = opp_get_opp_count(&pdev->dev);
+ if (gccorecontext->opp_count <= 0) {
+ gccorecontext->opp_count = 0;
+ goto done;
+ }
+
+ size = gccorecontext->opp_count * sizeof(unsigned long);
+ gccorecontext->opp_freqs = kzalloc(size, GFP_ATOMIC);
+ if (!gccorecontext->opp_freqs) {
+ gccorecontext->opp_count = 0;
+ goto done;
+ }
+
+ GCDBG(GCZONE_FREQSCALE, "frequency scaling table:\n");
+
+ for (i = 0; i < gccorecontext->opp_count; i++) {
+ struct opp *opp = opp_find_freq_ceil(&pdev->dev, &freq);
+ if (IS_ERR_OR_NULL(opp)) {
+ gccorecontext->opp_count = i;
+ goto done;
+ }
+
+ /* Set freq, prepare to next. */
+ gccorecontext->opp_freqs[i] = freq++;
+ GCDBG(GCZONE_FREQSCALE, " [%d] 0x%08X\n",
+ i, gccorecontext->opp_freqs[i]);
+ }
+
+done:
+ rcu_read_unlock();
+ gcpwr_set(gccorecontext, GCPWR_LOW);
+ return 0;
+}
+
+static int gc_probe(struct platform_device *pdev)
+{
+ struct gccorecontext *gccorecontext = &g_context;
+ int ret;
+
+ GCENTER(GCZONE_PROBE);
+
+ gccorecontext->bb2ddevice = &pdev->dev;
+ gccorecontext->plat = (struct omap_gcx_platform_data *)
+ pdev->dev.platform_data;
+
+ if (!gccorecontext->plat->is_hw_present) {
+ GCERR("gc_probe failed. gcx hardware is not present\n");
+ return -ENODEV;
+ }
+
+ gccorecontext->regbase = gccorecontext->plat->regbase;
+ gccorecontext->irqline = platform_get_irq(pdev, pdev->id);
+ gccorecontext->device = &pdev->dev;
+
+
+ pm_runtime_enable(gccorecontext->device);
+ gccorecontext->plat->get_context_loss_count(gccorecontext->device);
+
+ gc_probe_opp(pdev);
+
+ ret = pm_runtime_get_sync(gccorecontext->device);
+
+ gccorecontext->gcmodel = gc_read_reg(GC_CHIP_ID_Address);
+ gccorecontext->gcrevision = gc_read_reg(GC_CHIP_REV_Address);
+ gccorecontext->gcdate = gc_read_reg(GC_CHIP_DATE_Address);
+ gccorecontext->gctime = gc_read_reg(GC_CHIP_TIME_Address);
+ gccorecontext->gcfeatures.raw = gc_read_reg(GC_FEATURES_Address);
+ gccorecontext->gcfeatures0.raw = gc_read_reg(GC_FEATURES0_Address);
+ gccorecontext->gcfeatures1.raw = gc_read_reg(GC_FEATURES1_Address);
+ gccorecontext->gcfeatures2.raw = gc_read_reg(GC_FEATURES2_Address);
+ gccorecontext->gcfeatures3.raw = gc_read_reg(GC_FEATURES3_Address);
+
+ GCDBG(GCZONE_PROBE, "GPU IDENTITY:\n");
+ GCDBG(GCZONE_PROBE, " model=%X\n", gccorecontext->gcmodel);
+ GCDBG(GCZONE_PROBE, " revision=%X\n", gccorecontext->gcrevision);
+ GCDBG(GCZONE_PROBE, " date=%X\n", gccorecontext->gcdate);
+ GCDBG(GCZONE_PROBE, " time=%X\n", gccorecontext->gctime);
+ GCDBG(GCZONE_PROBE, " features=0x%08X\n", gccorecontext->gcfeatures);
+ GCDBG(GCZONE_PROBE, " features0=0x%08X\n", gccorecontext->gcfeatures0);
+ GCDBG(GCZONE_PROBE, " features1=0x%08X\n", gccorecontext->gcfeatures1);
+ GCDBG(GCZONE_PROBE, " features2=0x%08X\n", gccorecontext->gcfeatures2);
+ GCDBG(GCZONE_PROBE, " features3=0x%08X\n", gccorecontext->gcfeatures3);
+
+ pm_runtime_put_sync(gccorecontext->device);
+
+ GCEXIT(GCZONE_PROBE);
+ return 0;
+}
+
+static int gc_remove(struct platform_device *pdev)
+{
+ kfree(g_context.opp_freqs);
+ return 0;
+}
+
+#if GC_ENABLE_SUSPEND
+static int gc_suspend(struct platform_device *pdev, pm_message_t s)
+{
+ GCENTER(GCZONE_POWER);
+ gcqueue_wait_idle(&g_context);
+ GCEXIT(GCZONE_POWER);
+ return 0;
+}
+
+static int gc_resume(struct platform_device *pdev)
+{
+ GCENTER(GCZONE_POWER);
+ GCEXIT(GCZONE_POWER);
+ return 0;
+}
+#endif
+
+static struct platform_driver plat_drv = {
+ .probe = gc_probe,
+ .remove = gc_remove,
+#if GC_ENABLE_SUSPEND
+ .suspend = gc_suspend,
+ .resume = gc_resume,
+#endif
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "gccore",
+ },
+};
+
+#if CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+static void gc_early_suspend(struct early_suspend *h)
+{
+ GCENTER(GCZONE_POWER);
+ gcqueue_wait_idle(&g_context);
+ GCEXIT(GCZONE_POWER);
+}
+
+static void gc_late_resume(struct early_suspend *h)
+{
+ GCENTER(GCZONE_POWER);
+ GCEXIT(GCZONE_POWER);
+}
+
+static struct early_suspend early_suspend_info = {
+ .suspend = gc_early_suspend,
+ .resume = gc_late_resume,
+ .level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
+};
+#endif
+
+
+/*******************************************************************************
+ * Driver init/shutdown.
+ */
+
+static int gc_init(struct gccorecontext *gccorecontext);
+static void gc_exit(struct gccorecontext *gccorecontext);
+
+static int gc_init(struct gccorecontext *gccorecontext)
+{
+ int result;
+
+ GCENTER(GCZONE_INIT);
+
+ /* Initialize data structutres. */
+ GCLOCK_INIT(&gccorecontext->powerlock);
+ GCLOCK_INIT(&gccorecontext->resetlock);
+ GCLOCK_INIT(&gccorecontext->mmucontextlock);
+ INIT_LIST_HEAD(&gccorecontext->mmuctxlist);
+ INIT_LIST_HEAD(&gccorecontext->mmuctxvac);
+
+ /* Pulse skipping isn't known. */
+ gccorecontext->pulseskipping = -1;
+
+ result = platform_driver_register(&plat_drv);
+ if (result < 0) {
+ GCERR("failed to register platform driver.\n");
+ goto fail;
+ }
+ gccorecontext->platdriver = true;
+
+ /* Initialize MMU. */
+ if (gcmmu_init(gccorecontext) != GCERR_NONE) {
+ GCERR("failed to initialize MMU.\n");
+ result = -EINVAL;
+ goto fail;
+ }
+
+#if CONFIG_HAS_EARLYSUSPEND
+ register_early_suspend(&early_suspend_info);
+#endif
+
+ /* Initialize the command buffer. */
+ if (gcqueue_start(gccorecontext) != GCERR_NONE) {
+ GCERR("failed to initialize command buffer.\n");
+ result = -EINVAL;
+ goto fail;
+ }
+
+ /* Create debugfs entry. */
+ gc_debug_init();
+
+ GCEXIT(GCZONE_INIT);
+ return 0;
+
+fail:
+ gc_exit(gccorecontext);
+
+ GCEXITARG(GCZONE_INIT, "result = %d\n", result);
+ return result;
+}
+
+static void gc_exit(struct gccorecontext *gccorecontext)
+{
+ GCENTER(GCZONE_INIT);
+
+ if (gc_is_hw_present()) {
+ /* Stop command queue thread. */
+ gcqueue_stop(gccorecontext);
+
+ /* Destroy MMU. */
+ destroy_mmu_context(gccorecontext);
+ gcmmu_exit(gccorecontext);
+
+ /* Disable power. */
+ pm_runtime_disable(gccorecontext->device);
+
+ if (gccorecontext->platdriver) {
+ platform_driver_unregister(&plat_drv);
+ gccorecontext->platdriver = false;
+ }
+
+#if CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&early_suspend_info);
+#endif
+
+ gc_debug_shutdown();
+
+ GCLOCK_DESTROY(&gccorecontext->mmucontextlock);
+ GCLOCK_DESTROY(&gccorecontext->resetlock);
+ GCLOCK_DESTROY(&gccorecontext->powerlock);
+ }
+
+ GCEXIT(GCZONE_PROBE);
+}
+
+static int __init gc_init_wrapper(void)
+{
+ GCDBG_INIT();
+
+ GCDBG_REGISTER(core, GCZONE_NONE);
+ GCDBG_REGISTER(mem, GCZONE_NONE);
+ GCDBG_REGISTER(mmu, GCZONE_NONE);
+ GCDBG_REGISTER(queue, GCZONE_NONE);
+
+ return gc_init(&g_context);
+}
+
+static void __exit gc_exit_wrapper(void)
+{
+ gc_exit(&g_context);
+ GCDBG_EXIT();
+}
+
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("www.vivantecorp.com");
+MODULE_AUTHOR("www.ti.com");
+module_init(gc_init_wrapper);
+module_exit(gc_exit_wrapper);
diff --git a/drivers/misc/gcx/gccore/gcmain.h b/drivers/misc/gcx/gccore/gcmain.h
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * gcmain.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCMAIN_H
+#define GCMAIN_H
+
+#include <linux/gcx.h>
+#include <linux/gccore.h>
+#include "gcmmu.h"
+
+#define GC_DEV_NAME "gccore"
+
+
+/*******************************************************************************
+ * Power management modes.
+ */
+
+enum gcpower {
+ GCPWR_UNKNOWN,
+ GCPWR_ON,
+ GCPWR_LOW,
+ GCPWR_OFF
+};
+
+
+/*******************************************************************************
+ * Driver context.
+ */
+
+struct omap_gcx_platform_data;
+
+struct gccorecontext {
+ /* GPU IRQ line. */
+ int irqline;
+
+ /* Capabilities and characteristics. */
+ unsigned int gcmodel;
+ unsigned int gcrevision;
+ unsigned int gcdate;
+ unsigned int gctime;
+ union gcfeatures gcfeatures;
+ union gcfeatures0 gcfeatures0;
+ union gcfeatures1 gcfeatures1;
+ union gcfeatures2 gcfeatures2;
+ union gcfeatures3 gcfeatures3;
+
+ /* Virtual pointer to the GPU register bank. */
+ void *regbase;
+
+ /* Platform driver install flag. */
+ bool platdriver;
+ struct omap_gcx_platform_data *plat;
+
+ /* Pointers to the gccore and BB2D devices. */
+ struct device *device;
+ struct device *bb2ddevice;
+
+ /* Current power mode. */
+ enum gcpower gcpower;
+ GCLOCK_TYPE powerlock;
+ GCLOCK_TYPE resetlock;
+
+ /* Current graphics pipe. */
+ enum gcpipe gcpipe;
+
+ /* Power mode flags. */
+ bool clockenabled;
+ int pulseskipping;
+
+ /* MMU and command buffer managers. */
+ struct gcmmu gcmmu;
+ struct gcqueue gcqueue;
+
+ /* MMU context lists. */
+ struct list_head mmuctxlist;
+ struct list_head mmuctxvac;
+ GCLOCK_TYPE mmucontextlock;
+
+ /* Device frequency scaling. */
+ int opp_count;
+ unsigned long *opp_freqs;
+ unsigned long cur_freq;
+};
+
+
+/*******************************************************************************
+ * Register access.
+ */
+
+unsigned int gc_read_reg(unsigned int address);
+void gc_write_reg(unsigned int address, unsigned int data);
+
+
+/*******************************************************************************
+ * Power management.
+ */
+
+enum gcpower gcpwr_get(void);
+void gcpwr_set(struct gccorecontext *gccorecontext, enum gcpower gcpower);
+void gcpwr_reset(struct gccorecontext *gccorecontext);
+unsigned int gcpwr_get_speed(void);
+
+#endif
diff --git a/drivers/misc/gcx/gccore/gcmem.c b/drivers/misc/gcx/gccore/gcmem.c
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * gcmain.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/pagemap.h>
+#include <linux/dma-mapping.h>
+#include "gcmain.h"
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_CACHED (1 << 0)
+#define GCZONE_NONCACHED (1 << 1)
+#define GCZONE_FLUSH (1 << 2)
+
+GCDBG_FILTERDEF(mem, GCZONE_NONE,
+ "cached",
+ "noncached",
+ "flush")
+
+enum gcerror gc_alloc_noncached(struct gcpage *p, unsigned int size)
+{
+ enum gcerror gcerror;
+
+ GCENTERARG(GCZONE_NONCACHED, "p = 0x%08X\n", (unsigned int) p);
+
+ p->pages = NULL;
+ p->order = 0;
+ p->size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+ p->logical = NULL;
+ p->physical = ~0UL;
+
+ GCDBG(GCZONE_NONCACHED, "requested size=%d\n", size);
+ GCDBG(GCZONE_NONCACHED, "aligned size=%d\n", p->size);
+
+ p->logical = dma_alloc_coherent(NULL, p->size, &p->physical,
+ GFP_KERNEL);
+ if (!p->logical) {
+ GCERR("failed to allocate memory\n");
+ gcerror = GCERR_OOPM;
+ goto exit;
+ }
+
+ GCDBG(GCZONE_NONCACHED, "logical=0x%08X\n",
+ (unsigned int) p->logical);
+ GCDBG(GCZONE_NONCACHED, "physical=0x%08X\n",
+ (unsigned int) p->physical);
+
+ GCEXIT(GCZONE_NONCACHED);
+ return GCERR_NONE;
+
+exit:
+ gc_free_noncached(p);
+
+ GCEXITARG(GCZONE_NONCACHED, "gcerror = 0x%08X\n", gcerror);
+ return gcerror;
+}
+
+void gc_free_noncached(struct gcpage *p)
+{
+ GCENTERARG(GCZONE_NONCACHED, "p = 0x%08X\n", (unsigned int) p);
+
+ if (p->logical != NULL) {
+ dma_free_coherent(NULL, p->size, p->logical, p->physical);
+ p->logical = NULL;
+ }
+
+ p->physical = ~0UL;
+ p->size = 0;
+
+ GCEXIT(GCZONE_NONCACHED);
+}
+
+enum gcerror gc_alloc_cached(struct gcpage *p, unsigned int size)
+{
+ enum gcerror gcerror;
+ struct page *pages;
+ int count;
+
+ GCENTERARG(GCZONE_CACHED, "p = 0x%08X\n", (unsigned int) p);
+
+ p->order = get_order(size);
+ p->pages = NULL;
+ p->size = (1 << p->order) * PAGE_SIZE;
+ p->logical = NULL;
+ p->physical = ~0UL;
+
+ GCDBG(GCZONE_CACHED, "requested size=%d\n", size);
+ GCDBG(GCZONE_CACHED, "aligned size=%d\n", p->size);
+
+ p->pages = alloc_pages(GFP_KERNEL, p->order);
+ if (p->pages == NULL) {
+ GCERR("failed to allocate memory\n");
+ gcerror = GCERR_OOPM;
+ goto exit;
+ }
+
+ p->physical = page_to_phys(p->pages);
+ p->logical = (unsigned int *) page_address(p->pages);
+
+ if (p->logical == NULL) {
+ GCERR("failed to retrieve page virtual address\n");
+ gcerror = GCERR_PMMAP;
+ goto exit;
+ }
+
+ /* Reserve pages. */
+ pages = p->pages;
+ count = p->size / PAGE_SIZE;
+
+ while (count--)
+ SetPageReserved(pages++);
+
+ GCDBG(GCZONE_CACHED, "page array=0x%08X\n", (unsigned int) p->pages);
+ GCDBG(GCZONE_CACHED, "logical=0x%08X\n", (unsigned int) p->logical);
+ GCDBG(GCZONE_CACHED, "physical=0x%08X\n", (unsigned int) p->physical);
+
+ GCEXIT(GCZONE_CACHED);
+ return GCERR_NONE;
+
+exit:
+ gc_free_cached(p);
+
+ GCEXITARG(GCZONE_CACHED, "gcerror = 0x%08X\n", gcerror);
+ return gcerror;
+}
+
+void gc_free_cached(struct gcpage *p)
+{
+ GCENTERARG(GCZONE_CACHED, "p = 0x%08X\n", (unsigned int) p);
+
+ GCDBG(GCZONE_CACHED, "page array=0x%08X\n", (unsigned int) p->pages);
+ GCDBG(GCZONE_CACHED, "logical=0x%08X\n", (unsigned int) p->logical);
+ GCDBG(GCZONE_CACHED, "physical=0x%08X\n", (unsigned int) p->physical);
+ GCDBG(GCZONE_CACHED, "size=%d\n", p->size);
+
+ if (p->logical != NULL) {
+ struct page *pages;
+ int count;
+
+ pages = p->pages;
+ count = p->size / PAGE_SIZE;
+
+ while (count--)
+ ClearPageReserved(pages++);
+
+ p->logical = NULL;
+ }
+
+ if (p->pages != NULL) {
+ __free_pages(p->pages, p->order);
+ p->pages = NULL;
+ }
+
+ p->physical = ~0UL;
+ p->order = 0;
+ p->size = 0;
+
+ GCEXIT(GCZONE_CACHED);
+}
+
+void gc_flush_cached(struct gcpage *p)
+{
+ GCENTERARG(GCZONE_FLUSH, "p = 0x%08X\n", (unsigned int) p);
+
+ dmac_flush_range(p->logical, (unsigned char *) p->logical + p->size);
+ outer_flush_range(p->physical, p->physical + p->size);
+
+ GCEXIT(GCZONE_FLUSH);
+}
+
+void gc_flush_region(unsigned int physical, void *logical,
+ unsigned int offset, unsigned int size)
+{
+ unsigned char *startlog;
+ unsigned int startphys;
+
+ GCENTER(GCZONE_FLUSH);
+
+ GCDBG(GCZONE_FLUSH, "logical=0x%08X\n", (unsigned int) logical);
+ GCDBG(GCZONE_FLUSH, "physical=0x%08X\n", physical);
+ GCDBG(GCZONE_FLUSH, "offset=%d\n", offset);
+ GCDBG(GCZONE_FLUSH, "size=%d\n", size);
+
+ startlog = (unsigned char *) logical + offset;
+ startphys = physical + offset;
+
+ dmac_flush_range(startlog, startlog + size);
+ outer_flush_range(startphys, startphys + size);
+
+ GCEXIT(GCZONE_FLUSH);
+}
diff --git a/drivers/misc/gcx/gccore/gcmem.h b/drivers/misc/gcx/gccore/gcmem.h
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * gcmem.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCMEM_H
+#define GCMEM_H
+
+struct gcpage {
+ unsigned int order;
+ struct page *pages;
+
+ unsigned int size;
+ unsigned int physical;
+ unsigned int *logical;
+};
+
+enum gcerror gc_alloc_noncached(struct gcpage *p, unsigned int size);
+void gc_free_noncached(struct gcpage *p);
+
+enum gcerror gc_alloc_cached(struct gcpage *p, unsigned int size);
+void gc_free_cached(struct gcpage *p);
+void gc_flush_cached(struct gcpage *p);
+void gc_flush_region(unsigned int physical, void *logical,
+ unsigned int offset, unsigned int size);
+
+#endif
diff --git a/drivers/misc/gcx/gccore/gcmmu.c b/drivers/misc/gcx/gccore/gcmmu.c
--- /dev/null
@@ -0,0 +1,1332 @@
+/*
+ * gcmmu.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/pagemap.h>
+#include <linux/sched.h>
+#include "gcmain.h"
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_INIT (1 << 0)
+#define GCZONE_MAPPING (1 << 1)
+#define GCZONE_CONTEXT (1 << 2)
+#define GCZONE_MASTER (1 << 3)
+#define GCZONE_FIXUP (1 << 4)
+#define GCZONE_FLUSH (1 << 5)
+#define GCZONE_ARENA (1 << 6)
+#define GCZONE_DUMPMAP (1 << 7)
+#define GCZONE_DUMPUNMAP (1 << 8)
+
+GCDBG_FILTERDEF(mmu, GCZONE_NONE,
+ "init",
+ "mapping",
+ "context",
+ "master",
+ "fixup",
+ "flush",
+ "arena",
+ "dumpmap",
+ "dumpunmap")
+
+
+#define USE_CACHED_MASTER 0
+#define USE_CACHED_SLAVE 0
+/*******************************************************************************
+ * Internal definitions.
+ */
+
+/* Slave table preallocation block; can describe an array of slave tables. */
+struct gcmmustlbblock {
+ /* Slave table allocation. */
+ struct gcpage pages;
+
+ /* Next block of preallocated slave memory. */
+ struct gcmmustlbblock *next;
+};
+
+
+/*******************************************************************************
+ * Call back to enable MMU.
+ */
+
+static void event_enable_mmu(struct gcevent *gcevent, unsigned int *flags)
+{
+ GCENTER(GCZONE_INIT);
+
+ /*
+ * Enable MMU. For security reasons, once it is enabled,
+ * the only way to disable is to reset the system.
+ */
+ gc_write_reg(
+ GCREG_MMU_CONTROL_Address,
+ GCSETFIELDVAL(0, GCREG_MMU_CONTROL, ENABLE, ENABLE));
+
+ /* After MMU command buffer is processed, FE will stop.
+ * Let the control thread know that FE needs to be restarted. */
+ if (flags == NULL)
+ GCERR("flags are not set.\n");
+ else
+ *flags |= GC_CMDBUF_START_FE;
+
+ GCEXIT(GCZONE_INIT);
+}
+
+
+/*******************************************************************************
+ * Arena record management.
+ */
+
+static enum gcerror get_arena(struct gcmmu *gcmmu, struct gcmmuarena **arena)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gcmmuarena *temp;
+
+ GCENTER(GCZONE_ARENA);
+
+ GCLOCK(&gcmmu->lock);
+
+ if (list_empty(&gcmmu->vacarena)) {
+ temp = kmalloc(sizeof(struct gcmmuarena), GFP_KERNEL);
+ if (temp == NULL) {
+ GCERR("arena entry allocation failed.\n");
+ gcerror = GCERR_SETGRP(GCERR_OODM,
+ GCERR_MMU_ARENA_ALLOC);
+ goto exit;
+ }
+ } else {
+ struct list_head *head;
+ head = gcmmu->vacarena.next;
+ temp = list_entry(head, struct gcmmuarena, link);
+ list_del(head);
+ }
+
+ *arena = temp;
+
+exit:
+ GCUNLOCK(&gcmmu->lock);
+
+ GCEXITARG(GCZONE_ARENA, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+ return gcerror;
+}
+
+static inline bool siblings(struct list_head *head,
+ struct list_head *arenahead1,
+ struct list_head *arenahead2)
+{
+ struct gcmmuarena *arena1;
+ struct gcmmuarena *arena2;
+
+ if ((arenahead1 == head) || (arenahead2 == head))
+ return false;
+
+ arena1 = list_entry(arenahead1, struct gcmmuarena, link);
+ arena2 = list_entry(arenahead2, struct gcmmuarena, link);
+
+ return (arena1->end.absolute == arena2->start.absolute) ? true : false;
+}
+
+/*******************************************************************************
+ * Slave table allocation management.
+ */
+
+static enum gcerror allocate_slave(struct gcmmucontext *gcmmucontext,
+ union gcmmuloc index)
+{
+ enum gcerror gcerror;
+ struct gcmmustlbblock *block = NULL;
+ struct gcmmustlb *slave;
+ unsigned int *mtlblogical;
+ unsigned int prealloccount;
+ unsigned int preallocsize;
+ unsigned int preallocentries;
+ unsigned int physical;
+ unsigned int *logical;
+ unsigned int i;
+
+ GCENTER(GCZONE_MAPPING);
+
+ /* Allocate a new prealloc block wrapper. */
+ block = kmalloc(sizeof(struct gcmmustlbblock), GFP_KERNEL);
+ if (block == NULL) {
+ GCERR("failed to allocate slave page table wrapper\n");
+ gcerror = GCERR_SETGRP(GCERR_OODM,
+ GCERR_MMU_STLB_ALLOC);
+ goto exit;
+ }
+
+ /* Determine the number and the size of tables to allocate. */
+ prealloccount = min(GCMMU_STLB_PREALLOC_COUNT,
+ GCMMU_MTLB_ENTRY_NUM - index.loc.mtlb);
+
+ preallocsize = prealloccount * GCMMU_STLB_SIZE;
+ preallocentries = prealloccount * GCMMU_STLB_ENTRY_NUM;
+
+ GCDBG(GCZONE_MAPPING, "preallocating %d slave tables.\n",
+ prealloccount);
+
+ /* Allocate slave table pool. */
+#if USE_CACHED_SLAVE
+ gcerror = gc_alloc_cached(&block->pages, preallocsize);
+#else
+ gcerror = gc_alloc_noncached(&block->pages, preallocsize);
+#endif
+ if (gcerror != GCERR_NONE) {
+ GCERR("failed to allocate slave page table\n");
+ gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_STLB_ALLOC);
+ goto exit;
+ }
+
+ /* Add the block to the list. */
+ block->next = gcmmucontext->slavealloc;
+ gcmmucontext->slavealloc = block;
+
+ /* Get shortcuts to the pointers. */
+ physical = block->pages.physical;
+ logical = block->pages.logical;
+
+ /* Invalidate all slave entries. */
+ for (i = 0; i < preallocentries; i += 1)
+ logical[i] = GCMMU_STLB_ENTRY_VACANT;
+
+ /* Init the slaves. */
+ slave = &gcmmucontext->slave[index.loc.mtlb];
+ mtlblogical = &gcmmucontext->master.logical[index.loc.mtlb];
+
+ for (i = 0; i < prealloccount; i += 1) {
+ mtlblogical[i]
+ = (physical & GCMMU_MTLB_SLAVE_MASK)
+ | GCMMU_MTLB_4K_PAGE
+ | GCMMU_MTLB_EXCEPTION
+ | GCMMU_MTLB_PRESENT;
+
+ slave[i].physical = physical;
+ slave[i].logical = logical;
+
+ physical += GCMMU_STLB_SIZE;
+ logical = (unsigned int *)
+ ((unsigned char *) logical + GCMMU_STLB_SIZE);
+ }
+
+#if USE_CACHED_MASTER
+ /* Flush CPU cache. */
+ gc_flush_region(gcmmucontext->master.physical,
+ gcmmucontext->master.logical,
+ index.loc.mtlb * sizeof(unsigned int),
+ prealloccount * sizeof(unsigned int));
+#else
+ mb();
+#endif
+
+
+ GCEXIT(GCZONE_MAPPING);
+ return GCERR_NONE;
+
+exit:
+ if (block != NULL)
+ kfree(block);
+
+ GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+ return gcerror;
+}
+
+/*******************************************************************************
+ * Physical page array generation.
+ */
+
+static enum gcerror virt2phys(unsigned int logical, pte_t *physical)
+{
+ pgd_t *pgd; /* Page Global Directory (PGD). */
+ pmd_t *pmd; /* Page Middle Directory (PMD). */
+ pte_t *pte; /* Page Table Entry (PTE). */
+
+ /* Get the pointer to the entry in PGD for the address. */
+ pgd = pgd_offset(current->mm, logical);
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ return GCERR_MMU_PAGE_BAD;
+
+ /* Get the pointer to the entry in PMD for the address. */
+ pmd = pmd_offset((pud_t *)pgd, logical);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ return GCERR_MMU_PAGE_BAD;
+
+ /* Get the pointer to the entry in PTE for the address. */
+ pte = pte_offset_map(pmd, logical);
+ if ((pte == NULL) || !pte_present(*pte))
+ return GCERR_MMU_PAGE_BAD;
+
+ *physical = (*pte & PAGE_MASK) | (logical & ~PAGE_MASK);
+ return GCERR_NONE;
+}
+
+#if !defined(PFN_DOWN)
+# define PFN_DOWN(x) \
+ ((x) >> PAGE_SHIFT)
+#endif
+
+#if !defined(phys_to_pfn)
+# define phys_to_pfn(phys) \
+ (PFN_DOWN(phys))
+#endif
+
+#if !defined(phys_to_page)
+# define phys_to_page(paddr) \
+ (pfn_to_page(phys_to_pfn(paddr)))
+#endif
+
+static enum gcerror get_physical_pages(struct gcmmuphysmem *mem,
+ pte_t *parray,
+ struct gcmmuarena *arena)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct vm_area_struct *vma;
+ struct page **pages = NULL;
+ unsigned long base, start, end;
+ unsigned int write;
+ int i, count = 0;
+
+ GCENTER(GCZONE_MAPPING);
+
+ /* Get the base address. */
+ base = mem->base;
+
+ /* Reset page descriptor array. */
+ arena->pages = NULL;
+
+ /* Store the logical pointer. */
+ arena->logical = (void *) base;
+
+ /* Compute virtual memory area limits. */
+ start = base + mem->offset;
+ end = base + mem->count * mem->pagesize;
+ GCDBG(GCZONE_MAPPING, "base = 0x%08X\n", base);
+ GCDBG(GCZONE_MAPPING, "offset = 0x%08X\n", mem->offset);
+ GCDBG(GCZONE_MAPPING, "count = %d\n", mem->count);
+ GCDBG(GCZONE_MAPPING, "start = 0x%08X\n", start);
+ GCDBG(GCZONE_MAPPING, "end = 0x%08X\n", end);
+
+ vma = find_vma(current->mm, start);
+ if (vma == NULL) {
+ gcerror = GCERR_MMU_BUFFER_BAD;
+ GCERR("failed to find VMA.\n");
+ goto exit;
+ }
+
+ GCDBG(GCZONE_MAPPING, "vm_start = 0x%08X\n", vma->vm_start);
+ GCDBG(GCZONE_MAPPING, "vm_end = 0x%08X\n", vma->vm_end);
+ if ((start < vma->vm_start) || (end > vma->vm_end)) {
+ gcerror = GCERR_MMU_BUFFER_BAD;
+ GCERR("failed to find VMA...\n");
+ goto exit;
+ }
+
+ /* Allocate page descriptor array. */
+ pages = kmalloc(mem->count * sizeof(struct page *), GFP_KERNEL);
+ if (pages == NULL) {
+ GCERR("failed to allocate page descriptor array.\n");
+ gcerror = GCERR_SETGRP(GCERR_OODM, GCERR_MMU_DESC_ALLOC);
+ goto exit;
+ }
+
+ /* Query page descriptors. */
+ write = ((vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) != 0) ? 1 : 0;
+
+ down_read(¤t->mm->mmap_sem);
+ count = get_user_pages(current, current->mm, base, mem->count,
+ write, 1, pages, NULL);
+ up_read(¤t->mm->mmap_sem);
+
+ if (count < 0) {
+ /* Kernel allocated buffer. */
+ for (i = 0; i < mem->count; i += 1) {
+ gcerror = virt2phys(base, &parray[i]);
+ if (gcerror != GCERR_NONE) {
+ GCERR("failed to convert virtual address.\n");
+ goto exit;
+ }
+
+ base += mem->pagesize;
+ }
+ } else if (count == mem->count) {
+ /* User allocated buffer. */
+ for (i = 0; i < mem->count; i += 1) {
+ parray[i] = page_to_phys(pages[i]);
+ if (phys_to_page(parray[i]) != pages[i]) {
+ GCERR("failed to convert page address.\n");
+ gcerror = GCERR_MMU_PAGE_BAD;
+ goto exit;
+ }
+ }
+
+ /* Set page descriptor array. */
+ arena->pages = pages;
+ } else {
+ GCERR("invalid number of pages.\n");
+ gcerror = GCERR_MMU_BUFFER_BAD;
+ goto exit;
+ }
+
+exit:
+ if (arena->pages == NULL) {
+ for (i = 0; i < count; i += 1)
+ page_cache_release(pages[i]);
+
+ if (pages != NULL)
+ kfree(pages);
+ }
+
+ GCEXIT(GCZONE_MAPPING);
+ return gcerror;
+}
+
+static void release_physical_pages(struct gcmmuarena *arena)
+{
+ unsigned int i;
+
+ if (arena->pages != NULL) {
+ for (i = 0; i < arena->count; i += 1)
+ page_cache_release(arena->pages[i]);
+
+ kfree(arena->pages);
+ arena->pages = NULL;
+ }
+}
+
+/*******************************************************************************
+ * MMU management API.
+ */
+
+enum gcerror gcmmu_init(struct gccorecontext *gccorecontext)
+{
+ enum gcerror gcerror;
+ struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+
+ GCENTER(GCZONE_INIT);
+
+ /* Initialize access lock. */
+ GCLOCK_INIT(&gcmmu->lock);
+
+ /* Allocate one page. */
+ gcerror = gc_alloc_noncached(&gcmmu->gcpage, PAGE_SIZE);
+ if (gcerror != GCERR_NONE) {
+ GCERR("failed to allocate MMU management buffer.\n");
+ gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_SAFE_ALLOC);
+ goto exit;
+ }
+
+ /* Determine the location of the physical command buffer. */
+ gcmmu->cmdbufphys = gcmmu->gcpage.physical;
+ gcmmu->cmdbuflog = gcmmu->gcpage.logical;
+ gcmmu->cmdbufsize = PAGE_SIZE - GCMMU_SAFE_ZONE_SIZE;
+
+ /* Determine the location of the safe zone. */
+ gcmmu->safezonephys = gcmmu->gcpage.physical + gcmmu->cmdbufsize;
+ gcmmu->safezonelog = (unsigned int *) ((unsigned char *)
+ gcmmu->gcpage.logical + gcmmu->cmdbufsize);
+ gcmmu->safezonesize = GCMMU_SAFE_ZONE_SIZE;
+
+ /* Reset the master table. */
+ gcmmu->master = ~0U;
+
+ /* Initialize the list of vacant arenas. */
+ INIT_LIST_HEAD(&gcmmu->vacarena);
+
+exit:
+ GCEXITARG(GCZONE_INIT, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+ return gcerror;
+}
+
+void gcmmu_exit(struct gccorecontext *gccorecontext)
+{
+ struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+ struct list_head *head;
+ struct gcmmuarena *arena;
+
+ GCENTER(GCZONE_INIT);
+
+ /* Free the safe zone. */
+ gc_free_noncached(&gcmmu->gcpage);
+
+ /* Free vacant arena list. */
+ while (!list_empty(&gcmmu->vacarena)) {
+ head = gcmmu->vacarena.next;
+ arena = list_entry(head, struct gcmmuarena, link);
+ list_del(head);
+ kfree(arena);
+ }
+
+ GCEXIT(GCZONE_INIT);
+}
+
+enum gcerror gcmmu_create_context(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ pid_t pid)
+{
+ enum gcerror gcerror;
+ struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+ struct gcmmuarena *arena = NULL;
+ unsigned int *logical;
+ unsigned int i;
+
+ GCENTER(GCZONE_CONTEXT);
+
+ if (gcmmucontext == NULL) {
+ gcerror = GCERR_MMU_CTXT_BAD;
+ goto exit;
+ }
+
+ /* Reset the context. */
+ memset(gcmmucontext, 0, sizeof(struct gcmmucontext));
+
+ /* Initialize access lock. */
+ GCLOCK_INIT(&gcmmucontext->lock);
+
+ /* Initialize arena lists. */
+ INIT_LIST_HEAD(&gcmmucontext->vacant);
+ INIT_LIST_HEAD(&gcmmucontext->allocated);
+
+ /* Mark context as dirty. */
+ gcmmucontext->dirty = true;
+
+ /* Set PID. */
+ gcmmucontext->pid = pid;
+
+ /* Allocate MTLB table. */
+#if USE_CACHED_MASTER
+ gcerror = gc_alloc_cached(&gcmmucontext->master, GCMMU_MTLB_SIZE);
+#else
+ gcerror = gc_alloc_noncached(&gcmmucontext->master, GCMMU_MTLB_SIZE);
+#endif
+ if (gcerror != GCERR_NONE) {
+ gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_MTLB_ALLOC);
+ goto exit;
+ }
+
+ /* Invalidate MTLB entries. */
+ logical = gcmmucontext->master.logical;
+ for (i = 0; i < GCMMU_MTLB_ENTRY_NUM; i += 1)
+ logical[i] = GCMMU_MTLB_ENTRY_VACANT;
+
+ /* Set MMU table mode. */
+ gcmmucontext->mmuconfig.reg.master_mask
+ = GCREG_MMU_CONFIGURATION_MASK_MODE_ENABLED;
+ gcmmucontext->mmuconfig.reg.master = GCMMU_MTLB_MODE;
+
+ /* Set the table address. */
+ gcmmucontext->mmuconfig.reg.address_mask
+ = GCREG_MMU_CONFIGURATION_MASK_ADDRESS_ENABLED;
+ gcmmucontext->mmuconfig.reg.address
+ = GCGETFIELD(gcmmucontext->master.physical,
+ GCREG_MMU_CONFIGURATION, ADDRESS);
+
+ /* Allocate the first vacant arena. */
+ gcerror = get_arena(gcmmu, &arena);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Entire range is currently vacant. */
+ arena->start.absolute = 0;
+ arena->end.absolute =
+ arena->count = GCMMU_MTLB_ENTRY_NUM * GCMMU_STLB_ENTRY_NUM;
+ list_add(&arena->link, &gcmmucontext->vacant);
+ GCDUMPARENA(GCZONE_ARENA, "initial vacant arena", arena);
+
+ /* Map the command queue. */
+ gcerror = gcqueue_map(gccorecontext, gcmmucontext);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Reference MMU. */
+ gcmmu->refcount += 1;
+
+ GCEXIT(GCZONE_CONTEXT);
+ return GCERR_NONE;
+
+exit:
+ gcmmu_destroy_context(gccorecontext, gcmmucontext);
+
+ GCEXITARG(GCZONE_CONTEXT, "gcerror = 0x%08X\n", gcerror);
+ return gcerror;
+}
+
+enum gcerror gcmmu_destroy_context(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext)
+{
+ enum gcerror gcerror;
+ struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+ struct list_head *head;
+ struct gcmmuarena *arena;
+ struct gcmmustlbblock *nextblock;
+
+ GCENTER(GCZONE_CONTEXT);
+
+ if (gcmmucontext == NULL) {
+ gcerror = GCERR_MMU_CTXT_BAD;
+ goto exit;
+ }
+
+ /* Unmap the command queue. */
+ gcerror = gcqueue_unmap(gccorecontext, gcmmucontext);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Free allocated arenas. */
+ while (!list_empty(&gcmmucontext->allocated)) {
+ head = gcmmucontext->allocated.next;
+ arena = list_entry(head, struct gcmmuarena, link);
+ release_physical_pages(arena);
+ list_move(head, &gcmmucontext->vacant);
+ }
+
+ /* Free slave tables. */
+ while (gcmmucontext->slavealloc != NULL) {
+#if USE_CACHED_SLAVE
+ gc_free_cached(&gcmmucontext->slavealloc->pages);
+#else
+ gc_free_noncached(&gcmmucontext->slavealloc->pages);
+#endif
+ nextblock = gcmmucontext->slavealloc->next;
+ kfree(gcmmucontext->slavealloc);
+ gcmmucontext->slavealloc = nextblock;
+ }
+
+ /* Reset the master table. */
+ if (gcmmu->master == gcmmucontext->mmuconfig.raw)
+ gcmmu->master = ~0U;
+
+ /* Free the master table. */
+#if USE_CACHED_MASTER
+ gc_free_cached(&gcmmucontext->master);
+#else
+ gc_free_noncached(&gcmmucontext->master);
+#endif
+
+ /* Free arenas. */
+ GCLOCK(&gcmmu->lock);
+ list_splice_init(&gcmmucontext->vacant, &gcmmu->vacarena);
+ GCUNLOCK(&gcmmu->lock);
+
+ /* Dereference. */
+ gcmmu->refcount -= 1;
+
+ GCEXIT(GCZONE_CONTEXT);
+ return GCERR_NONE;
+
+exit:
+ GCEXITARG(GCZONE_CONTEXT, "gcerror = 0x%08X\n", gcerror);
+ return gcerror;
+}
+
+enum gcerror gcmmu_enable(struct gccorecontext *gccorecontext,
+ struct gcqueue *gcqueue)
+{
+ enum gcerror gcerror;
+ struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+ struct list_head *head;
+ struct gccmdbuf *headcmdbuf;
+ struct gccmdbuf *gccmdbuf = NULL;
+ struct gcevent *gcevent = NULL;
+ struct gcmommuinit *gcmommuinit;
+ struct gcmosignal *gcmosignal;
+ struct gccmdend *gccmdend;
+ unsigned int status, enabled;
+
+ GCENTER(GCZONE_INIT);
+
+ /* Read the MMU status. */
+ status = gc_read_reg(GCREG_MMU_CONTROL_Address);
+ enabled = GCGETFIELD(status, GCREG_MMU_CONTROL, ENABLE);
+
+ /* Is MMU enabled? */
+ if (!enabled) {
+ GCDBG(GCZONE_MASTER, "enabling MMU.\n");
+
+ /* Queue cannot be empty. */
+ if (list_empty(&gcqueue->queue)) {
+ GCERR("queue is empty.");
+ gcerror = GCERR_MMU_INIT;
+ goto fail;
+ }
+
+ /* Get the first entry from the active queue. */
+ head = gcqueue->queue.next;
+ headcmdbuf = list_entry(head, struct gccmdbuf, link);
+
+ /* Allocate command init buffer. */
+ gcerror = gcqueue_alloc_cmdbuf(gcqueue, &gccmdbuf);
+ if (gcerror != GCERR_NONE)
+ goto fail;
+
+ /* Add event for the current command buffer. */
+ gcerror = gcqueue_alloc_event(gcqueue, &gcevent);
+ if (gcerror != GCERR_NONE)
+ goto fail;
+
+ /* Get free interrupt. */
+ gcerror = gcqueue_alloc_int(gcqueue, &gccmdbuf->interrupt);
+ if (gcerror != GCERR_NONE)
+ goto fail;
+
+ /* Initialize the event and add to the list. */
+ gcevent->handler = event_enable_mmu;
+
+ /* Attach records. */
+ list_add_tail(&gcevent->link, &gccmdbuf->events);
+ list_add(&gccmdbuf->link, &gcqueue->queue);
+
+ /* Program the safe zone and the master table address. */
+ gcmommuinit = (struct gcmommuinit *) gcmmu->cmdbuflog;
+ gcmommuinit->safe_ldst = gcmommuinit_safe_ldst;
+ gcmommuinit->safe = gcmmu->safezonephys;
+ gcmommuinit->mtlb = headcmdbuf->gcmmucontext->mmuconfig.raw;
+
+ /* Update the cached master */
+ gcmmu->master = gcmommuinit->mtlb;
+
+ /* Configure EVENT command. */
+ gcmosignal = (struct gcmosignal *) (gcmommuinit + 1);
+ gcmosignal->signal_ldst = gcmosignal_signal_ldst;
+ gcmosignal->signal.raw = 0;
+ gcmosignal->signal.reg.id = gccmdbuf->interrupt;
+ gcmosignal->signal.reg.pe = GCREG_EVENT_PE_SRC_ENABLE;
+
+ /* Configure the END command. */
+ gccmdend = (struct gccmdend *) (gcmosignal + 1);
+ gccmdend->cmd.raw = gccmdend_const.cmd.raw;
+
+ /* Initialize the command buffer. */
+ gccmdbuf->gcmmucontext = headcmdbuf->gcmmucontext;
+ gccmdbuf->logical = (unsigned char *) gcmmu->cmdbuflog;
+ gccmdbuf->physical = gcmmu->cmdbufphys;
+ gccmdbuf->size = sizeof(struct gcmommuinit)
+ + sizeof(struct gcmosignal)
+ + sizeof(struct gccmdend);
+ gccmdbuf->count = (gccmdbuf->size + 7) >> 3;
+ gccmdbuf->gcmoterminator = NULL;
+
+ GCDUMPBUFFER(GCZONE_INIT, gccmdbuf->logical,
+ gccmdbuf->physical, gccmdbuf->size);
+ }
+
+ GCEXIT(GCZONE_INIT);
+ return GCERR_NONE;
+
+fail:
+ if (gcevent != NULL)
+ gcqueue_free_event(gcqueue, gcevent);
+
+ if (gccmdbuf != NULL)
+ gcqueue_free_cmdbuf(gcqueue, gccmdbuf, NULL);
+
+ GCEXITARG(GCZONE_CONTEXT, "gcerror = 0x%08X\n", gcerror);
+ return gcerror;
+}
+
+enum gcerror gcmmu_set_master(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext)
+{
+ enum gcerror gcerror;
+ struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+ struct gcmommumaster *gcmommumaster;
+
+ GCENTER(GCZONE_MASTER);
+
+ if (gcmmucontext == NULL) {
+ gcerror = GCERR_MMU_CTXT_BAD;
+ goto exit;
+ }
+
+ /* Did the master change? */
+ if (gcmmu->master == gcmmucontext->mmuconfig.raw) {
+ gcerror = GCERR_NONE;
+ goto exit;
+ }
+
+ /* Flush required when switching mmu contexts */
+ gcmmucontext->dirty = true;
+
+ /* Allocate command buffer space. */
+ gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+ sizeof(struct gcmommumaster),
+ (void **) &gcmommumaster, NULL);
+ if (gcerror != GCERR_NONE) {
+ gcerror = GCERR_SETGRP(gcerror, GCERR_MMU_MTLB_SET);
+ goto exit;
+ }
+
+ /* Program master table address. */
+ gcmommumaster->master_ldst = gcmommumaster_master_ldst;
+ gcmommumaster->master = gcmmucontext->mmuconfig.raw;
+
+ /* Update master table address. */
+ gcmmu->master = gcmmucontext->mmuconfig.raw;
+
+exit:
+ GCEXITARG(GCZONE_MASTER, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+ return gcerror;
+}
+
+enum gcerror gcmmu_map(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ struct gcmmuphysmem *mem,
+ struct gcmmuarena **mapped)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ bool locked = false;
+ struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+ struct list_head *arenahead;
+ struct gcmmuarena *vacant = NULL, *split;
+ struct gcmmustlb *slave;
+ unsigned int *stlblogical;
+ union gcmmuloc index;
+ unsigned int i, allocated, count;
+ pte_t *parray_alloc = NULL;
+ pte_t *parray;
+
+ GCENTER(GCZONE_MAPPING);
+
+ if (gcmmucontext == NULL) {
+ gcerror = GCERR_MMU_CTXT_BAD;
+ goto exit;
+ }
+
+ if ((mem == NULL) || (mem->count <= 0) || (mapped == NULL) ||
+ ((mem->pagesize != 0) && (mem->pagesize != GCMMU_PAGE_SIZE))) {
+ gcerror = GCERR_MMU_ARG;
+ goto exit;
+ }
+
+ GCLOCK(&gcmmucontext->lock);
+ locked = true;
+
+ /*
+ * Find available sufficient arena.
+ */
+
+ GCDBG(GCZONE_MAPPING, "mapping (%d) pages\n", mem->count);
+
+ list_for_each(arenahead, &gcmmucontext->vacant) {
+ vacant = list_entry(arenahead, struct gcmmuarena, link);
+ if (vacant->count >= mem->count)
+ break;
+ }
+
+ if (arenahead == &gcmmucontext->vacant) {
+ gcerror = GCERR_MMU_OOM;
+ goto exit;
+ }
+
+ GCDUMPARENA(GCZONE_ARENA, "allocating from arena", vacant);
+
+ /*
+ * If page array isn't provided, create it here.
+ */
+
+ /* Reset page array. */
+ vacant->pages = NULL;
+
+ /* No page array given? */
+ if (mem->pages == NULL) {
+ /* Allocate physical address array. */
+ parray_alloc = kmalloc(mem->count * sizeof(pte_t *),
+ GFP_KERNEL);
+ if (parray_alloc == NULL) {
+ GCERR("failed to allocate page address array\n");
+ gcerror = GCERR_SETGRP(GCERR_OODM,
+ GCERR_MMU_PHYS_ALLOC);
+ goto exit;
+ }
+
+ /* Fetch page addresses. */
+ gcerror = get_physical_pages(mem, parray_alloc, vacant);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ parray = parray_alloc;
+
+ GCDBG(GCZONE_MAPPING,
+ "physical page array allocated (0x%08X)\n",
+ (unsigned int) parray);
+ } else {
+ parray = mem->pages;
+
+ GCDBG(GCZONE_MAPPING,
+ "physical page array provided (0x%08X)\n",
+ (unsigned int) parray);
+ }
+
+ /*
+ * Create the mapping.
+ */
+
+ index.absolute = vacant->start.absolute;
+ slave = &gcmmucontext->slave[index.loc.mtlb];
+ count = mem->count;
+
+ while (count > 0) {
+ /* Allocate slaves if not yet allocated. */
+ if (slave->logical == NULL) {
+ gcerror = allocate_slave(gcmmucontext, index);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+ }
+
+ /* Determine the number of entries allocated. */
+ allocated = GCMMU_STLB_ENTRY_NUM - index.loc.stlb;
+ if (allocated > count)
+ allocated = count;
+
+ /* Initialize slave entries. */
+ stlblogical = &slave->logical[index.loc.stlb];
+ for (i = 0; i < allocated; i += 1)
+ *stlblogical++
+ = (*parray++ & GCMMU_STLB_ADDRESS_MASK)
+ | GCMMU_STLB_PRESENT
+ | GCMMU_STLB_EXCEPTION
+ | GCMMU_STLB_WRITEABLE;
+
+#if USE_CACHED_SLAVE
+ /* Flush CPU cache. */
+ gc_flush_region(slave->physical, slave->logical,
+ index.loc.stlb * sizeof(unsigned int),
+ allocated * sizeof(unsigned int));
+#else
+ mb();
+#endif
+
+ GCDBG(GCZONE_MAPPING, "allocated %d pages at %d.%d\n",
+ allocated, index.loc.mtlb, index.loc.stlb);
+
+ /* Advance. */
+ slave += 1;
+ index.absolute += allocated;
+ count -= allocated;
+ }
+
+ /*
+ * Claim arena.
+ */
+
+ /* Split the arena. */
+ if (vacant->count != mem->count) {
+ GCDBG(GCZONE_MAPPING, "splitting vacant arena\n");
+
+ gcerror = get_arena(gcmmu, &split);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ split->start.absolute = index.absolute;
+ split->end.absolute = vacant->end.absolute;
+ split->count = vacant->count - mem->count;
+ list_add(&split->link, &vacant->link);
+
+ vacant->end.absolute = index.absolute;
+ vacant->count = mem->count;
+ }
+
+ GCDUMPARENA(GCZONE_ARENA, "allocated arena", vacant);
+
+ /* Move the vacant arena to the list of allocated arenas. */
+ list_move(&vacant->link, &gcmmucontext->allocated);
+
+ /* Set page size. */
+ mem->pagesize = GCMMU_PAGE_SIZE;
+
+ /* Determine the virtual address. */
+ vacant->address
+ = ((vacant->start.loc.mtlb << GCMMU_MTLB_SHIFT)
+ & GCMMU_MTLB_MASK)
+ | ((vacant->start.loc.stlb << GCMMU_STLB_SHIFT)
+ & GCMMU_STLB_MASK)
+ | (mem->offset & GCMMU_OFFSET_MASK);
+
+ /* Determine the size of the area. */
+ vacant->size = mem->count * GCMMU_PAGE_SIZE - mem->offset;
+
+ /* Invalidate the MMU. */
+ gcmmucontext->dirty = true;
+
+ /* Set the result. */
+ *mapped = vacant;
+
+ GCDBG(GCZONE_MAPPING, "mapped %d bytes at 0x%08X\n",
+ vacant->size, vacant->address);
+
+ /* Dump tables. */
+ GCDUMPMMU(GCZONE_DUMPMAP, gcmmucontext);
+
+exit:
+ if (parray_alloc != NULL) {
+ kfree(parray_alloc);
+
+ if (gcerror != GCERR_NONE)
+ release_physical_pages(vacant);
+ }
+
+ if (locked)
+ GCUNLOCK(&gcmmucontext->lock);
+
+ GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+ return gcerror;
+}
+
+enum gcerror gcmmu_unmap(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ struct gcmmuarena *mapped)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ bool locked = false;
+ struct gcmmu *gcmmu = &gccorecontext->gcmmu;
+ struct list_head *allochead, *prevhead, *nexthead;
+ struct gcmmuarena *allocated, *prevvacant, *nextvacant = NULL;
+ struct gcmmustlb *slave;
+ unsigned int *stlblogical;
+ union gcmmuloc index;
+ unsigned int i, freed, count;
+
+ GCENTER(GCZONE_MAPPING);
+
+ if (gcmmucontext == NULL) {
+ gcerror = GCERR_MMU_CTXT_BAD;
+ goto exit;
+ }
+
+ GCLOCK(&gcmmucontext->lock);
+ locked = true;
+
+ /*
+ * Find the arena.
+ */
+
+ GCDBG(GCZONE_MAPPING, "unmapping arena 0x%08X\n",
+ (unsigned int) mapped);
+
+ list_for_each(allochead, &gcmmucontext->allocated) {
+ allocated = list_entry(allochead, struct gcmmuarena, link);
+ if (allocated == mapped)
+ break;
+ }
+
+ if (allochead == &gcmmucontext->allocated) {
+ GCERR("mapped arena 0x%08X not found.\n",
+ (unsigned int) mapped);
+ gcerror = GCERR_MMU_ARG;
+ goto exit;
+ }
+
+ GCDBG(GCZONE_MAPPING, "mapped arena found:\n");
+ GCDBG(GCZONE_MAPPING, " arena phys = 0x%08X\n", allocated->address);
+ GCDBG(GCZONE_MAPPING, " arena size = %d\n", allocated->size);
+
+ /*
+ * Free slave tables.
+ */
+
+ index.absolute = allocated->start.absolute;
+ slave = &gcmmucontext->slave[index.loc.mtlb];
+ count = allocated->count;
+
+ while (count > 0) {
+ /* Determine the number of entries freed. */
+ freed = GCMMU_STLB_ENTRY_NUM - index.loc.stlb;
+ if (freed > count)
+ freed = count;
+
+ GCDBG(GCZONE_MAPPING, "freeing %d pages at %d.%d\n",
+ freed, index.loc.mtlb, index.loc.stlb);
+
+ /* Free slave entries. */
+ stlblogical = &slave->logical[index.loc.stlb];
+ for (i = 0; i < freed; i += 1)
+ *stlblogical++ = GCMMU_STLB_ENTRY_VACANT;
+
+#if USE_CACHED_SLAVE
+ /* Flush CPU cache. */
+ gc_flush_region(slave->physical, slave->logical,
+ index.loc.stlb * sizeof(unsigned int),
+ freed * sizeof(unsigned int));
+#else
+ mb();
+#endif
+
+ /* Advance. */
+ slave += 1;
+ index.absolute += freed;
+ count -= freed;
+ }
+
+ /*
+ * Delete page cache for the arena.
+ */
+
+ release_physical_pages(allocated);
+
+ /*
+ * Find point of insertion and free the arena.
+ */
+
+ GCDBG(GCZONE_MAPPING,
+ "looking for the point of insertion.\n");
+
+ list_for_each(nexthead, &gcmmucontext->vacant) {
+ nextvacant = list_entry(nexthead, struct gcmmuarena, link);
+ if (nextvacant->start.absolute >= allocated->end.absolute) {
+ GCDBG(GCZONE_MAPPING, " point of insertion found.\n");
+ break;
+ }
+ }
+
+ /* Get the previous vacant entry. */
+ prevhead = nexthead->prev;
+
+ /* Merge the area back into vacant list. */
+ if (siblings(&gcmmucontext->vacant, prevhead, allochead)) {
+ if (siblings(&gcmmucontext->vacant, allochead, nexthead)) {
+ prevvacant = list_entry(prevhead, struct gcmmuarena,
+ link);
+
+ GCDBG(GCZONE_MAPPING, "merging three arenas:\n");
+
+ GCDUMPARENA(GCZONE_ARENA, "previous arena", prevvacant);
+ GCDUMPARENA(GCZONE_ARENA, "allocated arena", allocated);
+ GCDUMPARENA(GCZONE_ARENA, "next arena", nextvacant);
+
+ /* Merge all three arenas. */
+ prevvacant->count += allocated->count;
+ prevvacant->count += nextvacant->count;
+ prevvacant->end.absolute = nextvacant->end.absolute;
+
+ /* Free the merged arenas. */
+ GCLOCK(&gcmmu->lock);
+ list_move(allochead, &gcmmu->vacarena);
+ list_move(nexthead, &gcmmu->vacarena);
+ GCUNLOCK(&gcmmu->lock);
+ } else {
+ prevvacant = list_entry(prevhead, struct gcmmuarena,
+ link);
+
+ GCDBG(GCZONE_MAPPING, "merging with the previous:\n");
+
+ GCDUMPARENA(GCZONE_ARENA, "previous arena", prevvacant);
+ GCDUMPARENA(GCZONE_ARENA, "allocated arena", allocated);
+
+ /* Merge with the previous. */
+ prevvacant->count += allocated->count;
+ prevvacant->end.absolute = allocated->end.absolute;
+
+ /* Free the merged arena. */
+ GCLOCK(&gcmmu->lock);
+ list_move(allochead, &gcmmu->vacarena);
+ GCUNLOCK(&gcmmu->lock);
+ }
+ } else if (siblings(&gcmmucontext->vacant, allochead, nexthead)) {
+ GCDBG(GCZONE_MAPPING, "merged with the next:\n");
+
+ GCDUMPARENA(GCZONE_ARENA, "allocated arena", allocated);
+ GCDUMPARENA(GCZONE_ARENA, "next arena", nextvacant);
+
+ /* Merge with the next arena. */
+ nextvacant->start.absolute = allocated->start.absolute;
+ nextvacant->count += allocated->count;
+
+ /* Free the merged arena. */
+ GCLOCK(&gcmmu->lock);
+ list_move(allochead, &gcmmu->vacarena);
+ GCUNLOCK(&gcmmu->lock);
+ } else {
+ GCDBG(GCZONE_MAPPING,
+ "nothing to merge with, inserting in between:\n");
+ GCDUMPARENA(GCZONE_ARENA, "allocated arena", allocated);
+
+ /* Neighbor vacant arenas are not siblings, can't merge. */
+ list_move(allochead, prevhead);
+ }
+
+ /* Invalidate the MMU. */
+ gcmmucontext->dirty = true;
+
+ /* Dump tables. */
+ GCDUMPMMU(GCZONE_DUMPUNMAP, gcmmucontext);
+
+exit:
+ if (locked)
+ GCUNLOCK(&gcmmucontext->lock);
+
+ GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+ return gcerror;
+}
+
+enum gcerror gcmmu_flush(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gcmommuflush *flushlogical;
+ unsigned int flushaddress;
+ struct gcqueue *gcqueue;
+
+ GCENTER(GCZONE_FLUSH);
+
+ GCLOCK(&gcmmucontext->lock);
+
+ if (gcmmucontext->dirty) {
+ /* Allocate space for the flush. */
+ gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+ sizeof(struct gcmommuflush),
+ (void **) &flushlogical, &flushaddress);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ /* Store flush information. */
+ gcqueue->flushlogical = flushlogical;
+ gcqueue->flushaddress = flushaddress;
+
+ /* Validate the context. */
+ gcmmucontext->dirty = false;
+ }
+
+exit:
+ GCUNLOCK(&gcmmucontext->lock);
+
+ GCEXITARG(GCZONE_FLUSH, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+ return gcerror;
+}
+
+void gcmmu_flush_finalize(struct gccmdbuf *gccmdbuf,
+ struct gcmommuflush *flushlogical,
+ unsigned int flushaddress)
+{
+ int size;
+ unsigned int datacount;
+
+ GCENTER(GCZONE_FLUSH);
+
+ /* Compute the size of the command buffer after the flush block */
+ size = gccmdbuf->physical + gccmdbuf->size
+ - flushaddress - sizeof(struct gcmommuflush);
+
+ /* Compute the data count. */
+ datacount = (size + 7) >> 3;
+
+ /* Flush 2D PE cache. */
+ flushlogical->peflush.flush_ldst = gcmoflush_flush_ldst;
+ flushlogical->peflush.flush.reg = gcregflush_pe2D;
+
+ /* Arm the FE-PE semaphore. */
+ flushlogical->peflushsema.sema_ldst = gcmosema_sema_ldst;
+ flushlogical->peflushsema.sema.reg = gcregsema_fe_pe;
+
+ /* Stall FE until PE is done flushing. */
+ flushlogical->peflushstall.cmd.fld = gcfldstall;
+ flushlogical->peflushstall.arg.fld = gcfldstall_fe_pe;
+
+ /* LINK to the next slot to flush FE FIFO. */
+ flushlogical->feflush.cmd.fld = gcfldlink4;
+ flushlogical->feflush.address
+ = flushaddress
+ + offsetof(struct gcmommuflush, mmuflush_ldst);
+
+ /* Flush MMU cache. */
+ flushlogical->mmuflush_ldst = gcmommuflush_mmuflush_ldst;
+ flushlogical->mmuflush.reg = gcregmmu_flush;
+
+ /* Arm the FE-PE semaphore. */
+ flushlogical->mmuflushsema.sema_ldst = gcmosema_sema_ldst;
+ flushlogical->mmuflushsema.sema.reg = gcregsema_fe_pe;
+
+ /* Stall FE until PE is done flushing. */
+ flushlogical->mmuflushstall.cmd.fld = gcfldstall;
+ flushlogical->mmuflushstall.arg.fld = gcfldstall_fe_pe;
+
+ /* LINK to the next slot to flush FE FIFO. */
+ flushlogical->link.cmd.fld.opcode = GCREG_COMMAND_OPCODE_LINK;
+ flushlogical->link.cmd.fld.count = datacount;
+ flushlogical->link.address = flushaddress + sizeof(struct gcmommuflush);
+
+ GCEXIT(GCZONE_FLUSH);
+}
+
+enum gcerror gcmmu_fixup(struct list_head *fixuplist,
+ unsigned int *data)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct list_head *head;
+ struct gcfixup *gcfixup;
+ struct gcfixupentry *table;
+ struct gcmmuarena *arena;
+ unsigned int dataoffset;
+ unsigned int i;
+
+ GCENTER(GCZONE_FIXUP);
+
+ /* Process fixups. */
+ list_for_each(head, fixuplist) {
+ gcfixup = list_entry(head, struct gcfixup, link);
+
+ GCDBG(GCZONE_FIXUP, "%d fixup(s) @ 0x%08X\n",
+ gcfixup->count, (unsigned int) gcfixup);
+
+ /* Apply fixups. */
+ table = gcfixup->fixup;
+ for (i = 0; i < gcfixup->count; i += 1) {
+ GCDBG(GCZONE_FIXUP, "#%d\n", i);
+ GCDBG(GCZONE_FIXUP, " buffer offset = 0x%08X\n",
+ table->dataoffset * 4);
+ GCDBG(GCZONE_FIXUP, " surface offset = 0x%08X\n",
+ table->surfoffset);
+
+ dataoffset = table->dataoffset;
+
+ arena = (struct gcmmuarena *) data[dataoffset];
+ if (!virt_addr_valid(arena)) {
+ GCERR("bad arena @ 0x%08X\n",
+ (unsigned int) arena);
+ gcerror = GCERR_OODM;
+ goto exit;
+ }
+
+ GCDBG(GCZONE_FIXUP, " arena = 0x%08X\n",
+ (unsigned int) arena);
+ GCDBG(GCZONE_FIXUP, " arena phys = 0x%08X\n",
+ arena->address);
+ GCDBG(GCZONE_FIXUP, " arena size = %d\n",
+ arena->size);
+
+ data[dataoffset] = arena->address + table->surfoffset;
+
+ GCDBG(GCZONE_FIXUP, " surface @ 0x%08X\n",
+ data[dataoffset]);
+
+ table += 1;
+ }
+ }
+
+exit:
+ GCEXITARG(GCZONE_FIXUP, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+ return gcerror;
+}
diff --git a/drivers/misc/gcx/gccore/gcmmu.h b/drivers/misc/gcx/gccore/gcmmu.h
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * gcmmu.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCMMU_H
+#define GCMMU_H
+
+#include <linux/gccore.h>
+#include "gcmem.h"
+#include "gcqueue.h"
+
+/*******************************************************************************
+ * Master table can be configured in 1KB mode with 256 maximum entries
+ * or 4KB mode with 1024 maximum entries.
+ *
+ * Address bit allocation.
+ * +------+------+--------+
+ * | MTLB | STLB | Offset |
+ * +------+------+--------+
+ *
+ * # of address bits | # of address bits | Page | Addressable | Total
+ * / | / | size | per one | addressable
+ * # of MTLB entries | # of STLB entries | | MTLB entry |
+ * ------------------+-------------------+------+-------------+------------
+ * 8 / 256 | 4 / 16 | 1MB | |
+ * | 8 / 256 | 64KB | 16MB | 4GB
+ * | 12 / 4096 | 4KB | |
+ * ------------------+-------------------+------+-------------+------------
+ * 10 / 1024 | 6 / 64 | 64KB | |
+ * | 10 / 1024 | 4KB | 4MB | 4GB
+ */
+
+/* Page size. */
+#define GCMMU_PAGE_SIZE 4096
+
+/* Master table definitions. */
+#define GCMMU_MTLB_BITS 8
+#define GCMMU_MTLB_ENTRY_NUM (1 << GCMMU_MTLB_BITS)
+#define GCMMU_MTLB_SIZE (GCMMU_MTLB_ENTRY_NUM << 2)
+#define GCMMU_MTLB_SHIFT (32 - GCMMU_MTLB_BITS)
+#define GCMMU_MTLB_MASK (((1U << GCMMU_MTLB_BITS) - 1) \
+ << GCMMU_MTLB_SHIFT)
+
+#if GCMMU_MTLB_BITS == 8
+# define GCMMU_MTLB_MODE GCREG_MMU_CONFIGURATION_MODE_MODE1_K
+#elif GCMMU_MTLB_BITS == 10
+# define GCMMU_MTLB_MODE GCREG_MMU_CONFIGURATION_MODE_MODE4_K
+#else
+# error Invalid GCMMU_MTLB_BITS.
+#endif
+
+#define GCMMU_MTLB_PRESENT_MASK 0x00000001
+#define GCMMU_MTLB_EXCEPTION_MASK 0x00000002
+#define GCMMU_MTLB_PAGE_SIZE_MASK 0x0000000C
+#define GCMMU_MTLB_SLAVE_MASK 0xFFFFFFC0
+
+#define GCMMU_MTLB_PRESENT 0x00000001
+#define GCMMU_MTLB_EXCEPTION 0x00000002
+#define GCMMU_MTLB_4K_PAGE 0x00000000
+
+#define GCMMU_MTLB_ENTRY_VACANT GCMMU_MTLB_EXCEPTION
+
+/* Slave table definitions. */
+#define GCMMU_STLB_BITS 12
+#define GCMMU_STLB_ENTRY_NUM (1 << GCMMU_STLB_BITS)
+#define GCMMU_STLB_SIZE (GCMMU_STLB_ENTRY_NUM << 2)
+#define GCMMU_STLB_SHIFT (32 - (GCMMU_MTLB_BITS \
+ + GCMMU_STLB_BITS))
+#define GCMMU_STLB_MASK (((1U << GCMMU_STLB_BITS) - 1) \
+ << GCMMU_STLB_SHIFT)
+
+#define GCMMU_STLB_PRESENT_MASK 0x00000001
+#define GCMMU_STLB_EXCEPTION_MASK 0x00000002
+#define GCMMU_STLB_WRITEABLE_MASK 0x00000004
+#define GCMMU_STLB_ADDRESS_MASK 0xFFFFF000
+
+#define GCMMU_STLB_PRESENT 0x00000001
+#define GCMMU_STLB_EXCEPTION 0x00000002
+#define GCMMU_STLB_WRITEABLE 0x00000004
+
+#define GCMMU_STLB_ENTRY_VACANT GCMMU_STLB_EXCEPTION
+
+/* Page offset definitions. */
+#define GCMMU_OFFSET_BITS (32 - GCMMU_MTLB_BITS - GCMMU_STLB_BITS)
+#define GCMMU_OFFSET_MASK ((1U << GCMMU_OFFSET_BITS) - 1)
+
+#define GCMMU_SAFE_ZONE_SIZE 64
+
+/* STLB preallocation count. This value controls how many slave tables will be
+ * allocated every time we run out of available slave tables during mapping.
+ * The value must be between 1 and the total number of slave tables possible,
+ * which is equal to 256 assuming 4KB page size. */
+#define GCMMU_STLB_PREALLOC_COUNT (GCMMU_MTLB_ENTRY_NUM / 4)
+
+
+/*******************************************************************************
+ * MMU structures.
+ */
+
+/* This union defines a location within MMU. */
+union gcmmuloc {
+ struct _loc {
+ unsigned int stlb:GCMMU_STLB_BITS;
+ unsigned int mtlb:GCMMU_MTLB_BITS;
+ } loc;
+
+ unsigned int absolute;
+};
+
+/* Arenas describe memory regions. Two lists of areanas are maintained:
+ * one that defines a list of vacant arenas ready to map and the other
+ * a list of already mapped arenas. */
+struct gcmmuarena {
+ /* Arena starting and ending points. */
+ union gcmmuloc start;
+ union gcmmuloc end;
+
+ /* Number of pages. */
+ unsigned int count;
+
+ /* Mapped virtual pointer. */
+ unsigned int address;
+
+ /* Client's virtual pointer. */
+ void *logical;
+
+ /* Size of the mapped buffer. */
+ unsigned int size;
+
+ /* Page descriptor array. */
+ struct page **pages;
+
+ /* Prev/next arena. */
+ struct list_head link;
+};
+
+/* MMU shared object. */
+struct gcmmu {
+ /* Access lock. */
+ GCLOCK_TYPE lock;
+
+ /* Reference count. */
+ int refcount;
+
+ /* One physical page used for MMU management. */
+ struct gcpage gcpage;
+
+ /* Physical command buffer. */
+ unsigned int cmdbufphys;
+ unsigned int *cmdbuflog;
+ unsigned int cmdbufsize;
+
+ /* Safe zone location. */
+ unsigned int safezonephys;
+ unsigned int *safezonelog;
+ unsigned int safezonesize;
+
+ /* Currently set master table. */
+ unsigned int master;
+
+ /* Available page allocation arenas. */
+ struct list_head vacarena;
+};
+
+/* Slave table descriptor. */
+struct gcmmustlb {
+ unsigned int physical;
+ unsigned int *logical;
+};
+
+struct gcmmustlbblock;
+struct gcmmucontext {
+ /* Access lock. */
+ GCLOCK_TYPE lock;
+
+ /* PID of the owner process. */
+ pid_t pid;
+
+ /* If marked as dirty, MMU cache needs to be flushed. */
+ bool dirty;
+
+ /* Master table allocation. */
+ struct gcpage master;
+
+ /* Slave table descriptors. */
+ struct gcmmustlb slave[GCMMU_MTLB_ENTRY_NUM];
+ struct gcmmustlbblock *slavealloc;
+
+ /* MMU configuration. */
+ union mmuconfig {
+ struct gcregmmuconfiguration reg;
+ unsigned int raw;
+ } mmuconfig;
+
+ unsigned long physical;
+
+ /* Page mapping tracking. */
+ struct list_head vacant;
+ struct list_head allocated;
+
+ /* Driver instance has only one set of command buffers that must be
+ * mapped the same exact way in all clients. This array stores
+ * pointers to arena structures of mapped storage buffers. */
+ struct gcmmuarena *storagearray[GC_STORAGE_COUNT];
+
+ /* Prev/next context. */
+ struct list_head link;
+};
+
+
+/*******************************************************************************
+ * MMU management API.
+ */
+
+struct gcmmuphysmem {
+ /* Virtual pointer and offset of the first page to map. */
+ unsigned int base;
+ unsigned int offset;
+
+ /* An array of physical addresses of the pages to map. */
+ unsigned int count;
+ pte_t *pages;
+
+ /* 0 => system default. */
+ int pagesize;
+};
+
+struct gccorecontext;
+
+enum gcerror gcmmu_init(struct gccorecontext *gccorecontext);
+void gcmmu_exit(struct gccorecontext *gccorecontext);
+
+enum gcerror gcmmu_create_context(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ pid_t pid);
+enum gcerror gcmmu_destroy_context(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext);
+
+enum gcerror gcmmu_enable(struct gccorecontext *gccorecontext,
+ struct gcqueue *gcqueue);
+enum gcerror gcmmu_set_master(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext);
+
+enum gcerror gcmmu_map(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ struct gcmmuphysmem *mem,
+ struct gcmmuarena **mapped);
+enum gcerror gcmmu_unmap(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ struct gcmmuarena *mapped);
+
+enum gcerror gcmmu_flush(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext);
+void gcmmu_flush_finalize(struct gccmdbuf *openentry,
+ struct gcmommuflush *flushlogical,
+ unsigned int flushaddress);
+
+enum gcerror gcmmu_fixup(struct list_head *fixuplist,
+ unsigned int *data);
+
+#endif
diff --git a/drivers/misc/gcx/gccore/gcqueue.c b/drivers/misc/gcx/gccore/gcqueue.c
--- /dev/null
@@ -0,0 +1,1659 @@
+/*
+ * gcqueue.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/interrupt.h>
+#include <asm/cacheflush.h>
+#include "gcmain.h"
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_INIT (1 << 0)
+#define GCZONE_ISR (1 << 1)
+#define GCZONE_THREAD (1 << 2)
+#define GCZONE_INTERRUPT (1 << 3)
+#define GCZONE_BUFFER (1 << 4)
+#define GCZONE_EVENT (1 << 5)
+#define GCZONE_QUEUE (1 << 6)
+#define GCZONE_MAPPING (1 << 7)
+#define GCZONE_ALLOC (1 << 8)
+#define GCZONE_EXEC (1 << 9)
+
+GCDBG_FILTERDEF(queue, GCZONE_NONE,
+ "init",
+ "isr",
+ "thread",
+ "interrupt",
+ "buffer",
+ "event",
+ "queue",
+ "mapping",
+ "alloc",
+ "exec")
+
+#define GCDBG_QUEUE(zone, message, gccmdbuf) { \
+ GCDBG(zone, message "queue entry @ 0x%08X:\n", \
+ (unsigned int) gccmdbuf); \
+ GCDBG(zone, " logical = 0x%08X\n", \
+ (unsigned int) gccmdbuf->logical); \
+ GCDBG(zone, " physical = 0x%08X\n", \
+ gccmdbuf->physical); \
+ GCDBG(zone, " size = %d, count = %d\n", \
+ gccmdbuf->size, gccmdbuf->count); \
+ GCDBG(zone, " terminator = 0x%08X\n", \
+ (unsigned int) gccmdbuf->gcmoterminator); \
+ GCDBG(zone, " int = %d\n", \
+ gccmdbuf->interrupt); \
+ GCDBG(zone, " %s\n", \
+ list_empty(&gccmdbuf->events) ? "no events" : "has events"); \
+}
+
+
+/*******************************************************************************
+ * Internal definitions.
+ */
+
+/* GPU timeout in milliseconds. The timeout value controls when the power
+ * on the GPU is pulled if there is no activity in progress or scheduled. */
+#define GC_THREAD_TIMEOUT 20
+
+/* Time in milliseconds to wait for GPU to become idle. */
+#define GC_IDLE_TIMEOUT 100
+
+/* The size of storage buffer. */
+#define GC_STORAGE_SIZE ((GC_BUFFER_SIZE * GC_CMDBUF_FACTOR + \
+ (PAGE_SIZE - 1)) & PAGE_MASK)
+
+/* Number of pages per one kernel storage buffer. */
+#define GC_STORAGE_PAGES (GC_STORAGE_SIZE / PAGE_SIZE)
+
+/* Reserved number of bytes at the end of storage buffer. */
+#define GC_TAIL_RESERVE sizeof(struct gcmoterminator)
+
+/* Minimum available space requirement. */
+#define GC_MIN_THRESHOLD ((int) (GC_TAIL_RESERVE + 200))
+
+/* Event assignment. */
+#define GC_SIG_BUS_ERROR 31
+#define GC_SIG_MMU_ERROR 30
+#define GC_SIG_DMA_DONE_BITS 30
+
+#define GC_SIG_MASK_BUS_ERROR (1 << GC_SIG_BUS_ERROR)
+#define GC_SIG_MASK_MMU_ERROR (1 << GC_SIG_MMU_ERROR)
+#define GC_SIG_MASK_DMA_DONE ((1 << GC_SIG_DMA_DONE_BITS) - 1)
+
+
+/*******************************************************************************
+ * ISR.
+ */
+
+static irqreturn_t gcisr(int irq, void *_gccorecontext)
+{
+ struct gccorecontext *gccorecontext;
+ struct gcqueue *gcqueue;
+ unsigned int triggered;
+
+ /* Read gcregIntrAcknowledge register. */
+ triggered = gc_read_reg(GCREG_INTR_ACKNOWLEDGE_Address);
+
+ /* Return if not our interrupt. */
+ if (triggered == 0)
+ return IRQ_NONE;
+
+ /* Cast the context. */
+ gccorecontext = (struct gccorecontext *) _gccorecontext;
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ /* Log interrupt data. */
+ gc_debug_cache_gpu_status_from_irq(triggered);
+
+ /* Bus error? */
+ if ((triggered & GC_SIG_MASK_BUS_ERROR) != 0) {
+ triggered &= ~GC_SIG_MASK_BUS_ERROR;
+ complete(&gcqueue->buserror);
+ }
+
+ /* MMU error? */
+ if ((triggered & GC_SIG_MASK_MMU_ERROR) != 0) {
+ triggered &= ~GC_SIG_MASK_MMU_ERROR;
+ complete(&gcqueue->mmuerror);
+ }
+
+ /* Command buffer event? */
+ if (triggered != 0)
+ atomic_add(triggered, &gcqueue->triggered);
+
+ /* Release the command buffer thread. */
+ complete(&gcqueue->ready);
+
+ /* IRQ handled. */
+ return IRQ_HANDLED;
+}
+
+
+/*******************************************************************************
+ * Command buffer event and queue management.
+ */
+
+enum gcerror gcqueue_alloc_event(struct gcqueue *gcqueue,
+ struct gcevent **gcevent)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gcevent *temp;
+
+ GCENTER(GCZONE_EVENT);
+
+ GCLOCK(&gcqueue->vaceventlock);
+
+ if (list_empty(&gcqueue->vacevents)) {
+ GCDBG(GCZONE_EVENT, "allocating event entry.\n");
+ temp = kmalloc(sizeof(struct gcevent), GFP_KERNEL);
+ if (temp == NULL) {
+ GCERR("event entry allocation failed.\n");
+ gcerror = GCERR_CMD_EVENT_ALLOC;
+ goto exit;
+ }
+ } else {
+ struct list_head *head;
+ head = gcqueue->vacevents.next;
+ temp = list_entry(head, struct gcevent, link);
+ list_del(head);
+ }
+
+ GCDBG(GCZONE_EVENT, "event entry allocated @ 0x%08X.\n",
+ (unsigned int) temp);
+
+ *gcevent = temp;
+
+exit:
+ GCUNLOCK(&gcqueue->vaceventlock);
+
+ GCEXITARG(GCZONE_EVENT, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+ return gcerror;
+}
+
+enum gcerror gcqueue_free_event(struct gcqueue *gcqueue,
+ struct gcevent *gcevent)
+{
+ GCENTER(GCZONE_EVENT);
+
+ GCLOCK(&gcqueue->vaceventlock);
+ list_move(&gcevent->link, &gcqueue->vacevents);
+ GCUNLOCK(&gcqueue->vaceventlock);
+
+ GCEXIT(GCZONE_EVENT);
+ return GCERR_NONE;
+}
+
+enum gcerror gcqueue_alloc_cmdbuf(struct gcqueue *gcqueue,
+ struct gccmdbuf **gccmdbuf)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gccmdbuf *temp;
+
+ GCENTER(GCZONE_QUEUE);
+
+ GCLOCK(&gcqueue->vacqueuelock);
+
+ if (list_empty(&gcqueue->vacqueue)) {
+ GCDBG(GCZONE_QUEUE, "allocating queue entry.\n");
+ temp = kmalloc(sizeof(struct gccmdbuf), GFP_KERNEL);
+ if (temp == NULL) {
+ GCERR("queue entry allocation failed.\n");
+ gcerror = GCERR_CMD_QUEUE_ALLOC;
+ goto exit;
+ }
+ } else {
+ struct list_head *head;
+ head = gcqueue->vacqueue.next;
+ temp = list_entry(head, struct gccmdbuf, link);
+ list_del(head);
+ }
+
+ INIT_LIST_HEAD(&temp->events);
+
+ GCDBG(GCZONE_EVENT, "queue entry allocated @ 0x%08X.\n",
+ (unsigned int) temp);
+
+ *gccmdbuf = temp;
+
+exit:
+ GCUNLOCK(&gcqueue->vacqueuelock);
+
+ GCEXITARG(GCZONE_QUEUE, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+ return gcerror;
+}
+
+void gcqueue_free_cmdbuf(struct gcqueue *gcqueue,
+ struct gccmdbuf *gccmdbuf,
+ unsigned int *flags)
+{
+ struct list_head *head;
+ struct gcevent *gcevent;
+
+ GCENTERARG(GCZONE_QUEUE, "queue entry = 0x%08X\n",
+ (unsigned int) gccmdbuf);
+
+ /* Have events? */
+ if (!list_empty(&gccmdbuf->events)) {
+ /* Events not expected? */
+ if (flags == NULL)
+ GCERR("buffer has events.\n");
+
+ /* Execute and free all events. */
+ while (!list_empty(&gccmdbuf->events)) {
+ head = gccmdbuf->events.next;
+ gcevent = list_entry(head, struct gcevent, link);
+ gcevent->handler(gcevent, flags);
+ gcqueue_free_event(gcqueue, gcevent);
+ }
+ }
+
+ /* Move the queue entry to the vacant list. */
+ GCLOCK(&gcqueue->vacqueuelock);
+ list_move(&gccmdbuf->link, &gcqueue->vacqueue);
+ GCUNLOCK(&gcqueue->vacqueuelock);
+
+ GCEXIT(GCZONE_QUEUE);
+}
+
+
+/*******************************************************************************
+ * Event handlers.
+ */
+
+/* Completion event. */
+static void event_completion(struct gcevent *gcevent, unsigned int *flags)
+{
+ struct completion *completion;
+
+ GCENTER(GCZONE_EVENT);
+
+ completion = gcevent->event.completion.completion;
+ GCDBG(GCZONE_EVENT, "completion = 0x%08X\n",
+ (unsigned int) completion);
+
+ complete(completion);
+
+ GCEXIT(GCZONE_EVENT);
+}
+
+/* Callback event. */
+static void event_callback(struct gcevent *gcevent, unsigned int *flags)
+{
+ void (*callback) (void *callbackparam);
+ void *callbackparam;
+
+ GCENTER(GCZONE_EVENT);
+
+ callback = gcevent->event.callback.callback;
+ callbackparam = gcevent->event.callback.callbackparam;
+ GCDBG(GCZONE_EVENT, "callback = 0x%08X\n",
+ (unsigned int) callback);
+ GCDBG(GCZONE_EVENT, "callbackparam = 0x%08X\n",
+ (unsigned int) callbackparam);
+
+ callback(callbackparam);
+
+ GCEXIT(GCZONE_EVENT);
+}
+
+/* Unmap event. */
+static void event_unmap(struct gcevent *gcevent, unsigned int *flags)
+{
+ enum gcerror gcerror;
+ struct gccorecontext *gccorecontext;
+ struct gcmmucontext *gcmmucontext;
+ struct gcmmuarena *gcmmuarena;
+
+ GCENTER(GCZONE_EVENT);
+
+ gccorecontext = gcevent->event.unmap.gccorecontext;
+ gcmmucontext = gcevent->event.unmap.gcmmucontext;
+ gcmmuarena = gcevent->event.unmap.gcmmuarena;
+
+ GCDBG(GCZONE_EVENT, "arena = 0x%08X\n",
+ (unsigned int) gcmmuarena);
+
+ gcerror = gcmmu_unmap(gccorecontext, gcmmucontext, gcmmuarena);
+ if (gcerror != GCERR_NONE)
+ GCERR("failed to unmap 0x%08X (gcerror = 0x%08X).\n",
+ gcmmuarena, gcerror);
+
+ GCEXIT(GCZONE_EVENT);
+}
+
+
+/*******************************************************************************
+ * Command buffer thread.
+ */
+
+enum gcerror gcqueue_alloc_int(struct gcqueue *gcqueue,
+ unsigned int *interrupt)
+{
+ unsigned int i;
+
+ GCENTER(GCZONE_INTERRUPT);
+
+ /* Wait until there are available interrupts. */
+ GCWAIT_FOR_COMPLETION(&gcqueue->freeint);
+
+ /* Get acceess to the interrupt tracker. */
+ GCLOCK(&gcqueue->intusedlock);
+
+ /* Find the first available interrupt. */
+ for (i = 0; i < countof(gcqueue->intused); i += 1)
+ if (!gcqueue->intused[i]) {
+ gcqueue->intused[i] = true;
+
+ /* Release access to the interrupt tracker. */
+ GCUNLOCK(&gcqueue->intusedlock);
+ *interrupt = i;
+
+ GCEXITARG(GCZONE_INTERRUPT, "interrupt = %d.\n", i);
+ return GCERR_NONE;
+ }
+
+ /* Release access to the interrupt tracker. */
+ GCUNLOCK(&gcqueue->intusedlock);
+
+ /* This is unexpected. */
+ GCERR("unexpected condition.");
+
+ GCEXIT(GCZONE_INTERRUPT);
+ return GCERR_CMD_INT_ALLOC;
+}
+
+static void free_interrupt(struct gcqueue *gcqueue, unsigned int interrupt)
+{
+ GCENTERARG(GCZONE_INTERRUPT, "interrupt = %d.\n", interrupt);
+
+ GCLOCK(&gcqueue->intusedlock);
+
+ if (!gcqueue->intused[interrupt]) {
+ GCERR("interrupt %d is already free.\n", interrupt);
+ GCUNLOCK(&gcqueue->intusedlock);
+ } else {
+ gcqueue->intused[interrupt] = false;
+ GCUNLOCK(&gcqueue->intusedlock);
+
+ complete(&gcqueue->freeint);
+ }
+
+ GCEXIT(GCZONE_INTERRUPT);
+}
+
+static void link_queue(struct list_head *newlist,
+ struct list_head *queue,
+ struct gcmoterminator *gcmoterminator)
+{
+ struct list_head *head;
+ struct gccmdbuf *gccmdbuf;
+ struct gccmdlink gccmdlink;
+
+ GCENTER(GCZONE_QUEUE);
+
+ if (!list_empty(queue)) {
+ GCDBG(GCZONE_QUEUE, "main queue is not empty.\n");
+
+ /* Get the tail of the queue. */
+ head = queue->prev;
+ gccmdbuf = list_entry(head, struct gccmdbuf, link);
+ gcmoterminator = gccmdbuf->gcmoterminator;
+
+ /* Link the tail command buffer from the specified queue to
+ * the first command buffer in the specified list. If the tail
+ * command buffer has no events associated with it, the
+ * interrupt is not needed. */
+ if (list_empty(&gccmdbuf->events)) {
+ /* Replace EVENT with a NOP. */
+ GCDBG_QUEUE(GCZONE_QUEUE, "removing interrupt from ",
+ gccmdbuf);
+ gcmoterminator->u1.nop.cmd.raw = gccmdnop_const.cmd.raw;
+ mb();
+ }
+ }
+
+ if (gcmoterminator != NULL) {
+ GCDBG(GCZONE_QUEUE, "modifying the terminator @ 0x%08X.\n",
+ gcmoterminator);
+
+ /* Get the head of the list. */
+ head = newlist->next;
+ gccmdbuf = list_entry(head, struct gccmdbuf, link);
+
+ /* Configure new command word. */
+ gccmdlink.cmd.raw = 0;
+ gccmdlink.cmd.fld.count = gccmdbuf->count;
+ gccmdlink.cmd.fld.opcode = GCREG_COMMAND_OPCODE_LINK;
+
+ /* Change WAIT into a LINK command; write the address first. */
+ gcmoterminator->u2.linknext.address = gccmdbuf->physical;
+ mb();
+ gcmoterminator->u2.linknext.cmd.raw = gccmdlink.cmd.raw;
+ mb();
+ }
+
+ /* Merge the list to the end of the queue. */
+ list_splice_tail_init(newlist, queue);
+
+ GCEXIT(GCZONE_QUEUE);
+}
+
+static enum gcerror append_cmdbuf(
+ struct gccorecontext *gccorecontext,
+ struct gcqueue *gcqueue)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gccmdbuf *headcmdbuf, *tailcmdbuf;
+ struct list_head *head, *tail;
+
+ /* Dump scheduled command buffers. */
+#if GCDEBUG_ENABLE
+ list_for_each(head, &gcqueue->cmdbufhead) {
+ headcmdbuf = list_entry(head, struct gccmdbuf, link);
+
+ GCDUMPBUFFER(GCZONE_BUFFER,
+ headcmdbuf->logical,
+ headcmdbuf->physical,
+ headcmdbuf->size);
+ }
+#endif
+
+ GCLOCK(&gcqueue->queuelock);
+
+ /* Link the tail of the active command buffer to
+ * the first scheduled command buffer. */
+ link_queue(&gcqueue->cmdbufhead, &gcqueue->queue,
+ gcqueue->gcmoterminator);
+
+ /* Get the last entry from the active queue. */
+ tail = gcqueue->queue.prev;
+ tailcmdbuf = list_entry(tail, struct gccmdbuf, link);
+
+ /* Update the tail pointer. */
+ gcqueue->gcmoterminator = tailcmdbuf->gcmoterminator;
+
+ /* Start the GPU if not already running. */
+ if (try_wait_for_completion(&gcqueue->stopped)) {
+ GCDBG(GCZONE_THREAD, "GPU is currently stopped - starting.\n");
+
+ /* Enable power to the chip. */
+ gcpwr_set(gccorecontext, GCPWR_ON);
+
+ /* Eable MMU. */
+ gcerror = gcmmu_enable(gccorecontext, gcqueue);
+ if (gcerror != GCERR_NONE) {
+ GCERR("failed to enable MMU.\n");
+ goto exit;
+ }
+
+ /* Get the first entry from the active queue. */
+ head = gcqueue->queue.next;
+ headcmdbuf = list_entry(head, struct gccmdbuf, link);
+
+ GCDBG_QUEUE(GCZONE_THREAD, "starting ", headcmdbuf);
+
+ /* Enable all events. */
+ gc_write_reg(GCREG_INTR_ENBL_Address, ~0U);
+
+ /* Write address register. */
+ gc_write_reg(GCREG_CMD_BUFFER_ADDR_Address,
+ headcmdbuf->physical);
+
+ /* Write control register. */
+ gc_write_reg(GCREG_CMD_BUFFER_CTRL_Address,
+ GCSETFIELDVAL(0, GCREG_CMD_BUFFER_CTRL,
+ ENABLE, ENABLE) |
+ GCSETFIELD(0, GCREG_CMD_BUFFER_CTRL,
+ PREFETCH, headcmdbuf->count));
+
+ /* Release the command buffer thread. */
+ complete(&gcqueue->ready);
+ }
+
+exit:
+ /* Unlock queue acccess. */
+ GCUNLOCK(&gcqueue->queuelock);
+
+ return gcerror;
+}
+
+static int gccmdthread(void *_gccorecontext)
+{
+ struct gccorecontext *gccorecontext;
+ struct gcqueue *gcqueue;
+ unsigned long timeout, signaled;
+ unsigned int i, triggered, ints2process, intmask;
+ struct list_head *head;
+ struct gccmdbuf *headcmdbuf;
+ unsigned int flags;
+ unsigned int dmapc, pc1, pc2;
+
+ GCDBG(GCZONE_THREAD, "context = 0x%08X\n",
+ (unsigned int) _gccorecontext);
+
+ /* Cast the context. */
+ gccorecontext = (struct gccorecontext *) _gccorecontext;
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ GCDBG(GCZONE_THREAD, "starting command queue thread.\n");
+
+ /* Set initial timeout to infinity since at this point GPU is
+ * considered to be powered off and there is no work pending or
+ * in progress yet. */
+ timeout = MAX_SCHEDULE_TIMEOUT;
+
+ /* Main thread loop. */
+ while (true) {
+ /* Wait for ready signal. If 'ready' is signaled before the
+ * call times out, signaled is set to a value greater then
+ * zero. If the call times out, signaled is set to zero. */
+ signaled = wait_for_completion_interruptible_timeout(
+ &gcqueue->ready, timeout);
+ GCDBG(GCZONE_THREAD, "wait(ready) = %d.\n", signaled);
+
+ if (signaled < 0)
+ continue;
+
+ /* Get triggered interrupts. */
+ ints2process = triggered = atomic_read(&gcqueue->triggered);
+ GCDBG(GCZONE_THREAD, "int = 0x%08X.\n", triggered);
+
+ GCLOCK(&gcqueue->queuelock);
+
+ /* Reset execution control flags. */
+ flags = 0;
+
+ /* Process triggered interrupts. */
+ while (ints2process != 0) {
+ GCDBG(GCZONE_INTERRUPT, "ints2process = 0x%08X.\n",
+ ints2process);
+
+ /* Queue empty? */
+ if (list_empty(&gcqueue->queue)) {
+ GCERR("no match for triggered ints 0x%08X.\n",
+ ints2process);
+
+ /* Reset triggered interrupts. */
+ atomic_sub(triggered, &gcqueue->triggered);
+ GCDBG(GCZONE_INTERRUPT, "triggered = 0x%08X.\n",
+ atomic_read(&gcqueue->triggered));
+
+ /* Free triggered interrupts. */
+ for (i = 0, intmask = 1; ints2process != 0;
+ i += 1, intmask <<= 1) {
+ GCDBG(GCZONE_INTERRUPT,
+ "ints2process = 0x%08X.\n",
+ ints2process);
+ GCDBG(GCZONE_INTERRUPT,
+ "intmask = 0x%08X (%d).\n",
+ intmask, i);
+
+ if ((ints2process & intmask) != 0) {
+ free_interrupt(gcqueue, i);
+ ints2process &= ~intmask;
+ }
+ }
+
+ break;
+ }
+
+ /* Get the head entry from the queue. */
+ head = gcqueue->queue.next;
+ headcmdbuf = list_entry(head, struct gccmdbuf, link);
+
+ GCDBG_QUEUE(GCZONE_THREAD, "processing ", headcmdbuf);
+
+ /* Buffer with no events? */
+ if (headcmdbuf->interrupt == ~0U) {
+ GCDBG(GCZONE_THREAD,
+ "buffer has no interrupt.\n");
+
+ /* Free the entry. */
+ gcqueue_free_cmdbuf(gcqueue, headcmdbuf, NULL);
+ continue;
+ }
+
+ /* Compute interrupt mask for the buffer. */
+ intmask = 1 << headcmdbuf->interrupt;
+ GCDBG(GCZONE_INTERRUPT, "intmask = 0x%08X.\n", intmask);
+
+ /* Did interrupt happen for the head entry? */
+ if ((ints2process & intmask) != 0) {
+ ints2process &= ~intmask;
+ GCDBG(GCZONE_INTERRUPT,
+ "ints2process = 0x%08X\n", ints2process);
+
+ atomic_sub(intmask, &gcqueue->triggered);
+ GCDBG(GCZONE_INTERRUPT, "triggered = 0x%08X.\n",
+ atomic_read(&gcqueue->triggered));
+ } else {
+ if (list_empty(&headcmdbuf->events)) {
+ GCDBG(GCZONE_THREAD,
+ "possibility of a lost "
+ "interrupt %d.\n",
+ headcmdbuf->interrupt);
+ } else {
+ GCERR("lost interrupt %d.\n",
+ headcmdbuf->interrupt);
+ }
+ }
+
+ /* Free the interrupt. */
+ free_interrupt(gcqueue, headcmdbuf->interrupt);
+
+ /* Execute events if any and free the entry. */
+ gcqueue_free_cmdbuf(gcqueue, headcmdbuf, &flags);
+ }
+
+ GCUNLOCK(&gcqueue->queuelock);
+
+ /* Bus error? */
+ if (try_wait_for_completion(&gcqueue->buserror)) {
+ GCERR("bus error detected.\n");
+ GCGPUSTATUS();
+
+ GCLOCK(&gcqueue->queuelock);
+
+ /* Execute all pending events. */
+ while (!list_empty(&gcqueue->queue)) {
+ head = gcqueue->queue.next;
+ headcmdbuf = list_entry(head,
+ struct gccmdbuf,
+ link);
+
+ /* Execute events if any and free the entry. */
+ gcqueue_free_cmdbuf(gcqueue, headcmdbuf,
+ &flags);
+ }
+
+ GCUNLOCK(&gcqueue->queuelock);
+
+ /* Reset GPU. */
+ gcpwr_reset(gccorecontext);
+ continue;
+ }
+
+ /* MMU error? */
+ if (try_wait_for_completion(&gcqueue->mmuerror)) {
+ static char *mmuerror[] = {
+ " no error",
+ " slave not present",
+ " page not present",
+ " write violation"
+ };
+
+ unsigned int mmustatus, mmucode;
+ unsigned int mmuaddress;
+ unsigned int mtlb, stlb, offset;
+
+ mmustatus = gc_read_reg(GCREG_MMU_STATUS_Address);
+ GCERR("MMU error detected; status = 0x%08X.\n",
+ mmustatus);
+
+ for (i = 0; i < 4; i += 1) {
+ mmucode = mmustatus & 0xF;
+ mmustatus >>= 4;
+
+ if (mmucode == 0)
+ continue;
+
+ GCERR("MMU%d is at fault:\n", i);
+ if (mmucode >= countof(mmuerror))
+ GCERR(" unknown state %d.\n", mmucode);
+ else
+ GCERR("%s.\n", mmuerror[mmucode]);
+
+ mmuaddress = gc_read_reg(
+ GCREG_MMU_EXCEPTION_Address + i);
+
+ mtlb = (mmuaddress & GCMMU_MTLB_MASK)
+ >> GCMMU_MTLB_SHIFT;
+ stlb = (mmuaddress & GCMMU_STLB_MASK)
+ >> GCMMU_STLB_SHIFT;
+ offset = mmuaddress & GCMMU_OFFSET_MASK;
+
+ GCERR(" address = 0x%08X\n", mmuaddress);
+ GCERR(" mtlb = %d\n", mtlb);
+ GCERR(" stlb = %d\n", stlb);
+ GCERR(" offset = 0x%08X (%d)\n",
+ offset, offset);
+
+ /* Route the invalid access to the safe zone. */
+ gc_write_reg(GCREG_MMU_EXCEPTION_Address + i,
+ gccorecontext->gcmmu.safezonephys);
+
+ GCERR(" rcovery address = 0x%08X\n",
+ gccorecontext->gcmmu.safezonephys);
+ }
+
+ continue;
+ }
+
+ /* Need to start FE? */
+ if ((flags & GC_CMDBUF_START_FE) != 0) {
+ GCLOCK(&gcqueue->queuelock);
+
+ /* Get the first entry from the active queue. */
+ head = gcqueue->queue.next;
+ headcmdbuf = list_entry(head,
+ struct gccmdbuf,
+ link);
+
+ GCDBG_QUEUE(GCZONE_THREAD, "restarting ", headcmdbuf);
+
+ /* Write address register. */
+ gc_write_reg(GCREG_CMD_BUFFER_ADDR_Address,
+ headcmdbuf->physical);
+
+ /* Write control register. */
+ gc_write_reg(GCREG_CMD_BUFFER_CTRL_Address,
+ GCSETFIELDVAL(0, GCREG_CMD_BUFFER_CTRL,
+ ENABLE, ENABLE) |
+ GCSETFIELD(0, GCREG_CMD_BUFFER_CTRL,
+ PREFETCH, headcmdbuf->count));
+
+ GCDBG(GCZONE_THREAD, "queue restarted.\n");
+ GCUNLOCK(&gcqueue->queuelock);
+ continue;
+ }
+
+ if (signaled && !gcqueue->suspend) {
+ /* The timeout value controls when the power
+ * on the GPU is pulled if there is no activity
+ * in progress or scheduled. */
+ timeout = msecs_to_jiffies(GC_THREAD_TIMEOUT);
+ } else {
+ GCLOCK(&gcqueue->queuelock);
+
+ if (gcqueue->suspend)
+ GCDBG(GCZONE_THREAD, "suspend requested\n");
+
+ if (!signaled)
+ GCDBG(GCZONE_THREAD, "thread timedout.\n");
+
+ if (gcqueue->gcmoterminator == NULL) {
+ GCDBG(GCZONE_THREAD, "no work scheduled.\n");
+
+ if (!list_empty(&gcqueue->queue))
+ GCERR("queue is not empty.\n");
+
+ gcqueue->suspend = false;
+
+ /* Set timeout to infinity. */
+ timeout = MAX_SCHEDULE_TIMEOUT;
+
+ GCUNLOCK(&gcqueue->queuelock);
+ continue;
+ }
+
+ /* Determine PC range for the terminatior. */
+ pc1 = gcqueue->gcmoterminator->u3.linkwait.address;
+ pc2 = pc1
+ + sizeof(struct gccmdwait)
+ + sizeof(struct gccmdlink);
+
+ /* Check to see if the FE reached the terminatior. */
+ dmapc = gc_read_reg(GCREG_FE_DEBUG_CUR_CMD_ADR_Address);
+ if ((dmapc < pc1) || (dmapc > pc2)) {
+ /* Haven't reached yet. */
+ GCDBG(GCZONE_THREAD,
+ "execution hasn't reached the end; "
+ "large amount of work?\n");
+ GCDBG(GCZONE_THREAD,
+ "current location @ 0x%08X.\n",
+ dmapc);
+ GCGPUSTATUS();
+ GCUNLOCK(&gcqueue->queuelock);
+ continue;
+ }
+
+ /* Free the queue. */
+ while (!list_empty(&gcqueue->queue)) {
+ head = gcqueue->queue.next;
+ headcmdbuf = list_entry(head,
+ struct gccmdbuf,
+ link);
+
+ if (!list_empty(&headcmdbuf->events)) {
+ /* Found events, there must be
+ * pending interrupts. */
+ break;
+ }
+
+ /* Free the entry. */
+ gcqueue_free_cmdbuf(gcqueue, headcmdbuf,
+ NULL);
+ }
+
+ if (!list_empty(&gcqueue->queue)) {
+ GCDBG(GCZONE_THREAD,
+ "aborting shutdown to process events\n");
+ GCGPUSTATUS();
+ GCUNLOCK(&gcqueue->queuelock);
+ continue;
+ }
+
+ GCDBG(GCZONE_THREAD,
+ "execution finished, shutting down.\n");
+
+ /* Convert WAIT to END. */
+ gcqueue->gcmoterminator->u2.end.cmd.raw
+ = gccmdend_const.cmd.raw;
+ mb();
+
+ gcqueue->gcmoterminator = NULL;
+
+ /* Go to suspend. */
+ gcpwr_set(gccorecontext, GCPWR_OFF);
+
+ /* Set idle state. */
+ complete(&gcqueue->stopped);
+
+ gcqueue->suspend = false;
+
+ /* Set timeout to infinity. */
+ timeout = MAX_SCHEDULE_TIMEOUT;
+
+ GCUNLOCK(&gcqueue->queuelock);
+
+ /* Is termination requested? */
+ if (try_wait_for_completion(&gcqueue->stop)) {
+ GCDBG(GCZONE_THREAD,
+ "terminating command queue thread.\n");
+ break;
+ }
+ }
+ }
+
+ GCDBG(GCZONE_THREAD, "thread exiting.\n");
+ return 0;
+}
+
+/*******************************************************************************
+ * Command buffer API.
+ */
+
+enum gcerror gcqueue_start(struct gccorecontext *gccorecontext)
+{
+ enum gcerror gcerror;
+ struct gcqueue *gcqueue;
+ struct gccmdstorage *storage;
+ unsigned int i;
+
+ GCENTERARG(GCZONE_INIT, "context = 0x%08X\n",
+ (unsigned int) gccorecontext);
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ /* Reset the queue object. */
+ memset(gcqueue, 0, sizeof(struct gcqueue));
+
+ /* ISR not installed yet. */
+ gcqueue->isrroutine = -1;
+
+ /* Initialize all storage buffers. */
+ for (i = 0; i < GC_STORAGE_COUNT; i += 1) {
+ /* Get a shortcut to the current storage buffer. */
+ storage = &gcqueue->storagearray[i];
+
+ /* Allocate storage buffer. */
+ gcerror = gc_alloc_noncached(&storage->page, GC_STORAGE_SIZE);
+ if (gcerror != GCERR_NONE) {
+ gcerror = GCERR_SETGRP(gcerror, GCERR_CMD_ALLOC);
+ goto fail;
+ }
+
+ /* Reset buffer info. */
+ storage->physical = storage->page.physical;
+ storage->mapped = 0;
+
+ init_completion(&storage->ready);
+ complete(&storage->ready);
+
+ GCDBG(GCZONE_INIT, "storage buffer [%d] allocated:\n", i);
+ GCDBG(GCZONE_INIT, " physical = 0x%08X\n", storage->physical);
+ GCDBG(GCZONE_INIT, " logical = 0x%08X\n",
+ (unsigned int) storage->page.logical);
+ GCDBG(GCZONE_INIT, " size = %d\n", storage->page.size);
+ }
+
+ /* Set the current storage buffer. */
+ gcqueue->dirtystorage = true;
+ gcqueue->curstorageidx = 0;
+ gcqueue->curstorage = &gcqueue->storagearray[gcqueue->curstorageidx];
+
+ /* Initialize current allocation info. */
+ gcqueue->logical = (unsigned char *) gcqueue->curstorage->page.logical;
+ gcqueue->physical = gcqueue->curstorage->physical;
+ gcqueue->available = gcqueue->curstorage->page.size - GC_TAIL_RESERVE;
+
+ /* Initialize interrupt tracking. */
+ GCLOCK_INIT(&gcqueue->intusedlock);
+ atomic_set(&gcqueue->triggered, 0);
+
+ /* Mark all interrupts as available. */
+ init_completion(&gcqueue->freeint);
+ for (i = 0; i < countof(gcqueue->intused); i += 1)
+ complete(&gcqueue->freeint);
+
+ /* Set GPU running state. */
+ init_completion(&gcqueue->stopped);
+ complete(&gcqueue->stopped);
+
+ /* Initialize sleep completion. */
+ init_completion(&gcqueue->sleep);
+
+ /* Initialize thread control completions. */
+ init_completion(&gcqueue->ready);
+ init_completion(&gcqueue->stop);
+ init_completion(&gcqueue->stall);
+
+ /* Initialize error signals. */
+ init_completion(&gcqueue->mmuerror);
+ init_completion(&gcqueue->buserror);
+
+ /* Initialize the current command buffer entry. */
+ INIT_LIST_HEAD(&gcqueue->cmdbufhead);
+
+ /* Initialize the schedule and active queue. */
+ INIT_LIST_HEAD(&gcqueue->queue);
+ GCLOCK_INIT(&gcqueue->queuelock);
+
+ /* Initialize entry cache. */
+ INIT_LIST_HEAD(&gcqueue->vacevents);
+ INIT_LIST_HEAD(&gcqueue->vacqueue);
+ GCLOCK_INIT(&gcqueue->vaceventlock);
+ GCLOCK_INIT(&gcqueue->vacqueuelock);
+
+ /* Reset MMU flush state. */
+ gcqueue->flushlogical = NULL;
+
+ /* Install ISR. */
+ gcqueue->isrroutine = request_irq(gccorecontext->irqline, gcisr,
+ IRQF_SHARED, GC_DEV_NAME,
+ gccorecontext);
+ if (gcqueue->isrroutine < 0) {
+ GCERR("failed to install ISR (%d).\n", gcqueue->isrroutine);
+ gcerror = GCERR_CMD_ISR;
+ goto fail;
+ }
+
+ GCDBG(GCZONE_INIT, "starting the command queue thread.\n");
+ gcqueue->cmdthread = kthread_create(gccmdthread, gccorecontext,
+ "gccmdthread");
+ if (IS_ERR(gcqueue->cmdthread)) {
+ GCERR("failed to start command thread.\n");
+ gcqueue->cmdthread = NULL;
+ gcerror = GCERR_CMD_THREAD;
+ goto fail;
+ }
+
+ wake_up_process(gcqueue->cmdthread);
+
+ GCEXIT(GCZONE_INIT);
+ return GCERR_NONE;
+
+fail:
+ gcqueue_stop(gccorecontext);
+ GCEXITARG(GCZONE_INIT, "gcerror = 0x%08X\n", gcerror);
+ return gcerror;
+}
+
+enum gcerror gcqueue_stop(struct gccorecontext *gccorecontext)
+{
+ struct gcqueue *gcqueue;
+ struct gccmdstorage *storage;
+ struct list_head *head;
+ struct gccmdbuf *gccmdbuf;
+ struct gcevent *gcevent;
+ unsigned int i;
+
+ GCENTERARG(GCZONE_INIT, "context = 0x%08X\n",
+ (unsigned int) gccorecontext);
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ /* Stop the command buffer thread. */
+ if (gcqueue->cmdthread != NULL) {
+ GCDBG(GCZONE_INIT, "stopping the command queue thread.\n");
+ complete(&gcqueue->stop);
+ complete(&gcqueue->ready);
+ kthread_stop(gcqueue->cmdthread);
+ gcqueue->cmdthread = NULL;
+ GCDBG(GCZONE_INIT, "command queue thread stopped.\n");
+ }
+
+ /* Remove ISR routine. */
+ if (gcqueue->isrroutine == 0) {
+ GCDBG(GCZONE_ISR, "removing ISR.\n");
+ free_irq(gccorecontext->irqline, gccorecontext);
+ gcqueue->isrroutine = -1;
+ }
+
+ /* Free all storage buffers. */
+ for (i = 0; i < GC_STORAGE_COUNT; i += 1) {
+ /* Get a shortcut to the current storage buffer. */
+ storage = &gcqueue->storagearray[i];
+
+ /* Verify that the storage buffer is not mapped. */
+ if (storage->mapped != 0)
+ GCERR("storage buffer is mapped.\n");
+
+ /* Free the buffer. */
+ if (storage->page.logical != NULL) {
+ gc_free_noncached(&storage->page);
+ storage->physical = ~0U;
+ }
+ }
+
+ /* Reset current buffer info. */
+ gcqueue->logical = NULL;
+ gcqueue->physical = ~0U;
+ gcqueue->available = 0;
+
+ /* Free the current command buffer. */
+ while (!list_empty(&gcqueue->cmdbufhead)) {
+ head = gcqueue->cmdbufhead.next;
+ gccmdbuf = list_entry(head, struct gccmdbuf, link);
+ gcqueue_free_cmdbuf(gcqueue, gccmdbuf, NULL);
+ }
+
+ /* Free command queue entries. */
+ while (!list_empty(&gcqueue->queue)) {
+ head = gcqueue->queue.next;
+ gccmdbuf = list_entry(head, struct gccmdbuf, link);
+ gcqueue_free_cmdbuf(gcqueue, gccmdbuf, NULL);
+ }
+
+ /* Free vacant entry lists. */
+ while (!list_empty(&gcqueue->vacevents)) {
+ head = gcqueue->vacevents.next;
+ gcevent = list_entry(head, struct gcevent, link);
+ list_del(head);
+ kfree(gcevent);
+ }
+
+ while (!list_empty(&gcqueue->vacqueue)) {
+ head = gcqueue->vacqueue.next;
+ gccmdbuf = list_entry(head, struct gccmdbuf, link);
+ list_del(head);
+ kfree(gccmdbuf);
+ }
+
+ GCEXIT(GCZONE_INIT);
+ return GCERR_NONE;
+}
+
+enum gcerror gcqueue_map(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext)
+{
+ enum gcerror gcerror;
+ struct gcqueue *gcqueue;
+ struct gccmdstorage *gccmdstorage;
+ struct gcmmuphysmem mem;
+ pte_t physpages[GC_STORAGE_PAGES];
+ unsigned int i, j, physical;
+
+ GCENTERARG(GCZONE_MAPPING, "context = 0x%08X\n",
+ (unsigned int) gccorecontext);
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ /* Map all command buffers. */
+ for (i = 0; i < GC_STORAGE_COUNT; i += 1) {
+ /* Get a shortcut to the current storage buffer. */
+ gccmdstorage = &gcqueue->storagearray[i];
+
+ /* Make sure command buffer hasn't been mapped yet. */
+ if (gcmmucontext->storagearray[i] != NULL) {
+ GCERR("storage %d is already mapped.\n", i);
+ gcerror = GCERR_CMD_MAPPED;
+ goto fail;
+ }
+
+ GCDBG(GCZONE_MAPPING, "maping storage %d.\n", i);
+ GCDBG(GCZONE_MAPPING, " physical = 0x%08X\n",
+ gccmdstorage->page.physical);
+ GCDBG(GCZONE_MAPPING, " logical = 0x%08X\n",
+ (unsigned int) gccmdstorage->page.logical);
+ GCDBG(GCZONE_MAPPING, " size = %d\n",
+ gccmdstorage->page.size);
+
+ /* Get physical pages. */
+ physical = gccmdstorage->page.physical;
+ for (j = 0; j < GC_STORAGE_PAGES; j += 1) {
+ physpages[j] = physical;
+ physical += PAGE_SIZE;
+ }
+
+ /* Map the buffer. */
+ mem.base = 0;
+ mem.offset = 0;
+ mem.count = GC_STORAGE_PAGES;
+ mem.pages = physpages;
+ mem.pagesize = PAGE_SIZE;
+
+ gcerror = gcmmu_map(gccorecontext, gcmmucontext, &mem,
+ &gcmmucontext->storagearray[i]);
+ if (gcerror != 0) {
+ GCERR("failed to map storage %d.\n", i);
+ goto fail;
+ }
+
+ physical = gcmmucontext->storagearray[i]->address;
+ if (gccmdstorage->mapped) {
+ GCDBG(GCZONE_MAPPING,
+ " storage %d is already mapped.\n", i);
+
+ if (gccmdstorage->physical != physical) {
+ GCERR("storage %d, inconsistent mapping!\n", i);
+ gcerror = GCERR_CMD_CONSISTENCY;
+ goto fail;
+ }
+ } else {
+ GCDBG(GCZONE_MAPPING,
+ " mapped storage %d @ 0x%08X.\n",
+ i, physical);
+
+ /* Not mapped yet, replace the physical address with
+ * the mapped one. */
+ gccmdstorage->physical = physical;
+
+ /* Update the allocatable address. */
+ if (gccmdstorage == gcqueue->curstorage) {
+ gcqueue->physical = gccmdstorage->physical;
+ GCDBG(GCZONE_MAPPING,
+ " setting current physical address.\n");
+ }
+ }
+
+ gccmdstorage->mapped += 1;
+ }
+
+ GCEXIT(GCZONE_MAPPING);
+ return GCERR_NONE;
+
+fail:
+ gcqueue_unmap(gccorecontext, gcmmucontext);
+ GCEXITARG(GCZONE_MAPPING, "gcerror = 0x%08X\n", gcerror);
+ return gcerror;
+}
+
+enum gcerror gcqueue_unmap(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext)
+{
+ enum gcerror gcerror;
+ struct gcqueue *gcqueue;
+ struct gccmdstorage *gccmdstorage;
+ unsigned int i;
+
+ GCENTERARG(GCZONE_MAPPING, "context = 0x%08X\n",
+ (unsigned int) gccorecontext);
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ /* Map all command buffers. */
+ for (i = 0; i < GC_STORAGE_COUNT; i += 1) {
+ /* Get a shortcut to the current command buffer structure. */
+ gccmdstorage = &gcqueue->storagearray[i];
+
+ /* Make sure command buffer is mapped. */
+ if (gcmmucontext->storagearray[i] == NULL)
+ continue;
+
+ gcerror = gcmmu_unmap(gccorecontext, gcmmucontext,
+ gcmmucontext->storagearray[i]);
+ if (gcerror != 0) {
+ GCERR("failed to unmap command buffer %d.\n", i);
+ goto fail;
+ }
+
+ /* Reset mapping. */
+ gcmmucontext->storagearray[i] = NULL;
+ gccmdstorage->mapped -= 1;
+ }
+
+ GCEXIT(GCZONE_MAPPING);
+ return GCERR_NONE;
+
+fail:
+ GCEXITARG(GCZONE_MAPPING, "gcerror = 0x%08X\n", gcerror);
+ return gcerror;
+}
+
+enum gcerror gcqueue_callback(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ void (*callback) (void *callbackparam),
+ void *callbackparam)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gcqueue *gcqueue;
+ struct gccmdbuf *gccmdbuf;
+ struct list_head *head;
+ struct gcevent *gcevent;
+
+ GCENTER(GCZONE_EVENT);
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ /* Allocate command buffer. */
+ if (list_empty(&gcqueue->cmdbufhead)) {
+ gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+ 0, NULL, NULL);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+ }
+
+ /* Get the current command buffer. */
+ head = gcqueue->cmdbufhead.prev;
+ gccmdbuf = list_entry(head, struct gccmdbuf, link);
+
+ /* Add callback event. */
+ gcerror = gcqueue_alloc_event(gcqueue, &gcevent);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Initialize the event and add to the list. */
+ gcevent->handler = event_callback;
+ gcevent->event.callback.callback = callback;
+ gcevent->event.callback.callbackparam = callbackparam;
+ list_add_tail(&gcevent->link, &gccmdbuf->events);
+
+ GCDBG(GCZONE_EVENT, "callback = 0x%08X\n",
+ (unsigned int) callback);
+ GCDBG(GCZONE_EVENT, "callbackparam = 0x%08X\n",
+ (unsigned int) callbackparam);
+
+exit:
+ GCEXIT(GCZONE_EVENT);
+ return gcerror;
+}
+
+enum gcerror gcqueue_schedunmap(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ unsigned long handle)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gcqueue *gcqueue;
+ struct gccmdbuf *gccmdbuf;
+ struct list_head *head;
+ struct gcevent *gcevent;
+
+ GCENTER(GCZONE_EVENT);
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ /* Allocate command buffer. */
+ if (list_empty(&gcqueue->cmdbufhead)) {
+ gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+ 0, NULL, NULL);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+ }
+
+ /* Get the current command buffer. */
+ head = gcqueue->cmdbufhead.prev;
+ gccmdbuf = list_entry(head, struct gccmdbuf, link);
+
+ /* Add callback event. */
+ gcerror = gcqueue_alloc_event(gcqueue, &gcevent);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Initialize the event and add to the list. */
+ gcevent->handler = event_unmap;
+ gcevent->event.unmap.gccorecontext = gccorecontext;
+ gcevent->event.unmap.gcmmucontext = gcmmucontext;
+ gcevent->event.unmap.gcmmuarena = (struct gcmmuarena *) handle;
+ list_add_tail(&gcevent->link, &gccmdbuf->events);
+
+ GCDBG(GCZONE_EVENT, "handle = 0x%08X\n", handle);
+
+exit:
+ GCEXIT(GCZONE_EVENT);
+ return gcerror;
+}
+
+enum gcerror gcqueue_alloc(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ unsigned int size,
+ void **logical,
+ unsigned int *physical)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gcqueue *gcqueue;
+ struct gccmdbuf *gccmdbuf;
+ struct list_head *head;
+
+ GCENTERARG(GCZONE_ALLOC, "context = 0x%08X, size = %d\n",
+ (unsigned int) gccorecontext, size);
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ while (true) {
+ /* Wait until the storage buffer becomes available. */
+ if (gcqueue->dirtystorage) {
+ if (!try_wait_for_completion(
+ &gcqueue->curstorage->ready)) {
+ GCDBG(GCZONE_ALLOC,
+ "waiting for the storage buffer"
+ " to become available.\n");
+
+ GCWAIT_FOR_COMPLETION(
+ &gcqueue->curstorage->ready);
+ }
+
+ GCDBG(GCZONE_ALLOC, "using storage buffer #%d.\n",
+ gcqueue->curstorageidx);
+
+ gcqueue->dirtystorage = false;
+ }
+
+ GCDBG(GCZONE_ALLOC, "queue logical = 0x%08X\n",
+ (unsigned int) gcqueue->logical);
+ GCDBG(GCZONE_ALLOC, "queue physical = 0x%08X\n",
+ gcqueue->physical);
+ GCDBG(GCZONE_ALLOC, "queue available = %d\n",
+ gcqueue->available);
+
+ /* Create a new command buffer entry if not created yet. */
+ if (list_empty(&gcqueue->cmdbufhead)) {
+ GCDBG(GCZONE_ALLOC, "allocating new queue entry.\n");
+
+ gcerror = gcqueue_alloc_cmdbuf(gcqueue, &gccmdbuf);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ list_add_tail(&gccmdbuf->link, &gcqueue->cmdbufhead);
+
+ gccmdbuf->gcmmucontext = gcmmucontext;
+ gccmdbuf->logical = gcqueue->logical;
+ gccmdbuf->physical = gcqueue->physical;
+ gccmdbuf->size = 0;
+ gccmdbuf->count = 0;
+ gccmdbuf->gcmoterminator = NULL;
+ gccmdbuf->interrupt = ~0U;
+ } else {
+ head = gcqueue->cmdbufhead.next;
+ gccmdbuf = list_entry(head, struct gccmdbuf, link);
+ }
+
+ /* Do we have enough room in the current buffer? */
+ if ((int) size <= gcqueue->available) {
+ /* Set the pointers. */
+ if (logical != NULL)
+ *logical = gcqueue->logical;
+
+ if (physical != NULL)
+ *physical = gcqueue->physical;
+
+ /* Update the info. */
+ gcqueue->logical += size;
+ gcqueue->physical += size;
+ gcqueue->available -= size;
+ gccmdbuf->size += size;
+
+ GCDBG_QUEUE(GCZONE_ALLOC, "updated ", gccmdbuf);
+ goto exit;
+ }
+
+ /* Execute the current command buffer. */
+ GCDBG_QUEUE(GCZONE_ALLOC, "current ", gccmdbuf);
+ GCDBG(GCZONE_ALLOC, "out of available space.\n");
+ gcerror = gcqueue_execute(gccorecontext, true, true);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+ }
+
+exit:
+ GCEXITARG(GCZONE_ALLOC, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+
+ return gcerror;
+}
+
+enum gcerror gcqueue_free(struct gccorecontext *gccorecontext,
+ unsigned int size)
+{
+ struct list_head *head;
+ struct gcqueue *gcqueue;
+ struct gccmdbuf *gccmdbuf;
+
+ GCENTERARG(GCZONE_ALLOC, "context = 0x%08X, size = %d\n",
+ (unsigned int) gccorecontext, size);
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ if (list_empty(&gcqueue->cmdbufhead)) {
+ GCERR("no current command buffer\n");
+ } else {
+ /* Get a pointer to the open entry. */
+ head = gcqueue->cmdbufhead.next;
+ gccmdbuf = list_entry(head, struct gccmdbuf, link);
+
+ /* Roll back the previous allocation. */
+ gcqueue->logical -= size;
+ gcqueue->physical -= size;
+ gcqueue->available += size;
+ gccmdbuf->size -= size;
+ }
+
+ GCEXIT(GCZONE_ALLOC);
+ return GCERR_NONE;
+}
+
+enum gcerror gcqueue_execute(struct gccorecontext *gccorecontext,
+ bool switchtonext, bool asynchronous)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gcqueue *gcqueue;
+ struct gcmoterminator *gcmoterminator;
+ struct gcevent *gcevent;
+ struct gccmdbuf *gccmdbuf;
+ struct list_head *head;
+
+ GCENTERARG(GCZONE_EXEC, "context = 0x%08X, asynchronous = %d\n",
+ (unsigned int) gccorecontext, asynchronous);
+
+ /* Get a shortcut to the queue object. */
+ gcqueue = &gccorecontext->gcqueue;
+
+ /* Nothing to execute? */
+ if (list_empty(&gcqueue->cmdbufhead))
+ goto exit;
+
+ /* Get the current command buffer. */
+ head = gcqueue->cmdbufhead.prev;
+ gccmdbuf = list_entry(head, struct gccmdbuf, link);
+
+ /* Determine the location of the terminator. */
+ gccmdbuf->gcmoterminator = gcmoterminator
+ = (struct gcmoterminator *) gcqueue->logical;
+
+ /* Configure the second entry as a wait. */
+ gcmoterminator->u2.wait.cmd.fld = gcfldwait200;
+
+ /* Configure the third entry as a link back to the wait. */
+ gcmoterminator->u3.linkwait.cmd.fld = gcfldlink2;
+ gcmoterminator->u3.linkwait.address = gcqueue->physical
+ + offsetof(struct gcmoterminator, u2);
+
+ /* Update the info. */
+ gcqueue->logical += GC_TAIL_RESERVE;
+ gcqueue->physical += GC_TAIL_RESERVE;
+ gcqueue->available -= GC_TAIL_RESERVE;
+ gccmdbuf->size += GC_TAIL_RESERVE;
+
+ GCDBG(GCZONE_EXEC, "queue logical = 0x%08X\n",
+ (unsigned int) gcqueue->logical);
+ GCDBG(GCZONE_EXEC, "queue physical = 0x%08X\n",
+ gcqueue->physical);
+ GCDBG(GCZONE_EXEC, "queue available = %d\n",
+ gcqueue->available);
+
+ /* Determine data count. */
+ gccmdbuf->count = (gccmdbuf->size + 7) >> 3;
+
+ /* Is there an MMU flush in the buffer? */
+ if (gcqueue->flushlogical != NULL) {
+ GCDBG(GCZONE_EXEC, "finalizing MMU flush.\n");
+
+ /* Finalize the flush. */
+ gcmmu_flush_finalize(gccmdbuf,
+ gcqueue->flushlogical,
+ gcqueue->flushaddress);
+
+ /* Reset flush pointer. */
+ gcqueue->flushlogical = NULL;
+ }
+
+ GCDBG_QUEUE(GCZONE_EXEC, "current ", gccmdbuf);
+
+ /* Check the remaining space minimum threshold. */
+ if (switchtonext || (gcqueue->available < GC_MIN_THRESHOLD)) {
+ GCDBG(GCZONE_EXEC, "switching to the next storage.\n");
+
+ /* Add event for the current command buffer. */
+ gcerror = gcqueue_alloc_event(gcqueue, &gcevent);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Initialize the event and add to the list. */
+ gcevent->handler = event_completion;
+ gcevent->event.completion.completion
+ = &gcqueue->curstorage->ready;
+ list_add_tail(&gcevent->link, &gccmdbuf->events);
+ GCDBG(GCZONE_EXEC, "buffer switch completion 0x%08X.\n",
+ (unsigned int) gcevent->event.completion.completion);
+
+ /* Switch to the next storage buffer. */
+ gcqueue->curstorageidx = (gcqueue->curstorageidx + 1)
+ % GC_STORAGE_COUNT;
+ gcqueue->curstorage = &gcqueue->storagearray
+ [gcqueue->curstorageidx];
+
+ /* Initialize current allocation info. */
+ gcqueue->logical = (unsigned char *)
+ gcqueue->curstorage->page.logical;
+ gcqueue->physical = gcqueue->curstorage->physical;
+ gcqueue->available = gcqueue->curstorage->page.size
+ - GC_TAIL_RESERVE;
+
+ /* Invalidate the storage. */
+ gcqueue->dirtystorage = true;
+
+ GCDBG(GCZONE_EXEC, "switching to storage %d.\n",
+ gcqueue->curstorageidx);
+ }
+
+ /* Add stall event for synchronous operation. */
+ if (!asynchronous) {
+ GCDBG(GCZONE_EXEC, "appending stall event.\n");
+
+ /* Add stall event. */
+ gcerror = gcqueue_alloc_event(gcqueue, &gcevent);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Initialize the event and add to the list. */
+ gcevent->handler = event_completion;
+ gcevent->event.completion.completion = &gcqueue->stall;
+ list_add_tail(&gcevent->link, &gccmdbuf->events);
+ GCDBG(GCZONE_EXEC, "stall completion 0x%08X.\n",
+ (unsigned int) gcevent->event.completion.completion);
+ }
+
+ /* If the buffer has no events, don't allocate an interrupt for it. */
+ if (list_empty(&gccmdbuf->events)) {
+ gcmoterminator->u1.nop.cmd.raw = gccmdnop_const.cmd.raw;
+ } else {
+ gcerror = gcqueue_alloc_int(gcqueue, &gccmdbuf->interrupt);
+ if (gcerror != GCERR_NONE)
+ goto exit;
+
+ gcmoterminator->u1.done.signal_ldst = gcmosignal_signal_ldst;
+ gcmoterminator->u1.done.signal.raw = 0;
+ gcmoterminator->u1.done.signal.reg.id = gccmdbuf->interrupt;
+ gcmoterminator->u1.done.signal.reg.pe
+ = GCREG_EVENT_PE_SRC_ENABLE;
+ }
+
+ /* Append the current command buffer to the queue. */
+ append_cmdbuf(gccorecontext, gcqueue);
+
+ /* Wait for completion. */
+ if (!asynchronous) {
+ GCDBG(GCZONE_EXEC, "waiting until execution is complete.\n");
+ GCWAIT_FOR_COMPLETION(&gcqueue->stall);
+ GCDBG(GCZONE_EXEC, "execution complete.\n");
+ }
+
+exit:
+ GCEXITARG(GCZONE_EXEC, "gc%s = 0x%08X\n",
+ (gcerror == GCERR_NONE) ? "result" : "error", gcerror);
+ return gcerror;
+}
+
+enum gcerror gcqueue_wait_idle(struct gccorecontext *gccorecontext)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gcqueue *gcqueue = &gccorecontext->gcqueue;
+ unsigned long timeout;
+ unsigned int count, limit;
+
+ GCENTER(GCZONE_THREAD);
+
+ /* Indicate shutdown immediately. */
+ gcqueue->suspend = true;
+ complete(&gcqueue->ready);
+
+ /* Convert timeout to jiffies. */
+ timeout = msecs_to_jiffies(GC_IDLE_TIMEOUT);
+
+ /* Compute the maximum number of attempts. */
+ limit = 5000 / GC_IDLE_TIMEOUT;
+
+ /* Wait for GPU to stop. */
+ count = 0;
+ while (gcqueue->suspend) {
+ wait_for_completion_timeout(&gcqueue->sleep, timeout);
+
+ /* Waiting too long? */
+ if (++count == limit) {
+ GCERR("wait for idle takes too long.\n");
+ gcerror = GCERR_TIMEOUT;
+ break;
+ }
+ }
+
+ GCEXIT(GCZONE_THREAD);
+ return gcerror;
+}
diff --git a/drivers/misc/gcx/gccore/gcqueue.h b/drivers/misc/gcx/gccore/gcqueue.h
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * gcqueue.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCQUEUE_H
+#define GCQUEUE_H
+
+#include <linux/gccore.h>
+
+
+/*******************************************************************************
+ * Command queue defines.
+ */
+
+/* Number of the storage buffers that the driver will switch between. */
+#define GC_STORAGE_COUNT 2
+
+/* Number of command buffers that fit in one storage buffer. */
+#define GC_CMDBUF_FACTOR 2
+
+
+/*******************************************************************************
+ * Command queue structures.
+ */
+
+/* Execution control flags. */
+#define GC_CMDBUF_START_FE (1 << 0)
+
+/* Event record. */
+struct gcevent {
+ /* Event handler function. */
+ void (*handler) (struct gcevent *gcevent, unsigned int *flags);
+
+ /* Event specific data. */
+ union {
+ struct {
+ struct completion *completion;
+ } completion;
+
+ struct {
+ void (*callback) (void *callbackparam);
+ void *callbackparam;
+ } callback;
+
+ struct {
+ struct gccorecontext *gccorecontext;
+ struct gcmmucontext *gcmmucontext;
+ struct gcmmuarena *gcmmuarena;
+ } unmap;
+ } event;
+
+ /* Previous/next event link. */
+ struct list_head link;
+};
+
+/* Command buffer storage descriptor. This represents a container within
+ * which smaller allocations are made, filled with commands and executed.
+ * There should be at least two of these storage buffers to allow for seamless
+ * execution. When there is no more room in the current storage buffer, the
+ * buffer is sent for execution while allocation can continue from the next
+ * storage buffer. */
+struct gccmdstorage {
+ /* Storage buffer allocation descriptor. */
+ struct gcpage page;
+
+ /* Physical (GPU mapped) address of the storage buffer. */
+ unsigned int physical;
+
+ /* Number of clients that have the storage buffer mapped.*/
+ unsigned int mapped;
+
+ /* Completion used for switching to this storage buffer. */
+ struct completion ready;
+};
+
+/* Command queue entry. */
+struct gccmdbuf {
+ /* Associated MMU context. */
+ struct gcmmucontext *gcmmucontext;
+
+ /* Pointers to the beginning of the command buffer and the size
+ * of the command buffer in bytes. */
+ unsigned char *logical;
+ unsigned int physical;
+ unsigned int size;
+
+ /* The size of the command buffer in the number if 64-bit chunks. */
+ unsigned int count;
+
+ /* Command buffer terminator structure. */
+ struct gcmoterminator *gcmoterminator;
+
+ /* Interrupt number assigned to the command buffer. */
+ unsigned int interrupt;
+
+ /* Event list associated with the command buffer. */
+ struct list_head events;
+
+ /* Previous/next command queue entry. */
+ struct list_head link;
+};
+
+/* Command queue object. */
+struct gcqueue {
+ /* ISR installed flag. */
+ int isrroutine;
+
+ /* Storage buffer array. */
+ bool dirtystorage;
+ struct gccmdstorage storagearray[GC_STORAGE_COUNT];
+ struct gccmdstorage *curstorage;
+ unsigned int curstorageidx;
+
+ /* Pointers to the area of the current storage buffer available for
+ * allocation and the size of the available space in bytes. */
+ unsigned char *logical;
+ unsigned int physical;
+ int available;
+
+ /* Array to keep track of which interrupts are in use. */
+ bool intused[30];
+ GCLOCK_TYPE intusedlock;
+
+ /* The completion to track the number of available interrupts. */
+ struct completion freeint;
+
+ /* Bit mask containing triggered interrupts. */
+ atomic_t triggered;
+
+ /* The tail of the last command buffer. */
+ struct gcmoterminator *gcmoterminator;
+
+ /* GPU running state. */
+ struct completion stopped;
+
+ /* Command buffer thread and thread control completions. */
+ struct task_struct *cmdthread;
+ struct completion ready;
+ struct completion stop;
+ struct completion sleep;
+
+ /* Suspend request flag. */
+ bool suspend;
+
+ /* Stall completion; used to imitate synchronous behaviour. */
+ struct completion stall;
+
+ /* Error signals. */
+ struct completion mmuerror;
+ struct completion buserror;
+
+ /* Command buffer currently being worked on. */
+ struct list_head cmdbufhead;
+
+ /* Queue of entries being executed (gccmdbuf). */
+ struct list_head queue;
+ GCLOCK_TYPE queuelock;
+
+ /* Cache of vacant event entries (gcevent). */
+ struct list_head vacevents;
+ GCLOCK_TYPE vaceventlock;
+
+ /* Cache of vacant queue entries (gccmdbuf). */
+ struct list_head vacqueue;
+ GCLOCK_TYPE vacqueuelock;
+
+ /* MMU flush pointers. */
+ struct gcmommuflush *flushlogical;
+ unsigned int flushaddress;
+};
+
+
+/*******************************************************************************
+ * Command queue management API.
+ */
+
+struct gccorecontext;
+struct gcmmucontext;
+
+enum gcerror gcqueue_start(struct gccorecontext *gccorecontext);
+enum gcerror gcqueue_stop(struct gccorecontext *gccorecontext);
+
+enum gcerror gcqueue_map(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext);
+enum gcerror gcqueue_unmap(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext);
+
+enum gcerror gcqueue_callback(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ void (*callback) (void *callbackparam),
+ void *callbackparam);
+enum gcerror gcqueue_schedunmap(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ unsigned long handle);
+enum gcerror gcqueue_alloc(struct gccorecontext *gccorecontext,
+ struct gcmmucontext *gcmmucontext,
+ unsigned int size,
+ void **logical,
+ unsigned int *physical);
+enum gcerror gcqueue_free(struct gccorecontext *gccorecontext,
+ unsigned int size);
+enum gcerror gcqueue_execute(struct gccorecontext *gccorecontext,
+ bool switchtonext, bool asynchronous);
+
+enum gcerror gcqueue_alloc_event(struct gcqueue *gcqueue,
+ struct gcevent **gcevent);
+enum gcerror gcqueue_free_event(struct gcqueue *gcqueue,
+ struct gcevent *gcevent);
+
+enum gcerror gcqueue_alloc_cmdbuf(struct gcqueue *gcqueue,
+ struct gccmdbuf **gccmdbuf);
+void gcqueue_free_cmdbuf(struct gcqueue *gcqueue,
+ struct gccmdbuf *gccmdbuf,
+ unsigned int *flags);
+
+enum gcerror gcqueue_alloc_int(struct gcqueue *gcqueue,
+ unsigned int *interrupt);
+
+enum gcerror gcqueue_wait_idle(struct gccorecontext *gccorecontext);
+
+#endif
diff --git a/drivers/misc/gcx/gcioctl/Kconfig b/drivers/misc/gcx/gcioctl/Kconfig
--- /dev/null
@@ -0,0 +1,6 @@
+config GCIOCTL
+ tristate "User interface to Vivante 2D/3D driver"
+ default y
+ depends on GCCORE
+ help
+ User interface to Vivante 2D/3D driver.
diff --git a/drivers/misc/gcx/gcioctl/Makefile b/drivers/misc/gcx/gcioctl/Makefile
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_GCIOCTL) += gcioctl.o
+
+gcioctl-y := \
+ gcif.o
diff --git a/drivers/misc/gcx/gcioctl/gcif.c b/drivers/misc/gcx/gcioctl/gcif.c
--- /dev/null
@@ -0,0 +1,1152 @@
+/*
+ * gcmain.c
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <plat/cpu.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/gcx.h>
+#include <linux/gccore.h>
+#include <linux/cache-2dmanager.h>
+#include "gcif.h"
+#include "version.h"
+
+#define GCZONE_NONE 0
+#define GCZONE_ALL (~0U)
+#define GCZONE_INIT (1 << 0)
+#define GCZONE_CAPS (1 << 1)
+#define GCZONE_MAPPING (1 << 2)
+#define GCZONE_CACHE (1 << 3)
+#define GCZONE_COMMIT (1 << 4)
+#define GCZONE_IOCTL (1 << 5)
+#define GCZONE_CALLBACK (1 << 6)
+
+GCDBG_FILTERDEF(ioctl, GCZONE_NONE,
+ "init",
+ "caps",
+ "mapping",
+ "cache",
+ "commit",
+ "ioctl",
+ "callback")
+
+static GCDEFINE_LOCK(g_fixuplock);
+static GCDEFINE_LOCK(g_bufferlock);
+static GCDEFINE_LOCK(g_unmaplock);
+
+static LIST_HEAD(g_buffervac); /* gcbuffer */
+static LIST_HEAD(g_fixupvac); /* gcfixup */
+static LIST_HEAD(g_unmapvac); /* gcschedunmap */
+
+
+/*******************************************************************************
+ * Command buffer copy management.
+ */
+
+static enum gcerror alloc_fixup(struct gcfixup **gcfixup)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gcfixup *temp;
+
+ GCLOCK(&g_fixuplock);
+
+ if (list_empty(&g_fixupvac)) {
+ temp = kmalloc(sizeof(struct gcfixup), GFP_KERNEL);
+ if (temp == NULL) {
+ GCERR("out of memory.\n");
+ gcerror = GCERR_SETGRP(GCERR_OODM,
+ GCERR_IOCTL_FIXUP_ALLOC);
+ goto exit;
+ }
+ } else {
+ struct list_head *head;
+ head = g_fixupvac.next;
+ temp = list_entry(head, struct gcfixup, link);
+ list_del(head);
+ }
+
+ GCUNLOCK(&g_fixuplock);
+
+ INIT_LIST_HEAD(&temp->link);
+ *gcfixup = temp;
+
+exit:
+ return gcerror;
+}
+
+static void free_fixup(struct gcfixup *gcfixup)
+{
+ GCLOCK(&g_fixuplock);
+ list_move(&gcfixup->link, &g_fixupvac);
+ GCUNLOCK(&g_fixuplock);
+}
+
+static void free_fixup_list(struct list_head *fixuplist)
+{
+ GCLOCK(&g_fixuplock);
+ list_splice_init(fixuplist, &g_fixupvac);
+ GCUNLOCK(&g_fixuplock);
+}
+
+static void free_vacant_fixups(void)
+{
+ struct list_head *head;
+ struct gcfixup *gcfixup;
+
+ GCLOCK(&g_fixuplock);
+ while (!list_empty(&g_fixupvac)) {
+ head = g_fixupvac.next;
+ gcfixup = list_entry(head, struct gcfixup, link);
+ list_del(head);
+ kfree(gcfixup);
+ }
+ GCUNLOCK(&g_fixuplock);
+}
+
+static enum gcerror alloc_buffer(struct gcbuffer **gcbuffer)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gcbuffer *temp;
+
+ GCLOCK(&g_bufferlock);
+
+ if (list_empty(&g_buffervac)) {
+ temp = kmalloc(sizeof(struct gcbuffer), GFP_KERNEL);
+ if (temp == NULL) {
+ GCERR("out of memory.\n");
+ gcerror = GCERR_SETGRP(GCERR_OODM,
+ GCERR_IOCTL_BUF_ALLOC);
+ goto exit;
+ }
+ } else {
+ struct list_head *head;
+ head = g_buffervac.next;
+ temp = list_entry(head, struct gcbuffer, link);
+ list_del(head);
+ }
+
+ GCUNLOCK(&g_bufferlock);
+
+ INIT_LIST_HEAD(&temp->fixup);
+ INIT_LIST_HEAD(&temp->link);
+ *gcbuffer = temp;
+
+exit:
+ return gcerror;
+}
+
+static void free_buffer(struct gcbuffer *gcbuffer)
+{
+ /* Free fixups. */
+ free_fixup_list(&gcbuffer->fixup);
+
+ /* Free the buffer. */
+ GCLOCK(&g_bufferlock);
+ list_move(&gcbuffer->link, &g_buffervac);
+ GCUNLOCK(&g_bufferlock);
+}
+
+static void free_buffer_list(struct list_head *bufferlist)
+{
+ struct list_head *head;
+ struct gcbuffer *gcbuffer;
+
+ while (!list_empty(bufferlist)) {
+ head = bufferlist->next;
+ gcbuffer = list_entry(head, struct gcbuffer, link);
+ free_buffer(gcbuffer);
+ }
+}
+
+static void free_vacant_buffers(void)
+{
+ struct list_head *head;
+ struct gcbuffer *gcbuffer;
+
+ GCLOCK(&g_bufferlock);
+ while (!list_empty(&g_buffervac)) {
+ head = g_buffervac.next;
+ gcbuffer = list_entry(head, struct gcbuffer, link);
+ list_del(head);
+ kfree(gcbuffer);
+ }
+ GCUNLOCK(&g_bufferlock);
+}
+
+
+/*******************************************************************************
+ * Unmap list management.
+ */
+
+static enum gcerror alloc_schedunmap(struct gcschedunmap **gcschedunmap)
+{
+ enum gcerror gcerror = GCERR_NONE;
+ struct gcschedunmap *temp;
+
+ GCLOCK(&g_unmaplock);
+
+ if (list_empty(&g_unmapvac)) {
+ temp = kmalloc(sizeof(struct gcschedunmap), GFP_KERNEL);
+ if (temp == NULL) {
+ GCERR("out of memory.\n");
+ gcerror = GCERR_SETGRP(GCERR_OODM,
+ GCERR_IOCTL_BUF_ALLOC);
+ goto exit;
+ }
+ } else {
+ struct list_head *head;
+ head = g_unmapvac.next;
+ temp = list_entry(head, struct gcschedunmap, link);
+ list_del(head);
+ }
+
+ GCUNLOCK(&g_unmaplock);
+
+ INIT_LIST_HEAD(&temp->link);
+ *gcschedunmap = temp;
+
+exit:
+ return gcerror;
+}
+
+static void free_schedunmap(struct gcschedunmap *gcschedunmap)
+{
+ GCLOCK(&g_unmaplock);
+ list_move(&gcschedunmap->link, &g_unmapvac);
+ GCUNLOCK(&g_unmaplock);
+}
+
+static void free_schedunmap_list(struct list_head *schedunmaplist)
+{
+ GCLOCK(&g_unmaplock);
+ list_splice_init(schedunmaplist, &g_unmapvac);
+ GCUNLOCK(&g_unmaplock);
+}
+
+static void free_vacant_unmap(void)
+{
+ struct list_head *head;
+ struct gcschedunmap *gcschedunmap;
+
+ GCLOCK(&g_unmaplock);
+ while (!list_empty(&g_unmapvac)) {
+ head = g_unmapvac.next;
+ gcschedunmap = list_entry(head, struct gcschedunmap, link);
+ list_del(head);
+ kfree(gcschedunmap);
+ }
+ GCUNLOCK(&g_unmaplock);
+}
+
+
+/*******************************************************************************
+ * Callback managemnent.
+ */
+
+/* Per-client callback handle. */
+struct gccallbackhandle {
+ /* Ready signal. */
+ struct completion ready;
+
+ /* List of triggered callbacks (gccallbackinfo). */
+ struct list_head triggered;
+
+ /* List of scheduled callbacks (gccallbackinfo). */
+ struct list_head scheduled;
+
+ /* Previous/next callback handle. */
+ struct list_head link;
+};
+
+/* Callback information. */
+struct gccallbackinfo {
+ /* Callback handle. */
+ unsigned long handle;
+
+ /* User callback. */
+ void (*callback) (void *callbackparam);
+ void *callbackparam;
+
+ /* Previous/next callback information. */
+ struct list_head link;
+};
+
+/* Callback lists. */
+static LIST_HEAD(g_handlelist);
+static LIST_HEAD(g_vachandle);
+static LIST_HEAD(g_vacinfo);
+static GCDEFINE_LOCK(g_callbacklock);
+
+static enum gcerror alloc_callbackhandle(struct gccallbackhandle **handle)
+{
+ enum gcerror gcerror;
+ struct gccallbackhandle *temp;
+
+ GCLOCK(&g_callbacklock);
+
+ if (list_empty(&g_vachandle)) {
+ temp = kmalloc(sizeof(struct gccallbackhandle), GFP_KERNEL);
+ if (temp == NULL) {
+ GCERR("failed to allocate callback handle.\n");
+ gcerror = GCERR_OODM;
+ goto exit;
+ }
+ list_add(&temp->link, &g_handlelist);
+ } else {
+ struct list_head *head;
+ head = g_vachandle.next;
+ temp = list_entry(head, struct gccallbackhandle, link);
+ list_move(head, &g_handlelist);
+ }
+
+ init_completion(&temp->ready);
+ INIT_LIST_HEAD(&temp->triggered);
+ INIT_LIST_HEAD(&temp->scheduled);
+
+ *handle = temp;
+ gcerror = GCERR_NONE;
+
+exit:
+ GCUNLOCK(&g_callbacklock);
+ return gcerror;
+}
+
+static void free_callbackhandle(struct gccallbackhandle *handle)
+{
+ GCLOCK(&g_callbacklock);
+ list_move(&handle->link, &g_vachandle);
+ GCUNLOCK(&g_callbacklock);
+}
+
+static enum gcerror alloc_callbackinfo(unsigned long handle,
+ struct gccallbackinfo **info)
+{
+ enum gcerror gcerror;
+ struct gccallbackinfo *temp;
+ struct gccallbackhandle *gccallbackhandle;
+
+ GCLOCK(&g_callbacklock);
+
+ /* Get the callback handle. */
+ gccallbackhandle = (struct gccallbackhandle *) handle;
+
+ if (list_empty(&g_vacinfo)) {
+ temp = kmalloc(sizeof(struct gccallbackinfo), GFP_KERNEL);
+ if (temp == NULL) {
+ GCERR("failed to allocate callback info.\n");
+ gcerror = GCERR_OODM;
+ goto exit;
+ }
+ list_add_tail(&temp->link, &gccallbackhandle->scheduled);
+ } else {
+ struct list_head *head;
+ head = g_vacinfo.next;
+ temp = list_entry(head, struct gccallbackinfo, link);
+ list_move_tail(head, &gccallbackhandle->scheduled);
+ }
+
+ temp->handle = handle;
+
+ *info = temp;
+ gcerror = GCERR_NONE;
+
+exit:
+ GCUNLOCK(&g_callbacklock);
+ return gcerror;
+}
+
+static void gccallback(void *callbackparam)
+{
+ struct gccallbackinfo *gccallbackinfo;
+ struct gccallbackhandle *gccallbackhandle;
+
+ GCENTER(GCZONE_CALLBACK);
+
+ /* Cast callback info. */
+ gccallbackinfo = (struct gccallbackinfo *) callbackparam;
+ GCDBG(GCZONE_CALLBACK, "callback info received 0x%08X.\n",
+ (unsigned int) gccallbackinfo);
+
+ /* Get the callback handle. */
+ gccallbackhandle = (struct gccallbackhandle *) gccallbackinfo->handle;
+ GCDBG(GCZONE_CALLBACK, "callback handle 0x%08X.\n",
+ (unsigned int) gccallbackhandle);
+
+ /* Move to the triggered list. */
+ GCLOCK(&g_callbacklock);
+ list_move_tail(&gccallbackinfo->link, &gccallbackhandle->triggered);
+ GCUNLOCK(&g_callbacklock);
+
+ /* Complete ready signal. */
+ complete(&gccallbackhandle->ready);
+ GCDBG(GCZONE_CALLBACK, "user released.\n");
+
+ GCEXIT(GCZONE_CALLBACK);
+}
+
+static void destroy_callback(void)
+{
+ struct list_head *head;
+ struct gccallbackhandle *gccallbackhandle;
+ struct gccallbackinfo *gccallbackinfo;
+
+ while (!list_empty(&g_handlelist)) {
+ head = g_handlelist.next;
+ gccallbackhandle = list_entry(head,
+ struct gccallbackhandle,
+ link);
+
+ list_splice_init(&gccallbackhandle->triggered, &g_vacinfo);
+ list_splice_init(&gccallbackhandle->scheduled, &g_vacinfo);
+
+ list_del(head);
+ kfree(gccallbackhandle);
+ }
+
+ while (!list_empty(&g_vachandle)) {
+ head = g_vachandle.next;
+ gccallbackhandle = list_entry(head,
+ struct gccallbackhandle,
+ link);
+ list_del(head);
+ kfree(gccallbackhandle);
+ }
+
+ while (!list_empty(&g_vacinfo)) {
+ head = g_vacinfo.next;
+ gccallbackinfo = list_entry(head,
+ struct gccallbackinfo,
+ link);
+ list_del(head);
+ kfree(gccallbackinfo);
+ }
+}
+
+
+/*******************************************************************************
+ * API user wrappers.
+ */
+
+static int gc_getcaps_wrapper(struct gcicaps *gcicaps)
+{
+ int ret = 0;
+ struct gcicaps cpcaps;
+
+ GCENTER(GCZONE_CAPS);
+
+ /* Call the core driver. */
+ gc_caps(&cpcaps);
+
+ if (copy_to_user(gcicaps, &cpcaps, sizeof(struct gcicaps))) {
+ GCERR("failed to write data.\n");
+ ret = -EFAULT;
+ }
+
+ GCEXIT(GCZONE_CAPS);
+ return ret;
+}
+
+static int gc_commit_wrapper(struct gcicommit *gcicommit)
+{
+ int ret = 0;
+ bool buffercopied = false;
+ bool unmapcopied = false;
+ struct gcicommit cpcommit;
+ struct gccallbackinfo *gccallbackinfo;
+
+ struct list_head *gcbufferhead;
+ struct gcbuffer *cpbuffer, *gcbuffer;
+ LIST_HEAD(cpbufferlist);
+
+ struct list_head *gcfixuphead;
+ struct gcfixup *cpfixup, *gcfixup;
+ struct gcfixupentry *gcfixupentry;
+ int tablesize;
+
+ struct list_head *gcschedunmaphead;
+ struct gcschedunmap *cpschedunmap, *gcschedunmap;
+ LIST_HEAD(cpunmaplist);
+
+ GCENTER(GCZONE_COMMIT);
+
+ /* Get IOCTL parameters. */
+ if (copy_from_user(&cpcommit, gcicommit, sizeof(struct gcicommit))) {
+ GCERR("failed to read data.\n");
+ cpcommit.gcerror = GCERR_USER_READ;
+ goto exit;
+ }
+
+ /* Make a copy of the user buffer list. */
+ gcbufferhead = cpcommit.buffer.next;
+ while (gcbufferhead != &gcicommit->buffer) {
+ gcbuffer = list_entry(gcbufferhead, struct gcbuffer, link);
+ GCDBG(GCZONE_COMMIT, "copying buffer 0x%08X.\n",
+ (unsigned int) gcbuffer);
+
+ /* Allocate a buffer structure. */
+ cpcommit.gcerror = alloc_buffer(&cpbuffer);
+ if (cpcommit.gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Get the data from the user. */
+ if (copy_from_user(cpbuffer, gcbuffer,
+ sizeof(struct gcbuffer))) {
+ free_buffer(cpbuffer);
+ GCERR("failed to read data.\n");
+ cpcommit.gcerror = GCERR_USER_READ;
+ goto exit;
+ }
+
+ /* Get the next user buffer. */
+ gcbufferhead = cpbuffer->link.next;
+
+ /* Add the buffer to the list. */
+ list_add_tail(&cpbuffer->link, &cpbufferlist);
+
+ /* Copy all fixups. */
+ gcfixuphead = cpbuffer->fixup.next;
+ INIT_LIST_HEAD(&cpbuffer->fixup);
+ while (gcfixuphead != &gcbuffer->fixup) {
+ gcfixup = list_entry(gcfixuphead, struct gcfixup, link);
+ GCDBG(GCZONE_COMMIT, "copying fixup 0x%08X.\n",
+ (unsigned int) gcfixup);
+
+ /* Allocare a fixup structure. */
+ cpcommit.gcerror = alloc_fixup(&cpfixup);
+ if (cpcommit.gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Get the size of the fixup array. */
+ if (copy_from_user(cpfixup, gcfixup,
+ offsetof(struct gcfixup, fixup))) {
+ free_fixup(cpfixup);
+ GCERR("failed to read data.\n");
+ cpcommit.gcerror = GCERR_USER_READ;
+ goto exit;
+ }
+
+ /* Get the next fixup. */
+ gcfixuphead = cpfixup->link.next;
+
+ /* Add to the list. */
+ list_add_tail(&cpfixup->link, &cpbuffer->fixup);
+
+ /* Get the fixup array. */
+ gcfixupentry = gcfixup->fixup;
+
+ /* Compute the size of the fixup table. */
+ tablesize = cpfixup->count
+ * sizeof(struct gcfixupentry);
+
+ /* Get the fixup table. */
+ if (copy_from_user(cpfixup->fixup, gcfixupentry,
+ tablesize)) {
+ GCERR("failed to read data.\n");
+ cpcommit.gcerror = GCERR_USER_READ;
+ goto exit;
+ }
+ }
+ }
+
+ /* Move the local list to the commit structure. */
+ INIT_LIST_HEAD(&cpcommit.buffer);
+ list_splice_init(&cpbufferlist, &cpcommit.buffer);
+ buffercopied = true;
+
+ /* Copy scheduled unmappings to the local list. */
+ GCDBG(GCZONE_COMMIT, "copying unmaps.\n");
+ gcschedunmaphead = cpcommit.unmap.next;
+ while (gcschedunmaphead != &gcicommit->unmap) {
+ /* Get a pointer to the user structure. */
+ gcschedunmap = list_entry(gcschedunmaphead,
+ struct gcschedunmap,
+ link);
+ GCDBG(GCZONE_COMMIT, "unmap 0x%08X.\n",
+ (unsigned int) gcschedunmap);
+
+ /* Allocate unmap record. */
+ cpcommit.gcerror = alloc_schedunmap(&cpschedunmap);
+ if (cpcommit.gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Copy unmap record from user. */
+ if (copy_from_user(cpschedunmap, gcschedunmap,
+ sizeof(struct gcschedunmap))) {
+ free_schedunmap(cpschedunmap);
+ GCERR("failed to read data.\n");
+ cpcommit.gcerror = GCERR_USER_READ;
+ goto exit;
+ }
+
+ /* Get the next record. */
+ gcschedunmaphead = cpschedunmap->link.next;
+
+ /* Append to the list. */
+ list_add_tail(&cpschedunmap->link, &cpunmaplist);
+ }
+
+ /* Move the local list to the commit structure. */
+ INIT_LIST_HEAD(&cpcommit.unmap);
+ list_splice_init(&cpunmaplist, &cpcommit.unmap);
+ unmapcopied = true;
+
+ /* Setup callback. */
+ if (cpcommit.callback != NULL) {
+ GCDBG(GCZONE_COMMIT, "setting up callback.\n");
+
+ /* Allocate callback info. */
+ cpcommit.gcerror = alloc_callbackinfo(cpcommit.handle,
+ &gccallbackinfo);
+ if (cpcommit.gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Initialize callback info. */
+ gccallbackinfo->callback = cpcommit.callback;
+ gccallbackinfo->callbackparam = cpcommit.callbackparam;
+
+ /* Substiture the callback. */
+ cpcommit.callback = gccallback;
+ cpcommit.callbackparam = gccallbackinfo;
+ } else {
+ GCDBG(GCZONE_COMMIT, "no callback provided.\n");
+ }
+
+ /* Call the core driver. */
+ gc_commit(&cpcommit, true);
+
+exit:
+ if (copy_to_user(&gcicommit->gcerror, &cpcommit.gcerror,
+ sizeof(enum gcerror))) {
+ GCERR("failed to write data.\n");
+ ret = -EFAULT;
+ }
+
+ /* Free temporary resources. */
+ free_buffer_list(buffercopied ? &cpcommit.buffer : &cpbufferlist);
+ free_schedunmap_list(unmapcopied ? &cpcommit.unmap : &cpunmaplist);
+
+ GCEXIT(GCZONE_COMMIT);
+ return ret;
+}
+
+static int gc_map_wrapper(struct gcimap *gcimap)
+{
+ int ret = 0;
+ int mapped = 0;
+ struct gcimap cpmap;
+
+ GCENTER(GCZONE_MAPPING);
+
+ /* Get IOCTL parameters. */
+ if (copy_from_user(&cpmap, gcimap, sizeof(struct gcimap))) {
+ GCERR("failed to read data.\n");
+ cpmap.gcerror = GCERR_USER_READ;
+ goto exit;
+ }
+
+ cpmap.pagearray = NULL;
+
+ /* Call the core driver. */
+ gc_map(&cpmap, true);
+ if (cpmap.gcerror != GCERR_NONE)
+ goto exit;
+ mapped = 1;
+
+exit:
+ if (copy_to_user(gcimap, &cpmap, offsetof(struct gcimap, buf))) {
+ GCERR("failed to write data.\n");
+ cpmap.gcerror = GCERR_USER_WRITE;
+ ret = -EFAULT;
+ }
+
+ if (cpmap.gcerror != GCERR_NONE) {
+ if (mapped)
+ gc_unmap(&cpmap, true);
+ }
+
+ GCEXIT(GCZONE_MAPPING);
+ return ret;
+}
+
+static int gc_unmap_wrapper(struct gcimap *gcimap)
+{
+ int ret = 0;
+ struct gcimap cpmap;
+
+ GCENTER(GCZONE_MAPPING);
+
+ /* Get IOCTL parameters. */
+ if (copy_from_user(&cpmap, gcimap, sizeof(struct gcimap))) {
+ GCERR("failed to read data.\n");
+ cpmap.gcerror = GCERR_USER_READ;
+ goto exit;
+ }
+
+ /* Call the core driver. */
+ gc_unmap(&cpmap, true);
+
+exit:
+ if (copy_to_user(gcimap, &cpmap, offsetof(struct gcimap, buf))) {
+ GCERR("failed to write data.\n");
+ ret = -EFAULT;
+ }
+
+ GCEXIT(GCZONE_MAPPING);
+ return ret;
+}
+
+static int gc_cache_wrapper(struct gcicache *gcicache)
+{
+ int ret = 0;
+ struct gcicache cpcache;
+
+ GCENTER(GCZONE_CACHE);
+
+ /* Get IOCTL parameters. */
+ if (copy_from_user(&cpcache, gcicache, sizeof(struct gcicache))) {
+ GCERR("failed to read data.\n");
+ goto exit;
+ }
+
+ switch (cpcache.dir) {
+ case DMA_FROM_DEVICE:
+ c2dm_l2cache(cpcache.count, cpcache.rgn, cpcache.dir);
+ c2dm_l1cache(cpcache.count, cpcache.rgn, cpcache.dir);
+ break;
+
+ case DMA_TO_DEVICE:
+ c2dm_l1cache(cpcache.count, cpcache.rgn, cpcache.dir);
+ c2dm_l2cache(cpcache.count, cpcache.rgn, cpcache.dir);
+ break;
+
+ case DMA_BIDIRECTIONAL:
+ c2dm_l1cache(cpcache.count, cpcache.rgn, cpcache.dir);
+ c2dm_l2cache(cpcache.count, cpcache.rgn, cpcache.dir);
+ break;
+ }
+
+exit:
+ GCEXIT(GCZONE_CACHE);
+ return ret;
+}
+
+static int gc_callback_alloc(struct gcicallback *gcicallback)
+{
+ int ret = 0;
+ struct gcicallback cpcmdcallback;
+ struct gccallbackhandle *gccallbackhandle;
+
+ GCENTER(GCZONE_CALLBACK);
+
+ /* Reset the handle. */
+ cpcmdcallback.handle = 0;
+
+ /* Allocate callback handle struct. */
+ cpcmdcallback.gcerror = alloc_callbackhandle(&gccallbackhandle);
+ if (cpcmdcallback.gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Set the handle. */
+ cpcmdcallback.handle = (unsigned long) gccallbackhandle;
+
+exit:
+ if (copy_to_user(gcicallback, &cpcmdcallback,
+ sizeof(struct gcicallback))) {
+ GCERR("failed to write data.\n");
+ ret = -EFAULT;
+ }
+
+ GCEXIT(GCZONE_CALLBACK);
+ return ret;
+}
+
+static int gc_callback_free(struct gcicallback *gcicallback)
+{
+ int ret = 0;
+ struct gcicallback cpcmdcallback;
+ struct gccallbackhandle *gccallbackhandle;
+
+ GCENTER(GCZONE_CALLBACK);
+
+ /* Get IOCTL parameters. */
+ if (copy_from_user(&cpcmdcallback, gcicallback,
+ sizeof(struct gcicallback))) {
+ GCERR("failed to read data.\n");
+ cpcmdcallback.gcerror = GCERR_USER_READ;
+ goto exit;
+ }
+
+ /* Free the handle struct. */
+ gccallbackhandle = (struct gccallbackhandle *) cpcmdcallback.handle;
+ free_callbackhandle(gccallbackhandle);
+
+ /* Reset the handle. */
+ cpcmdcallback.handle = 0;
+ cpcmdcallback.gcerror = GCERR_NONE;
+
+exit:
+ if (copy_to_user(gcicallback, &cpcmdcallback,
+ sizeof(struct gcicallback))) {
+ GCERR("failed to write data.\n");
+ ret = -EFAULT;
+ }
+
+ GCEXIT(GCZONE_CALLBACK);
+ return ret;
+}
+
+static int gc_callback_wait(struct gcicallbackwait *gcicallbackwait)
+{
+ int ret = 0;
+ struct gcicallbackwait cpcmdcallbackwait;
+ struct gccallbackhandle *gccallbackhandle;
+ struct gccallbackinfo *gccallbackinfo;
+ struct list_head *head;
+ unsigned long timeout;
+
+ GCENTER(GCZONE_CALLBACK);
+
+ /* Get IOCTL parameters. */
+ if (copy_from_user(&cpcmdcallbackwait, gcicallbackwait,
+ sizeof(struct gcicallbackwait))) {
+ GCERR("failed to read data.\n");
+ cpcmdcallbackwait.gcerror = GCERR_USER_READ;
+ goto exit;
+ }
+
+ /* Cast the handle. */
+ gccallbackhandle = (struct gccallbackhandle *) cpcmdcallbackwait.handle;
+
+ /* Convert milliseconds to jiffies. */
+ timeout = (cpcmdcallbackwait.timeoutms == ~0U)
+ ? MAX_SCHEDULE_TIMEOUT
+ : msecs_to_jiffies(cpcmdcallbackwait.timeoutms);
+
+ /* Wait until a callback is triggered. */
+ timeout = wait_for_completion_interruptible_timeout(
+ &gccallbackhandle->ready, timeout);
+
+ if (timeout < 0) {
+ /* Error occurred. */
+ ret = timeout;
+ } else if (timeout == 0) {
+ /* Timeout. */
+ cpcmdcallbackwait.gcerror = GCERR_TIMEOUT;
+ cpcmdcallbackwait.callback = NULL;
+ cpcmdcallbackwait.callbackparam = NULL;
+ } else {
+ /* Callback event triggered. */
+ GCLOCK(&g_callbacklock);
+
+ if (list_empty(&gccallbackhandle->triggered)) {
+ GCERR("triggered list is empty.\n");
+ } else {
+ /* Get the head of the triggered list. */
+ head = gccallbackhandle->triggered.next;
+ gccallbackinfo = list_entry(head,
+ struct gccallbackinfo,
+ link);
+
+ /* Set callback info. */
+ cpcmdcallbackwait.callback
+ = gccallbackinfo->callback;
+ cpcmdcallbackwait.callbackparam
+ = gccallbackinfo->callbackparam;
+
+ /* Free the entry. */
+ list_move(head, &g_vacinfo);
+ }
+
+ GCUNLOCK(&g_callbacklock);
+ cpcmdcallbackwait.gcerror = GCERR_NONE;
+ }
+
+exit:
+ if (copy_to_user(gcicallbackwait, &cpcmdcallbackwait,
+ sizeof(struct gcicallbackwait))) {
+ GCERR("failed to write data.\n");
+ ret = -EFAULT;
+ }
+
+ GCEXIT(GCZONE_CALLBACK);
+ return ret;
+}
+
+static int gc_callback_arm(struct gcicallbackarm *gcicallbackarm)
+{
+ int ret = 0;
+ struct gcicallbackarm cpcallbackarm;
+ struct gccallbackinfo *gccallbackinfo;
+
+ GCENTER(GCZONE_CALLBACK);
+
+ /* Get IOCTL parameters. */
+ if (copy_from_user(&cpcallbackarm, gcicallbackarm,
+ sizeof(struct gcicallbackarm))) {
+ GCERR("failed to read data.\n");
+ cpcallbackarm.gcerror = GCERR_USER_READ;
+ goto exit;
+ }
+
+ /* Allocate callback info. */
+ cpcallbackarm.gcerror = alloc_callbackinfo(cpcallbackarm.handle,
+ &gccallbackinfo);
+ if (cpcallbackarm.gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Initialize callback info. */
+ gccallbackinfo->callback = cpcallbackarm.callback;
+ gccallbackinfo->callbackparam = cpcallbackarm.callbackparam;
+
+ /* Substiture the callback. */
+ cpcallbackarm.callback = gccallback;
+ cpcallbackarm.callbackparam = gccallbackinfo;
+
+ /* Call the core driver. */
+ gc_callback(&cpcallbackarm, true);
+
+exit:
+ if (copy_to_user(&gcicallbackarm->gcerror, &cpcallbackarm.gcerror,
+ sizeof(enum gcerror))) {
+ GCERR("failed to write data.\n");
+ ret = -EFAULT;
+ }
+
+ GCEXIT(GCZONE_CALLBACK);
+ return ret;
+}
+
+
+/*******************************************************************************
+ * Device definitions/operations.
+ */
+
+static int dev_major;
+static struct class *dev_class;
+static struct device *dev_object;
+
+static int dev_open(struct inode *inode, struct file *file)
+{
+ if (gc_is_hw_present()) {
+ return 0;
+ } else {
+ GCERR("gcx hardware is not present\n");
+ return -ENODEV;
+ }
+}
+
+static int dev_release(struct inode *inode, struct file *file)
+{
+ gc_release();
+ return 0;
+}
+
+static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret;
+
+ switch (cmd) {
+ case GCIOCTL_GETCAPS:
+ GCDBG(GCZONE_IOCTL, "GCIOCTL_GETCAPS\n");
+ ret = gc_getcaps_wrapper((struct gcicaps *) arg);
+ break;
+
+ case GCIOCTL_COMMIT:
+ GCDBG(GCZONE_IOCTL, "GCIOCTL_COMMIT\n");
+ ret = gc_commit_wrapper((struct gcicommit *) arg);
+ break;
+
+ case GCIOCTL_MAP:
+ GCDBG(GCZONE_IOCTL, "GCIOCTL_MAP\n");
+ ret = gc_map_wrapper((struct gcimap *) arg);
+ break;
+
+ case GCIOCTL_UNMAP:
+ GCDBG(GCZONE_IOCTL, "GCIOCTL_UNMAP\n");
+ ret = gc_unmap_wrapper((struct gcimap *) arg);
+ break;
+
+ case GCIOCTL_CACHE:
+ GCDBG(GCZONE_IOCTL, "GCIOCTL_CACHE\n");
+ ret = gc_cache_wrapper((struct gcicache *) arg);
+ break;
+
+ case GCIOCTL_CALLBACK_ALLOC:
+ GCDBG(GCZONE_IOCTL, "GCIOCTL_CALLBACK_ALLOC\n");
+ ret = gc_callback_alloc((struct gcicallback *) arg);
+ break;
+
+ case GCIOCTL_CALLBACK_FREE:
+ GCDBG(GCZONE_IOCTL, "GCIOCTL_CALLBACK_FREE\n");
+ ret = gc_callback_free((struct gcicallback *) arg);
+ break;
+
+ case GCIOCTL_CALLBACK_WAIT:
+ GCDBG(GCZONE_IOCTL, "GCIOCTL_CALLBACK_WAIT\n");
+ ret = gc_callback_wait((struct gcicallbackwait *) arg);
+ break;
+
+ case GCIOCTL_CALLBACK_ARM:
+ GCDBG(GCZONE_IOCTL, "GCIOCTL_CALLBACK_ARM\n");
+ ret = gc_callback_arm((struct gcicallbackarm *) arg);
+ break;
+
+ default:
+ GCERR("invalid command (%d)\n", cmd);
+ ret = -EINVAL;
+ }
+
+ GCDBG(GCZONE_IOCTL, "ret = %d\n", ret);
+
+ return ret;
+}
+
+static const struct file_operations dev_operations = {
+ .open = dev_open,
+ .release = dev_release,
+ .unlocked_ioctl = dev_ioctl,
+};
+
+
+/*******************************************************************************
+ * Device init/cleanup.
+ */
+
+static int mod_init(void);
+static void mod_exit(void);
+
+static struct platform_driver gcx_drv = {
+ .probe = 0,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "gcx",
+ },
+};
+
+static const char *gcx_version = VER_FILEVERSION_STR;
+
+static ssize_t show_version(struct device_driver *driver, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%s\n", gcx_version);
+}
+
+static DRIVER_ATTR(version, 0444, show_version, NULL);
+
+static int mod_init(void)
+{
+ int ret = 0;
+
+ GCDBG(GCZONE_INIT, "initializing device.\n");
+
+ /* Register the character device. */
+ dev_major = register_chrdev(0, GC_DEV_NAME, &dev_operations);
+ if (dev_major < 0) {
+ GCERR("failed to allocate device (%d).\n", ret = dev_major);
+ goto failed;
+ }
+
+ /* Create the device class. */
+ dev_class = class_create(THIS_MODULE, GC_DEV_NAME);
+ if (IS_ERR(dev_class)) {
+ GCERR("failed to create class (%d).\n",
+ ret = PTR_ERR(dev_class));
+ goto failed;
+ }
+
+ /* Create device. */
+ dev_object = device_create(dev_class, NULL, MKDEV(dev_major, 0),
+ NULL, GC_DEV_NAME);
+ if (IS_ERR(dev_object)) {
+ GCERR("failed to create device (%d).\n",
+ ret = PTR_ERR(dev_object));
+ goto failed;
+ }
+
+ ret = platform_driver_register(&gcx_drv);
+ if (ret) {
+ GCERR("failed to create gcx driver (%d).\n", ret);
+ goto failed;
+ }
+
+ ret = driver_create_file(&gcx_drv.driver, &driver_attr_version);
+ if (ret) {
+ GCERR("failed to create gcx driver version (%d).\n", ret);
+ goto failed;
+ }
+
+ GCDBG_REGISTER(ioctl, GCZONE_NONE);
+
+ GCDBG(GCZONE_INIT, "device number = %d\n", dev_major);
+ GCDBG(GCZONE_INIT, "device class = 0x%08X\n",
+ (unsigned int) dev_class);
+ GCDBG(GCZONE_INIT, "device object = 0x%08X\n",
+ (unsigned int) dev_object);
+
+ return 0;
+
+failed:
+ mod_exit();
+ return ret;
+}
+
+static void mod_exit(void)
+{
+ GCDBG(GCZONE_INIT, "cleaning up resources.\n");
+
+ if ((dev_object != NULL) && !IS_ERR(dev_object)) {
+ device_destroy(dev_class, MKDEV(dev_major, 0));
+ dev_object = NULL;
+ }
+
+ if ((dev_class != NULL) && !IS_ERR(dev_class)) {
+ class_destroy(dev_class);
+ dev_class = NULL;
+ }
+
+ if (dev_major > 0) {
+ unregister_chrdev(dev_major, GC_DEV_NAME);
+ dev_major = 0;
+ }
+
+ platform_driver_unregister(&gcx_drv);
+ driver_remove_file(&gcx_drv.driver, &driver_attr_version);
+
+ free_vacant_buffers();
+ free_vacant_fixups();
+ free_vacant_unmap();
+ destroy_callback();
+}
+
+static int __init mod_init_wrapper(void)
+{
+ return mod_init();
+}
+
+static void __exit mod_exit_wrapper(void)
+{
+ mod_exit();
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("www.vivantecorp.com");
+MODULE_AUTHOR("www.ti.com");
+module_init(mod_init_wrapper);
+module_exit(mod_exit_wrapper);
diff --git a/drivers/misc/gcx/gcioctl/gcif.h b/drivers/misc/gcx/gcioctl/gcif.h
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * gcmain.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCMAIN_H
+#define GCMAIN_H
+
+#define GC_DEV_NAME "gcioctl"
+
+#endif
diff --git a/drivers/misc/gcx/gcioctl/version.h b/drivers/misc/gcx/gcioctl/version.h
--- /dev/null
@@ -0,0 +1,4 @@
+#define VER_FILEVERSION {2, 2, 2, 0}
+#define VER_FILEVERSION_STR "2.2.2.0\0"
+#define VER_PRODUCTVERSION {2, 2, 2, 0}
+#define VER_PRODUCTVERSION_STR "2.2\0"
index 74392c177313a7178841e8e17caf3ab666be33d2..cb05cbefe1044b47e9868e95ac9831c917197260 100644 (file)
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
#include <linux/usb/otg.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+#include <linux/usb/of.h>
#include "core.h"
#include "gadget.h"
#include "debug.h"
-static char *maximum_speed = "super";
-module_param(maximum_speed, charp, 0);
-MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
-
/* -------------------------------------------------------------------------- */
void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
void *mem;
u8 mode;
+ u8 dt_mode;
mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
if (!mem) {
}
if (node) {
- dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
- dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
+ dwc->maximum_speed = of_usb_get_maximum_speed(node);
+ switch (dwc->maximum_speed) {
+ case USB_SPEED_SUPER:
+ case USB_SPEED_UNKNOWN:
+ dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
+ dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
+ break;
+ case USB_SPEED_HIGH:
+ case USB_SPEED_FULL:
+ case USB_SPEED_LOW:
+ dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
+ break;
+ }
} else {
- dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
- dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+ dwc->maximum_speed = USB_SPEED_UNKNOWN;
+ switch (dwc->maximum_speed) {
+ case USB_SPEED_SUPER:
+ case USB_SPEED_UNKNOWN:
+ dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+ break;
+ case USB_SPEED_HIGH:
+ case USB_SPEED_FULL:
+ case USB_SPEED_LOW:
+ dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ break;
+ }
}
+ /* default to superspeed if no maximum_speed passed */
+ if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
+ dwc->maximum_speed = USB_SPEED_SUPER;
+
if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
dev_err(dev, "no usb2 phy configured\n");
return -EPROBE_DEFER;
}
- if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
- dev_err(dev, "no usb3 phy configured\n");
- return -EPROBE_DEFER;
+ if (dwc->maximum_speed == USB_SPEED_SUPER) {
+ if (IS_ERR(dwc->usb3_phy)) {
+ ret = PTR_ERR(dwc->usb2_phy);
+ dev_err(dev, "no usb3 phy configured\n");
+ return -EPROBE_DEFER;
+ }
}
usb_phy_set_suspend(dwc->usb2_phy, 0);
dwc->regs_size = resource_size(res);
dwc->dev = dev;
- if (!strncmp("super", maximum_speed, 5))
- dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
- else if (!strncmp("high", maximum_speed, 4))
- dwc->maximum_speed = DWC3_DCFG_HIGHSPEED;
- else if (!strncmp("full", maximum_speed, 4))
- dwc->maximum_speed = DWC3_DCFG_FULLSPEED1;
- else if (!strncmp("low", maximum_speed, 3))
- dwc->maximum_speed = DWC3_DCFG_LOWSPEED;
- else
- dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
-
dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
pm_runtime_enable(dev);
goto err0;
}
- if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
- mode = DWC3_MODE_HOST;
- else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
- mode = DWC3_MODE_DEVICE;
- else
- mode = DWC3_MODE_DRD;
+ mode = USB_DR_MODE_UNKNOWN;
+ if (node)
+ dt_mode = of_usb_get_dr_mode(node);
+
+ if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) {
+ mode = USB_DR_MODE_HOST;
+ if (node && (mode != dt_mode))
+ dev_warn(dev, "dr_mode set to host,check value in DT\n");
+ }
+ else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
+ mode = USB_DR_MODE_PERIPHERAL;
+ if (node && (mode != dt_mode))
+ dev_warn(dev, "dr_mode set to periph,check value in DT\n");
+ }
+ else if (node)
+ mode = dt_mode;
+
+ if (mode == USB_DR_MODE_UNKNOWN) {
+ mode = USB_DR_MODE_OTG;
+ dev_warn(dev, "dwc3 mode set to otg default\n");
+ }
switch (mode) {
- case DWC3_MODE_DEVICE:
+ case USB_DR_MODE_PERIPHERAL:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
ret = dwc3_gadget_init(dwc);
if (ret) {
goto err1;
}
break;
- case DWC3_MODE_HOST:
+ case USB_DR_MODE_HOST:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
ret = dwc3_host_init(dwc);
if (ret) {
goto err1;
}
break;
- case DWC3_MODE_DRD:
+ case USB_DR_MODE_OTG:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
ret = dwc3_host_init(dwc);
if (ret) {
err2:
switch (mode) {
- case DWC3_MODE_DEVICE:
+ case USB_DR_MODE_PERIPHERAL:
dwc3_gadget_exit(dwc);
break;
- case DWC3_MODE_HOST:
+ case USB_DR_MODE_HOST:
dwc3_host_exit(dwc);
break;
- case DWC3_MODE_DRD:
+ case USB_DR_MODE_OTG:
dwc3_host_exit(dwc);
dwc3_gadget_exit(dwc);
break;
dwc3_debugfs_exit(dwc);
switch (dwc->mode) {
- case DWC3_MODE_DEVICE:
+ case USB_DR_MODE_PERIPHERAL:
dwc3_gadget_exit(dwc);
break;
- case DWC3_MODE_HOST:
+ case USB_DR_MODE_HOST:
dwc3_host_exit(dwc);
break;
- case DWC3_MODE_DRD:
+ case USB_DR_MODE_OTG:
dwc3_host_exit(dwc);
dwc3_gadget_exit(dwc);
break;
index c56d404d651e41fc817de47c12dc1ec2b451a6b4..425466663fca67a3896a5748d6c7bcddb1117277 100644 (file)
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
/* HWPARAMS0 */
#define DWC3_MODE(n) ((n) & 0x7)
-#define DWC3_MODE_DEVICE 0
-#define DWC3_MODE_HOST 1
-#define DWC3_MODE_DRD 2
-#define DWC3_MODE_HUB 3
-
#define DWC3_MDWIDTH(n) (((n) & 0xff00) >> 8)
/* HWPARAMS1 */
* @irq: IRQ number
* @num_event_buffers: calculated number of event buffers
* @u1u2: only used on revisions <1.83a for workaround
- * @maximum_speed: maximum speed requested (mainly for testing purposes)
+ * @maximum_speed: maximum speed requested
* @revision: revision register contents
* @mode: mode of operation
* @usb2_phy: pointer to USB2 PHY
u32 num_event_buffers;
u32 u1u2;
- u32 maximum_speed;
+ enum usb_device_speed maximum_speed;
u32 revision;
u32 mode;
index 352f397d4aae3e7c17a22d5b47e0887ee3594303..e4a9dbe8cbc6f08137e5d67408d7a1b7e02f4759 100644 (file)
@@ -139,14 +139,22 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
writel(value, base + offset);
}
-int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+int dwc3_omap_mailbox(struct device *dev, enum omap_dwc3_vbus_id_status status)
{
u32 val;
- struct dwc3_omap *omap = _omap;
+ struct platform_device *pdev;
+ struct dwc3_omap *omap;
- if (!omap)
- return -EPROBE_DEFER;
+ if (dev) { /* i.e. this is being called from a non palmas driver */
+ pdev = to_platform_device(dev);
+ omap = platform_get_drvdata(pdev);
+ } else /* This is being invoked by palmas and the global is needed */
+ omap = _omap;
+ if (!omap) {
+ dev_dbg(omap->dev, "not ready , deferring\n");
+ return -EPROBE_DEFER;
+ }
switch (status) {
case OMAP_DWC3_ID_GROUND:
dev_dbg(omap->dev, "ID GND\n");
dev_dbg(omap->dev, "ID float\n");
}
- return IRQ_HANDLED;
+ return 0;
}
EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
return 0;
}
+static u64 dwc3_omap_dma_mask1 = DMA_BIT_MASK(32);
+
+static int dwc3_omap_set_dmamask1(struct device *dev, void *c)
+{
+ dev->dma_mask = &dwc3_omap_dma_mask1;
+ return 0;
+}
+
+static u64 dwc3_omap_dma_mask2 = DMA_BIT_MASK(32);
+
+static int dwc3_omap_set_dmamask2(struct device *dev, void *c)
+{
+ dev->dma_mask = &dwc3_omap_dma_mask2;
+ return 0;
+}
+
static int dwc3_omap_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
return ret;
}
- device_for_each_child(&pdev->dev, NULL, dwc3_omap_set_dmamask);
+ if (strstr(dev_name(dev), "omap_dwc31") != NULL)
+ device_for_each_child(&pdev->dev, NULL, dwc3_omap_set_dmamask1);
+ else
+ if (strstr(dev_name(dev), "omap_dwc32") != NULL)
+ device_for_each_child(&pdev->dev, NULL, dwc3_omap_set_dmamask2);
+ else
+ if (strstr(dev_name(dev), "omap_dwc3") != NULL)
+ device_for_each_child(&pdev->dev, NULL, dwc3_omap_set_dmamask);
return 0;
}
index 6990601f2906deb1285228bb91293805d27966b2..f90fa6e11f7be6e86c8de0784ca00a4728e5552c 100644 (file)
#include "core.h"
#include "gadget.h"
#include "io.h"
+#include <linux/usb/dwc3-omap.h>
+#include <linux/platform_data/dwc3-omap.h>
/**
* dwc3_gadget_set_test_mode - Enables USB2 Test Modes
@@ -1048,6 +1050,13 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
req->direction = dep->direction;
req->epnum = dep->number;
+ /* For a "read" direction aka OUT endpoints */
+ if (req->direction == 0) {
+ if (req->request.length % dep->endpoint.desc->wMaxPacketSize) {
+ req->request.length += ( dep->endpoint.desc->wMaxPacketSize - req->request.length);
+ }
+ }
+
/*
* We only add to our list of requests now and
* start consuming the list once we get XferNotReady
is_on = !!is_on;
+#if defined(CONFIG_SOC_DRA7XX)
+ if (is_on) {
+ if (dwc3_omap_mailbox(dwc->dev->parent, OMAP_DWC3_VBUS_VALID))
+ dev_err(dwc->dev, "Error wrapper may not be initilized\n");
+ }
+#endif
spin_lock_irqsave(&dwc->lock, flags);
ret = dwc3_gadget_run_stop(dwc, is_on);
spin_unlock_irqrestore(&dwc->lock, flags);
* STAR#9000525659: Clock Domain Crossing on DCTL in
* USB 2.0 Mode
*/
- if (dwc->revision < DWC3_REVISION_220A)
+ if (dwc->revision < DWC3_REVISION_220A) {
reg |= DWC3_DCFG_SUPERSPEED;
- else
- reg |= dwc->maximum_speed;
+ } else {
+ switch (dwc->maximum_speed) {
+ case USB_SPEED_LOW:
+ reg |= DWC3_DSTS_LOWSPEED;
+ break;
+ case USB_SPEED_FULL:
+ reg |= DWC3_DSTS_FULLSPEED1;
+ break;
+ case USB_SPEED_HIGH:
+ reg |= DWC3_DSTS_HIGHSPEED;
+ break;
+ case USB_SPEED_SUPER: /* FALLTHROUGH */
+ case USB_SPEED_UNKNOWN: /* FALTHROUGH */
+ default:
+ reg |= DWC3_DSTS_SUPERSPEED;
+ }
+ }
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
dwc->start_config_issued = false;
/* -------------------------------------------------------------------------- */
+static int dwc3_gadget_get_maxpacket_ep0(struct dwc3 *dwc)
+{
+ switch (dwc->maximum_speed) {
+ case USB_SPEED_HIGH:
+ case USB_SPEED_FULL:
+ return 64;
+ case USB_SPEED_LOW:
+ return 8;
+ case USB_SPEED_SUPER:
+ default:
+ return 512;
+ }
+}
+
+static int dwc3_gadget_get_maxpacket(struct dwc3 *dwc)
+{
+ return 1024;
+}
+
static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
{
struct dwc3_ep *dep;
dep->direction = (epnum & 1);
if (epnum == 0 || epnum == 1) {
- dep->endpoint.maxpacket = 512;
+ dep->endpoint.maxpacket = dwc3_gadget_get_maxpacket_ep0(dwc);
dep->endpoint.maxburst = 1;
dep->endpoint.ops = &dwc3_gadget_ep0_ops;
if (!epnum)
} else {
int ret;
- dep->endpoint.maxpacket = 1024;
+ dep->endpoint.maxpacket = dwc3_gadget_get_maxpacket(dwc);
dep->endpoint.max_streams = 15;
dep->endpoint.ops = &dwc3_gadget_ep_ops;
list_add_tail(&dep->endpoint.ep_list,
index 11d247cc0e9fef03c04907947f5d5c2877680b21..3bd8de5af6e55ded403ffd6c759865b86d2cbdb7 100644 (file)
#include "gadget_chips.h"
#include "f_fs.c"
-#include "f_audio_source.c"
+//#include "f_audio_source.c"
#include "f_mass_storage.c"
#include "u_serial.c"
#include "f_acm.c"
.bind_config = accessory_function_bind_config,
.ctrlrequest = accessory_function_ctrlrequest,
};
-
+#if 0 //HACK
static int audio_source_function_init(struct android_usb_function *f,
struct usb_composite_dev *cdev)
{
.unbind_config = audio_source_function_unbind_config,
.attributes = audio_source_function_attributes,
};
-
+#endif
static struct android_usb_function *supported_functions[] = {
&ffs_function,
&acm_function,
&rndis_function,
&mass_storage_function,
&accessory_function,
- &audio_source_function,
+// &audio_source_function,
NULL
};
return 0;
}
-
-static int __init init(void)
+static int omap_android_probe(struct platform_device *pdev)
{
struct android_dev *dev;
int err;
+ if (usb_composite_probe_ready(&android_usb_driver) != 0) {
+ err = -EPROBE_DEFER;
+ goto err_ret;
+ }
+
android_class = class_create(THIS_MODULE, "android_usb");
if (IS_ERR(android_class))
return PTR_ERR(android_class);
kfree(dev);
err_dev:
class_destroy(android_class);
+err_ret:
return err;
}
-module_init(init);
-static void __exit cleanup(void)
+static int omap_android_remove(struct platform_device *pdev)
{
usb_composite_unregister(&android_usb_driver);
class_destroy(android_class);
kfree(_android_dev);
_android_dev = NULL;
+ return 0;
+}
+
+static struct platform_driver omap_g_androiddrv = {
+ .driver = {
+ .name = "omap_g_android",
+ .owner = THIS_MODULE,
+ },
+ .probe = omap_android_probe,
+ .remove = omap_android_remove,
+};
+module_platform_driver(omap_g_androiddrv);
+
+static int __init omap_init_g_android(void)
+{
+ struct platform_device_info devinfo = { .name = "omap_g_android", };
+ platform_device_register_full(&devinfo);
+ return 0;
}
-module_exit(cleanup);
+module_init(omap_init_g_android);
index 733047b31cfb5500a7079a7a24abd3c1c9c7bc87..a8ee0637dfeebe74c79d82000d18afe0560d1d14 100644 (file)
/**
* usb_string_ids() - allocate unused string IDs in batch
- * @cdev: the device whose string descriptor IDs are being allocated
+ @cdev: the device whose string descriptor IDs are being allocated
* @str: an array of usb_string objects to assign numbers to
* Context: single threaded during gadget setup
*
},
};
+int usb_composite_probe_ready(struct usb_composite_driver *driver){
+ struct usb_gadget_driver *gadget_driver;
+ int ready=0;
+
+ if (!driver || !driver->dev || !driver->bind)
+ return -EINVAL;
+
+ if (!driver->name)
+ driver->name = "composite";
+
+ driver->gadget_driver = composite_driver_template;
+ gadget_driver = &driver->gadget_driver;
+
+ gadget_driver->function = (char *) driver->name;
+ gadget_driver->driver.name = driver->name;
+ gadget_driver->max_speed = driver->max_speed;
+
+ ready = usb_gadget_probe_driver_ready(gadget_driver);
+ driver->name = NULL;
+ return ready;
+}
+
/**
* usb_composite_probe() - register a composite driver
* @driver: the driver to register
index 0b10575a2fac1eeccaf55c73a068965a89f158fd..a10ea8edc3724e87ab5dae79f4db42bc9a981260 100644 (file)
}
EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
+int usb_gadget_probe_driver_ready(struct usb_gadget_driver *driver)
+{
+ struct usb_udc *udc = NULL;
+
+ if (!driver || !driver->bind || !driver->setup)
+ return -EINVAL;
+
+ mutex_lock(&udc_lock);
+ list_for_each_entry(udc, &udc_list, list) {
+ /* For now we take the first one */
+ if (!udc->driver) {
+ mutex_unlock(&udc_lock);
+ return 0;
+ }
+ }
+
+ mutex_unlock(&udc_lock);
+ return -EPROBE_DEFER;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_probe_driver_ready);
+
/* ------------------------------------------------------------------------- */
int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
* on bind and expects the gadget to stay disconnected until
* it calls usb_gadget_connect when userspace is ready. Remove
* the call to usb_gadget_connect bellow to avoid enabling the
- * pullup before userspace is ready.
- *
- * usb_gadget_connect(udc->gadget);
+ * pullup before userspace is ready. Do the gadget connect in
+ * case of a non android system.
*/
+#ifndef CONFIG_USB_G_ANDROID
+ usb_gadget_connect(udc->gadget);
+#endif
} else {
ret = usb_gadget_start(udc->gadget, driver, driver->bind);
index 9215ae3da9dcccf3fdbdbb4e6d9b92df2c89d7ae..6d9234242b7034ae476ffb74488ce6a98bbd4b1d 100644 (file)
#include <linux/delay.h>
#include <linux/usb/musb-omap.h>
#include <linux/usb/omap_control_usb.h>
+#include <linux/of_platform.h>
#include "musb_core.h"
#include "omap2430.h"
struct platform_device *musb;
struct omap2430_glue *glue;
struct device_node *np = pdev->dev.of_node;
+ struct device_node *omap_control_usb_node;
+ struct platform_device *pdev_control_usb;
+
struct musb_hdrc_config *config;
int ret = -ENOMEM;
}
if (pdata->has_mailbox) {
- glue->control_otghs = omap_get_control_dev();
+ omap_control_usb_node = of_parse_phandle(np, "ctrl-module", 0);
+ if (IS_ERR(omap_control_usb_node)) {
+ dev_err(&pdev->dev, "Failed to find ctrl-module\n");
+ return -EPROBE_DEFER;
+ }
+ pdev_control_usb = of_find_device_by_node(omap_control_usb_node);
+
+ if (IS_ERR(pdev_control_usb)) {
+ dev_err(&pdev->dev, "Failed to find device node for ctrl-module\n");
+ return -EPROBE_DEFER;
+ }
+
+ glue->control_otghs = &pdev_control_usb->dev;
if (IS_ERR(glue->control_otghs)) {
dev_vdbg(&pdev->dev, "Failed to get control device\n");
return -ENODEV;
index 0ecbd94b16227dcec735053adc1b193e025f667e..3881cd19821cfbebb8df0b4b3fcfb3186bbc293d 100644 (file)
enum omap_dwc3_vbus_id_status status = OMAP_DWC3_UNKNOWN;
int slave;
unsigned int vbus_line_state, addr;
+ int ret = IRQ_NONE;
slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE);
addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE,
palmas_usb->linkstat = status;
if (status != OMAP_DWC3_UNKNOWN) {
- return dwc3_omap_mailbox(status);
+ ret = dwc3_omap_mailbox(NULL, status);
+ if (!ret)
+ ret = IRQ_HANDLED;
}
- return IRQ_NONE;
+ return ret;
}
static irqreturn_t palmas_id_wakeup_irq(int irq, void *_palmas_usb)
enum omap_dwc3_vbus_id_status status = OMAP_DWC3_UNKNOWN;
unsigned int set;
struct palmas_usb *palmas_usb = _palmas_usb;
+ int ret = IRQ_NONE;
palmas_usb_read(palmas_usb->palmas, PALMAS_USB_ID_INT_LATCH_SET, &set);
palmas_usb->linkstat = status;
if (status != OMAP_DWC3_UNKNOWN) {
- return dwc3_omap_mailbox(status);
+ ret = dwc3_omap_mailbox(NULL, status);
+ if (!ret)
+ ret = IRQ_HANDLED;
}
return IRQ_NONE;
index 6a072986b9bd935d1e05627e2fa4504815cc26a5..0d6c6c7ba68c377177e5dddabbff56623b114302 100644 (file)
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o
obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o
obj-$(CONFIG_USB_RCAR_PHY) += rcar-phy.o
+obj-$(CONFIG_OF) += of.o
+
diff --git a/drivers/usb/phy/of.c b/drivers/usb/phy/of.c
--- /dev/null
+++ b/drivers/usb/phy/of.c
@@ -0,0 +1,47 @@
+/*
+ * USB of helper code
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/usb/of.h>
+#include <linux/usb/otg.h>
+
+static const char *const usbphy_modes[] = {
+ [USBPHY_INTERFACE_MODE_UNKNOWN] = "",
+ [USBPHY_INTERFACE_MODE_UTMI] = "utmi",
+ [USBPHY_INTERFACE_MODE_UTMIW] = "utmi_wide",
+ [USBPHY_INTERFACE_MODE_ULPI] = "ulpi",
+ [USBPHY_INTERFACE_MODE_SERIAL] = "serial",
+ [USBPHY_INTERFACE_MODE_HSIC] = "hsic",
+};
+
+/**
+ * of_usb_get_phy_mode - Get phy mode for given device_node
+ * @np: Pointer to the given device_node
+ *
+ * The function gets phy interface string from property 'phy_type',
+ * and returns the correspondig enum usb_phy_interface
+ */
+enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np)
+{
+ const char *phy_type;
+ int err, i;
+
+ err = of_property_read_string(np, "phy_type", &phy_type);
+ if (err < 0)
+ return USBPHY_INTERFACE_MODE_UNKNOWN;
+
+ for (i = 0; i < ARRAY_SIZE(usbphy_modes); i++)
+ if (!strcmp(phy_type, usbphy_modes[i]))
+ return i;
+
+ return USBPHY_INTERFACE_MODE_UNKNOWN;
+}
+EXPORT_SYMBOL_GPL(of_usb_get_phy_mode);
index 5323b71c3521f4ebe41ad74260787103e6933ce5..3a605b01dd76da670e1b87a8a9ea00ce8e46b519 100644 (file)
#include <linux/clk.h>
#include <linux/usb/omap_control_usb.h>
-static struct omap_control_usb *control_usb;
-
-/**
- * omap_get_control_dev - returns the device pointer for this control device
- *
- * This API should be called to get the device pointer for this control
- * module device. This device pointer should be used for called other
- * exported API's in this driver.
- *
- * To be used by PHY driver and glue driver.
- */
-struct device *omap_get_control_dev(void)
-{
- if (!control_usb)
- return ERR_PTR(-ENODEV);
-
- return control_usb->dev;
-}
-EXPORT_SYMBOL_GPL(omap_get_control_dev);
-
/**
* omap_control_usb3_phy_power - power on/off the serializer using control
* module
u32 val;
struct omap_control_usb *control_usb = dev_get_drvdata(dev);
- val = readl(control_usb->dev_conf);
+ if (control_usb->type == OMAP_CTRL_DEV_TYPE2) {
- if (on)
- val &= ~OMAP_CTRL_DEV_PHY_PD;
- else
- val |= OMAP_CTRL_DEV_PHY_PD;
+ val = readl(control_usb->dev_conf);
+ if (on)
+ val &= ~OMAP_CTRL_DEV_PHY_PD;
+ else
+ val |= OMAP_CTRL_DEV_PHY_PD;
- writel(val, control_usb->dev_conf);
+ writel(val, control_usb->dev_conf);
+ } else {
+
+ if (on) {
+ val = readl(control_usb->dummy_reg);
+ val |= 0x100;
+ writel(val , control_usb->dummy_reg);
+
+ val = readl(control_usb->ctrl_core_srcomp_north_side);
+ val &= ~OMAP_CTRL_USB_SRCOMP_NORTH_SIDE_PD;
+ writel(val, control_usb->ctrl_core_srcomp_north_side);
+ } else {
+ val = readl(control_usb->ctrl_core_srcomp_north_side);
+ val |= OMAP_CTRL_USB_SRCOMP_NORTH_SIDE_PD;
+ writel(val, control_usb->ctrl_core_srcomp_north_side);
+
+ val = readl(control_usb->dummy_reg);
+ val &= ~0x100;
+ writel(val , control_usb->dummy_reg);
+ }
+
+ }
}
EXPORT_SYMBOL_GPL(omap_control_usb_phy_power);
{
struct omap_control_usb *ctrl_usb;
- if (IS_ERR(dev) || control_usb->type != OMAP_CTRL_DEV_TYPE1)
+ if (IS_ERR(dev))
return;
ctrl_usb = dev_get_drvdata(dev);
+ if (ctrl_usb->type != OMAP_CTRL_DEV_TYPE1)
+ return;
switch (mode) {
case USB_MODE_HOST:
struct resource *res;
struct device_node *np = pdev->dev.of_node;
struct omap_control_usb_platform_data *pdata = pdev->dev.platform_data;
+ struct omap_control_usb *control_usb;
control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),
GFP_KERNEL);
control_usb->dev = &pdev->dev;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "control_dev_conf");
- control_usb->dev_conf = devm_request_and_ioremap(&pdev->dev, res);
- if (!control_usb->dev_conf) {
- dev_err(&pdev->dev, "Failed to obtain io memory\n");
- return -EADDRNOTAVAIL;
- }
-
if (control_usb->type == OMAP_CTRL_DEV_TYPE1) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"otghs_control");
}
if (control_usb->type == OMAP_CTRL_DEV_TYPE2) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "control_dev_conf");
+ control_usb->dev_conf = devm_request_and_ioremap(&pdev->dev, res);
+ if (!control_usb->dev_conf) {
+ dev_err(&pdev->dev, "Failed to obtain io memory\n");
+ return -EADDRNOTAVAIL;
+ }
+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"phy_power_usb");
control_usb->phy_power = devm_request_and_ioremap(
return -EADDRNOTAVAIL;
}
+ }
+
+ if (control_usb->type == OMAP_CTRL_DEV_TYPE3) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "ctrl_core_srcomp_north_side");
+ control_usb->ctrl_core_srcomp_north_side =
+ devm_request_and_ioremap(&pdev->dev, res);
+ if (!control_usb->ctrl_core_srcomp_north_side) {
+ dev_err(&pdev->dev, "Failed to obtain io memory\n");
+ return -EADDRNOTAVAIL;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "dummy_reg");
+ control_usb->dummy_reg = devm_request_and_ioremap(&pdev->dev, res);
+ if (!control_usb->dummy_reg) {
+ dev_err(&pdev->dev, "Failed to obtain io memory\n");
+ dev_err(&pdev->dev, "#RK: DUMMY not found \n");
+ return -EADDRNOTAVAIL;
+ }
+
+ }
+
+ if ((control_usb->type == OMAP_CTRL_DEV_TYPE2) ||
+ (control_usb->type == OMAP_CTRL_DEV_TYPE3)) {
+
control_usb->sys_clk = devm_clk_get(control_usb->dev,
"sys_clkin");
if (IS_ERR(control_usb->sys_clk)) {
index 844ab68f08d04d6600594fb74fc56a3225b079b2..f3f5afd2058a35224b5582b200bfa27b26a2b842 100644 (file)
#include <linux/pm_runtime.h>
#include <linux/delay.h>
#include <linux/usb/omap_control_usb.h>
+#include <linux/of_platform.h>
/**
* omap_usb2_set_comparator - links the comparator present in the sytem with
{
struct omap_usb *phy;
struct usb_otg *otg;
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *omap_control_usb_node;
+ struct platform_device *pdev_control_usb;
+ const char *clk_name;
phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
if (!phy) {
phy->phy.set_suspend = omap_usb2_suspend;
phy->phy.otg = otg;
phy->phy.type = USB_PHY_TYPE_USB2;
+ omap_control_usb_node = of_parse_phandle(node, "ctrl-module", 0);
+
+ if (IS_ERR(omap_control_usb_node)) {
+ dev_err(&pdev->dev, "Failed to find ctrl-module\n");
+ return -EPROBE_DEFER;
+ }
+
+ pdev_control_usb = of_find_device_by_node(omap_control_usb_node);
+
+ if (IS_ERR(pdev_control_usb)) {
+ dev_dbg(&pdev->dev, "Attempt to get the platform control usb failed\n");
+ return -EPROBE_DEFER;
+ }
+ phy->control_dev = &pdev_control_usb->dev;
- phy->control_dev = omap_get_control_dev();
if (IS_ERR(phy->control_dev)) {
dev_dbg(&pdev->dev, "Failed to get control device\n");
return -ENODEV;
}
-
+ dev_dbg(&pdev->dev, "got control usb name %s\n",
+ dev_name(phy->control_dev));
+ phy->control_node = omap_control_usb_node;
phy->is_suspended = 1;
omap_control_usb_phy_power(phy->control_dev, 0);
otg->start_srp = omap_usb_start_srp;
otg->phy = &phy->phy;
- phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
- if (IS_ERR(phy->wkupclk)) {
- dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
- return PTR_ERR(phy->wkupclk);
+
+ of_property_read_string(node, "wkupclk", &clk_name);
+ if (!clk_name) {
+ dev_err(&pdev->dev, "unable to read wkupclk property from dt \n");
+ return -ENODEV;
+ } else {
+ phy->wkupclk = devm_clk_get(phy->dev, clk_name);
+ if (IS_ERR(phy->wkupclk)) {
+ dev_err(&pdev->dev, "unable to get usb_phy wk clk\n");
+ return PTR_ERR(phy->wkupclk);
+ }
}
+
clk_prepare(phy->wkupclk);
- phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
- if (IS_ERR(phy->optclk))
- dev_vdbg(&pdev->dev, "unable to get refclk960m\n");
- else
- clk_prepare(phy->optclk);
+ of_property_read_string(node, "optclk", &clk_name);
+ if (!clk_name)
+ dev_err(&pdev->dev, "unable to read optclk property from dt\n");
+ else {
+ phy->optclk = devm_clk_get(phy->dev, clk_name);
+ if (IS_ERR(phy->optclk)) {
+ dev_err(&pdev->dev, "unable to get usb_phy opt clk\n");
+ return PTR_ERR(phy->optclk);
+ }
+ else
+ clk_prepare(phy->optclk);
+ }
usb_add_phy_dev(&phy->phy);
struct omap_usb *phy = platform_get_drvdata(pdev);
clk_unprepare(phy->wkupclk);
+ of_node_put(phy->control_node);
if (!IS_ERR(phy->optclk))
clk_unprepare(phy->optclk);
usb_remove_phy(&phy->phy);
index fadc0c2b65bb7baf6b633c97cb187a16c4bd9d93..3b533a5dfa502e08e642474498a665e191f5f4b4 100644 (file)
#include <linux/pm_runtime.h>
#include <linux/delay.h>
#include <linux/usb/omap_control_usb.h>
+#include <linux/of_platform.h>
-#define NUM_SYS_CLKS 5
+#define NUM_SYS_CLKS 6
#define PLL_STATUS 0x00000004
#define PLL_GO 0x00000008
#define PLL_CONFIGURATION1 0x0000000C
CLK_RATE_12MHZ,
CLK_RATE_16MHZ,
CLK_RATE_19MHZ,
+ CLK_RATE_20MHZ,
CLK_RATE_26MHZ,
CLK_RATE_38MHZ
};
{1250, 5, 4, 20, 0}, /* 12 MHz */
{3125, 20, 4, 20, 0}, /* 16.8 MHz */
{1172, 8, 4, 20, 65537}, /* 19.2 MHz */
+ {1000, 7, 4, 10, 0}, /* 20 MHz */
{1250, 12, 4, 20, 0}, /* 26 MHz */
{3125, 47, 4, 20, 92843}, /* 38.4 MHz */
};
return CLK_RATE_16MHZ;
case 19200000:
return CLK_RATE_19MHZ;
+ case 20000000:
+ return CLK_RATE_20MHZ;
case 26000000:
return CLK_RATE_26MHZ;
case 38400000:
{
struct omap_usb *phy;
struct resource *res;
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *omap_control_usb_node;
+ struct platform_device *pdev_control_usb;
+ const char *clk_name;
phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
if (!phy) {
}
phy->dev = &pdev->dev;
-
phy->phy.dev = phy->dev;
phy->phy.label = "omap-usb3";
phy->phy.init = omap_usb3_init;
phy->phy.set_suspend = omap_usb3_suspend;
phy->phy.type = USB_PHY_TYPE_USB3;
-
phy->is_suspended = 1;
- phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
- if (IS_ERR(phy->wkupclk)) {
- dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
- return PTR_ERR(phy->wkupclk);
+
+ of_property_read_string(node, "wkupclk", &clk_name);
+ if (!clk_name) {
+ dev_err(&pdev->dev, "unable to read wkupclk property from dt \n");
+ return -EINVAL;
+ } else {
+ phy->wkupclk = devm_clk_get(phy->dev, clk_name);
+ if (IS_ERR(phy->wkupclk)) {
+ dev_err(&pdev->dev, "unable to get usb_phy wk clk\n");
+ return PTR_ERR(phy->wkupclk);
+ }
}
+
clk_prepare(phy->wkupclk);
- phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
- if (IS_ERR(phy->optclk)) {
- dev_err(&pdev->dev, "unable to get usb_otg_ss_refclk960m\n");
- return PTR_ERR(phy->optclk);
+ of_property_read_string(node, "optclk", &clk_name);
+ if (!clk_name)
+ dev_err(&pdev->dev, "unable to read optclk property from dt\n");
+ else {
+ phy->optclk = devm_clk_get(phy->dev, clk_name);
+ if (IS_ERR(phy->optclk)) {
+ dev_err(&pdev->dev, "unable to get usb_phy opt clk\n");
+ return PTR_ERR(phy->optclk);
+ }
+ else
+ clk_prepare(phy->optclk);
}
- clk_prepare(phy->optclk);
+
phy->sys_clk = devm_clk_get(phy->dev, "sys_clkin");
if (IS_ERR(phy->sys_clk)) {
return -EINVAL;
}
- phy->control_dev = omap_get_control_dev();
+ omap_control_usb_node = of_parse_phandle(node, "ctrl-module", 0);
+ if (IS_ERR(omap_control_usb_node)) {
+ dev_err(&pdev->dev, "Failed to find ctrl-module\n");
+ return -EPROBE_DEFER;
+ }
+
+ pdev_control_usb = of_find_device_by_node(omap_control_usb_node);
+ if (IS_ERR(pdev_control_usb)) {
+ dev_dbg(&pdev->dev, "Attempt to get the platform control usb failed\n");
+ return -EPROBE_DEFER;
+ }
+
+ phy->control_dev = &pdev_control_usb->dev;
if (IS_ERR(phy->control_dev)) {
dev_dbg(&pdev->dev, "Failed to get control device\n");
return -ENODEV;
}
+ dev_dbg(&pdev->dev, "got control usb name %s\n",
+ dev_name(phy->control_dev));
+ phy->control_node = omap_control_usb_node;
+
omap_control_usb3_phy_power(phy->control_dev, 0);
usb_add_phy_dev(&phy->phy);
clk_unprepare(phy->wkupclk);
clk_unprepare(phy->optclk);
+ of_node_put(phy->control_node);
usb_remove_phy(&phy->phy);
if (!pm_runtime_suspended(&pdev->dev))
pm_runtime_put(&pdev->dev);
index d29503e954abf829c71e69f08ec995da39291481..aa5fa26e1ec1725007e3e085e260c80f8fba18db 100644 (file)
--- a/drivers/usb/usb-common.c
+++ b/drivers/usb/usb-common.c
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/usb/ch9.h>
+#include <linux/usb/of.h>
const char *usb_speed_string(enum usb_device_speed speed)
{
}
EXPORT_SYMBOL_GPL(usb_speed_string);
+#ifdef CONFIG_OF
+static const char *const usb_dr_modes[] = {
+ [USB_DR_MODE_UNKNOWN] = "",
+ [USB_DR_MODE_HOST] = "host",
+ [USB_DR_MODE_PERIPHERAL] = "peripheral",
+ [USB_DR_MODE_OTG] = "otg",
+};
+
+/**
+ * of_usb_get_dr_mode - Get dual role mode for given device_node
+ * @np: Pointer to the given device_node
+ *
+ * The function gets phy interface string from property 'dr_mode',
+ * and returns the correspondig enum usb_dr_mode
+ */
+enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
+{
+ const char *dr_mode;
+ int err, i;
+
+ err = of_property_read_string(np, "dr_mode", &dr_mode);
+ if (err < 0)
+ return USB_DR_MODE_UNKNOWN;
+
+ for (i = 0; i < ARRAY_SIZE(usb_dr_modes); i++)
+ if (!strcmp(dr_mode, usb_dr_modes[i]))
+ return i;
+
+ return USB_DR_MODE_UNKNOWN;
+}
+EXPORT_SYMBOL_GPL(of_usb_get_dr_mode);
+
+static const char *const usb_maximum_speed[] = {
+ [USB_SPEED_UNKNOWN] = "",
+ [USB_SPEED_LOW] = "lowspeed",
+ [USB_SPEED_FULL] = "fullspeed",
+ [USB_SPEED_HIGH] = "highspeed",
+ [USB_SPEED_WIRELESS] = "wireless",
+ [USB_SPEED_SUPER] = "superspeed",
+};
+
+/**
+ * of_usb_get_maximum_speed - Get maximum requested speed for a given USB
+ * controller.
+ * @np: Pointer to the given device_node
+ *
+ * The function gets the maximum speed string from property "maximum-speed",
+ * and returns the corresponding enum usb_device_speed.
+ */
+enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np)
+{
+ const char *maximum_speed;
+ int err;
+ int i;
+
+ err = of_property_read_string(np, "maximum-speed", &maximum_speed);
+ if (err < 0)
+ return USB_SPEED_UNKNOWN;
+
+ for (i = 0; i < ARRAY_SIZE(usb_maximum_speed); i++)
+ if (strcmp(maximum_speed, usb_maximum_speed[i]) == 0)
+ return i;
+
+ return USB_SPEED_UNKNOWN;
+}
+EXPORT_SYMBOL_GPL(of_usb_get_maximum_speed);
+
+#endif
+
MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index cef65574db6c09bd906d3ab2eac8c235f208dedf..f1ca1598a3bf8bee602c19a7873deea6336dcb9f 100644 (file)
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
static void get_detailed_timing(unsigned char *block,
struct fb_videomode *mode)
{
+ int v_size = V_SIZE;
+ int h_size = H_SIZE;
+
mode->xres = H_ACTIVE;
mode->yres = V_ACTIVE;
mode->pixclock = PIXEL_CLOCK;
}
mode->flag = FB_MODE_IS_DETAILED;
+ /* get aspect ratio to set flags for timings which do not have
+ aspect ration like VESA*/
+ if (h_size * 18 > v_size * 31 && h_size * 18 < v_size * 33)
+ mode->flag |= FB_FLAG_RATIO_16_9;
+ if (h_size * 18 > v_size * 23 && h_size * 18 < v_size * 25)
+ mode->flag |= FB_FLAG_RATIO_4_3;
+
DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000);
DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
+ DPRINTK("%dmm %dmm ", H_SIZE, V_SIZE);
DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
(VSYNC_POSITIVE) ? "+" : "-");
}
/**
* fb_edid_add_monspecs() - add monitor video modes from E-EDID data
* @edid: 128 byte array with an E-EDID block
- * @spacs: monitor specs to be extended
+ * @specs: monitor specs to be extended
*/
void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
{
while (pos < edid[2]) {
u8 len = edid[pos] & 0x1f, type = (edid[pos] >> 5) & 7;
pr_debug("Data block %u of %u bytes\n", type, len);
- if (type == 2)
+
+ pos++;
+ if (type == 2) {
for (i = pos; i < pos + len; i++) {
- u8 idx = edid[pos + i] & 0x7f;
+ u8 idx = edid[i] & 0x7f;
svd[svd_n++] = idx;
pr_debug("N%sative mode #%d\n",
- edid[pos + i] & 0x80 ? "" : "on-n", idx);
+ edid[i] & 0x80 ? "" : "on-n", idx);
}
- pos += len + 1;
+ } else if (type == 3 && len >= 3) {
+ u32 ieee_reg = edid[pos] | (edid[pos + 1] << 8) |
+ (edid[pos + 2] << 16);
+ if (ieee_reg == 0x000c03)
+ specs->misc |= FB_MISC_HDMI;
+ }
+
+ pos += len;
}
block = edid + edid[2];
for (i = specs->modedb_len + num; i < specs->modedb_len + num + svd_n; i++) {
int idx = svd[i - specs->modedb_len - num];
- if (!idx || idx > 63) {
+ if (!idx || idx > (CEA_MODEDB_SIZE - 1)) {
pr_warning("Reserved SVD code %d\n", idx);
- } else if (idx > ARRAY_SIZE(cea_modes) || !cea_modes[idx].xres) {
+ } else if (!cea_modes[idx].xres) {
pr_warning("Unimplemented SVD code %d\n", idx);
} else {
memcpy(&m[i], cea_modes + idx, sizeof(m[i]));
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index a9a907c440d73ee89f2acc8fd20d7aa905230b43..86431ef493725c364cb08afffdd1d8f7ef8c58ad 100644 (file)
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
};
#ifdef CONFIG_FB_MODE_HELPERS
-const struct fb_videomode cea_modes[64] = {
- /* #1: 640x480p@59.94/60Hz */
- [1] = {
- NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
- FB_VMODE_NONINTERLACED, 0,
- },
- /* #3: 720x480p@59.94/60Hz */
- [3] = {
- NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
- FB_VMODE_NONINTERLACED, 0,
- },
- /* #5: 1920x1080i@59.94/60Hz */
- [5] = {
- NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
- FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_INTERLACED, 0,
- },
- /* #7: 720(1440)x480iH@59.94/60Hz */
- [7] = {
- NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
- FB_VMODE_INTERLACED, 0,
- },
- /* #9: 720(1440)x240pH@59.94/60Hz */
- [9] = {
- NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0,
- FB_VMODE_NONINTERLACED, 0,
- },
- /* #18: 720x576pH@50Hz */
- [18] = {
- NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
- FB_VMODE_NONINTERLACED, 0,
- },
- /* #19: 1280x720p@50Hz */
- [19] = {
- NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
- FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED, 0,
- },
- /* #20: 1920x1080i@50Hz */
- [20] = {
- NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
- FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_INTERLACED, 0,
- },
- /* #32: 1920x1080p@23.98/24Hz */
- [32] = {
- NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
- FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED, 0,
- },
- /* #35: (2880)x480p4x@59.94/60Hz */
- [35] = {
- NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0,
- FB_VMODE_NONINTERLACED, 0,
- },
+const struct fb_videomode cea_modes[CEA_MODEDB_SIZE] = {
+ {},
+ /* 1: 640x480p @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 640, .yres = 480, .pixclock = 39721,
+ .left_margin = 48, .right_margin = 16,
+ .upper_margin = 33, .lower_margin = 10,
+ .hsync_len = 96, .vsync_len = 2,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 2: 720x480p @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 720, .yres = 480, .pixclock = 37037,
+ .left_margin = 60, .right_margin = 16,
+ .upper_margin = 30, .lower_margin = 9,
+ .hsync_len = 62, .vsync_len = 6,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 3: 720x480p @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 720, .yres = 480, .pixclock = 37037,
+ .left_margin = 60, .right_margin = 16,
+ .upper_margin = 30, .lower_margin = 9,
+ .hsync_len = 62, .vsync_len = 6,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 4: 1280x720p @ 59.94Hz/60Hz */
+ {.refresh = 60, .xres = 1280, .yres = 720, .pixclock = 13468,
+ .left_margin = 220, .right_margin = 110,
+ .upper_margin = 20, .lower_margin = 5,
+ .hsync_len = 40, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 5: 1920x1080i @ 59.94Hz/60Hz */
+ {.refresh = 60, .xres = 1920, .yres = 1080, .pixclock = 13468,
+ .left_margin = 148, .right_margin = 88,
+ .upper_margin = 15, .lower_margin = 2,
+ .hsync_len = 44, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 6: 720(1440)x480i @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 1440, .yres = 480, .pixclock = 37037,
+ .left_margin = 114, .right_margin = 38,
+ .upper_margin = 15, .lower_margin = 4,
+ .hsync_len = 124, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 7: 720(1440)x480i @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 1440, .yres = 480, .pixclock = 37037,
+ .left_margin = 114, .right_margin = 38,
+ .upper_margin = 15, .lower_margin = 4,
+ .hsync_len = 124, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 8: 720(1440)x240p @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 1440, .yres = 240, .pixclock = 37037,
+ .left_margin = 114, .right_margin = 38,
+ .upper_margin = 15, .lower_margin = 5,
+ .hsync_len = 124, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 9: 720(1440)x240p @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 1440, .yres = 240, .pixclock = 37037,
+ .left_margin = 114, .right_margin = 38,
+ .upper_margin = 15, .lower_margin = 5,
+ .hsync_len = 124, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 10: 2880x480i @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 2880, .yres = 480, .pixclock = 18518,
+ .left_margin = 228, .right_margin = 76,
+ .upper_margin = 15, .lower_margin = 4,
+ .hsync_len = 248, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 11: 2880x480i @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 2880, .yres = 480, .pixclock = 18518,
+ .left_margin = 228, .right_margin = 76,
+ .upper_margin = 15, .lower_margin = 4,
+ .hsync_len = 248, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 12: 2880x240p @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 2880, .yres = 240, .pixclock = 18518,
+ .left_margin = 228, .right_margin = 76,
+ .upper_margin = 15, .lower_margin = 5,
+ .hsync_len = 248, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 13: 2880x240p @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 2880, .yres = 240, .pixclock = 18518,
+ .left_margin = 228, .right_margin = 76,
+ .upper_margin = 15, .lower_margin = 5,
+ .hsync_len = 248, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 14: 1440x480p @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 1440, .yres = 480, .pixclock = 18518,
+ .left_margin = 120, .right_margin = 32,
+ .upper_margin = 30, .lower_margin = 9,
+ .hsync_len = 124, .vsync_len = 6,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 15: 1440x480p @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 1440, .yres = 480, .pixclock = 18518,
+ .left_margin = 120, .right_margin = 32,
+ .upper_margin = 30, .lower_margin = 9,
+ .hsync_len = 124, .vsync_len = 6,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 16: 1920x1080p @ 59.94Hz/60Hz */
+ {.refresh = 60, .xres = 1920, .yres = 1080, .pixclock = 6734,
+ .left_margin = 148, .right_margin = 88,
+ .upper_margin = 36, .lower_margin = 4,
+ .hsync_len = 44, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 17: 720x576p @ 50Hz */
+ {.refresh = 50, .xres = 720, .yres = 576, .pixclock = 37037,
+ .left_margin = 68, .right_margin = 12,
+ .upper_margin = 39, .lower_margin = 5,
+ .hsync_len = 64, .vsync_len = 5,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 18: 720x576p @ 50Hz */
+ {.refresh = 50, .xres = 720, .yres = 576, .pixclock = 37037,
+ .left_margin = 68, .right_margin = 12,
+ .upper_margin = 39, .lower_margin = 5,
+ .hsync_len = 64, .vsync_len = 5,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 19: 1280x720p @ 50Hz */
+ {.refresh = 50, .xres = 1280, .yres = 720, .pixclock = 13468,
+ .left_margin = 220, .right_margin = 440,
+ .upper_margin = 20, .lower_margin = 5,
+ .hsync_len = 40, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 20: 1920x1080i @ 50Hz */
+ {.refresh = 50, .xres = 1920, .yres = 1080, .pixclock = 13468,
+ .left_margin = 148, .right_margin = 528,
+ .upper_margin = 15, .lower_margin = 2,
+ .hsync_len = 44, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 21: 720(1440)x576i @ 50Hz */
+ {.refresh = 50, .xres = 1440, .yres = 576, .pixclock = 37037,
+ .left_margin = 138, .right_margin = 24,
+ .upper_margin = 19, .lower_margin = 2,
+ .hsync_len = 126, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 22: 720(1440)x576i @ 50Hz */
+ {.refresh = 50, .xres = 1440, .yres = 576, .pixclock = 37037,
+ .left_margin = 138, .right_margin = 24,
+ .upper_margin = 19, .lower_margin = 2,
+ .hsync_len = 126, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 23: 720(1440)x288p @ 50Hz */
+ {.refresh = 49, .xres = 1440, .yres = 288, .pixclock = 37037,
+ .left_margin = 138, .right_margin = 24,
+ .upper_margin = 19, .lower_margin = 4,
+ .hsync_len = 126, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 24: 720(1440)x288p @ 50Hz */
+ {.refresh = 49, .xres = 1440, .yres = 288, .pixclock = 37037,
+ .left_margin = 138, .right_margin = 24,
+ .upper_margin = 19, .lower_margin = 4,
+ .hsync_len = 126, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 25: 2880x576i @ 50Hz */
+ {.refresh = 50, .xres = 2880, .yres = 576, .pixclock = 18518,
+ .left_margin = 276, .right_margin = 48,
+ .upper_margin = 19, .lower_margin = 2,
+ .hsync_len = 252, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 26: 2880x576i @ 50Hz */
+ {.refresh = 50, .xres = 2880, .yres = 576, .pixclock = 18518,
+ .left_margin = 276, .right_margin = 48,
+ .upper_margin = 19, .lower_margin = 2,
+ .hsync_len = 252, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 27: 2880x288p @ 50Hz */
+ {.refresh = 49, .xres = 2880, .yres = 288, .pixclock = 18518,
+ .left_margin = 276, .right_margin = 48,
+ .upper_margin = 19, .lower_margin = 4,
+ .hsync_len = 252, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 28: 2880x288p @ 50Hz */
+ {.refresh = 49, .xres = 2880, .yres = 288, .pixclock = 18518,
+ .left_margin = 276, .right_margin = 48,
+ .upper_margin = 19, .lower_margin = 4,
+ .hsync_len = 252, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 29: 1440x576p @ 50Hz */
+ {.refresh = 50, .xres = 1440, .yres = 576, .pixclock = 18518,
+ .left_margin = 136, .right_margin = 24,
+ .upper_margin = 39, .lower_margin = 5,
+ .hsync_len = 128, .vsync_len = 5,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 30: 1440x576p @ 50Hz */
+ {.refresh = 50, .xres = 1440, .yres = 576, .pixclock = 18518,
+ .left_margin = 136, .right_margin = 24,
+ .upper_margin = 39, .lower_margin = 5,
+ .hsync_len = 128, .vsync_len = 5,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 31: 1920x1080p @ 50Hz */
+ {.refresh = 50, .xres = 1920, .yres = 1080, .pixclock = 6734,
+ .left_margin = 148, .right_margin = 528,
+ .upper_margin = 36, .lower_margin = 4,
+ .hsync_len = 44, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 32: 1920x1080p @ 23.97Hz/24Hz */
+ {.refresh = 24, .xres = 1920, .yres = 1080, .pixclock = 13468,
+ .left_margin = 148, .right_margin = 638,
+ .upper_margin = 36, .lower_margin = 4,
+ .hsync_len = 44, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 33: 1920x1080p @ 25Hz */
+ {.refresh = 25, .xres = 1920, .yres = 1080, .pixclock = 13468,
+ .left_margin = 148, .right_margin = 528,
+ .upper_margin = 36, .lower_margin = 4,
+ .hsync_len = 44, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 34: 1920x1080p @ 29.97Hz/30Hz */
+ {.refresh = 30, .xres = 1920, .yres = 1080, .pixclock = 13468,
+ .left_margin = 148, .right_margin = 88,
+ .upper_margin = 36, .lower_margin = 4,
+ .hsync_len = 44, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 35: 2880x480p @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 2880, .yres = 480, .pixclock = 9259,
+ .left_margin = 240, .right_margin = 64,
+ .upper_margin = 30, .lower_margin = 9,
+ .hsync_len = 248, .vsync_len = 6,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 36: 2880x480p @ 59.94Hz/60Hz */
+ {.refresh = 59, .xres = 2880, .yres = 480, .pixclock = 9259,
+ .left_margin = 240, .right_margin = 64,
+ .upper_margin = 30, .lower_margin = 9,
+ .hsync_len = 248, .vsync_len = 6,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 37: 2880x576p @ 50Hz */
+ {.refresh = 50, .xres = 2880, .yres = 576, .pixclock = 9259,
+ .left_margin = 272, .right_margin = 48,
+ .upper_margin = 39, .lower_margin = 5,
+ .hsync_len = 256, .vsync_len = 5,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 38: 2880x576p @ 50Hz */
+ {.refresh = 50, .xres = 2880, .yres = 576, .pixclock = 9259,
+ .left_margin = 272, .right_margin = 48,
+ .upper_margin = 39, .lower_margin = 5,
+ .hsync_len = 256, .vsync_len = 5,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 39: 1920x1080i @ 50Hz */
+ {.refresh = 50, .xres = 1920, .yres = 1080, .pixclock = 13888,
+ .left_margin = 184, .right_margin = 32,
+ .upper_margin = 57, .lower_margin = 23,
+ .hsync_len = 168, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 40: 1920x1080i @ 100Hz */
+ {.refresh = 100, .xres = 1920, .yres = 1080, .pixclock = 6734,
+ .left_margin = 148, .right_margin = 528,
+ .upper_margin = 15, .lower_margin = 2,
+ .hsync_len = 44, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 41: 1280x720p @ 100Hz */
+ {.refresh = 100, .xres = 1280, .yres = 720, .pixclock = 6734,
+ .left_margin = 220, .right_margin = 440,
+ .upper_margin = 20, .lower_margin = 5,
+ .hsync_len = 40, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 42: 720x576p @ 100Hz */
+ {.refresh = 100, .xres = 720, .yres = 576, .pixclock = 18518,
+ .left_margin = 68, .right_margin = 12,
+ .upper_margin = 39, .lower_margin = 5,
+ .hsync_len = 64, .vsync_len = 5,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 43: 720x576p @ 100Hz */
+ {.refresh = 100, .xres = 720, .yres = 576, .pixclock = 18518,
+ .left_margin = 68, .right_margin = 12,
+ .upper_margin = 39, .lower_margin = 5,
+ .hsync_len = 64, .vsync_len = 5,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 44: 720(1440)x576i @ 100Hz */
+ {.refresh = 100, .xres = 1440, .yres = 576, .pixclock = 18518,
+ .left_margin = 138, .right_margin = 24,
+ .upper_margin = 19, .lower_margin = 2,
+ .hsync_len = 126, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 45: 720(1440)x576i @ 100Hz */
+ {.refresh = 100, .xres = 1440, .yres = 576, .pixclock = 18518,
+ .left_margin = 138, .right_margin = 24,
+ .upper_margin = 19, .lower_margin = 2,
+ .hsync_len = 126, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 46: 1920x1080i @ 119.88/120Hz */
+ {.refresh = 120, .xres = 1920, .yres = 1080, .pixclock = 6734,
+ .left_margin = 148, .right_margin = 88,
+ .upper_margin = 15, .lower_margin = 2,
+ .hsync_len = 44, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 47: 1280x720p @ 119.88/120Hz */
+ {.refresh = 120, .xres = 1280, .yres = 720, .pixclock = 6734,
+ .left_margin = 220, .right_margin = 110,
+ .upper_margin = 20, .lower_margin = 5,
+ .hsync_len = 40, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 48: 720x480p @ 119.88/120Hz */
+ {.refresh = 119, .xres = 720, .yres = 480, .pixclock = 18518,
+ .left_margin = 60, .right_margin = 16,
+ .upper_margin = 30, .lower_margin = 9,
+ .hsync_len = 62, .vsync_len = 6,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 49: 720x480p @ 119.88/120Hz */
+ {.refresh = 119, .xres = 720, .yres = 480, .pixclock = 18518,
+ .left_margin = 60, .right_margin = 16,
+ .upper_margin = 30, .lower_margin = 9,
+ .hsync_len = 62, .vsync_len = 6,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 50: 720(1440)x480i @ 119.88/120Hz */
+ {.refresh = 119, .xres = 1440, .yres = 480, .pixclock = 18518,
+ .left_margin = 114, .right_margin = 38,
+ .upper_margin = 15, .lower_margin = 4,
+ .hsync_len = 124, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 51: 720(1440)x480i @ 119.88/120Hz */
+ {.refresh = 119, .xres = 1440, .yres = 480, .pixclock = 18518,
+ .left_margin = 114, .right_margin = 38,
+ .upper_margin = 15, .lower_margin = 4,
+ .hsync_len = 124, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 52: 720x576p @ 200Hz */
+ {.refresh = 200, .xres = 720, .yres = 576, .pixclock = 9259,
+ .left_margin = 68, .right_margin = 12,
+ .upper_margin = 39, .lower_margin = 5,
+ .hsync_len = 64, .vsync_len = 5,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 53: 720x576p @ 200Hz */
+ {.refresh = 200, .xres = 720, .yres = 576, .pixclock = 9259,
+ .left_margin = 68, .right_margin = 12,
+ .upper_margin = 39, .lower_margin = 5,
+ .hsync_len = 64, .vsync_len = 5,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 54: 720(1440)x576i @ 200Hz */
+ {.refresh = 200, .xres = 1440, .yres = 576, .pixclock = 9259,
+ .left_margin = 138, .right_margin = 24,
+ .upper_margin = 19, .lower_margin = 2,
+ .hsync_len = 126, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 55: 720(1440)x576i @ 200Hz */
+ {.refresh = 200, .xres = 1440, .yres = 576, .pixclock = 9259,
+ .left_margin = 138, .right_margin = 24,
+ .upper_margin = 19, .lower_margin = 2,
+ .hsync_len = 126, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 56: 720x480p @ 239.76/240Hz */
+ {.refresh = 239, .xres = 720, .yres = 480, .pixclock = 9259,
+ .left_margin = 60, .right_margin = 16,
+ .upper_margin = 30, .lower_margin = 9,
+ .hsync_len = 62, .vsync_len = 6,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 57: 720x480p @ 239.76/240Hz */
+ {.refresh = 239, .xres = 720, .yres = 480, .pixclock = 9259,
+ .left_margin = 60, .right_margin = 16,
+ .upper_margin = 30, .lower_margin = 9,
+ .hsync_len = 62, .vsync_len = 6,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 58: 720(1440)x480i @ 239.76/240Hz */
+ {.refresh = 239, .xres = 1440, .yres = 480, .pixclock = 9259,
+ .left_margin = 114, .right_margin = 38,
+ .upper_margin = 15, .lower_margin = 4,
+ .hsync_len = 124, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_4_3 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 59: 720(1440)x480i @ 239.76/240Hz */
+ {.refresh = 239, .xres = 1440, .yres = 480, .pixclock = 9259,
+ .left_margin = 114, .right_margin = 38,
+ .upper_margin = 15, .lower_margin = 4,
+ .hsync_len = 124, .vsync_len = 3,
+ .sync = 0,
+ .flag = FB_FLAG_RATIO_16_9 | FB_FLAG_PIXEL_REPEAT,
+ .vmode = FB_VMODE_INTERLACED},
+ /* 60: 1280x720p @ 23.97Hz/24Hz */
+ {.refresh = 24, .xres = 1280, .yres = 720, .pixclock = 16835,
+ .left_margin = 220, .right_margin = 1760,
+ .upper_margin = 20, .lower_margin = 5,
+ .hsync_len = 40, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 61: 1280x720p @ 25Hz */
+ {.refresh = 25, .xres = 1280, .yres = 720, .pixclock = 13468,
+ .left_margin = 220, .right_margin = 2420,
+ .upper_margin = 20, .lower_margin = 5,
+ .hsync_len = 40, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 62: 1280x720p @ 29.97Hz/30Hz */
+ {.refresh = 30, .xres = 1280, .yres = 720, .pixclock = 13468,
+ .left_margin = 220, .right_margin = 1760,
+ .upper_margin = 20, .lower_margin = 5,
+ .hsync_len = 40, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 63: 1920x1080p @ 119.88/120Hz */
+ {.refresh = 120, .xres = 1920, .yres = 1080, .pixclock = 3367,
+ .left_margin = 148, .right_margin = 88,
+ .upper_margin = 36, .lower_margin = 4,
+ .hsync_len = 44, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
+ /* 64: 1920x1080p @ 100Hz */
+ {.refresh = 100, .xres = 1920, .yres = 1080, .pixclock = 3367,
+ .left_margin = 148, .right_margin = 528,
+ .upper_margin = 36, .lower_margin = 4,
+ .hsync_len = 44, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED},
};
+EXPORT_SYMBOL(cea_modes);
-const struct fb_videomode vesa_modes[] = {
+const struct fb_videomode vesa_modes[VESA_MODEDB_SIZE] = {
/* 0 640x350-85 VESA */
{ NULL, 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3,
FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
index b07b2b042e7e242e6ff515ef0348912106f8cccb..eb93cbbac87e7d6b03617f3e8507cea04ce39729 100644 (file)
source "drivers/video/omap2/dss/Kconfig"
source "drivers/video/omap2/omapfb/Kconfig"
source "drivers/video/omap2/displays/Kconfig"
+source "drivers/video/omap2/dsscomp/Kconfig"
+source "drivers/video/omap2/omaplfb/Kconfig"
endif
index 5ea7cb9aed17b9d666bfdba808b889d745fa8ffb..e4e76ea1aca598ce7bca01ab3640540815ab95fd 100644 (file)
obj-$(CONFIG_OMAP2_DSS) += dss/
obj-$(CONFIG_FB_OMAP2) += omapfb/
obj-y += displays/
+obj-y += dsscomp/
+obj-$(CONFIG_OMAPLFB) += omaplfb/
config OMAP4_DSS_HDMI
bool "OMAP4 HDMI support"
+ depends on ARCH_OMAP4 || ANDROID_SWITCH
+ select FB
+ select FB_MODE_HELPERS
+ select FB_OMAP2
default y
select I2C_ALGOBIT
help
select GPIO_PCA953X
select MFD_PALMAS
select REGULATOR_PALMAS
+ select FB
+ select FB_MODE_HELPERS
+ select FB_OMAP2
help
HDMI Interface.This add the High Deinition Multimedia Interface.
See http://wwww.hdmi.org/ for HDMI specification.
This option enables the sleep, and is enabled by default. You can
disable the sleep if it doesn't cause problems on your platform.
+config USE_FB_MODE_DB
+ bool "Enable FB mode db support"
+ default y
+ help
+ Enable FB mode support.
+
endif
index 0aa8ad8f96679db07b11c6221f7a3eff9f150ffe..cb34f5700bec8a79dd36a3f46c2191b7331eca02 100644 (file)
}
EXPORT_SYMBOL(omapdss_default_get_resolution);
+void omapdss_display_get_dimensions(struct omap_dss_device *dssdev,
+ u32 *width_in_um, u32 *height_in_um)
+{
+ if (dssdev->driver->get_dimensions) {
+ dssdev->driver->get_dimensions(dssdev,
+ width_in_um, width_in_um);
+ } else {
+ *width_in_um = dssdev->panel.width_in_um;
+ *height_in_um = dssdev->panel.height_in_um;
+ }
+}
+
int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
{
switch (dssdev->type) {
#undef DUMPREG
}
-static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
+void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
{
struct platform_device *dsidev;
int b;
int dss_sdi_enable(void);
void dss_sdi_disable(void);
+void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src);
void dss_select_dsi_clk_source(int dsi_module,
enum omap_dss_clk_source clk_src);
void dss_select_lcd_clk_source(enum omap_channel channel,
struct s3d_disp_info *info, int code);
void sel_i2c(void);
void sel_hdmi(void);
+int omapdss_hdmi_display_set_mode(struct omap_dss_device *dssdev,
+ struct fb_videomode *mode);
+u8 *hdmi_read_valid_edid(void);
+void omapdss_hdmi_clear_edid(void);
+ssize_t omapdss_get_edid(char *buf);
+void hdmi_get_monspecs(struct omap_dss_device *dssdev);
int hdmi_panel_init(void);
void hdmi_panel_exit(void);
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || \
#include <linux/slab.h>
#include <linux/of_gpio.h>
#include <linux/of_i2c.h>
+#include <linux/fb.h>
+#include <linux/omapfb.h>
#include <video/omapdss.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include "dss_features.h"
/* HDMI EDID Length move this */
-#define HDMI_EDID_MAX_LENGTH 256
+#define HDMI_EDID_MAX_LENGTH 512
#define EDID_TIMING_DESCRIPTOR_SIZE 0x12
#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
+#define EDID_HDMI_VENDOR_SPECIFIC_DATA_BLOCK 128
#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
struct platform_device *audio_pdev;
#endif
+ int code;
+ int mode;
+ u8 edid[HDMI_EDID_MAX_LENGTH];
+ bool edid_set;
+ bool custom_set;
+ bool can_do_hdmi;
+ bool force_timings;
+ int source_physical_address;
struct hdmi_ip_data ip_data;
int hdmi_irq;
struct omap_dss_output output;
} hdmi;
+static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0};
+
/*
* Logic for the below structure :
* user enters the CEA or VESA timings by specifying the HDMI/DVI code.
sel_hdmi();
}
+static int relaxed_fb_mode_is_equal(const struct fb_videomode *mode1,
+ const struct fb_videomode *mode2)
+{
+ u32 ratio1 = mode1->flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9);
+ u32 ratio2 = mode2->flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9);
+ return (mode1->xres == mode2->xres &&
+ mode1->yres == mode2->yres &&
+ mode1->pixclock <= mode2->pixclock * 201 / 200 &&
+ mode1->pixclock >= mode2->pixclock * 200 / 201 &&
+ mode1->hsync_len + mode1->left_margin + mode1->right_margin ==
+ mode2->hsync_len + mode2->left_margin + mode2->right_margin &&
+ mode1->vsync_len + mode1->upper_margin + mode1->lower_margin ==
+ mode2->vsync_len + mode2->upper_margin + mode2->lower_margin &&
+ (!ratio1 || !ratio2 || ratio1 == ratio2) &&
+ (mode1->vmode & FB_VMODE_INTERLACED) ==
+ (mode2->vmode & FB_VMODE_INTERLACED));
+
+}
+
+static int hdmi_set_timings(struct fb_videomode *vm, bool check_only)
+{
+ int i = 0;
+ int r = 0;
+ DSSDBG("hdmi_set_timings\n");
+
+ if (!vm->xres || !vm->yres || !vm->pixclock)
+ goto fail;
+
+ for (i = 0; i < CEA_MODEDB_SIZE; i++) {
+ if (relaxed_fb_mode_is_equal(cea_modes + i, vm)) {
+ *vm = cea_modes[i];
+ if (check_only)
+ return 1;
+ hdmi.ip_data.cfg.cm.code = i;
+ hdmi.ip_data.cfg.cm.mode = HDMI_HDMI;
+ hdmi.ip_data.cfg.timingsfb =
+ cea_modes[hdmi.ip_data.cfg.cm.code];
+ goto done;
+ }
+ }
+ for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+ if (relaxed_fb_mode_is_equal(vesa_modes + i, vm)) {
+ *vm = vesa_modes[i];
+ if (check_only)
+ return 1;
+ hdmi.ip_data.cfg.cm.code = i;
+ hdmi.ip_data.cfg.cm.mode = HDMI_DVI;
+ hdmi.ip_data.cfg.timingsfb =
+ vesa_modes[hdmi.ip_data.cfg.cm.code];
+ goto done;
+ }
+ }
+fail:
+ if (check_only)
+ return 0;
+ hdmi.ip_data.cfg.cm.code = 1;
+ hdmi.ip_data.cfg.cm.mode = HDMI_HDMI;
+ hdmi.ip_data.cfg.timingsfb = cea_modes[hdmi.ip_data.cfg.cm.code];
+ i = -1;
+done:
+ DSSDBG("%s-%d\n", hdmi.ip_data.cfg.cm.mode ? "CEA" : "VESA",
+ hdmi.ip_data.cfg.cm.code);
+
+ /* convert fb timing to dss timings to be in sync. */
+ omapfb_fb2dss_timings(&hdmi.ip_data.cfg.timingsfb,&hdmi.ip_data.cfg.timings);
+
+ r = i >= 0 ? 1 : 0;
+ return r;
+
+}
+
+void hdmi_get_monspecs(struct omap_dss_device *dssdev)
+{
+ int i, j;
+ char *edid = (char *)hdmi.edid;
+ struct fb_monspecs *specs = &dssdev->panel.monspecs;
+ u32 fclk = dispc_fclk_rate() / 1000;
+ u32 max_pclk = dssdev->clocks.hdmi.max_pixclk_khz;
+
+ if (max_pclk && max_pclk < fclk)
+ fclk = max_pclk;
+
+ memset(specs, 0x0, sizeof(*specs));
+ if (!hdmi.edid_set)
+ return;
+ fb_edid_to_monspecs(edid, specs);
+ if (specs->modedb == NULL)
+ return;
+
+ for (i = 1; i <= edid[0x7e] && i * 128 < HDMI_EDID_MAX_LENGTH; i++) {
+ if (edid[i * 128] == 0x2)
+ fb_edid_add_monspecs(edid + i * 128, specs);
+ }
+ if (hdmi.force_timings) {
+ for (i = 0; i < specs->modedb_len; i++) {
+ specs->modedb[i++] = hdmi.ip_data.cfg.timingsfb;
+ break;
+ }
+ specs->modedb_len = i;
+ hdmi.force_timings = false;
+ return;
+ }
+
+ hdmi.can_do_hdmi = specs->misc & FB_MISC_HDMI;
+
+ /* filter out resolutions we don't support */
+ for (i = j = 0; i < specs->modedb_len; i++) {
+ if (!hdmi_set_timings(&specs->modedb[i], true))
+ continue;
+ if (fclk < PICOS2KHZ(specs->modedb[i].pixclock))
+ continue;
+ if (specs->modedb[i].flag & FB_FLAG_PIXEL_REPEAT)
+ continue;
+ specs->modedb[j++] = specs->modedb[i];
+ }
+ specs->modedb_len = j;
+
+}
+
static int hdmi_runtime_get(void)
{
int r;
}
+u8 *hdmi_read_valid_edid(void)
+{
+ int ret, i;
+
+ if (hdmi.edid_set)
+ return hdmi.edid;
+
+ memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH);
+
+ hdmi_runtime_get();
+
+ ret = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, hdmi.edid,
+ HDMI_EDID_MAX_LENGTH);
+
+ hdmi_runtime_put();
+
+ for (i = 0; i < HDMI_EDID_MAX_LENGTH; i += 16)
+ DSSDBG("edid[%03x] = %02x %02x %02x %02x %02x %02x %02x %02x "\
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n", i,
+ hdmi.edid[i], hdmi.edid[i + 1], hdmi.edid[i + 2],
+ hdmi.edid[i + 3], hdmi.edid[i + 4], hdmi.edid[i + 5],
+ hdmi.edid[i + 6], hdmi.edid[i + 7], hdmi.edid[i + 8],
+ hdmi.edid[i + 9], hdmi.edid[i + 10], hdmi.edid[i + 11],
+ hdmi.edid[i + 12], hdmi.edid[i + 13], hdmi.edid[i + 14],
+ hdmi.edid[i + 15]);
+
+ if (ret) {
+ DSSWARN("failed to read E-EDID\n");
+ return NULL;
+ }
+ if (memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
+ DSSWARN("failed to read E-EDID: wrong header\n");
+ return NULL;
+ }
+ hdmi.edid_set = true;
+
+ return hdmi.edid;
+}
+
unsigned long hdmi_get_pixel_clock(void)
{
/* HDMI Pixel Clock in Mhz */
p = &hdmi.ip_data.cfg.timings;
DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
+#ifdef CONFIG_USE_FB_MODE_DB
+ if (!hdmi.custom_set) {
+ struct fb_videomode fb_mode = vesa_modes[4];
+ if ((hdmi.ip_data.cfg.cm.code != 4) &&
+ (hdmi.ip_data.cfg.cm.mode != HDMI_DVI)) {
+ if (hdmi.ip_data.cfg.cm.mode == HDMI_DVI)
+ fb_mode = vesa_modes[hdmi.ip_data.cfg.cm.code];
+ else
+ fb_mode = cea_modes[hdmi.ip_data.cfg.cm.code];
+ }
+ if (!hdmi_set_timings(&fb_mode, false)) {
+ /* Fallback in case we cannot set the timings */
+ DSSERR("fallback to vesa default code");
+ fb_mode = vesa_modes[4];
+ hdmi_set_timings(&fb_mode, false);
+ }
+ }
+ /* Update the panel timing in dssdev */
+ omapfb_fb2dss_timings(&hdmi.ip_data.cfg.timingsfb,
+ &dssdev->panel.timings);
+#endif
switch (hdmi.ip_data.cfg.deep_color) {
case HDMI_DEEP_COLOR_30BIT:
phy = (p->pixel_clock * 125) / 100 ;
goto err_phy_enable;
}
+ hdmi.ip_data.cfg.cm.mode = hdmi.can_do_hdmi ? hdmi.mode : HDMI_DVI;
+
hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
+ /* Make selection of HDMI in DSS */
+ dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
+
+ /* Select the dispc clock source as PRCM clock, to ensure that it is not
+ * DSI PLL source as the clock selected by DSI PLL might not be
+ * sufficient for the resolution selected / that can be changed
+ * dynamically by user. This can be moved to single location , say
+ * Boardfile.
+ */
+ dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
+
/* bypass TV gamma table */
dispc_enable_gamma_table(0);
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
+#ifdef CONFIG_USE_FB_MODE_DB
+ struct fb_videomode t;
+ omapfb_dss2fb_timings(timings, &t);
+
+ /* also check interlaced timings */
+ if (!hdmi_set_timings(&t, true)) {
+ t.yres *= 2;
+ t.vmode |= FB_VMODE_INTERLACED;
+ }
+ if (!hdmi_set_timings(&t, true))
+ return -EINVAL;
+#else
struct hdmi_cm cm;
cm = hdmi_get_code(timings);
return -EINVAL;
}
+#endif
return 0;
}
+int omapdss_hdmi_display_set_mode(struct omap_dss_device *dssdev,
+ struct fb_videomode *vm)
+{
+ int r1, r2;
+ /* turn the hdmi off and on to get new timings to use */
+ hdmi.ip_data.set_mode = true;
+ dssdev->driver->disable(dssdev);
+ hdmi.ip_data.set_mode = false;
+ r1 = hdmi_set_timings(vm, false) ? 0 : -EINVAL;
+ hdmi.custom_set = true;
+ hdmi.code = hdmi.ip_data.cfg.cm.code;
+ hdmi.mode = hdmi.ip_data.cfg.cm.mode;
+ r2 = dssdev->driver->enable(dssdev);
+ return r1 ? : r2;
+}
+
int omapdss_hdmi_display_3d_enable(struct omap_dss_device *dssdev,
struct s3d_disp_info *info, int code)
{
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
+#ifdef CONFIG_USE_FB_MODE_DB
+ struct fb_videomode t;
+
+ DSSDBG("x_res= %d y_res = %d\n",
+ dssdev->panel.timings.x_res,
+ dssdev->panel.timings.y_res);
+
+ omapfb_dss2fb_timings(&dssdev->panel.timings, &t);
+ /* also check interlaced timings */
+ if (!hdmi_set_timings(&t, true)) {
+ t.yres *= 2;
+ t.vmode |= FB_VMODE_INTERLACED;
+ }
+ omapdss_hdmi_display_set_mode(dssdev, &t);
+#else
struct hdmi_cm cm;
const struct hdmi_config *t;
hdmi.ip_data.cfg = *t;
mutex_unlock(&hdmi.lock);
+#endif
}
static void hdmi_dump_regs(struct seq_file *s)
r = hdmi_runtime_get();
BUG_ON(r);
-
hdmi_set_ls_state(LS_ENABLED);
- r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len);
+ //r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len);
+ if(hdmi_read_valid_edid())
+ omapdss_get_edid(buf);
+ else
+ r = -1;
/* restore level shifter state */
hdmi_set_ls_state(restore_state);
hdmi_runtime_put();
mutex_unlock(&hdmi.lock);
+
return r;
}
goto err0;
}
+ /* Update the mode db database */
+ if (hdmi.edid_set) {
+ /* get monspecs from edid */
+ hdmi_get_monspecs(dssdev);
+ }
+
r = hdmi_power_on_full(dssdev);
if (r) {
DSSERR("failed to power on device\n");
mutex_unlock(&hdmi.lock);
}
+void omapdss_hdmi_clear_edid(void)
+{
+ hdmi.edid_set = false;
+ hdmi.custom_set = false;
+}
+
+ssize_t omapdss_get_edid(char *buf)
+{
+ ssize_t size = hdmi.edid_set ? HDMI_EDID_MAX_LENGTH : 0;
+ memcpy(buf, hdmi.edid, size);
+ return size;
+}
+
static irqreturn_t hdmi_irq_handler(int irq, void *arg)
{
int r = 0;
goto err_panel_init;
}
+ hdmi.edid_set = false;
+
dss_debugfs_create_file("hdmi", hdmi_dump_regs);
hdmi_init_output(pdev);
DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
dssdev->panel.timings.x_res,
dssdev->panel.timings.y_res);
-
+#ifndef CONFIG_USE_FB_MODE_DB
omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
-
hdmi.dssdev = dssdev;
-
+#endif
return 0;
}
r = -EINVAL;
goto err;
}
-
+#ifndef CONFIG_USE_FB_MODE_DB
omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
-
+#endif
r = omapdss_hdmi_display_enable(dssdev);
if (r) {
DSSERR("failed to power on\n");
*/
hdmi_panel_audio_disable(dssdev);
- omapdss_hdmi_display_set_timing(dssdev, timings);
dssdev->panel.timings = *timings;
-
+#ifndef CONFIG_USE_FB_MODE_DB
+ omapdss_hdmi_display_set_timing(dssdev, timings);
+ mutex_unlock(&hdmi.lock);
+#else
mutex_unlock(&hdmi.lock);
+ omapdss_hdmi_display_set_timing(dssdev, timings);
+#endif
}
static int hdmi_check_timings(struct omap_dss_device *dssdev,
#define dss_of_match NULL
#endif
+static int hdmi_get_modedb(struct omap_dss_device *dssdev,
+ struct fb_videomode *modedb, int modedb_len)
+{
+ struct fb_monspecs *specs = &dssdev->panel.monspecs;
+ if (specs->modedb_len < modedb_len)
+ modedb_len = specs->modedb_len;
+ memcpy(modedb, specs->modedb, sizeof(*modedb) * modedb_len);
+ return modedb_len;
+}
+
static struct omap_dss_driver hdmi_driver = {
.probe = hdmi_panel_probe,
.remove = hdmi_panel_remove,
.set_timings = hdmi_set_timings,
.check_timings = hdmi_check_timings,
.read_edid = hdmi_read_edid,
+ .get_modedb = hdmi_get_modedb,
+ .set_mode = omapdss_hdmi_display_set_mode,
.detect = hdmi_detect,
.audio_enable = hdmi_panel_audio_enable,
.audio_disable = hdmi_panel_audio_disable,
struct hdmi_s3d_info s3d_info;
enum hdmi_deep_color_mode deep_color;
enum hdmi_range range;
+ struct fb_videomode timingsfb;
};
/* HDMI PLL structure */
/* ti_hdmi_4xxx_ip private data. These should be in a separate struct */
int hpd_gpio;
struct mutex lock;
+ bool set_mode;
};
int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
index 232d708df0e2e50e4dd092160b1a30a6032d54ec..c77d865b1f99a0042291f794d79a05905129e1ad 100644 (file)
REG_FLD_MOD(core_sys_base, HDMI_CORE_AUD_CONF0, 0, 5, 5);
/* enable two channels in GPA */
REG_FLD_MOD(core_sys_base, HDMI_CORE_AUD_GP_CONF1, 3, 7, 0);
+ } else if (cfg->layout == HDMI_AUDIO_LAYOUT_6CH) {
+ /* select HBR/SPDIF interfaces */
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_AUD_CONF0, 0, 5, 5);
+ /* enable six channels in GPA */
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_AUD_GP_CONF1, 0x3F, 7, 0);
} else {
/* select HBR/SPDIF interfaces */
REG_FLD_MOD(core_sys_base, HDMI_CORE_AUD_CONF0, 0, 5, 5);
- /* enable two channels in GPA */
+ /* enable eight channels in GPA */
REG_FLD_MOD(core_sys_base, HDMI_CORE_AUD_GP_CONF1, 0xFF, 7, 0);
}
{
void __iomem *core_sys_base = hdmi_core_sys_base(ip_data);
+ /* Channel count and coding type fields in AUDICONF0 are swapped */
hdmi_write_reg(core_sys_base, HDMI_CORE_FC_AUDICONF0,
- info_aud->db1_ct_cc);
+ (info_aud->db1_ct_cc & CEA861_AUDIO_INFOFRAME_DB1CC)<<4 |
+ (info_aud->db1_ct_cc & CEA861_AUDIO_INFOFRAME_DB1CT)>>4);
hdmi_write_reg(core_sys_base, HDMI_CORE_FC_AUDICONF1,
info_aud->db2_sf_ss);
diff --git a/drivers/video/omap2/dsscomp/Kconfig b/drivers/video/omap2/dsscomp/Kconfig
--- /dev/null
@@ -0,0 +1,21 @@
+menuconfig DSSCOMP
+ tristate "OMAP DSS Composition support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && OMAP2_DSS && DRM_OMAP_DMM_TILER && ION_OMAP
+ default y
+
+ help
+ Frame composition driver using OMAP DSS2. Allows using
+ all DSS2 resources in a unified configuration. Should not
+ be used together with other DSS2 devices, such as V4L2
+ or OMAPFB.
+
+config DSSCOMP_DEBUG_LOG
+ bool "Log event timestamps in debugfs"
+ default y
+ depends on DEBUG_FS && DSSCOMP
+
+ help
+ Takes timestamp for each callback and state transition, and
+ logs the last 128 entries (last few frames' worth) in a
+ log buffer. This is a separate menuconfig in case this is
+ deemed an overhead.
diff --git a/drivers/video/omap2/dsscomp/Makefile b/drivers/video/omap2/dsscomp/Makefile
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_DSSCOMP) += dsscomp.o
+dsscomp-y := device.o base.o queue.o
+dsscomp-y += gralloc.o
+dsscomp-y += tiler-utils.o
diff --git a/drivers/video/omap2/dsscomp/base.c b/drivers/video/omap2/dsscomp/base.c
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ * linux/drivers/video/omap2/dsscomp/base.c
+ *
+ * DSS Composition basic operation support
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+
+#include <linux/notifier.h>
+#include "../../../drivers/gpu/drm/omapdrm/omap_dmm_tiler.h"
+
+#include <video/omapdss.h>
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+
+#include "dsscomp.h"
+
+int debug;
+module_param(debug, int, 0644);
+
+/* color formats supported - bitfield info is used for truncation logic */
+static const struct color_info {
+ int a_ix, a_bt; /* bitfields */
+ int r_ix, r_bt;
+ int g_ix, g_bt;
+ int b_ix, b_bt;
+ int x_bt;
+ enum omap_color_mode mode;
+ const char *name;
+} fmts[2][17] = { {
+ { 0, 0, 0, 0, 0, 0, 0, 0, 1, OMAP_DSS_COLOR_CLUT1, "BITMAP1" },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 2, OMAP_DSS_COLOR_CLUT2, "BITMAP2" },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 4, OMAP_DSS_COLOR_CLUT4, "BITMAP4" },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 8, OMAP_DSS_COLOR_CLUT8, "BITMAP8" },
+ { 0, 0, 8, 4, 4, 4, 0, 4, 4, OMAP_DSS_COLOR_RGB12U, "xRGB12-4444" },
+ { 12, 4, 8, 4, 4, 4, 0, 4, 0, OMAP_DSS_COLOR_ARGB16, "ARGB16-4444" },
+ { 0, 0, 11, 5, 5, 6, 0, 5, 0, OMAP_DSS_COLOR_RGB16, "RGB16-565" },
+ { 15, 1, 10, 5, 5, 5, 0, 5, 0, OMAP_DSS_COLOR_ARGB16_1555,
+ "ARGB16-1555" },
+ { 0, 0, 16, 8, 8, 8, 0, 8, 8, OMAP_DSS_COLOR_RGB24U, "xRGB24-8888" },
+ { 0, 0, 16, 8, 8, 8, 0, 8, 0, OMAP_DSS_COLOR_RGB24P, "RGB24-888" },
+ { 0, 0, 12, 4, 8, 4, 4, 4, 4, OMAP_DSS_COLOR_RGBX16, "RGBx12-4444" },
+ { 0, 4, 12, 4, 8, 4, 4, 4, 0, OMAP_DSS_COLOR_RGBA16, "RGBA16-4444" },
+ { 24, 8, 16, 8, 8, 8, 0, 8, 0, OMAP_DSS_COLOR_ARGB32, "ARGB32-8888" },
+ { 0, 8, 24, 8, 16, 8, 8, 8, 0, OMAP_DSS_COLOR_RGBA32, "RGBA32-8888" },
+ { 0, 0, 24, 8, 16, 8, 8, 8, 8, OMAP_DSS_COLOR_RGBX32, "RGBx24-8888" },
+ { 0, 8, 8, 8, 16, 8, 24, 8, 0, OMAP_DSS_COLOR_BGRA32, "BGRA32-8888" },
+ { 0, 0, 10, 5, 5, 5, 0, 5, 1, OMAP_DSS_COLOR_XRGB16_1555,
+ "xRGB15-1555" },
+}, {
+ { 0, 0, 0, 0, 0, 0, 0, 0, 12, OMAP_DSS_COLOR_NV12, "NV12" },
+ { 0, 0, 12, 4, 8, 4, 4, 4, 4, OMAP_DSS_COLOR_RGBX16, "RGBx12-4444" },
+ { 0, 4, 12, 4, 8, 4, 4, 4, 0, OMAP_DSS_COLOR_RGBA16, "RGBA16-4444" },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "invalid" },
+ { 0, 0, 8, 4, 4, 4, 0, 4, 4, OMAP_DSS_COLOR_RGB12U, "xRGB12-4444" },
+ { 12, 4, 8, 4, 4, 4, 0, 4, 0, OMAP_DSS_COLOR_ARGB16, "ARGB16-4444" },
+ { 0, 0, 11, 5, 5, 6, 0, 5, 0, OMAP_DSS_COLOR_RGB16, "RGB16-565" },
+ { 15, 1, 10, 5, 5, 5, 0, 5, 0, OMAP_DSS_COLOR_ARGB16_1555,
+ "ARGB16-1555" },
+ { 0, 0, 16, 8, 8, 8, 0, 8, 8, OMAP_DSS_COLOR_RGB24U, "xRGB24-8888" },
+ { 0, 0, 16, 8, 8, 8, 0, 8, 0, OMAP_DSS_COLOR_RGB24P, "RGB24-888" },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 16, OMAP_DSS_COLOR_YUV2, "YUYV" },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 16, OMAP_DSS_COLOR_UYVY, "UYVY" },
+ { 24, 8, 16, 8, 8, 8, 0, 8, 0, OMAP_DSS_COLOR_ARGB32, "ARGB32-8888" },
+ { 0, 8, 24, 8, 16, 8, 8, 8, 0, OMAP_DSS_COLOR_RGBA32, "RGBA32-8888" },
+ { 0, 8, 8, 8, 16, 8, 24, 8, 0, OMAP_DSS_COLOR_BGRA32, "BGRA32-8888" },
+ { 0, 0, 24, 8, 16, 8, 8, 8, 8, OMAP_DSS_COLOR_RGBX32, "RGBx24-8888" },
+ { 0, 0, 10, 5, 5, 5, 0, 5, 1, OMAP_DSS_COLOR_XRGB16_1555,
+ "xRGB15-1555" },
+} };
+
+static const struct color_info *get_color_info(enum omap_color_mode mode)
+{
+ int i;
+ for (i = 0; i < sizeof(fmts) / sizeof(fmts[0][0]); i++)
+ if (fmts[0][i].mode == mode)
+ return fmts[0] + i;
+ return NULL;
+}
+
+static int color_mode_to_bpp(enum omap_color_mode color_mode)
+{
+ const struct color_info *ci = get_color_info(color_mode);
+ if (!ci)
+ return 0;
+
+ return ci->a_bt + ci->r_bt + ci->g_bt + ci->b_bt + ci->x_bt;
+}
+
+#ifdef CONFIG_DEBUG_FS
+const char *dsscomp_get_color_name(enum omap_color_mode m)
+{
+ const struct color_info *ci = get_color_info(m);
+ return ci ? ci->name : NULL;
+}
+#endif
+
+union rect {
+ struct {
+ s32 x;
+ s32 y;
+ s32 w;
+ s32 h;
+ };
+ struct {
+ s32 xy[2];
+ s32 wh[2];
+ };
+ struct dss2_rect_t r;
+};
+
+static int crop_to_rect(union rect *crop, union rect *win, union rect *vis,
+ int rotation, int mirror)
+{
+ int c, swap = rotation & 1;
+
+ /* align crop window with display coordinates */
+ if (swap)
+ crop->y -= (crop->h = -crop->h);
+ if (rotation & 2)
+ crop->xy[!swap] -= (crop->wh[!swap] = -crop->wh[!swap]);
+ if ((!mirror) ^ !(rotation & 2))
+ crop->xy[swap] -= (crop->wh[swap] = -crop->wh[swap]);
+
+ for (c = 0; c < 2; c++) {
+ /* see if complete buffer is outside the vis or it is
+ fully cropped or scaled to 0 */
+ if (win->wh[c] <= 0 || vis->wh[c] <= 0 ||
+ win->xy[c] + win->wh[c] <= vis->xy[c] ||
+ win->xy[c] >= vis->xy[c] + vis->wh[c] ||
+ !crop->wh[c ^ swap])
+ return -ENOENT;
+
+ /* crop left/top */
+ if (win->xy[c] < vis->xy[c]) {
+ /* correction term */
+ int a = (vis->xy[c] - win->xy[c]) *
+ crop->wh[c ^ swap] / win->wh[c];
+ crop->xy[c ^ swap] += a;
+ crop->wh[c ^ swap] -= a;
+ win->wh[c] -= vis->xy[c] - win->xy[c];
+ win->xy[c] = vis->xy[c];
+ }
+ /* crop right/bottom */
+ if (win->xy[c] + win->wh[c] > vis->xy[c] + vis->wh[c]) {
+ crop->wh[c ^ swap] = crop->wh[c ^ swap] *
+ (vis->xy[c] + vis->wh[c] - win->xy[c]) /
+ win->wh[c];
+ win->wh[c] = vis->xy[c] + vis->wh[c] - win->xy[c];
+ }
+
+ if (!crop->wh[c ^ swap] || !win->wh[c])
+ return -ENOENT;
+ }
+
+ /* realign crop window to buffer coordinates */
+ if (rotation & 2)
+ crop->xy[!swap] -= (crop->wh[!swap] = -crop->wh[!swap]);
+ if ((!mirror) ^ !(rotation & 2))
+ crop->xy[swap] -= (crop->wh[swap] = -crop->wh[swap]);
+ if (swap)
+ crop->y -= (crop->h = -crop->h);
+ return 0;
+}
+
+int set_dss_ovl_info(struct dss2_ovl_info *oi)
+{
+ struct omap_overlay_info info;
+ struct omap_overlay *ovl;
+ struct dss2_ovl_cfg *cfg;
+ union rect crop, win, vis;
+ int c;
+ int bpp;
+ enum tiler_fmt fmt;
+
+ /* check overlay number */
+ if (!oi || oi->cfg.ix >= omap_dss_get_num_overlays())
+ return -EINVAL;
+ cfg = &oi->cfg;
+ ovl = omap_dss_get_overlay(cfg->ix);
+
+ /* just in case there are new fields, we get the current info */
+ ovl->get_overlay_info(ovl, &info);
+
+ ovl->enabled = cfg->enabled;
+ if (!cfg->enabled)
+ goto done;
+
+ /* copied params */
+ info.zorder = cfg->zorder;
+
+ if (cfg->zonly)
+ goto done;
+
+ info.global_alpha = cfg->global_alpha;
+ info.pre_mult_alpha = cfg->pre_mult_alpha;
+ info.wb_source = cfg->wb_source;
+ info.rotation = cfg->rotation;
+ info.mirror = cfg->mirror;
+ info.color_mode = cfg->color_mode;
+
+ info.force_1d = cfg->force_1d;
+
+ /* mflag for the overlay */
+ info.mflag_en = cfg->mflag_en;
+
+ /* crop to screen */
+ crop.r = cfg->crop;
+ win.r = cfg->win;
+ vis.x = vis.y = 0;
+ vis.w = ovl->manager->output->device->panel.timings.x_res;
+ vis.h = ovl->manager->output->device->panel.timings.y_res;
+
+ if (!info.wb_source)
+ if (crop_to_rect(&crop, &win, &vis, cfg->rotation,
+ cfg->mirror) || vis.w < 2)
+ goto done;
+
+ /* adjust crop to UV pixel boundaries */
+ for (c = 0; c < (cfg->color_mode == OMAP_DSS_COLOR_NV12 ? 2 :
+ (cfg->color_mode &
+ (OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY)) ? 1 : 0); c++) {
+ /* keep the output window to avoid trembling edges */
+ crop.wh[c] += crop.xy[c] & 1; /* round down start */
+ crop.xy[c] &= ~1;
+ crop.wh[c] += crop.wh[c] & 1; /* round up end */
+
+ /*
+ * Buffer is aligned on UV pixel boundaries, so no
+ * worries about extending crop region.
+ */
+ }
+
+ info.width = crop.w;
+ info.height = crop.h;
+ if (cfg->rotation & 1)
+ /* DISPC uses swapped height/width for 90/270 degrees */
+ swap(info.width, info.height);
+ info.pos_x = win.x;
+ info.pos_y = win.y;
+ info.out_width = win.w;
+ info.out_height = win.h;
+
+ /* calculate addresses and cropping */
+ info.paddr = oi->ba;
+ info.p_uv_addr = (info.color_mode == OMAP_DSS_COLOR_NV12) ? oi->uv : 0;
+
+ /* check for TILER 2D buffer */
+ if (tiler_get_fmt(info.paddr, &fmt) && fmt >= TILFMT_8BIT &&
+ fmt <= TILFMT_32BIT) {
+ int bpp = 1 << (fmt - TILFMT_8BIT);
+ struct tiler_view_t t;
+
+ /* crop to top-left */
+
+ /*
+ * DSS supports YUV422 on 32-bit mode, but its technically
+ * 2 bytes-per-pixel.
+ * Also RGB24-888 is 3 bytes-per-pixel even though no
+ * tiler pixel format matches this.
+ */
+ if (cfg->color_mode &
+ (OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY))
+ bpp = 2;
+ else if (cfg->color_mode == OMAP_DSS_COLOR_RGB24P)
+ bpp = 3;
+
+ tilview_create(&t, info.paddr, cfg->width, cfg->height);
+ info.paddr -= t.tsptr;
+ tilview_crop(&t, 0, crop.y, cfg->width, crop.h);
+ info.paddr += t.tsptr + bpp * crop.x;
+
+ info.rotation_type = OMAP_DSS_ROT_TILER;
+ info.screen_width = 0;
+
+ /* for NV12 format also crop NV12 */
+ if (info.color_mode == OMAP_DSS_COLOR_NV12) {
+ tilview_create(&t, info.p_uv_addr,
+ cfg->width >> 1, cfg->height >> 1);
+ info.p_uv_addr -= t.tsptr;
+ tilview_crop(&t, 0, crop.y >> 1, cfg->width >> 1,
+ crop.h >> 1);
+ info.p_uv_addr += t.tsptr + bpp * crop.x;
+ }
+ } else {
+ /* program tiler 1D as SDMA */
+
+ int bpp = color_mode_to_bpp(cfg->color_mode);
+ if (!bpp) {
+ pr_warn("invalid color format %u for ovl%d\n",
+ cfg->color_mode, cfg->ix);
+ goto done;
+ }
+
+ info.screen_width = cfg->stride * 8 / (bpp == 12 ? 8 : bpp);
+ info.paddr += crop.x * (bpp / 8) + crop.y * cfg->stride;
+
+ /* for NV12 format also crop NV12 */
+ if (info.color_mode == OMAP_DSS_COLOR_NV12)
+ info.p_uv_addr += crop.x * (bpp / 8) +
+ (crop.y >> 1) * cfg->stride;
+
+ /* no rotation on DMA buffer */
+ if (cfg->rotation & 3 || cfg->mirror)
+ return -EINVAL;
+
+ info.rotation_type = OMAP_DSS_ROT_DMA;
+ }
+
+ info.max_x_decim = cfg->decim.max_x ? : 255;
+ info.max_y_decim = cfg->decim.max_y ? : 255;
+ info.min_x_decim = cfg->decim.min_x ? : 1;
+ info.min_y_decim = cfg->decim.min_y ? : 1;
+#if 0
+ info.pic_height = cfg->height;
+
+ info.field = 0;
+ if (cfg->ilace & OMAP_DSS_ILACE_SEQ)
+ info.field |= OMAP_FLAG_IBUF;
+ if (cfg->ilace & OMAP_DSS_ILACE_SWAP)
+ info.field |= OMAP_FLAG_ISWAP;
+ /*
+ * Ignore OMAP_DSS_ILACE as there is no real support yet for
+ * interlaced interleaved vs progressive buffers
+ */
+ if (ovl->manager &&
+ ovl->manager->device &&
+ !strcmp(ovl->manager->device->name, "hdmi") &&
+ is_hdmi_interlaced())
+ info.field |= OMAP_FLAG_IDEV;
+
+ info.out_wb = 0;
+#endif
+
+ info.cconv = cfg->cconv;
+
+done:
+ pr_debug("ovl%d: en=%d %x/%x ", ovl->id, ovl->is_enabled(ovl),
+ info.paddr, info.p_uv_addr);
+ pr_debug("(%dx%d|%d) => ", info.width, info.height, info.screen_width);
+ pr_debug("(%dx%d) @ ", info.out_width, info.out_height);
+ pr_debug("(%d,%d) rot=%d ", info.pos_x, info.pos_y, info.rotation);
+ pr_debug("mir=%d col=%x z=%d ", info.mirror, info.color_mode,
+ info.zorder);
+ pr_debug("al=%02x prem=%d\n", info.global_alpha, info.pre_mult_alpha);
+ /* set overlay info */
+ return ovl->set_overlay_info(ovl, &info);
+}
+
+void swap_rb_in_ovl_info(struct dss2_ovl_info *oi)
+{
+ /* we need to swap YUV color matrix if we are swapping R and B */
+ if (oi->cfg.color_mode &
+ (OMAP_DSS_COLOR_NV12 | OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY)) {
+ swap(oi->cfg.cconv.ry, oi->cfg.cconv.by);
+ swap(oi->cfg.cconv.rcr, oi->cfg.cconv.bcr);
+ swap(oi->cfg.cconv.rcb, oi->cfg.cconv.bcb);
+ }
+}
+
+struct omap_overlay_manager *find_dss_mgr(int display_ix)
+{
+ struct omap_overlay_manager *mgr;
+ char name[32];
+ int i;
+
+ sprintf(name, "display%d", display_ix);
+
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
+ mgr = omap_dss_get_overlay_manager(i);
+ if((mgr) && (mgr->output))
+ {
+ if (mgr->output->device && !strcmp(name,
+ dev_name(&mgr->output->device->dev)))
+ return mgr;
+ }
+ }
+ return NULL;
+}
+
+int set_dss_mgr_info(struct dss2_mgr_info *mi, struct omapdss_ovl_cb *cb)
+{
+ struct omap_overlay_manager_info info;
+ struct omap_overlay_manager *mgr;
+
+ if (!mi)
+ return -EINVAL;
+ mgr = find_dss_mgr(mi->ix);
+ if (!mgr)
+ return -EINVAL;
+
+ /* just in case there are new fields, we get the current info */
+ mgr->get_manager_info(mgr, &info);
+
+ /* we support alpha-enabled only if we have free zorder */
+ /* :FIXME: for now DSS has this as an ovl cap */
+ if (alpha_only) {
+ if (!mi->alpha_blending)
+ return -EINVAL;
+ info.partial_alpha_enabled = false;
+ } else {
+ info.partial_alpha_enabled = mi->alpha_blending;
+ }
+
+ info.default_color = mi->default_color;
+ info.trans_enabled = mi->trans_enabled && !mi->alpha_blending;
+ info.trans_key = mi->trans_key;
+ info.trans_key_type = mi->trans_key_type;
+
+ info.cpr_coefs = mi->cpr_coefs;
+ info.cpr_enable = mi->cpr_enabled;
+ info.cb = *cb;
+
+ return mgr->set_manager_info(mgr, &info);
+}
+
+void swap_rb_in_mgr_info(struct dss2_mgr_info *mi)
+{
+ const struct omap_dss_cpr_coefs c = { 256, 0, 0, 0, 256, 0, 0, 0, 256 };
+
+ /* set default CPR */
+ if (!mi->cpr_enabled)
+ mi->cpr_coefs = c;
+ mi->cpr_enabled = true;
+
+ /* swap red and blue */
+ swap(mi->cpr_coefs.rr, mi->cpr_coefs.br);
+ swap(mi->cpr_coefs.rg, mi->cpr_coefs.bg);
+ swap(mi->cpr_coefs.rb, mi->cpr_coefs.bb);
+}
+
+/*
+ * ===========================================================================
+ * DEBUG METHODS
+ * ===========================================================================
+ */
+void dump_ovl_info(struct dsscomp_dev *cdev, struct dss2_ovl_info *oi)
+{
+ struct dss2_ovl_cfg *c = &oi->cfg;
+ const struct color_info *ci;
+
+ if (!(debug & DEBUG_OVERLAYS) ||
+ !(debug & DEBUG_COMPOSITIONS))
+ return;
+
+ ci = get_color_info(c->color_mode);
+ if (c->zonly) {
+ dev_info(DEV(cdev), "ovl%d(%s z%d)\n", c->ix, c->enabled ?
+ "ON" : "off", c->zorder);
+ return;
+ }
+ dev_info(DEV(cdev), "ovl%d(%s ", c->ix, c->enabled ? "ON" : "off");
+ dev_info(DEV(cdev), "z%d %s", c->zorder, ci ? (ci->name ? :
+ "(none)") : "(invalid)");
+ dev_info(DEV(cdev), "%s", c->pre_mult_alpha ? " premult" : "");
+ dev_info(DEV(cdev), "*%d%%", (c->global_alpha * 100 + 128) / 255);
+ dev_info(DEV(cdev), "%d*%d:%d,%d+", c->width, c->height, c->crop.x,
+ c->crop.y);
+ dev_info(DEV(cdev), "%d,%d rot%d", c->crop.w, c->crop.h, c->rotation);
+ dev_info(DEV(cdev), "%s => %d,", c->mirror ? "+mir" : "", c->win.x);
+ dev_info(DEV(cdev), "%d+%d,%d ", c->win.y, c->win.w, c->win.h);
+ dev_info(DEV(cdev), "%p/%p|%d)\n", (void *)oi->ba, (void *)oi->uv,
+ c->stride);
+}
+
+static void print_mgr_info(struct dsscomp_dev *cdev,
+ struct dss2_mgr_info *mi)
+{
+ pr_cont("(dis%d(%s) alpha=%d col=%08x ilace=%d) ",
+ mi->ix,
+ (mi->ix < cdev->num_displays && cdev->displays[mi->ix]) ?
+ cdev->displays[mi->ix]->name : "NONE",
+ mi->alpha_blending, mi->default_color,
+ mi->interlaced);
+}
+
+void dump_comp_info(struct dsscomp_dev *cdev, struct dsscomp_setup_mgr_data *d,
+ const char *phase)
+{
+ if (!(debug & DEBUG_COMPOSITIONS))
+ return;
+
+ dev_info(DEV(cdev), "[%p] %s: %c%c%c ",
+ *phase == 'q' ? (void *)d->sync_id : d, phase,
+ (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-',
+ (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-',
+ (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-');
+ print_mgr_info(cdev, &d->mgr);
+ pr_cont("n=%d\n", d->num_ovls);
+}
+
+void dump_total_comp_info(struct dsscomp_dev *cdev,
+ struct dsscomp_setup_dispc_data *d,
+ const char *phase)
+{
+ int i;
+
+ if (!(debug & DEBUG_COMPOSITIONS))
+ return;
+
+ dev_info(DEV(cdev), "[%p] ", *phase == 'q' ? (void *)d->sync_id : d);
+ dev_info(DEV(cdev), "%s: %c", phase,
+ (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-');
+ dev_info(DEV(cdev), "%c",
+ (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-');
+ dev_info(DEV(cdev), "%c ",
+ (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-');
+
+ for (i = 0; i < d->num_mgrs && i < ARRAY_SIZE(d->mgrs); i++)
+ print_mgr_info(cdev, d->mgrs + i);
+ pr_cont("n=%d\n", d->num_ovls);
+}
diff --git a/drivers/video/omap2/dsscomp/device.c b/drivers/video/omap2/dsscomp/device.c
--- /dev/null
@@ -0,0 +1,799 @@
+/*
+ * linux/drivers/video/omap2/dsscomp/device.c
+ *
+ * DSS Composition file device and ioctl support
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DEBUG
+
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/anon_inodes.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+
+#define MODULE_NAME_DSSCOMP "dsscomp"
+
+#include <video/omapdss.h>
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+#include "../../../drivers/gpu/drm/omapdrm/omap_dmm_tiler.h"
+#include "dsscomp.h"
+#include "../dss/dss_features.h"
+#include "../dss/dss.h"
+
+#include <linux/debugfs.h>
+#include <plat/android-display.h>
+
+static DECLARE_WAIT_QUEUE_HEAD(waitq);
+static DEFINE_MUTEX(wait_mtx);
+bool alpha_only = true;
+
+static struct dsscomp_platform_info platform_info;
+
+static u32 hwc_virt_to_phys(u32 arg)
+{
+ pmd_t *pmd;
+ pte_t *ptep;
+
+ pgd_t *pgd = pgd_offset(current->mm, arg);
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ return 0;
+
+ pmd = pmd_offset((pud_t *)pgd, arg);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ return 0;
+
+ ptep = pte_offset_map(pmd, arg);
+ if (ptep && pte_present(*ptep))
+ return (PAGE_MASK & *ptep) | (~PAGE_MASK & arg);
+
+ return 0;
+}
+
+/*
+ * ===========================================================================
+ * WAIT OPERATIONS
+ * ===========================================================================
+ */
+
+static void sync_drop(struct dsscomp_sync_obj *sync)
+{
+ if (sync && atomic_dec_and_test(&sync->refs)) {
+ if (debug & DEBUG_WAITS)
+ pr_info("free sync [%p]\n", sync);
+
+ kfree(sync);
+ }
+}
+
+static int sync_setup(const char *name, const struct file_operations *fops,
+ struct dsscomp_sync_obj *sync, int flags)
+{
+ if (!sync)
+ return -ENOMEM;
+
+ sync->refs.counter = 1;
+ sync->fd = anon_inode_getfd(name, fops, sync, flags);
+ return sync->fd < 0 ? sync->fd : 0;
+}
+
+static int sync_finalize(struct dsscomp_sync_obj *sync, int r)
+{
+ if (sync) {
+ if (r < 0)
+ /* delete sync object on failure */
+ sys_close(sync->fd);
+ else
+ /* return file descriptor on success */
+ r = sync->fd;
+ }
+ return r;
+}
+
+/* wait for programming or release of a composition */
+int dsscomp_wait(struct dsscomp_sync_obj *sync, enum dsscomp_wait_phase phase,
+ int timeout)
+{
+ mutex_lock(&wait_mtx);
+ if (debug & DEBUG_WAITS) {
+ pr_info("wait %s on ", phase == DSSCOMP_WAIT_DISPLAYED ?
+ "display" : phase == DSSCOMP_WAIT_PROGRAMMED ?
+ "program" : "release");
+ pr_info("[%p]\n", sync);
+ }
+
+ if (sync->state < phase) {
+ mutex_unlock(&wait_mtx);
+
+ timeout = wait_event_interruptible_timeout(waitq,
+ sync->state >= phase, timeout);
+ if (debug & DEBUG_WAITS) {
+ pr_info("wait over [%p]: ", sync);
+ pr_info("%s", timeout < 0 ? "signal" : timeout > 0 ?
+ "ok" : "timeout");
+ pr_info("%d\n", timeout);
+ }
+ if (timeout <= 0)
+ return timeout ? : -ETIME;
+
+ mutex_lock(&wait_mtx);
+ }
+ mutex_unlock(&wait_mtx);
+
+ return 0;
+}
+EXPORT_SYMBOL(dsscomp_wait);
+
+static void dsscomp_queue_cb(void *data, int status)
+{
+ struct dsscomp_sync_obj *sync = data;
+ enum dsscomp_wait_phase phase =
+ status == DSS_COMPLETION_PROGRAMMED ? DSSCOMP_WAIT_PROGRAMMED :
+ status == DSS_COMPLETION_DISPLAYED ? DSSCOMP_WAIT_DISPLAYED :
+ DSSCOMP_WAIT_RELEASED, old_phase;
+
+ mutex_lock(&wait_mtx);
+ old_phase = sync->state;
+ if (old_phase < phase)
+ sync->state = phase;
+ mutex_unlock(&wait_mtx);
+
+ if (status & DSS_COMPLETION_RELEASED)
+ sync_drop(sync);
+ if (old_phase < phase)
+ wake_up_interruptible_sync(&waitq);
+}
+
+static int sync_release(struct inode *inode, struct file *filp)
+{
+ struct dsscomp_sync_obj *sync = filp->private_data;
+ sync_drop(sync);
+ return 0;
+}
+
+static long sync_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int r = 0;
+ struct dsscomp_sync_obj *sync = filp->private_data;
+ void __user *ptr = (void __user *)arg;
+
+ switch (cmd) {
+ case DSSCIOC_WAIT:
+ {
+ struct dsscomp_wait_data wd;
+ r = copy_from_user(&wd, ptr, sizeof(wd)) ? :
+ dsscomp_wait(sync, wd.phase,
+ usecs_to_jiffies(wd.timeout_us));
+ break;
+ }
+ default:
+ r = -EINVAL;
+ }
+ return r;
+}
+
+static const struct file_operations sync_fops = {
+ .owner = THIS_MODULE,
+ .release = sync_release,
+ .unlocked_ioctl = sync_ioctl,
+};
+
+static long setup_mgr(struct dsscomp_dev *cdev,
+ struct dsscomp_setup_mgr_data *d)
+{
+ int i, r;
+ struct omap_dss_device *dev;
+ struct omap_overlay_manager *mgr;
+ struct dsscomp *comp;
+ struct dsscomp_sync_obj *sync = NULL;
+
+ dump_comp_info(cdev, d, "queue");
+ for (i = 0; i < d->num_ovls; i++)
+ dump_ovl_info(cdev, d->ovls + i);
+
+ /* verify display is valid and connected */
+ if (d->mgr.ix >= cdev->num_displays)
+ return -EINVAL;
+ dev = cdev->displays[d->mgr.ix];
+ if (!dev)
+ return -EINVAL;
+ mgr = dev->output->manager;
+ if (!mgr)
+ return -ENODEV;
+
+ comp = dsscomp_new(mgr);
+ if (IS_ERR(comp))
+ return PTR_ERR(comp);
+
+ /* swap red & blue if requested */
+ if (d->mgr.swap_rb) {
+ swap_rb_in_mgr_info(&d->mgr);
+ for (i = 0; i < d->num_ovls; i++)
+ swap_rb_in_ovl_info(d->ovls + i);
+ }
+
+ r = dsscomp_set_mgr(comp, &d->mgr);
+
+ for (i = 0; i < d->num_ovls; i++) {
+ struct dss2_ovl_info *oi = d->ovls + i;
+ u32 addr = (u32) oi->address;
+
+ if (oi->addressing != OMAP_DSS_BUFADDR_DIRECT)
+ return -EINVAL;
+
+ /* convert addresses to user space */
+ if (oi->cfg.color_mode == OMAP_DSS_COLOR_NV12) {
+ if (oi->uv_address)
+ oi->uv = hwc_virt_to_phys((u32) oi->uv_address);
+ else
+ oi->uv = hwc_virt_to_phys(addr +
+ oi->cfg.height * oi->cfg.stride);
+ }
+ oi->ba = hwc_virt_to_phys(addr);
+
+ r = r ? : dsscomp_set_ovl(comp, oi);
+ }
+
+ r = r ? : dsscomp_setup(comp, d->mode, d->win);
+
+ /* create sync object */
+ if (d->get_sync_obj) {
+ sync = kzalloc(sizeof(*sync), GFP_KERNEL);
+ r = sync_setup("dsscomp_sync", &sync_fops, sync, O_RDONLY);
+ if (sync && (debug & DEBUG_WAITS))
+ dev_info(DEV(cdev), "new sync [%p] on #%d\n", sync,
+ sync->fd);
+ if (r)
+ sync_drop(sync);
+ }
+
+ /* drop composition if failed to create */
+ if (r) {
+ dsscomp_drop(comp);
+ return r;
+ }
+
+ if (sync) {
+ sync->refs.counter++;
+ comp->extra_cb = dsscomp_queue_cb;
+ comp->extra_cb_data = sync;
+ }
+ if (d->mode & DSSCOMP_SETUP_APPLY)
+ r = dsscomp_delayed_apply(comp);
+
+ /* delete sync object if failed to apply or create file */
+ if (sync) {
+ r = sync_finalize(sync, r);
+ if (r < 0)
+ sync_drop(sync);
+ }
+ return r;
+}
+
+static long query_display(struct dsscomp_dev *cdev,
+ struct dsscomp_display_info *dis)
+{
+ struct omap_dss_device *dev;
+ struct omap_overlay_manager *mgr;
+ struct omap_overlay_manager_info info;
+ int i;
+
+ /* get display */
+ if (dis->ix >= cdev->num_displays)
+ return -EINVAL;
+ dev = cdev->displays[dis->ix];
+ if (!dev)
+ return -EINVAL;
+ mgr = dev->output->manager;
+
+ /* fill out display information */
+ dis->channel = dev->channel;
+ dis->enabled = (dev->state == OMAP_DSS_DISPLAY_SUSPENDED) ?
+ dev->activate_after_resume :
+ (dev->state == OMAP_DSS_DISPLAY_ACTIVE);
+ dis->overlays_available = 0;
+ dis->overlays_owned = 0;
+#if 0
+ dis->s3d_info = dev->panel.s3d_info;
+#endif
+ dis->state = dev->state;
+ dis->timings = dev->panel.timings;
+
+ dis->width_in_mm = DIV_ROUND_CLOSEST(dev->panel.width_in_um, 1000);
+ dis->height_in_mm = DIV_ROUND_CLOSEST(dev->panel.height_in_um, 1000);
+
+ /* find all overlays available for/owned by this display */
+ for (i = 0; i < cdev->num_ovls && dis->enabled; i++) {
+ if (cdev->ovls[i]->manager == mgr)
+ dis->overlays_owned |= 1 << i;
+ else if (!cdev->ovls[i]->is_enabled(cdev->ovls[i]))
+ dis->overlays_available |= 1 << i;
+ }
+ dis->overlays_available |= dis->overlays_owned;
+
+ /* fill out manager information */
+ if (mgr) {
+ mgr->get_manager_info(mgr, &info);
+ dis->mgr.alpha_blending =
+ alpha_only || info.partial_alpha_enabled;
+ dis->mgr.default_color = info.default_color;
+#if 0
+ dis->mgr.interlaced = !strcmp(dev->name, "hdmi") &&
+ is_hdmi_interlaced()
+#else
+ dis->mgr.interlaced = 0;
+#endif
+ dis->mgr.trans_enabled = info.trans_enabled;
+ dis->mgr.trans_key = info.trans_key;
+ dis->mgr.trans_key_type = info.trans_key_type;
+ } else {
+ /* display is disabled if it has no manager */
+ memset(&dis->mgr, 0, sizeof(dis->mgr));
+ }
+ dis->mgr.ix = dis->ix;
+
+ if (dev->driver && dis->modedb_len && dev->driver->get_modedb)
+ dis->modedb_len = dev->driver->get_modedb(dev,
+ (struct fb_videomode *)dis->modedb, dis->modedb_len);
+ return 0;
+}
+
+static long check_ovl(struct dsscomp_dev *cdev,
+ struct dsscomp_check_ovl_data *chk)
+{
+ u16 x_decim, y_decim;
+ bool five_taps;
+ struct omap_dss_device *dev;
+ struct omap_overlay_manager *mgr;
+ int i;
+ long allowed = 0;
+ bool checked_vid = false, scale_ok = false;
+ struct dss2_ovl_cfg *c = &chk->ovl.cfg;
+ enum tiler_fmt fmt;
+
+ /* get display */
+ if (chk->mgr.ix >= cdev->num_displays)
+ return -EINVAL;
+
+ dev = cdev->displays[chk->mgr.ix];
+ if (!dev)
+ return -EINVAL;
+ mgr = dev->output->manager;
+
+ /* we support alpha-enabled only if we have free zorder */
+ /* :FIXME: for now DSS has this as an ovl cap */
+ if (alpha_only && !chk->mgr.alpha_blending)
+ return -EINVAL;
+
+ /* normalize decimation */
+ if (!c->decim.min_x)
+ c->decim.min_x = 1;
+ if (!c->decim.min_y)
+ c->decim.min_y = 1;
+ if (!c->decim.max_x)
+ c->decim.max_x = 255;
+ if (!c->decim.max_y)
+ c->decim.max_y = 255;
+
+ /* check scaling support */
+ for (i = 0; i < cdev->num_ovls; i++) {
+ /* verify color format support */
+ if (c->color_mode & ~cdev->ovls[i]->supported_modes)
+ continue;
+
+ /* verify scaling on GFX and VID pipes */
+ if (!i || !checked_vid) {
+ struct omap_overlay_info info = {
+ .out_width = c->win.w,
+ .out_height = c->win.h,
+ .width = c->crop.w,
+ .height = c->crop.h,
+ .color_mode = c->color_mode,
+ .rotation = c->rotation,
+ .min_x_decim = c->decim.min_x,
+ .max_x_decim = c->decim.max_x,
+ .min_y_decim = c->decim.min_y,
+ .max_y_decim = c->decim.max_y,
+ };
+ u32 ba = (unsigned int) &chk->ovl.address;
+
+ ba = hwc_virt_to_phys(ba);
+ /* check for valid tiler container */
+ if (tiler_get_fmt(ba, &fmt) && fmt >= TILFMT_8BIT &&
+ fmt <= TILFMT_32BIT)
+ info.rotation_type = OMAP_DSS_ROT_TILER;
+ else
+ info.rotation_type = OMAP_DSS_ROT_DMA;
+
+/* scale_ok = !dispc_scaling_decision(i, &info, mgr->id,
+ &x_decim, &y_decim, &five_taps);
+*/
+ /* update minimum decimation needs to support ovl */
+ if (scale_ok) {
+ if (x_decim > c->decim.min_x)
+ c->decim.min_x = x_decim;
+ if (y_decim > c->decim.min_y)
+ c->decim.min_y = y_decim;
+ }
+ }
+ checked_vid = i;
+ if (scale_ok)
+ allowed |= 1 << i;
+ }
+
+ return allowed;
+}
+
+static long setup_display(struct dsscomp_dev *cdev,
+ struct dsscomp_setup_display_data *dis)
+{
+ struct omap_dss_device *dev;
+
+ /* get display */
+ if (dis->ix >= cdev->num_displays)
+ return -EINVAL;
+ dev = cdev->displays[dis->ix];
+ if (!dev)
+ return -EINVAL;
+
+ if (dev->driver->set_mode)
+ return dev->driver->set_mode(dev,
+ (struct fb_videomode *)&dis->mode);
+ else
+ return 0;
+}
+
+static void fill_cache(struct dsscomp_dev *cdev)
+{
+ unsigned long i;
+ struct omap_dss_device *dssdev = NULL;
+
+ cdev->num_ovls = min(omap_dss_get_num_overlays(), MAX_OVERLAYS);
+ for (i = 0; i < cdev->num_ovls; i++)
+ cdev->ovls[i] = omap_dss_get_overlay(i);
+
+ cdev->num_mgrs = min(omap_dss_get_num_overlay_managers(), MAX_MANAGERS);
+ for (i = 0; i < cdev->num_mgrs; i++)
+ cdev->mgrs[i] = omap_dss_get_overlay_manager(i);
+
+ for_each_dss_dev(dssdev) {
+ const char *name = dev_name(&dssdev->dev);
+ if (strncmp(name, "display", 7) ||
+ strict_strtoul(name + 7, 10, &i) ||
+ i >= MAX_DISPLAYS)
+ continue;
+
+ if (cdev->num_displays <= i)
+ cdev->num_displays = i + 1;
+
+ cdev->displays[i] = dssdev;
+ dev_dbg(DEV(cdev), "display%lu=%s\n", i, dssdev->driver_name);
+
+ cdev->state_notifiers[i].notifier_call = dsscomp_state_notifier;
+ blocking_notifier_chain_register(&dssdev->state_notifiers,
+ cdev->state_notifiers + i);
+ }
+ dev_info(DEV(cdev), "found %d displays and %d overlays\n",
+ cdev->num_displays, cdev->num_ovls);
+
+ /*
+ * :FIXME: for now DSS has this as an ovl cap, even though it relates
+ * to the manager. For now we store this globally so we can access
+ * this.
+ */
+ alpha_only = cdev->num_ovls &&
+ (cdev->ovls[0]->caps & OMAP_DSS_OVL_CAP_ZORDER);
+}
+
+static void fill_platform_info(struct dsscomp_dev *cdev)
+{
+ struct dsscomp_platform_info *p = &platform_info;
+
+ p->max_xdecim_1d = 16;
+ p->max_xdecim_2d = 16;
+ p->max_ydecim_1d = 16;
+ p->max_ydecim_2d = 2;
+
+ p->fclk = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+ /*
+ * :TODO: for now overwrite with actual fclock as dss will not scale
+ * fclock based on composition
+ */
+ p->fclk = dispc_fclk_rate();
+
+ p->min_width = 2;
+ p->max_width = 2048;
+ p->max_height = 2048;
+
+ p->max_downscale = 4;
+ p->integer_scale_ratio_limit = 2048;
+
+ p->tiler1d_slot_size = tiler1d_slot_size(cdev);
+
+ p->fbmem_type = DSSCOMP_FBMEM_TILER2D;
+}
+
+static long comp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int r = 0;
+ struct miscdevice *dev = filp->private_data;
+ struct dsscomp_dev *cdev = container_of(dev, struct dsscomp_dev, dev);
+ void __user *ptr = (void __user *)arg;
+
+ union {
+ struct {
+ struct dsscomp_setup_mgr_data set;
+ struct dss2_ovl_info ovl[MAX_OVERLAYS];
+ } m;
+ struct dsscomp_setup_dispc_data dispc;
+ struct dsscomp_display_info dis;
+ struct dsscomp_check_ovl_data chk;
+ struct dsscomp_setup_display_data sdis;
+ } u;
+
+ dsscomp_gralloc_init(cdev);
+
+ switch (cmd) {
+ case DSSCIOC_SETUP_MGR:
+ {
+ r = copy_from_user(&u.m.set, ptr, sizeof(u.m.set)) ? :
+ u.m.set.num_ovls > ARRAY_SIZE(u.m.ovl) ? -EINVAL :
+ copy_from_user(&u.m.ovl,
+ (void __user *)arg + sizeof(u.m.set),
+ sizeof(*u.m.ovl) * u.m.set.num_ovls) ? :
+ setup_mgr(cdev, &u.m.set);
+ break;
+ }
+ case DSSCIOC_SETUP_DISPC:
+ {
+ r = copy_from_user(&u.dispc, ptr, sizeof(u.dispc)) ? :
+ dsscomp_gralloc_queue_ioctl(&u.dispc);
+ break;
+ }
+ case DSSCIOC_QUERY_DISPLAY:
+ {
+ struct dsscomp_display_info *dis = NULL;
+ r = copy_from_user(&u.dis, ptr, sizeof(u.dis));
+ if (!r)
+ dis = kzalloc(sizeof(*dis->modedb) * u.dis.modedb_len +
+ sizeof(*dis), GFP_KERNEL);
+ if (dis) {
+ *dis = u.dis;
+ r = query_display(cdev, dis) ? :
+ copy_to_user(ptr, dis, sizeof(*dis) +
+ sizeof(*dis->modedb) * dis->modedb_len);
+ kfree(dis);
+ } else {
+ r = r ? : -ENOMEM;
+ }
+ break;
+ }
+ case DSSCIOC_CHECK_OVL:
+ {
+ r = copy_from_user(&u.chk, ptr, sizeof(u.chk)) ? :
+ check_ovl(cdev, &u.chk);
+ break;
+ }
+ case DSSCIOC_SETUP_DISPLAY:
+ {
+ r = copy_from_user(&u.sdis, ptr, sizeof(u.sdis)) ? :
+ setup_display(cdev, &u.sdis);
+ break;
+ }
+ case DSSCIOC_QUERY_PLATFORM:
+ {
+ /* :TODO: for now refill platform info as it is dynamic */
+ r = copy_to_user(ptr, &platform_info, sizeof(platform_info));
+ break;
+ }
+ default:
+ r = -EINVAL;
+ }
+ return r;
+}
+
+/* must implement open for filp->private_data to be filled */
+static int comp_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static const struct file_operations comp_fops = {
+ .owner = THIS_MODULE,
+ .open = comp_open,
+ .unlocked_ioctl = comp_ioctl,
+};
+
+static int dsscomp_debug_show(struct seq_file *s, void *unused)
+{
+ void (*fn)(struct seq_file *s) = s->private;
+ fn(s);
+ return 0;
+}
+
+static int dsscomp_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dsscomp_debug_show, inode->i_private);
+}
+
+static const struct file_operations dsscomp_debug_fops = {
+ .open = dsscomp_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int dsscomp_probe(struct platform_device *pdev)
+{
+ int ret;
+ int r = 0;
+ int num_displays = 1;
+ struct device_node *node;
+ struct omap_dss_board_info display_layout_data;
+ struct dsscomp_platform_data dsscomp_config;
+ struct sgx_omaplfb_platform_data omaplfb_plat_data;
+ struct omapfb_platform_data fb_pdata;
+
+ struct dsscomp_dev *cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+ if (!cdev) {
+ pr_err("dsscomp: failed to allocate device.\n");
+ return -ENOMEM;
+ }
+ cdev->dev.minor = MISC_DYNAMIC_MINOR;
+ cdev->dev.name = "dsscomp";
+ cdev->dev.mode = 0666;
+ cdev->dev.fops = &comp_fops;
+
+ ret = misc_register(&cdev->dev);
+ if (ret) {
+ pr_err("dsscomp: failed to register misc device.\n");
+ kfree(cdev);
+ return ret;
+ }
+ cdev->dbgfs = debugfs_create_dir("dsscomp", NULL);
+ if (IS_ERR_OR_NULL(cdev->dbgfs)) {
+ dev_warn(DEV(cdev), "failed to create debug files.\n");
+ } else {
+ debugfs_create_file("comps", S_IRUGO,
+ cdev->dbgfs, dsscomp_dbg_comps, &dsscomp_debug_fops);
+ debugfs_create_file("gralloc", S_IRUGO,
+ cdev->dbgfs, dsscomp_dbg_gralloc, &dsscomp_debug_fops);
+#ifdef CONFIG_DSSCOMP_DEBUG_LOG
+ debugfs_create_file("log", S_IRUGO,
+ cdev->dbgfs, dsscomp_dbg_events, &dsscomp_debug_fops);
+#endif
+ }
+
+ r = omapdss_compat_init();
+ if (r) {
+ pr_err("dsscomp: compatibility mode not initialized");
+ return r;
+ }
+
+ cdev->pdev = &pdev->dev;
+ platform_set_drvdata(pdev, cdev);
+
+ pr_info("dsscomp: initializing.\n");
+
+ fill_cache(cdev);
+ fill_platform_info(cdev);
+
+
+ node = of_find_node_by_name(NULL, "display_layout");
+ if (node) {
+ of_property_read_u32(node, "ti,num_displays",
+ &num_displays);
+ }
+
+ memset(&display_layout_data, 0x00, sizeof(display_layout_data));
+ memset(&dsscomp_config, 0x00, sizeof(dsscomp_config));
+ memset(&omaplfb_plat_data, 0x00, sizeof(omaplfb_plat_data));
+ memset(&fb_pdata, 0x00, sizeof(fb_pdata));
+
+ display_layout_data.num_devices = num_displays;
+ display_layout_data.devices = cdev->displays;
+ display_layout_data.default_device = cdev->displays[0];
+ dsscomp_config.tiler1d_slotsz = SZ_16M;
+ omaplfb_plat_data.num_configs = num_displays;
+ omaplfb_plat_data.configs = NULL;
+ fb_pdata.mem_desc.region_cnt = num_displays;
+
+ omap_android_display_setup(&display_layout_data,
+ &dsscomp_config,
+ &omaplfb_plat_data,
+ &fb_pdata);
+
+ omapfb_set_platform_data(&fb_pdata);
+
+ /* initialize queues */
+ dsscomp_queue_init(cdev);
+ dsscomp_gralloc_init(cdev);
+
+ return 0;
+}
+
+static int dsscomp_remove(struct platform_device *pdev)
+{
+ struct dsscomp_dev *cdev = platform_get_drvdata(pdev);
+ misc_deregister(&cdev->dev);
+ debugfs_remove_recursive(cdev->dbgfs);
+ dsscomp_queue_exit();
+ dsscomp_gralloc_exit();
+ kfree(cdev);
+
+ return 0;
+}
+
+static struct platform_driver dsscomp_pdriver = {
+ .probe = dsscomp_probe,
+ .remove = dsscomp_remove,
+ .driver = { .name = MODULE_NAME_DSSCOMP, .owner = THIS_MODULE }
+};
+
+static int __init dsscomp_init(void)
+{
+ return platform_driver_register(&dsscomp_pdriver);
+}
+
+static void __exit dsscomp_exit(void)
+{
+ platform_driver_unregister(&dsscomp_pdriver);
+}
+
+#define DUMP_CHUNK 256
+static char dump_buf[64 * 1024];
+static void dsscomp_kdump(void)
+{
+ struct seq_file s = {
+ .buf = dump_buf,
+ .size = sizeof(dump_buf) - 1,
+ };
+ int i;
+
+#ifdef CONFIG_DSSCOMP_DEBUG_LOG
+ dsscomp_dbg_events(&s);
+#endif
+ dsscomp_dbg_comps(&s);
+ dsscomp_dbg_gralloc(&s);
+
+ for (i = 0; i < s.count; i += DUMP_CHUNK) {
+ if ((s.count - i) > DUMP_CHUNK) {
+ char c = s.buf[i + DUMP_CHUNK];
+ s.buf[i + DUMP_CHUNK] = 0;
+ pr_cont("%s", s.buf + i);
+ s.buf[i + DUMP_CHUNK] = c;
+ } else {
+ s.buf[s.count] = 0;
+ pr_cont("%s", s.buf + i);
+ }
+ }
+}
+EXPORT_SYMBOL(dsscomp_kdump);
+
+MODULE_LICENSE("GPL v2");
+module_init(dsscomp_init);
+module_exit(dsscomp_exit);
diff --git a/drivers/video/omap2/dsscomp/dsscomp.h b/drivers/video/omap2/dsscomp/dsscomp.h
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * linux/drivers/video/omap2/dsscomp/base.c
+ *
+ * DSS Composition basic operation support
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _DSSCOMP_H
+#define _DSSCOMP_H
+
+#include <linux/miscdevice.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#ifdef CONFIG_DSSCOMP_DEBUG_LOG
+#include <linux/hrtimer.h>
+#endif
+
+#define MAX_OVERLAYS 5
+#define MAX_MANAGERS 3
+#define MAX_DISPLAYS 4
+
+#define DEBUG_OVERLAYS (1 << 0)
+#define DEBUG_COMPOSITIONS (1 << 1)
+#define DEBUG_PHASES (1 << 2)
+#define DEBUG_WAITS (1 << 3)
+#define DEBUG_GRALLOC_PHASES (1 << 4)
+
+/*
+ * Utility macros
+ */
+#define ZERO(c) memset(&c, 0, sizeof(c))
+#define ZEROn(c, n) memset(c, 0, sizeof(*c) * n)
+#define DEV(c) (c->dev.this_device)
+
+/**
+ * DSS Composition Device Driver
+ *
+ * @pdev: hook for platform device data
+ * @dev: misc device base
+ * @dbgfs: debugfs hook
+ */
+struct dsscomp_dev {
+ struct device *pdev;
+ struct miscdevice dev;
+ struct dentry *dbgfs;
+
+ /* cached DSS objects */
+ u32 num_ovls;
+ struct omap_overlay *ovls[MAX_OVERLAYS];
+ u32 num_mgrs;
+ struct omap_overlay_manager *mgrs[MAX_MANAGERS];
+ u32 num_displays;
+ struct omap_dss_device *displays[MAX_DISPLAYS];
+ struct notifier_block state_notifiers[MAX_DISPLAYS];
+};
+
+extern int debug;
+
+#ifdef CONFIG_DEBUG_FS
+extern struct mutex dbg_mtx;
+extern struct list_head dbg_comps;
+#define DO_IF_DEBUG_FS(cmd) { \
+ mutex_lock(&dbg_mtx); \
+ cmd; \
+ mutex_unlock(&dbg_mtx); \
+}
+#else
+#define DO_IF_DEBUG_FS(cmd)
+#endif
+
+enum dsscomp_state {
+ DSSCOMP_STATE_ACTIVE = 0xAC54156E,
+ DSSCOMP_STATE_APPLYING = 0xB554C591,
+ DSSCOMP_STATE_APPLIED = 0xB60504C1,
+ DSSCOMP_STATE_PROGRAMMED = 0xC0520652,
+ DSSCOMP_STATE_DISPLAYED = 0xD15504CA,
+};
+
+struct dsscomp {
+ enum dsscomp_state state;
+ /*
+ * :TRICKY: before applying, overlays used in a composition are stored
+ * in ovl_mask and the other masks are empty. Once composition is
+ * applied, blank is set to see if all overlays are to be disabled on
+ * this composition, any disabled overlays in the composition are set in
+ * ovl_dmask, and ovl_mask is updated to include ALL overlays that are
+ * actually on the display - even if they are not part of the
+ * composition. The reason: we use ovl_mask to see if an overlay is used
+ * or planned to be used on a manager. We update ovl_mask when
+ * composition is programmed (removing the disabled overlays).
+ */
+ bool blank; /* true if all overlays are to be disabled */
+ u32 ovl_mask; /* overlays used on this frame */
+ u32 ovl_dmask; /* overlays disabled on this frame */
+ u32 ix; /* manager index that this frame is on */
+ struct dsscomp_setup_mgr_data frm;
+ struct dss2_ovl_info ovls[5];
+ void (*extra_cb)(void *data, int status);
+ void *extra_cb_data;
+ bool must_apply; /* whether composition must be applied */
+
+#ifdef CONFIG_DEBUG_FS
+ struct list_head dbg_q;
+ u32 dbg_used;
+ struct {
+ u32 t, state;
+ } dbg_log[8];
+#endif
+};
+
+struct dsscomp_sync_obj {
+ int state;
+ int fd;
+ atomic_t refs;
+};
+
+/*
+ * Kernel interface
+ */
+int dsscomp_queue_init(struct dsscomp_dev *cdev);
+void dsscomp_queue_exit(void);
+void dsscomp_gralloc_init(struct dsscomp_dev *cdev);
+void dsscomp_gralloc_exit(void);
+int dsscomp_gralloc_queue_ioctl(struct dsscomp_setup_dispc_data *d);
+int dsscomp_wait(struct dsscomp_sync_obj *sync, enum dsscomp_wait_phase phase,
+ int timeout);
+int dsscomp_state_notifier(struct notifier_block *nb,
+ unsigned long arg, void *ptr);
+
+/* basic operation - if not using queues */
+int set_dss_ovl_info(struct dss2_ovl_info *oi);
+int set_dss_mgr_info(struct dss2_mgr_info *mi, struct omapdss_ovl_cb *cb);
+struct omap_overlay_manager *find_dss_mgr(int display_ix);
+void swap_rb_in_ovl_info(struct dss2_ovl_info *oi);
+void swap_rb_in_mgr_info(struct dss2_mgr_info *mi);
+
+static inline u32 tiler1d_slot_size(struct dsscomp_dev *cdev)
+{
+ struct dsscomp_platform_data *pdata;
+ pdata = (struct dsscomp_platform_data *)cdev->pdev->platform_data;
+ return pdata->tiler1d_slotsz;
+}
+
+/*
+ * Debug functions
+ */
+void dump_ovl_info(struct dsscomp_dev *cdev, struct dss2_ovl_info *oi);
+void dump_comp_info(struct dsscomp_dev *cdev, struct dsscomp_setup_mgr_data *d,
+ const char *phase);
+void dump_total_comp_info(struct dsscomp_dev *cdev,
+ struct dsscomp_setup_dispc_data *d,
+ const char *phase);
+const char *dsscomp_get_color_name(enum omap_color_mode m);
+
+void dsscomp_dbg_comps(struct seq_file *s);
+void dsscomp_dbg_gralloc(struct seq_file *s);
+
+#define log_state_str(s) (\
+ (s) == DSSCOMP_STATE_ACTIVE ? "ACTIVE" : \
+ (s) == DSSCOMP_STATE_APPLYING ? "APPLY'N" : \
+ (s) == DSSCOMP_STATE_APPLIED ? "APPLIED" : \
+ (s) == DSSCOMP_STATE_PROGRAMMED ? "PROGR'D" : \
+ (s) == DSSCOMP_STATE_DISPLAYED ? "DISPL'D" : "INVALID")
+
+#define log_status_str(ev) ( \
+ ((ev) & DSS_COMPLETION_CHANGED) ? "CHANGED" : \
+ (ev) == DSS_COMPLETION_DISPLAYED ? "DISPLAYED" : \
+ (ev) == DSS_COMPLETION_PROGRAMMED ? "PROGRAMMED" : \
+ (ev) == DSS_COMPLETION_TORN ? "TORN" : \
+ (ev) == DSS_COMPLETION_RELEASED ? "RELEASED" : \
+ ((ev) & DSS_COMPLETION_RELEASED) ? "ECLIPSED" : "???")
+
+#ifdef CONFIG_DSSCOMP_DEBUG_LOG
+extern struct dbg_event_t {
+ u32 ms, a1, a2, ix;
+ void *data;
+ const char *fmt;
+} dbg_events[128];
+extern u32 dbg_event_ix;
+
+void dsscomp_dbg_events(struct seq_file *s);
+#endif
+extern bool alpha_only;
+
+static inline
+void __log_event(u32 ix, u32 ms, void *data, const char *fmt, u32 a1, u32 a2)
+{
+#ifdef CONFIG_DSSCOMP_DEBUG_LOG
+ if (!ms)
+ ms = ktime_to_ms(ktime_get());
+ dbg_events[dbg_event_ix].ms = ms;
+ dbg_events[dbg_event_ix].data = data;
+ dbg_events[dbg_event_ix].fmt = fmt;
+ dbg_events[dbg_event_ix].a1 = a1;
+ dbg_events[dbg_event_ix].a2 = a2;
+ dbg_events[dbg_event_ix].ix = ix;
+ dbg_event_ix = (dbg_event_ix + 1) % ARRAY_SIZE(dbg_events);
+#endif
+}
+
+#define log_event(ix, ms, data, fmt, a1, a2) \
+ DO_IF_DEBUG_FS(__log_event(ix, ms, data, fmt, a1, a2))
+
+#endif
diff --git a/drivers/video/omap2/dsscomp/gralloc.c b/drivers/video/omap2/dsscomp/gralloc.c
--- /dev/null
@@ -0,0 +1,801 @@
+/*
+ * drivers/video/omap2/dsscomp/gralloc.c
+ *
+ * DSS Composition gralloc file
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include "../../../drivers/gpu/drm/omapdrm/omap_dmm_tiler.h"
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+#include "dsscomp.h"
+#include "tiler-utils.h"
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+static bool blanked;
+static bool presentation_mode;
+
+#define NUM_TILER1D_SLOTS 2
+#define MAX_NUM_TILER1D_SLOTS 4
+
+static struct tiler1d_slot {
+ struct list_head q;
+ struct tiler_block *block_handle;
+ u32 phys;
+ u32 size;
+ u32 *page_map;
+ short id;
+} slots[MAX_NUM_TILER1D_SLOTS];
+static struct list_head free_slots;
+static struct dsscomp_dev *cdev;
+static DEFINE_MUTEX(mtx);
+static struct semaphore free_slots_sem =
+ __SEMAPHORE_INITIALIZER(free_slots_sem, 0);
+
+/* gralloc composition sync object */
+struct dsscomp_gralloc_t {
+ void (*cb_fn)(void *, int);
+ void *cb_arg;
+ struct list_head q;
+ struct list_head slots;
+ atomic_t refs;
+ bool early_callback;
+ bool programmed;
+};
+
+/* queued gralloc compositions */
+static LIST_HEAD(flip_queue);
+
+static u32 ovl_use_mask[MAX_MANAGERS];
+
+static inline bool needs_split(struct tiler1d_slot *slot)
+{
+ return slot->size == tiler1d_slot_size(cdev) >> PAGE_SHIFT;
+}
+
+static struct tiler1d_slot *split_slots(struct tiler1d_slot *slot);
+static struct tiler1d_slot *merge_slots(struct tiler1d_slot *slot);
+static struct tiler1d_slot *alloc_tiler_slot(void);
+
+static void unpin_tiler_blocks(struct list_head *slots)
+{
+ struct tiler1d_slot *slot;
+
+ /* unpin any tiler memory */
+ list_for_each_entry(slot, slots, q) {
+ tiler_unpin(slot->block_handle);
+ up(&free_slots_sem);
+ }
+
+ /* free tiler slots */
+ list_splice_init(slots, &free_slots);
+}
+
+static void dsscomp_gralloc_cb(void *data, int status)
+{
+ struct dsscomp_gralloc_t *gsync = data, *gsync_;
+ bool early_cbs = true;
+ LIST_HEAD(done);
+
+ mutex_lock(&mtx);
+ if (gsync->early_callback && status == DSS_COMPLETION_PROGRAMMED)
+ gsync->programmed = true;
+
+ if (status & DSS_COMPLETION_RELEASED) {
+ if (atomic_dec_and_test(&gsync->refs))
+ unpin_tiler_blocks(&gsync->slots);
+
+ log_event(0, 0, gsync, "--refs=%d on %s",
+ atomic_read(&gsync->refs),
+ (u32) log_status_str(status));
+ }
+
+ /* get completed list items in order, if any */
+ list_for_each_entry_safe(gsync, gsync_, &flip_queue, q) {
+ if (gsync->cb_fn) {
+ early_cbs &= gsync->early_callback && gsync->programmed;
+ if (early_cbs) {
+ gsync->cb_fn(gsync->cb_arg, 1);
+ gsync->cb_fn = NULL;
+ }
+ }
+ if (gsync->refs.counter && gsync->cb_fn)
+ break;
+ if (gsync->refs.counter == 0)
+ list_move_tail(&gsync->q, &done);
+ }
+ mutex_unlock(&mtx);
+
+ /* call back for completed composition with mutex unlocked */
+ list_for_each_entry_safe(gsync, gsync_, &done, q) {
+ if (debug & DEBUG_GRALLOC_PHASES)
+ dev_info(DEV(cdev), "[%p] completed flip\n", gsync);
+
+ log_event(0, 0, gsync, "calling %pf [%p]", (u32)gsync->cb_fn,
+ (u32)gsync->cb_arg);
+
+ if (gsync->cb_fn)
+ gsync->cb_fn(gsync->cb_arg, 1);
+ kfree(gsync);
+ }
+}
+
+/* This is just test code for now that does the setup + apply.
+ It still uses userspace virtual addresses, but maps non
+ TILER buffers into 1D */
+int dsscomp_gralloc_queue_ioctl(struct dsscomp_setup_dispc_data *d)
+{
+ struct tiler_pa_info *pas[MAX_OVERLAYS];
+ s32 ret;
+ u32 i;
+
+ /* convert virtual addresses to physical and get tiler pa infos */
+ for (i = 0; i < d->num_ovls; i++) {
+ struct dss2_ovl_info *oi = d->ovls + i;
+ u32 addr = (u32) oi->address;
+
+ pas[i] = NULL;
+
+ /* only supporting DIRECT buffer types */
+
+ /* assume virtual NV12 for now */
+ if (oi->cfg.color_mode == OMAP_DSS_COLOR_NV12)
+ oi->uv = tiler_virt2phys(addr +
+ oi->cfg.height * oi->cfg.stride);
+ else
+ oi->uv = 0;
+ oi->ba = tiler_virt2phys(addr);
+
+ /* map non-TILER buffers to 1D */
+ if (oi->ba && !is_tiler_addr(oi->ba))
+ pas[i] = user_block_to_pa(addr & PAGE_MASK,
+ PAGE_ALIGN(oi->cfg.height * oi->cfg.stride +
+ (addr & ~PAGE_MASK)) >> PAGE_SHIFT);
+ }
+ ret = dsscomp_gralloc_queue(d, pas, false, NULL, NULL);
+ for (i = 0; i < d->num_ovls; i++)
+ tiler_pa_free(pas[i]);
+ return ret;
+}
+
+static bool dsscomp_is_any_device_active(void)
+{
+ struct omap_dss_device *dssdev;
+ u32 display_ix;
+
+ /* We have to also check for device active in case HWC logic has
+ * not yet started for boot logo.
+ */
+ for (display_ix = 0 ; display_ix < cdev->num_displays ; display_ix++) {
+ dssdev = cdev->displays[display_ix];
+ if (dssdev && dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+ return true;
+ }
+ return false;
+}
+
+int dsscomp_gralloc_queue(struct dsscomp_setup_dispc_data *d,
+ struct tiler_pa_info **pas,
+ bool early_callback,
+ void (*cb_fn)(void *, int), void *cb_arg)
+{
+ u32 i;
+ int r = 0;
+ struct omap_dss_device *dev;
+ struct omap_overlay_manager *mgr;
+ static DEFINE_MUTEX(local_mtx);
+ struct dsscomp *comp[MAX_MANAGERS];
+ u32 ovl_new_use_mask[MAX_MANAGERS];
+ u32 mgr_set_mask = 0;
+ u32 ovl_set_mask = 0;
+ struct tiler1d_slot *slot = NULL;
+ u32 slot_used = 0;
+#ifdef CONFIG_DEBUG_FS
+ u32 ms = ktime_to_ms(ktime_get());
+#endif
+ u32 channels[MAX_MANAGERS], ch;
+ int skip;
+ struct dsscomp_gralloc_t *gsync;
+ struct dss2_rect_t win = { .w = 0 };
+
+ /* reserve tiler areas if not already done so */
+ dsscomp_gralloc_init(cdev);
+
+ dump_total_comp_info(cdev, d, "queue");
+ for (i = 0; i < d->num_ovls; i++)
+ dump_ovl_info(cdev, d->ovls + i);
+
+ mutex_lock(&local_mtx);
+
+ mutex_lock(&mtx);
+
+ /* create sync object with 1 temporary ref */
+ gsync = kzalloc(sizeof(*gsync), GFP_KERNEL);
+ gsync->cb_arg = cb_arg;
+ gsync->cb_fn = cb_fn;
+ gsync->refs.counter = 1;
+ gsync->early_callback = early_callback;
+ INIT_LIST_HEAD(&gsync->slots);
+ list_add_tail(&gsync->q, &flip_queue);
+ if (debug & DEBUG_GRALLOC_PHASES)
+ dev_info(DEV(cdev), "[%p] queuing flip\n", gsync);
+
+ log_event(0, ms, gsync, "new in %pf (refs=1)",
+ (u32)dsscomp_gralloc_queue, 0);
+
+ /* ignore frames while we are blanked */
+ skip = blanked;
+ if (skip && (debug & DEBUG_PHASES))
+ dev_info(DEV(cdev), "[%p,%08x] ignored\n", gsync, d->sync_id);
+
+ /* mark blank frame by NULL tiler pa pointer */
+ if (!skip && pas == NULL)
+ blanked = true;
+
+ mutex_unlock(&mtx);
+
+ d->num_mgrs = min_t(u16, d->num_mgrs, ARRAY_SIZE(d->mgrs));
+ d->num_ovls = min_t(u16, d->num_ovls, ARRAY_SIZE(d->ovls));
+
+ memset(comp, 0, sizeof(comp));
+ memset(ovl_new_use_mask, 0, sizeof(ovl_new_use_mask));
+
+ if (skip || !dsscomp_is_any_device_active())
+ goto skip_comp;
+
+ d->mode = DSSCOMP_SETUP_DISPLAY;
+
+ /* mark managers we are using */
+ for (i = 0; i < d->num_mgrs; i++) {
+ /* verify display is valid & connected, ignore if not */
+ if (d->mgrs[i].ix >= cdev->num_displays)
+ continue;
+ dev = cdev->displays[d->mgrs[i].ix];
+ if (!dev) {
+ dev_warn(DEV(cdev), "failed to get display%d\n",
+ d->mgrs[i].ix);
+ continue;
+ }
+ mgr = dev->output->manager;
+ if (!mgr) {
+ dev_warn(DEV(cdev), "no manager for display%d\n",
+ d->mgrs[i].ix);
+ continue;
+ }
+ ch = mgr->id;
+ channels[i] = ch;
+ mgr_set_mask |= 1 << ch;
+
+ /* swap red & blue if requested */
+ if (d->mgrs[i].swap_rb)
+ swap_rb_in_mgr_info(d->mgrs + i);
+ }
+
+ /* create dsscomp objects for set managers (including active ones) */
+ for (ch = 0; ch < MAX_MANAGERS; ch++) {
+ if (!(mgr_set_mask & (1 << ch)))
+ continue;
+
+ mgr = cdev->mgrs[ch];
+
+ comp[ch] = dsscomp_new(mgr);
+ if (IS_ERR(comp[ch])) {
+ comp[ch] = NULL;
+ dev_warn(DEV(cdev), "failed to get composition on %s\n",
+ mgr->name);
+ continue;
+ }
+
+ comp[ch]->must_apply = true;
+ r = dsscomp_setup(comp[ch], d->mode, win);
+ if (r)
+ dev_err(DEV(cdev), "failed to setup comp (%d)\n", r);
+ }
+
+ /* configure manager data from gralloc composition */
+ for (i = 0; i < d->num_mgrs; i++) {
+ ch = channels[i];
+ r = dsscomp_set_mgr(comp[ch], d->mgrs + i);
+ if (r)
+ dev_err(DEV(cdev), "failed to set mgr%d (%d)\n", ch, r);
+ }
+
+ /* NOTE: none of the dsscomp sets should fail as composition is new */
+ for (i = 0; i < d->num_ovls; i++) {
+ struct dss2_ovl_info *oi = d->ovls + i;
+ u32 size;
+ int j;
+ for (j = 0; j < d->num_mgrs; j++)
+ if (d->mgrs[j].ix == oi->cfg.mgr_ix) {
+ /* swap red & blue if requested */
+ if (d->mgrs[j].swap_rb)
+ swap_rb_in_ovl_info(d->ovls + i);
+ break;
+ }
+
+ if (j == d->num_mgrs) {
+ dev_err(DEV(cdev), "invalid manager %d for ovl%d\n",
+ ch, oi->cfg.ix);
+ continue;
+ }
+
+ /* skip overlays on compositions we could not create */
+ ch = channels[j];
+ if (!comp[ch])
+ continue;
+ /* copy prior overlay to avoid mapping layers twice to 1D */
+ if (oi->addressing == OMAP_DSS_BUFADDR_OVL_IX) {
+ unsigned int j = oi->ba;
+ if (j >= i || !d->ovls[j].cfg.enabled) {
+ WARN(1, "Invalid clone layer (%u)", j);
+ goto skip_buffer;
+ }
+
+ oi->ba = d->ovls[j].ba;
+ oi->uv = d->ovls[j].uv;
+ goto skip_map1d;
+ } else if (oi->addressing == OMAP_DSS_BUFADDR_FB) {
+ /* get fb */
+ int fb_ix = (oi->ba >> 28);
+ int fb_uv_ix = (oi->uv >> 28);
+ struct fb_info *fbi = NULL, *fbi_uv = NULL;
+ size_t hs_size = oi->cfg.height * oi->cfg.stride;
+ if (fb_ix >= num_registered_fb ||
+ (oi->cfg.color_mode == OMAP_DSS_COLOR_NV12 &&
+ fb_uv_ix >= num_registered_fb)) {
+ WARN(1, "display has no framebuffer");
+ goto skip_buffer;
+ }
+
+ fbi_uv = registered_fb[fb_ix];
+ fbi = fbi_uv;
+ if (oi->cfg.color_mode == OMAP_DSS_COLOR_NV12)
+ fbi_uv = registered_fb[fb_uv_ix];
+
+ if (hs_size + oi->ba > fbi->fix.smem_len ||
+ (oi->cfg.color_mode == OMAP_DSS_COLOR_NV12 &&
+ (hs_size >> 1) + oi->uv > fbi_uv->fix.smem_len)) {
+ WARN(1, "image outside of framebuffer memory");
+ goto skip_buffer;
+ }
+
+ oi->ba += fbi->fix.smem_start;
+ oi->uv += fbi_uv->fix.smem_start;
+ goto skip_map1d;
+ } else if (oi->addressing != OMAP_DSS_BUFADDR_DIRECT) {
+ goto skip_buffer;
+ }
+
+ /* map non-TILER buffers to 1D */
+
+ /* skip 2D and disabled layers */
+ if (!pas[i] || !oi->cfg.enabled)
+ goto skip_map1d;
+
+ if (!slot) {
+ mutex_lock(&mtx);
+ /* separate comp for tv means presentation mode */
+ if (d->num_mgrs == 1 && d->mgrs[0].ix == 1)
+ presentation_mode = true;
+ else if (d->num_mgrs == 2 ||
+ cdev->mgrs[1]->output->device->state !=
+ OMAP_DSS_DISPLAY_ACTIVE)
+ presentation_mode = false;
+
+ slot = alloc_tiler_slot();
+ if (IS_ERR_OR_NULL(slot)) {
+ dev_warn(DEV(cdev), "could not obtain "
+ "tiler slot");
+ slot = NULL;
+ mutex_unlock(&mtx);
+ goto skip_buffer;
+ }
+ list_move(&slot->q, &gsync->slots);
+ mutex_unlock(&mtx);
+ }
+
+ size = oi->cfg.stride * oi->cfg.height;
+ if (oi->cfg.color_mode == OMAP_DSS_COLOR_NV12)
+ size += size >> 2;
+ size = DIV_ROUND_UP(size, PAGE_SIZE);
+
+ if (slot_used + size > slot->size) {
+ dev_err(DEV(cdev), "tiler slot not big enough for "
+ "frame %d + %d > %d", slot_used, size,
+ slot->size);
+ goto skip_buffer;
+ }
+
+ /* "map" into TILER 1D - will happen after loop */
+ oi->ba = slot->phys + (slot_used << PAGE_SHIFT) +
+ (oi->ba & ~PAGE_MASK);
+ if (oi->cfg.color_mode == OMAP_DSS_COLOR_NV12)
+ oi->uv = oi->ba + oi->cfg.stride * oi->cfg.height;
+ memcpy(slot->page_map + slot_used, pas[i]->mem,
+ sizeof(*slot->page_map) * size);
+ slot_used += size;
+ goto skip_map1d;
+
+skip_buffer:
+ oi->cfg.enabled = false;
+skip_map1d:
+
+ if (oi->cfg.enabled)
+ ovl_new_use_mask[ch] |= 1 << oi->cfg.ix;
+
+ r = dsscomp_set_ovl(comp[ch], oi);
+ if (r)
+ dev_err(DEV(cdev), "failed to set ovl%d (%d)\n",
+ oi->cfg.ix, r);
+ else
+ ovl_set_mask |= 1 << oi->cfg.ix;
+ }
+
+ if (slot && slot_used) {
+ r = tiler_pin_phys(slot->block_handle, slot->page_map,
+ slot_used);
+ if (r)
+ dev_err(DEV(cdev), "failed to pin %d pages into"
+ " %d-pg slots (%d)\n", slot_used,
+ tiler1d_slot_size(cdev) >> PAGE_SHIFT, r);
+ }
+
+ for (ch = 0; ch < MAX_MANAGERS; ch++) {
+ /* disable all overlays not specifically set from prior frame */
+ u32 mask = ovl_use_mask[ch] & ~ovl_set_mask;
+
+ if (!comp[ch])
+ continue;
+
+ while (mask) {
+ struct dss2_ovl_info oi = {
+ .cfg.zonly = true,
+ .cfg.enabled = false,
+ .cfg.ix = fls(mask) - 1,
+ };
+ dsscomp_set_ovl(comp[ch], &oi);
+ mask &= ~(1 << oi.cfg.ix);
+ }
+
+ /* associate dsscomp objects with this gralloc composition */
+ comp[ch]->extra_cb = dsscomp_gralloc_cb;
+ comp[ch]->extra_cb_data = gsync;
+ atomic_inc(&gsync->refs);
+ log_event(0, ms, gsync, "++refs=%d for [%p]",
+ atomic_read(&gsync->refs), (u32) comp[ch]);
+
+ r = dsscomp_delayed_apply(comp[ch]);
+ if (r)
+ dev_err(DEV(cdev), "failed to apply comp (%d)\n", r);
+ else
+ ovl_use_mask[ch] = ovl_new_use_mask[ch];
+ }
+skip_comp:
+ /* release sync object ref - this completes unapplied compositions */
+ dsscomp_gralloc_cb(gsync, DSS_COMPLETION_RELEASED);
+
+ mutex_unlock(&local_mtx);
+
+ return r;
+}
+EXPORT_SYMBOL(dsscomp_gralloc_queue);
+
+#ifdef CONFIG_EARLYSUSPEND
+static int blank_complete;
+static DECLARE_WAIT_QUEUE_HEAD(early_suspend_wq);
+
+static void dsscomp_early_suspend_cb(void *data, int status)
+{
+ blank_complete = true;
+ wake_up(&early_suspend_wq);
+}
+
+static void dsscomp_early_suspend(struct early_suspend *h)
+{
+ struct dsscomp_setup_dispc_data d = {
+ .num_mgrs = 0,
+ };
+
+ int err, mgr_ix;
+
+ pr_info("DSSCOMP: %s\n", __func__);
+
+ /*dsscomp_gralloc_queue() expects all blanking mgrs set up in comp */
+ for (mgr_ix = 0 ; mgr_ix < cdev->num_mgrs ; mgr_ix++) {
+ struct omap_dss_device *dssdev = cdev->mgrs[mgr_ix]->device;
+ if (dssdev && dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+ d.num_mgrs++;
+ d.mgrs[mgr_ix].ix = mgr_ix;
+ d.mgrs[mgr_ix].alpha_blending = true;
+ }
+ }
+
+ /* use gralloc queue as we need to blank all screens */
+ blank_complete = false;
+ dsscomp_gralloc_queue(&d, NULL, true, dsscomp_early_suspend_cb, NULL);
+
+ /* wait until composition is displayed */
+ err = wait_event_timeout(early_suspend_wq, blank_complete,
+ msecs_to_jiffies(500));
+ if (err == 0)
+ pr_warn("DSSCOMP: timeout blanking screen\n");
+ else
+ pr_info("DSSCOMP: blanked screen\n");
+}
+
+static void dsscomp_late_resume(struct early_suspend *h)
+{
+ pr_info("DSSCOMP: %s\n", __func__);
+ blanked = false;
+}
+
+static struct early_suspend early_suspend_info = {
+ .suspend = dsscomp_early_suspend,
+ .resume = dsscomp_late_resume,
+ .level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
+};
+#endif
+
+void dsscomp_dbg_gralloc(struct seq_file *s)
+{
+#ifdef CONFIG_DEBUG_FS
+ struct dsscomp_gralloc_t *g;
+ struct tiler1d_slot *t;
+ struct dsscomp *c;
+#ifdef CONFIG_DSSCOMP_DEBUG_LOG
+ int i;
+#endif
+
+ mutex_lock(&dbg_mtx);
+ seq_printf(s, "ACTIVE GRALLOC FLIPS\n\n");
+ list_for_each_entry(g, &flip_queue, q) {
+ char *sep = "";
+ seq_printf(s, " [%p] (refs=%d)\n"
+ " slots=[", g, atomic_read(&g->refs));
+ list_for_each_entry(t, &g->slots, q) {
+ seq_printf(s, "%s%08x", sep, t->phys);
+ sep = ", ";
+ }
+ seq_printf(s, "]\n cmdcb=[%08x] ", (u32) g->cb_arg);
+ if (g->cb_fn)
+ seq_printf(s, "%pf\n\n ", g->cb_fn);
+ else
+ seq_printf(s, "(called)\n\n ");
+
+ list_for_each_entry(c, &dbg_comps, dbg_q) {
+ if (c->extra_cb && c->extra_cb_data == g)
+ seq_printf(s, "| %8s ",
+ cdev->mgrs[c->ix]->name);
+ }
+ seq_printf(s, "\n ");
+ list_for_each_entry(c, &dbg_comps, dbg_q) {
+ if (c->extra_cb && c->extra_cb_data == g)
+ seq_printf(s, "| [%08x] %7s ", (u32) c,
+ log_state_str(c->state));
+ }
+#ifdef CONFIG_DSSCOMP_DEBUG_LOG
+ for (i = 0; i < ARRAY_SIZE(c->dbg_log); i++) {
+ int go = false;
+ seq_printf(s, "\n ");
+ list_for_each_entry(c, &dbg_comps, dbg_q) {
+ if (!c->extra_cb || c->extra_cb_data != g)
+ continue;
+ if (i < c->dbg_used) {
+ u32 dbg_t = c->dbg_log[i].t;
+ u32 state = c->dbg_log[i].state;
+ seq_printf(s, "| % 6d.%03d %7s ",
+ dbg_t / 1000,
+ dbg_t % 1000,
+ log_state_str(state));
+ go |= c->dbg_used > i + 1;
+ } else {
+ seq_printf(s, "%-21s", "|");
+ }
+ }
+ if (!go)
+ break;
+ }
+#endif
+ seq_printf(s, "\n\n");
+ }
+ seq_printf(s, "\n");
+ mutex_unlock(&dbg_mtx);
+#endif
+}
+
+void dsscomp_gralloc_init(struct dsscomp_dev *cdev_)
+{
+ int i;
+
+ if (!cdev_)
+ return;
+
+ /* save at least cdev pointer */
+ if (!cdev) {
+ cdev = cdev_;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ register_early_suspend(&early_suspend_info);
+#endif
+ }
+
+ if (!free_slots.next) {
+ INIT_LIST_HEAD(&free_slots);
+ for (i = 0; i < MAX_NUM_TILER1D_SLOTS; i++)
+ slots[i].id = -1;
+
+ for (i = 0; i < NUM_TILER1D_SLOTS; i++) {
+ struct tiler_block *block_handle =
+ tiler_reserve_1d(tiler1d_slot_size(cdev_));
+ if (IS_ERR_OR_NULL(block_handle)) {
+ pr_err("could not allocate tiler block\n");
+ break;
+ }
+ slots[i].block_handle = block_handle;
+ slots[i].phys = tiler_ssptr(block_handle);
+ slots[i].size = tiler1d_slot_size(cdev_) >> PAGE_SHIFT;
+ slots[i].page_map = vmalloc(sizeof(*slots[i].page_map) *
+ slots[i].size);
+ if (!slots[i].page_map) {
+ pr_err("could not allocate page_map\n");
+ tiler_unpin(block_handle);
+ break;
+ }
+ slots[i].id = i;
+ list_add(&slots[i].q, &free_slots);
+ up(&free_slots_sem);
+ }
+ /* reset free_slots if no TILER memory could be reserved */
+ if (!i)
+ ZERO(free_slots);
+ }
+}
+
+static struct tiler1d_slot *alloc_tiler_slot(void)
+{
+ struct tiler1d_slot *slot, *ret;
+ if (down_timeout(&free_slots_sem,
+ msecs_to_jiffies(100))) {
+ return ERR_PTR(-ETIME);
+ }
+ slot = list_first_entry(&free_slots, typeof(*slot), q);
+ if (presentation_mode && needs_split(slot)) {
+ ret = split_slots(slot);
+ if (IS_ERR_OR_NULL(ret))
+ goto err;
+ dev_dbg(DEV(cdev),
+ "slot split, size %u block 0x%x\n",
+ slot->size, slot->phys);
+ } else if (!presentation_mode && !needs_split(slot)) {
+ ret = merge_slots(slot);
+ if (IS_ERR_OR_NULL(ret))
+ goto err;
+ dev_dbg(DEV(cdev),
+ "slot merged, size %u ptr 0x%x\n",
+ slot->size, slot->phys);
+ }
+
+ return slot;
+err:
+ up(&free_slots_sem);
+ return ret;
+}
+
+static struct tiler1d_slot *merge_slots(struct tiler1d_slot *slot)
+{
+ struct tiler1d_slot *slot2free;
+ u32 new_size = tiler1d_slot_size(cdev);
+
+ list_for_each_entry(slot2free, &free_slots, q)
+ if (!needs_split(slot2free) && slot2free != slot)
+ break;
+
+ if (&slot2free->q == &free_slots || slot2free->id == -1) {
+ dev_err(DEV(cdev), "%s: no free slot to megre\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ down(&free_slots_sem);
+ list_del(&slot2free->q);
+
+ dev_dbg(DEV(cdev), "%s: merging with %d id\n", __func__,
+ slot2free->id);
+ /*FIXME: potentially unsafe, as tiler1d space
+ * might be overtaken before we claim it again.
+ * Will be fixed later with tiler slot splitting API
+ */
+ tiler_release(slot->block_handle);
+
+ tiler_release(slot2free->block_handle);
+
+ slot->size = new_size >> PAGE_SHIFT;
+ slot->block_handle = tiler_reserve_1d(new_size);
+
+ if (IS_ERR_OR_NULL(slot->block_handle)) {
+ dev_err(DEV(cdev), "%s: failed to allocate slot\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ slot->phys = tiler_ssptr(slot->block_handle);
+
+ vfree(slot2free->page_map);
+ slot2free->id = -1;
+
+ return slot;
+}
+
+static struct tiler1d_slot *split_slots(struct tiler1d_slot *slot)
+{
+ int i;
+ u32 new_size = tiler1d_slot_size(cdev)/2;
+
+ /*FIXME: potentially unsafe, as tiler1d space
+ * might be overtaken before we claim it again.
+ * Will be fixed later with tiler slot splitting API
+ */
+ tiler_release(slot->block_handle);
+ for (i = 0; i < MAX_NUM_TILER1D_SLOTS; i++)
+ if (slots[i].id == -1)
+ break;
+
+ if (i == MAX_NUM_TILER1D_SLOTS) {
+ dev_err(DEV(cdev), "%s: all slots allocated\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ dev_dbg(DEV(cdev), "%s: splitting to %d id\n", __func__, i);
+ slot->size = slots[i].size = new_size >> PAGE_SHIFT;
+ slots[i].page_map = vmalloc(sizeof(*slots[i].page_map) *
+ slots[i].size*2);
+ slot->block_handle = tiler_reserve_1d(new_size);
+ slots[i].block_handle = tiler_reserve_1d(new_size);
+
+ if (IS_ERR_OR_NULL(slot->block_handle) ||
+ IS_ERR_OR_NULL(slots[i].block_handle)) {
+ dev_err(DEV(cdev), "%s: failed to allocate slot\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ slot->phys = tiler_ssptr(slot->block_handle);
+ slots[i].phys = tiler_ssptr(slots[i].block_handle);
+ slots[i].id = i;
+ list_add(&slots[i].q, &free_slots);
+ up(&free_slots_sem);
+
+ return &slots[i];
+}
+
+void dsscomp_gralloc_exit(void)
+{
+ struct tiler1d_slot *slot;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&early_suspend_info);
+#endif
+
+ list_for_each_entry(slot, &free_slots, q) {
+ vfree(slot->page_map);
+ tiler_unpin(slot->block_handle);
+ }
+ INIT_LIST_HEAD(&free_slots);
+}
diff --git a/drivers/video/omap2/dsscomp/queue.c b/drivers/video/omap2/dsscomp/queue.c
--- /dev/null
@@ -0,0 +1,830 @@
+/*
+ * linux/drivers/video/omap2/dsscomp/queue.c
+ *
+ * DSS Composition queueing support
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/ratelimit.h>
+
+#include <video/omapdss.h>
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+
+#include <linux/debugfs.h>
+
+#include "dsscomp.h"
+/* queue state */
+
+static DEFINE_MUTEX(mtx);
+
+/* free overlay structs */
+struct maskref {
+ u32 mask;
+ u32 refs[MAX_OVERLAYS];
+};
+
+static struct {
+ struct workqueue_struct *apply_workq;
+
+ u32 ovl_mask; /* overlays used on this display */
+ struct maskref ovl_qmask; /* overlays queued to this display */
+ bool blanking;
+} mgrq[MAX_MANAGERS];
+
+static struct workqueue_struct *cb_wkq; /* callback work queue */
+static struct dsscomp_dev *cdev;
+
+#ifdef CONFIG_DEBUG_FS
+LIST_HEAD(dbg_comps);
+DEFINE_MUTEX(dbg_mtx); /* Mutex for debug operations */
+#endif
+
+#ifdef CONFIG_DSSCOMP_DEBUG_LOG
+struct dbg_event_t dbg_events[128];
+u32 dbg_event_ix;
+#endif
+
+static inline void __log_state(struct dsscomp *c, void *fn, u32 ev)
+{
+#ifdef CONFIG_DSSCOMP_DEBUG_LOG
+ if (c->dbg_used < ARRAY_SIZE(c->dbg_log)) {
+ u32 t = (u32) ktime_to_ms(ktime_get());
+ c->dbg_log[c->dbg_used].t = t;
+ c->dbg_log[c->dbg_used++].state = c->state;
+ __log_event(20 * c->ix + 20, t, c, ev ? "%pf on %s" : "%pf",
+ (u32) fn, (u32) log_status_str(ev));
+ }
+#endif
+}
+#define log_state(c, fn, ev) DO_IF_DEBUG_FS(__log_state(c, fn, ev))
+
+static inline void maskref_incbit(struct maskref *om, u32 ix)
+{
+ om->refs[ix]++;
+ om->mask |= 1 << ix;
+}
+
+static void maskref_decmask(struct maskref *om, u32 mask)
+{
+ while (mask) {
+ u32 ix = fls(mask) - 1, m = 1 << ix;
+ if (!--om->refs[ix])
+ om->mask &= ~m;
+ mask &= ~m;
+ }
+}
+
+/*
+ * ===========================================================================
+ * EXIT
+ * ===========================================================================
+ */
+
+/* Initialize queue structures, and set up state of the displays */
+int dsscomp_queue_init(struct dsscomp_dev *cdev_)
+{
+ u32 i, j;
+ cdev = cdev_;
+
+ if (ARRAY_SIZE(mgrq) < cdev->num_mgrs)
+ return -EINVAL;
+
+ ZERO(mgrq);
+ for (i = 0; i < cdev->num_mgrs; i++) {
+ struct omap_overlay_manager *mgr;
+ mgrq[i].apply_workq =
+ create_singlethread_workqueue("dsscomp_apply");
+ if (!mgrq[i].apply_workq)
+ goto error;
+
+ /* record overlays on this display */
+ mgr = cdev->mgrs[i];
+ for (j = 0; j < cdev->num_ovls; j++) {
+ if (cdev->ovls[j]->is_enabled(cdev->ovls[j]) &&
+ mgr &&
+ cdev->ovls[j]->manager == mgr)
+ mgrq[i].ovl_mask |= 1 << j;
+ }
+ }
+
+ cb_wkq = create_singlethread_workqueue("dsscomp_cb");
+ if (!cb_wkq)
+ goto error;
+
+ return 0;
+error:
+ while (i--)
+ destroy_workqueue(mgrq[i].apply_workq);
+ return -ENOMEM;
+}
+
+/* get display index from manager */
+static u32 get_display_ix(struct omap_overlay_manager *mgr)
+{
+ u32 i;
+
+ /* handle if manager is not attached to a display */
+ if (!mgr || !mgr->output->device)
+ return cdev->num_displays;
+
+ /* find manager's display */
+ for (i = 0; i < cdev->num_displays; i++)
+ if (cdev->displays[i] == mgr->output->device)
+ break;
+
+ return i;
+}
+
+/*
+ * ===========================================================================
+ * QUEUING SETUP OPERATIONS
+ * ===========================================================================
+ */
+
+/* create a new composition for a display */
+struct dsscomp *dsscomp_new(struct omap_overlay_manager *mgr)
+{
+ struct dsscomp *comp = NULL;
+ u32 display_ix = get_display_ix(mgr);
+
+ /* check manager */
+ u32 ix = mgr ? mgr->id : cdev->num_mgrs;
+ if (ix >= cdev->num_mgrs || display_ix >= cdev->num_displays)
+ return ERR_PTR(-EINVAL);
+
+ /* allocate composition */
+ comp = kzalloc(sizeof(*comp), GFP_KERNEL);
+ if (!comp)
+ return NULL;
+
+ /* initialize new composition */
+ comp->ix = ix; /* save where this composition came from */
+ comp->ovl_mask = 0;
+ comp->ovl_dmask = 0;
+ comp->frm.sync_id = 0;
+ comp->frm.mgr.ix = display_ix;
+ comp->state = DSSCOMP_STATE_ACTIVE;
+
+ DO_IF_DEBUG_FS({
+ __log_state(comp, dsscomp_new, 0);
+ list_add(&comp->dbg_q, &dbg_comps);
+ });
+
+ return comp;
+}
+EXPORT_SYMBOL(dsscomp_new);
+
+/* returns overlays used in a composition */
+u32 dsscomp_get_ovls(struct dsscomp *comp)
+{
+ u32 mask;
+
+ mutex_lock(&mtx);
+ BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
+ mask = comp->ovl_mask;
+ mutex_unlock(&mtx);
+
+ return mask;
+}
+EXPORT_SYMBOL(dsscomp_get_ovls);
+
+/* set overlay info */
+int dsscomp_set_ovl(struct dsscomp *comp, struct dss2_ovl_info *ovl)
+{
+ int r = -EBUSY;
+ u32 i, mask, oix, ix;
+ struct omap_overlay *o;
+
+ mutex_lock(&mtx);
+
+ BUG_ON(!ovl);
+ BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
+
+ ix = comp->ix;
+
+ if (ovl->cfg.ix >= cdev->num_ovls) {
+ r = -EINVAL;
+ goto done;
+ }
+
+ /* if overlay is already part of the composition */
+ mask = 1 << ovl->cfg.ix;
+ if (mask & comp->ovl_mask) {
+ /* look up overlay */
+ for (oix = 0; oix < comp->frm.num_ovls; oix++) {
+ if (comp->ovls[oix].cfg.ix == ovl->cfg.ix)
+ break;
+ }
+ BUG_ON(oix == comp->frm.num_ovls);
+ } else {
+ /* check if ovl is free to use */
+ if (comp->frm.num_ovls >= ARRAY_SIZE(comp->ovls))
+ goto done;
+
+ /* not in any other displays queue */
+ if (mask & ~mgrq[ix].ovl_qmask.mask) {
+ for (i = 0; i < cdev->num_mgrs; i++) {
+ if (i == ix)
+ continue;
+ if (mgrq[i].ovl_qmask.mask & mask)
+ goto done;
+ }
+ }
+
+ /* and disabled (unless forced) if on another manager */
+ o = cdev->ovls[ovl->cfg.ix];
+ if (o->is_enabled(o) && (!o->manager || o->manager->id != ix))
+ goto done;
+
+ /* add overlay to composition & display */
+ comp->ovl_mask |= mask;
+ oix = comp->frm.num_ovls++;
+ maskref_incbit(&mgrq[ix].ovl_qmask, ovl->cfg.ix);
+ }
+
+ comp->ovls[oix] = *ovl;
+ r = 0;
+done:
+ mutex_unlock(&mtx);
+
+ return r;
+}
+EXPORT_SYMBOL(dsscomp_set_ovl);
+
+/* get overlay info */
+int dsscomp_get_ovl(struct dsscomp *comp, u32 ix, struct dss2_ovl_info *ovl)
+{
+ int r;
+ u32 oix;
+
+ mutex_lock(&mtx);
+
+ BUG_ON(!ovl);
+ BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
+
+ if (ix >= cdev->num_ovls) {
+ r = -EINVAL;
+ } else if (comp->ovl_mask & (1 << ix)) {
+ r = 0;
+ for (oix = 0; oix < comp->frm.num_ovls; oix++)
+ if (comp->ovls[oix].cfg.ix == ovl->cfg.ix) {
+ *ovl = comp->ovls[oix];
+ break;
+ }
+ BUG_ON(oix == comp->frm.num_ovls);
+ } else {
+ r = -ENOENT;
+ }
+
+ mutex_unlock(&mtx);
+
+ return r;
+}
+EXPORT_SYMBOL(dsscomp_get_ovl);
+
+/* set manager info */
+int dsscomp_set_mgr(struct dsscomp *comp, struct dss2_mgr_info *mgr)
+{
+ mutex_lock(&mtx);
+
+ BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
+ BUG_ON(mgr->ix != comp->frm.mgr.ix);
+
+ comp->frm.mgr = *mgr;
+
+ mutex_unlock(&mtx);
+
+ return 0;
+}
+EXPORT_SYMBOL(dsscomp_set_mgr);
+
+/* get manager info */
+int dsscomp_get_mgr(struct dsscomp *comp, struct dss2_mgr_info *mgr)
+{
+ mutex_lock(&mtx);
+
+ BUG_ON(!mgr);
+ BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
+
+ *mgr = comp->frm.mgr;
+
+ mutex_unlock(&mtx);
+
+ return 0;
+}
+EXPORT_SYMBOL(dsscomp_get_mgr);
+
+/* get manager info */
+int dsscomp_setup(struct dsscomp *comp, enum dsscomp_setup_mode mode,
+ struct dss2_rect_t win)
+{
+ mutex_lock(&mtx);
+
+ BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
+
+ comp->frm.mode = mode;
+ comp->frm.win = win;
+
+ mutex_unlock(&mtx);
+
+ return 0;
+}
+EXPORT_SYMBOL(dsscomp_setup);
+
+/*
+ * ===========================================================================
+ * QUEUING COMMITTING OPERATIONS
+ * ===========================================================================
+ */
+void dsscomp_drop(struct dsscomp *comp)
+{
+ /* decrement unprogrammed references */
+ if (comp->state < DSSCOMP_STATE_PROGRAMMED)
+ maskref_decmask(&mgrq[comp->ix].ovl_qmask, comp->ovl_mask);
+ comp->state = 0;
+
+ if (debug & DEBUG_COMPOSITIONS)
+ dev_info(DEV(cdev), "[%p] released\n", comp);
+
+ DO_IF_DEBUG_FS(list_del(&comp->dbg_q));
+
+ kfree(comp);
+}
+EXPORT_SYMBOL(dsscomp_drop);
+
+struct dsscomp_cb_work {
+ struct work_struct work;
+ struct dsscomp *comp;
+ int status;
+};
+
+static void dsscomp_mgr_delayed_cb(struct work_struct *work)
+{
+ struct dsscomp_cb_work *wk = container_of(work, typeof(*wk), work);
+ struct dsscomp *comp = wk->comp;
+ int status = wk->status;
+ u32 ix;
+
+ kfree(work);
+
+ mutex_lock(&mtx);
+
+ BUG_ON(comp->state == DSSCOMP_STATE_ACTIVE);
+ ix = comp->ix;
+
+ /* call extra callbacks if requested */
+ if (comp->extra_cb)
+ comp->extra_cb(comp->extra_cb_data, status);
+
+ /* handle programming & release */
+ if (status == DSS_COMPLETION_PROGRAMMED) {
+ comp->state = DSSCOMP_STATE_PROGRAMMED;
+ log_state(comp, dsscomp_mgr_delayed_cb, status);
+
+ /* update used overlay mask */
+ mgrq[ix].ovl_mask = comp->ovl_mask & ~comp->ovl_dmask;
+ maskref_decmask(&mgrq[ix].ovl_qmask, comp->ovl_mask);
+
+ if (debug & DEBUG_PHASES)
+ dev_info(DEV(cdev), "[%p] programmed\n", comp);
+ } else if ((status == DSS_COMPLETION_DISPLAYED) &&
+ comp->state == DSSCOMP_STATE_PROGRAMMED) {
+ /* composition is 1st displayed */
+ comp->state = DSSCOMP_STATE_DISPLAYED;
+ log_state(comp, dsscomp_mgr_delayed_cb, status);
+ if (debug & DEBUG_PHASES)
+ dev_info(DEV(cdev), "[%p] displayed\n", comp);
+ } else if (status & DSS_COMPLETION_RELEASED) {
+ /* composition is no longer displayed */
+ log_event(20 * comp->ix + 20, 0, comp, "%pf on %s",
+ (u32)dsscomp_mgr_delayed_cb,
+ (u32)log_status_str(status));
+ dsscomp_drop(comp);
+ }
+ mutex_unlock(&mtx);
+}
+
+static u32 dsscomp_mgr_callback(void *data, int id, int status)
+{
+ struct dsscomp *comp = data;
+
+ if (status == DSS_COMPLETION_PROGRAMMED ||
+ (status == DSS_COMPLETION_DISPLAYED &&
+ comp->state != DSSCOMP_STATE_DISPLAYED) ||
+ (status & DSS_COMPLETION_RELEASED)) {
+ struct dsscomp_cb_work *wk = kzalloc(sizeof(*wk), GFP_ATOMIC);
+ wk->comp = comp;
+ wk->status = status;
+ INIT_WORK(&wk->work, dsscomp_mgr_delayed_cb);
+ queue_work(cb_wkq, &wk->work);
+ }
+
+ /* get each callback only once */
+ return ~status;
+}
+
+static inline bool dssdev_manually_updated(struct omap_dss_device *dev)
+{
+ return dev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+}
+
+/* apply composition */
+/* at this point the composition is not on any queue */
+static int dsscomp_apply(struct dsscomp *comp)
+{
+ int i, r = -EFAULT;
+ u32 dmask, display_ix;
+ struct omap_dss_device *dssdev;
+ struct omap_dss_driver *drv;
+ struct omap_overlay_manager *mgr;
+ struct omap_overlay *ovl;
+ struct dsscomp_setup_mgr_data *d;
+ u32 oix;
+ bool cb_programmed = false;
+
+ struct omapdss_ovl_cb cb = {
+ .fn = dsscomp_mgr_callback,
+ .data = comp,
+ .mask = DSS_COMPLETION_DISPLAYED |
+ DSS_COMPLETION_PROGRAMMED | DSS_COMPLETION_RELEASED,
+ };
+
+ BUG_ON(comp->state != DSSCOMP_STATE_APPLYING);
+
+ /* check if the display is valid and used */
+ r = -ENODEV;
+ d = &comp->frm;
+ display_ix = d->mgr.ix;
+ if (display_ix >= cdev->num_displays)
+ goto done;
+ dssdev = cdev->displays[display_ix];
+ if (!dssdev)
+ goto done;
+
+ drv = dssdev->driver;
+ mgr = dssdev->output->manager;
+ if (!mgr || !drv || mgr->id >= cdev->num_mgrs)
+ goto done;
+
+ dump_comp_info(cdev, d, "apply");
+
+ r = 0;
+ dmask = 0;
+ for (oix = 0; oix < comp->frm.num_ovls; oix++) {
+ struct dss2_ovl_info *oi = comp->ovls + oix;
+
+ /* keep track of disabled overlays */
+ if (!oi->cfg.enabled)
+ dmask |= 1 << oi->cfg.ix;
+
+ if (r && !comp->must_apply)
+ continue;
+
+ dump_ovl_info(cdev, oi);
+
+ if (oi->cfg.ix >= cdev->num_ovls) {
+ r = -EINVAL;
+ continue;
+ }
+ ovl = cdev->ovls[oi->cfg.ix];
+
+ /* set overlays' manager & info */
+ if (ovl->is_enabled(ovl) && ovl->manager != mgr) {
+ r = -EBUSY;
+ goto skip_ovl_set;
+ }
+ if (ovl->manager != mgr) {
+ /* :NOTE: ignore error from unset */
+ ovl->unset_manager(ovl);
+ r = ovl->set_manager(ovl, mgr);
+ if (r)
+ goto skip_ovl_set;
+ }
+
+ r = set_dss_ovl_info(oi);
+skip_ovl_set:
+ if (r && comp->must_apply) {
+ dev_err(DEV(cdev), "[%p] set ovl%d failed %d",
+ comp, oi->cfg.ix, r);
+ oi->cfg.enabled = false;
+ dmask |= 1 << oi->cfg.ix;
+ set_dss_ovl_info(oi);
+ }
+ }
+
+ /*
+ * set manager's info - this also sets the completion callback,
+ * so if it succeeds, we will use the callback to complete the
+ * composition. Otherwise, we can skip the composition now.
+ */
+ if (!r || comp->must_apply) {
+ r = set_dss_mgr_info(&d->mgr, &cb);
+ cb_programmed = r == 0;
+ }
+
+ if (r && !comp->must_apply) {
+ dev_err(DEV(cdev), "[%p] set failed %d\n", comp, r);
+ goto done;
+ } else {
+ if (r)
+ dev_warn(DEV(cdev), "[%p] ignoring set failure %d\n",
+ comp, r);
+ comp->blank = dmask == comp->ovl_mask;
+ comp->ovl_dmask = dmask;
+
+ /*
+ * Check other overlays that may also use this display.
+ * NOTE: This is only needed in case someone changes
+ * overlays via sysfs. We use comp->ovl_mask to refresh
+ * the overlays actually used on a manager when the
+ * composition is programmed.
+ */
+ for (i = 0; i < cdev->num_ovls; i++) {
+ u32 mask = 1 << i;
+ if ((~comp->ovl_mask & mask) &&
+ cdev->ovls[i]->is_enabled(cdev->ovls[i]) &&
+ cdev->ovls[i]->manager == mgr) {
+ mutex_lock(&mtx);
+ comp->ovl_mask |= mask;
+ maskref_incbit(&mgrq[comp->ix].ovl_qmask, i);
+ mutex_unlock(&mtx);
+ }
+ }
+ }
+
+ /* apply changes and call update on manual panels */
+ /* no need for mutex as no callbacks are scheduled yet */
+ comp->state = DSSCOMP_STATE_APPLIED;
+ log_state(comp, dsscomp_apply, 0);
+
+ if (!d->win.w && !d->win.x)
+ d->win.w = dssdev->panel.timings.x_res - d->win.x;
+ if (!d->win.h && !d->win.y)
+ d->win.h = dssdev->panel.timings.y_res - d->win.y;
+
+ mutex_lock(&mtx);
+ if (mgrq[comp->ix].blanking) {
+ pr_info_ratelimited("ignoring apply mgr(%s) while blanking\n",
+ mgr->name);
+ r = -ENODEV;
+ } else {
+ r = mgr->apply(mgr);
+ if (r)
+ dev_err(DEV(cdev), "failed while applying %d", r);
+ /* keep error if set_mgr_info failed */
+ if (!r && !cb_programmed)
+ r = -EINVAL;
+ mgr->num_ovls = comp->frm.num_ovls;
+ for (oix = 0; oix < comp->frm.num_ovls; oix++) {
+ struct dss2_ovl_info *oi;
+ oi = comp->ovls + oix;
+ mgr->ovls[oix] = cdev->ovls[oi->cfg.ix];
+ mgr->ovls[oix]->enabled = oi->cfg.enabled;
+ }
+ if (!r) {
+ r = mgr->set_ovl(mgr);
+ if (r) {
+ dev_err(DEV(cdev), "[%p] "
+ "set_ovl failed\n", comp);
+ goto err;
+ }
+ }
+ }
+ mutex_unlock(&mtx);
+
+ /*
+ * TRICKY: try to unregister callback to see if callbacks have
+ * been applied (moved into DSS2 pipeline). Unregistering also
+ * avoids having to unnecessarily kick out compositions (which
+ * would result in screen blinking). If callbacks failed to apply,
+ * (e.g. could not set them or apply them) we will need to call
+ * them ourselves (we note this by returning an error).
+ */
+ if (cb_programmed && r) {
+ /* clear error if callback already registered */
+ if (omap_dss_manager_unregister_callback(mgr, &cb))
+ r = 0;
+ }
+ /* if failed to apply, kick out prior composition */
+ if (comp->must_apply && r)
+ mgr->blank(mgr, true);
+
+ if (!r && (d->mode & DSSCOMP_SETUP_MODE_DISPLAY)) {
+ /* cannot handle update errors, so ignore them */
+ if (dssdev_manually_updated(dssdev) && drv->sync)
+ drv->update(dssdev, d->win.x, d->win.y, d->win.w,
+ d->win.h);
+ else
+ /* wait for sync to do smooth animations */
+ mgr->wait_for_vsync(mgr);
+ }
+
+ return r;
+err:
+ mutex_unlock(&mtx);
+done:
+ return r;
+}
+
+struct dsscomp_apply_work {
+ struct work_struct work;
+ struct dsscomp *comp;
+};
+
+int dsscomp_state_notifier(struct notifier_block *nb,
+ unsigned long arg, void *ptr)
+{
+ struct omap_dss_device *dssdev = ptr;
+ enum omap_dss_display_state state = arg;
+ struct omap_overlay_manager *mgr = dssdev->output->manager;
+ if (mgr) {
+ mutex_lock(&mtx);
+ if (state == OMAP_DSS_DISPLAY_DISABLED) {
+ mgr->blank(mgr, true);
+ mgrq[mgr->id].blanking = true;
+ } else if (state == OMAP_DSS_DISPLAY_ACTIVE) {
+ mgrq[mgr->id].blanking = false;
+ }
+ mutex_unlock(&mtx);
+ }
+ return 0;
+}
+
+
+static void dsscomp_do_apply(struct work_struct *work)
+{
+ struct dsscomp_apply_work *wk = container_of(work, typeof(*wk), work);
+ /* complete compositions that failed to apply */
+ if (dsscomp_apply(wk->comp))
+ dsscomp_mgr_callback(wk->comp, -1, DSS_COMPLETION_ECLIPSED_SET);
+ kfree(wk);
+}
+
+int dsscomp_delayed_apply(struct dsscomp *comp)
+{
+ /* don't block in case we are called from interrupt context */
+ struct dsscomp_apply_work *wk = kzalloc(sizeof(*wk), GFP_NOWAIT);
+ if (!wk)
+ return -ENOMEM;
+
+ mutex_lock(&mtx);
+
+ BUG_ON(comp->state != DSSCOMP_STATE_ACTIVE);
+ comp->state = DSSCOMP_STATE_APPLYING;
+ log_state(comp, dsscomp_delayed_apply, 0);
+
+ if (debug & DEBUG_PHASES)
+ dev_info(DEV(cdev), "[%p] applying\n", comp);
+ mutex_unlock(&mtx);
+
+ wk->comp = comp;
+ INIT_WORK(&wk->work, dsscomp_do_apply);
+ return queue_work(mgrq[comp->ix].apply_workq, &wk->work) ? 0 : -EBUSY;
+}
+EXPORT_SYMBOL(dsscomp_delayed_apply);
+
+/*
+ * ===========================================================================
+ * DEBUGFS
+ * ===========================================================================
+ */
+
+#ifdef CONFIG_DEBUG_FS
+static void seq_print_comp(struct seq_file *s, struct dsscomp *c)
+{
+ struct dsscomp_setup_mgr_data *d = &c->frm;
+ int i;
+
+ seq_printf(s, " [%p]: %s%s\n", c, c->blank ? "blank " : "",
+ c->state == DSSCOMP_STATE_ACTIVE ? "ACTIVE" :
+ c->state == DSSCOMP_STATE_APPLYING ? "APPLYING" :
+ c->state == DSSCOMP_STATE_APPLIED ? "APPLIED" :
+ c->state == DSSCOMP_STATE_PROGRAMMED ? "PROGRAMMED" :
+ c->state == DSSCOMP_STATE_DISPLAYED ? "DISPLAYED" :
+ "???");
+ seq_printf(s, " sync_id=%x, flags=%c%c%c\n",
+ d->sync_id,
+ (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-',
+ (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-',
+ (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-');
+ for (i = 0; i < d->num_ovls; i++) {
+ struct dss2_ovl_info *oi;
+ struct dss2_ovl_cfg *g;
+ oi = d->ovls + i;
+ g = &oi->cfg;
+ if (g->zonly) {
+ seq_printf(s, " ovl%d={%s z%d}\n", g->ix,
+ g->enabled ? "ON" : "off",
+ g->zorder);
+ } else {
+ seq_printf(s, " ovl%d={%s ", g->ix,
+ g->enabled ? "ON" : "off");
+ seq_printf(s, "z%d %s", g->zorder,
+ dsscomp_get_color_name(g->color_mode) ?
+ : "N/A");
+ seq_printf(s, "%s ", g->pre_mult_alpha ?
+ " premult" : "");
+ seq_printf(s, "*%d%%", (g->global_alpha * 100 + 128) /
+ 255);
+ seq_printf(s, "%d*%d:%d,", g->width, g->height,
+ g->crop.x);
+ seq_printf(s, "%d+%d,%d ", g->crop.y, g->crop.w,
+ g->crop.h);
+ seq_printf(s, "rot%d%s => ", g->rotation, g->mirror ?
+ "+mir" : "");
+ seq_printf(s, "%d,%d+%d, ", g->win.x, g->win.y,
+ g->win.w);
+ seq_printf(s, "%d %p/%p|%d}\n", g->win.h,
+ (void *)oi->ba, (void *)oi->uv,
+ g->stride);
+ }
+ }
+ if (c->extra_cb)
+ seq_printf(s, " gsync=[%p] %pf\n\n", c->extra_cb_data,
+ c->extra_cb);
+ else
+ seq_printf(s, " gsync=[%p] (called)\n\n", c->extra_cb_data);
+}
+#endif
+
+void dsscomp_dbg_comps(struct seq_file *s)
+{
+#ifdef CONFIG_DEBUG_FS
+ struct dsscomp *c;
+ u32 i;
+
+ mutex_lock(&dbg_mtx);
+ for (i = 0; i < cdev->num_mgrs; i++) {
+ struct omap_overlay_manager *mgr = cdev->mgrs[i];
+ seq_printf(s, "ACTIVE COMPOSITIONS on %s\n\n", mgr->name);
+ list_for_each_entry(c, &dbg_comps, dbg_q) {
+ struct dss2_mgr_info *mi = &c->frm.mgr;
+ if (mi->ix < cdev->num_displays &&
+ cdev->displays[mi->ix]->output->manager == mgr)
+ seq_print_comp(s, c);
+ }
+
+ /* print manager cache */
+ mgr->dump_cb(mgr, s);
+ }
+ mutex_unlock(&dbg_mtx);
+#endif
+}
+
+void dsscomp_dbg_events(struct seq_file *s)
+{
+#ifdef CONFIG_DSSCOMP_DEBUG_LOG
+ u32 i;
+ struct dbg_event_t *d;
+
+ mutex_lock(&dbg_mtx);
+ for (i = dbg_event_ix; i < dbg_event_ix + ARRAY_SIZE(dbg_events); i++) {
+ d = dbg_events + (i % ARRAY_SIZE(dbg_events));
+ if (!d->ms)
+ continue;
+ seq_printf(s, "[% 5d.%03d] %*s[%08x] ",
+ d->ms / 1000, d->ms % 1000,
+ d->ix + ((u32) d->data) % 7,
+ "", (u32) d->data);
+ seq_printf(s, d->fmt, d->a1, d->a2);
+ seq_printf(s, "\n");
+ }
+ mutex_unlock(&dbg_mtx);
+#endif
+}
+
+/*
+ * ===========================================================================
+ * EXIT
+ * ===========================================================================
+ */
+void dsscomp_queue_exit(void)
+{
+ if (cdev) {
+ int i;
+ for (i = 0; i < cdev->num_displays; i++)
+ destroy_workqueue(mgrq[i].apply_workq);
+ destroy_workqueue(cb_wkq);
+ cdev = NULL;
+ }
+}
+EXPORT_SYMBOL(dsscomp_queue_exit);
diff --git a/drivers/video/omap2/dsscomp/tiler-utils.c b/drivers/video/omap2/dsscomp/tiler-utils.c
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * drivers/video/omap2/dsscomp/tiler-utils.c
+ *
+ * Tiler Utility APIs source file
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc
+ * Author: Sreenidhi Koti <sreenidhi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/shmem_fs.h>
+#include <linux/module.h>
+
+#include "tiler-utils.h"
+/* ==========================================================================
+ * Kernel APIs
+ * ==========================================================================
+ */
+
+u32 tiler_virt2phys(u32 usr)
+{
+ pmd_t *pmd;
+ pte_t *ptep;
+ pgd_t *pgd = pgd_offset(current->mm, usr);
+
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ return 0;
+
+ pmd = pmd_offset((pud_t *)pgd, usr);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ return 0;
+
+ ptep = pte_offset_map(pmd, usr);
+ if (ptep && pte_present(*ptep))
+ return (*ptep & PAGE_MASK) | (~PAGE_MASK & usr);
+
+ return 0;
+}
+
+void tiler_pa_free(struct tiler_pa_info *pa)
+{
+ if (pa)
+ kfree(pa->mem);
+ kfree(pa);
+}
+EXPORT_SYMBOL(tiler_pa_free);
+
+/* get physical pages of a user block */
+struct tiler_pa_info *user_block_to_pa(u32 usr_addr, u32 num_pg)
+{
+ struct task_struct *curr_task = current;
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma = NULL;
+
+ struct tiler_pa_info *pa = NULL;
+ struct page **pages = NULL;
+ u32 *mem = NULL, write, i;
+ int usr_count;
+
+ pa = kzalloc(sizeof(*pa), GFP_KERNEL);
+ if (!pa)
+ return NULL;
+
+ mem = kzalloc(num_pg * sizeof(*mem), GFP_KERNEL);
+ if (!mem) {
+ kfree(pa);
+ return NULL;
+ }
+
+ pages = kmalloc(num_pg * sizeof(*pages), GFP_KERNEL);
+ if (!pages) {
+ kfree(mem);
+ kfree(pa);
+ return NULL;
+ }
+
+ /*
+ * Important Note: usr_addr is mapped from user
+ * application process to current process - it must lie
+ * completely within the current virtual memory address
+ * space in order to be of use to us here.
+ */
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, usr_addr + (num_pg << PAGE_SHIFT) - 1);
+
+ if (!vma || (usr_addr < vma->vm_start)) {
+ kfree(mem);
+ kfree(pa);
+ kfree(pages);
+ up_read(&mm->mmap_sem);
+ printk(KERN_ERR "Address is outside VMA: ");
+ printk(KERN_ERR "address start = %08x", usr_addr);
+ printk(KERN_ERR "user end = %08x\n", (usr_addr +
+ (num_pg << PAGE_SHIFT)));
+ return ERR_PTR(-EFAULT);
+ }
+
+ if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE))
+ write = 1;
+
+ usr_count = get_user_pages(curr_task, mm, usr_addr, num_pg, write, 1,
+ pages, NULL);
+
+ if (usr_count > 0) {
+ /* process user allocated buffer */
+ if (usr_count != num_pg) {
+ /* release the pages we did get */
+ for (i = 0; i < usr_count; i++)
+ page_cache_release(pages[i]);
+ } else {
+ /* fill in the physical address information */
+ for (i = 0; i < num_pg; i++) {
+ mem[i] = page_to_phys(pages[i]);
+ BUG_ON(pages[i] != phys_to_page(mem[i]));
+ }
+ }
+ } else {
+ /* fallback for kernel allocated buffers */
+ for (i = 0; i < num_pg; i++) {
+ mem[i] = tiler_virt2phys(usr_addr);
+
+ if (!mem[i]) {
+ printk(KERN_ERR "VMA not in page table\n");
+ break;
+ }
+
+ usr_addr += PAGE_SIZE;
+ }
+ }
+
+ up_read(&mm->mmap_sem);
+
+ kfree(pages);
+
+ /* if failed to map all pages */
+ if (i < num_pg) {
+ kfree(mem);
+ kfree(pa);
+ return ERR_PTR(-EFAULT);
+ }
+
+ pa->mem = mem;
+ pa->memtype = usr_count > 0 ? TILER_MEM_GOT_PAGES : TILER_MEM_USING;
+ pa->num_pg = num_pg;
+ return pa;
+}
diff --git a/drivers/video/omap2/dsscomp/tiler-utils.h b/drivers/video/omap2/dsscomp/tiler-utils.h
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * drivers/video/omap2/dsscomp/tiler-utils.h
+ *
+ * Tiler Utility APIs header file
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc
+ * Author: Sreenidhi Koti <sreenidhi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* type of tiler memory */
+enum tiler_memtype {
+ TILER_MEM_ALLOCED, /* tiler allocated the memory */
+ TILER_MEM_GOT_PAGES, /* tiler used get_user_pages */
+ TILER_MEM_USING, /* tiler is using the pages */
+};
+
+/* physical pages to pin - mem must be kmalloced */
+struct tiler_pa_info {
+ u32 num_pg; /* number of pages in page-list */
+ u32 *mem; /* list of phys page addresses */
+ enum tiler_memtype memtype; /* how we got physical pages */
+};
+
+/**
+ * Frees a tiler_pa_info structure and associated memory
+ *
+ * @param pa Ptr to tiler_pa_info structure
+ *
+ */
+void tiler_pa_free(struct tiler_pa_info *pa);
+
+/**
+ * Creates and returns a tiler_pa_info structure from a user address
+ *
+ * @param usr_addr User Address
+ * @param num_pg Number of pages
+ *
+ * @return Ptr to new tiler_pa_info structure
+ */
+struct tiler_pa_info *user_block_to_pa(u32 usr_addr, u32 num_pg);
+/**
+ * Get the physical address for a given user va.
+ *
+ * @param usr user virtual address
+ *
+ * @return valid pa or 0 for error
+ */
+u32 tiler_virt2phys(u32 usr);
index 4cb12ce68855ae998644a8454e8802494173659a..e612028980a803499e93565a522598c620960a6c 100644 (file)
menuconfig FB_OMAP2
tristate "OMAP2+ frame buffer support"
- depends on FB && OMAP2_DSS && !DRM_OMAP
+ depends on FB && OMAP2_DSS
select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
+ select FB_MODE_HELPERS
help
Frame buffer driver for OMAP2+ based boards.
index d30b45d7264972590a4cf39a9131cc619eb9fbb2..27d7d033f372ff0c4f74e48cb68a88e01df5b701 100644 (file)
return r;
}
+EXPORT_SYMBOL(omapfb_set_update_mode);
int omapfb_get_update_mode(struct fb_info *fbi,
enum omapfb_update_mode *mode)
return 0;
}
+EXPORT_SYMBOL(omapfb_get_update_mode);
/* XXX this color key handling is a hack... */
static struct omapfb_color_key omapfb_color_keys[2];
case OMAPFB_GET_DISPLAY_INFO: {
u16 xres, yres;
+ u32 w, h;
DBG("ioctl GET_DISPLAY_INFO\n");
break;
}
- display->driver->get_resolution(display, &xres, &yres);
-
+ get_fb_resolution(display, &xres, &yres);
p.display_info.xres = xres;
p.display_info.yres = yres;
- if (display->driver->get_dimensions) {
- u32 w, h;
- display->driver->get_dimensions(display, &w, &h);
- p.display_info.width = w;
- p.display_info.height = h;
- } else {
- p.display_info.width = 0;
- p.display_info.height = 0;
- }
+ omapdss_display_get_dimensions(display, &w, &h);
+ p.display_info.width = w;
+ p.display_info.height = h;
if (copy_to_user((void __user *)arg, &p.display_info,
sizeof(p.display_info)))
break;
}
+ case OMAPFB_ENABLEVSYNC:
+ if (get_user(p.crt, (__u32 __user *)arg)) {
+ r = -EFAULT;
+ break;
+ }
+
+ omapfb_lock(fbdev);
+ fbdev->vsync_active = !!p.crt;
+ if (p.crt)
+ if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
+ omapfb_enable_vsync(fbdev, display->channel,
+ true);
+ else
+ r = -EBUSY;
+ else
+ omapfb_enable_vsync(fbdev, display->channel,
+ false);
+ omapfb_unlock(fbdev);
+ break;
+
default:
dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
r = -EINVAL;
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/omapfb.h>
+#include <linux/wait.h>
#include <video/omapdss.h>
#include <video/omapvrfb.h>
module_param(auto_update, bool, 0);
module_param(auto_update_freq, uint, 0644);
+/* Max 4 framebuffers assumed : FB-ix-W-H */
+#define MAX_FB_COUNT 4
+#define ELEMENT_COUNT 3
+struct fb_options {
+ int ix;
+ int width;
+ int height;
+};
+static int fb_opt[MAX_FB_COUNT*ELEMENT_COUNT] = { -1, -1, -1,
+ -1, -1, -1,
+ -1, -1, -1,
+ -1, -1, -1};
+
+module_param_array(fb_opt, int, NULL, 0);
+MODULE_PARM_DESC(fb_opt, "FB[ix][w][h]");
+
#ifdef DEBUG
bool omapfb_debug;
module_param_named(debug, omapfb_debug, bool, 0644);
module_param_named(test, omapfb_test_pattern, bool, 0644);
#endif
+static bool intialize_dev_fb_resolution(u16 display_ix,
+ struct omap_dss_device *dssdev)
+{
+ struct fb_options *pfb_opt = NULL;
+
+ if (display_ix > MAX_FB_COUNT || !dssdev)
+ return false;
+
+ pfb_opt = (struct fb_options *)&fb_opt[display_ix*ELEMENT_COUNT];
+
+ DBG("cmd line dev ix %d - W %d - H %d\n",
+ pfb_opt->ix, pfb_opt->width , pfb_opt->height);
+
+ if (pfb_opt->ix != -1) {
+ dssdev->panel.fb_xres = pfb_opt->width;
+ dssdev->panel.fb_yres = pfb_opt->height;
+ } else {
+ dssdev->panel.fb_xres = dssdev->panel.timings.x_res;
+ dssdev->panel.fb_yres = dssdev->panel.timings.y_res;
+ }
+ DBG("init dev %s dev-%d:w-%d:h-%d\n", dssdev->name, display_ix,
+ dssdev->panel.fb_xres, dssdev->panel.fb_yres);
+ return true;
+}
+
+void get_fb_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres)
+{
+ *xres = dssdev->panel.fb_xres;
+ *yres = dssdev->panel.fb_yres;
+ DBG("%s %s %d x %d", __func__, dssdev->name, *xres, *yres);
+ return;
+}
+
static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
struct omap_dss_device *dssdev);
.green = { .length = 8, .offset = 16, .msb_right = 0 },
.blue = { .length = 8, .offset = 8, .msb_right = 0 },
.transp = { .length = 0, .offset = 0, .msb_right = 0 },
+ }, {
+ .dssmode = OMAP_DSS_COLOR_BGRA32,
+ .bits_per_pixel = 32,
+ .red = { .length = 8, .offset = 8, .msb_right = 0 },
+ .green = { .length = 8, .offset = 16, .msb_right = 0 },
+ .blue = { .length = 8, .offset = 24, .msb_right = 0 },
+ .transp = { .length = 8, .offset = 0, .msb_right = 0 },
},
};
var->transp = color->transp;
}
-static int fb_mode_to_dss_mode(struct fb_var_screeninfo *var,
+int omapfb_mode_to_dss_mode(struct fb_var_screeninfo *var,
enum omap_color_mode *mode)
{
enum omap_color_mode dssmode;
dssmode = OMAP_DSS_COLOR_RGB24P;
break;
case 32:
- dssmode = OMAP_DSS_COLOR_RGB24U;
+ dssmode = OMAP_DSS_COLOR_ARGB32;
break;
default:
return -EINVAL;
return -EINVAL;
}
+EXPORT_SYMBOL(omapfb_mode_to_dss_mode);
static int check_fb_res_bounds(struct fb_var_screeninfo *var)
{
DBG("setup_vrfb_rotation\n");
- r = fb_mode_to_dss_mode(var, &mode);
+ r = omapfb_mode_to_dss_mode(var, &mode);
if (r)
return r;
enum omap_color_mode mode = 0;
int i;
int r;
+ u32 w = 0, h = 0;
DBG("check_fb_var %d\n", ofbi->id);
WARN_ON(!atomic_read(&ofbi->region->lock_count));
- r = fb_mode_to_dss_mode(var, &mode);
+ r = omapfb_mode_to_dss_mode(var, &mode);
if (r) {
DBG("cannot convert var to omap dss mode\n");
return r;
var->xres, var->yres,
var->xres_virtual, var->yres_virtual);
- if (display && display->driver->get_dimensions) {
- u32 w, h;
- display->driver->get_dimensions(display, &w, &h);
+ if (display)
+ omapdss_display_get_dimensions(display, &w, &h);
+
+ if (w && h) {
var->width = DIV_ROUND_CLOSEST(w, 1000);
var->height = DIV_ROUND_CLOSEST(h, 1000);
} else {
return 0;
}
+
+bool check_fb_scale(struct omap_dss_device *dssdev)
+{
+ u16 fb_w, fb_h , pn_w , pn_h;
+ struct omap_dss_driver *dssdrv;
+
+ if (!dssdev || !dssdev->driver)
+ return false;
+ DBG("default device %s", dssdev->name);
+ fb_w = fb_h = pn_w = pn_h = 0;
+ dssdrv = dssdev->driver;
+
+ get_fb_resolution(dssdev, &fb_w, &fb_h);
+ if (fb_w <= 0 || fb_h <= 0)
+ return false;
+
+ if (dssdrv->get_resolution)
+ dssdrv->get_resolution(dssdev, &pn_w, &pn_h);
+
+ if (fb_w != pn_w || fb_h != pn_h)
+ return true;
+ else
+ return false;
+}
+
/*
* ---------------------------------------------------------------------------
* fbdev framework callbacks
static int omapfb_release(struct fb_info *fbi, int user)
{
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
+
+ if (!display)
+ return -ENODEV;
+
+ omapfb_enable_vsync(fbdev, display->channel, false);
+
return 0;
}
if (ofbi->region->size)
omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
- r = fb_mode_to_dss_mode(var, &mode);
+ r = omapfb_mode_to_dss_mode(var, &mode);
if (r) {
- DBG("fb_mode_to_dss_mode failed");
+ DBG("omapfb_mode_to_dss_mode failed");
goto err;
}
u16 posx, posy;
u16 outw, outh;
int i;
+ struct omap_dss_device *display = fb2display(fbi);
#ifdef DEBUG
if (omapfb_test_pattern)
}
if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+ u16 p_width , p_height;
int rotation = (var->rotate + ofbi->rotation[i]) % 4;
+ p_width = var->xres;
+ p_height = var->yres;
+ if (display && display->driver &&
+ display->driver->get_resolution)
+ display->driver->get_resolution(display,
+ &p_width, &p_height);
+
if (rotation == FB_ROTATE_CW ||
rotation == FB_ROTATE_CCW) {
- outw = var->yres;
- outh = var->xres;
+ outw = p_height;
+ outh = p_width;
} else {
- outw = var->xres;
- outh = var->yres;
+ outw = p_width;
+ outh = p_height;
}
} else {
struct omap_overlay_info info;
@@ -1021,6 +1124,41 @@ static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
return r;
}
+void omapfb_fb2dss_timings(struct fb_videomode *fb_timings,
+ struct omap_video_timings *dss_timings)
+{
+ dss_timings->x_res = fb_timings->xres;
+ dss_timings->y_res = fb_timings->yres;
+ if (fb_timings->vmode & FB_VMODE_INTERLACED)
+ dss_timings->y_res /= 2;
+ dss_timings->pixel_clock = fb_timings->pixclock ?
+ PICOS2KHZ(fb_timings->pixclock) : 0;
+ dss_timings->hfp = fb_timings->right_margin;
+ dss_timings->hbp = fb_timings->left_margin;
+ dss_timings->hsw = fb_timings->hsync_len;
+ dss_timings->vfp = fb_timings->lower_margin;
+ dss_timings->vbp = fb_timings->upper_margin;
+ dss_timings->vsw = fb_timings->vsync_len;
+}
+EXPORT_SYMBOL(omapfb_fb2dss_timings);
+
+void omapfb_dss2fb_timings(struct omap_video_timings *dss_timings,
+ struct fb_videomode *fb_timings)
+{
+ memset(fb_timings, 0, sizeof(*fb_timings));
+ fb_timings->xres = dss_timings->x_res;
+ fb_timings->yres = dss_timings->y_res;
+ fb_timings->pixclock = dss_timings->pixel_clock ?
+ KHZ2PICOS(dss_timings->pixel_clock) : 0;
+ fb_timings->right_margin = dss_timings->hfp;
+ fb_timings->left_margin = dss_timings->hbp;
+ fb_timings->hsync_len = dss_timings->hsw;
+ fb_timings->lower_margin = dss_timings->vfp;
+ fb_timings->upper_margin = dss_timings->vbp;
+ fb_timings->vsync_len = dss_timings->vsw;
+}
+EXPORT_SYMBOL(omapfb_dss2fb_timings);
+
/* set the video mode according to info->var */
static int omapfb_set_par(struct fb_info *fbi)
{
!d->auto_update_work_enabled)
omapfb_start_auto_update(fbdev, display);
+ if (fbdev->vsync_active &&
+ (display->state == OMAP_DSS_DISPLAY_ACTIVE))
+ omapfb_enable_vsync(fbdev, display->channel, true);
+
break;
case FB_BLANK_NORMAL:
/* FB_BLANK_NORMAL could be implemented.
- * Needs DSS additions. */
+ * Do not suspend for HDMI in case of early
+ * suspend since HDMI audio can be active */
+ if (display && display->name &&
+ strcmp(display->name, "hdmi") == 0) {
+ DBG("HDMI not suspended\n");
+ break;
+ }
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_POWERDOWN:
+ if (fbdev->vsync_active)
+ omapfb_enable_vsync(fbdev, display->channel, false);
+
if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
goto exit;
@@ -1471,8 +1622,7 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
if (!size) {
u16 w, h;
- display->driver->get_resolution(display, &w, &h);
-
+ get_fb_resolution(display, &w, &h);
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
size = max(omap_vrfb_min_phys_size(w, h, bytespp),
omap_vrfb_min_phys_size(h, w, bytespp));
@@ -1484,6 +1634,12 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
}
}
+ /*FIXME: This is a hack for swap chain creation.
+ If you see this in production code, there is a
+ serious problem!!!
+ */
+ size *= 2;
+
if (!size)
return 0;
memset(&vram_paddrs, 0, sizeof(vram_paddrs));
}
+ if (fbdev->dev->platform_data) {
+ struct omapfb_platform_data *opd;
+ opd = fbdev->dev->platform_data;
+ for (i = 0; i < opd->mem_desc.region_cnt; ++i) {
+ if (!vram_sizes[i]) {
+ unsigned long size;
+ unsigned long paddr;
+
+ size = opd->mem_desc.region[i].size;
+ paddr = opd->mem_desc.region[i].paddr;
+
+ vram_sizes[i] = size;
+ vram_paddrs[i] = paddr;
+ }
+ }
+ }
+
for (i = 0; i < fbdev->num_fbs; i++) {
/* allocate memory automatically only for fb0, or if
* excplicitly defined with vram or plat data option */
u16 w, h;
int rotation = (var->rotate + ofbi->rotation[0]) % 4;
- display->driver->get_resolution(display, &w, &h);
-
+ get_fb_resolution(display, &w, &h);
if (rotation == FB_ROTATE_CW ||
rotation == FB_ROTATE_CCW) {
var->xres = h;
DBG("fb_infos allocated\n");
/* assign overlays for the fbs */
- for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
+ for (i = 0; i < min3(fbdev->num_fbs, fbdev->num_overlays,
+ fbdev->num_managers); i++) {
struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
-
+ struct omap_overlay_manager *mgr = fbdev->managers[i];
ofbi->overlays[0] = fbdev->overlays[i];
ofbi->num_overlays = 1;
+ if (mgr->output) {
+ ofbi->overlays[0]->unset_manager(ofbi->overlays[0]);
+ ofbi->overlays[0]->set_manager(ofbi->overlays[0], mgr);
+ DBG("ofbi%d assigned dev %s",
+ ofbi->id, mgr->name);
+ }
}
/* allocate fb memories */
struct omapfb_display_data *d;
int r;
- r = dssdrv->enable(dssdev);
- if (r) {
- dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
- dssdev->name);
- return r;
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+
+ r = dssdrv->enable(dssdev);
+ if (r) {
+ dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
+ dssdev->name);
+ return r;
+ }
}
d = get_display_data(fbdev, dssdev);
return 0;
}
+static void omapfb_send_vsync_work(struct work_struct *work)
+{
+ struct omapfb2_device *fbdev =
+ container_of(work, typeof(*fbdev), vsync_work);
+ char buf[64];
+ char *envp[2];
+
+ snprintf(buf, sizeof(buf), "VSYNC=%llu",
+ ktime_to_ns(fbdev->vsync_timestamp));
+ envp[0] = buf;
+ envp[1] = NULL;
+ kobject_uevent_env(&fbdev->dev->kobj, KOBJ_CHANGE, envp);
+}
+static void omapfb_vsync_isr(void *data, u32 mask)
+{
+ struct omapfb2_device *fbdev = data;
+ fbdev->vsync_timestamp = ktime_get();
+ schedule_work(&fbdev->vsync_work);
+}
+
+int omapfb_enable_vsync(struct omapfb2_device *fbdev, enum omap_channel ch,
+ bool enable)
+{
+ int r = 0;
+ const u32 masks[] = {
+ DISPC_IRQ_VSYNC,
+ DISPC_IRQ_EVSYNC_EVEN,
+ DISPC_IRQ_VSYNC2
+ };
+
+ if (ch > OMAP_DSS_CHANNEL_LCD2) {
+ pr_warn("%s wrong channel number\n", __func__);
+ return -ENODEV;
+ }
+
+ if (enable)
+ r = omap_dispc_register_isr(omapfb_vsync_isr, fbdev,
+ masks[ch]);
+ else
+ r = omap_dispc_unregister_isr(omapfb_vsync_isr, fbdev,
+ masks[ch]);
+
+ return r;
+}
+
static int __init omapfb_probe(struct platform_device *pdev)
{
struct omapfb2_device *fbdev = NULL;
int i;
struct omap_dss_device *def_display;
struct omap_dss_device *dssdev;
+ u16 fb_ov_start_ix = 0;
DBG("omapfb_probe\n");
r = -EINVAL;
goto cleanup;
}
-
fbdev->num_overlays = omap_dss_get_num_overlays();
for (i = 0; i < fbdev->num_overlays; i++)
fbdev->overlays[i] = omap_dss_get_overlay(i);
-
fbdev->num_managers = omap_dss_get_num_overlay_managers();
for (i = 0; i < fbdev->num_managers; i++)
fbdev->managers[i] = omap_dss_get_overlay_manager(i);
if (def_mode && strlen(def_mode) > 0) {
if (omapfb_parse_def_modes(fbdev))
dev_warn(&pdev->dev, "cannot parse default modes\n");
- } else if (def_display && def_display->driver->set_timings &&
- def_display->driver->check_timings) {
- struct omap_video_timings t;
+ }
- r = omapfb_find_best_mode(def_display, &t);
+ for (i = 0; i < fbdev->num_displays; ++i) {
+ struct omap_dss_device *dssdev;
+ dssdev = fbdev->displays[i].dssdev;
+ if (dssdev && dssdev->driver->set_timings &&
+ dssdev->driver->check_timings) {
+ struct omap_video_timings t;
+ r = omapfb_find_best_mode(dssdev, &t);
+ if (r == 0)
+ dssdev->driver->set_timings(dssdev, &t);
+ }
+ }
- if (r == 0)
- def_display->driver->set_timings(def_display, &t);
+ for (i = 0; i < fbdev->num_displays; i++) {
+ if (!intialize_dev_fb_resolution(i, fbdev->displays[i].dssdev))
+ goto cleanup;
}
+ fbdev->num_overlays = omap_dss_get_num_overlays();
+ if (def_display && check_fb_scale(def_display)) {
+ fb_ov_start_ix = 1;
+ fbdev->num_overlays -= 1;
+ }
+ for (i = 0; i < fbdev->num_overlays; i++)
+ fbdev->overlays[i] = omap_dss_get_overlay(i+fb_ov_start_ix);
r = omapfb_create_framebuffers(fbdev);
if (r)
goto cleanup;
goto cleanup;
}
+ INIT_WORK(&fbdev->vsync_work, omapfb_send_vsync_work);
return 0;
cleanup:
struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
/* FIXME: wait till completion of pending events */
+ /* TODO: terminate vsync thread */
omapfb_remove_sysfs(fbdev);
index 623cd872a36788f3dc8cccd25fa53b475995cb3a..6e45f984563d8680626d5044d0736c8a03633b30 100644 (file)
#include <linux/rwsem.h>
#include <linux/dma-attrs.h>
#include <linux/dma-mapping.h>
-
+#include <video/omapvrfb.h>
#include <video/omapdss.h>
#ifdef DEBUG
struct omap_overlay_manager *managers[10];
struct workqueue_struct *auto_update_wq;
+ unsigned num_bpp_overrides;
+ struct {
+ struct omap_dss_device *dssdev;
+ u8 bpp;
+ } bpp_overrides[10];
+
+ bool vsync_active;
+ ktime_t vsync_timestamp;
+ struct work_struct vsync_work;
};
struct omapfb_colormode {
int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode);
int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
+int omapfb_enable_vsync(struct omapfb2_device *fbdev, enum omap_channel ch,
+ bool enable);
+void get_fb_resolution(struct omap_dss_device *dssdev,
+ u16 *xres, u16 *yres);
+
/* find the display connected to this fb, if any */
static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
{
diff --git a/drivers/video/omap2/omaplfb/Kconfig b/drivers/video/omap2/omaplfb/Kconfig
--- /dev/null
@@ -0,0 +1,7 @@
+config OMAPLFB
+ bool "In-kernel omaplfb support"
+ depends on OMAP2_DSS && DSSCOMP
+ default n
+ help
+ Support for in-kernel omaplfb. This is an interface between display and the
+ kernel side PowerVR graphics driver.
diff --git a/drivers/video/omap2/omaplfb/Makefile b/drivers/video/omap2/omaplfb/Makefile
--- /dev/null
@@ -0,0 +1,18 @@
+obj-$(CONFIG_OMAPLFB) := omaplfb.o
+
+ccflags-y += \
+ -I$(KERNELDIR)/drivers/video/omap2 \
+ -I$(KERNELDIR)/arch/arm/plat-omap/include
+
+ccflags-y += \
+ -DLINUX \
+ -D__linux__ \
+ -D__KERNEL__ \
+ -DPVR_LINUX_USING_WORKQUEUES
+
+omaplfb-y += \
+ omaplfb_linux.o \
+ omaplfb_displayclass.o
+
+omaplfb-$(CONFIG_GCBV) += \
+ omaplfb_bv.o
diff --git a/drivers/video/omap2/omaplfb/img_defs.h b/drivers/video/omap2/omaplfb/img_defs.h
--- /dev/null
@@ -0,0 +1,154 @@
+/*************************************************************************/ /*!
+@Title Common header containing type definitions for portability
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Contains variable and structure definitions. Any platform
+ specific types should be defined in this file.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+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.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) 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; AND (B) 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.
+
+*/ /**************************************************************************/
+#if !defined (__IMG_DEFS_H__)
+#define __IMG_DEFS_H__
+
+#include "img_types.h"
+
+typedef enum img_tag_TriStateSwitch
+{
+ IMG_ON = 0x00,
+ IMG_OFF,
+ IMG_IGNORE
+
+} img_TriStateSwitch, * img_pTriStateSwitch;
+
+#define IMG_SUCCESS 0
+
+#define IMG_NO_REG 1
+
+#if defined (NO_INLINE_FUNCS)
+ #define INLINE
+ #define FORCE_INLINE
+#else
+#if defined (__cplusplus)
+ #define INLINE inline
+ #define FORCE_INLINE inline
+#else
+#if !defined(INLINE)
+ #define INLINE __inline
+#endif
+ #define FORCE_INLINE static __inline
+#endif
+#endif
+
+
+/* Use this in any file, or use attributes under GCC - see below */
+#ifndef PVR_UNREFERENCED_PARAMETER
+#define PVR_UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+/* The best way to supress unused parameter warnings using GCC is to use a
+ * variable attribute. Place the unref__ between the type and name of an
+ * unused parameter in a function parameter list, eg `int unref__ var'. This
+ * should only be used in GCC build environments, for example, in files that
+ * compile only on Linux. Other files should use UNREFERENCED_PARAMETER */
+#ifdef __GNUC__
+#define unref__ __attribute__ ((unused))
+#else
+#define unref__
+#endif
+
+/*
+ Wide character definitions
+*/
+#ifndef _TCHAR_DEFINED
+#if defined(UNICODE)
+typedef unsigned short TCHAR, *PTCHAR, *PTSTR;
+#else /* #if defined(UNICODE) */
+typedef char TCHAR, *PTCHAR, *PTSTR;
+#endif /* #if defined(UNICODE) */
+#define _TCHAR_DEFINED
+#endif /* #ifndef _TCHAR_DEFINED */
+
+
+ #if defined(__linux__) || defined(__QNXNTO__) || defined(__METAG)
+
+ #define IMG_CALLCONV
+ #define IMG_INTERNAL __attribute__((visibility("hidden")))
+ #define IMG_EXPORT __attribute__((visibility("default")))
+ #define IMG_IMPORT
+ #define IMG_RESTRICT __restrict__
+
+ #else
+ #error("define an OS")
+ #endif
+
+// Use default definition if not overridden
+#ifndef IMG_ABORT
+ #define IMG_ABORT() abort()
+#endif
+
+#ifndef IMG_MALLOC
+ #define IMG_MALLOC(A) malloc (A)
+#endif
+
+#ifndef IMG_FREE
+ #define IMG_FREE(A) free (A)
+#endif
+
+#define IMG_CONST const
+
+#if defined(__GNUC__)
+#define IMG_FORMAT_PRINTF(x,y) __attribute__((format(printf,x,y)))
+#else
+#define IMG_FORMAT_PRINTF(x,y)
+#endif
+
+/*
+ * Cleanup request defines
+ */
+#define CLEANUP_WITH_POLL IMG_FALSE
+#define FORCE_CLEANUP IMG_TRUE
+
+#if defined (_WIN64)
+#define IMG_UNDEF (~0ULL)
+#else
+#define IMG_UNDEF (~0UL)
+#endif
+
+#endif /* #if !defined (__IMG_DEFS_H__) */
+/*****************************************************************************
+ End of file (IMG_DEFS.H)
+*****************************************************************************/
diff --git a/drivers/video/omap2/omaplfb/img_types.h b/drivers/video/omap2/omaplfb/img_types.h
--- /dev/null
@@ -0,0 +1,215 @@
+/*************************************************************************/ /*!
+@Title Global types for use by IMG APIs
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Defines type aliases for use by IMG APIs.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+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.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) 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; AND (B) 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.
+
+*/ /**************************************************************************/
+#ifndef __IMG_TYPES_H__
+#define __IMG_TYPES_H__
+
+/* define all address space bit depths: */
+/* CPU virtual address space defaults to 32bits */
+#if !defined(IMG_ADDRSPACE_CPUVADDR_BITS)
+#define IMG_ADDRSPACE_CPUVADDR_BITS 32
+#endif
+
+/* Physical address space defaults to 32bits */
+#if !defined(IMG_ADDRSPACE_PHYSADDR_BITS)
+#define IMG_ADDRSPACE_PHYSADDR_BITS 32
+#endif
+
+typedef unsigned int IMG_UINT, *IMG_PUINT;
+typedef signed int IMG_INT, *IMG_PINT;
+
+typedef unsigned char IMG_UINT8, *IMG_PUINT8;
+typedef unsigned char IMG_BYTE, *IMG_PBYTE;
+typedef signed char IMG_INT8, *IMG_PINT8;
+typedef char IMG_CHAR, *IMG_PCHAR;
+
+typedef unsigned short IMG_UINT16, *IMG_PUINT16;
+typedef signed short IMG_INT16, *IMG_PINT16;
+#if !defined(IMG_UINT32_IS_ULONG)
+typedef unsigned int IMG_UINT32, *IMG_PUINT32;
+typedef signed int IMG_INT32, *IMG_PINT32;
+#else
+typedef unsigned long IMG_UINT32, *IMG_PUINT32;
+typedef signed long IMG_INT32, *IMG_PINT32;
+#endif
+#if !defined(IMG_UINT32_MAX)
+ #define IMG_UINT32_MAX 0xFFFFFFFFUL
+#endif
+
+#if defined(USE_CODE)
+
+typedef unsigned __int64 IMG_UINT64, *IMG_PUINT64;
+typedef __int64 IMG_INT64, *IMG_PINT64;
+
+#else
+ #if ((defined(LINUX) || defined(__METAG)) || defined(__QNXNTO__))
+ typedef unsigned long long IMG_UINT64, *IMG_PUINT64;
+ typedef long long IMG_INT64, *IMG_PINT64;
+ #else
+ #error("define an OS")
+ #endif
+#endif
+
+#if !(defined(LINUX) && defined (__KERNEL__))
+/* Linux kernel mode does not use floating point */
+typedef float IMG_FLOAT, *IMG_PFLOAT;
+typedef double IMG_DOUBLE, *IMG_PDOUBLE;
+#endif
+
+typedef enum tag_img_bool
+{
+ IMG_FALSE = 0,
+ IMG_TRUE = 1,
+ IMG_FORCE_ALIGN = 0x7FFFFFFF
+} IMG_BOOL, *IMG_PBOOL;
+
+typedef void IMG_VOID, *IMG_PVOID;
+
+typedef IMG_INT32 IMG_RESULT;
+
+#if defined(_WIN64)
+ typedef unsigned __int64 IMG_UINTPTR_T;
+ typedef signed __int64 IMG_PTRDIFF_T;
+ typedef IMG_UINT64 IMG_SIZE_T;
+#else
+ typedef unsigned int IMG_UINTPTR_T;
+ typedef IMG_UINT32 IMG_SIZE_T;
+#endif
+
+typedef IMG_PVOID IMG_HANDLE;
+
+typedef void** IMG_HVOID, * IMG_PHVOID;
+
+#define IMG_NULL 0
+
+/* services/stream ID */
+typedef IMG_UINT32 IMG_SID;
+
+typedef IMG_UINT32 IMG_EVENTSID;
+
+/*
+ * Address types.
+ * All types used to refer to a block of memory are wrapped in structures
+ * to enforce some degree of type safety, i.e. a IMG_DEV_VIRTADDR cannot
+ * be assigned to a variable of type IMG_DEV_PHYADDR because they are not the
+ * same thing.
+ *
+ * There is an assumption that the system contains at most one non-cpu mmu,
+ * and a memory block is only mapped by the MMU once.
+ *
+ * Different devices could have offset views of the physical address space.
+ *
+ */
+
+
+/*
+ *
+ * +------------+ +------------+ +------------+ +------------+
+ * | CPU | | DEV | | DEV | | DEV |
+ * +------------+ +------------+ +------------+ +------------+
+ * | | | |
+ * | PVOID |IMG_DEV_VIRTADDR |IMG_DEV_VIRTADDR |
+ * | \-------------------/ |
+ * | | |
+ * +------------+ +------------+ |
+ * | MMU | | MMU | |
+ * +------------+ +------------+ |
+ * | | |
+ * | | |
+ * | | |
+ * +--------+ +---------+ +--------+
+ * | Offset | | (Offset)| | Offset |
+ * +--------+ +---------+ +--------+
+ * | | IMG_DEV_PHYADDR |
+ * | | |
+ * | | IMG_DEV_PHYADDR |
+ * +---------------------------------------------------------------------+
+ * | System Address bus |
+ * +---------------------------------------------------------------------+
+ *
+ */
+
+typedef IMG_PVOID IMG_CPU_VIRTADDR;
+
+/* device virtual address */
+typedef struct _IMG_DEV_VIRTADDR
+{
+ /* device virtual addresses are 32bit for now */
+ IMG_UINT32 uiAddr;
+#define IMG_CAST_TO_DEVVADDR_UINT(var) (IMG_UINT32)(var)
+
+} IMG_DEV_VIRTADDR;
+
+typedef IMG_UINT32 IMG_DEVMEM_SIZE_T;
+
+/* cpu physical address */
+typedef struct _IMG_CPU_PHYADDR
+{
+ /* variable sized type (32,64) */
+ IMG_UINTPTR_T uiAddr;
+} IMG_CPU_PHYADDR;
+
+/* device physical address */
+typedef struct _IMG_DEV_PHYADDR
+{
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+ /* variable sized type (32,64) */
+ IMG_UINTPTR_T uiAddr;
+#else
+ IMG_UINT32 uiAddr;
+ IMG_UINT32 uiHighAddr;
+#endif
+} IMG_DEV_PHYADDR;
+
+/* system physical address */
+typedef struct _IMG_SYS_PHYADDR
+{
+ /* variable sized type (32,64) */
+ IMG_UINTPTR_T uiAddr;
+} IMG_SYS_PHYADDR;
+
+#include "img_defs.h"
+
+#endif /* __IMG_TYPES_H__ */
+/******************************************************************************
+ End of file (img_types.h)
+******************************************************************************/
diff --git a/drivers/video/omap2/omaplfb/kerneldisplay.h b/drivers/video/omap2/omaplfb/kerneldisplay.h
--- /dev/null
@@ -0,0 +1,244 @@
+/*************************************************************************/ /*!
+@Title Display device class API structures and prototypes
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides display device class API structures and prototypes
+ for kernel services to kernel 3rd party display.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+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.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) 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; AND (B) 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.
+
+*/ /**************************************************************************/
+
+#if !defined (__KERNELDISPLAY_H__)
+#define __KERNELDISPLAY_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef PVRSRV_ERROR (*PFN_OPEN_DC_DEVICE)(IMG_UINT32, IMG_HANDLE*, PVRSRV_SYNC_DATA*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_DC_DEVICE)(IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_FORMATS)(IMG_HANDLE, IMG_UINT32*, DISPLAY_FORMAT*);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_DIMS)(IMG_HANDLE,
+ DISPLAY_FORMAT*,
+ IMG_UINT32*,
+ DISPLAY_DIMS*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_SYSTEMBUFFER)(IMG_HANDLE, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_INFO)(IMG_HANDLE, DISPLAY_INFO*);
+typedef PVRSRV_ERROR (*PFN_CREATE_DC_SWAPCHAIN)(IMG_HANDLE,
+ IMG_UINT32,
+ DISPLAY_SURF_ATTRIBUTES*,
+ DISPLAY_SURF_ATTRIBUTES*,
+ IMG_UINT32,
+ PVRSRV_SYNC_DATA**,
+ IMG_UINT32,
+ IMG_HANDLE*,
+ IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DESTROY_DC_SWAPCHAIN)(IMG_HANDLE,
+ IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_GET_DC_BUFFERS)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_UINT32*,
+ IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_BUFFER)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_UINT32,
+ IMG_HANDLE,
+ IMG_UINT32,
+ IMG_RECT*);
+typedef IMG_VOID (*PFN_QUERY_SWAP_COMMAND_ID)(IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_UINT16*, IMG_BOOL*);
+typedef IMG_VOID (*PFN_SET_DC_STATE)(IMG_HANDLE, IMG_UINT32);
+
+/*
+ Function table for SRVKM->DISPLAY
+*/
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_OPEN_DC_DEVICE pfnOpenDCDevice;
+ PFN_CLOSE_DC_DEVICE pfnCloseDCDevice;
+ PFN_ENUM_DC_FORMATS pfnEnumDCFormats;
+ PFN_ENUM_DC_DIMS pfnEnumDCDims;
+ PFN_GET_DC_SYSTEMBUFFER pfnGetDCSystemBuffer;
+ PFN_GET_DC_INFO pfnGetDCInfo;
+ PFN_GET_BUFFER_ADDR pfnGetBufferAddr;
+ PFN_CREATE_DC_SWAPCHAIN pfnCreateDCSwapChain;
+ PFN_DESTROY_DC_SWAPCHAIN pfnDestroyDCSwapChain;
+ PFN_SET_DC_DSTRECT pfnSetDCDstRect;
+ PFN_SET_DC_SRCRECT pfnSetDCSrcRect;
+ PFN_SET_DC_DSTCK pfnSetDCDstColourKey;
+ PFN_SET_DC_SRCCK pfnSetDCSrcColourKey;
+ PFN_GET_DC_BUFFERS pfnGetDCBuffers;
+ PFN_SWAP_TO_DC_BUFFER pfnSwapToDCBuffer;
+ PFN_SET_DC_STATE pfnSetDCState;
+ PFN_QUERY_SWAP_COMMAND_ID pfnQuerySwapCommandID;
+
+} PVRSRV_DC_SRV2DISP_KMJTABLE;
+
+/* ISR callback pfn prototype */
+typedef IMG_BOOL (*PFN_ISR_HANDLER)(IMG_VOID*);
+
+/*
+ functions exported by kernel services for use by 3rd party kernel display class device driver
+*/
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_DISPLAY_DEV)(PVRSRV_DC_SRV2DISP_KMJTABLE*, IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_DISPLAY_DEV)(IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_OEM_FUNCTION)(IMG_UINT32, IMG_VOID*, IMG_UINT32, IMG_VOID*, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_COMMANDPROCLIST)(IMG_UINT32, PPFN_CMD_PROC,IMG_UINT32[][2], IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_COMMANDPROCLIST)(IMG_UINT32, IMG_UINT32);
+typedef IMG_VOID (*PFN_DC_CMD_COMPLETE)(IMG_HANDLE, IMG_BOOL);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_SYS_ISR)(PFN_ISR_HANDLER, IMG_VOID*, IMG_UINT32, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_POWER)(IMG_UINT32, PFN_PRE_POWER, PFN_POST_POWER,
+ PFN_PRE_CLOCKSPEED_CHANGE, PFN_POST_CLOCKSPEED_CHANGE,
+ IMG_HANDLE, PVRSRV_DEV_POWER_STATE, PVRSRV_DEV_POWER_STATE);
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_* PDC_MEM_INFO;
+
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_CPU_VADDR)(PDC_MEM_INFO, IMG_CPU_VIRTADDR *pVAddr);
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_CPU_PADDR)(PDC_MEM_INFO, IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr);
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_BYTE_SIZE)(PDC_MEM_INFO, IMG_SIZE_T *uByteSize);
+typedef IMG_BOOL (*PFN_DC_MEMINFO_IS_PHYS_CONTIG)(PDC_MEM_INFO);
+typedef PVRSRV_ERROR (*PFN_DC_GETBVHANDLE)(PDC_MEM_INFO, IMG_VOID **handle);
+typedef IMG_INT32 (*PFN_DC_MEMINFO_GET_MULTI_PLANE_CPU_PADDRS)(PDC_MEM_INFO, IMG_SIZE_T* puByteOffsets,
+ IMG_CPU_PHYADDR *pPAddrs, IMG_UINT32* pui32NumAddrOffsets);
+
+/*
+ Function table for DISPLAY->SRVKM
+*/
+typedef struct PVRSRV_DC_DISP2SRV_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_DC_REGISTER_DISPLAY_DEV pfnPVRSRVRegisterDCDevice;
+ PFN_DC_REMOVE_DISPLAY_DEV pfnPVRSRVRemoveDCDevice;
+ PFN_DC_OEM_FUNCTION pfnPVRSRVOEMFunction;
+ PFN_DC_REGISTER_COMMANDPROCLIST pfnPVRSRVRegisterCmdProcList;
+ PFN_DC_REMOVE_COMMANDPROCLIST pfnPVRSRVRemoveCmdProcList;
+ PFN_DC_CMD_COMPLETE pfnPVRSRVCmdComplete;
+ PFN_DC_REGISTER_SYS_ISR pfnPVRSRVRegisterSystemISRHandler;
+ PFN_DC_REGISTER_POWER pfnPVRSRVRegisterPowerDevice;
+ PFN_DC_CMD_COMPLETE pfnPVRSRVFreeCmdCompletePacket;
+ PFN_DC_MEMINFO_GET_CPU_VADDR pfnPVRSRVDCMemInfoGetCpuVAddr;
+ PFN_DC_MEMINFO_GET_CPU_PADDR pfnPVRSRVDCMemInfoGetCpuPAddr;
+ PFN_DC_MEMINFO_GET_BYTE_SIZE pfnPVRSRVDCMemInfoGetByteSize;
+ PFN_DC_MEMINFO_IS_PHYS_CONTIG pfnPVRSRVDCMemInfoIsPhysContig;
+ PFN_DC_GETBVHANDLE pfnPVRSRVDCMemInfoGetBvHandle;
+ PFN_DC_MEMINFO_GET_MULTI_PLANE_CPU_PADDRS pfnPVRSRVDCMemInfoGetCpuMultiPlanePAddr;
+
+} PVRSRV_DC_DISP2SRV_KMJTABLE, *PPVRSRV_DC_DISP2SRV_KMJTABLE;
+
+
+typedef struct DISPLAYCLASS_FLIP_COMMAND_TAG
+{
+ /* Ext Device Handle */
+ IMG_HANDLE hExtDevice;
+
+ /* Ext SwapChain Handle */
+ IMG_HANDLE hExtSwapChain;
+
+ /* Ext Buffer Handle (Buffer to Flip to) */
+ IMG_HANDLE hExtBuffer;
+
+ /* private tag */
+ IMG_HANDLE hPrivateTag;
+
+ /* number of clip rects */
+ IMG_UINT32 ui32ClipRectCount;
+
+ /* clip rects */
+ IMG_RECT *psClipRect;
+
+ /* number of vsync intervals between successive flips */
+ IMG_UINT32 ui32SwapInterval;
+
+} DISPLAYCLASS_FLIP_COMMAND;
+
+
+typedef struct DISPLAYCLASS_FLIP_COMMAND2_TAG
+{
+ /* Ext Device Handle */
+ IMG_HANDLE hExtDevice;
+
+ /* Ext SwapChain Handle */
+ IMG_HANDLE hExtSwapChain;
+
+ /* Unused field, padding for compatibility with above structure */
+ IMG_HANDLE hUnused;
+
+ /* number of vsync intervals between successive flips */
+ IMG_UINT32 ui32SwapInterval;
+
+ /* private data from userspace */
+ IMG_PVOID pvPrivData;
+
+ /* length of private data in bytes */
+ IMG_UINT32 ui32PrivDataLength;
+
+ /* meminfos */
+ PDC_MEM_INFO *ppsMemInfos;
+
+ /* number of meminfos */
+ IMG_UINT32 ui32NumMemInfos;
+
+} DISPLAYCLASS_FLIP_COMMAND2;
+
+/* start command IDs from 0 */
+#define DC_FLIP_COMMAND 0
+
+/* States used in PFN_SET_DC_STATE */
+#define DC_STATE_NO_FLUSH_COMMANDS 0
+#define DC_STATE_FLUSH_COMMANDS 1
+#define DC_STATE_FORCE_SWAP_TO_SYSTEM 2
+
+/* function to retrieve kernel services function table from kernel services */
+typedef IMG_BOOL (*PFN_DC_GET_PVRJTABLE)(PPVRSRV_DC_DISP2SRV_KMJTABLE);
+
+/* Prototype for platforms that access the JTable via linkage */
+IMG_IMPORT IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif/* #if !defined (__KERNELDISPLAY_H__) */
+
+/******************************************************************************
+ End of file (kerneldisplay.h)
+******************************************************************************/
diff --git a/drivers/video/omap2/omaplfb/omaplfb.h b/drivers/video/omap2/omaplfb/omaplfb.h
--- /dev/null
@@ -0,0 +1,334 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __OMAPLFB_H__
+#define __OMAPLFB_H__
+
+#include <linux/version.h>
+
+#include <asm/atomic.h>
+
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/notifier.h>
+#include <linux/mutex.h>
+#include <plat/sgx_omaplfb.h>
+
+#ifdef CONFIG_ION_OMAP
+#include <linux/ion.h>
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include <video/dsscomp.h>
+#include <linux/bltsville.h>
+#include <video/omap_hwc.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+#define OMAPLFB_CONSOLE_LOCK()
+#define OMAPLFB_CONSOLE_UNLOCK()
+#else
+#define OMAPLFB_CONSOLE_LOCK() acquire_console_sem()
+#define OMAPLFB_CONSOLE_UNLOCK() release_console_sem()
+#endif
+
+#define unref__ __attribute__ ((unused))
+
+typedef void * OMAPLFB_HANDLE;
+
+typedef bool OMAPLFB_BOOL, *OMAPLFB_PBOOL;
+#define OMAPLFB_FALSE false
+#define OMAPLFB_TRUE true
+
+typedef atomic_t OMAPLFB_ATOMIC_BOOL;
+
+typedef atomic_t OMAPLFB_ATOMIC_INT;
+
+typedef struct OMAPLFB_BUFFER_TAG
+{
+ struct OMAPLFB_BUFFER_TAG *psNext;
+ struct OMAPLFB_DEVINFO_TAG *psDevInfo;
+
+ struct work_struct sWork;
+
+
+ unsigned long ulYOffset;
+
+
+
+ IMG_SYS_PHYADDR sSysAddr;
+ IMG_CPU_VIRTADDR sCPUVAddr;
+ PVRSRV_SYNC_DATA *psSyncData;
+
+ OMAPLFB_HANDLE hCmdComplete;
+ unsigned long ulSwapInterval;
+ void *bvmap_handle;
+} OMAPLFB_BUFFER;
+
+typedef struct OMAPLFB_SWAPCHAIN_TAG
+{
+
+ unsigned int uiSwapChainID;
+
+
+ unsigned long ulBufferCount;
+
+
+ OMAPLFB_BUFFER *psBuffer;
+
+
+ struct workqueue_struct *psWorkQueue;
+
+
+ OMAPLFB_BOOL bNotVSynced;
+
+
+ int iBlankEvents;
+
+
+ unsigned int uiFBDevID;
+} OMAPLFB_SWAPCHAIN;
+
+typedef struct OMAPLFB_FBINFO_TAG
+{
+ unsigned long ulFBSize;
+ unsigned long ulBufferSize;
+ unsigned long ulRoundedBufferSize;
+ unsigned long ulWidth;
+ unsigned long ulHeight;
+ unsigned long ulByteStride;
+ unsigned long ulPhysicalWidthmm;
+ unsigned long ulPhysicalHeightmm;
+
+ IMG_SYS_PHYADDR sSysAddr;
+ IMG_CPU_VIRTADDR sCPUVAddr;
+
+
+ PVRSRV_PIXEL_FORMAT ePixelFormat;
+
+ OMAPLFB_BOOL bIs2D;
+ IMG_SYS_PHYADDR *psPageList;
+#if defined(CONFIG_DSSCOMP)
+ struct ion_handle *psIONHandle;
+ /* This is the ION handle for the blit framebuffers */
+ struct ion_handle *psBltFBsIonHndl;
+ /* The number of blit framebuffers */
+ IMG_UINT32 psBltFBsNo;
+ /* These are the BV handles for the framebuffers */
+ void **psBltFBsBvHndl;
+ /* Physical addresses of the blit framebuffers */
+ IMG_UINTPTR_T *psBltFBsBvPhys;
+ /* The current blit buffer index */
+ unsigned int iBltFBsIdx;
+ IMG_UINT uiBltFBsByteStride;
+ /* Buffer used to clear the screen */
+ void *pvClearBuffer;
+#endif
+ IMG_UINT32 uiBytesPerPixel;
+}OMAPLFB_FBINFO;
+
+typedef struct OMAPLFB_DEVINFO_TAG
+{
+
+ unsigned int uiFBDevID;
+
+
+ unsigned int uiPVRDevID;
+
+
+ struct mutex sCreateSwapChainMutex;
+
+
+ OMAPLFB_BUFFER sSystemBuffer;
+
+
+ PVRSRV_DC_DISP2SRV_KMJTABLE sPVRJTable;
+
+
+ PVRSRV_DC_SRV2DISP_KMJTABLE sDCJTable;
+
+
+ OMAPLFB_FBINFO sFBInfo;
+
+
+ OMAPLFB_SWAPCHAIN *psSwapChain;
+
+
+ unsigned int uiSwapChainID;
+
+
+ OMAPLFB_ATOMIC_BOOL sFlushCommands;
+
+
+ struct fb_info *psLINFBInfo;
+
+
+ struct notifier_block sLINNotifBlock;
+
+
+
+
+
+ IMG_DEV_VIRTADDR sDisplayDevVAddr;
+
+ DISPLAY_INFO sDisplayInfo;
+
+
+ DISPLAY_FORMAT sDisplayFormat;
+
+
+ DISPLAY_DIMS sDisplayDim;
+
+
+ OMAPLFB_ATOMIC_BOOL sBlanked;
+
+
+ OMAPLFB_ATOMIC_INT sBlankEvents;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+
+ OMAPLFB_ATOMIC_BOOL sEarlySuspendFlag;
+
+ struct early_suspend sEarlySuspend;
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+ OMAPLFB_ATOMIC_BOOL sLeaveVT;
+#endif
+
+} OMAPLFB_DEVINFO;
+
+struct omaplfb_device {
+ struct device *dev;
+};
+
+#define OMAPLFB_PAGE_SIZE 4096
+
+#ifdef DEBUG
+#define DEBUG_PRINTK(x) printk x
+#else
+#define DEBUG_PRINTK(x)
+#endif
+
+#define DISPLAY_DEVICE_NAME "PowerVR OMAP Linux Display Driver"
+#define DRVNAME "omaplfb"
+#define DEVNAME DRVNAME
+#define DRIVER_PREFIX DRVNAME
+
+typedef enum _OMAPLFB_ERROR_
+{
+ OMAPLFB_OK = 0,
+ OMAPLFB_ERROR_GENERIC = 1,
+ OMAPLFB_ERROR_OUT_OF_MEMORY = 2,
+ OMAPLFB_ERROR_TOO_FEW_BUFFERS = 3,
+ OMAPLFB_ERROR_INVALID_PARAMS = 4,
+ OMAPLFB_ERROR_INIT_FAILURE = 5,
+ OMAPLFB_ERROR_CANT_REGISTER_CALLBACK = 6,
+ OMAPLFB_ERROR_INVALID_DEVICE = 7,
+ OMAPLFB_ERROR_DEVICE_REGISTER_FAILED = 8,
+ OMAPLFB_ERROR_SET_UPDATE_MODE_FAILED = 9
+} OMAPLFB_ERROR;
+
+typedef enum _OMAPLFB_UPDATE_MODE_
+{
+ OMAPLFB_UPDATE_MODE_UNDEFINED = 0,
+ OMAPLFB_UPDATE_MODE_MANUAL = 1,
+ OMAPLFB_UPDATE_MODE_AUTO = 2,
+ OMAPLFB_UPDATE_MODE_DISABLED = 3
+} OMAPLFB_UPDATE_MODE;
+
+#ifndef UNREFERENCED_PARAMETER
+#define UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+OMAPLFB_ERROR OMAPLFBInit(void);
+OMAPLFB_ERROR OMAPLFBDeInit(void);
+
+OMAPLFB_DEVINFO *OMAPLFBGetDevInfoPtr(unsigned uiFBDevID);
+unsigned OMAPLFBMaxFBDevIDPlusOne(void);
+void *OMAPLFBAllocKernelMem(unsigned long ulSize);
+void OMAPLFBFreeKernelMem(void *pvMem);
+OMAPLFB_ERROR OMAPLFBGetLibFuncAddr(char *szFunctionName, PFN_DC_GET_PVRJTABLE *ppfnFuncTable);
+OMAPLFB_ERROR OMAPLFBCreateSwapQueue (OMAPLFB_SWAPCHAIN *psSwapChain);
+void OMAPLFBDestroySwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain);
+void OMAPLFBInitBufferForSwap(OMAPLFB_BUFFER *psBuffer);
+void OMAPLFBSwapHandler(OMAPLFB_BUFFER *psBuffer);
+void OMAPLFBQueueBufferForSwap(OMAPLFB_SWAPCHAIN *psSwapChain, OMAPLFB_BUFFER *psBuffer);
+void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer);
+OMAPLFB_UPDATE_MODE OMAPLFBGetUpdateMode(OMAPLFB_DEVINFO *psDevInfo);
+OMAPLFB_BOOL OMAPLFBSetUpdateMode(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_UPDATE_MODE eMode);
+OMAPLFB_BOOL OMAPLFBWaitForVSync(OMAPLFB_DEVINFO *psDevInfo);
+OMAPLFB_BOOL OMAPLFBManualSync(OMAPLFB_DEVINFO *psDevInfo);
+OMAPLFB_BOOL OMAPLFBCheckModeAndSync(OMAPLFB_DEVINFO *psDevInfo);
+OMAPLFB_ERROR OMAPLFBUnblankDisplay(OMAPLFB_DEVINFO *psDevInfo);
+OMAPLFB_ERROR OMAPLFBEnableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo);
+OMAPLFB_ERROR OMAPLFBDisableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo);
+void OMAPLFBCreateSwapChainLockInit(OMAPLFB_DEVINFO *psDevInfo);
+void OMAPLFBCreateSwapChainLockDeInit(OMAPLFB_DEVINFO *psDevInfo);
+void OMAPLFBCreateSwapChainLock(OMAPLFB_DEVINFO *psDevInfo);
+void OMAPLFBCreateSwapChainUnLock(OMAPLFB_DEVINFO *psDevInfo);
+void OMAPLFBAtomicBoolInit(OMAPLFB_ATOMIC_BOOL *psAtomic, OMAPLFB_BOOL bVal);
+void OMAPLFBAtomicBoolDeInit(OMAPLFB_ATOMIC_BOOL *psAtomic);
+void OMAPLFBAtomicBoolSet(OMAPLFB_ATOMIC_BOOL *psAtomic, OMAPLFB_BOOL bVal);
+OMAPLFB_BOOL OMAPLFBAtomicBoolRead(OMAPLFB_ATOMIC_BOOL *psAtomic);
+void OMAPLFBAtomicIntInit(OMAPLFB_ATOMIC_INT *psAtomic, int iVal);
+void OMAPLFBAtomicIntDeInit(OMAPLFB_ATOMIC_INT *psAtomic);
+void OMAPLFBAtomicIntSet(OMAPLFB_ATOMIC_INT *psAtomic, int iVal);
+int OMAPLFBAtomicIntRead(OMAPLFB_ATOMIC_INT *psAtomic);
+void OMAPLFBAtomicIntInc(OMAPLFB_ATOMIC_INT *psAtomic);
+IMG_UINT32 GetVramStart(OMAPLFB_DEVINFO *psDevInfo);
+unsigned long GetVramFBSize(OMAPLFB_DEVINFO *psDevInfo);
+unsigned long GetVramFBTotalSize(struct fb_info *psLINFBInfo);
+struct sgx_omaplfb_config *GetFBPlatConfig(int fbidx);
+
+#if defined (CONFIG_DSSCOMP)
+int meminfo_idx_valid(unsigned int meminfo_ix, int num_meminfos);
+#endif
+
+/* Blt stubs implemented when CONFIG_GCBV is enabled */
+IMG_BOOL OMAPLFBInitBlt(void);
+OMAPLFB_ERROR OMAPLFBInitBltFBs(OMAPLFB_DEVINFO *psDevInfo);
+void OMAPLFBDeInitBltFBs(OMAPLFB_DEVINFO *psDevInfo);
+void OMAPLFBGetBltFBsBvHndl(OMAPLFB_FBINFO *psPVRFBInfo, IMG_UINTPTR_T *ppPhysAddr);
+void OMAPLFBDoBlits(OMAPLFB_DEVINFO *psDevInfo, PDC_MEM_INFO *ppsMemInfos,
+ struct omap_hwc_blit_data *blit_data, IMG_UINT32 ui32NumMemInfos);
+
+#if defined(DEBUG)
+void OMAPLFBPrintInfo(OMAPLFB_DEVINFO *psDevInfo);
+#else
+#define OMAPLFBPrintInfo(psDevInfo)
+#endif
+
+#if defined(CONFIG_GCBV)
+/*
+ * This is the number of framebuffers rendered to by GC320
+ */
+#define OMAPLFB_NUM_BLT_FBS 2
+#endif /* CONFIG_GCBV */
+#endif /* __OMAPLFB_H__ */
diff --git a/drivers/video/omap2/omaplfb/omaplfb_bv.c b/drivers/video/omap2/omaplfb/omaplfb_bv.c
--- /dev/null
@@ -0,0 +1,592 @@
+/*
+ * BltsVille support in omaplfb
+ *
+ * Copyright (C) 2012 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/notifier.h>
+
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+#include <mach/tiler.h>
+#include <linux/gcbv-iface.h>
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "omaplfb.h"
+
+static int debugbv = 0;
+extern struct ion_client *gpsIONClient;
+
+/*
+ * Are the blit framebuffers in VRAM?
+ */
+#define OMAPLFB_BLT_FBS_VRAM 1
+/*
+ * GC needs buffers aligned to 8 pixels, we need the clear buffer honor this
+ * requirement, a 32bpp buffer with 8 pixels for the destination is enough.
+ */
+#define OMAPLFB_GCSTRIDE_PIXEL_ALIGN 8
+#define OMAPLFB_CLRBUFF_SZ OMAPLFB_GCSTRIDE_PIXEL_ALIGN * 4
+
+#define OMAPLFB_COMMAND_COUNT 1
+
+#define OMAPLFB_VSYNC_SETTLE_COUNT 5
+
+#define OMAPLFB_MAX_NUM_DEVICES FB_MAX
+#if (OMAPLFB_MAX_NUM_DEVICES > FB_MAX)
+#error "OMAPLFB_MAX_NUM_DEVICES must not be greater than FB_MAX"
+#endif
+
+static IMG_BOOL gbBvInterfacePresent;
+static struct bventry gsBvInterface;
+
+static void print_bvparams(struct bvbltparams *bltparams,
+ unsigned int pSrc1DescInfo, unsigned int pSrc2DescInfo)
+{
+ struct bvphysdesc *physdesc = NULL;
+ if (bltparams->flags & BVFLAG_BLEND)
+ {
+ printk(KERN_INFO "%s: param %s %x (%s), flags %ld\n",
+ "bv", "blend", bltparams->op.blend,
+ bltparams->op.blend == BVBLEND_SRC1OVER ? "src1over" : "??",
+ bltparams->flags);
+ }
+
+ if (bltparams->flags & BVFLAG_ROP)
+ {
+ printk(KERN_INFO "%s: param %s %x (%s), flags %ld\n",
+ "bv", "rop", bltparams->op.rop,
+ bltparams->op.rop == 0xCCCC ? "srccopy" : "??",
+ bltparams->flags);
+ }
+
+ if (bltparams->dstdesc->auxtype == BVAT_PHYSDESC)
+ physdesc = bltparams->dstdesc->auxptr;
+
+ printk(KERN_INFO "%s: dst %d,%d rect{%d,%d sz %d,%d}"
+ " stride %ld desc 0x%p\n", "bv",
+ bltparams->dstgeom->width,
+ bltparams->dstgeom->height,
+ bltparams->dstrect.left, bltparams->dstrect.top,
+ bltparams->dstrect.width, bltparams->dstrect.height,
+ bltparams->dstgeom->virtstride,
+ physdesc ? physdesc->pagearray : NULL);
+
+ printk(KERN_INFO "%s: src1 %d,%d rect{%d,%d sz %d,%d}"
+ " stride %ld, %s 0x%x (0x%x)\n", "bv",
+ bltparams->src1geom->width,
+ bltparams->src1geom->height, bltparams->src1rect.left,
+ bltparams->src1rect.top, bltparams->src1rect.width,
+ bltparams->src1rect.height, bltparams->src1geom->virtstride,
+ bltparams->src1.desc->auxtype == BVAT_PHYSDESC ? "phys" : "unk",
+ bltparams->src1.desc->auxtype == BVAT_PHYSDESC ? (unsigned int)bltparams->src1.desc : 0,
+ pSrc1DescInfo);
+
+ if (!(bltparams->flags & BVFLAG_BLEND))
+ return;
+
+ printk(KERN_INFO "%s: src2 %d,%d rect{%d,%d sz %d,%d}"
+ " stride %ld, %s 0x%x (0x%x)\n", "bv",
+ bltparams->src2geom->width,
+ bltparams->src2geom->height, bltparams->src2rect.left,
+ bltparams->src2rect.top, bltparams->src2rect.width,
+ bltparams->src2rect.height, bltparams->src2geom->virtstride,
+ bltparams->src2.desc->auxtype == BVAT_PHYSDESC ? "phys" : "unk",
+ bltparams->src2.desc->auxtype == BVAT_PHYSDESC ? (unsigned int)bltparams->src2.desc : 0,
+ pSrc2DescInfo);
+}
+
+void OMAPLFBGetBltFBsBvHndl(OMAPLFB_FBINFO *psPVRFBInfo, IMG_UINTPTR_T *ppPhysAddr)
+{
+ if (++psPVRFBInfo->iBltFBsIdx >= OMAPLFB_NUM_BLT_FBS)
+ {
+ psPVRFBInfo->iBltFBsIdx = 0;
+ }
+ *ppPhysAddr = psPVRFBInfo->psBltFBsBvPhys[psPVRFBInfo->iBltFBsIdx];
+}
+
+static OMAPLFB_ERROR InitBltFBsCommon(OMAPLFB_DEVINFO *psDevInfo)
+{
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ IMG_INT n = OMAPLFB_NUM_BLT_FBS;
+
+ psPVRFBInfo->psBltFBsNo = n;
+ psPVRFBInfo->psBltFBsIonHndl = NULL;
+ psPVRFBInfo->psBltFBsBvHndl = kzalloc(n * sizeof(*psPVRFBInfo->psBltFBsBvHndl), GFP_KERNEL);
+ if (!psPVRFBInfo->psBltFBsBvHndl)
+ {
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+
+ psPVRFBInfo->psBltFBsBvPhys = kzalloc(n * sizeof(*psPVRFBInfo->psBltFBsBvPhys), GFP_KERNEL);
+ if (!psPVRFBInfo->psBltFBsBvPhys)
+ {
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+
+ psPVRFBInfo->pvClearBuffer = kzalloc(OMAPLFB_CLRBUFF_SZ, GFP_KERNEL);
+ if (!psPVRFBInfo->pvClearBuffer)
+ {
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+
+ /* Freeing of resources is handled in deinit code */
+ return OMAPLFB_OK;
+}
+
+/*
+ * Initialize the blit framebuffers and create the Bltsville mappings, these
+ * buffers are separate from the swapchain to reduce complexity
+ */
+static OMAPLFB_ERROR InitBltFBsVram(OMAPLFB_DEVINFO *psDevInfo)
+{
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ IMG_UINT uiBltFBSize = psDevInfo->sFBInfo.ulHeight * psDevInfo->psLINFBInfo->fix.line_length;
+ IMG_UINT uiNumPages = uiBltFBSize >> PAGE_SHIFT;
+ IMG_UINT uiFb;
+
+ if (InitBltFBsCommon(psDevInfo) != OMAPLFB_OK)
+ {
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+ psPVRFBInfo->uiBltFBsByteStride = psDevInfo->psLINFBInfo->fix.line_length;
+
+ for (uiFb = 0; uiFb < psPVRFBInfo->psBltFBsNo; uiFb++)
+ {
+ unsigned long *pPaddrs;
+ enum bverror iBvErr;
+ IMG_UINT j;
+ struct bvbuffdesc *pBvDesc;
+ struct bvphysdesc *pBvPhysDesc;
+ IMG_UINT uiVramStart;
+ IMG_UINT uiFbOff;
+
+ pPaddrs = kzalloc(sizeof(*pPaddrs) *
+ uiNumPages, GFP_KERNEL);
+ if (!pPaddrs)
+ {
+ return OMAPLFB_ERROR_OUT_OF_MEMORY;
+ }
+
+ pBvPhysDesc = kzalloc(sizeof(*pBvPhysDesc), GFP_KERNEL);
+ if (!pBvPhysDesc)
+ {
+ kfree(pPaddrs);
+ return OMAPLFB_ERROR_OUT_OF_MEMORY;
+ }
+
+ pBvDesc = kzalloc(sizeof(*pBvDesc), GFP_KERNEL);
+ if (!pBvDesc)
+ {
+ kfree(pPaddrs);
+ kfree(pBvPhysDesc);
+ return OMAPLFB_ERROR_OUT_OF_MEMORY;
+ }
+ /*
+ * Handle the swapchain buffers being located in TILER2D or in
+ * VRAM
+ */
+ uiFbOff = psPVRFBInfo->bIs2D ? 0 :
+ psDevInfo->sFBInfo.ulRoundedBufferSize *
+ psDevInfo->psSwapChain->ulBufferCount;
+ uiVramStart = psDevInfo->psLINFBInfo->fix.smem_start + uiFbOff +
+ (uiBltFBSize * uiFb);
+
+ for(j = 0; j < uiNumPages; j++)
+ {
+ pPaddrs[j] = uiVramStart + (j * PAGE_SIZE);
+ }
+ psPVRFBInfo->psBltFBsBvPhys[uiFb] = pPaddrs[0];
+
+ pBvDesc->structsize = sizeof(*pBvDesc);
+ pBvDesc->auxtype = BVAT_PHYSDESC;
+ pBvPhysDesc->structsize = sizeof(*pBvPhysDesc);
+ pBvPhysDesc->pagesize = PAGE_SIZE;
+ pBvPhysDesc->pagearray = pPaddrs;
+ pBvPhysDesc->pagecount = uiNumPages;
+ pBvDesc->length = pBvPhysDesc->pagecount * pBvPhysDesc->pagesize;
+ pBvDesc->auxptr = pBvPhysDesc;
+
+ iBvErr = gsBvInterface.bv_map(pBvDesc);
+ if (iBvErr)
+ {
+ WARN(1, "%s: BV map Blt FB buffer failed %d\n",
+ __func__, iBvErr);
+ kfree(pBvDesc);
+ kfree(pBvPhysDesc);
+ kfree(pPaddrs);
+ return OMAPLFB_ERROR_GENERIC;
+ }
+ psPVRFBInfo->psBltFBsBvHndl[uiFb] = pBvDesc;
+ }
+ return OMAPLFB_OK;
+}
+
+static PVRSRV_ERROR InitBltFBsMapTiler2D(OMAPLFB_DEVINFO *psDevInfo)
+{
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
+ struct bvbuffdesc *pBvDesc;
+ struct bvphysdesc *pBvPhysDesc;
+ struct bventry *pBvEntry;
+ enum bverror eBvErr;
+ int iFB;
+ ion_phys_addr_t phys;
+ size_t size;
+ int res = PVRSRV_OK;
+
+ pBvEntry = &gsBvInterface;
+ ion_phys(gpsIONClient, psPVRFBInfo->psBltFBsIonHndl, &phys, &size);
+
+ for (iFB = 0; iFB < psPVRFBInfo->psBltFBsNo; iFB++)
+ {
+ unsigned long *pPageList;
+
+ struct tiler_view_t view;
+ int wpages = psPVRFBInfo->uiBltFBsByteStride >> PAGE_SHIFT;
+ int h = psLINFBInfo->var.yres;
+ int x, y;
+
+ phys += psPVRFBInfo->uiBltFBsByteStride * iFB;
+ pPageList = kzalloc(
+ wpages * h * sizeof(*pPageList),
+ GFP_KERNEL);
+ if ( !pPageList) {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": %s: Could not allocate page list\n",
+ __FUNCTION__);
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+ tilview_create(&view, phys, psLINFBInfo->var.xres, h);
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < wpages; x++) {
+ pPageList[y * wpages + x] = phys + view.v_inc * y
+ + (x << PAGE_SHIFT);
+ }
+ }
+ pBvDesc = kzalloc(sizeof(*pBvDesc), GFP_KERNEL);
+ pBvDesc->structsize = sizeof(*pBvDesc);
+ pBvDesc->auxtype = BVAT_PHYSDESC;
+
+ pBvPhysDesc = kzalloc(sizeof(*pBvPhysDesc), GFP_KERNEL);
+ pBvPhysDesc->pagesize = PAGE_SIZE;
+ pBvPhysDesc->pagearray = pPageList;
+ pBvPhysDesc->pagecount = wpages * h;
+
+ pBvDesc->auxptr = pBvPhysDesc;
+
+ eBvErr = pBvEntry->bv_map(pBvDesc);
+
+ pBvPhysDesc->pagearray = NULL;
+
+ if (eBvErr)
+ {
+ WARN(1, "%s: BV map blt buffer failed %d\n",__func__, eBvErr);
+ psPVRFBInfo->psBltFBsBvHndl[iFB]= NULL;
+ kfree(pBvDesc);
+ kfree(pBvPhysDesc);
+ res = PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ else
+ {
+ psPVRFBInfo->psBltFBsBvHndl[iFB] = pBvDesc;
+ psPVRFBInfo->psBltFBsBvPhys[iFB] = pPageList[0];
+ }
+ }
+
+ return res;
+}
+
+/*
+ * Allocate buffers from the blit 'framebuffers'. These buffers are not shared
+ * with the SGX flip chain to reduce complexity
+ */
+static OMAPLFB_ERROR InitBltFBsTiler2D(OMAPLFB_DEVINFO *psDevInfo)
+{
+ /*
+ * Pick up the calculated bytes per pixel from the deduced
+ * OMAPLFB_FBINFO, get the rest of the display parameters from the
+ * struct fb_info
+ */
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
+ int res, w, h;
+
+ struct omap_ion_tiler_alloc_data sAllocData = {
+ .fmt = psPVRFBInfo->uiBytesPerPixel == 2 ? TILER_PIXEL_FMT_16BIT : TILER_PIXEL_FMT_32BIT,
+ .flags = 0,
+ };
+
+ if (InitBltFBsCommon(psDevInfo) != OMAPLFB_OK)
+ {
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+ psPVRFBInfo->uiBltFBsByteStride = PAGE_ALIGN(psLINFBInfo->var.xres * psPVRFBInfo->uiBytesPerPixel);
+
+ /* TILER will align width to 128-bytes */
+ /* however, SGX must have full page width */
+ w = ALIGN(psLINFBInfo->var.xres, PAGE_SIZE / psPVRFBInfo->uiBytesPerPixel);
+ h = psLINFBInfo->var.yres;
+ sAllocData.h = h;
+ sAllocData.w = psPVRFBInfo->psBltFBsNo * w;
+
+ printk(KERN_INFO DRIVER_PREFIX
+ ":BltFBs alloc %d x (%d x %d) [stride %d]\n",
+ psPVRFBInfo->psBltFBsNo, w, h, psPVRFBInfo->uiBltFBsByteStride);
+ res = omap_ion_nonsecure_tiler_alloc(gpsIONClient, &sAllocData);
+ if (res < 0)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ "Could not allocate BltFBs\n");
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+
+ psPVRFBInfo->psBltFBsIonHndl = sAllocData.handle;
+
+ res = InitBltFBsMapTiler2D(psDevInfo);
+ if (res != OMAPLFB_OK)
+ {
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+ return OMAPLFB_OK;
+}
+
+static struct bvbuffdesc *GetBvDescriptor(OMAPLFB_DEVINFO *psDevInfo, PDC_MEM_INFO *ppsMemInfos, IMG_UINT32 ui32Idx, IMG_UINT32 ui32NumMemInfos)
+{
+ struct bvbuffdesc *pBvDesc;
+ if (!meminfo_idx_valid(ui32Idx, ui32NumMemInfos)) {
+ WARN(1, "%s: index out of range\n", __func__);
+ return NULL;
+ }
+
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetBvHandle(ppsMemInfos[ui32Idx], (IMG_VOID**)&pBvDesc);
+ WARN(!pBvDesc, "%s: null handle\n", __func__);
+ return pBvDesc;
+}
+
+static void OMAPLFBSetNV12Params(struct bvsurfgeom *geom, struct bvbuffdesc *desc)
+{
+ if (geom->format != OCDFMT_NV12)
+ return;
+
+ /* Fixup stride for NV12 format */
+ if (geom->orientation % 180 == 0)
+ geom->virtstride = (desc->length * 2) / (geom->height * 3);
+ else
+ geom->virtstride = (desc->length * 2) / (geom->width * 3);
+}
+
+void OMAPLFBDoBlits(OMAPLFB_DEVINFO *psDevInfo, PDC_MEM_INFO *ppsMemInfos, struct omap_hwc_blit_data *blit_data, IMG_UINT32 ui32NumMemInfos)
+{
+ struct rgz_blt_entry *entry_list;
+ struct bventry *bv_entry = &gsBvInterface;
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ int rgz_items = blit_data->rgz_items;
+ int j;
+ void* lastBatch = NULL;
+ unsigned int batchFlags;
+
+ /* DSS pipes are setup up to this point, we can begin blitting here */
+ entry_list = (struct rgz_blt_entry *) (blit_data->rgz_blts);
+ for (j = 0; j < rgz_items; j++)
+ {
+ struct rgz_blt_entry *entry = &entry_list[j];
+ enum bverror bv_error = 0;
+ unsigned int meminfo_ix;
+ unsigned int iSrc1DescInfo = 0, iSrc2DescInfo = 0;
+
+ /* Destination data */
+ entry->dstgeom.virtstride = psDevInfo->sFBInfo.uiBltFBsByteStride;
+ entry->bp.dstdesc = psPVRFBInfo->psBltFBsBvHndl[psPVRFBInfo->iBltFBsIdx];
+ entry->bp.dstgeom = &entry->dstgeom;
+ OMAPLFBSetNV12Params(entry->bp.dstgeom, entry->bp.dstdesc);
+
+ /* Src1 buffer data */
+ meminfo_ix = (unsigned int)entry->src1desc.auxptr;
+ if (meminfo_ix == -1)
+ {
+ /* Making fill with transparent pixels, fixup stride and clear buffer */
+ entry->bp.src1geom = &entry->src1geom;
+ entry->bp.src1geom->virtstride = OMAPLFB_CLRBUFF_SZ;
+ entry->bp.src1.desc = &entry->src1desc;
+ entry->bp.src1.desc->virtaddr = psPVRFBInfo->pvClearBuffer;
+ entry->bp.src1.desc->length = OMAPLFB_CLRBUFF_SZ;
+ }
+ else if (meminfo_ix & HWC_BLT_DESC_FLAG)
+ {
+ /* This code might be redundant? Do we want to ever blit out of the framebuffer? */
+ if (meminfo_ix & HWC_BLT_DESC_FB)
+ {
+ entry->bp.src1.desc = entry->bp.dstdesc;
+ entry->bp.src1geom = entry->bp.dstgeom;
+ }
+ else
+ {
+ WARN(1, "%s: Unable to determine scr1 buffer\n",
+ __func__);
+ continue;
+ }
+ }
+ else
+ {
+ struct bvbuffdesc *pBvDesc;
+ pBvDesc = GetBvDescriptor(psDevInfo, ppsMemInfos,
+ meminfo_ix, ui32NumMemInfos);
+ if (!pBvDesc)
+ continue;
+
+ entry->bp.src1.desc = pBvDesc;
+ entry->bp.src1geom = &entry->src1geom;
+ OMAPLFBSetNV12Params(entry->bp.src1geom, pBvDesc);
+ }
+
+ /* Src2 buffer data
+ * Check if this blit involves src2 as the FB or another
+ * buffer, if the last case is true then map the src2 buffer
+ */
+ if (entry->bp.flags & BVFLAG_BLEND)
+ {
+ meminfo_ix = (unsigned int)entry->src2desc.auxptr;
+ if (meminfo_ix & HWC_BLT_DESC_FLAG)
+ {
+ if (meminfo_ix & HWC_BLT_DESC_FB)
+ {
+ /* Blending with destination (FB) */
+ entry->bp.src2.desc = entry->bp.dstdesc;
+ entry->bp.src2geom = entry->bp.dstgeom;
+ }
+ else
+ {
+ WARN(1, "%s: Unable to determine scr2 buffer\n",
+ __func__);
+ continue;
+ }
+ }
+ else
+ {
+ struct bvbuffdesc *pBvDesc;
+ pBvDesc = GetBvDescriptor(psDevInfo,
+ ppsMemInfos, meminfo_ix,
+ ui32NumMemInfos);
+ if (!pBvDesc)
+ continue;
+
+ entry->bp.src2.desc = pBvDesc;
+ entry->bp.src2geom = &entry->src2geom;
+ OMAPLFBSetNV12Params(entry->bp.src2geom, pBvDesc);
+ }
+ }
+ else
+ {
+ entry->bp.src2.desc = NULL;
+ }
+
+ if (debugbv)
+ {
+ iSrc1DescInfo = (unsigned int)entry->src1desc.auxptr;
+ iSrc2DescInfo = (unsigned int)entry->src2desc.auxptr;
+ print_bvparams(&entry->bp, iSrc1DescInfo, iSrc2DescInfo);
+ }
+
+ batchFlags = entry->bp.flags & BVFLAG_BATCH_MASK;
+ switch (batchFlags) {
+ case BVFLAG_BATCH_CONTINUE:
+ case BVFLAG_BATCH_END:
+ entry->bp.batch = lastBatch;
+ break;
+ case BVFLAG_BATCH_BEGIN:
+ entry->bp.batch = NULL;
+ }
+
+ bv_error = bv_entry->bv_blt(&entry->bp);
+ if (bv_error)
+ printk(KERN_ERR "%s: blit failed %d\n",
+ __func__, bv_error);
+
+ if (batchFlags == BVFLAG_BATCH_BEGIN) {
+ /* cache the batch handle */
+ lastBatch = entry->bp.batch;
+ }
+ }
+}
+
+OMAPLFB_ERROR OMAPLFBInitBltFBs(OMAPLFB_DEVINFO *psDevInfo)
+{
+ return (OMAPLFB_BLT_FBS_VRAM) ? InitBltFBsVram(psDevInfo) : InitBltFBsTiler2D(psDevInfo);
+}
+
+void OMAPLFBDeInitBltFBs(OMAPLFB_DEVINFO *psDevInfo)
+{
+ struct bventry *bv_entry = &gsBvInterface;
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ struct bvbuffdesc *pBufDesc;
+
+ if (!gbBvInterfacePresent)
+ {
+ return;
+ }
+
+ if (psPVRFBInfo->pvClearBuffer) {
+ kfree(psPVRFBInfo->pvClearBuffer);
+ psPVRFBInfo->pvClearBuffer = NULL;
+ }
+
+ if (psPVRFBInfo->psBltFBsBvHndl)
+ {
+ IMG_INT i;
+ for (i = 0; i < psPVRFBInfo->psBltFBsNo; i++)
+ {
+ pBufDesc = psPVRFBInfo->psBltFBsBvHndl[i];
+ if (pBufDesc)
+ {
+ struct bvphysdesc *pPhyDesc;
+ bv_entry->bv_unmap(pBufDesc);
+ pPhyDesc = (struct bvphysdesc*) pBufDesc->auxptr;
+ kfree(pPhyDesc->pagearray);
+ kfree(pPhyDesc);
+ kfree(pBufDesc);
+ }
+ }
+ kfree(psPVRFBInfo->psBltFBsBvHndl);
+ psPVRFBInfo->psBltFBsBvHndl = NULL;
+ }
+
+ if (psPVRFBInfo->psBltFBsIonHndl)
+ {
+ ion_free(gpsIONClient, psPVRFBInfo->psBltFBsIonHndl);
+ psPVRFBInfo->psBltFBsIonHndl = NULL;
+ }
+}
+
+IMG_BOOL OMAPLFBInitBlt(void)
+{
+#if defined(CONFIG_GCBV)
+ /* Get the GC2D Bltsville implementation */
+ gcbv_init(&gsBvInterface);
+ gbBvInterfacePresent = gsBvInterface.bv_map ? IMG_TRUE : IMG_FALSE;
+#else
+ gbBvInterfacePresent = IMG_FALSE;
+#endif
+ return gbBvInterfacePresent;
+}
diff --git a/drivers/video/omap2/omaplfb/omaplfb_displayclass.c b/drivers/video/omap2/omaplfb/omaplfb_displayclass.c
--- /dev/null
@@ -0,0 +1,1843 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/notifier.h>
+#include <plat/sgx_omaplfb.h>
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "omaplfb.h"
+
+/*
+ * Just use CONFIG_DSSCOMP to distinguish code which previously had
+ * additional mixes of CONFIG_TI_TILER and CONFIG_ION_OMAP. DSSCOMP makes
+ * it a given that ION and the TILER will be used.
+ * For kernel 3.4 we use CONFIG_DRM_OMAP_DMM_TILER instead of CONFIG_TI_TILER
+ */
+#if defined(CONFIG_DSSCOMP)
+#if !defined(CONFIG_ION_OMAP)
+#error Expected CONFIG_ION_OMAP to be defined
+#endif
+#if defined(CONFIG_DRM_OMAP_DMM_TILER)
+#include <../drivers/gpu/drm/omapdrm/omap_dmm_tiler.h>
+#include <../drivers/video/omap2/dsscomp/tiler-utils.h>
+#elif defined(CONFIG_TI_TILER)
+#include <mach/tiler.h>
+#else
+#error Expected CONFIG_DRM_OMAP_DMM_TILER or CONFIG_TI_TILER to be defined
+#endif
+
+#ifndef DSS_MAX_NUMBER_YUV_PLANES
+#define DSS_MAX_NUMBER_YUV_PLANES 2
+#endif
+
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+#include <video/omap_hwc.h>
+
+extern struct ion_device *omap_ion_device;
+struct ion_client *gpsIONClient;
+
+#endif
+
+#define OMAPLFB_COMMAND_COUNT 1
+
+#define OMAPLFB_VSYNC_SETTLE_COUNT 5
+
+#define OMAPLFB_MAX_NUM_DEVICES FB_MAX
+#if (OMAPLFB_MAX_NUM_DEVICES > FB_MAX)
+#error "OMAPLFB_MAX_NUM_DEVICES must not be greater than FB_MAX"
+#endif
+
+static OMAPLFB_DEVINFO *gapsDevInfo[OMAPLFB_MAX_NUM_DEVICES];
+
+static PFN_DC_GET_PVRJTABLE gpfnGetPVRJTable = NULL;
+
+static IMG_BOOL gbBvInterfacePresent;
+static IMG_BOOL gbBvReady = IMG_FALSE;
+static IMG_BOOL bBltReady = IMG_FALSE;
+
+static inline unsigned long RoundUpToMultiple(unsigned long x, unsigned long y)
+{
+ unsigned long div = x / y;
+ unsigned long rem = x % y;
+
+ return (div + ((rem == 0) ? 0 : 1)) * y;
+}
+
+static unsigned long GCD(unsigned long x, unsigned long y)
+{
+ while (y != 0)
+ {
+ unsigned long r = x % y;
+ x = y;
+ y = r;
+ }
+
+ return x;
+}
+
+static unsigned long LCM(unsigned long x, unsigned long y)
+{
+ unsigned long gcd = GCD(x, y);
+
+ return (gcd == 0) ? 0 : ((x / gcd) * y);
+}
+
+unsigned OMAPLFBMaxFBDevIDPlusOne(void)
+{
+ return OMAPLFB_MAX_NUM_DEVICES;
+}
+
+OMAPLFB_DEVINFO *OMAPLFBGetDevInfoPtr(unsigned uiFBDevID)
+{
+ WARN_ON(uiFBDevID >= OMAPLFBMaxFBDevIDPlusOne());
+
+ if (uiFBDevID >= OMAPLFB_MAX_NUM_DEVICES)
+ {
+ return NULL;
+ }
+
+ return gapsDevInfo[uiFBDevID];
+}
+
+static inline void OMAPLFBSetDevInfoPtr(unsigned uiFBDevID, OMAPLFB_DEVINFO *psDevInfo)
+{
+ WARN_ON(uiFBDevID >= OMAPLFB_MAX_NUM_DEVICES);
+
+ if (uiFBDevID < OMAPLFB_MAX_NUM_DEVICES)
+ {
+ gapsDevInfo[uiFBDevID] = psDevInfo;
+ }
+}
+
+static inline OMAPLFB_BOOL SwapChainHasChanged(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_SWAPCHAIN *psSwapChain)
+{
+ return (psDevInfo->psSwapChain != psSwapChain) ||
+ (psDevInfo->uiSwapChainID != psSwapChain->uiSwapChainID);
+}
+
+static inline OMAPLFB_BOOL DontWaitForVSync(OMAPLFB_DEVINFO *psDevInfo)
+{
+ OMAPLFB_BOOL bDontWait;
+
+ bDontWait = OMAPLFBAtomicBoolRead(&psDevInfo->sBlanked) ||
+ OMAPLFBAtomicBoolRead(&psDevInfo->sFlushCommands);
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ bDontWait = bDontWait || OMAPLFBAtomicBoolRead(&psDevInfo->sEarlySuspendFlag);
+#endif
+#if defined(SUPPORT_DRI_DRM)
+ bDontWait = bDontWait || OMAPLFBAtomicBoolRead(&psDevInfo->sLeaveVT);
+#endif
+ return bDontWait;
+}
+
+static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
+{
+ OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)hDevice;
+
+ switch (ui32State)
+ {
+ case DC_STATE_FLUSH_COMMANDS:
+ OMAPLFBAtomicBoolSet(&psDevInfo->sFlushCommands, OMAPLFB_TRUE);
+ break;
+ case DC_STATE_FORCE_SWAP_TO_SYSTEM:
+ OMAPLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer);
+ break;
+ case DC_STATE_NO_FLUSH_COMMANDS:
+ OMAPLFBAtomicBoolSet(&psDevInfo->sFlushCommands, OMAPLFB_FALSE);
+ break;
+ default:
+ break;
+ }
+}
+
+static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 uiPVRDevID,
+ IMG_HANDLE *phDevice,
+ PVRSRV_SYNC_DATA* psSystemBufferSyncData)
+{
+ OMAPLFB_DEVINFO *psDevInfo;
+ OMAPLFB_ERROR eError;
+ unsigned uiMaxFBDevIDPlusOne = OMAPLFBMaxFBDevIDPlusOne();
+ unsigned i;
+
+ for (i = 0; i < uiMaxFBDevIDPlusOne; i++)
+ {
+ psDevInfo = OMAPLFBGetDevInfoPtr(i);
+ if (psDevInfo != NULL && psDevInfo->uiPVRDevID == uiPVRDevID)
+ {
+ break;
+ }
+ }
+ if (i == uiMaxFBDevIDPlusOne)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
+ ": %s: PVR Device %u not found\n", __FUNCTION__, uiPVRDevID));
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+
+
+ psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
+
+ eError = OMAPLFBUnblankDisplay(psDevInfo);
+ if (eError != OMAPLFB_OK)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
+ ": %s: Device %u: OMAPLFBUnblankDisplay failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eError));
+ return PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED;
+ }
+
+
+ *phDevice = (IMG_HANDLE)psDevInfo;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE hDevice)
+{
+#if defined(SUPPORT_DRI_DRM)
+ OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)hDevice;
+
+ OMAPLFBAtomicBoolSet(&psDevInfo->sLeaveVT, OMAPLFB_FALSE);
+ (void) OMAPLFBUnblankDisplay(psDevInfo);
+#else
+ UNREFERENCED_PARAMETER(hDevice);
+#endif
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE hDevice,
+ IMG_UINT32 *pui32NumFormats,
+ DISPLAY_FORMAT *psFormat)
+{
+ OMAPLFB_DEVINFO *psDevInfo;
+
+ if(!hDevice || !pui32NumFormats)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
+
+ *pui32NumFormats = 1;
+
+ if(psFormat)
+ {
+ psFormat[0] = psDevInfo->sDisplayFormat;
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnumDCDims(IMG_HANDLE hDevice,
+ DISPLAY_FORMAT *psFormat,
+ IMG_UINT32 *pui32NumDims,
+ DISPLAY_DIMS *psDim)
+{
+ OMAPLFB_DEVINFO *psDevInfo;
+
+ if(!hDevice || !psFormat || !pui32NumDims)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
+
+ *pui32NumDims = 1;
+
+
+ if(psDim)
+ {
+ psDim[0] = psDevInfo->sDisplayDim;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE hDevice, IMG_HANDLE *phBuffer)
+{
+ OMAPLFB_DEVINFO *psDevInfo;
+
+ if(!hDevice || !phBuffer)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
+
+ *phBuffer = (IMG_HANDLE)&psDevInfo->sSystemBuffer;
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR GetDCInfo(IMG_HANDLE hDevice, DISPLAY_INFO *psDCInfo)
+{
+ OMAPLFB_DEVINFO *psDevInfo;
+
+ if(!hDevice || !psDCInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
+
+ *psDCInfo = psDevInfo->sDisplayInfo;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE hDevice,
+ IMG_HANDLE hBuffer,
+ IMG_SYS_PHYADDR **ppsSysAddr,
+ IMG_UINT32 *pui32ByteSize,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMapInfo,
+ IMG_BOOL *pbIsContiguous,
+ IMG_UINT32 *pui32TilingStride)
+{
+ OMAPLFB_DEVINFO *psDevInfo;
+ OMAPLFB_BUFFER *psSystemBuffer;
+
+ UNREFERENCED_PARAMETER(pui32TilingStride);
+
+ if(!hDevice)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(!hBuffer)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (!ppsSysAddr)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (!pui32ByteSize)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
+
+ psSystemBuffer = (OMAPLFB_BUFFER *)hBuffer;
+
+ *ppsSysAddr = &psSystemBuffer->sSysAddr;
+
+ *pui32ByteSize = (IMG_UINT32)psDevInfo->sFBInfo.ulBufferSize;
+
+ if (ppvCpuVAddr)
+ {
+ *ppvCpuVAddr = psDevInfo->sFBInfo.bIs2D ? NULL : psSystemBuffer->sCPUVAddr;
+ }
+
+ if (phOSMapInfo)
+ {
+ *phOSMapInfo = (IMG_HANDLE)0;
+ }
+
+ if (pbIsContiguous)
+ {
+ *pbIsContiguous = !psDevInfo->sFBInfo.bIs2D;
+ }
+
+#if defined(CONFIG_DSSCOMP)
+ if (psDevInfo->sFBInfo.bIs2D) {
+ int i = (psSystemBuffer->sSysAddr.uiAddr - psDevInfo->sFBInfo.psPageList->uiAddr) >> PAGE_SHIFT;
+ *ppsSysAddr = psDevInfo->sFBInfo.psPageList + psDevInfo->sFBInfo.ulHeight * i;
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ PVRSRV_SYNC_DATA **ppsSyncData,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_HANDLE *phSwapChain,
+ IMG_UINT32 *pui32SwapChainID)
+{
+ OMAPLFB_DEVINFO *psDevInfo;
+ OMAPLFB_SWAPCHAIN *psSwapChain;
+ OMAPLFB_BUFFER *psBuffer;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+
+ UNREFERENCED_PARAMETER(ui32OEMFlags);
+
+
+ if(!hDevice
+ || !psDstSurfAttrib
+ || !psSrcSurfAttrib
+ || !ppsSyncData
+ || !phSwapChain)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
+
+
+ if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0)
+ {
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+ }
+
+ OMAPLFBCreateSwapChainLock(psDevInfo);
+
+
+ if(psDevInfo->psSwapChain != NULL)
+ {
+ eError = PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
+ goto ExitUnLock;
+ }
+
+
+ if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
+ {
+ eError = PVRSRV_ERROR_TOOMANYBUFFERS;
+ goto ExitUnLock;
+ }
+
+ if ((psDevInfo->sFBInfo.ulRoundedBufferSize * (unsigned long)ui32BufferCount) > psDevInfo->sFBInfo.ulFBSize)
+ {
+ eError = PVRSRV_ERROR_TOOMANYBUFFERS;
+ goto ExitUnLock;
+ }
+
+ if(psDstSurfAttrib->pixelformat != psDevInfo->sDisplayFormat.pixelformat
+ || psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sDisplayDim.ui32ByteStride
+ || psDstSurfAttrib->sDims.ui32Width != psDevInfo->sDisplayDim.ui32Width
+ || psDstSurfAttrib->sDims.ui32Height != psDevInfo->sDisplayDim.ui32Height)
+ {
+
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto ExitUnLock;
+ }
+
+ if(psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat
+ || psDstSurfAttrib->sDims.ui32ByteStride != psSrcSurfAttrib->sDims.ui32ByteStride
+ || psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width
+ || psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height)
+ {
+
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto ExitUnLock;
+ }
+
+ UNREFERENCED_PARAMETER(ui32Flags);
+
+#if defined(PVR_OMAPFB3_UPDATE_MODE)
+ if (!OMAPLFBSetUpdateMode(psDevInfo, PVR_OMAPFB3_UPDATE_MODE))
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set frame buffer update mode %d\n", __FUNCTION__, psDevInfo->uiFBDevID, PVR_OMAPFB3_UPDATE_MODE);
+ }
+#endif
+
+ psSwapChain = (OMAPLFB_SWAPCHAIN*)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_SWAPCHAIN));
+ if(!psSwapChain)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ExitUnLock;
+ }
+
+ psBuffer = (OMAPLFB_BUFFER*)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_BUFFER) * ui32BufferCount);
+ if(!psBuffer)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorFreeSwapChain;
+ }
+
+ psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount;
+ psSwapChain->psBuffer = psBuffer;
+ psSwapChain->bNotVSynced = OMAPLFB_TRUE;
+ psSwapChain->uiFBDevID = psDevInfo->uiFBDevID;
+
+
+ for(i=0; i<ui32BufferCount-1; i++)
+ {
+ psBuffer[i].psNext = &psBuffer[i+1];
+ }
+
+ psBuffer[i].psNext = &psBuffer[0];
+
+ for(i=0; i<ui32BufferCount; i++)
+ {
+ IMG_UINT32 ui32SwapBuffer = i;
+ IMG_UINT32 ui32BufferOffset = ui32SwapBuffer * (IMG_UINT32)psDevInfo->sFBInfo.ulRoundedBufferSize;
+ if (psDevInfo->sFBInfo.bIs2D)
+ {
+ ui32BufferOffset = 0;
+ }
+
+ psBuffer[i].psSyncData = ppsSyncData[i];
+ psBuffer[i].sSysAddr.uiAddr = psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset;
+ psBuffer[i].sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr + ui32BufferOffset;
+ psBuffer[i].ulYOffset = ui32BufferOffset / psDevInfo->sFBInfo.ulByteStride;
+ if (psDevInfo->sFBInfo.bIs2D)
+ {
+ psBuffer[i].sSysAddr.uiAddr += ui32SwapBuffer *
+ ALIGN((IMG_UINT32)psDevInfo->sFBInfo.ulWidth * psDevInfo->sFBInfo.uiBytesPerPixel, PAGE_SIZE);
+ }
+ psBuffer[i].psDevInfo = psDevInfo;
+ OMAPLFBInitBufferForSwap(&psBuffer[i]);
+ psBuffer[i].bvmap_handle = NULL;
+ }
+
+
+ if (OMAPLFBCreateSwapQueue(psSwapChain) != OMAPLFB_OK)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Failed to create workqueue\n", __FUNCTION__, psDevInfo->uiFBDevID);
+ eError = PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+ goto ErrorFreeBuffers;
+ }
+
+ if (OMAPLFBEnableLFBEventNotification(psDevInfo)!= OMAPLFB_OK)
+ {
+ eError = PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT;
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't enable framebuffer event notification\n", __FUNCTION__, psDevInfo->uiFBDevID);
+ goto ErrorDestroySwapQueue;
+ }
+
+ psDevInfo->uiSwapChainID++;
+ if (psDevInfo->uiSwapChainID == 0)
+ {
+ psDevInfo->uiSwapChainID++;
+ }
+
+ psSwapChain->uiSwapChainID = psDevInfo->uiSwapChainID;
+
+ psDevInfo->psSwapChain = psSwapChain;
+
+ *pui32SwapChainID = psDevInfo->uiSwapChainID;
+
+ *phSwapChain = (IMG_HANDLE)psSwapChain;
+
+ eError = PVRSRV_OK;
+ goto ExitUnLock;
+
+ErrorDestroySwapQueue:
+ OMAPLFBDestroySwapQueue(psSwapChain);
+ErrorFreeBuffers:
+ OMAPLFBFreeKernelMem(psBuffer);
+ErrorFreeSwapChain:
+ OMAPLFBFreeKernelMem(psSwapChain);
+ExitUnLock:
+ OMAPLFBCreateSwapChainUnLock(psDevInfo);
+ return eError;
+}
+
+static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain)
+{
+ OMAPLFB_DEVINFO *psDevInfo;
+ OMAPLFB_SWAPCHAIN *psSwapChain;
+ OMAPLFB_ERROR eError;
+
+ if(!hDevice || !hSwapChain)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
+ psSwapChain = (OMAPLFB_SWAPCHAIN*)hSwapChain;
+
+ OMAPLFBCreateSwapChainLock(psDevInfo);
+
+ if (SwapChainHasChanged(psDevInfo, psSwapChain))
+ {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": %s: Device %u: Swap chain mismatch\n", __FUNCTION__, psDevInfo->uiFBDevID);
+
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto ExitUnLock;
+ }
+
+
+ OMAPLFBDestroySwapQueue(psSwapChain);
+
+ eError = OMAPLFBDisableLFBEventNotification(psDevInfo);
+ if (eError != OMAPLFB_OK)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't disable framebuffer event notification\n", __FUNCTION__, psDevInfo->uiFBDevID);
+ }
+
+ OMAPLFBDeInitBltFBs(psDevInfo);
+ gbBvReady = IMG_FALSE;
+ bBltReady = IMG_FALSE;
+
+ OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
+ OMAPLFBFreeKernelMem(psSwapChain);
+
+ psDevInfo->psSwapChain = NULL;
+
+ OMAPLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer);
+ (void) OMAPLFBCheckModeAndSync(psDevInfo);
+
+ eError = PVRSRV_OK;
+
+ExitUnLock:
+ OMAPLFBCreateSwapChainUnLock(psDevInfo);
+
+ return eError;
+}
+
+static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect)
+{
+ UNREFERENCED_PARAMETER(hDevice);
+ UNREFERENCED_PARAMETER(hSwapChain);
+ UNREFERENCED_PARAMETER(psRect);
+
+
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect)
+{
+ UNREFERENCED_PARAMETER(hDevice);
+ UNREFERENCED_PARAMETER(hSwapChain);
+ UNREFERENCED_PARAMETER(psRect);
+
+
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour)
+{
+ UNREFERENCED_PARAMETER(hDevice);
+ UNREFERENCED_PARAMETER(hSwapChain);
+ UNREFERENCED_PARAMETER(ui32CKColour);
+
+
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour)
+{
+ UNREFERENCED_PARAMETER(hDevice);
+ UNREFERENCED_PARAMETER(hSwapChain);
+ UNREFERENCED_PARAMETER(ui32CKColour);
+
+
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 *pui32BufferCount,
+ IMG_HANDLE *phBuffer)
+{
+ OMAPLFB_DEVINFO *psDevInfo;
+ OMAPLFB_SWAPCHAIN *psSwapChain;
+ PVRSRV_ERROR eError;
+ unsigned i;
+
+
+ if(!hDevice
+ || !hSwapChain
+ || !pui32BufferCount
+ || !phBuffer)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
+ psSwapChain = (OMAPLFB_SWAPCHAIN*)hSwapChain;
+
+ OMAPLFBCreateSwapChainLock(psDevInfo);
+
+ if (SwapChainHasChanged(psDevInfo, psSwapChain))
+ {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": %s: Device %u: Swap chain mismatch\n", __FUNCTION__, psDevInfo->uiFBDevID);
+
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto Exit;
+ }
+
+
+ *pui32BufferCount = (IMG_UINT32)psSwapChain->ulBufferCount;
+
+
+ for(i=0; i<psSwapChain->ulBufferCount; i++)
+ {
+ phBuffer[i] = (IMG_HANDLE)&psSwapChain->psBuffer[i];
+ }
+
+ eError = PVRSRV_OK;
+
+Exit:
+ OMAPLFBCreateSwapChainUnLock(psDevInfo);
+
+ return eError;
+}
+
+static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE hDevice,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32SwapInterval,
+ IMG_HANDLE hPrivateTag,
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect)
+{
+ UNREFERENCED_PARAMETER(hDevice);
+ UNREFERENCED_PARAMETER(hBuffer);
+ UNREFERENCED_PARAMETER(ui32SwapInterval);
+ UNREFERENCED_PARAMETER(hPrivateTag);
+ UNREFERENCED_PARAMETER(ui32ClipRectCount);
+ UNREFERENCED_PARAMETER(psClipRect);
+
+
+
+ return PVRSRV_OK;
+}
+
+#if !defined(CONFIG_GCBV)
+IMG_BOOL OMAPLFBInitBlt(void)
+{
+ return IMG_FALSE;
+}
+
+OMAPLFB_ERROR OMAPLFBInitBltFBs(OMAPLFB_DEVINFO *psDevInfo)
+{
+ return OMAPLFB_ERROR_INIT_FAILURE;
+}
+
+void OMAPLFBDeInitBltFBs(OMAPLFB_DEVINFO *psDevInfo)
+{
+}
+
+void OMAPLFBGetBltFBsBvHndl(OMAPLFB_FBINFO *psPVRFBInfo, IMG_UINTPTR_T *ppPhysAddr)
+{
+ *ppPhysAddr = 0;
+}
+
+void OMAPLFBDoBlits(OMAPLFB_DEVINFO *psDevInfo, PDC_MEM_INFO *ppsMemInfos, struct omap_hwc_blit_data *blit_data, IMG_UINT32 ui32NumMemInfos)
+{
+}
+#endif /* CONFIG_GCBV */
+static OMAPLFB_BOOL WaitForVSyncSettle(OMAPLFB_DEVINFO *psDevInfo)
+{
+ unsigned i;
+ for(i = 0; i < OMAPLFB_VSYNC_SETTLE_COUNT; i++)
+ {
+ if (DontWaitForVSync(psDevInfo) || !OMAPLFBWaitForVSync(psDevInfo))
+ {
+ return OMAPLFB_FALSE;
+ }
+ }
+
+ return OMAPLFB_TRUE;
+}
+
+void OMAPLFBSwapHandler(OMAPLFB_BUFFER *psBuffer)
+{
+ OMAPLFB_DEVINFO *psDevInfo = psBuffer->psDevInfo;
+ OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
+ OMAPLFB_BOOL bPreviouslyNotVSynced;
+
+#if defined(SUPPORT_DRI_DRM)
+ if (!OMAPLFBAtomicBoolRead(&psDevInfo->sLeaveVT))
+#endif
+ {
+ OMAPLFBFlip(psDevInfo, psBuffer);
+ }
+
+ bPreviouslyNotVSynced = psSwapChain->bNotVSynced;
+ psSwapChain->bNotVSynced = OMAPLFB_TRUE;
+
+
+ if (!DontWaitForVSync(psDevInfo))
+ {
+ OMAPLFB_UPDATE_MODE eMode = OMAPLFBGetUpdateMode(psDevInfo);
+ int iBlankEvents = OMAPLFBAtomicIntRead(&psDevInfo->sBlankEvents);
+
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ psSwapChain->bNotVSynced = OMAPLFB_FALSE;
+
+ if (bPreviouslyNotVSynced || psSwapChain->iBlankEvents != iBlankEvents)
+ {
+ psSwapChain->iBlankEvents = iBlankEvents;
+ psSwapChain->bNotVSynced = !WaitForVSyncSettle(psDevInfo);
+ } else if (psBuffer->ulSwapInterval != 0)
+ {
+ psSwapChain->bNotVSynced = !OMAPLFBWaitForVSync(psDevInfo);
+ }
+ break;
+#if defined(PVR_OMAPFB3_MANUAL_UPDATE_SYNC_IN_SWAP)
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ if (psBuffer->ulSwapInterval != 0)
+ {
+ (void) OMAPLFBManualSync(psDevInfo);
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+
+ psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psBuffer->hCmdComplete, IMG_TRUE);
+}
+
+#if defined(CONFIG_DSSCOMP)
+
+
+static void dsscomp_proxy_cmdcomplete(void * cookie, int i)
+{
+ gapsDevInfo[0]->sPVRJTable.pfnPVRSRVCmdComplete(cookie, i);
+}
+#endif
+
+static IMG_BOOL ProcessFlipV1(IMG_HANDLE hCmdCookie,
+ OMAPLFB_DEVINFO *psDevInfo,
+ OMAPLFB_SWAPCHAIN *psSwapChain,
+ OMAPLFB_BUFFER *psBuffer,
+ unsigned long ulSwapInterval)
+{
+ OMAPLFBCreateSwapChainLock(psDevInfo);
+
+ if (SwapChainHasChanged(psDevInfo, psSwapChain))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
+ ": %s: Device %u (PVR Device ID %u): The swap chain has been destroyed\n",
+ __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
+ }
+ else
+ {
+ psBuffer->hCmdComplete = (OMAPLFB_HANDLE)hCmdCookie;
+ psBuffer->ulSwapInterval = ulSwapInterval;
+#if defined(CONFIG_DSSCOMP)
+ if (is_tiler_addr(psBuffer->sSysAddr.uiAddr)) {
+ IMG_UINT32 w = psBuffer->psDevInfo->sDisplayDim.ui32Width;
+ IMG_UINT32 h = psBuffer->psDevInfo->sDisplayDim.ui32Height;
+ struct dsscomp_setup_dispc_data comp = {
+ .num_mgrs = 1,
+ .mgrs[0].alpha_blending = 1,
+ .num_ovls = 1,
+ .ovls[0].cfg = {
+ .width = w,
+ .win.w = w,
+ .crop.w = w,
+ .height = h,
+ .win.h = h,
+ .crop.h = h,
+ .stride = psBuffer->psDevInfo->sDisplayDim.ui32ByteStride,
+ .color_mode = OMAP_DSS_COLOR_ARGB32,
+ .enabled = 1,
+ .global_alpha = 255,
+ },
+ .mode = DSSCOMP_SETUP_DISPLAY,
+ };
+ struct tiler_pa_info *pas[1] = { NULL };
+ comp.ovls[0].ba = (u32) psBuffer->sSysAddr.uiAddr;
+ dsscomp_gralloc_queue(&comp, pas, true,
+ dsscomp_proxy_cmdcomplete,
+ (void *) psBuffer->hCmdComplete);
+ } else
+#endif
+ {
+ OMAPLFBQueueBufferForSwap(psSwapChain, psBuffer);
+ }
+ }
+
+ OMAPLFBCreateSwapChainUnLock(psDevInfo);
+
+ return IMG_TRUE;
+}
+
+#if defined(CONFIG_DSSCOMP) && (defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER))
+int meminfo_idx_valid(unsigned int meminfo_ix, int num_meminfos)
+{
+ if (meminfo_ix < 0 || meminfo_ix >= num_meminfos) {
+ WARN(1, "%s: Invalid meminfo index %d, max %d\n",
+ __func__, meminfo_ix, num_meminfos);
+ return 0;
+ }
+ return 1;
+}
+
+static IMG_BOOL ProcessFlipV2(IMG_HANDLE hCmdCookie,
+ OMAPLFB_DEVINFO *psDevInfo,
+ PDC_MEM_INFO *ppsMemInfos,
+ IMG_UINT32 ui32NumMemInfos,
+ struct omap_hwc_data *psHwcData,
+ IMG_UINT32 uiHwcDataSz)
+{
+ struct tiler_pa_info *apsTilerPAs[5];
+ IMG_UINT32 i, k;
+ struct {
+ IMG_UINTPTR_T uiAddr;
+ IMG_UINTPTR_T uiUVAddr;
+ struct tiler_pa_info *psTilerInfo;
+ } asMemInfo[5];
+
+ /* Framebuffer info just used to get FB geometry, the address to
+ * use for blitting (dst buffer) is the first meminfo
+ */
+ int rgz_items;
+ int calcsz;
+ struct dsscomp_setup_dispc_data *psDssData = &(psHwcData->dsscomp_data);
+ int iMemIdx = 0;
+ int iUseBltFB;
+#ifdef CONFIG_DRM_OMAP_DMM_TILER
+ enum tiler_fmt fmt;
+#endif
+
+ if (uiHwcDataSz <= offsetof(struct omap_hwc_data, blit_data))
+ rgz_items = 0;
+ else
+ rgz_items = psHwcData->blit_data.rgz_items;
+
+
+ psDssData = &(psHwcData->dsscomp_data);
+ calcsz = sizeof(*psHwcData) +
+ (sizeof(struct rgz_blt_entry) * rgz_items);
+ iUseBltFB = psHwcData->blit_data.rgz_flags & HWC_BLT_FLAG_USE_FB;
+
+ if (!iUseBltFB && rgz_items > 0) {
+ WARN(1, "Trying to blit without a pipe configured for the blit FB");
+ return IMG_FALSE;
+ }
+
+ if (rgz_items > 0 && !gbBvInterfacePresent)
+ {
+ /* We cannot blit if BV GC2D is not present!, likely a bug */
+ WARN(1, "Trying to blit when BV GC2D is not present");
+ rgz_items = 0; /* Prevent blits */
+ }
+
+ if (iUseBltFB && !bBltReady)
+ {
+ /* Defer allocation and mapping of blit buffers */
+ if (OMAPLFBInitBltFBs(psDevInfo) != OMAPLFB_OK)
+ {
+ WARN(1, "Could not initialize blit FBs");
+ return IMG_FALSE;
+ }
+
+ bBltReady = IMG_TRUE;
+ }
+
+ memset(asMemInfo, 0, sizeof(asMemInfo));
+
+ /* Check the size of private data along with the blit operations */
+ if (uiHwcDataSz != calcsz)
+ {
+ WARN(1, "invalid size of private data (%d vs %d)",
+ uiHwcDataSz, calcsz);
+ }
+
+ if (ui32NumMemInfos == 0)
+ {
+ WARN(1, "must have at least one layer");
+ return IMG_FALSE;
+ }
+
+ if (iUseBltFB)
+ {
+ iMemIdx++;
+ /* Increment the Blt framebuffer and get new address */
+ OMAPLFBGetBltFBsBvHndl(&psDevInfo->sFBInfo, &asMemInfo[0].uiAddr);
+ }
+
+ for (i = 0, k = iMemIdx; i < ui32NumMemInfos && k < ARRAY_SIZE(apsTilerPAs) &&
+ k < psDssData->num_ovls; i++, k++) {
+
+ struct tiler_pa_info *psTilerInfo;
+ IMG_CPU_VIRTADDR virtAddr;
+ IMG_CPU_PHYADDR aPhyAddr[DSS_MAX_NUMBER_YUV_PLANES];
+ IMG_UINT32 ui32NumPages;
+ IMG_SIZE_T uByteSize;
+ IMG_UINT32 ui32NumAddrOffsets = DSS_MAX_NUMBER_YUV_PLANES;
+ int j;
+
+ memset(aPhyAddr, 0x00, sizeof(aPhyAddr));
+
+ uByteSize = psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuMultiPlanePAddr(
+ ppsMemInfos[i], IMG_NULL /* We want the beginning of the buffers */,
+ aPhyAddr, &ui32NumAddrOffsets);
+
+ if(uByteSize < 0)
+ continue;
+
+ ui32NumPages = (uByteSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ /* TILER buffers do not need meminfos */
+ if(is_tiler_addr((u32)aPhyAddr[0].uiAddr))
+ {
+ asMemInfo[k].uiAddr = aPhyAddr[0].uiAddr;
+#ifdef CONFIG_DRM_OMAP_DMM_TILER
+ if (tiler_get_fmt((u32)aPhyAddr[0].uiAddr, &fmt) && fmt == TILFMT_8BIT)
+#else /* CONFIG_TI_TILER must be defined if CONFIG_DRM_OMAP_DMM_TILER is not */
+ if (tiler_fmt((u32)aPhyAddr[0].uiAddr) == TILFMT_8BIT)
+#endif
+ {
+ if(ui32NumAddrOffsets > 1)
+ asMemInfo[k].uiUVAddr = aPhyAddr[1].uiAddr;
+ }
+ continue;
+ }
+
+ if (aPhyAddr[0].uiAddr >= psDevInfo->psLINFBInfo->fix.smem_start &&
+ aPhyAddr[0].uiAddr < (psDevInfo->psLINFBInfo->fix.smem_start + psDevInfo->psLINFBInfo->fix.smem_len))
+ {
+ asMemInfo[k].uiAddr = aPhyAddr[0].uiAddr;
+ continue;
+ }
+ /* normal gralloc layer */
+ psTilerInfo = kzalloc(sizeof(*psTilerInfo), GFP_KERNEL);
+ if(!psTilerInfo)
+ {
+ continue;
+ }
+
+ psTilerInfo->mem = kzalloc(sizeof(*psTilerInfo->mem) * ui32NumPages, GFP_KERNEL);
+ if(!psTilerInfo->mem)
+ {
+ kfree(psTilerInfo);
+ continue;
+ }
+
+ psTilerInfo->num_pg = ui32NumPages;
+ psTilerInfo->memtype = TILER_MEM_USING;
+ for(j = 0; j < ui32NumPages; j++)
+ {
+ IMG_CPU_PHYADDR pagePhyAddr;
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], j << PAGE_SHIFT, &pagePhyAddr);
+ psTilerInfo->mem[j] = (u32)pagePhyAddr.uiAddr;
+ }
+
+ /* need base address for in-page offset */
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuVAddr(ppsMemInfos[i], &virtAddr);
+ asMemInfo[k].uiAddr = (IMG_UINTPTR_T) virtAddr;
+ asMemInfo[k].psTilerInfo = psTilerInfo;
+ }
+
+ for(i = 0; i < psDssData->num_ovls; i++)
+ {
+ unsigned int ix;
+ apsTilerPAs[i] = NULL;
+
+ /* only supporting Post2, cloned and fbmem layers */
+ if (psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_LAYER_IX &&
+ psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_OVL_IX &&
+ psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_FB &&
+ psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_ION)
+ psDssData->ovls[i].cfg.enabled = false;
+
+ if (psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_LAYER_IX)
+ continue;
+
+ /* Post2 layers */
+ ix = psDssData->ovls[i].ba;
+ if (ix >= k)
+ {
+ WARN(1, "Invalid Post2 layer (%u)", ix);
+ psDssData->ovls[i].cfg.enabled = false;
+ continue;
+ }
+
+ psDssData->ovls[i].addressing = OMAP_DSS_BUFADDR_DIRECT;
+ psDssData->ovls[i].ba = (u32) asMemInfo[ix].uiAddr;
+ psDssData->ovls[i].uv = (u32) asMemInfo[ix].uiUVAddr;
+ apsTilerPAs[i] = asMemInfo[ix].psTilerInfo;
+ }
+
+ if (rgz_items > 0)
+ {
+ OMAPLFBDoBlits(psDevInfo, ppsMemInfos, &psHwcData->blit_data, ui32NumMemInfos);
+ }
+
+ if (psDssData->num_ovls == 0)
+ dsscomp_proxy_cmdcomplete((void *)hCmdCookie, IMG_TRUE);
+ else
+ dsscomp_gralloc_queue(psDssData, apsTilerPAs, false,
+ dsscomp_proxy_cmdcomplete,
+ (void *)hCmdCookie);
+
+ for(i = 0; i < ARRAY_SIZE(asMemInfo); i++)
+ {
+ tiler_pa_free(asMemInfo[i].psTilerInfo);
+ }
+
+ return IMG_TRUE;
+}
+
+#endif
+
+static IMG_BOOL ProcessFlip(IMG_HANDLE hCmdCookie,
+ IMG_UINT32 ui32DataSize,
+ IMG_VOID *pvData)
+{
+ DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ OMAPLFB_DEVINFO *psDevInfo;
+
+ if(!hCmdCookie || !pvData)
+ {
+ return IMG_FALSE;
+ }
+
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)pvData;
+
+ if (psFlipCmd == IMG_NULL)
+ {
+ return IMG_FALSE;
+ }
+
+ psDevInfo = (OMAPLFB_DEVINFO*)psFlipCmd->hExtDevice;
+
+ if(psFlipCmd->hExtBuffer)
+ {
+ return ProcessFlipV1(hCmdCookie,
+ psDevInfo,
+ psFlipCmd->hExtSwapChain,
+ psFlipCmd->hExtBuffer,
+ psFlipCmd->ui32SwapInterval);
+ }
+ else
+ {
+#if defined(CONFIG_DSSCOMP) && (defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER))
+ DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd2;
+ psFlipCmd2 = (DISPLAYCLASS_FLIP_COMMAND2 *)pvData;
+ return ProcessFlipV2(hCmdCookie,
+ psDevInfo,
+ psFlipCmd2->ppsMemInfos,
+ psFlipCmd2->ui32NumMemInfos,
+ psFlipCmd2->pvPrivData,
+ psFlipCmd2->ui32PrivDataLength);
+#else
+ BUG();
+#endif
+ }
+}
+
+#if defined(CONFIG_DSSCOMP)
+
+static OMAPLFB_ERROR OMAPLFBInitIonOmap(OMAPLFB_DEVINFO *psDevInfo,
+ struct fb_info *psLINFBInfo,
+ OMAPLFB_FBINFO *psPVRFBInfo)
+{
+ int n;
+ int iMaxSwapChainBuffs;
+ int res;
+ int i, x, y, w;
+ ion_phys_addr_t phys;
+ size_t size;
+ struct tiler_view_t view;
+
+ struct omap_ion_tiler_alloc_data sAllocData = {
+ .w = ALIGN(psLINFBInfo->var.xres, PAGE_SIZE / (psLINFBInfo->var.bits_per_pixel / 8)),
+ .h = psLINFBInfo->var.yres,
+ .fmt = psLINFBInfo->var.bits_per_pixel == 16 ? TILER_PIXEL_FMT_16BIT : TILER_PIXEL_FMT_32BIT,
+ .flags = 0,
+ .token = 0,
+ .out_align = PAGE_SIZE
+ };
+ unsigned uiFBDevID = psDevInfo->uiFBDevID;
+ struct sgx_omaplfb_config *psFBPlatConfig = GetFBPlatConfig(uiFBDevID);
+
+#if defined(CONFIG_ION_OMAP)
+ gpsIONClient = ion_client_create(omap_ion_device,
+ "omaplfb");
+ if (IS_ERR_OR_NULL(gpsIONClient))
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ " %s: Could not create ion client\n", __FUNCTION__);
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+#endif /* defined(CONFIG_ION_OMAP) */
+
+ if (!psFBPlatConfig->swap_chain_length)
+ {
+ /* Set a default swap chain length if it's not present in the platform data */
+ iMaxSwapChainBuffs = 2;
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Swap chain length missing in "
+ "platform data, defaulting to %d\n", __FUNCTION__, psDevInfo->uiFBDevID,
+ iMaxSwapChainBuffs);
+ }
+ else
+ {
+ iMaxSwapChainBuffs = psFBPlatConfig->swap_chain_length;
+ }
+
+ if (psFBPlatConfig->tiler2d_buffers < iMaxSwapChainBuffs)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Trying to use %d tiler "
+ "buffers which is less than the swap chain length of %d, maximum "
+ "swap chain length will be set to %d\n", __FUNCTION__, psDevInfo->uiFBDevID,
+ psFBPlatConfig->tiler2d_buffers, iMaxSwapChainBuffs, psFBPlatConfig->tiler2d_buffers);
+ iMaxSwapChainBuffs = psFBPlatConfig->tiler2d_buffers;
+ }
+
+ psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = iMaxSwapChainBuffs;
+ n = psFBPlatConfig->tiler2d_buffers;
+
+ printk(KERN_DEBUG DRIVER_PREFIX
+ ": %s: Device %u: Requesting %d TILER 2D framebuffers\n", __FUNCTION__, uiFBDevID, n);
+ sAllocData.w *= n;
+
+ psPVRFBInfo->uiBytesPerPixel = psLINFBInfo->var.bits_per_pixel >> 3;
+ psPVRFBInfo->bIs2D = OMAPLFB_TRUE;
+ res = omap_ion_nonsecure_tiler_alloc(gpsIONClient, &sAllocData);
+ if (res < 0)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ " %s: Device %u: Could not allocate 2D framebuffer(%d)\n", __FUNCTION__, uiFBDevID, res);
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+
+ ion_phys(gpsIONClient, sAllocData.handle, &phys, &size);
+ psPVRFBInfo->sSysAddr.uiAddr = phys;
+ psPVRFBInfo->sCPUVAddr = 0;
+
+ psPVRFBInfo->ulWidth = psLINFBInfo->var.xres;
+ psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
+ psPVRFBInfo->ulByteStride = PAGE_ALIGN(psPVRFBInfo->ulWidth * psPVRFBInfo->uiBytesPerPixel);
+ psPVRFBInfo->ulBufferSize = psPVRFBInfo->ulHeight * psPVRFBInfo->ulByteStride;
+ psPVRFBInfo->ulRoundedBufferSize = psPVRFBInfo->ulBufferSize;
+ w = psPVRFBInfo->ulByteStride >> PAGE_SHIFT;
+
+ /* this is an "effective" FB size to get correct number of buffers */
+ psPVRFBInfo->ulFBSize = sAllocData.h * n * psPVRFBInfo->ulByteStride;
+ psPVRFBInfo->psPageList = kzalloc(w * n * psPVRFBInfo->ulHeight * sizeof(*psPVRFBInfo->psPageList), GFP_KERNEL);
+ if (!psPVRFBInfo->psPageList)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Could not allocate page list\n", __FUNCTION__, psDevInfo->uiFBDevID);
+ ion_free(gpsIONClient, sAllocData.handle);
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+ psPVRFBInfo->psIONHandle = sAllocData.handle;
+
+ tilview_create(&view, phys, psDevInfo->sFBInfo.ulWidth, psDevInfo->sFBInfo.ulHeight);
+ for(i=0; i<n; i++)
+ {
+ for(y=0; y<psDevInfo->sFBInfo.ulHeight; y++)
+ {
+ for(x=0; x<w; x++)
+ {
+ psPVRFBInfo->psPageList[i * psDevInfo->sFBInfo.ulHeight * w + y * w + x].uiAddr =
+ phys + view.v_inc * y + ((x + i * w) << PAGE_SHIFT);
+ }
+ }
+ }
+ return OMAPLFB_OK;
+}
+#endif
+
+static OMAPLFB_ERROR OMAPLFBInitFBVRAM(OMAPLFB_DEVINFO *psDevInfo,
+ struct fb_info *psLINFBInfo,
+ OMAPLFB_FBINFO *psPVRFBInfo)
+{
+ struct sgx_omaplfb_config *psFBPlatConfig = GetFBPlatConfig(psDevInfo->uiFBDevID);
+ unsigned long FBSize = psLINFBInfo->fix.smem_len;
+ unsigned long ulLCM;
+ int iMaxSwapChainBuffs;
+ IMG_UINT32 ui32FBAvailableBuffs;
+
+ /* Check if there is VRAM reserved for this FB */
+ if (FBSize == 0 || psLINFBInfo->fix.line_length == 0)
+ {
+ return OMAPLFB_ERROR_INVALID_DEVICE;
+ }
+
+ /* Fail to init this DC device if vram buffers are not set */
+ if (!psFBPlatConfig->vram_buffers)
+ {
+ return OMAPLFB_ERROR_INVALID_PARAMS;
+ }
+
+ if (!psFBPlatConfig->swap_chain_length)
+ {
+ /* Set a default swap chain length if it's not present in the platform data */
+ iMaxSwapChainBuffs = 2;
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Swap chain length missing in "
+ "platform data, defaulting to %d\n", __FUNCTION__, psDevInfo->uiFBDevID,
+ iMaxSwapChainBuffs);
+ }
+ else
+ {
+ iMaxSwapChainBuffs = psFBPlatConfig->swap_chain_length;
+ }
+
+ if (psFBPlatConfig->vram_buffers < iMaxSwapChainBuffs)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Trying to use %d vram "
+ "buffers which is less than the swap chain length of %d, maximum "
+ "swap chain length will be set to %d\n", __FUNCTION__, psDevInfo->uiFBDevID,
+ psFBPlatConfig->vram_buffers, iMaxSwapChainBuffs, psFBPlatConfig->vram_buffers);
+ iMaxSwapChainBuffs = psFBPlatConfig->vram_buffers;
+ }
+
+ ulLCM = LCM(psLINFBInfo->fix.line_length, OMAPLFB_PAGE_SIZE);
+ psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
+ psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;
+ psPVRFBInfo->ulWidth = psLINFBInfo->var.xres;
+ psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
+ psPVRFBInfo->ulByteStride = psLINFBInfo->fix.line_length;
+ psPVRFBInfo->ulFBSize = FBSize;
+ psPVRFBInfo->bIs2D = OMAPLFB_FALSE;
+ psPVRFBInfo->psPageList = IMG_NULL;
+ psPVRFBInfo->ulBufferSize = psPVRFBInfo->ulHeight * psPVRFBInfo->ulByteStride;
+ psPVRFBInfo->ulRoundedBufferSize = RoundUpToMultiple(psPVRFBInfo->ulBufferSize, ulLCM);
+ ui32FBAvailableBuffs = (IMG_UINT32)(psDevInfo->sFBInfo.ulFBSize / psDevInfo->sFBInfo.ulRoundedBufferSize);
+
+ if (!ui32FBAvailableBuffs)
+ {
+ printk(KERN_ERR DRIVER_PREFIX " %s: Device %u: Not enough vram to init swap "
+ "chain buffers\n", __FUNCTION__, psDevInfo->uiFBDevID);
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+ else if (ui32FBAvailableBuffs < psFBPlatConfig->vram_buffers)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Not enough vram to hold "
+ "%d buffers (available %d), swap chain length will be set to %d\n",
+ __FUNCTION__, psDevInfo->uiFBDevID, iMaxSwapChainBuffs, ui32FBAvailableBuffs,
+ ui32FBAvailableBuffs);
+ iMaxSwapChainBuffs = ui32FBAvailableBuffs;
+ }
+ else
+ {
+ iMaxSwapChainBuffs = psFBPlatConfig->vram_buffers;
+ }
+
+ psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = iMaxSwapChainBuffs;
+
+ printk(KERN_DEBUG DRIVER_PREFIX ": %s: Device %u: Using %d VRAM framebuffers\n", __FUNCTION__,
+ psDevInfo->uiFBDevID, iMaxSwapChainBuffs);
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Device %u: Framebuffer virtual width: %u\n",
+ psDevInfo->uiFBDevID, psLINFBInfo->var.xres_virtual));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Device %u: Framebuffer virtual height: %u\n",
+ psDevInfo->uiFBDevID, psLINFBInfo->var.yres_virtual));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Device %u: LCM of stride and page size: %lu\n",
+ psDevInfo->uiFBDevID, ulLCM));
+
+ return OMAPLFB_OK;
+}
+
+static OMAPLFB_ERROR OMAPLFBInitFBDev(OMAPLFB_DEVINFO *psDevInfo)
+{
+ struct fb_info *psLINFBInfo;
+ struct module *psLINFBOwner;
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ OMAPLFB_ERROR eError = OMAPLFB_ERROR_GENERIC;
+ unsigned uiFBDevID = psDevInfo->uiFBDevID;
+ struct sgx_omaplfb_config *psFBPlatConfig;
+
+ OMAPLFB_CONSOLE_LOCK();
+
+ psLINFBInfo = registered_fb[uiFBDevID];
+ if (psLINFBInfo == NULL)
+ {
+ eError = OMAPLFB_ERROR_INVALID_DEVICE;
+ goto ErrorRelSem;
+ }
+
+ psLINFBOwner = psLINFBInfo->fbops->owner;
+ if (!try_module_get(psLINFBOwner))
+ {
+ printk(KERN_INFO DRIVER_PREFIX
+ ": %s: Device %u: Couldn't get framebuffer module\n", __FUNCTION__, uiFBDevID);
+
+ goto ErrorRelSem;
+ }
+
+ if (psLINFBInfo->fbops->fb_open != NULL)
+ {
+ int res;
+
+ res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
+ if (res != 0)
+ {
+ printk(KERN_INFO DRIVER_PREFIX
+ " %s: Device %u: Couldn't open framebuffer(%d)\n", __FUNCTION__, uiFBDevID, res);
+
+ goto ErrorModPut;
+ }
+ }
+
+ psDevInfo->psLINFBInfo = psLINFBInfo;
+
+ /*
+ * Abort registering this DC device if no platform data found. This
+ * shouldn't happen since the FB index must be valid at this point.
+ */
+ psFBPlatConfig = GetFBPlatConfig(uiFBDevID);
+ if (!psFBPlatConfig)
+ {
+ eError = OMAPLFB_ERROR_INVALID_PARAMS;
+ goto ErrorModPut;
+ }
+
+ /* skip framebuffer in case of zero width or height */
+ if (psDevInfo->psLINFBInfo->var.xres == 0 ||
+ psDevInfo->psLINFBInfo->var.yres == 0) {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": %s: Device %u: invalid framebuffer size\n",
+ __func__, uiFBDevID);
+ eError = OMAPLFB_ERROR_INVALID_PARAMS;
+ goto ErrorModPut;
+ }
+
+#if defined(CONFIG_DSSCOMP)
+ if (psFBPlatConfig->tiler2d_buffers)
+ {
+ /* Use ION to create the flip chain buffers with TILER */
+ eError = OMAPLFBInitIonOmap(psDevInfo, psLINFBInfo, psPVRFBInfo);
+ if (eError != OMAPLFB_OK)
+ {
+ goto ErrorModPut;
+ }
+ }
+ else
+#endif
+ {
+ /* Fall back to allocate flip chain buffers with VRAM */
+ eError = OMAPLFBInitFBVRAM(psDevInfo, psLINFBInfo, psPVRFBInfo);
+ if (eError != OMAPLFB_OK)
+ {
+ goto ErrorModPut;
+ }
+ }
+
+ OMAPLFBPrintInfo(psDevInfo);
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Device %u: Framebuffer physical address: %p\n",
+ psDevInfo->uiFBDevID, (void *)psPVRFBInfo->sSysAddr.uiAddr));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Device %u: Framebuffer virtual address: %p\n",
+ psDevInfo->uiFBDevID, (void *)psPVRFBInfo->sCPUVAddr));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Device %u: Framebuffer size: %lu\n",
+ psDevInfo->uiFBDevID, psPVRFBInfo->ulFBSize));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Device %u: Framebuffer width: %lu\n",
+ psDevInfo->uiFBDevID, psPVRFBInfo->ulWidth));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Device %u: Framebuffer height: %lu\n",
+ psDevInfo->uiFBDevID, psPVRFBInfo->ulHeight));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Device %u: Framebuffer stride: %lu\n",
+ psDevInfo->uiFBDevID, psPVRFBInfo->ulByteStride));
+
+ if(psLINFBInfo->var.bits_per_pixel == 16)
+ {
+ if((psLINFBInfo->var.red.length == 5) &&
+ (psLINFBInfo->var.green.length == 6) &&
+ (psLINFBInfo->var.blue.length == 5) &&
+ (psLINFBInfo->var.red.offset == 11) &&
+ (psLINFBInfo->var.green.offset == 5) &&
+ (psLINFBInfo->var.blue.offset == 0) &&
+ (psLINFBInfo->var.red.msb_right == 0))
+ {
+ psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565;
+ }
+ else
+ {
+ printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown FB format\n", __FUNCTION__, uiFBDevID);
+ }
+ }
+ else if(psLINFBInfo->var.bits_per_pixel == 32)
+ {
+ if((psLINFBInfo->var.red.length == 8) &&
+ (psLINFBInfo->var.green.length == 8) &&
+ (psLINFBInfo->var.blue.length == 8) &&
+ (psLINFBInfo->var.red.offset == 16) &&
+ (psLINFBInfo->var.green.offset == 8) &&
+ (psLINFBInfo->var.blue.offset == 0) &&
+ (psLINFBInfo->var.red.msb_right == 0))
+ {
+ psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_ARGB8888;
+ }
+ else
+ {
+ printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown FB format\n", __FUNCTION__, uiFBDevID);
+ }
+ }
+ else
+ {
+ printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown FB format\n", __FUNCTION__, uiFBDevID);
+ }
+
+ psDevInfo->sFBInfo.ulPhysicalWidthmm =
+ ((int)psLINFBInfo->var.width > 0) ? psLINFBInfo->var.width : 90;
+
+ psDevInfo->sFBInfo.ulPhysicalHeightmm =
+ ((int)psLINFBInfo->var.height > 0) ? psLINFBInfo->var.height : 54;
+
+
+ psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
+ psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
+
+ eError = OMAPLFB_OK;
+ goto ErrorRelSem;
+
+ErrorModPut:
+ module_put(psLINFBOwner);
+ErrorRelSem:
+ OMAPLFB_CONSOLE_UNLOCK();
+
+ return eError;
+}
+
+static void OMAPLFBDeInitFBDev(OMAPLFB_DEVINFO *psDevInfo)
+{
+ struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ struct module *psLINFBOwner;
+
+ OMAPLFB_CONSOLE_LOCK();
+
+ psLINFBOwner = psLINFBInfo->fbops->owner;
+
+#if defined(CONFIG_DSSCOMP)
+ kfree(psPVRFBInfo->psPageList);
+ if (psPVRFBInfo->psIONHandle)
+ {
+ ion_free(gpsIONClient, psPVRFBInfo->psIONHandle);
+ }
+ if (psPVRFBInfo->psBltFBsIonHndl)
+ {
+ ion_free(gpsIONClient, psPVRFBInfo->psBltFBsIonHndl);
+ }
+ if (psPVRFBInfo->psBltFBsBvHndl)
+ {
+ int i;
+ for (i = 0; i < psPVRFBInfo->psBltFBsNo; i++)
+ {
+ if (psPVRFBInfo->psBltFBsBvHndl[i])
+ {
+ kfree(psPVRFBInfo->psBltFBsBvHndl[i]);
+ }
+ }
+ kfree(psPVRFBInfo->psBltFBsBvHndl);
+ kfree(psPVRFBInfo->psBltFBsBvPhys);
+ }
+#endif
+ if (psLINFBInfo->fbops->fb_release != NULL)
+ {
+ (void) psLINFBInfo->fbops->fb_release(psLINFBInfo, 0);
+ }
+
+ module_put(psLINFBOwner);
+
+ OMAPLFB_CONSOLE_UNLOCK();
+}
+
+static OMAPLFB_DEVINFO *OMAPLFBInitDev(unsigned uiFBDevID)
+{
+ PFN_CMD_PROC pfnCmdProcList[OMAPLFB_COMMAND_COUNT];
+ IMG_UINT32 aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
+ OMAPLFB_DEVINFO *psDevInfo = NULL;
+
+
+ psDevInfo = (OMAPLFB_DEVINFO *)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_DEVINFO));
+
+ if(psDevInfo == NULL)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ ": %s: Device %u: Couldn't allocate device information structure\n", __FUNCTION__, uiFBDevID);
+
+ goto ErrorExit;
+ }
+
+
+ memset(psDevInfo, 0, sizeof(OMAPLFB_DEVINFO));
+
+ psDevInfo->uiFBDevID = uiFBDevID;
+
+
+ if(!(*gpfnGetPVRJTable)(&psDevInfo->sPVRJTable))
+ {
+ goto ErrorFreeDevInfo;
+ }
+
+
+ if(OMAPLFBInitFBDev(psDevInfo) != OMAPLFB_OK)
+ {
+
+ goto ErrorFreeDevInfo;
+ }
+
+ if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers != 0)
+ {
+ psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1;
+ psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 1;
+ }
+
+ psDevInfo->sDisplayInfo.ui32PhysicalWidthmm = psDevInfo->sFBInfo.ulPhysicalWidthmm;
+ psDevInfo->sDisplayInfo.ui32PhysicalHeightmm = psDevInfo->sFBInfo.ulPhysicalHeightmm;
+
+ strncpy(psDevInfo->sDisplayInfo.szDisplayName, DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
+
+ psDevInfo->sDisplayFormat.pixelformat = psDevInfo->sFBInfo.ePixelFormat;
+ psDevInfo->sDisplayDim.ui32Width = (IMG_UINT32)psDevInfo->sFBInfo.ulWidth;
+ psDevInfo->sDisplayDim.ui32Height = (IMG_UINT32)psDevInfo->sFBInfo.ulHeight;
+ psDevInfo->sDisplayDim.ui32ByteStride = (IMG_UINT32)psDevInfo->sFBInfo.ulByteStride;
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Device %u: Maximum number of swap chain buffers: %u\n",
+ psDevInfo->uiFBDevID, psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
+
+
+ psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
+ psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
+ psDevInfo->sSystemBuffer.psDevInfo = psDevInfo;
+
+ OMAPLFBInitBufferForSwap(&psDevInfo->sSystemBuffer);
+
+
+
+ psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
+ psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
+ psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
+ psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
+ psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
+ psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
+ psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
+ psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
+ psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
+ psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
+ psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
+ psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
+ psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
+ psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
+ psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
+ psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
+ psDevInfo->sDCJTable.pfnSetDCState = SetDCState;
+
+
+ if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice(
+ &psDevInfo->sDCJTable,
+ &psDevInfo->uiPVRDevID) != PVRSRV_OK)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ ": %s: Device %u: PVR Services device registration failed\n", __FUNCTION__, uiFBDevID);
+
+ goto ErrorDeInitFBDev;
+ }
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Device %u: PVR Device ID: %u\n",
+ psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
+
+
+ pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
+
+
+ aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
+ if (gbBvInterfacePresent)
+ {
+ aui32SyncCountList[DC_FLIP_COMMAND][1] = 32;
+ }
+ else
+ {
+ aui32SyncCountList[DC_FLIP_COMMAND][1] = 10;
+ }
+
+
+
+
+
+ if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList(psDevInfo->uiPVRDevID,
+ &pfnCmdProcList[0],
+ aui32SyncCountList,
+ OMAPLFB_COMMAND_COUNT) != PVRSRV_OK)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ ": %s: Device %u: Couldn't register command processing functions with PVR Services\n", __FUNCTION__, uiFBDevID);
+ goto ErrorUnregisterDevice;
+ }
+
+ OMAPLFBCreateSwapChainLockInit(psDevInfo);
+
+ OMAPLFBAtomicBoolInit(&psDevInfo->sBlanked, OMAPLFB_FALSE);
+ OMAPLFBAtomicIntInit(&psDevInfo->sBlankEvents, 0);
+ OMAPLFBAtomicBoolInit(&psDevInfo->sFlushCommands, OMAPLFB_FALSE);
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ OMAPLFBAtomicBoolInit(&psDevInfo->sEarlySuspendFlag, OMAPLFB_FALSE);
+#endif
+#if defined(SUPPORT_DRI_DRM)
+ OMAPLFBAtomicBoolInit(&psDevInfo->sLeaveVT, OMAPLFB_FALSE);
+#endif
+ return psDevInfo;
+
+ErrorUnregisterDevice:
+ (void)psDevInfo->sPVRJTable.pfnPVRSRVRemoveDCDevice(psDevInfo->uiPVRDevID);
+ErrorDeInitFBDev:
+ OMAPLFBDeInitFBDev(psDevInfo);
+ErrorFreeDevInfo:
+ OMAPLFBFreeKernelMem(psDevInfo);
+ErrorExit:
+ return NULL;
+}
+
+#if defined(CONFIG_OMAPLFB)
+int OMAPLFBRegisterPVRDriver(PFN_DC_GET_PVRJTABLE pfnFuncTable)
+{
+ gpfnGetPVRJTable = pfnFuncTable;
+
+ if(OMAPLFBInit() != OMAPLFB_OK)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ " %s: Could not create ion client\n", __FUNCTION__);
+ return -1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(OMAPLFBRegisterPVRDriver);
+#endif
+
+OMAPLFB_ERROR OMAPLFBInit(void)
+{
+ unsigned uiMaxFBDevIDPlusOne = OMAPLFBMaxFBDevIDPlusOne();
+ unsigned i;
+ unsigned uiDevicesFound = 0;
+
+#if !defined(CONFIG_OMAPLFB)
+ if(OMAPLFBGetLibFuncAddr ("PVRGetDisplayClassJTable", &gpfnGetPVRJTable) != OMAPLFB_OK)
+ {
+ return OMAPLFB_ERROR_INIT_FAILURE;
+ }
+#endif
+
+ gbBvInterfacePresent = OMAPLFBInitBlt();
+
+ if (!gbBvInterfacePresent)
+ {
+ printk(KERN_INFO DRIVER_PREFIX "%s: Blitsville gc2d "
+ "not present, blits disabled\n", __func__);
+ }
+ for(i = uiMaxFBDevIDPlusOne; i-- != 0;)
+ {
+ OMAPLFB_DEVINFO *psDevInfo = OMAPLFBInitDev(i);
+
+ if (psDevInfo != NULL)
+ {
+
+ OMAPLFBSetDevInfoPtr(psDevInfo->uiFBDevID, psDevInfo);
+ uiDevicesFound++;
+ }
+ }
+
+ return (uiDevicesFound != 0) ? OMAPLFB_OK : OMAPLFB_ERROR_INIT_FAILURE;
+}
+
+static OMAPLFB_BOOL OMAPLFBDeInitDev(OMAPLFB_DEVINFO *psDevInfo)
+{
+ PVRSRV_DC_DISP2SRV_KMJTABLE *psPVRJTable = &psDevInfo->sPVRJTable;
+
+ OMAPLFBCreateSwapChainLockDeInit(psDevInfo);
+
+ OMAPLFBAtomicBoolDeInit(&psDevInfo->sBlanked);
+ OMAPLFBAtomicIntDeInit(&psDevInfo->sBlankEvents);
+ OMAPLFBAtomicBoolDeInit(&psDevInfo->sFlushCommands);
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ OMAPLFBAtomicBoolDeInit(&psDevInfo->sEarlySuspendFlag);
+#endif
+#if defined(SUPPORT_DRI_DRM)
+ OMAPLFBAtomicBoolDeInit(&psDevInfo->sLeaveVT);
+#endif
+ psPVRJTable = &psDevInfo->sPVRJTable;
+
+ if (psPVRJTable->pfnPVRSRVRemoveCmdProcList (psDevInfo->uiPVRDevID, OMAPLFB_COMMAND_COUNT) != PVRSRV_OK)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ ": %s: Device %u: PVR Device %u: Couldn't unregister command processing functions\n", __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID);
+ return OMAPLFB_FALSE;
+ }
+
+
+ if (psPVRJTable->pfnPVRSRVRemoveDCDevice(psDevInfo->uiPVRDevID) != PVRSRV_OK)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ ": %s: Device %u: PVR Device %u: Couldn't remove device from PVR Services\n", __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID);
+ return OMAPLFB_FALSE;
+ }
+
+ OMAPLFBDeInitFBDev(psDevInfo);
+
+ OMAPLFBSetDevInfoPtr(psDevInfo->uiFBDevID, NULL);
+
+
+ OMAPLFBFreeKernelMem(psDevInfo);
+
+ return OMAPLFB_TRUE;
+}
+
+OMAPLFB_ERROR OMAPLFBDeInit(void)
+{
+ unsigned uiMaxFBDevIDPlusOne = OMAPLFBMaxFBDevIDPlusOne();
+ unsigned i;
+ OMAPLFB_BOOL bError = OMAPLFB_FALSE;
+
+ for(i = 0; i < uiMaxFBDevIDPlusOne; i++)
+ {
+ OMAPLFB_DEVINFO *psDevInfo = OMAPLFBGetDevInfoPtr(i);
+
+ if (psDevInfo != NULL)
+ {
+ bError |= !OMAPLFBDeInitDev(psDevInfo);
+ }
+ }
+
+ return (bError) ? OMAPLFB_ERROR_INIT_FAILURE : OMAPLFB_OK;
+}
+
diff --git a/drivers/video/omap2/omaplfb/omaplfb_linux.c b/drivers/video/omap2/omaplfb/omaplfb_linux.c
--- /dev/null
@@ -0,0 +1,1147 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <asm/atomic.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#else
+#include <linux/module.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/hardirq.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/omapfb.h>
+#include <linux/mutex.h>
+#include <plat/sgx_omaplfb.h>
+
+#if defined(PVR_OMAPLFB_DRM_FB)
+#include <plat/display.h>
+#include <linux/omap_gpu.h>
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
+#define PVR_OMAPFB3_NEEDS_PLAT_VRFB_H
+#endif
+
+
+#if 0
+#if defined(PVR_OMAPFB3_NEEDS_PLAT_VRFB_H)
+#include <plat/vrfb.h>
+#else
+#if defined(PVR_OMAPFB3_NEEDS_MACH_VRFB_H)
+#include <mach/vrfb.h>
+#endif
+#endif
+#endif
+
+#if defined(DEBUG)
+#define PVR_DEBUG DEBUG
+#undef DEBUG
+#endif
+#include "../omapfb/omapfb.h"
+#if defined(DEBUG)
+#undef DEBUG
+#endif
+#if defined(PVR_DEBUG)
+#define DEBUG PVR_DEBUG
+#undef PVR_DEBUG
+#endif
+#endif
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "omaplfb.h"
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#include "3rdparty_dc_drm_shared.h"
+#endif
+
+#if !defined(PVR_LINUX_USING_WORKQUEUES)
+#error "PVR_LINUX_USING_WORKQUEUES must be defined"
+#endif
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+#if !defined(PVR_OMAPLFB_DRM_FB)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
+#define OMAP_DSS_DRIVER(drv, dev) struct omap_dss_driver *drv = (dev) != NULL ? (dev)->driver : NULL
+#define OMAP_DSS_MANAGER(man, dev) struct omap_overlay_manager *man = (dev) != NULL ? (dev)->output->manager : NULL
+#define WAIT_FOR_VSYNC(man) ((man)->wait_for_vsync)
+#else
+#define OMAP_DSS_DRIVER(drv, dev) struct omap_dss_device *drv = (dev)
+#define OMAP_DSS_MANAGER(man, dev) struct omap_dss_device *man = (dev)
+#define WAIT_FOR_VSYNC(man) ((man)->wait_vsync)
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0))
+#define OMAP_FB_UPDATE_MODE
+#define OMAP_UPDATE_MODE omapfb_update_mode
+#define OMAP_UPDATE_MODE_AUTO OMAPFB_AUTO_UPDATE
+#define OMAP_UPDATE_MODE_MANUAL OMAPFB_MANUAL_UPDATE
+#define OMAP_UPDATE_MODE_DISABLED OMAPFB_UPDATE_DISABLED
+#else
+#define OMAP_UPDATE_MODE omap_dss_update_mode
+#define OMAP_UPDATE_MODE_AUTO OMAP_DSS_UPDATE_AUTO
+#define OMAP_UPDATE_MODE_MANUAL OMAP_DSS_UPDATE_MANUAL
+#define OMAP_UPDATE_MODE_DISABLED OMAP_DSS_UPDATE_DISABLED
+#endif
+
+static int debug;
+module_param(debug, int, 0644); /* For future use */
+
+static struct sgx_omaplfb_platform_data *gplatdata;
+
+void *OMAPLFBAllocKernelMem(unsigned long ulSize)
+{
+ return kmalloc(ulSize, GFP_KERNEL);
+}
+
+void OMAPLFBFreeKernelMem(void *pvMem)
+{
+ kfree(pvMem);
+}
+
+void OMAPLFBCreateSwapChainLockInit(OMAPLFB_DEVINFO *psDevInfo)
+{
+ mutex_init(&psDevInfo->sCreateSwapChainMutex);
+}
+
+void OMAPLFBCreateSwapChainLockDeInit(OMAPLFB_DEVINFO *psDevInfo)
+{
+ mutex_destroy(&psDevInfo->sCreateSwapChainMutex);
+}
+
+void OMAPLFBCreateSwapChainLock(OMAPLFB_DEVINFO *psDevInfo)
+{
+ mutex_lock(&psDevInfo->sCreateSwapChainMutex);
+}
+
+void OMAPLFBCreateSwapChainUnLock(OMAPLFB_DEVINFO *psDevInfo)
+{
+ mutex_unlock(&psDevInfo->sCreateSwapChainMutex);
+}
+
+void OMAPLFBAtomicBoolInit(OMAPLFB_ATOMIC_BOOL *psAtomic, OMAPLFB_BOOL bVal)
+{
+ atomic_set(psAtomic, (int)bVal);
+}
+
+void OMAPLFBAtomicBoolDeInit(OMAPLFB_ATOMIC_BOOL *psAtomic)
+{
+}
+
+void OMAPLFBAtomicBoolSet(OMAPLFB_ATOMIC_BOOL *psAtomic, OMAPLFB_BOOL bVal)
+{
+ atomic_set(psAtomic, (int)bVal);
+}
+
+OMAPLFB_BOOL OMAPLFBAtomicBoolRead(OMAPLFB_ATOMIC_BOOL *psAtomic)
+{
+ return (OMAPLFB_BOOL)atomic_read(psAtomic);
+}
+
+void OMAPLFBAtomicIntInit(OMAPLFB_ATOMIC_INT *psAtomic, int iVal)
+{
+ atomic_set(psAtomic, iVal);
+}
+
+void OMAPLFBAtomicIntDeInit(OMAPLFB_ATOMIC_INT *psAtomic)
+{
+}
+
+void OMAPLFBAtomicIntSet(OMAPLFB_ATOMIC_INT *psAtomic, int iVal)
+{
+ atomic_set(psAtomic, iVal);
+}
+
+int OMAPLFBAtomicIntRead(OMAPLFB_ATOMIC_INT *psAtomic)
+{
+ return atomic_read(psAtomic);
+}
+
+void OMAPLFBAtomicIntInc(OMAPLFB_ATOMIC_INT *psAtomic)
+{
+ atomic_inc(psAtomic);
+}
+
+#if !defined(CONFIG_OMAPLFB)
+OMAPLFB_ERROR OMAPLFBGetLibFuncAddr (char *szFunctionName, PFN_DC_GET_PVRJTABLE *ppfnFuncTable)
+{
+ if(strcmp("PVRGetDisplayClassJTable", szFunctionName) != 0)
+ {
+ return (OMAPLFB_ERROR_INVALID_PARAMS);
+ }
+
+
+ *ppfnFuncTable = PVRGetDisplayClassJTable;
+
+ return (OMAPLFB_OK);
+}
+#endif
+
+void OMAPLFBQueueBufferForSwap(OMAPLFB_SWAPCHAIN *psSwapChain, OMAPLFB_BUFFER *psBuffer)
+{
+ int res = queue_work(psSwapChain->psWorkQueue, &psBuffer->sWork);
+
+ if (res == 0)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Buffer already on work queue\n", __FUNCTION__, psSwapChain->uiFBDevID);
+ }
+}
+
+static void WorkQueueHandler(struct work_struct *psWork)
+{
+ OMAPLFB_BUFFER *psBuffer = container_of(psWork, OMAPLFB_BUFFER, sWork);
+
+ OMAPLFBSwapHandler(psBuffer);
+}
+
+OMAPLFB_ERROR OMAPLFBCreateSwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+
+ psSwapChain->psWorkQueue = alloc_ordered_workqueue(DEVNAME, WQ_FREEZABLE | WQ_MEM_RECLAIM);
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+ psSwapChain->psWorkQueue = create_freezable_workqueue(DEVNAME);
+#else
+
+ psSwapChain->psWorkQueue = __create_workqueue(DEVNAME, 1, 1, 1);
+#endif
+#endif
+ if (psSwapChain->psWorkQueue == NULL)
+ {
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: Couldn't create workqueue\n", __FUNCTION__, psSwapChain->uiFBDevID);
+
+ return (OMAPLFB_ERROR_INIT_FAILURE);
+ }
+
+ return (OMAPLFB_OK);
+}
+
+void OMAPLFBInitBufferForSwap(OMAPLFB_BUFFER *psBuffer)
+{
+ INIT_WORK(&psBuffer->sWork, WorkQueueHandler);
+}
+
+void OMAPLFBDestroySwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
+{
+ destroy_workqueue(psSwapChain->psWorkQueue);
+}
+
+#if defined(CONFIG_DSSCOMP)
+#include <video/dsscomp.h>
+#include <plat/dsscomp.h>
+#include <linux/omapfb.h>
+#endif
+
+void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer)
+{
+ struct fb_var_screeninfo sFBVar;
+ int res;
+ unsigned long ulYResVirtual;
+
+ OMAPLFB_CONSOLE_LOCK();
+
+ sFBVar = psDevInfo->psLINFBInfo->var;
+
+ sFBVar.xoffset = 0;
+ sFBVar.yoffset = psBuffer->ulYOffset;
+
+ ulYResVirtual = psBuffer->ulYOffset + sFBVar.yres;
+
+
+#if defined(CONFIG_DSSCOMP)
+ {
+ /*
+ * If using DSSCOMP, we need to use dsscomp queuing for normal
+ * framebuffer updates, so that previously used overlays get
+ * automatically disabled, and manager gets dirtied. We can
+ * do that because DSSCOMP takes ownership of all pipelines on
+ * a manager.
+ */
+ struct fb_fix_screeninfo sFBFix = psDevInfo->psLINFBInfo->fix;
+ struct dsscomp_setup_dispc_data d = {
+ .num_ovls = 1,
+ .num_mgrs = 1,
+ .mgrs[0].alpha_blending = 1,
+ .ovls[0] = {
+ .cfg = {
+ .win.w = sFBVar.xres,
+ .win.h = sFBVar.yres,
+ .crop.x = sFBVar.xoffset,
+ .crop.y = sFBVar.yoffset,
+ .crop.w = sFBVar.xres,
+ .crop.h = sFBVar.yres,
+ .width = sFBVar.xres_virtual,
+ .height = sFBVar.yres_virtual,
+ .stride = sFBFix.line_length,
+ .enabled = 1,
+ .global_alpha = 255,
+ },
+ },
+ };
+ /* do not map buffer into TILER1D as it is contiguous */
+ struct tiler_pa_info *pas[] = { NULL };
+
+ d.ovls[0].ba = sFBFix.smem_start;
+ omapfb_mode_to_dss_mode(&sFBVar, &d.ovls[0].cfg.color_mode);
+
+ res = dsscomp_gralloc_queue(&d, pas, true, NULL, NULL);
+ }
+#else
+#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
+
+ if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual)
+#endif
+ {
+ sFBVar.xres_virtual = sFBVar.xres;
+ sFBVar.yres_virtual = ulYResVirtual;
+
+ sFBVar.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
+
+ res = fb_set_var(psDevInfo->psLINFBInfo, &sFBVar);
+ if (res != 0)
+ {
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
+ }
+ }
+#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
+ else
+ {
+ res = fb_pan_display(psDevInfo->psLINFBInfo, &sFBVar);
+ if (res != 0)
+ {
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
+ }
+ }
+#endif
+#endif
+ OMAPLFB_CONSOLE_UNLOCK();
+}
+
+#if !defined(PVR_OMAPLFB_DRM_FB) || defined(DEBUG)
+static OMAPLFB_BOOL OMAPLFBValidUpdateMode(enum OMAP_UPDATE_MODE eMode)
+{
+ switch (eMode)
+ {
+ case OMAP_UPDATE_MODE_AUTO:
+ case OMAP_UPDATE_MODE_MANUAL:
+ case OMAP_UPDATE_MODE_DISABLED:
+ return OMAPLFB_TRUE;
+ default:
+ break;
+ }
+
+ return OMAPLFB_FALSE;
+}
+
+static OMAPLFB_UPDATE_MODE OMAPLFBFromUpdateMode(enum OMAP_UPDATE_MODE eMode)
+{
+ switch (eMode)
+ {
+ case OMAP_UPDATE_MODE_AUTO:
+ return OMAPLFB_UPDATE_MODE_AUTO;
+ case OMAP_UPDATE_MODE_MANUAL:
+ return OMAPLFB_UPDATE_MODE_MANUAL;
+ case OMAP_UPDATE_MODE_DISABLED:
+ return OMAPLFB_UPDATE_MODE_DISABLED;
+ default:
+ break;
+ }
+
+ return OMAPLFB_UPDATE_MODE_UNDEFINED;
+}
+#endif
+
+static OMAPLFB_BOOL OMAPLFBValidateUpdateMode(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return OMAPLFB_TRUE;
+ default:
+ break;
+ }
+
+ return OMAPLFB_FALSE;
+}
+
+static enum OMAP_UPDATE_MODE OMAPLFBToUpdateMode(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ return OMAP_UPDATE_MODE_AUTO;
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ return OMAP_UPDATE_MODE_MANUAL;
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return OMAP_UPDATE_MODE_DISABLED;
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+#if defined(DEBUG)
+static const char *OMAPLFBUpdateModeToString(OMAPLFB_UPDATE_MODE eMode)
+{
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ return "Auto Update Mode";
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ return "Manual Update Mode";
+ case OMAPLFB_UPDATE_MODE_DISABLED:
+ return "Update Mode Disabled";
+ case OMAPLFB_UPDATE_MODE_UNDEFINED:
+ return "Update Mode Undefined";
+ default:
+ break;
+ }
+
+ return "Unknown Update Mode";
+}
+
+static const char *OMAPLFBDSSUpdateModeToString(enum OMAP_UPDATE_MODE eMode)
+{
+ if (!OMAPLFBValidUpdateMode(eMode))
+ {
+ return "Unknown Update Mode";
+ }
+
+ return OMAPLFBUpdateModeToString(OMAPLFBFromUpdateMode(eMode));
+}
+
+void OMAPLFBPrintInfo(OMAPLFB_DEVINFO *psDevInfo)
+{
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+ unsigned uConnectors;
+ unsigned uConnector;
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: DRM framebuffer\n", psDevInfo->uiFBDevID));
+
+ for (psConnector = NULL, uConnectors = 0;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ uConnectors++;
+ }
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: Number of screens (DRM connectors): %u\n", psDevInfo->uiFBDevID, uConnectors));
+
+ if (uConnectors == 0)
+ {
+ return;
+ }
+
+ for (psConnector = NULL, uConnector = 0;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL; uConnector++)
+ {
+ enum OMAP_UPDATE_MODE eMode = omap_connector_get_update_mode(psConnector);
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: Screen %u: %s (%d)\n", psDevInfo->uiFBDevID, uConnector, OMAPLFBDSSUpdateModeToString(eMode), (int)eMode));
+
+ }
+#else
+ OMAPLFB_UPDATE_MODE eMode = OMAPLFBGetUpdateMode(psDevInfo);
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: non-DRM framebuffer\n", psDevInfo->uiFBDevID));
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": Device %u: %s\n", psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+#endif
+}
+#endif
+
+#if defined(PVR_OMAPLFB_DRM_FB)
+OMAPLFB_UPDATE_MODE OMAPLFBGetUpdateMode(OMAPLFB_DEVINFO *psDevInfo)
+{
+ struct drm_connector *psConnector;
+ OMAPLFB_UPDATE_MODE eMode = OMAPLFB_UPDATE_MODE_UNDEFINED;
+
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ switch(omap_connector_get_update_mode(psConnector))
+ {
+ case OMAP_DSS_UPDATE_MANUAL:
+ eMode = OMAPLFB_UPDATE_MODE_MANUAL;
+ break;
+ case OMAP_DSS_UPDATE_DISABLED:
+ if (eMode == OMAPLFB_UPDATE_MODE_UNDEFINED)
+ {
+ eMode = OMAPLFB_UPDATE_MODE_DISABLED;
+ }
+ break;
+ case OMAP_DSS_UPDATE_AUTO:
+
+ default:
+
+ if (eMode != OMAPLFB_UPDATE_MODE_MANUAL)
+ {
+ eMode = OMAPLFB_UPDATE_MODE_AUTO;
+ }
+ break;
+ }
+ }
+
+ return eMode;
+}
+
+OMAPLFB_BOOL OMAPLFBSetUpdateMode(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_UPDATE_MODE eMode)
+{
+ struct drm_connector *psConnector;
+ enum OMAP_UPDATE_MODE eDSSMode;
+ OMAPLFB_BOOL bSuccess = OMAPLFB_FALSE;
+ OMAPLFB_BOOL bFailure = OMAPLFB_FALSE;
+
+ if (!OMAPLFBValidateUpdateMode(eMode))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
+ return OMAPLFB_FALSE;
+ }
+ eDSSMode = OMAPLFBToUpdateMode(eMode);
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ int iRes = omap_connector_set_update_mode(psConnector, eDSSMode);
+ OMAPLFB_BOOL bRes = (iRes == 0);
+
+
+ bSuccess |= bRes;
+ bFailure |= !bRes;
+ }
+
+ if (!bFailure)
+ {
+ if (!bSuccess)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No screens\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ }
+
+ return OMAPLFB_TRUE;
+ }
+
+ if (!bSuccess)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set %s for any screen\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+ return OMAPLFB_FALSE;
+ }
+
+ if (eMode == OMAPLFB_UPDATE_MODE_AUTO)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set %s for all screens\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+ return OMAPLFB_FALSE;
+ }
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: %s set for some screens\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eMode)));
+
+ return OMAPLFB_TRUE;
+}
+
+#elif defined(OMAP_FB_UPDATE_MODE)
+
+OMAPLFB_UPDATE_MODE OMAPLFBGetUpdateMode(OMAPLFB_DEVINFO *psDevInfo)
+{
+ enum OMAP_UPDATE_MODE eMode;
+
+ omapfb_get_update_mode(psDevInfo->psLINFBInfo, &eMode);
+
+ if (!OMAPLFBValidUpdateMode(eMode))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
+ }
+
+ return OMAPLFBFromUpdateMode(eMode);
+}
+
+OMAPLFB_BOOL OMAPLFBSetUpdateMode(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_UPDATE_MODE eMode)
+{
+ enum OMAP_UPDATE_MODE eUpdateMode;
+ int res;
+
+ if (!OMAPLFBValidateUpdateMode(eMode))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
+ return OMAPLFB_FALSE;
+ }
+
+ eUpdateMode = OMAPLFBToUpdateMode(eMode);
+ res = omapfb_set_update_mode(psDevInfo->psLINFBInfo, eUpdateMode);
+
+ if (res != 0)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX \
+ ": %s: Device %u: set_update_mode (%s) failed (%d)\n", __func__,
+ psDevInfo->uiFBDevID,
+ OMAPLFBUpdateModeToString(eUpdateMode), res));
+ }
+
+ return (res == 0);
+}
+
+#else
+
+OMAPLFB_UPDATE_MODE OMAPLFBGetUpdateMode(OMAPLFB_DEVINFO *psDevInfo)
+{
+ struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
+ OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
+
+ enum OMAP_UPDATE_MODE eMode;
+
+ if (psDSSDrv == NULL)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No DSS device\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ return OMAPLFB_UPDATE_MODE_UNDEFINED;
+ }
+
+ if (psDSSDrv->get_update_mode == NULL)
+ {
+ if (strcmp(psDSSDev->name, "hdmi") == 0)
+ {
+ return OMAPLFB_UPDATE_MODE_AUTO;
+ }
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: No get_update_mode function\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ return OMAPLFB_UPDATE_MODE_UNDEFINED;
+ }
+
+ eMode = psDSSDrv->get_update_mode(psDSSDev);
+
+ if (!OMAPLFBValidUpdateMode(eMode))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
+ }
+
+ return OMAPLFBFromUpdateMode(eMode);
+}
+
+OMAPLFB_BOOL OMAPLFBSetUpdateMode(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_UPDATE_MODE eMode)
+{
+ struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
+ OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
+ enum OMAP_UPDATE_MODE eUpdateMode;
+ int res;
+
+ if (psDSSDrv == NULL || psDSSDrv->set_update_mode == NULL)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Can't set update mode\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ return OMAPLFB_FALSE;
+ }
+
+ if (!OMAPLFBValidateUpdateMode(eMode))
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Unknown update mode (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, (int)eMode));
+ return OMAPLFB_FALSE;
+ }
+
+ eUpdateMode = OMAPLFBToUpdateMode(eMode);
+
+ res = psDSSDrv->set_update_mode(psDSSDev, eUpdateMode);
+
+ if (res != 0)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: set_update_mode (%s) failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, OMAPLFBUpdateModeToString(eUpdateMode), res));
+ }
+
+ return (res == 0);
+}
+#endif
+
+OMAPLFB_BOOL OMAPLFBWaitForVSync(OMAPLFB_DEVINFO *psDevInfo)
+{
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL;)
+ {
+ (void) omap_encoder_wait_for_vsync(psConnector->encoder);
+ }
+
+ return OMAPLFB_TRUE;
+#else
+ struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
+ OMAP_DSS_MANAGER(psDSSMan, psDSSDev);
+
+ if (psDSSMan != NULL && WAIT_FOR_VSYNC(psDSSMan) != NULL)
+ {
+ int res = WAIT_FOR_VSYNC(psDSSMan)(psDSSMan);
+ if (res != 0)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Wait for vsync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res));
+ return OMAPLFB_FALSE;
+ }
+ }
+
+ return OMAPLFB_TRUE;
+#endif
+}
+
+OMAPLFB_BOOL OMAPLFBManualSync(OMAPLFB_DEVINFO *psDevInfo)
+{
+#if defined(PVR_OMAPLFB_DRM_FB)
+ struct drm_connector *psConnector;
+
+ for (psConnector = NULL;
+ (psConnector = omap_fbdev_get_next_connector(psDevInfo->psLINFBInfo, psConnector)) != NULL; )
+ {
+
+ if (omap_connector_sync(psConnector) != 0)
+ {
+ (void) omap_encoder_wait_for_vsync(psConnector->encoder);
+ }
+ }
+
+ return OMAPLFB_TRUE;
+#else
+ struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
+ OMAP_DSS_DRIVER(psDSSDrv, psDSSDev);
+
+ if (psDSSDrv != NULL && psDSSDrv->sync != NULL)
+ {
+ int res = psDSSDrv->sync(psDSSDev);
+ if (res != 0)
+ {
+ printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: Sync failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
+ return OMAPLFB_FALSE;
+ }
+ }
+
+ return OMAPLFB_TRUE;
+#endif
+}
+
+OMAPLFB_BOOL OMAPLFBCheckModeAndSync(OMAPLFB_DEVINFO *psDevInfo)
+{
+ OMAPLFB_UPDATE_MODE eMode = OMAPLFBGetUpdateMode(psDevInfo);
+
+ switch(eMode)
+ {
+ case OMAPLFB_UPDATE_MODE_AUTO:
+ case OMAPLFB_UPDATE_MODE_MANUAL:
+ return OMAPLFBManualSync(psDevInfo);
+ default:
+ break;
+ }
+
+ return OMAPLFB_TRUE;
+}
+
+static int OMAPLFBFrameBufferEvents(struct notifier_block *psNotif,
+ unsigned long event, void *data)
+{
+ OMAPLFB_DEVINFO *psDevInfo;
+ struct fb_event *psFBEvent = (struct fb_event *)data;
+ struct fb_info *psFBInfo = psFBEvent->info;
+ OMAPLFB_BOOL bBlanked;
+
+
+ if (event != FB_EVENT_BLANK)
+ {
+ return 0;
+ }
+
+ bBlanked = (*(IMG_INT *)psFBEvent->data != 0) ? OMAPLFB_TRUE: OMAPLFB_FALSE;
+
+ psDevInfo = OMAPLFBGetDevInfoPtr(psFBInfo->node);
+
+#if 0
+ if (psDevInfo != NULL)
+ {
+ if (bBlanked)
+ {
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Blank event received\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ }
+ else
+ {
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unblank event received\n", __FUNCTION__, psDevInfo->uiFBDevID));
+ }
+ }
+ else
+ {
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": %s: Device %u: Blank/Unblank event for unknown framebuffer\n", __FUNCTION__, psFBInfo->node));
+ }
+#endif
+
+ if (psDevInfo != NULL)
+ {
+ OMAPLFBAtomicBoolSet(&psDevInfo->sBlanked, bBlanked);
+ OMAPLFBAtomicIntInc(&psDevInfo->sBlankEvents);
+ }
+
+ return 0;
+}
+
+OMAPLFB_ERROR OMAPLFBUnblankDisplay(OMAPLFB_DEVINFO *psDevInfo)
+{
+ int res;
+
+ OMAPLFB_CONSOLE_LOCK();
+ res = fb_blank(psDevInfo->psLINFBInfo, 0);
+ OMAPLFB_CONSOLE_UNLOCK();
+ if (res != 0 && res != -EINVAL)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ ": %s: Device %u: fb_blank failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
+ return (OMAPLFB_ERROR_GENERIC);
+ }
+
+ return (OMAPLFB_OK);
+}
+
+OMAPLFB_ERROR OMAPLFBEnableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
+{
+ int res;
+ OMAPLFB_ERROR eError;
+
+
+ memset(&psDevInfo->sLINNotifBlock, 0, sizeof(psDevInfo->sLINNotifBlock));
+
+ psDevInfo->sLINNotifBlock.notifier_call = OMAPLFBFrameBufferEvents;
+
+ OMAPLFBAtomicBoolSet(&psDevInfo->sBlanked, OMAPLFB_FALSE);
+ OMAPLFBAtomicIntSet(&psDevInfo->sBlankEvents, 0);
+
+ res = fb_register_client(&psDevInfo->sLINNotifBlock);
+ if (res != 0)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ ": %s: Device %u: fb_register_client failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
+
+ return (OMAPLFB_ERROR_GENERIC);
+ }
+
+ eError = OMAPLFBUnblankDisplay(psDevInfo);
+ if (eError != OMAPLFB_OK)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ ": %s: Device %u: UnblankDisplay failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eError);
+ return eError;
+ }
+
+ return (OMAPLFB_OK);
+}
+
+OMAPLFB_ERROR OMAPLFBDisableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
+{
+ int res;
+
+ res = fb_unregister_client(&psDevInfo->sLINNotifBlock);
+ if (res != 0)
+ {
+ printk(KERN_ERR DRIVER_PREFIX
+ ": %s: Device %u: fb_unregister_client failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, res);
+ return (OMAPLFB_ERROR_GENERIC);
+ }
+
+ OMAPLFBAtomicBoolSet(&psDevInfo->sBlanked, OMAPLFB_FALSE);
+
+ return (OMAPLFB_OK);
+}
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+static OMAPLFB_DEVINFO *OMAPLFBPVRDevIDToDevInfo(unsigned uiPVRDevID)
+{
+ unsigned uiMaxFBDevIDPlusOne = OMAPLFBMaxFBDevIDPlusOne();
+ unsigned i;
+
+ for (i=0; i < uiMaxFBDevIDPlusOne; i++)
+ {
+ OMAPLFB_DEVINFO *psDevInfo = OMAPLFBGetDevInfoPtr(i);
+
+ if (psDevInfo->uiPVRDevID == uiPVRDevID)
+ {
+ return psDevInfo;
+ }
+ }
+
+ printk(KERN_ERR DRIVER_PREFIX
+ ": %s: PVR Device %u: Couldn't find device\n", __FUNCTION__, uiPVRDevID);
+
+ return NULL;
+}
+
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(struct drm_device unref__ *dev, void *arg, struct drm_file unref__ *pFile)
+{
+ uint32_t *puiArgs;
+ uint32_t uiCmd;
+ unsigned uiPVRDevID;
+ int ret = 0;
+ OMAPLFB_DEVINFO *psDevInfo;
+
+ if (arg == NULL)
+ {
+ return -EFAULT;
+ }
+
+ puiArgs = (uint32_t *)arg;
+ uiCmd = puiArgs[PVR_DRM_DISP_ARG_CMD];
+ uiPVRDevID = puiArgs[PVR_DRM_DISP_ARG_DEV];
+
+ psDevInfo = OMAPLFBPVRDevIDToDevInfo(uiPVRDevID);
+ if (psDevInfo == NULL)
+ {
+ return -EINVAL;
+ }
+
+
+ switch (uiCmd)
+ {
+ case PVR_DRM_DISP_CMD_LEAVE_VT:
+ case PVR_DRM_DISP_CMD_ENTER_VT:
+ {
+ OMAPLFB_BOOL bLeaveVT = (uiCmd == PVR_DRM_DISP_CMD_LEAVE_VT);
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: %s\n",
+ __FUNCTION__, uiPVRDevID,
+ bLeaveVT ? "Leave VT" : "Enter VT"));
+
+ OMAPLFBCreateSwapChainLock(psDevInfo);
+
+ OMAPLFBAtomicBoolSet(&psDevInfo->sLeaveVT, bLeaveVT);
+ if (psDevInfo->psSwapChain != NULL)
+ {
+ flush_workqueue(psDevInfo->psSwapChain->psWorkQueue);
+
+ if (bLeaveVT)
+ {
+ OMAPLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer);
+ (void) OMAPLFBCheckModeAndSync(psDevInfo);
+ }
+ }
+
+ OMAPLFBCreateSwapChainUnLock(psDevInfo);
+ (void) OMAPLFBUnblankDisplay(psDevInfo);
+ break;
+ }
+ case PVR_DRM_DISP_CMD_ON:
+ case PVR_DRM_DISP_CMD_STANDBY:
+ case PVR_DRM_DISP_CMD_SUSPEND:
+ case PVR_DRM_DISP_CMD_OFF:
+ {
+ int iFBMode;
+#if defined(DEBUG)
+ {
+ const char *pszMode;
+ switch(uiCmd)
+ {
+ case PVR_DRM_DISP_CMD_ON:
+ pszMode = "On";
+ break;
+ case PVR_DRM_DISP_CMD_STANDBY:
+ pszMode = "Standby";
+ break;
+ case PVR_DRM_DISP_CMD_SUSPEND:
+ pszMode = "Suspend";
+ break;
+ case PVR_DRM_DISP_CMD_OFF:
+ pszMode = "Off";
+ break;
+ default:
+ pszMode = "(Unknown Mode)";
+ break;
+ }
+ printk(KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: Display %s\n",
+ __FUNCTION__, uiPVRDevID, pszMode);
+ }
+#endif
+ switch(uiCmd)
+ {
+ case PVR_DRM_DISP_CMD_ON:
+ iFBMode = FB_BLANK_UNBLANK;
+ break;
+ case PVR_DRM_DISP_CMD_STANDBY:
+ iFBMode = FB_BLANK_HSYNC_SUSPEND;
+ break;
+ case PVR_DRM_DISP_CMD_SUSPEND:
+ iFBMode = FB_BLANK_VSYNC_SUSPEND;
+ break;
+ case PVR_DRM_DISP_CMD_OFF:
+ iFBMode = FB_BLANK_POWERDOWN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ OMAPLFBCreateSwapChainLock(psDevInfo);
+
+ if (psDevInfo->psSwapChain != NULL)
+ {
+ flush_workqueue(psDevInfo->psSwapChain->psWorkQueue);
+ }
+
+ OMAPLFB_CONSOLE_LOCK();
+ ret = fb_blank(psDevInfo->psLINFBInfo, iFBMode);
+ OMAPLFB_CONSOLE_UNLOCK();
+
+ OMAPLFBCreateSwapChainUnLock(psDevInfo);
+
+ break;
+ }
+ default:
+ {
+ ret = -EINVAL;
+ break;
+ }
+ }
+
+ return ret;
+}
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+struct sgx_omaplfb_config *GetFBPlatConfig(int fbix)
+{
+ return NULL;
+}
+#else
+struct sgx_omaplfb_config *GetFBPlatConfig(int fbix)
+{
+ if (fbix >= gplatdata->num_configs)
+ {
+ WARN(1, "Invalid FB device index");
+ return NULL;
+ }
+ return &gplatdata->configs[fbix];
+}
+
+static int omaplfb_probe(struct platform_device *pdev)
+{
+ struct omaplfb_device *odev = kzalloc(sizeof(*odev), GFP_KERNEL);
+
+ if (!odev)
+ return -ENOMEM;
+
+ odev->dev = &pdev->dev;
+ platform_set_drvdata(pdev, odev);
+ gplatdata = (struct sgx_omaplfb_platform_data *)odev->dev->platform_data;
+
+ if (!gplatdata)
+ {
+ WARN(1, "Platform data is null");
+ return -ENODEV;
+ }
+
+#if !defined(CONFIG_OMAPLFB)
+ if(OMAPLFBInit() != OMAPLFB_OK)
+ {
+ dev_err(&pdev->dev, "failed to probe omaplfb\n");
+ kfree(odev);
+ return -ENODEV;
+ }
+#endif
+
+ return 0;
+}
+
+static int omaplfb_remove(struct platform_device *pdev)
+{
+ struct omaplfb_device *odev;
+
+ odev = platform_get_drvdata(pdev);
+
+ if(OMAPLFBDeInit() != OMAPLFB_OK)
+ {
+ dev_err(&pdev->dev, "failed to remove omaplfb\n");
+ }
+
+ gplatdata = NULL;
+ kfree(odev);
+ return 0;
+}
+
+static struct platform_driver omaplfb_driver = {
+ .driver = {
+ .name = DRVNAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = omaplfb_probe,
+ .remove = omaplfb_remove,
+};
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device unref__ *dev)
+#else
+static int __init OMAPLFB_Init(void)
+#endif
+{
+#if defined(SUPPORT_DRI_DRM)
+ if(OMAPLFBInit() != OMAPLFB_OK)
+ {
+ printk(KERN_ERR DRIVER_PREFIX ": %s: OMAPLFBInit failed\n", __FUNCTION__);
+ return -ENODEV;
+ }
+#else
+ if (platform_driver_register(&omaplfb_driver))
+ {
+ printk(KERN_ERR DRIVER_PREFIX ": %s: failed to register platform driver\n", __FUNCTION__);
+ return -ENODEV;
+ }
+#endif
+ return 0;
+}
+
+#if defined(SUPPORT_DRI_DRM)
+void PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device unref__ *dev)
+#else
+static void __exit OMAPLFB_Cleanup(void)
+#endif
+{
+#if defined(SUPPORT_DRI_DRM)
+ if(OMAPLFBDeInit() != OMAPLFB_OK)
+ {
+ printk(KERN_ERR DRIVER_PREFIX ": %s: OMAPLFBDeInit failed\n", __FUNCTION__);
+ return -ENODEV;
+ }
+#else
+ platform_driver_unregister(&omaplfb_driver);
+#endif
+}
+
+#if !defined(SUPPORT_DRI_DRM)
+late_initcall(OMAPLFB_Init);
+module_exit(OMAPLFB_Cleanup);
+#endif
diff --git a/drivers/video/omap2/omaplfb/servicesext.h b/drivers/video/omap2/omaplfb/servicesext.h
--- /dev/null
@@ -0,0 +1,966 @@
+/*************************************************************************/ /*!
+@Title Services definitions required by external drivers
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides services data structures, defines and prototypes
+ required by external drivers.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+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.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) 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; AND (B) 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.
+
+*/ /**************************************************************************/
+
+#if !defined (__SERVICESEXT_H__)
+#define __SERVICESEXT_H__
+
+/*
+ * Lock buffer read/write flags
+ */
+#define PVRSRV_LOCKFLG_READONLY (1) /*!< The locking process will only read the locked surface */
+
+/*!
+ *****************************************************************************
+ * Error values
+ *
+ * NOTE: If you change this, make sure you update the error texts in
+ * services4/include/pvrsrv_errors.h to match.
+ *
+ *****************************************************************************/
+typedef enum _PVRSRV_ERROR_
+{
+ PVRSRV_OK = 0,
+ PVRSRV_ERROR_OUT_OF_MEMORY,
+ PVRSRV_ERROR_TOO_FEW_BUFFERS,
+ PVRSRV_ERROR_INVALID_PARAMS,
+ PVRSRV_ERROR_INIT_FAILURE,
+ PVRSRV_ERROR_CANT_REGISTER_CALLBACK,
+ PVRSRV_ERROR_INVALID_DEVICE,
+ PVRSRV_ERROR_NOT_OWNER,
+ PVRSRV_ERROR_BAD_MAPPING,
+ PVRSRV_ERROR_TIMEOUT,
+ PVRSRV_ERROR_FLIP_CHAIN_EXISTS,
+ PVRSRV_ERROR_INVALID_SWAPINTERVAL,
+ PVRSRV_ERROR_SCENE_INVALID,
+ PVRSRV_ERROR_STREAM_ERROR,
+ PVRSRV_ERROR_FAILED_DEPENDENCIES,
+ PVRSRV_ERROR_CMD_NOT_PROCESSED,
+ PVRSRV_ERROR_CMD_TOO_BIG,
+ PVRSRV_ERROR_DEVICE_REGISTER_FAILED,
+ PVRSRV_ERROR_TOOMANYBUFFERS,
+ PVRSRV_ERROR_NOT_SUPPORTED,
+ PVRSRV_ERROR_PROCESSING_BLOCKED,
+
+ PVRSRV_ERROR_CANNOT_FLUSH_QUEUE,
+ PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE,
+ PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS,
+ PVRSRV_ERROR_RETRY,
+
+ PVRSRV_ERROR_DDK_VERSION_MISMATCH,
+ PVRSRV_ERROR_BUILD_MISMATCH,
+ PVRSRV_ERROR_CORE_REVISION_MISMATCH,
+
+ PVRSRV_ERROR_UPLOAD_TOO_BIG,
+
+ PVRSRV_ERROR_INVALID_FLAGS,
+ PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS,
+
+ PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY,
+ PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR,
+ PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED,
+
+ PVRSRV_ERROR_BRIDGE_CALL_FAILED,
+ PVRSRV_ERROR_IOCTL_CALL_FAILED,
+
+ PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND,
+ PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND,
+ PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT,
+
+ PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND,
+ PVRSRV_ERROR_PCI_CALL_FAILED,
+ PVRSRV_ERROR_PCI_REGION_TOO_SMALL,
+ PVRSRV_ERROR_PCI_REGION_UNAVAILABLE,
+ PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH,
+
+ PVRSRV_ERROR_REGISTER_BASE_NOT_SET,
+
+ PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE,
+
+ PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM,
+ PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY,
+ PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC,
+ PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR,
+
+ PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY,
+ PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY,
+
+ PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES,
+ PVRSRV_ERROR_FAILED_TO_FREE_PAGES,
+ PVRSRV_ERROR_FAILED_TO_COPY_PAGES,
+ PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES,
+ PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES,
+ PVRSRV_ERROR_STILL_MAPPED,
+ PVRSRV_ERROR_MAPPING_NOT_FOUND,
+ PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT,
+ PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE,
+
+ PVRSRV_ERROR_INVALID_SEGMENT_BLOCK,
+ PVRSRV_ERROR_INVALID_SGXDEVDATA,
+ PVRSRV_ERROR_INVALID_DEVINFO,
+ PVRSRV_ERROR_INVALID_MEMINFO,
+ PVRSRV_ERROR_INVALID_MISCINFO,
+ PVRSRV_ERROR_UNKNOWN_IOCTL,
+ PVRSRV_ERROR_INVALID_CONTEXT,
+ PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT,
+ PVRSRV_ERROR_INVALID_HEAP,
+ PVRSRV_ERROR_INVALID_KERNELINFO,
+ PVRSRV_ERROR_UNKNOWN_POWER_STATE,
+ PVRSRV_ERROR_INVALID_HANDLE_TYPE,
+ PVRSRV_ERROR_INVALID_WRAP_TYPE,
+ PVRSRV_ERROR_INVALID_PHYS_ADDR,
+ PVRSRV_ERROR_INVALID_CPU_ADDR,
+ PVRSRV_ERROR_INVALID_HEAPINFO,
+ PVRSRV_ERROR_INVALID_PERPROC,
+ PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO,
+ PVRSRV_ERROR_INVALID_MAP_REQUEST,
+ PVRSRV_ERROR_INVALID_UNMAP_REQUEST,
+ PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP,
+ PVRSRV_ERROR_MAPPING_STILL_IN_USE,
+
+ PVRSRV_ERROR_EXCEEDED_HW_LIMITS,
+ PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED,
+
+ PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA,
+ PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD,
+ PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD,
+ PVRSRV_ERROR_THREAD_READ_ERROR,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER,
+ PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR,
+ PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR,
+ PVRSRV_ERROR_ISR_ALREADY_INSTALLED,
+ PVRSRV_ERROR_ISR_NOT_INSTALLED,
+ PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT,
+ PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO,
+ PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT,
+ PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE,
+ PVRSRV_ERROR_UNABLE_TO_CLOSE_HANDLE,
+
+ PVRSRV_ERROR_INVALID_CCB_COMMAND,
+
+ PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE,
+ PVRSRV_ERROR_INVALID_LOCK_ID,
+ PVRSRV_ERROR_RESOURCE_NOT_LOCKED,
+
+ PVRSRV_ERROR_FLIP_FAILED,
+ PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED,
+
+ PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE,
+
+ PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED,
+ PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG,
+ PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG,
+ PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG,
+
+ PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID,
+
+ PVRSRV_ERROR_BLIT_SETUP_FAILED,
+
+ PVRSRV_ERROR_PDUMP_NOT_AVAILABLE,
+ PVRSRV_ERROR_PDUMP_BUFFER_FULL,
+ PVRSRV_ERROR_PDUMP_BUF_OVERFLOW,
+ PVRSRV_ERROR_PDUMP_NOT_ACTIVE,
+ PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES,
+
+ PVRSRV_ERROR_MUTEX_DESTROY_FAILED,
+ PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR,
+
+ PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE,
+ PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND,
+
+ PVRSRV_ERROR_PROCESS_NOT_INITIALISED,
+ PVRSRV_ERROR_PROCESS_NOT_FOUND,
+ PVRSRV_ERROR_SRV_CONNECT_FAILED,
+ PVRSRV_ERROR_SRV_DISCONNECT_FAILED,
+ PVRSRV_ERROR_DEINT_PHASE_FAILED,
+ PVRSRV_ERROR_INIT2_PHASE_FAILED,
+
+ PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE,
+
+ PVRSRV_ERROR_NO_DC_DEVICES_FOUND,
+ PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE,
+ PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE,
+ PVRSRV_ERROR_NO_DEVICEDATA_FOUND,
+ PVRSRV_ERROR_NO_DEVICENODE_FOUND,
+ PVRSRV_ERROR_NO_CLIENTNODE_FOUND,
+ PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE,
+
+ PVRSRV_ERROR_UNABLE_TO_INIT_TASK,
+ PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK,
+ PVRSRV_ERROR_UNABLE_TO_KILL_TASK,
+
+ PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER,
+ PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER,
+ PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER,
+
+ PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT,
+ PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION,
+
+ PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE,
+ PVRSRV_ERROR_HANDLE_NOT_ALLOCATED,
+ PVRSRV_ERROR_HANDLE_TYPE_MISMATCH,
+ PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE,
+ PVRSRV_ERROR_HANDLE_NOT_SHAREABLE,
+ PVRSRV_ERROR_HANDLE_NOT_FOUND,
+ PVRSRV_ERROR_INVALID_SUBHANDLE,
+ PVRSRV_ERROR_HANDLE_BATCH_IN_USE,
+ PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE,
+
+ PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE,
+ PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED,
+
+ PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE,
+ PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP,
+
+ PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE,
+
+ PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE,
+ PVRSRV_ERROR_INVALID_DEVICEID,
+ PVRSRV_ERROR_DEVICEID_NOT_FOUND,
+
+ PVRSRV_ERROR_MEMORY_TEST_FAILED,
+ PVRSRV_ERROR_CPUPADDR_TEST_FAILED,
+ PVRSRV_ERROR_COPY_TEST_FAILED,
+
+ PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED,
+
+ PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK,
+ PVRSRV_ERROR_CLOCK_REQUEST_FAILED,
+ PVRSRV_ERROR_DISABLE_CLOCK_FAILURE,
+ PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE,
+ PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE,
+ PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK,
+ PVRSRV_ERROR_UNABLE_TO_GET_CLOCK,
+ PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK,
+ PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK,
+
+ PVRSRV_ERROR_UNKNOWN_SGL_ERROR,
+
+ PVRSRV_ERROR_SYSTEM_POWER_CHANGE_FAILURE,
+ PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE,
+
+ PVRSRV_ERROR_BAD_SYNC_STATE,
+
+ PVRSRV_ERROR_CACHEOP_FAILED,
+
+ PVRSRV_ERROR_CACHE_INVALIDATE_FAILED,
+
+ PVRSRV_ERROR_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_ERROR;
+
+
+/*!
+ *****************************************************************************
+ * List of known device classes.
+ *****************************************************************************/
+typedef enum _PVRSRV_DEVICE_CLASS_
+{
+ PVRSRV_DEVICE_CLASS_3D = 0 ,
+ PVRSRV_DEVICE_CLASS_DISPLAY = 1 ,
+ PVRSRV_DEVICE_CLASS_BUFFER = 2 ,
+ PVRSRV_DEVICE_CLASS_VIDEO = 3 ,
+
+ PVRSRV_DEVICE_CLASS_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEVICE_CLASS;
+
+
+/*!
+ *****************************************************************************
+ * States for power management
+ *****************************************************************************/
+typedef enum _PVRSRV_SYS_POWER_STATE_
+{
+ PVRSRV_SYS_POWER_STATE_Unspecified = -1, /*!< Unspecified : Uninitialised */
+ PVRSRV_SYS_POWER_STATE_D0 = 0, /*!< On */
+ PVRSRV_SYS_POWER_STATE_D1 = 1, /*!< User Idle */
+ PVRSRV_SYS_POWER_STATE_D2 = 2, /*!< System Idle / sleep */
+ PVRSRV_SYS_POWER_STATE_D3 = 3, /*!< Suspend / Hibernate */
+ PVRSRV_SYS_POWER_STATE_D4 = 4, /*!< shutdown */
+
+ PVRSRV_SYS_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_SYS_POWER_STATE, *PPVRSRV_SYS_POWER_STATE;
+
+
+typedef enum _PVRSRV_DEV_POWER_STATE_
+{
+ PVRSRV_DEV_POWER_STATE_DEFAULT = -1, /*!< Default state for the device */
+ PVRSRV_DEV_POWER_STATE_ON = 0, /*!< Running */
+ PVRSRV_DEV_POWER_STATE_IDLE = 1, /*!< Powered but operation paused */
+ PVRSRV_DEV_POWER_STATE_OFF = 2, /*!< Unpowered */
+
+ PVRSRV_DEV_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEV_POWER_STATE, *PPVRSRV_DEV_POWER_STATE; /* PRQA S 3205 */
+
+
+/* Power transition handler prototypes */
+typedef PVRSRV_ERROR (*PFN_PRE_POWER) (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_POWER) (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+/* Clock speed handler prototypes */
+typedef PVRSRV_ERROR (*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+
+/*****************************************************************************
+ * Enumeration of all possible pixel types. Where applicable, Ordering of name
+ * is in reverse order of memory bytes (i.e. as a word in little endian).
+ * e.g. A8R8G8B8 is in memory as 4 bytes in order: BB GG RR AA
+ *
+ * NOTE: When modifying this structure please update the client driver format
+ * tables located in %WORKROOT%/eurasia/codegen/pixfmts using the tool
+ * located in %WORKROOT%/eurasia/tools/intern/TextureFormatParser.
+ *
+ *****************************************************************************/
+typedef enum _PVRSRV_PIXEL_FORMAT_ {
+ /* Basic types */
+ PVRSRV_PIXEL_FORMAT_UNKNOWN = 0,
+ PVRSRV_PIXEL_FORMAT_RGB565 = 1,
+ PVRSRV_PIXEL_FORMAT_RGB555 = 2,
+ PVRSRV_PIXEL_FORMAT_RGB888 = 3, /*!< 24bit */
+ PVRSRV_PIXEL_FORMAT_BGR888 = 4, /*!< 24bit */
+ PVRSRV_PIXEL_FORMAT_GREY_SCALE = 8,
+ PVRSRV_PIXEL_FORMAT_PAL12 = 13,
+ PVRSRV_PIXEL_FORMAT_PAL8 = 14,
+ PVRSRV_PIXEL_FORMAT_PAL4 = 15,
+ PVRSRV_PIXEL_FORMAT_PAL2 = 16,
+ PVRSRV_PIXEL_FORMAT_PAL1 = 17,
+ PVRSRV_PIXEL_FORMAT_ARGB1555 = 18,
+ PVRSRV_PIXEL_FORMAT_ARGB4444 = 19,
+ PVRSRV_PIXEL_FORMAT_ARGB8888 = 20,
+ PVRSRV_PIXEL_FORMAT_ABGR8888 = 21,
+ PVRSRV_PIXEL_FORMAT_YV12 = 22,
+ PVRSRV_PIXEL_FORMAT_I420 = 23,
+ PVRSRV_PIXEL_FORMAT_IMC2 = 25,
+ PVRSRV_PIXEL_FORMAT_XRGB8888 = 26,
+ PVRSRV_PIXEL_FORMAT_XBGR8888 = 27,
+ PVRSRV_PIXEL_FORMAT_BGRA8888 = 28,
+ PVRSRV_PIXEL_FORMAT_XRGB4444 = 29,
+ PVRSRV_PIXEL_FORMAT_ARGB8332 = 30,
+ PVRSRV_PIXEL_FORMAT_A2RGB10 = 31, /*!< 32bpp, 10 bits for R, G, B, 2 bits for A */
+ PVRSRV_PIXEL_FORMAT_A2BGR10 = 32, /*!< 32bpp, 10 bits for B, G, R, 2 bits for A */
+ PVRSRV_PIXEL_FORMAT_P8 = 33,
+ PVRSRV_PIXEL_FORMAT_L8 = 34,
+ PVRSRV_PIXEL_FORMAT_A8L8 = 35,
+ PVRSRV_PIXEL_FORMAT_A4L4 = 36,
+ PVRSRV_PIXEL_FORMAT_L16 = 37,
+ PVRSRV_PIXEL_FORMAT_L6V5U5 = 38,
+ PVRSRV_PIXEL_FORMAT_V8U8 = 39,
+ PVRSRV_PIXEL_FORMAT_V16U16 = 40,
+ PVRSRV_PIXEL_FORMAT_QWVU8888 = 41,
+ PVRSRV_PIXEL_FORMAT_XLVU8888 = 42,
+ PVRSRV_PIXEL_FORMAT_QWVU16 = 43,
+ PVRSRV_PIXEL_FORMAT_D16 = 44,
+ PVRSRV_PIXEL_FORMAT_D24S8 = 45,
+ PVRSRV_PIXEL_FORMAT_D24X8 = 46,
+
+ /* Added to ensure TQ build */
+ PVRSRV_PIXEL_FORMAT_ABGR16 = 47,
+ PVRSRV_PIXEL_FORMAT_ABGR16F = 48,
+ PVRSRV_PIXEL_FORMAT_ABGR32 = 49,
+ PVRSRV_PIXEL_FORMAT_ABGR32F = 50,
+ PVRSRV_PIXEL_FORMAT_B10GR11 = 51,
+ PVRSRV_PIXEL_FORMAT_GR88 = 52,
+ PVRSRV_PIXEL_FORMAT_BGR32 = 53,
+ PVRSRV_PIXEL_FORMAT_GR32 = 54,
+ PVRSRV_PIXEL_FORMAT_E5BGR9 = 55,
+
+ /* reserved types */
+ PVRSRV_PIXEL_FORMAT_RESERVED1 = 56,
+ PVRSRV_PIXEL_FORMAT_RESERVED2 = 57,
+ PVRSRV_PIXEL_FORMAT_RESERVED3 = 58,
+ PVRSRV_PIXEL_FORMAT_RESERVED4 = 59,
+ PVRSRV_PIXEL_FORMAT_RESERVED5 = 60,
+
+ /* RGB space packed formats */
+ PVRSRV_PIXEL_FORMAT_R8G8_B8G8 = 61,
+ PVRSRV_PIXEL_FORMAT_G8R8_G8B8 = 62,
+
+ /* YUV space planar formats */
+ PVRSRV_PIXEL_FORMAT_NV11 = 63,
+ PVRSRV_PIXEL_FORMAT_NV12 = 64,
+
+ /* YUV space packed formats */
+ PVRSRV_PIXEL_FORMAT_YUY2 = 65,
+ PVRSRV_PIXEL_FORMAT_YUV420 = 66,
+ PVRSRV_PIXEL_FORMAT_YUV444 = 67,
+ PVRSRV_PIXEL_FORMAT_VUY444 = 68,
+ PVRSRV_PIXEL_FORMAT_YUYV = 69,
+ PVRSRV_PIXEL_FORMAT_YVYU = 70,
+ PVRSRV_PIXEL_FORMAT_UYVY = 71,
+ PVRSRV_PIXEL_FORMAT_VYUY = 72,
+
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY = 73, /*!< See http://www.fourcc.org/yuv.php#UYVY */
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV = 74, /*!< See http://www.fourcc.org/yuv.php#YUYV */
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YVYU = 75, /*!< See http://www.fourcc.org/yuv.php#YVYU */
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_VYUY = 76, /*!< No fourcc.org link */
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_AYUV = 77, /*!< See http://www.fourcc.org/yuv.php#AYUV */
+
+ /* 4 component, 32 bits per component types */
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32 = 78, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32F = 79, /*!< float type */
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_UINT = 80, /*!< uint type */
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_SINT = 81, /*!< sint type */
+
+ /* 3 component, 32 bits per component types */
+ PVRSRV_PIXEL_FORMAT_B32G32R32 = 82, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_B32G32R32F = 83, /*!< float data */
+ PVRSRV_PIXEL_FORMAT_B32G32R32_UINT = 84, /*!< uint data */
+ PVRSRV_PIXEL_FORMAT_B32G32R32_SINT = 85, /*!< signed int data */
+
+ /* 2 component, 32 bits per component types */
+ PVRSRV_PIXEL_FORMAT_G32R32 = 86, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_G32R32F = 87, /*!< float */
+ PVRSRV_PIXEL_FORMAT_G32R32_UINT = 88, /*!< uint */
+ PVRSRV_PIXEL_FORMAT_G32R32_SINT = 89, /*!< signed int */
+
+ /* 1 component, 32 bits per component types */
+ PVRSRV_PIXEL_FORMAT_D32F = 90, /*!< float depth */
+ PVRSRV_PIXEL_FORMAT_R32 = 91, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_R32F = 92, /*!< float type */
+ PVRSRV_PIXEL_FORMAT_R32_UINT = 93, /*!< unsigned int type */
+ PVRSRV_PIXEL_FORMAT_R32_SINT = 94, /*!< signed int type */
+
+ /* 4 component, 16 bits per component types */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16 = 95, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16F = 96, /*!< type float */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SINT = 97, /*!< signed ints */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SNORM = 98, /*!< signed normalised int */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UINT = 99, /*!< unsigned ints */
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UNORM = 100, /*!< normalised unsigned int */
+
+ /* 2 component, 16 bits per component types */
+ PVRSRV_PIXEL_FORMAT_G16R16 = 101, /*!< unspecified type */
+ PVRSRV_PIXEL_FORMAT_G16R16F = 102, /*!< float type */
+ PVRSRV_PIXEL_FORMAT_G16R16_UINT = 103, /*!< unsigned int type */
+ PVRSRV_PIXEL_FORMAT_G16R16_UNORM = 104, /*!< unsigned normalised */
+ PVRSRV_PIXEL_FORMAT_G16R16_SINT = 105, /*!< signed int */
+ PVRSRV_PIXEL_FORMAT_G16R16_SNORM = 106, /*!< signed normalised */
+
+ /* 1 component, 16 bits per component types */
+ PVRSRV_PIXEL_FORMAT_R16 = 107, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_R16F = 108, /*!< float type */
+ PVRSRV_PIXEL_FORMAT_R16_UINT = 109, /*!< unsigned int type */
+ PVRSRV_PIXEL_FORMAT_R16_UNORM = 110, /*!< unsigned normalised int type */
+ PVRSRV_PIXEL_FORMAT_R16_SINT = 111, /*!< signed int type */
+ PVRSRV_PIXEL_FORMAT_R16_SNORM = 112, /*!< signed normalised int type */
+
+ /* 4 component, 8 bits per component types */
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8 = 113, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM = 114, /*!< normalised unsigned int */
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM_SRGB = 115, /*!< normalised uint with sRGB */
+
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8 = 116, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM = 117, /*!< normalised unsigned int */
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM_SRGB = 118, /*!< normalised uint with sRGB */
+
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8 = 119, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UINT = 120, /*!< unsigned int */
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM = 121, /*!< normalised unsigned int */
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM_SRGB = 122, /*!< normalised unsigned int */
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SINT = 123, /*!< signed int */
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SNORM = 124, /*!< normalised signed int */
+
+ /* 2 component, 8 bits per component types */
+ PVRSRV_PIXEL_FORMAT_G8R8 = 125, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_G8R8_UINT = 126, /*!< unsigned int type */
+ PVRSRV_PIXEL_FORMAT_G8R8_UNORM = 127, /*!< unsigned int normalised */
+ PVRSRV_PIXEL_FORMAT_G8R8_SINT = 128, /*!< signed int type */
+ PVRSRV_PIXEL_FORMAT_G8R8_SNORM = 129, /*!< signed int normalised */
+
+ /* 1 component, 8 bits per component types */
+ PVRSRV_PIXEL_FORMAT_A8 = 130, /*!< type unspecified, alpha channel */
+ PVRSRV_PIXEL_FORMAT_R8 = 131, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_R8_UINT = 132, /*!< unsigned int */
+ PVRSRV_PIXEL_FORMAT_R8_UNORM = 133, /*!< unsigned normalised int */
+ PVRSRV_PIXEL_FORMAT_R8_SINT = 134, /*!< signed int */
+ PVRSRV_PIXEL_FORMAT_R8_SNORM = 135, /*!< signed normalised int */
+
+ /* A2RGB10 types */
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10 = 136, /*!< Type unspecified */
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UNORM = 137, /*!< normalised unsigned int */
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UINT = 138, /*!< unsigned int */
+
+ /* F11F11F10 types */
+ PVRSRV_PIXEL_FORMAT_B10G11R11 = 139, /*!< type unspecified */
+ PVRSRV_PIXEL_FORMAT_B10G11R11F = 140, /*!< float type */
+
+ /* esoteric types */
+ PVRSRV_PIXEL_FORMAT_X24G8R32 = 141, /*!< 64 bit, type unspecified (Usually typed to D32S8 style) */
+ PVRSRV_PIXEL_FORMAT_G8R24 = 142, /*!< 32 bit, type unspecified (Usually typed to D24S8 style) */
+ PVRSRV_PIXEL_FORMAT_X8R24 = 143,
+ PVRSRV_PIXEL_FORMAT_E5B9G9R9 = 144, /*!< 32 bit, shared exponent (RGBE). */
+ PVRSRV_PIXEL_FORMAT_R1 = 145, /*!< 1 bit monochrome */
+
+ PVRSRV_PIXEL_FORMAT_RESERVED6 = 146,
+ PVRSRV_PIXEL_FORMAT_RESERVED7 = 147,
+ PVRSRV_PIXEL_FORMAT_RESERVED8 = 148,
+ PVRSRV_PIXEL_FORMAT_RESERVED9 = 149,
+ PVRSRV_PIXEL_FORMAT_RESERVED10 = 150,
+ PVRSRV_PIXEL_FORMAT_RESERVED11 = 151,
+ PVRSRV_PIXEL_FORMAT_RESERVED12 = 152,
+ PVRSRV_PIXEL_FORMAT_RESERVED13 = 153,
+ PVRSRV_PIXEL_FORMAT_RESERVED14 = 154,
+ PVRSRV_PIXEL_FORMAT_RESERVED15 = 155,
+ PVRSRV_PIXEL_FORMAT_RESERVED16 = 156,
+ PVRSRV_PIXEL_FORMAT_RESERVED17 = 157,
+ PVRSRV_PIXEL_FORMAT_RESERVED18 = 158,
+ PVRSRV_PIXEL_FORMAT_RESERVED19 = 159,
+ PVRSRV_PIXEL_FORMAT_RESERVED20 = 160,
+
+ /* DXLegacy vertex types */
+ PVRSRV_PIXEL_FORMAT_UBYTE4 = 161, /*!< 4 channels, 1 byte per channel, normalised */
+ PVRSRV_PIXEL_FORMAT_SHORT4 = 162, /*!< 4 signed channels, 16 bits each, unnormalised */
+ PVRSRV_PIXEL_FORMAT_SHORT4N = 163, /*!< 4 signed channels, 16 bits each, normalised */
+ PVRSRV_PIXEL_FORMAT_USHORT4N = 164, /*!< 4 unsigned channels, 16 bits each, normalised */
+ PVRSRV_PIXEL_FORMAT_SHORT2N = 165, /*!< 2 signed channels, 16 bits each, normalised */
+ PVRSRV_PIXEL_FORMAT_SHORT2 = 166, /*!< 2 signed channels, 16 bits each, unnormalised */
+ PVRSRV_PIXEL_FORMAT_USHORT2N = 167, /*!< 2 unsigned channels, 16 bits each, normalised */
+ PVRSRV_PIXEL_FORMAT_UDEC3 = 168, /*!< 3 10-bit channels, unnormalised, unsigned*/
+ PVRSRV_PIXEL_FORMAT_DEC3N = 169, /*!< 3 10-bit channels, signed normalised */
+ PVRSRV_PIXEL_FORMAT_F16_2 = 170, /*!< 2 F16 channels */
+ PVRSRV_PIXEL_FORMAT_F16_4 = 171, /*!< 4 F16 channels */
+
+ /* misc float types */
+ PVRSRV_PIXEL_FORMAT_L_F16 = 172,
+ PVRSRV_PIXEL_FORMAT_L_F16_REP = 173,
+ PVRSRV_PIXEL_FORMAT_L_F16_A_F16 = 174,
+ PVRSRV_PIXEL_FORMAT_A_F16 = 175,
+ PVRSRV_PIXEL_FORMAT_B16G16R16F = 176,
+
+ PVRSRV_PIXEL_FORMAT_L_F32 = 177,
+ PVRSRV_PIXEL_FORMAT_A_F32 = 178,
+ PVRSRV_PIXEL_FORMAT_L_F32_A_F32 = 179,
+
+ /* powervr types */
+ PVRSRV_PIXEL_FORMAT_PVRTC2 = 180,
+ PVRSRV_PIXEL_FORMAT_PVRTC4 = 181,
+ PVRSRV_PIXEL_FORMAT_PVRTCII2 = 182,
+ PVRSRV_PIXEL_FORMAT_PVRTCII4 = 183,
+ PVRSRV_PIXEL_FORMAT_PVRTCIII = 184,
+ PVRSRV_PIXEL_FORMAT_PVRO8 = 185,
+ PVRSRV_PIXEL_FORMAT_PVRO88 = 186,
+ PVRSRV_PIXEL_FORMAT_PT1 = 187,
+ PVRSRV_PIXEL_FORMAT_PT2 = 188,
+ PVRSRV_PIXEL_FORMAT_PT4 = 189,
+ PVRSRV_PIXEL_FORMAT_PT8 = 190,
+ PVRSRV_PIXEL_FORMAT_PTW = 191,
+ PVRSRV_PIXEL_FORMAT_PTB = 192,
+ PVRSRV_PIXEL_FORMAT_MONO8 = 193,
+ PVRSRV_PIXEL_FORMAT_MONO16 = 194,
+
+ /* additional YUV types */
+ PVRSRV_PIXEL_FORMAT_C0_YUYV = 195,
+ PVRSRV_PIXEL_FORMAT_C0_UYVY = 196,
+ PVRSRV_PIXEL_FORMAT_C0_YVYU = 197,
+ PVRSRV_PIXEL_FORMAT_C0_VYUY = 198,
+ PVRSRV_PIXEL_FORMAT_C1_YUYV = 199,
+ PVRSRV_PIXEL_FORMAT_C1_UYVY = 200,
+ PVRSRV_PIXEL_FORMAT_C1_YVYU = 201,
+ PVRSRV_PIXEL_FORMAT_C1_VYUY = 202,
+
+ /* planar YUV types */
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_UV = 203,
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_VU = 204,
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_3P = 205,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_UV = 206,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_VU = 207,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_3P = 208,
+
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10F = 209,
+ PVRSRV_PIXEL_FORMAT_B8G8R8_SINT = 210,
+ PVRSRV_PIXEL_FORMAT_PVRF32SIGNMASK = 211,
+
+ PVRSRV_PIXEL_FORMAT_ABGR4444 = 212,
+ PVRSRV_PIXEL_FORMAT_ABGR1555 = 213,
+ PVRSRV_PIXEL_FORMAT_BGR565 = 214,
+
+ /* 4k aligned planar YUV */
+ PVRSRV_PIXEL_FORMAT_C0_4KYUV420_2P_UV = 215,
+ PVRSRV_PIXEL_FORMAT_C0_4KYUV420_2P_VU = 216,
+ PVRSRV_PIXEL_FORMAT_C1_4KYUV420_2P_UV = 217,
+ PVRSRV_PIXEL_FORMAT_C1_4KYUV420_2P_VU = 218,
+ PVRSRV_PIXEL_FORMAT_P208 = 219,
+ PVRSRV_PIXEL_FORMAT_A8P8 = 220,
+
+ PVRSRV_PIXEL_FORMAT_A4 = 221,
+ PVRSRV_PIXEL_FORMAT_AYUV8888 = 222,
+ PVRSRV_PIXEL_FORMAT_RAW256 = 223,
+ PVRSRV_PIXEL_FORMAT_RAW512 = 224,
+ PVRSRV_PIXEL_FORMAT_RAW1024 = 225,
+
+ PVRSRV_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_PIXEL_FORMAT;
+
+/*!
+ *****************************************************************************
+ * Enumeration of possible alpha types.
+ *****************************************************************************/
+typedef enum _PVRSRV_ALPHA_FORMAT_ {
+ PVRSRV_ALPHA_FORMAT_UNKNOWN = 0x00000000,
+ PVRSRV_ALPHA_FORMAT_PRE = 0x00000001,
+ PVRSRV_ALPHA_FORMAT_NONPRE = 0x00000002,
+ PVRSRV_ALPHA_FORMAT_MASK = 0x0000000F,
+} PVRSRV_ALPHA_FORMAT;
+
+/*!
+ *****************************************************************************
+ * Enumeration of possible alpha types.
+ *****************************************************************************/
+typedef enum _PVRSRV_COLOURSPACE_FORMAT_ {
+ PVRSRV_COLOURSPACE_FORMAT_UNKNOWN = 0x00000000,
+ PVRSRV_COLOURSPACE_FORMAT_LINEAR = 0x00010000,
+ PVRSRV_COLOURSPACE_FORMAT_NONLINEAR = 0x00020000,
+ PVRSRV_COLOURSPACE_FORMAT_MASK = 0x000F0000,
+} PVRSRV_COLOURSPACE_FORMAT;
+
+
+/*
+ * Drawable orientation (in degrees clockwise).
+ * Opposite sense from WSEGL.
+ */
+typedef enum _PVRSRV_ROTATION_ {
+ PVRSRV_ROTATE_0 = 0,
+ PVRSRV_ROTATE_90 = 1,
+ PVRSRV_ROTATE_180 = 2,
+ PVRSRV_ROTATE_270 = 3,
+ PVRSRV_FLIP_Y
+
+} PVRSRV_ROTATION;
+
+/*!
+ * Flags for DisplayClassCreateSwapChain.
+ */
+#define PVRSRV_CREATE_SWAPCHAIN_SHARED (1<<0)
+#define PVRSRV_CREATE_SWAPCHAIN_QUERY (1<<1)
+#define PVRSRV_CREATE_SWAPCHAIN_OEMOVERLAY (1<<2)
+
+/*!
+ *****************************************************************************
+ * Structure providing implementation details for serialisation and
+ * synchronisation of operations. This is the fundamental unit on which operations
+ * are synced, and would typically be included in any data structures that require
+ * serialised accesses etc. e.g. MEM_INFO structures
+ *
+ *****************************************************************************/
+/*
+ Sync Data to be shared/mapped between user/kernel
+*/
+typedef struct _PVRSRV_SYNC_DATA_
+{
+ /* CPU accessible WriteOp Info */
+ IMG_UINT32 ui32WriteOpsPending;
+ volatile IMG_UINT32 ui32WriteOpsComplete;
+
+ /* CPU accessible ReadOp Info */
+ IMG_UINT32 ui32ReadOpsPending;
+ volatile IMG_UINT32 ui32ReadOpsComplete;
+
+ /* CPU accessible ReadOp2 Info */
+ IMG_UINT32 ui32ReadOps2Pending;
+ volatile IMG_UINT32 ui32ReadOps2Complete;
+
+ /* pdump specific value */
+ IMG_UINT32 ui32LastOpDumpVal;
+ IMG_UINT32 ui32LastReadOpDumpVal;
+
+ /* Last write oprtation on this sync */
+ IMG_UINT64 ui64LastWrite;
+
+} PVRSRV_SYNC_DATA;
+
+/*
+ Client Sync Info structure
+*/
+typedef struct _PVRSRV_CLIENT_SYNC_INFO_
+{
+ /* mapping of the kernel sync data */
+ PVRSRV_SYNC_DATA *psSyncData;
+
+ /* Device accessible WriteOp Info */
+ IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+
+ /* Device accessible ReadOp Info */
+ IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+
+ /* Device accessible ReadOp2 Info */
+ IMG_DEV_VIRTADDR sReadOps2CompleteDevVAddr;
+
+ /* handle to client mapping data (OS specific) */
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMappingInfo;
+
+ /* handle to kernel sync info */
+ IMG_SID hKernelSyncInfo;
+#else
+ IMG_HANDLE hMappingInfo;
+
+ /* handle to kernel sync info */
+ IMG_HANDLE hKernelSyncInfo;
+#endif
+
+} PVRSRV_CLIENT_SYNC_INFO, *PPVRSRV_CLIENT_SYNC_INFO;
+
+/*!
+ *****************************************************************************
+ * Resource locking structure
+ *****************************************************************************/
+typedef struct PVRSRV_RESOURCE_TAG
+{
+ volatile IMG_UINT32 ui32Lock;
+ IMG_UINT32 ui32ID;
+}PVRSRV_RESOURCE;
+typedef PVRSRV_RESOURCE PVRSRV_RES_HANDLE;
+
+
+/* command complete callback pfn prototype */
+typedef IMG_VOID (*PFN_CMD_COMPLETE) (IMG_HANDLE);
+typedef IMG_VOID (**PPFN_CMD_COMPLETE) (IMG_HANDLE);
+
+/* private command handler prototype */
+typedef IMG_BOOL (*PFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+typedef IMG_BOOL (**PPFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+
+
+/*
+ rectangle structure required by Lock API
+*/
+typedef struct _IMG_RECT_
+{
+ IMG_INT32 x0;
+ IMG_INT32 y0;
+ IMG_INT32 x1;
+ IMG_INT32 y1;
+}IMG_RECT;
+
+typedef struct _IMG_RECT_16_
+{
+ IMG_INT16 x0;
+ IMG_INT16 y0;
+ IMG_INT16 x1;
+ IMG_INT16 y1;
+}IMG_RECT_16;
+
+
+/* common pfn between BC/DC */
+typedef PVRSRV_ERROR (*PFN_GET_BUFFER_ADDR)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_SYS_PHYADDR**,
+ IMG_SIZE_T*,
+ IMG_VOID**,
+ IMG_HANDLE*,
+ IMG_BOOL*,
+ IMG_UINT32*);
+
+
+/*
+ Display dimension structure definition
+*/
+typedef struct DISPLAY_DIMS_TAG
+{
+ IMG_UINT32 ui32ByteStride;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+} DISPLAY_DIMS;
+
+
+/*
+ Display format structure definition
+*/
+typedef struct DISPLAY_FORMAT_TAG
+{
+ /* pixel format type */
+ PVRSRV_PIXEL_FORMAT pixelformat;
+} DISPLAY_FORMAT;
+
+/*
+ Display Surface Attributes structure definition
+*/
+typedef struct DISPLAY_SURF_ATTRIBUTES_TAG
+{
+ /* pixel format type */
+ PVRSRV_PIXEL_FORMAT pixelformat;
+ /* dimensions information structure array */
+ DISPLAY_DIMS sDims;
+} DISPLAY_SURF_ATTRIBUTES;
+
+
+/*
+ Display Mode information structure definition
+*/
+typedef struct DISPLAY_MODE_INFO_TAG
+{
+ /* pixel format type */
+ PVRSRV_PIXEL_FORMAT pixelformat;
+ /* dimensions information structure array */
+ DISPLAY_DIMS sDims;
+ /* refresh rate of the display */
+ IMG_UINT32 ui32RefreshHZ;
+ /* OEM specific flags */
+ IMG_UINT32 ui32OEMFlags;
+} DISPLAY_MODE_INFO;
+
+
+
+#define MAX_DISPLAY_NAME_SIZE (50) /* arbitrary choice! */
+
+/*
+ Display info structure definition
+*/
+typedef struct DISPLAY_INFO_TAG
+{
+ /* max swapchains supported */
+ IMG_UINT32 ui32MaxSwapChains;
+ /* max buffers in a swapchain */
+ IMG_UINT32 ui32MaxSwapChainBuffers;
+ /* min swap interval supported */
+ IMG_UINT32 ui32MinSwapInterval;
+ /* max swap interval supported */
+ IMG_UINT32 ui32MaxSwapInterval;
+ /* physical dimensions of the display required for DPI calc. */
+ IMG_UINT32 ui32PhysicalWidthmm;
+ IMG_UINT32 ui32PhysicalHeightmm;
+ /* display name */
+ IMG_CHAR szDisplayName[MAX_DISPLAY_NAME_SIZE];
+#if defined(SUPPORT_HW_CURSOR)
+ /* cursor dimensions */
+ IMG_UINT16 ui32CursorWidth;
+ IMG_UINT16 ui32CursorHeight;
+#endif
+} DISPLAY_INFO;
+
+typedef struct ACCESS_INFO_TAG
+{
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32FBPhysBaseAddress;
+ IMG_UINT32 ui32FBMemAvailable; /* size of usable FB memory */
+ IMG_UINT32 ui32SysPhysBaseAddress;
+ IMG_UINT32 ui32SysSize;
+ IMG_UINT32 ui32DevIRQ;
+}ACCESS_INFO;
+
+
+
+#if defined(PDUMP_SUSPEND_IS_PER_THREAD)
+/** Present only on WinMobile 6.5 */
+
+typedef struct {
+ IMG_UINT32 threadId;
+ IMG_INT suspendCount;
+} PVRSRV_THREAD_SUSPEND_COUNT;
+
+#define PVRSRV_PDUMP_SUSPEND_Q_NAME "PVRSRVPDumpSuspendMsgQ"
+#define PVRSRV_PDUMP_SUSPEND_Q_LENGTH 8
+
+#endif /* defined(PDUMP_SUSPEND_IS_PER_THREAD) */
+
+
+/*!
+ *****************************************************************************
+ * This structure is used for OS independent registry (profile) access
+ *****************************************************************************/
+typedef struct _PVRSRV_REGISTRY_INFO_
+{
+ IMG_UINT32 ui32DevCookie;
+ IMG_PCHAR pszKey;
+ IMG_PCHAR pszValue;
+ IMG_PCHAR pszBuf;
+ IMG_UINT32 ui32BufSize;
+} PVRSRV_REGISTRY_INFO, *PPVRSRV_REGISTRY_INFO;
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReadRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWriteRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+
+
+#define PVRSRV_BC_FLAGS_YUVCSC_CONFORMANT_RANGE (0 << 0)
+#define PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE (1 << 0)
+
+#define PVRSRV_BC_FLAGS_YUVCSC_BT601 (0 << 1)
+#define PVRSRV_BC_FLAGS_YUVCSC_BT709 (1 << 1)
+
+#define MAX_BUFFER_DEVICE_NAME_SIZE (50) /* arbitrary choice! */
+
+/* buffer information structure */
+typedef struct BUFFER_INFO_TAG
+{
+ IMG_UINT32 ui32BufferCount;
+ IMG_UINT32 ui32BufferDeviceID;
+ PVRSRV_PIXEL_FORMAT pixelformat;
+ IMG_UINT32 ui32ByteStride;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+ IMG_UINT32 ui32Flags;
+ IMG_CHAR szDeviceName[MAX_BUFFER_DEVICE_NAME_SIZE];
+} BUFFER_INFO;
+
+typedef enum _OVERLAY_DEINTERLACE_MODE_
+{
+ WEAVE=0x0,
+ BOB_ODD,
+ BOB_EVEN,
+ BOB_EVEN_NONINTERLEAVED
+} OVERLAY_DEINTERLACE_MODE;
+
+#endif /* __SERVICESEXT_H__ */
+/*****************************************************************************
+ End of file (servicesext.h)
+*****************************************************************************/
diff --git a/include/linux/bltsville.h b/include/linux/bltsville.h
--- /dev/null
@@ -0,0 +1,599 @@
+/*
+ * bltsville.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef BLTSVILLE_H
+#define BLTSVILLE_H
+
+#include "ocd.h"
+#include "bverror.h"
+#include "bvblend.h"
+#include "bvfilter.h"
+#include "bvbuffdesc.h"
+#include "bvcache.h"
+#include "bventry.h"
+#include "bvsurfgeom.h"
+
+/*
+ * bvrect - This structure is used to specify rectangles in BLTsville.
+ */
+struct bvrect {
+ int left;
+ int top;
+ unsigned int width;
+ unsigned int height;
+};
+
+
+/*
+ * BVFLAG_* - These define the type of BLT to be performed and are placed in
+ * the bvparams.flags element.
+ */
+#define BVFLAG_OP_SHIFT 0
+#define BVFLAG_OP_MASK (0xF << BVFLAG_OP_SHIFT)
+
+/* 0 reserved */
+#define BVFLAG_ROP (0x1 << BVFLAG_OP_SHIFT) /* ROP4 spec'd in rop */
+#define BVFLAG_BLEND (0x2 << BVFLAG_OP_SHIFT) /* blend spec'd in blend */
+/* 3 reserved */
+#define BVFLAG_FILTER (0x4 << BVFLAG_OP_SHIFT) /* filter spec'd in filter */
+/* 5-F reserved */
+
+#define BVFLAG_KEY_SRC 0x00000010 /* source color key - value spec'd
+ by pcolorkey; Mutually exclusive
+ with BVFLAG_KEY_DST */
+#define BVFLAG_KEY_DST 0x00000020 /* dest color key - value spec'd
+ by pcolorkey; Mutually exclusive
+ with BVFLAG_KEY_SRC */
+#define BVFLAG_CLIP 0x00000040 /* clipping rectangle spec'd by
+ cliprect */
+#define BVFLAG_SRCMASK 0x00000080 /* when scaling a masked copy, mask
+ at the source instead of the
+ (default) destination */
+
+#define BVFLAG_ASYNC 0x00000100 /* call should return once queued */
+
+#define BVFLAG_TILE_SRC1 0x00000200 /* source 1 is tiled */
+#define BVFLAG_TILE_SRC2 0x00000400 /* source 2 is tiled */
+#define BVFLAG_TILE_MASK 0x00000800 /* mask is tiled */
+
+
+#define BVFLAG_BATCH_SHIFT 12
+#define BVFLAG_BATCH_MASK (3 << BVFLAG_BATCH_SHIFT)
+
+#define BVFLAG_BATCH_NONE (0 << BVFLAG_BATCH_SHIFT) /* not batched */
+#define BVFLAG_BATCH_BEGIN (1 << BVFLAG_BATCH_SHIFT) /* begin batch */
+#define BVFLAG_BATCH_CONTINUE (2 << BVFLAG_BATCH_SHIFT) /* continue batch */
+#define BVFLAG_BATCH_END (3 << BVFLAG_BATCH_SHIFT) /* end batch */
+
+
+#define BVFLAG_HORZ_FLIP_SRC1 0x00004000 /* flip src1 horizontally */
+#define BVFLAG_VERT_FLIP_SRC1 0x00008000 /* flip src1 vertically */
+#define BVFLAG_HORZ_FLIP_SRC2 0x00010000 /* flip src2 horizontally */
+#define BVFLAG_VERT_FLIP_SRC2 0x00020000 /* flip src2 vertically */
+#define BVFLAG_HORZ_FLIP_MASK 0x00040000 /* flip mask horizontally */
+#define BVFLAG_VERT_FLIP_MASK 0x00080000 /* flip mask vertically */
+
+
+#define BVFLAG_SCALE_RETURN 0x00100000 /* return scale type used */
+#define BVFLAG_DITHER_RETURN 0x00200000 /* return dither type used */
+
+
+#define BVFLAG_SRC2_AUXDSTRECT 0x00400000 /* src2auxdstrect used */
+#define BVFLAG_MASK_AUXDSTRECT 0x00800000 /* maskauxdstrect used */
+/**** Bits 31-24 reserved ****/
+
+/*
+ * BVIMPL_* - BLTsville implementations may be combined under managers to
+ * allow clients to take advantage of multiple implementations without doing
+ * so explicitly. The BVIMPL_* definition are placed into the
+ * bvparams.implementation member by the client to override the manager's
+ * choice of implementation.
+ */
+#define BVIMPL_ANY 0
+#define BVIMPL_FIRST_HW (1 << 31) /* Continues to the right */
+#define BVIMPL_FIRST_CPU (1 << 0) /* Continues to the left */
+
+
+/*
+ * bvscalemode - This specifies the type of scaling to perform.
+ */
+#define BVSCALEDEF_VENDOR_SHIFT 24
+#define BVSCALEDEF_VENDOR_MASK (0xFF << BVSCALEDEF_VENDOR_SHIFT)
+
+#define BVSCALEDEF_VENDOR_ALL (0 << BVSCALEDEF_VENDOR_SHIFT)
+#define BVSCALEDEF_VENDOR_TI (1 << BVSCALEDEF_VENDOR_SHIFT)
+/* 0xF0-0xFE reserved */
+#define BVSCALEDEF_VENDOR_GENERIC (0xFF << BVSCALEDEF_VENDOR_SHIFT)
+
+/***** VENDOR_GENERIC definitions *****/
+/**** Bits 23-22 indicate classification ****/
+#define BVSCALEDEF_CLASS_SHIFT 22
+#define BVSCALEDEF_IMPLICIT (0 << BVSCALEDEF_CLASS_SHIFT)
+#define BVSCALEDEF_EXPLICIT (1 << BVSCALEDEF_CLASS_SHIFT)
+/* 2-3 reserved */
+#define BVSCALEDEF_CLASS_MASK (3 << BVSCALEDEF_CLASS_SHIFT)
+
+/**** IMPLICIT definitions ****/
+/*** Bits 21-16 indicate the quality (speed) desired ***/
+#define BVSCALEDEF_QUALITY_SHIFT 16
+#define BVSCALEDEF_FASTEST (0x00 << BVSCALEDEF_QUALITY_SHIFT)
+#define BVSCALEDEF_GOOD (0x15 << BVSCALEDEF_QUALITY_SHIFT)
+#define BVSCALEDEF_BETTER (0x2A << BVSCALEDEF_QUALITY_SHIFT)
+#define BVSCALEDEF_BEST (0x3F << BVSCALEDEF_QUALITY_SHIFT)
+#define BVSCALEDEF_QUALITY_MASK (0x3F << BVSCALEDEF_QUALITY_SHIFT)
+/* Bits 15-12 are reserved */
+/*** Bits 11-8 indicate the desired technique ***/
+#define BVSCALEDEF_TECHNIQUE_SHIFT 8
+#define BVSCALEDEF_DONT_CARE (0x0 << BVSCALEDEF_TECHNIQUE_SHIFT)
+#define BVSCALEDEF_NOT_NEAREST_NEIGHBOR (0x1 << BVSCALEDEF_TECHNIQUE_SHIFT)
+#define BVSCALEDEF_POINT_SAMPLE (0x2 << BVSCALEDEF_TECHNIQUE_SHIFT)
+#define BVSCALEDEF_INTERPOLATED (0x3 << BVSCALEDEF_TECHNIQUE_SHIFT)
+#define BVSCALEDEF_TECHNIQUE_MASK (0xF << BVSCALEDEF_TECHNIQUE_SHIFT)
+/* Bits 7-2 reserved */
+/*** Bits 1-0 indicate the type of image ***/
+#define BVSCALEDEF_TYPE_SHIFT 0
+/* 0 don't know */
+#define BVSCALEDEF_PHOTO (1 << BVSCALEDEF_TYPE_SHIFT)
+#define BVSCALEDEF_DRAWING (2 << BVSCALEDEF_TYPE_SHIFT)
+/* 3 reserved */
+#define BVSCALEDEF_TYPE_MASK (3 << BVSCALEDEF_TYPE_SHIFT)
+
+/**** EXPLICIT definitions ****/
+/* Bits 21-16 reserved */
+#define BVSCALEDEF_HORZ_SHIFT 8
+#define BVSCALEDEF_HORZ_MASK (0xFF << BVSCALEDEF_HORZ_SHIFT)
+
+#define BVSCALEDEF_VERT_SHIFT 0
+#define BVSCALEDEF_VERT_MASK (0xFF << BVSCALEDEF_VERT_SHIFT)
+
+#define BVSCALEDEF_NEAREST_NEIGHBOR 0x00
+#define BVSCALEDEF_LINEAR 0x01
+#define BVSCALEDEF_CUBIC 0x02
+#define BVSCALEDEF_3_TAP 0x03
+/* 0x04 reserved */
+#define BVSCALEDEF_5_TAP 0x05
+/* 0x06 reserved */
+#define BVSCALEDEF_7_TAP 0x07
+/* 0x08 reserved */
+#define BVSCALEDEF_9_TAP 0x09
+/* 0x0A-0xFF reserved */
+
+enum bvscalemode {
+ BVSCALE_FASTEST = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_FASTEST |
+ BVSCALEDEF_DONT_CARE,
+ BVSCALE_FASTEST_NOT_NEAREST_NEIGHBOR = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_FASTEST |
+ BVSCALEDEF_NOT_NEAREST_NEIGHBOR,
+ BVSCALE_FASTEST_POINT_SAMPLE = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_FASTEST |
+ BVSCALEDEF_POINT_SAMPLE,
+ BVSCALE_FASTEST_INTERPOLATED = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_FASTEST |
+ BVSCALEDEF_INTERPOLATED,
+ BVSCALE_FASTEST_PHOTO = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_FASTEST |
+ BVSCALEDEF_PHOTO,
+ BVSCALE_FASTEST_DRAWING = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_FASTEST |
+ BVSCALEDEF_DRAWING,
+ BVSCALE_GOOD = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_GOOD |
+ BVSCALEDEF_DONT_CARE,
+ BVSCALE_GOOD_POINT_SAMPLE = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_GOOD |
+ BVSCALEDEF_POINT_SAMPLE,
+ BVSCALE_GOOD_INTERPOLATED = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_GOOD |
+ BVSCALEDEF_INTERPOLATED,
+ BVSCALE_GOOD_PHOTO = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_GOOD |
+ BVSCALEDEF_PHOTO,
+ BVSCALE_GOOD_DRAWING = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_GOOD |
+ BVSCALEDEF_DRAWING,
+ BVSCALE_BETTER = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_BETTER |
+ BVSCALEDEF_DONT_CARE,
+ BVSCALE_BETTER_POINT_SAMPLE = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_BETTER |
+ BVSCALEDEF_POINT_SAMPLE,
+ BVSCALE_BETTER_INTERPOLATED = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_BETTER |
+ BVSCALEDEF_INTERPOLATED,
+ BVSCALE_BETTER_PHOTO = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_BETTER |
+ BVSCALEDEF_PHOTO,
+ BVSCALE_BETTER_DRAWING = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_BETTER |
+ BVSCALEDEF_DRAWING,
+ BVSCALE_BEST = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_BEST |
+ BVSCALEDEF_DONT_CARE,
+ BVSCALE_BEST_POINT_SAMPLE = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_BEST |
+ BVSCALEDEF_POINT_SAMPLE,
+ BVSCALE_BEST_INTERPOLATED = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_BEST |
+ BVSCALEDEF_INTERPOLATED,
+ BVSCALE_BEST_PHOTO = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_BEST |
+ BVSCALEDEF_PHOTO,
+ BVSCALE_BEST_DRAWING = BVSCALEDEF_VENDOR_ALL |
+ BVSCALEDEF_IMPLICIT |
+ BVSCALEDEF_BEST |
+ BVSCALEDEF_DRAWING,
+
+ BVSCALE_NEAREST_NEIGHBOR = BVSCALEDEF_VENDOR_GENERIC |
+ BVSCALEDEF_EXPLICIT |
+ (BVSCALEDEF_NEAREST_NEIGHBOR << BVSCALEDEF_HORZ_SHIFT) |
+ (BVSCALEDEF_NEAREST_NEIGHBOR << BVSCALEDEF_VERT_SHIFT),
+ BVSCALE_BILINEAR = BVSCALEDEF_VENDOR_GENERIC |
+ BVSCALEDEF_EXPLICIT |
+ (BVSCALEDEF_LINEAR << BVSCALEDEF_HORZ_SHIFT) |
+ (BVSCALEDEF_LINEAR << BVSCALEDEF_VERT_SHIFT),
+ BVSCALE_BICUBIC = BVSCALEDEF_VENDOR_GENERIC |
+ BVSCALEDEF_EXPLICIT |
+ (BVSCALEDEF_CUBIC << BVSCALEDEF_HORZ_SHIFT) |
+ (BVSCALEDEF_CUBIC << BVSCALEDEF_VERT_SHIFT),
+ BVSCALE_3x3_TAP = BVSCALEDEF_VENDOR_GENERIC |
+ BVSCALEDEF_EXPLICIT |
+ (BVSCALEDEF_3_TAP << BVSCALEDEF_HORZ_SHIFT) |
+ (BVSCALEDEF_3_TAP << BVSCALEDEF_VERT_SHIFT),
+ BVSCALE_5x5_TAP = BVSCALEDEF_VENDOR_GENERIC |
+ BVSCALEDEF_EXPLICIT |
+ (BVSCALEDEF_5_TAP << BVSCALEDEF_HORZ_SHIFT) |
+ (BVSCALEDEF_5_TAP << BVSCALEDEF_VERT_SHIFT),
+ BVSCALE_7x7_TAP = BVSCALEDEF_VENDOR_GENERIC |
+ BVSCALEDEF_EXPLICIT |
+ (BVSCALEDEF_7_TAP << BVSCALEDEF_HORZ_SHIFT) |
+ (BVSCALEDEF_7_TAP << BVSCALEDEF_VERT_SHIFT),
+ BVSCALE_9x9_TAP = BVSCALEDEF_VENDOR_GENERIC |
+ BVSCALEDEF_EXPLICIT |
+ (BVSCALEDEF_9_TAP << BVSCALEDEF_HORZ_SHIFT) |
+ (BVSCALEDEF_9_TAP << BVSCALEDEF_VERT_SHIFT),
+
+#ifdef BVSCALE_EXTERNAL_INCLUDE
+#include BVSCALE_EXTERNAL_INCLUDE
+#endif
+};
+
+
+/*
+ * bvdithermode - This defines the type of dithering to use.
+ */
+#define BVDITHERDEF_VENDOR_SHIFT 24
+#define BVDITHERDEF_VENDOR_MASK (0xFF << BVDITHERDEF_VENDOR_SHIFT)
+
+#define BVDITHERDEF_VENDOR_ALL (0 << BVDITHERDEF_VENDOR_SHIFT)
+#define BVDITHERDEF_VENDOR_TI (1 << BVDITHERDEF_VENDOR_SHIFT)
+/* 0xF0-0xFE reserved */
+#define BVDITHERDEF_VENDOR_GENERIC (0xFF << BVDITHERDEF_VENDOR_SHIFT)
+
+/***** VENDOR_GENERIC definitions *****/
+/* Bits 23-18 reserved */
+/**** Bits 17-16 indicate the type of image - 0 = don't know ****/
+#define BVDITHERDEF_TYPE_SHIFT 16
+#define BVDITHERDEF_PHOTO (0x01 << BVDITHERDEF_TYPE_SHIFT)
+#define BVDITHERDEF_DRAWING (0x02 << BVDITHERDEF_TYPE_SHIFT)
+/**** Bits 15-8 indicate the desired technique ****/
+#define BVDITHERDEF_TECHNIQUE_SHIFT 8
+#define BVDITHERDEF_DONT_CARE (0x00 << BVDITHERDEF_TECHNIQUE_SHIFT)
+#define BVDITHERDEF_RANDOM (0x01 << BVDITHERDEF_TECHNIQUE_SHIFT)
+#define BVDITHERDEF_ORDERED (0x02 << BVDITHERDEF_TECHNIQUE_SHIFT)
+#define BVDITHERDEF_DIFFUSED (0x04 << BVDITHERDEF_TECHNIQUE_SHIFT)
+#define BVDITHERDEF_ON (0xFF << BVDITHERDEF_TECHNIQUE_SHIFT)
+/**** Bits 7-0 indicate the quality (speed) desired ****/
+#define BVDITHERDEF_QUALITY_SHIFT 0
+#define BVDITHERDEF_FASTEST (0x00 << BVDITHERDEF_QUALITY_SHIFT)
+#define BVDITHERDEF_GOOD (0x55 << BVDITHERDEF_QUALITY_SHIFT)
+#define BVDITHERDEF_BETTER (0xAA << BVDITHERDEF_QUALITY_SHIFT)
+#define BVDITHERDEF_BEST (0xFF << BVDITHERDEF_QUALITY_SHIFT)
+
+enum bvdithermode {
+ BVDITHER_FASTEST = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_FASTEST |
+ BVDITHERDEF_DONT_CARE,
+ BVDITHER_FASTEST_ON = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_FASTEST |
+ BVDITHERDEF_ON,
+ BVDITHER_FASTEST_RANDOM = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_FASTEST |
+ BVDITHERDEF_RANDOM,
+ BVDITHER_FASTEST_ORDERED = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_FASTEST |
+ BVDITHERDEF_ORDERED,
+ BVDITHER_FASTEST_DIFFUSED = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_FASTEST |
+ BVDITHERDEF_DIFFUSED,
+ BVDITHER_FASTEST_PHOTO = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_FASTEST |
+ BVDITHERDEF_PHOTO,
+ BVDITHER_FASTEST_DRAWING = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_FASTEST |
+ BVDITHERDEF_DRAWING,
+ BVDITHER_GOOD = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_GOOD |
+ BVDITHERDEF_DONT_CARE,
+ BVDITHER_GOOD_ON = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_GOOD |
+ BVDITHERDEF_ON,
+ BVDITHER_GOOD_RANDOM = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_GOOD |
+ BVDITHERDEF_RANDOM,
+ BVDITHER_GOOD_ORDERED = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_GOOD |
+ BVDITHERDEF_ORDERED,
+ BVDITHER_GOOD_DIFFUSED = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_GOOD |
+ BVDITHERDEF_DIFFUSED,
+ BVDITHER_GOOD_PHOTO = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_GOOD |
+ BVDITHERDEF_PHOTO,
+ BVDITHER_GOOD_DRAWING = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_GOOD |
+ BVDITHERDEF_DRAWING,
+ BVDITHER_BETTER = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BETTER |
+ BVDITHERDEF_DONT_CARE,
+ BVDITHER_BETTER_ON = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BETTER |
+ BVDITHERDEF_ON,
+ BVDITHER_BETTER_RANDOM = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BETTER |
+ BVDITHERDEF_RANDOM,
+ BVDITHER_BETTER_ORDERED = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BETTER |
+ BVDITHERDEF_ORDERED,
+ BVDITHER_BETTER_DIFFUSED = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BETTER |
+ BVDITHERDEF_DIFFUSED,
+ BVDITHER_BETTER_PHOTO = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BETTER |
+ BVDITHERDEF_PHOTO,
+ BVDITHER_BETTER_DRAWING = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BETTER |
+ BVDITHERDEF_DRAWING,
+ BVDITHER_BEST = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BEST |
+ BVDITHERDEF_DONT_CARE,
+ BVDITHER_BEST_ON = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BEST |
+ BVDITHERDEF_ON,
+ BVDITHER_BEST_RANDOM = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BEST |
+ BVDITHERDEF_RANDOM,
+ BVDITHER_BEST_ORDERED = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BEST |
+ BVDITHERDEF_ORDERED,
+ BVDITHER_BEST_DIFFUSED = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BEST |
+ BVDITHERDEF_DIFFUSED,
+ BVDITHER_BEST_PHOTO = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BEST |
+ BVDITHERDEF_PHOTO,
+ BVDITHER_BEST_DRAWING = BVDITHERDEF_VENDOR_ALL |
+ BVDITHERDEF_BEST |
+ BVDITHERDEF_DRAWING,
+
+ BVDITHER_NONE = BVDITHERDEF_VENDOR_GENERIC + 0,
+ BVDITHER_ORDERED_2x2 = BVDITHERDEF_VENDOR_GENERIC + 4,
+ BVDITHER_ORDERED_4x4 = BVDITHERDEF_VENDOR_GENERIC + 16,
+ BVDITHER_ORDERED_2x2_4x4 = BVDITHERDEF_VENDOR_GENERIC + 4 + 16,
+ /* 2x2 for 6->8, 4x4 for 5->8 */
+
+#ifdef BVDITHER_EXTERNAL_INCLUDE
+#include BVDITHER_EXTERNAL_INCLUDE
+#endif
+};
+
+
+/*
+ * BVTILE_* flags - These specify parameters used when tiling.
+ */
+#define BVTILE_LEFT_SHIFT 0
+#define BVTILE_TOP_SHIFT (BVTILE_LEFT_SHIFT + 2)
+#define BVTILE_RIGHT_SHIFT (BVTILE_TOP_SHIFT + 2)
+#define BVTILE_BOTTOM_SHIFT (BVTILE_RIGHT_SHIFT + 2)
+#define BVTILE_LEFT_REPEAT (0 << BVTILE_LEFT_SHIFT) /* ...012301230123 */
+#define BVTILE_TOP_REPEAT (0 << BVTILE_TOP_SHIFT) /* ...012301230123 */
+#define BVTILE_RIGHT_REPEAT (0 << BVTILE_RIGHT_SHIFT) /* 012301230123... */
+#define BVTILE_BOTTOM_REPEAT (0 << BVTILE_BOTTOM_SHIFT) /* 012301230123... */
+#define BVTILE_LEFT_MIRROR (1 << BVTILE_LEFT_SHIFT) /* ...012332100123 */
+#define BVTILE_TOP_MIRROR (1 << BVTILE_TOP_SHIFT) /* ...012332100123 */
+#define BVTILE_RIGHT_MIRROR (1 << BVTILE_RIGHT_SHIFT) /* 012332100123... */
+#define BVTILE_BOTTOM_MIRROR (1 << BVTILE_BOTTOM_SHIFT) /* 012332100123... */
+
+/*
+ * bvtileparams - This structure provides additional parameters needed when
+ * tiling. This structure replaces the bvbuffdesc in bvbltparams when the
+ * associated BVFLAG_TILE_* flag is set in bvbltparams.flags.
+ */
+struct bvtileparams {
+ unsigned int structsize; /* used to ID structure version */
+ unsigned long flags; /* tile flags */
+ void *virtaddr; /* pointer to the brush */
+ int dstleft; /* horizontal offset */
+ int dsttop; /* vertical offset */
+ unsigned int srcwidth; /* w/dst width to spec horz scale */
+ unsigned int srcheight; /* w/dst height to spec vert scale */
+};
+
+/*
+ * BVBATCH_* - These flags specify the parameters that change between
+ * batched BLTs, when BVFLAG_CONTINUE or BVFLAG_END set.
+ */
+#define BVBATCH_OP 0x00000001 /* type of operation changed */
+#define BVBATCH_KEY 0x00000002 /* color key changed */
+#define BVBATCH_MISCFLAGS 0x00000004 /* other flags changed */
+#define BVBATCH_ALPHA 0x00000008 /* global alpha changed */
+#define BVBATCH_DITHER 0x00000010 /* dither changed */
+#define BVBATCH_SCALE 0x00000020 /* scaling type changed */
+/* Bits 6-7 reserved */
+#define BVBATCH_DST 0x00000100 /* destination surface changed */
+#define BVBATCH_SRC1 0x00000200 /* source 1 surface changed */
+#define BVBATCH_SRC2 0x00000400 /* source 2 surface changed */
+#define BVBATCH_MASK 0x00000800 /* mask surface changed */
+#define BVBATCH_DSTRECT_ORIGIN 0x00001000 /* dest rect origin changed */
+#define BVBATCH_DSTRECT_SIZE 0x00002000 /* dest rect dimensions changed */
+#define BVBATCH_SRC1RECT_ORIGIN 0x00004000 /* src 1 rect origin changed */
+#define BVBATCH_SRC1RECT_SIZE 0x00008000 /* src 1 rect dimensions changed */
+#define BVBATCH_SRC2RECT_ORIGIN 0x00010000 /* src 2 rect origin changed */
+#define BVBATCH_SRC2RECT_SIZE 0x00020000 /* src 2 rect dimensions changed */
+#define BVBATCH_MASKRECT_ORIGIN 0x00040000 /* mask rect origin changed */
+#define BVBATCH_MASKRECT_SIZE 0x00080000 /* mask rect dimensions changed */
+#define BVBATCH_CLIPRECT_ORIGIN 0x00100000 /* Clip rect origin changed */
+#define BVBATCH_CLIPRECT_SIZE 0x00200000 /* Clip rect dimensions changed */
+#define BVBATCH_CLIPRECT (BVBATCH_CLIPRECT_ORIGIN | \
+ BVBATCH_CLIPRECT_SIZE) /* clip rect... */
+ /* ...changed */
+#define BVBATCH_TILE_SRC1 0x00400000 /* tile params for src 1 changed */
+#define BVBATCH_TILE_SRC2 0x00800000 /* tile params for src 2 changed */
+#define BVBATCH_TILE_MASK 0x00100000 /* tile params for mask changed */
+/* Bits 30-21 reserved */
+#define BVBATCH_ENDNOP 0x80000000 /* just end batch, don't do BLT;
+ only with BVFLAG_BATCH_END */
+
+/*
+ * bvcallbackerror - This structure is passed into the callback function
+ * if an error occurs.
+ */
+struct bvcallbackerror {
+ unsigned int structsize; /* used to ID structure version */
+ enum bverror error; /* error during async BLT */
+ char *errdesc; /* 0-terminated ASCII string
+ with extended error info (not
+ for end users) */
+};
+
+/*
+ * bvbatch - an implementation-specific container for batch information;
+ * not used by client; forward declaration here
+ */
+struct bvbatch;
+
+/*
+ * bvinbuff - provides the buffer in bvbltparams
+ */
+union bvinbuff {
+ struct bvbuffdesc *desc; /* buffer description when
+ associated BVFLAG_TILE_*
+ is not set */
+ struct bvtileparams *tileparams; /* tile params when associated
+ BVFLAG_TILE_* flag is set */
+};
+
+/*
+ * bvop - used to hold the operation in bvbltparams
+ */
+union bvop {
+ unsigned short rop; /* when BVFLAG_ROP set */
+ enum bvblend blend; /* when BVFLAG_BLEND set */
+ struct bvfilter *filter; /* when BVFLAG_FILTER set */
+};
+
+
+/*
+ * bvbltparams - This structure is passed into bv_blt() to specify the
+ * parameters for a BLT.
+ */
+struct bvbltparams {
+ unsigned int structsize; /* (i) used to ID structure version */
+ char *errdesc; /* (o) 0-terminated ASCII string
+ with extended error info (not
+ for end users) */
+
+ unsigned long implementation; /* (i) override manager choice */
+
+ unsigned long flags; /* (i) see BVFLAG_* above */
+
+ union bvop op; /* (i) operation; determined by
+ BVFLAG_OP_MASK bits in flags */
+
+ void *colorkey; /* (i) pointer to color key pixel
+ matching non-SUBSAMPLE format
+ of the keyed surface when
+ BVFLAG_KEY_* is set */
+
+ union bvalpha globalalpha; /* (i) global alpha when BVFLAG_BLEND
+ set in flags and
+ BVBLENDDEF_GLOBAL_* is set in
+ blend; typed determined by
+ BVBLENDDEF_GLOBAL_* */
+
+ enum bvscalemode scalemode; /* (i/o) type of scaling */
+ enum bvdithermode dithermode; /* (i/o) type of dither */
+
+ struct bvbuffdesc *dstdesc; /* (i) dest after bv_map() */
+ struct bvsurfgeom *dstgeom; /* (i) dest surf fmt and geometry */
+ struct bvrect dstrect; /* (i) rect into which data written */
+
+ union bvinbuff src1; /* (i) src1 buffer */
+ struct bvsurfgeom *src1geom; /* (i) src1 surf fmt and geometry */
+ struct bvrect src1rect; /* (i) rect from which data is read */
+
+ union bvinbuff src2; /* (i) src2 buffer */
+ struct bvsurfgeom *src2geom; /* (i) src2 surf fmt and geometry */
+ struct bvrect src2rect; /* (i) rect from which data is read */
+
+ union bvinbuff mask; /* (i) mask buffer */
+ struct bvsurfgeom *maskgeom; /* (i) mask surf fmt and geometry */
+ struct bvrect maskrect; /* (i) rect from which data is read */
+
+ struct bvrect cliprect; /* (i) dest clipping rect when
+ BVFLAG_CLIP flag set */
+
+ unsigned long batchflags; /* (i) BVBATCH_* flags used to
+ indicate params changed between
+ batch BLTs */
+ struct bvbatch *batch; /* (i/o) handle for associated batch;
+ returned when
+ BVFLAG_BATCH_BEGIN set;
+ provided to subsequent BLTs
+ with BVFLAG_BATCH_CONTINUE */
+
+ void (*callbackfn)(struct bvcallbackerror *err,
+ unsigned long callbackdata); /* (i) callback
+ function when
+ BVFLAG_ASYNC is set -
+ err is 0 when no
+ error; handle contains
+ callbackdata below */
+ unsigned long callbackdata; /* (i) callback data */
+
+ struct bvrect src2auxdstrect;
+ struct bvrect maskauxdstrect;
+};
+
+#endif /* BLTSVILLE_H */
diff --git a/include/linux/bvblend.h b/include/linux/bvblend.h
--- /dev/null
+++ b/include/linux/bvblend.h
@@ -0,0 +1,507 @@
+/*
+ * bvblend.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * This file defines the types of shared blends available.
+ *
+ * To extend the list of blends, create a file containing additional
+ * enumerations to be added to enum bvblend below. Then #define
+ * BVBLEND_EXTERNAL_INCLUDE as the name of that file before including
+ * this file in your project.
+ */
+
+#ifndef BVBLEND_H
+#define BVBLEND_H
+
+/*
+ * bvblend - specifies the type of blending operation to perform; only valid
+ * when BVFLAG_BLEND is set in the bvbltparams.flags field.
+ */
+
+/*
+ * The blendmode value is divided into two sections.
+ *
+ * [31:28] The most significant 4 bits indicate the blend format.
+ *
+ * [27:0] The remainder of the bits is defined by the format chosen.
+ *
+ * 3322222222221111111111
+ * 10987654321098765432109876543210
+ * [ ][ ]
+ * | |
+ * format defined by format
+ */
+
+#define BVBLENDDEF_FORMAT_SHIFT 28
+#define BVBLENDDEF_FORMAT_MASK (0xF << BVBLENDDEF_FORMAT_SHIFT)
+
+#define BVBLENDDEF_FORMAT_CLASSIC (0x0 << BVBLENDDEF_FORMAT_SHIFT)
+#define BVBLENDDEF_FORMAT_ESSENTIAL (0x1 << BVBLENDDEF_FORMAT_SHIFT)
+
+/*
+ * The BVBLENDDEF_FORMAT_CLASSIC is meant to handle the classic Porter-Duff
+ * equations. It can also handle the DirectFB blending.
+ * BVBLENDDEF_FORMAT_CLASSIC is based on the following equations:
+ *
+ * Cd = K1 x C1 + K2 x C2
+ * Ad = K3 x A1 + K4 x A2
+ *
+ * where:
+ * Cd: destination color
+ * C1: source 1 color
+ * C2: source 2 color
+ * Ad: destination alpha
+ * A1: source 1 alpha
+ * A2: source 2 alpha
+ * K#: one of the constants defined using the bitfields below.
+ */
+
+/*
+ * The 28 bits for BVBLENDDEF_FORMAT_CLASSIC are divided into 5 sections.
+ *
+ * The most significant 4 bits are modifiers, used to include additional
+ * alpha values from global or remote sources.
+ *
+ * [27] The most significant bit indicates that a remote alpha is to be
+ * included in the blend. The format of this is defined by
+ * bvbltparams.maskgeom.format.
+ *
+ * [26] The next bit is reserved.
+ *
+ * [25:24] The next 2 bits are used to indicate that a global alpha is to be
+ * included, and what its format is:
+ * 00: no global included
+ * 01: global included; bvbltparams.globalalpha.size8 is used (0 -> 255)
+ * 10: this value is reserved
+ * 11: global included; bvbltparams.flogalalpha.fp is used (0.0 -> 1.0)
+ *
+ * The remaining bits are divided into 4 sections, one to define each of the
+ * constants:
+ *
+ * [23:18] - K1
+ * [17:12] - K2
+ * [11:6] - K3
+ * [5:0] - K4
+ *
+ * The format is the same for all 4 constant fields:
+ *
+ * [5:4] The first 2 bits of each field indicates the way in which the other
+ * 2 fields are interpreted:
+ * 00: only As: the other two fields contain only As; there should be only
+ * one valid A value between the two fields
+ * 01: minimum: the value of the constant is the minimum of the two fields
+ * 10: maximum: the value of the constant is the maximum of the two fields
+ * 11: only Cs: the other two fields contain only Cs; there should be only
+ * one valid C value between the two fields
+ *
+ * [3:2] The middle 2 bits of each field contain the inverse field:
+ * 00: 1-C1 ("don't care" for "only As")
+ * 01: 1-A1 ("don't care" for "only Cs")
+ * 10: 1-C2 ("don't care" for "only As")
+ * 11: 1-A2 ("don't care" for "only Cs")
+ *
+ * [1:0] The last 2 bits if each field contain the normal field:
+ * 00: C1 ("don't care" for "only As")
+ * 01: A1 ("don't care" for "only Cs")
+ * 10: C2 ("don't care" for "only As")
+ * 11: A2 ("don't care" for "only Cs")
+ *
+ * EXCEPTIONS:
+ *
+ * 00 00 00 - The value 00 00 00, which normally would indicate "only As"
+ * with two "don't care" fields, is interpreted as a 0.
+ *
+ * 11 11 11 - The value 11 11 11, which normally would indicate "only Cs"
+ * with two "don't care" fields, is interpreted as a 1.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Put together, these can define portions of the blend equations that can be
+ * put together in a variety of ways:
+ *
+ * 00 00 00: undefined -> zero
+ * 00 00 01: A1 (preferred)
+ * 00 00 10: undefined
+ * 00 00 11: A2 (preferred)
+ * 00 01 00: 1-A1 (preferred)
+ * 00 01 01: undefined
+ * 00 01 10: 1-A1 (use 00 01 00)
+ * 00 01 11: undefined
+ * 00 10 00: undefined
+ * 00 10 01: A1 (use 00 00 01)
+ * 00 10 10: undefined
+ * 00 10 11: A2 (use 00 00 11)
+ * 00 11 00: 1-A2 (preferred)
+ * 00 11 01: undefined
+ * 00 11 10: 1-A2 (use 00 11 00)
+ * 00 11 11: undefined
+ *
+ * 01 00 00: min(C1,1-C1)
+ * 01 00 01: min(A1,1-C1)
+ * 01 00 10: min(C2,1-C1)
+ * 01 00 11: min(A2,1-C1)
+ * 01 01 00: min(C1,1-A1)
+ * 01 01 01: min(A1,1-A1)
+ * 01 01 10: min(C2,1-A1)
+ * 01 01 11: min(A2,1-A1)
+ * 01 10 00: min(C1,1-C2)
+ * 01 10 01: min(A1,1-C2)
+ * 01 10 10: min(C2,1-C2)
+ * 01 10 11: min(A2,1-C2)
+ * 01 11 00: min(C1,1-A2)
+ * 01 11 01: min(A1,1-A2)
+ * 01 11 10: min(C2,1-A2)
+ * 01 11 11: min(A2,1-A2)
+ *
+ * 10 00 00: max(C1,1-C1)
+ * 10 00 01: max(A1,1-C1)
+ * 10 00 10: max(C2,1-C1)
+ * 10 00 11: max(A2,1-C1)
+ * 10 01 00: max(C1,1-A1)
+ * 10 01 01: max(A1,1-A1)
+ * 10 01 10: max(C2,1-A1)
+ * 10 01 11: max(A2,1-A1)
+ * 10 10 00: max(C1,1-C2)
+ * 10 10 01: max(A1,1-C2)
+ * 10 10 10: max(C2,1-C2)
+ * 10 10 11: max(A2,1-C2)
+ * 10 11 00: max(C1,1-A2)
+ * 10 11 01: max(A1,1-A2)
+ * 10 11 10: max(C2,1-A2)
+ * 10 11 11: max(A2,1-A2)
+ *
+ * 11 00 00: undefined
+ * 11 00 01: 1-C1 (use 11 00 11)
+ * 11 00 10: undefined
+ * 11 00 11: 1-C1 (preferred)
+ * 11 01 00: C1 (use 11 11 00)
+ * 11 01 01: undefined
+ * 11 01 10: C2 (use 11 11 10)
+ * 11 01 11: undefined
+ * 11 10 00: undefined
+ * 11 10 01: 1-C2 (use 11 10 11)
+ * 11 10 10: undefined
+ * 11 10 11: 1-C2 (preferred)
+ * 11 11 00: C1 (preferred)
+ * 11 11 01: undefined
+ * 11 11 10: C2 (preferred)
+ * 11 11 11: undefined -> one
+ *
+ * ==========================================================================
+ * DirectFB
+ * ==========================================================================
+ *
+ * Putting these together into the proper constants, the blending equations
+ * can be built for DirectFB as well:
+ *
+ * For DirectFB, the SetSrcBlendFunction() and SetDstBlendFunction() can
+ * specify 121 combinations of blends (11 x 11). It's impractical to
+ * specify these combinations individually. Instead, the settings indicated
+ * by each call should be bitwise OR'd to make the proper single value used in
+ * BLTsville.
+ *
+ * binary value <- SetSrcBlendFunction()
+ * [--K1--] [--K2--] [--K3--] [--K4--]
+ * 0000 0000 00 00 00 xx xx xx 00 00 00 xx xx xx <- DSBF_ZERO
+ * 0000 0000 11 11 11 xx xx xx 11 11 11 xx xx xx <- DSBF_ONE
+ * 0000 0000 11 11 00 xx xx xx 00 00 01 xx xx xx <- DSBF_SRCCOLOR
+ * 0000 0000 11 00 11 xx xx xx 00 01 00 xx xx xx <- DSBF_INVSRCCOLOR
+ * 0000 0000 00 00 01 xx xx xx 00 00 01 xx xx xx <- DSBF_SRCALPHA
+ * 0000 0000 00 01 00 xx xx xx 00 01 00 xx xx xx <- DSBF_INVSRCALPHA
+ * 0000 0000 11 11 10 xx xx xx 00 00 11 xx xx xx <- DSBF_DESTCOLOR
+ * 0000 0000 11 10 11 xx xx xx 00 11 00 xx xx xx <- DSBF_INVDESTCOLOR
+ * 0000 0000 00 00 11 xx xx xx 00 00 11 xx xx xx <- DSBF_DESTALPHA
+ * 0000 0000 00 11 00 xx xx xx 00 11 00 xx xx xx <- DSBF_INVDESTALPHA
+ * 0000 0000 01 11 01 xx xx xx 11 11 11 xx xx xx <- DSBF_SRCALPHASAT
+ *
+ * binary value <- SetDstBlendFunction()
+ * [--K1--] [--K2--] [--K3--] [--K4--]
+ * 0000 0000 xx xx xx 00 00 00 xx xx xx 00 00 00 <- DSBF_ZERO
+ * 0000 0000 xx xx xx 11 11 11 xx xx xx 11 11 11 <- DSBF_ONE
+ * 0000 0000 xx xx xx 11 11 00 xx xx xx 00 00 01 <- DSBF_SRCCOLOR
+ * etc.
+ *
+ * ==========================================================================
+ * Porter-Duff
+ * ==========================================================================
+ *
+ * For Porter-Duff, the equations can be more specifically defined. For
+ * convenience, these are enumerated below. These utilize the local alpha as
+ * indicated. To use global or remote alpha, these enumerations need to be
+ * modified. For example, to include the global alpha in the Porter-Duff
+ * SRC1OVER blend, the blend could be defined like this:
+ * params.op.blend = BVBLEND_SRC1OVER +
+ * BVBLENDDEF_GLOBAL_UCHAR;
+ *
+ * To include the remote alpha, the blend could be defined like this:
+ * params.op.blend = BVBLEND_SRC1OVER +
+ * BVBLENDDEF_REMOTE;
+ *
+ * And to include both:
+ * params.op.blend = BVBLEND_SRC1OVER +
+ * BVBLENDDEF_GLOBAL_UCHAR +
+ * BVBLENDDEF_REMOTE;
+ *
+ * Note that if the source color formats include local alphas, the local
+ * alphas, global alpha, and remote alpha will be used together.
+ *
+ * Note also that the equations assume the surfaces are premultiplied. So
+ * if the surface formats indicate that they are not premultiplied, the
+ * alpha multiplication of each color is done prior to using the surface
+ * values in the equations.
+ *
+ * For example, BVBLEND_SRC1OVER specifies the equations:
+ * Cd = 1 x C1 + (1 - A1) x C2
+ * Ad = 1 x A1 + (1 - A1) x A2
+ *
+ * If the format of surface 1 is non-premultiplied, the equations
+ * are modified to include the multiplication explicitly:
+ * Cd = 1 x A1 x C1 + (1 - A1) x C2
+ * Ad = 1 x A1 + (1 - A1) x A2
+ *
+ * Likewise, if the format of surface 2 is non-premultiplied, the
+ * equations are modified for this:
+ * Cd = 1 x C1 + (1 - A1) x A2 x C2
+ * Ad = 1 x A1 + (1 - A1) x A2
+ *
+ * When including global or remote alphas, these values are used to modify
+ * the source 1 value values before being used in the blend equation:
+ * C1 = Ag x C1
+ * A1 = Ag x A1
+ * -or-
+ * C1 = Ar x C1
+ * A1 = Ar x A1
+ * -or-
+ * C1 = Ag x Ar x C1
+ * A1 = Ag x Ar x A1
+ *
+ */
+
+#define BVBLENDDEF_MODE_SHIFT 4
+#define BVBLENDDEF_INV_SHIFT 2
+#define BVBLENDDEF_NORM_SHIFT 0
+
+#define BVBLENDDEF_ONLY_A (0 << BVBLENDDEF_MODE_SHIFT)
+#define BVBLENDDEF_MIN (1 << BVBLENDDEF_MODE_SHIFT)
+#define BVBLENDDEF_MAX (2 << BVBLENDDEF_MODE_SHIFT)
+#define BVBLENDDEF_ONLY_C (3 << BVBLENDDEF_MODE_SHIFT)
+#define BVBLENDDEF_MODE_MASK (3 << BVBLENDDEF_MODE_SHIFT)
+
+#define BVBLENDDEF_NORM_C1 (0 << BVBLENDDEF_NORM_SHIFT)
+#define BVBLENDDEF_NORM_A1 (1 << BVBLENDDEF_NORM_SHIFT)
+#define BVBLENDDEF_NORM_C2 (2 << BVBLENDDEF_NORM_SHIFT)
+#define BVBLENDDEF_NORM_A2 (3 << BVBLENDDEF_NORM_SHIFT)
+#define BVBLENDDEF_NORM_MASK (3 << BVBLENDDEF_NORM_SHIFT)
+
+#define BVBLENDDEF_INV_C1 (0 << BVBLENDDEF_INV_SHIFT)
+#define BVBLENDDEF_INV_A1 (1 << BVBLENDDEF_INV_SHIFT)
+#define BVBLENDDEF_INV_C2 (2 << BVBLENDDEF_INV_SHIFT)
+#define BVBLENDDEF_INV_A2 (3 << BVBLENDDEF_INV_SHIFT)
+#define BVBLENDDEF_INV_MASK (3 << BVBLENDDEF_INV_SHIFT)
+
+#define BVBLENDDEF_ONLY_A_NORM_xx BVBLENDDEF_NORM_C1
+#define BVBLENDDEF_ONLY_A_INV_xx BVBLENDDEF_INV_C1
+#define BVBLENDDEF_ONLY_C_NORM_xx BVBLENDDEF_NORM_A2
+#define BVBLENDDEF_ONLY_C_INV_xx BVBLENDDEF_INV_A2
+
+#define BVBLENDDEF_ZERO \
+ (BVBLENDDEF_ONLY_A | \
+ BVBLENDDEF_ONLY_A_NORM_xx | \
+ BVBLENDDEF_ONLY_A_INV_xx)
+#define BVBLENDDEF_C1 \
+ (BVBLENDDEF_ONLY_C | \
+ BVBLENDDEF_NORM_C1 | \
+ BVBLENDDEF_ONLY_C_INV_xx)
+#define BVBLENDDEF_A1 \
+ (BVBLENDDEF_ONLY_A | \
+ BVBLENDDEF_NORM_A1 | \
+ BVBLENDDEF_ONLY_A_INV_xx)
+#define BVBLENDDEF_C2 \
+ (BVBLENDDEF_ONLY_C | \
+ BVBLENDDEF_NORM_C2 | \
+ BVBLENDDEF_ONLY_C_INV_xx)
+#define BVBLENDDEF_A2 \
+ (BVBLENDDEF_ONLY_A | \
+ BVBLENDDEF_NORM_A2 | \
+ BVBLENDDEF_ONLY_A_INV_xx)
+#define BVBLENDDEF_ONE_MINUS_C1 \
+ (BVBLENDDEF_ONLY_C | \
+ BVBLENDDEF_ONLY_C_NORM_xx | \
+ BVBLENDDEF_INV_C1)
+#define BVBLENDDEF_ONE_MINUS_A1 \
+ (BVBLENDDEF_ONLY_A | \
+ BVBLENDDEF_ONLY_A_NORM_xx | \
+ BVBLENDDEF_INV_A1)
+#define BVBLENDDEF_ONE_MINUS_C2 \
+ (BVBLENDDEF_ONLY_C | \
+ BVBLENDDEF_ONLY_C_NORM_xx | \
+ BVBLENDDEF_INV_C2)
+#define BVBLENDDEF_ONE_MINUS_A2 \
+ (BVBLENDDEF_ONLY_A | \
+ BVBLENDDEF_ONLY_A_NORM_xx | \
+ BVBLENDDEF_INV_A2)
+#define BVBLENDDEF_ONE \
+ (BVBLENDDEF_ONLY_C | \
+ BVBLENDDEF_ONLY_C_NORM_xx | \
+ BVBLENDDEF_ONLY_C_INV_xx)
+
+#define BVBLENDDEF_K_MASK \
+ (BVBLENDDEF_MODE_MASK | \
+ BVBLENDDEF_INV_MASK | \
+ BVBLENDDEF_NORM_MASK)
+
+#define BVBLENDDEF_K1_SHIFT 18
+#define BVBLENDDEF_K2_SHIFT 12
+#define BVBLENDDEF_K3_SHIFT 6
+#define BVBLENDDEF_K4_SHIFT 0
+
+#define BVBLENDDEF_K1_MASK \
+ (BVBLENDDEF_K_MASK << BVBLENDDEF_K1_SHIFT)
+#define BVBLENDDEF_K2_MASK \
+ (BVBLENDDEF_K_MASK << BVBLENDDEF_K2_SHIFT)
+#define BVBLENDDEF_K3_MASK \
+ (BVBLENDDEF_K_MASK << BVBLENDDEF_K3_SHIFT)
+#define BVBLENDDEF_K4_MASK \
+ (BVBLENDDEF_K_MASK << BVBLENDDEF_K4_SHIFT)
+
+#define BVBLENDDEF_CLASSIC_EQUATION_MASK 0x00FFFFFF
+
+/*
+ * The following definitions are be used to modify the enumerations.
+ */
+#define BVBLENDDEF_REMOTE 0x08000000 /* mask surface provides alpha
+ for source 1 */
+
+/* Bit 26 reserved */
+
+/* These enable global alpha and define the type of globalalpha */
+#define BVBLENDDEF_GLOBAL_SHIFT 24
+#define BVBLENDDEF_GLOBAL_MASK (3 << BVBLENDDEF_GLOBAL_SHIFT)
+
+#define BVBLENDDEF_GLOBAL_NONE (0 << BVBLENDDEF_GLOBAL_SHIFT)
+#define BVBLENDDEF_GLOBAL_UCHAR (1 << BVBLENDDEF_GLOBAL_SHIFT)
+/* 2 reserved */
+#define BVBLENDDEF_GLOBAL_FLOAT (3 << BVBLENDDEF_GLOBAL_SHIFT)
+
+union bvalpha {
+ unsigned char size8; /* btwn 0 (0.0) and 255 (1.0) */
+ float fp; /* btwn 0.0 and 1.0 */
+};
+
+
+enum bvblend {
+ /* Porter-Duff blending equations */
+ BVBLEND_CLEAR = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_SRC1 = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_SRC2 = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_SRC1OVER = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_SRC2OVER = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_SRC1IN = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_A2 << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_A2 << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_SRC2IN = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_A1 << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_A1 << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_SRC1OUT = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_SRC2OUT = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_ZERO << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_SRC1ATOP = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_A2 << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_A2 << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_SRC2ATOP = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_A1 << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_A1 << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_XOR = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A2 << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_ONE_MINUS_A1 << BVBLENDDEF_K4_SHIFT),
+ BVBLEND_PLUS = BVBLENDDEF_FORMAT_CLASSIC |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K1_SHIFT) |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K2_SHIFT) |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K3_SHIFT) |
+ (BVBLENDDEF_ONE << BVBLENDDEF_K4_SHIFT),
+
+/*
+ * For FORMAT_ESSENTIAL, the variety of well-known blending functions from
+ * popular image manipulation programs are specified.
+ */
+
+ BVBLEND_NORMAL = BVBLENDDEF_FORMAT_ESSENTIAL + 0,
+ BVBLEND_LIGHTEN = BVBLENDDEF_FORMAT_ESSENTIAL + 1,
+ BVBLEND_DARKEN = BVBLENDDEF_FORMAT_ESSENTIAL + 2,
+ BVBLEND_MULTIPLY = BVBLENDDEF_FORMAT_ESSENTIAL + 3,
+ BVBLEND_AVERAGE = BVBLENDDEF_FORMAT_ESSENTIAL + 4,
+ BVBLEND_ADD = BVBLENDDEF_FORMAT_ESSENTIAL + 5,
+ BVBLEND_LINEAR_DODGE = BVBLEND_ADD,
+ BVBLEND_SUBTRACT = BVBLENDDEF_FORMAT_ESSENTIAL + 6,
+ BVBLEND_LINEAR_BURN = BVBLEND_SUBTRACT,
+ BVBLEND_DIFFERENCE = BVBLENDDEF_FORMAT_ESSENTIAL + 7,
+ BVBLEND_NEGATE = BVBLENDDEF_FORMAT_ESSENTIAL + 8,
+ BVBLEND_SCREEN = BVBLENDDEF_FORMAT_ESSENTIAL + 9,
+ BVBLEND_EXCLUSION = BVBLENDDEF_FORMAT_ESSENTIAL + 10,
+ BVBLEND_OVERLAY = BVBLENDDEF_FORMAT_ESSENTIAL + 11,
+ BVBLEND_SOFT_LIGHT = BVBLENDDEF_FORMAT_ESSENTIAL + 12,
+ BVBLEND_HARD_LIGHT = BVBLENDDEF_FORMAT_ESSENTIAL + 13,
+ BVBLEND_COLOR_DODGE = BVBLENDDEF_FORMAT_ESSENTIAL + 14,
+ BVBLEND_COLOR_BURN = BVBLENDDEF_FORMAT_ESSENTIAL + 15,
+ BVBLEND_LINEAR_LIGHT = BVBLENDDEF_FORMAT_ESSENTIAL + 16,
+ BVBLEND_VIVID_LIGHT = BVBLENDDEF_FORMAT_ESSENTIAL + 17,
+ BVBLEND_PIN_LIGHT = BVBLENDDEF_FORMAT_ESSENTIAL + 18,
+ BVBLEND_HARD_MIX = BVBLENDDEF_FORMAT_ESSENTIAL + 19,
+ BVBLEND_REFLECT = BVBLENDDEF_FORMAT_ESSENTIAL + 20,
+ BVBLEND_GLOW = BVBLENDDEF_FORMAT_ESSENTIAL + 21,
+ BVBLEND_PHOENIX = BVBLENDDEF_FORMAT_ESSENTIAL + 22,
+
+#ifdef BVBLEND_EXTERNAL_INCLUDE
+#define BVBLEND_EXTERNAL_INCLUDE
+#endif
+};
+
+#endif /* BVBLEND_H */
diff --git a/include/linux/bvbuffdesc.h b/include/linux/bvbuffdesc.h
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * bvbuffdesc.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef BVBUFFDESC_H
+#define BVBUFFDESC_H
+
+/*
+ * bvbuffmap - This is a private structure used by BLTsville
+ * implementations to manage resources associated with a buffer. A pointer
+ * to this is returned from bv_map() and used in subsequent bv_blt() and
+ * bv_unmap() calls.
+ */
+struct bvbuffmap;
+
+#define BVATDEF_VENDOR_SHIFT 24
+#define BVATDEF_VENDOR_MASK (0xFF << BVATDEF_VENDOR_SHIFT)
+
+/* Common aux type */
+#define BVATDEF_VENDOR_ALL (0x00 << BVATDEF_VENDOR_SHIFT)
+
+/* Texas Instruments, Inc. */
+#define BVATDEF_VENDOR_TI (0x01 << BVATDEF_VENDOR_SHIFT)
+
+enum bvauxtype {
+ BVAT_NONE = 0, /* auxptr not used */
+ BVAT_PHYSDESC = /* handle points to bvphysdesc struct */
+ BVATDEF_VENDOR_ALL + 1,
+
+#ifdef BVAT_EXTERNAL_INCLUDE
+#include BVAT_EXTERNAL_INCLUDE
+#endif
+};
+
+
+struct bvphysdesc {
+ unsigned int structsize; /* used to identify struct version */
+ unsigned long pagesize; /* page size in bytes */
+ unsigned long *pagearray; /* array of physical pages */
+ unsigned int pagecount; /* number of pages in the pagearray */
+ unsigned long pageoffset; /* page offset in bytes */
+};
+
+/*
+ * bvbuffdesc - This structure is used to specify the buffer parameters
+ * in a call to bv_map().
+ */
+struct bvbuffdesc {
+ unsigned int structsize; /* used to identify struct version */
+ void *virtaddr; /* virtual ptr to start of buffer */
+ unsigned long length; /* length of the buffer in bytes */
+ struct bvbuffmap *map; /* resource(s) associated w/buffer */
+ enum bvauxtype auxtype; /* type of auxptr */
+ void *auxptr; /* additional buffer description data;
+ type depends on auxtype */
+};
+
+#endif /* BVBUFFDESC_H */
diff --git a/include/linux/bvcache.h b/include/linux/bvcache.h
--- /dev/null
+++ b/include/linux/bvcache.h
@@ -0,0 +1,44 @@
+/*
+ * bvcache.h
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef BVCACHE_H_
+#define BVCACHE_H_
+
+/* Forward declarations */
+struct bvbuffdesc;
+struct bvsurfgeom;
+struct bvrect;
+
+/*
+ * This defines which cache operation the user intends to use
+ * BVCACHE_CPU_TO_DEVICE = clean
+ * BVCACHE_CPU_FROM_DEVICE = invalidate
+ * BVCACHE_BIDIRECTIONAL = flush
+ */
+enum bvcacheop {
+ BVCACHE_BIDIRECTIONAL = 0,
+ BVCACHE_CPU_TO_DEVICE = 1,
+ BVCACHE_CPU_FROM_DEVICE = 2,
+ BVCACHE_RESERVED3 = 3,
+};
+
+struct bvcopparams {
+ unsigned int structsize; /* used to identify struct version */
+ struct bvbuffdesc *desc;
+ struct bvsurfgeom *geom;
+ struct bvrect *rect;
+ enum bvcacheop cacheop;
+};
+
+#endif /* BVCACHE_H_ */
diff --git a/include/linux/bventry.h b/include/linux/bventry.h
--- /dev/null
+++ b/include/linux/bventry.h
@@ -0,0 +1,38 @@
+/*
+ * bventry.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef BVENTRY_H
+#define BVENTRY_H
+
+/* Forward declarations */
+struct bvbuffdesc;
+struct bvbltparams;
+struct bvcopparams;
+/*
+ * BLTsville interface definition.
+ */
+typedef enum bverror (*BVFN_MAP) (struct bvbuffdesc *buffdesc);
+typedef enum bverror (*BVFN_UNMAP) (struct bvbuffdesc *buffdesc);
+typedef enum bverror (*BVFN_BLT) (struct bvbltparams *bltparams);
+typedef enum bverror (*BVFN_CACHE)(struct bvcopparams *copparams);
+
+struct bventry {
+ unsigned int structsize; /* used to identify struct version */
+ BVFN_MAP bv_map;
+ BVFN_UNMAP bv_unmap;
+ BVFN_BLT bv_blt;
+ BVFN_CACHE bv_cache;
+};
+
+#endif /* BVENTRY_H */
diff --git a/include/linux/bverror.h b/include/linux/bverror.h
--- /dev/null
+++ b/include/linux/bverror.h
@@ -0,0 +1,306 @@
+/*
+ * bverror.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef BVERROR_H
+#define BVERROR_H
+
+/*
+ * bverror - These are error codes returned by BLTsville functions.
+ */
+#define BVERRDEF_VENDOR_SHIFT 24
+#define BVERRDEF_VENDOR_MASK (0xFF << BVERRDEF_VENDOR_SHIFT)
+
+#define BVERRDEF_VENDOR_ALL (0x00 << BVERRDEF_VENDOR_SHIFT)
+#define BVERRDEF_VENDOR_TI (0x01 << BVERRDEF_VENDOR_SHIFT)
+/* 0xF0-0xFF reserved */
+
+enum bverror {
+ BVERR_NONE = 0, /* no error */
+
+ BVERR_UNK = /* unknown error */
+ BVERRDEF_VENDOR_ALL + 1,
+ BVERR_OOM = /* memory allocation failure */
+ BVERRDEF_VENDOR_ALL + 2,
+ BVERR_RSRC = /* required resource unavailable */
+ BVERRDEF_VENDOR_ALL + 3,
+
+ BVERR_VIRTADDR = /* virtaddr is bad */
+ BVERRDEF_VENDOR_ALL + 1000,
+ BVERR_VIRTPTR =
+ BVERR_VIRTADDR, /* for backwards compatibility*/
+
+ BVERR_BUFFERDESC = /* invalid bvbufferdesc */
+ BVERRDEF_VENDOR_ALL + 10000,
+ BVERR_BUFFERDESC_VERS = /* bvbufferdesc.structsize too small */
+ BVERRDEF_VENDOR_ALL + 11000,
+ BVERR_BUFFERDESC_VIRTADDR = /* bad bvbufferdesc.virtaddr */
+ BVERRDEF_VENDOR_ALL + 12000,
+ BVERR_BUFFERDESC_LEN = /* bvbufferdesc.length not supported */
+ BVERRDEF_VENDOR_ALL + 13000,
+ BVERR_BUFFERDESC_ALIGNMENT = /* unsupported buffer base address */
+ BVERRDEF_VENDOR_ALL + 14000,
+
+ BVERR_BLTPARAMS_VERS = /* bvbltparams.structsize too small */
+ BVERRDEF_VENDOR_ALL + 20000,
+ BVERR_IMPLEMENTATION = /* bvbltparams.implementation unsupported */
+ BVERRDEF_VENDOR_ALL + 21000,
+ BVERR_FLAGS = /* bvbltparams.flags unsupported */
+ BVERRDEF_VENDOR_ALL + 22000,
+ BVERR_OP = /* unsupported operation */
+ BVERRDEF_VENDOR_ALL + 22100,
+ BVERR_KEY = /* type of color key not supported */
+ BVERRDEF_VENDOR_ALL + 22200,
+ BVERR_SRC1_TILE = /* src1 tiling not supported */
+ BVERRDEF_VENDOR_ALL + 22300,
+ BVERR_SRC2_TILE = /* src2 tiling not supported */
+ BVERRDEF_VENDOR_ALL + 22310,
+ BVERR_MASK_TILE = /* mask tiling not supported */
+ BVERRDEF_VENDOR_ALL + 22320,
+ BVERR_FLIP = /* flipping not supported */
+ BVERRDEF_VENDOR_ALL + 22400,
+ BVERR_ROP = /* ROP code not supported */
+ BVERRDEF_VENDOR_ALL + 23000,
+ BVERR_BLEND = /* blend not supported */
+ BVERRDEF_VENDOR_ALL + 23100,
+ BVERR_GLOBAL_ALPHA = /* type of global alpha not supported */
+ BVERRDEF_VENDOR_ALL + 23110,
+ BVERR_FILTER = /* filter type not supported */
+ BVERRDEF_VENDOR_ALL + 23200,
+ BVERR_FILTER_PARAMS_VERS = /* filter parameter structsize too small */
+ BVERRDEF_VENDOR_ALL + 23210,
+ BVERR_FILTER_PARAMS = /* filter parameters not supported */
+ BVERRDEF_VENDOR_ALL + 23220,
+ BVERR_SCALE_MODE = /* bvbltparams.scalemode not supported */
+ BVERRDEF_VENDOR_ALL + 24000,
+ BVERR_DITHER_MODE = /* bvbltparams.dithermode not supported */
+ BVERRDEF_VENDOR_ALL + 25000,
+
+ BVERR_DSTDESC = /* invalid bvbltparams.dstdesc */
+ BVERRDEF_VENDOR_ALL + 26000,
+ BVERR_DSTDESC_VERS = /* bvbufferdesc.structsize too small */
+ BVERRDEF_VENDOR_ALL + 26100,
+ BVERR_DSTDESC_VIRTADDR = /* bad bvbufferdesc.virtaddr */
+ BVERRDEF_VENDOR_ALL + 26200,
+ BVERR_DSTDESC_LEN = /* bvbufferdesc.length not supported */
+ BVERRDEF_VENDOR_ALL + 26300,
+ BVERR_DST_ALIGNMENT = /* unsupported buffer base address */
+ BVERRDEF_VENDOR_ALL + 26400,
+
+ BVERR_DSTGEOM = /* invalid bvbltparams.dstgeom */
+ BVERRDEF_VENDOR_ALL + 27000,
+ BVERR_DSTGEOM_VERS = /* dstgeom.structsize too small */
+ BVERRDEF_VENDOR_ALL + 27100,
+ BVERR_DSTGEOM_FORMAT = /* bltparams.dstgeom.format not supported */
+ BVERRDEF_VENDOR_ALL + 27200,
+ BVERR_DSTGEOM_STRIDE = /* bltparams.dstgeom.stride not supported */
+ BVERRDEF_VENDOR_ALL + 27300,
+ BVERR_DSTGEOM_PALETTE = /* dstgeom.paletteformat not supported */
+ BVERRDEF_VENDOR_ALL + 27400,
+
+
+ BVERR_DSTRECT = /* bvbltparams.dstrect not supported */
+ BVERRDEF_VENDOR_ALL + 28000,
+
+ BVERR_SRC1DESC = /* invalid bvbltparams.src1.desc */
+ BVERRDEF_VENDOR_ALL + 29000,
+ BVERR_SRC1DESC_VERS = /* bvbufferdesc.structsize too small */
+ BVERRDEF_VENDOR_ALL + 29100,
+ BVERR_SRC1DESC_VIRTADDR = /* bad bvbufferdesc.virtaddr */
+ BVERRDEF_VENDOR_ALL + 29200,
+ BVERR_SRC1DESC_LEN = /* bvbufferdesc.length not supported */
+ BVERRDEF_VENDOR_ALL + 29300,
+ BVERR_SRC1DESC_ALIGNMENT = /* unsupported buffer base address */
+ BVERRDEF_VENDOR_ALL + 29400,
+
+ BVERR_SRC1GEOM = /* invalid bvbltparams.src1geom */
+ BVERRDEF_VENDOR_ALL + 30000,
+ BVERR_SRC1GEOM_VERS = /* src1geom.structsize too small */
+ BVERRDEF_VENDOR_ALL + 30100,
+ BVERR_SRC1GEOM_FORMAT = /* bltparams.src1geom.format not supported */
+ BVERRDEF_VENDOR_ALL + 30200,
+ BVERR_SRC1GEOM_STRIDE = /* bltparams.src1geom.stride not supported */
+ BVERRDEF_VENDOR_ALL + 30300,
+ BVERR_SRC1GEOM_PALETTE = /* src1geom.paletteformat not supported */
+ BVERRDEF_VENDOR_ALL + 30400,
+
+ BVERR_SRC1RECT = /* bvbltparams.src1rect not supported */
+ BVERRDEF_VENDOR_ALL + 31000,
+
+ BVERR_SRC1_HORZSCALE = /* horz scale for src1->dst not supported */
+ BVERRDEF_VENDOR_ALL + 31100,
+ BVERR_SRC1_VERTSCALE = /* vert scale for src1->dst not supported */
+ BVERRDEF_VENDOR_ALL + 31200,
+ BVERR_SRC1_ROT = /* src1->dst rotation angle not supported */
+ BVERRDEF_VENDOR_ALL + 31300,
+
+ BVERR_SRC1_TILEPARAMS = /* invalid src1.tileparams */
+ BVERR_SRC1DESC,
+ BVERR_SRC1_TILE_VERS = /* src1.tileparams.structsize too small */
+ BVERRDEF_VENDOR_ALL + 32000,
+ BVERR_SRC1_TILEPARAMS_VERS =
+ BVERR_SRC1_TILE_VERS,
+ BVERR_SRC1_TILE_FLAGS = /* tileparams.flags not supported */
+ BVERRDEF_VENDOR_ALL + 32100,
+ BVERR_SRC1_TILEPARAMS_FLAGS =
+ BVERR_SRC1_TILE_FLAGS,
+ BVERR_SRC1_TILE_VIRTADDR =
+ BVERR_SRC1DESC_VIRTADDR,
+ BVERR_SRC1_TILEPARAMS_VIRTADDR =
+ BVERR_SRC1_TILE_VIRTADDR,
+ BVERR_SRC1_TILE_ORIGIN = /* tileparams.left or .top not supported */
+ BVERRDEF_VENDOR_ALL + 32200,
+ BVERR_SRC1_TILEPARAMS_ORIGIN =
+ BVERR_SRC1_TILE_ORIGIN,
+ BVERR_SRC1_TILE_SIZE = /* tileparams.width or .height not supported */
+ BVERRDEF_VENDOR_ALL + 32300,
+ BVERR_SRC1_TILEPARAMS_SIZE =
+ BVERR_SRC1_TILE_SIZE,
+
+ BVERR_SRC2DESC = /* invalid bvbltparams.src2.desc */
+ BVERRDEF_VENDOR_ALL + 33000,
+ BVERR_SRC2DESC_VERS = /* bvbufferdesc.structsize too small */
+ BVERRDEF_VENDOR_ALL + 33100,
+ BVERR_SRC2DESC_VIRTADDR = /* bad bvbufferdesc.virtaddr */
+ BVERRDEF_VENDOR_ALL + 33200,
+ BVERR_SRC2DESC_LEN = /* bvbufferdesc.length not supported */
+ BVERRDEF_VENDOR_ALL + 33300,
+ BVERR_SRC2DESC_ALIGNMENT = /* unsupported buffer base address */
+ BVERRDEF_VENDOR_ALL + 33400,
+
+ BVERR_SRC2GEOM = /* invalid bvbltparams.src2geom */
+ BVERRDEF_VENDOR_ALL + 34000,
+ BVERR_SRC2GEOM_VERS = /* src2geom.structsize too small */
+ BVERRDEF_VENDOR_ALL + 34100,
+ BVERR_SRC2GEOM_FORMAT = /* bltparams.src2geom.format not supported */
+ BVERRDEF_VENDOR_ALL + 34200,
+ BVERR_SRC2GEOM_STRIDE = /* bltparams.src2geom.stride not supported */
+ BVERRDEF_VENDOR_ALL + 34300,
+ BVERR_SRC2GEOM_PALETTE = /* src2geom.paletteformat not supported */
+ BVERRDEF_VENDOR_ALL + 34400,
+
+ BVERR_SRC2RECT = /* bvbltparams.src2rect not supported */
+ BVERRDEF_VENDOR_ALL + 35000,
+
+ BVERR_SRC2_HORZSCALE = /* horz scale for src2->dst not supported */
+ BVERRDEF_VENDOR_ALL + 35100,
+ BVERR_SRC2_VERTSCALE = /* vert scale for src2->dst not supported */
+ BVERRDEF_VENDOR_ALL + 35200,
+ BVERR_SRC2_ROT = /* src2->dst rotation angle not supported */
+ BVERRDEF_VENDOR_ALL + 35300,
+
+ BVERR_SRC2_TILEPARAMS = /* invalid src2.tileparams */
+ BVERR_SRC2DESC,
+ BVERR_SRC2_TILE_VERS = /* src2.tileparams.structsize too small */
+ BVERRDEF_VENDOR_ALL + 36000,
+ BVERR_SRC2_TILEPARAMS_VERS =
+ BVERR_SRC2_TILE_VERS,
+ BVERR_SRC2_TILE_FLAGS = /* tileparams.flags not supported */
+ BVERRDEF_VENDOR_ALL + 36100,
+ BVERR_SRC2_TILEPARAMS_FLAGS =
+ BVERR_SRC2_TILE_FLAGS,
+ BVERR_SRC2_TILE_VIRTADDR =
+ BVERR_SRC2DESC_VIRTADDR,
+ BVERR_SRC2_TILEPARAMS_VIRTADDR =
+ BVERR_SRC2_TILE_VIRTADDR,
+ BVERR_SRC2_TILE_ORIGIN = /* tileparams.left or .top not supported */
+ BVERRDEF_VENDOR_ALL + 36200,
+ BVERR_SRC2_TILEPARAMS_ORIGIN =
+ BVERR_SRC2_TILE_ORIGIN,
+ BVERR_SRC2_TILE_SIZE = /* tileparams.width or .height not supported */
+ BVERRDEF_VENDOR_ALL + 36300,
+ BVERR_SRC2_TILEPARAMS_SIZE =
+ BVERR_SRC2_TILE_SIZE,
+
+ BVERR_MASKDESC = /* invalid bvbltparams.mask.desc */
+ BVERRDEF_VENDOR_ALL + 37000,
+ BVERR_MASKDESC_VERS = /* bvbufferdesc.structsize too small */
+ BVERRDEF_VENDOR_ALL + 37100,
+ BVERR_MASKDESC_VIRTADDR = /* bad bvbufferdesc.virtaddr */
+ BVERRDEF_VENDOR_ALL + 37200,
+ BVERR_MASKDESC_LEN = /* bvbufferdesc.length not supported */
+ BVERRDEF_VENDOR_ALL + 37300,
+ BVERR_MASKDESC_ALIGNMENT = /* unsupported buffer base address */
+ BVERRDEF_VENDOR_ALL + 37400,
+
+ BVERR_MASKGEOM = /* invalid bvbltparams.maskgeom */
+ BVERRDEF_VENDOR_ALL + 38000,
+ BVERR_MASKGEOM_VERS = /* maskgeom.structsize too small */
+ BVERRDEF_VENDOR_ALL + 38100,
+ BVERR_MASKGEOM_FORMAT = /* bltparams.maskgeom.format not supported */
+ BVERRDEF_VENDOR_ALL + 38200,
+ BVERR_MASKGEOM_STRIDE = /* bltparams.maskgeom.stride not supported */
+ BVERRDEF_VENDOR_ALL + 38300,
+ BVERR_MASKGEOM_PALETTE = /* maskgeom.paletteformat not supported */
+ BVERRDEF_VENDOR_ALL + 38400,
+
+ BVERR_MASKRECT = /* bvbltparams.maskrect not supported */
+ BVERRDEF_VENDOR_ALL + 39000,
+
+ BVERR_MASK_HORZSCALE = /* horz scale for mask->dst not supported */
+ BVERRDEF_VENDOR_ALL + 39100,
+ BVERR_MASK_VERTSCALE = /* vert scale for mask->dst not supported */
+ BVERRDEF_VENDOR_ALL + 39200,
+ BVERR_MASK_ROT = /* mask->dst rotation angle not supported */
+ BVERRDEF_VENDOR_ALL + 39300,
+
+ BVERR_MASK_TILEPARAMS = /* invalid mask.tileparams */
+ BVERR_MASKDESC,
+ BVERR_MASK_TILE_VERS = /* mask.tileparams.structsize too small */
+ BVERRDEF_VENDOR_ALL + 40000,
+ BVERR_MASK_TILEPARAMS_VERS =
+ BVERR_MASK_TILE_VERS,
+ BVERR_MASK_TILE_FLAGS = /* tileparams.flags not supported */
+ BVERRDEF_VENDOR_ALL + 40100,
+ BVERR_MASK_TILEPARAMS_FLAGS =
+ BVERR_MASK_TILE_FLAGS,
+ BVERR_MASK_TILE_VIRTADDR =
+ BVERR_MASKDESC_VIRTADDR,
+ BVERR_MASK_TILEPARAMS_VIRTADDR =
+ BVERR_MASK_TILE_VIRTADDR,
+ BVERR_MASK_TILE_ORIGIN = /* tileparams.left or .top not supported */
+ BVERRDEF_VENDOR_ALL + 40200,
+ BVERR_MASK_TILEPARAMS_ORIGIN =
+ BVERR_MASK_TILE_ORIGIN,
+ BVERR_MASK_TILE_SIZE = /* tileparams.width or .height not supported */
+ BVERRDEF_VENDOR_ALL + 40300,
+ BVERR_MASK_TILEPARAMS_SIZE =
+ BVERR_MASK_TILE_SIZE,
+
+ BVERR_CLIP_RECT = /* bvbltparams.cliprect not supported */
+ BVERRDEF_VENDOR_ALL + 41000,
+
+ BVERR_BATCH_FLAGS = /* bvbltparams.batchflags not supported */
+ BVERRDEF_VENDOR_ALL + 42000,
+ BVERR_BATCH = /* bvbltparams.batch not valid */
+ BVERRDEF_VENDOR_ALL + 43000,
+
+ BVERR_OP_FAILED = /* async operation failed to start */
+ BVERRDEF_VENDOR_ALL + 50000,
+ BVERR_OP_INCOMPLETE = /* async operation failed mid-way */
+ BVERRDEF_VENDOR_ALL + 50001,
+ BVERR_MEMORY_ERROR = /* async operation triggered memory error */
+ BVERRDEF_VENDOR_ALL + 51000,
+
+ BVERR_FORMAT = /* unsupported format */
+ BVERRDEF_VENDOR_ALL + 52000,
+
+ BVERR_CACHEOP = /* unsupported cache operation */
+ BVERRDEF_VENDOR_ALL + 60000,
+
+#ifdef BVERR_EXTERNAL_INCLUDE
+#include BVERR_EXTERNAL_INCLUDE
+#endif
+};
+
+#endif /* BVERROR_H */
diff --git a/include/linux/bvfilter.h b/include/linux/bvfilter.h
--- /dev/null
+++ b/include/linux/bvfilter.h
@@ -0,0 +1,50 @@
+/*
+ * bvfilter.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * This file defines the types of shared filters available and the associated
+ * parameters.
+ *
+ * To extend the list of filters, create a file containing additional
+ * enumerations to be added to enum bvfilter below. Then #define
+ * BVFILTER_EXTERNAL_INCLUDE as the name of that file before including
+ * this file in your project. Parameters need to be in a different file.
+ */
+
+#ifndef BVFILTER_H
+#define BVFILTER_H
+
+/*
+ * bvfilter is an enumeration used to designate the type of filter being used.
+ */
+enum bvfiltertype {
+ BVFILTER_DUMMY
+ /* TBD */
+
+#ifdef BVFILTER_EXTERNAL_INCLUDE
+#include BVFILTER_EXTERNAL_INCLUDE
+#endif
+};
+
+/*
+ * bvfilterop contains the filter type and a pointer to the associated
+ * parameters when the BVFLAG_FILTER operation is specified in
+ * bvbltparams.flags.
+ */
+struct bvfilter {
+ enum bvfiltertype filter;
+ void *params;
+};
+
+#endif /* BVFILTER_H */
diff --git a/include/linux/bvinternal.h b/include/linux/bvinternal.h
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * bvinternal.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * This file contains definitions used by implementations of BLTsville
+ * 2-D libraries. It should not be used by clients.
+ */
+
+#ifndef BVINTERNAL_H
+#define BVINTENRAL_H
+
+/*
+ * bvbuffmap - The bvbuffmap structure is used to track resources
+ * associated with a buffer, such as a h/w MMU entry. The implementations
+ * add bvbuffmap objects when they allocate the resources. Then when a
+ * buffer is accessed, the implementations can regain access to the
+ * associated resources. The implementations allocate and populate this
+ * structure when a bv_map() call is made. It is used in subsequent
+ * bv_blt() and bv_unmap() calls. The latter frees the associated resource
+ * and the structure (if applicable). Note that a given resource might be
+ * used by more than one implementation.
+ */
+struct bvbuffmap {
+ unsigned int structsize; /* used to ID structure ver */
+
+ /* function to unmap this resource */
+ BVFN_UNMAP bv_unmap;
+
+ unsigned long handle; /* resource-specific info */
+
+ /* pointer to next resource mapping structure */
+ struct bvbuffmap *nextmap;
+};
+
+#endif /* BVINTERNAL_H */
diff --git a/include/linux/bvsurfgeom.h b/include/linux/bvsurfgeom.h
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * bvsurfgeom.h
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef BVSURFGEOM_H
+#define BVSURFGEOM_H
+
+/*
+ * bvsurfdesc - This structure specifies the way a buffer should be used in a
+ * 2-D context.
+ */
+
+struct bvsurfgeom {
+ unsigned int structsize; /* used to identify struct version */
+ enum ocdformat format; /* color format of surface */
+ unsigned int width; /* width of the surface in pixels */
+ unsigned int height; /* height of the surface in lines */
+ int orientation; /* angle of the surface in degrees
+ (multiple of 90 only) */
+ long virtstride; /* distance from one pixel to the
+ pixel immediately below it in
+ virtual space */
+ enum ocdformat paletteformat; /* format of palette */
+ void *palette; /* array of palette entries of
+ paletteformat; only valid when
+ format includes BVFMTDEF_LUT;
+ number of entries is 2^bpp. */
+};
+
+#endif /* BVSURFGEOM_H */
diff --git a/include/linux/cache-2dmanager.h b/include/linux/cache-2dmanager.h
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * cache-2dmanager.h
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef CACHE_2DMANAGER_H_
+#define CACHE_2DMANAGER_H_
+
+#include "slab.h"
+
+#ifdef CONFIG_ARCH_OMAP4
+#define L1CACHE_SIZE 32768
+#define L2CACHE_SIZE 1048576
+
+#define L1THRESHOLD L1CACHE_SIZE
+#define L2THRESHOLD L2CACHE_SIZE
+#else
+#error Cache configuration must be specified.
+#endif
+
+struct c2dmrgn {
+ char *start; /* addr of upper left of rect */
+ size_t span; /* bytes to be operated on per line */
+ size_t lines; /* lines to be operated on */
+ long stride; /* bytes per line */
+};
+
+/*
+ * c2dm_l1cache(count, rgns, dir)
+ *
+ * L1 Cache operations in 2D
+ *
+ * - count - number of regions
+ * - rgns - array of regions
+ * - dir - cache operation direction
+ *
+ */
+void c2dm_l1cache(int count, struct c2dmrgn rgns[], int dir);
+
+/*
+ * c2dm_l2cache(count, rgns, dir)
+ *
+ * L2 Cache operations in 2D
+ *
+ * - count - number of regions
+ * - rgns - array of regions
+ * - dir - cache operation direction
+ *
+ */
+void c2dm_l2cache(int count, struct c2dmrgn rgns[], int dir);
+
+
+#endif /* CACHE_2DMANAGER_H_ */
diff --git a/include/linux/fb.h b/include/linux/fb.h
index c7a95714b1fe68e7f9b67e990a384cac0f490044..4629edc9e534cec7819e12b319cc971739adb967 100644 (file)
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
#define FB_MISC_PRIM_COLOR 1
#define FB_MISC_1ST_DETAIL 2 /* First Detailed Timing is preferred */
+#define FB_MISC_HDMI 4 /* display supports HDMI signaling */
+
struct fb_chroma {
__u32 redx; /* in fraction of 1024 */
__u32 greenx;
};
#endif
+#define FB_FLAG_RATIO_4_3 64
+#define FB_FLAG_RATIO_16_9 128
+#define FB_FLAG_PIXEL_REPEAT 256
+
/*
* Frame buffer operations
*
/* drivers/video/modedb.c */
#define VESA_MODEDB_SIZE 34
+#define CEA_MODEDB_SIZE 65
+
extern void fb_var_to_videomode(struct fb_videomode *mode,
const struct fb_var_screeninfo *var);
extern void fb_videomode_to_var(struct fb_var_screeninfo *var,
extern const char *fb_mode_option;
extern const struct fb_videomode vesa_modes[];
-extern const struct fb_videomode cea_modes[64];
+extern const struct fb_videomode cea_modes[];
struct fb_modelist {
struct list_head list;
diff --git a/include/linux/gcbv-iface.h b/include/linux/gcbv-iface.h
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * gcbv-iface.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCBV_IFACE_H
+#define GCBV_IFACE_H
+
+#include "bltsville.h"
+
+void gcbv_init(struct bventry *entry);
+
+#endif
diff --git a/include/linux/gccore.h b/include/linux/gccore.h
--- /dev/null
+++ b/include/linux/gccore.h
@@ -0,0 +1,41 @@
+/*
+ * gccore.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCCORE_H
+#define GCCORE_H
+
+#include "sched.h"
+#include "gcioctl.h"
+
+
+/* Hw availability query */
+bool gc_is_hw_present(void);
+
+/* Capability query. */
+void gc_caps(struct gcicaps *gcicaps);
+
+/* Command buffer submission. */
+void gc_commit(struct gcicommit *gcicommit, bool fromuser);
+
+/* Client memory mapping. */
+void gc_map(struct gcimap *gcimap, bool fromuser);
+void gc_unmap(struct gcimap *gcimap, bool fromuser);
+
+/* Arm a callback. */
+void gc_callback(struct gcicallbackarm *gcicallbackarm, bool fromuser);
+
+/* Process cleanup. */
+void gc_release(void);
+
+#endif
diff --git a/include/linux/gcdbglog.h b/include/linux/gcdbglog.h
--- /dev/null
+++ b/include/linux/gcdbglog.h
@@ -0,0 +1,412 @@
+/*
+ * gcdbglog.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCDBGLOG_H
+#define GCDBGLOG_H
+
+#include "list.h"
+#include "bltsville.h"
+struct gcmmucontext;
+
+
+/*******************************************************************************
+ * Debug logging switches.
+ */
+
+/* Enables internal gccore logging backend. */
+#if !defined(GCDEBUG_ENABLE)
+#define GCDEBUG_ENABLE 1 /* enabled for development branch only */
+#endif
+
+/* Enables linux builtin logging backend. */
+#if !defined(GCDEBUG_LINUXLOGS)
+#define GCDEBUG_LINUXLOGS 0
+#endif
+
+#if GCDEBUG_ENABLE && GCDEBUG_LINUXLOGS
+#error GCDEBUG_ENABLE and GCDEBUG_LINUXLOGS cannot be enabled simultaneously.
+#endif
+
+
+/*******************************************************************************
+ * Dumping interface macro for release mode.
+ */
+
+#if !GCDEBUG_ENABLE && !GCDEBUG_LINUXLOGS
+#define GCDBG_INIT(...)
+#define GCDBG_EXIT(...)
+#define GCDBG_FILTERDEF(...)
+#define GCDBG_REGISTER(...)
+#define GCENTER(...)
+#define GCEXIT(...)
+#define GCENTERARG(...)
+#define GCEXITARG(...)
+#define GCDBG(...)
+#define GCERR(...)
+#define GCDUMPSTRING(...)
+#define GCDUMPBUFFER(...)
+#define GCDUMPARENA(...)
+#define GCDUMPARENAS(...)
+#define GCDUMPMMU(...)
+#endif
+
+#if !GCDEBUG_ENABLE
+#define GCDBG_REPORT_MISSING(file, line) \
+ printk(KERN_INFO "(%s:%d) gcx logging is not integrated.\n", \
+ file, line)
+
+#define GCDBG_SHOWENABLED(s) \
+ GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#define GCDBG_ENABLEDUMP() \
+ GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#define GCDBG_DISABLEDUMP() \
+ GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#define GCDBG_SETFILTER(filtername, zone) \
+ GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#define GCDBG_FLUSHDUMP(s) \
+ GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#define GCDBG_RESETDUMP() \
+ GCDBG_REPORT_MISSING(__FILE__, __LINE__)
+
+#endif
+
+
+/*******************************************************************************
+ * Dumping macros not specific to a particular logging backend.
+ */
+
+#if GCDEBUG_ENABLE || GCDEBUG_LINUXLOGS
+
+#define GC_MOD_PREFIX \
+ GC_DEV_NAME ": %s(%d) "
+
+#define GCDUMPARENA(zone, text, arena) \
+do { \
+ GCDBG(zone, text " @ 0x%08X:\n", (unsigned int) arena); \
+ GCDBG(zone, " number of pages = %u\n", \
+ (arena)->count); \
+ GCDBG(zone, " from (absolute/mtlb/stlb) = 0x%08X / %u / %u\n", \
+ (arena)->start.absolute, \
+ (arena)->start.loc.mtlb, \
+ (arena)->start.loc.stlb); \
+ GCDBG(zone, " to (absolute/mtlb/stlb) = 0x%08X / %u / %u\n", \
+ (arena)->end.absolute, \
+ (arena)->end.loc.mtlb, \
+ (arena)->end.loc.stlb); \
+} while (false)
+
+#define GCDUMPARENAS(zone, text, arenahead) \
+do { \
+ GCDBG(zone, "%s:\n", text); \
+ \
+ if (list_empty(arenahead)) { \
+ GCDBG(zone, " no arenas defined in the list.\n"); \
+ } else { \
+ struct list_head *entry; \
+ struct gcmmuarena *arena; \
+ \
+ list_for_each(entry, arenahead) { \
+ arena = list_entry(entry, struct gcmmuarena, link); \
+ GCDUMPARENA(zone, "arena", arena); \
+ } \
+ } \
+} while (false)
+
+#endif
+
+#define GC_FUNC_ENTER "++"
+#define GC_FUNC_EXIT "--"
+
+
+/*******************************************************************************
+ * Dumping macros for internal gccore logging backend.
+ */
+
+#if GCDEBUG_ENABLE
+
+#define GCDBGFILTER \
+ g_gcdbgfilter
+
+#define GCDBG_INIT() \
+ gcdbg_init()
+
+#define GCDBG_EXIT() \
+ gcdbg_exit()
+
+#define GCDBG_FILTERDEF(name, initzone, ...) \
+ static struct gcdbgfilter GCDBGFILTER = { \
+ .link = LIST_HEAD_INIT(GCDBGFILTER.link), \
+ .filtername = #name, \
+ .zone = initzone, \
+ .zonename = { __VA_ARGS__, NULL } \
+ }; \
+ \
+ struct gcdbgfilter *name ## _dbgfilter(void) \
+ { \
+ return &GCDBGFILTER; \
+ }
+
+#define GCDBG_REGISTER(name, initalzone) \
+do { \
+ struct gcdbgfilter *name ## _dbgfilter(void); \
+ name ## _dbgfilter()->zone = initalzone; \
+ gc_dbg_add_client(name ## _dbgfilter()); \
+} while (0)
+
+#define GCDBG_SHOWENABLED(s) \
+ gc_dump_show_enabled(s)
+
+#define GCDBG_ENABLEDUMP() \
+ gc_dump_enable()
+
+#define GCDBG_DISABLEDUMP() \
+ gc_dump_disable()
+
+#define GCDBG_SETFILTER(filtername, zone) \
+ gc_dump_filter_enable(filtername, zone)
+
+#define GCDBG_FLUSHDUMP(s) \
+ gc_dump_flush(s)
+
+#define GCDBG_RESETDUMP() \
+ gc_dump_reset()
+
+#define GCENTER(zone) \
+ gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_ENTER GC_MOD_PREFIX "\n", \
+ __func__, __LINE__)
+
+#define GCEXIT(zone) \
+ gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_EXIT GC_MOD_PREFIX "\n", \
+ __func__, __LINE__)
+
+#define GCENTERARG(zone, msg, ...) \
+ gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_ENTER GC_MOD_PREFIX msg, \
+ __func__, __LINE__, ##__VA_ARGS__)
+
+#define GCEXITARG(zone, msg, ...) \
+ gc_dump_string(&GCDBGFILTER, zone, GC_FUNC_EXIT GC_MOD_PREFIX msg, \
+ __func__, __LINE__, ##__VA_ARGS__)
+
+#define GCDBG(zone, msg, ...) \
+ gc_dump_string(&GCDBGFILTER, zone, GC_MOD_PREFIX msg, \
+ __func__, __LINE__, ##__VA_ARGS__)
+
+#define GCERR(msg, ...) \
+ gc_dump_string(NULL, 0, GC_MOD_PREFIX "[ERROR] " msg, \
+ __func__, __LINE__, ##__VA_ARGS__)
+
+#define GCDUMPSTRING(msg, ...) \
+ gc_dump_string(NULL, 0, msg, ##__VA_ARGS__)
+
+#define GCDUMPBUFFER(zone, ptr, gpuaddr, datasize) \
+ gc_dump_cmd_buffer(&GCDBGFILTER, zone, ptr, gpuaddr, datasize)
+
+#define GCDUMPMMU(zone, gcmmucontext) \
+ gc_dump_mmu(&GCDBGFILTER, zone, gcmmucontext)
+
+#endif
+
+
+/*******************************************************************************
+ * Dumping macros for linux builtin logging backend.
+ */
+
+#if GCDEBUG_LINUXLOGS
+
+#define GCDBG_INIT()
+#define GCDBG_EXIT()
+#define GCDBG_FILTERDEF(...)
+#define GCDBG_REGISTER(...)
+
+#define GCENTER(zone) \
+ GCDBG(zone, GC_FUNC_ENTER " %s(%d)\n", __func__, __LINE__)
+
+#define GCEXIT(zone) \
+ GCDBG(zone, GC_FUNC_EXIT " %s(%d)\n", __func__, __LINE__)
+
+#define GCENTERARG(zone, msg, ...) \
+ GCDBG(zone, GC_FUNC_ENTER " %s(%d) " msg "\n", \
+ __func__, __LINE__, ##__VA_ARGS__)
+
+#define GCEXITARG(zone, msg, ...) \
+ GCDBG(zone, GC_FUNC_EXIT " %s(%d) " msg "\n", \
+ __func__, __LINE__, ##__VA_ARGS__)
+
+#define GCDBG(zone, msg, ...) \
+ dev_dbg(gc_get_dev(), msg, ##__VA_ARGS__)
+
+#define GCERR(msg, ...) \
+ GCDBG(0, msg, ##__VA_ARGS__)
+
+#define GCDUMPSTRING(msg, ...) \
+ GCDBG(0, msg, ##__VA_ARGS__)
+
+#define GCDUMPBUFFER(...)
+
+#endif
+
+
+/*******************************************************************************
+ * Command buffer parser.
+ */
+
+struct gcsurfaceinfo {
+ unsigned int width;
+ unsigned int height;
+ unsigned int address;
+ unsigned int stride;
+ unsigned int swizzle;
+ unsigned int format;
+ unsigned int bpp;
+};
+
+struct gcrect {
+ int left;
+ int top;
+ int right;
+ int bottom;
+};
+
+struct gcsourceinfo {
+ struct gcsurfaceinfo surf;
+ struct gcrect rect;
+};
+
+struct gcdestinfo {
+ struct gcsurfaceinfo surf;
+ unsigned int rectcount;
+ struct gcrect rect[256];
+};
+
+struct gccommandinfo {
+ unsigned int command;
+ unsigned int srccount;
+ struct gcsourceinfo src[4];
+ struct gcdestinfo dst;
+};
+
+/* Parse the specified command buffer and fill in the structure. */
+int gc_parse_command_buffer(unsigned int *buffer, unsigned int size,
+ struct gccommandinfo *info);
+
+
+/*******************************************************************************
+ * Filter structure.
+ */
+
+struct gcdbgfilter {
+ struct list_head link;
+ char *filtername;
+ unsigned int zone;
+ const char *zonename[];
+};
+
+
+/*******************************************************************************
+ * Debug init/exit functions.
+ */
+
+void gcdbg_init(void);
+void gcdbg_exit(void);
+
+
+/*******************************************************************************
+ * Dumping functions.
+ */
+
+/* Print GPU status. */
+void gc_dump_status(struct gcdbgfilter *filter, unsigned int zone,
+ char *function, int line);
+
+/* String dumping. */
+void gc_dump_string(struct gcdbgfilter *filter, unsigned int zone,
+ const char *message, ...);
+void gc_dump_string_sized(struct gcdbgfilter *filter, unsigned int zone,
+ unsigned int argsize, const char *message, ...);
+
+/* Dump command buffer. */
+void gc_dump_cmd_buffer(struct gcdbgfilter *filter, unsigned int zone,
+ void *ptr, unsigned int gpuaddr, unsigned int datasize);
+
+/* Dump generic buffer. */
+void gc_dump_buffer(struct gcdbgfilter *filter, unsigned int zone,
+ void *ptr, unsigned int gpuaddr, unsigned int datasize);
+void gc_dump_phys_buffer(struct gcdbgfilter *filter, unsigned int zone,
+ struct gcmmucontext *gcmmucontext,
+ unsigned int gpuaddr, unsigned int datasize);
+
+/* Dump surface. */
+void gc_dump_surface(struct gcdbgfilter *filter, unsigned int zone,
+ void *ptr, unsigned int surfwidth,
+ unsigned int surfheight, unsigned int surfbpp,
+ unsigned int x1, unsigned int y1,
+ unsigned int x2, unsigned int y2,
+ unsigned int gpuaddr);
+void gc_dump_phys_surface(struct gcdbgfilter *filter, unsigned int zone,
+ struct gcmmucontext *gcmmucontext,
+ unsigned int surfwidth, unsigned int surfheight,
+ unsigned int surfbpp,
+ unsigned int x1, unsigned int y1,
+ unsigned int x2, unsigned int y2,
+ unsigned int gpuaddr);
+
+/* Dump MMU content. */
+void gc_dump_mmu(struct gcdbgfilter *filter, unsigned int zone,
+ struct gcmmucontext *gcmmucontext);
+
+
+/*******************************************************************************
+ * CPU blitters.
+ */
+
+/* Fill surface using its virtual GPU address. */
+void gc_fill_phys_surface(struct gcdbgfilter *filter, unsigned int zone,
+ struct gcmmucontext *gcmmucontext,
+ unsigned int surfwidth,
+ unsigned int surfheight,
+ unsigned int surfbpp,
+ unsigned int x1, unsigned int y1,
+ unsigned int x2, unsigned int y2,
+ unsigned int gpuaddr,
+ unsigned int fillcolor);
+
+
+/*******************************************************************************
+ * Bltsville debugging.
+ */
+
+char *gc_bvblend_name(enum bvblend blend);
+
+
+/*******************************************************************************
+ * Dumping control.
+ */
+
+struct seq_file;
+
+struct device *gc_get_dev(void);
+void gc_dump_show_enabled(struct seq_file *s);
+void gc_dump_enable(void);
+void gc_dump_disable(void);
+void gc_dump_filter_enable(const char *filtername, int zone);
+void gc_dump_flush(struct seq_file *s);
+void gc_dump_reset(void);
+void gc_dbg_add_client(struct gcdbgfilter *filter);
+
+#endif
diff --git a/include/linux/gcdebug.h b/include/linux/gcdebug.h
--- /dev/null
+++ b/include/linux/gcdebug.h
@@ -0,0 +1,28 @@
+/*
+ * gcdebug.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCDEBUG_H
+#define GCDEBUG_H
+
+#define GCGPUSTATUS() \
+ gc_debug_dump_status(__func__, __LINE__)
+
+void gc_debug_init(void);
+void gc_debug_shutdown(void);
+
+void gc_debug_poweroff_cache(void);
+void gc_debug_cache_gpu_status_from_irq(unsigned int acknowledge);
+void gc_debug_dump_status(const char *function, int line);
+
+#endif
diff --git a/include/linux/gcerror.h b/include/linux/gcerror.h
--- /dev/null
+++ b/include/linux/gcerror.h
@@ -0,0 +1,208 @@
+/*
+ * gcerror.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCERROR_H
+#define GCERROR_H
+
+#define GCERR_SETGRP(error, group) \
+( \
+ (enum gcerror) \
+ ((error & GCERR_GENERIC_MASK) | group) \
+)
+
+#define GCERR_GENERIC(error) \
+( \
+ (error & GCERR_GENERIC_MASK) << GCERR_GENERIC_SHIFT \
+)
+
+#define GCERR_GROUP(error) \
+( \
+ (error & GCERR_GROUP_MASK) << GCERR_GROUP_SHIFT \
+)
+
+enum gcerror {
+ /***********************************************************************
+ ** No error / success.
+ */
+ GCERR_NONE = 0,
+
+ /***********************************************************************
+ ** Error code zones.
+ */
+
+ /* Generic error code zone. These errors inform of the low level
+ reason of the faulure, but don't carry information about which
+ logical part of the code generated the error. */
+ GCERR_GENERIC_SIZE = 12,
+ GCERR_GENERIC_SHIFT = 0,
+ GCERR_GENERIC_MASK
+ = ((1 << GCERR_GENERIC_SIZE) - 1) << GCERR_GENERIC_SHIFT,
+
+ /* Group error code zone. These errors inform about the logical part
+ of the code where the error occurred. */
+ GCERR_GROUP_SIZE = (32 - GCERR_GENERIC_SIZE),
+ GCERR_GROUP_SHIFT = GCERR_GENERIC_SIZE,
+ GCERR_GROUP_MASK
+ = ((1 << GCERR_GROUP_SIZE) - 1) << GCERR_GROUP_SHIFT,
+
+ /***********************************************************************
+ ** Generic zone errors.
+ */
+
+ GCERR_OODM /* Out of dynamic memory. */
+ = GCERR_GENERIC(1),
+
+ GCERR_OOPM /* Out of paged memory. */
+ = GCERR_GENERIC(2),
+
+ GCERR_PMMAP /* Paged memory mapping. */
+ = GCERR_GENERIC(3),
+
+ GCERR_USER_READ /* Reading user input. */
+ = GCERR_GENERIC(4),
+
+ GCERR_USER_WRITE /* Writing user output. */
+ = GCERR_GENERIC(5),
+
+ GCERR_INTERRUPTED /* Interrupted by a signal. */
+ = GCERR_GENERIC(6),
+
+ GCERR_TIMEOUT /* Timeout. */
+ = GCERR_GENERIC(7),
+
+ GCERR_NOT_FOUND /* Data/entry not found. */
+ = GCERR_GENERIC(8),
+
+ GCERR_IOCTL /* IOCTL failed. */
+ = GCERR_GENERIC(9),
+
+ /***********************************************************************
+ ** Group zone errors.
+ */
+
+ /**** Context errors. */
+ GCERR_CTX_ALLOC /* Context allocation. */
+ = GCERR_GROUP(0x01000),
+
+ GCERR_CTX_CHANGE /* Lock/unlock error. */
+ = GCERR_GROUP(0x01010),
+
+ GCERR_CTX_NULL /* Context not set. */
+ = GCERR_GROUP(0x01020),
+
+ /**** Command queue errors. */
+ GCERR_CMD_ENTRY_PIPE /* Entry pipe is invalid. */
+ = GCERR_GROUP(0x02000),
+
+ GCERR_CMD_EXIT_PIPE /* Exit pipe is invalid. */
+ = GCERR_GROUP(0x02010),
+
+ GCERR_CMD_MAPPED /* Command buffer mapping error. */
+ = GCERR_GROUP(0x02020),
+
+ GCERR_CMD_CONSISTENCY /* Inconsistent mapping. */
+ = GCERR_GROUP(0x02030),
+
+ GCERR_CMD_ALLOC /* Buffer allocation. */
+ = GCERR_GROUP(0x02040),
+
+ GCERR_CMD_QUEUE_ALLOC /* Buffer queue allocation. */
+ = GCERR_GROUP(0x02050),
+
+ GCERR_CMD_EVENT_ALLOC /* Event allocation. */
+ = GCERR_GROUP(0x02060),
+
+ GCERR_CMD_INT_ALLOC /* Interrupt allocation. */
+ = GCERR_GROUP(0x02070),
+
+ GCERR_CMD_ISR /* ISR initialization. */
+ = GCERR_GROUP(0x02080),
+
+ GCERR_CMD_THREAD /* Thread initialization. */
+ = GCERR_GROUP(0x02090),
+
+ /**** MMU errors. */
+ GCERR_MMU_CTXT_BAD /* Invalid context. */
+ = GCERR_GROUP(0x03000),
+
+ GCERR_MMU_MTLB_ALLOC /* MTLB allocation. */
+ = GCERR_GROUP(0x03010),
+
+ GCERR_MMU_MTLB_SET /* MTLB setting. */
+ = GCERR_GROUP(0x03020),
+
+ GCERR_MMU_STLB_ALLOC /* STLB allocation. */
+ = GCERR_GROUP(0x03030),
+
+ GCERR_MMU_STLBIDX_ALLOC /* STLB index allocation. */
+ = GCERR_GROUP(0x03040),
+
+ GCERR_MMU_ARENA_ALLOC /* Vacant arena allocation. */
+ = GCERR_GROUP(0x03050),
+
+ GCERR_MMU_OOM /* No available arenas to allocate. */
+ = GCERR_GROUP(0x03060),
+
+ GCERR_MMU_SAFE_ALLOC /* Safe zone allocation. */
+ = GCERR_GROUP(0x03070),
+
+ GCERR_MMU_INIT /* MMU initialization. */
+ = GCERR_GROUP(0x03080),
+
+ GCERR_MMU_ARG /* Invalid argument. */
+ = GCERR_GROUP(0x03090),
+
+ GCERR_MMU_CLIENT /* Client initialization. */
+ = GCERR_GROUP(0x030A0),
+
+ GCERR_MMU_BUFFER_BAD /* Invalid buffer to map. */
+ = GCERR_GROUP(0x030B0),
+
+ GCERR_MMU_PAGE_BAD /* Bad page within the buffer. */
+ = GCERR_GROUP(0x030C0),
+
+ GCERR_MMU_DESC_ALLOC /* Bad page within the buffer. */
+ = GCERR_GROUP(0x030D0),
+
+ GCERR_MMU_PHYS_ALLOC /* Bad page within the buffer. */
+ = GCERR_GROUP(0x030E0),
+
+ GCERR_MMU_OFFSET /* Bad buffer offset. */
+ = GCERR_GROUP(0x030F0),
+
+ /**** Power management. */
+ GCERR_POWER_MODE /* Invlalid power mode requested. */
+ = GCERR_GROUP(0x04000),
+
+ GCERR_POWER_CLOCK_ON /* Failed to enable clock. */
+ = GCERR_GROUP(0x04010),
+
+ GCERR_POWER_IRQ_ON /* Failed to install IRQ handler. */
+ = GCERR_GROUP(0x04020),
+
+ GCERR_POWER_PULSE /* Pulse skipping error. */
+ = GCERR_GROUP(0x04030),
+
+ /**** GCIOCTL module errors. */
+ GCERR_IOCTL_CTX_ALLOC /* Context wrapper allocation. */
+ = GCERR_GROUP(0x11000),
+
+ GCERR_IOCTL_BUF_ALLOC /* Command buffer allocation. */
+ = GCERR_GROUP(0x11010),
+
+ GCERR_IOCTL_FIXUP_ALLOC /* Fixup buffer allocation. */
+ = GCERR_GROUP(0x11020),
+};
+
+#endif
diff --git a/include/linux/gcioctl.h b/include/linux/gcioctl.h
--- /dev/null
+++ b/include/linux/gcioctl.h
@@ -0,0 +1,275 @@
+/*
+ * gcioctl.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCIOCTL_H
+#define GCIOCTL_H
+
+#include "list.h"
+#include "gcerror.h"
+#include "gcreg.h"
+#include "cache-2dmanager.h"
+#include "bverror.h"
+
+/* IOCTL parameters. */
+#define GCIOCTL_TYPE 0x5D
+#define GCIOCTL_BASE 0x5D
+
+
+/*******************************************************************************
+ * Capability query API entry.
+ */
+
+#define GCIOCTL_GETCAPS _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x00, \
+ struct gcicaps)
+
+/* GCIOCTL_CALLBACK_ALLOC / GCIOCTL_CALLBACK_FREE:
+ * To be able to use the callback mechanism each user space client must
+ * use the ALLOC/FREE APIs to manage a kernel side callback object
+ * represented by the handle member of struct gcicallback.
+ * ALLOC API allocates the object and returns the handle to it. */
+struct gcicaps {
+ /* Error code. */
+ enum gcerror gcerror;
+
+ /* Capabilities and characteristics. */
+ unsigned int gcmodel;
+ unsigned int gcrevision;
+ unsigned int gcdate;
+ unsigned int gctime;
+ union gcfeatures gcfeatures;
+ union gcfeatures0 gcfeatures0;
+ union gcfeatures1 gcfeatures1;
+ union gcfeatures2 gcfeatures2;
+ union gcfeatures3 gcfeatures3;
+};
+
+/*******************************************************************************
+ * Commit API entry.
+ */
+
+#define GCIOCTL_COMMIT _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x10, \
+ struct gcicommit)
+
+/* GPU graphics pipe definition. */
+enum gcpipe {
+ GCPIPE_UNKNOWN,
+ GCPIPE_2D,
+ GCPIPE_3D
+};
+
+/* Commit header; contains pointers to the head and the tail of a linked list
+ of command buffers to execute. */
+struct gcicommit {
+ /* Return status code. */
+ enum gcerror gcerror;
+
+ /* Entry graphics pipe specifies the pipe the GPU is expected to be in
+ * for successfull execution of the specified command buffers in this
+ * call. Exit graphics pipe specifies the state of the GPU after the
+ * buffers are executed. */
+ enum gcpipe entrypipe;
+ enum gcpipe exitpipe;
+
+ /* List of command buffers to be executed (gcbuffer). */
+ struct list_head buffer;
+
+ /* Pointer to the callback function to be called when the GPU completes
+ * execution of all buffers specified in this call. This member can be
+ * NULL if no callback is desired. callbackparam specifies data to be
+ * passed to the callback. */
+ void (*callback) (void *callbackparam);
+ void *callbackparam;
+
+ /* Callback object handle allocated with GCIOCTL_CALLBACK_ALLOC API. */
+ unsigned long handle;
+
+ /* If asynchronous is set to true, the call returns immediately without
+ * waiting until all specified buffers have been executed. If set to
+ * false, the call does not return until execution is finished. */
+ bool asynchronous;
+
+ /* Scheduled unmappings (gcschedunmap). */
+ struct list_head unmap;
+};
+
+/* Command buffer header. */
+#define GC_BUFFER_SIZE (32 * 1024)
+struct gcbuffer {
+ /* Fixup list (gcfixup). */
+ struct list_head fixup;
+
+ /* Number of pixels to be rendered. */
+ unsigned int pixelcount;
+
+ /* Pointers to the head and tail of the command buffer list. */
+ unsigned int *head;
+ unsigned int *tail;
+
+ /* Number of bytes available in the buffer for allocation. */
+ unsigned int available;
+
+ /* Commmand buffer list (gcbuffer). */
+ struct list_head link;
+};
+
+/* Fixup entry. */
+struct gcfixupentry {
+ /* Offset into the commmand buffer where fixup is to be performed. */
+ unsigned int dataoffset;
+
+ /* Offset to be added to the translated address. */
+ unsigned int surfoffset;
+};
+
+/* Address fixup array. */
+#define GC_FIXUP_MAX 1024
+struct gcfixup {
+ /* Fixup list (gcfixup). */
+ struct list_head link;
+
+ /* Fixup array. */
+ unsigned int count;
+ struct gcfixupentry fixup[GC_FIXUP_MAX];
+};
+
+/* Defines a link list of scheduled unmappings. */
+struct gcschedunmap {
+ /* Map handle. */
+ unsigned long handle;
+
+ /* Previous/next unmapping info (gcschedunmap). */
+ struct list_head link;
+};
+
+
+/*******************************************************************************
+ * Map/unmap API entries.
+ */
+
+#define GCIOCTL_MAP _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x20, \
+ struct gcimap)
+#define GCIOCTL_UNMAP _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x21, \
+ struct gcimap)
+
+struct gcimap {
+ /* Return status code. */
+ enum gcerror gcerror;
+
+ /* Mapped handle of the buffer. */
+ unsigned long handle;
+
+ union {
+ /* Pointer to the buffer to be mapped;
+ * used when pagearray is not provided (set to NULL). */
+ void *logical;
+
+ /* Page offset of the buffer to be mapped;
+ * used when pagearray is provided. */
+ unsigned int offset;
+ } buf;
+
+ /* Size of a physical page, 0 for default. */
+ unsigned int pagesize;
+
+ /* Pointer to array of physical pages. */
+ unsigned long *pagearray;
+
+ /* Size of the buffer to be mappped. */
+ unsigned int size;
+};
+
+
+/*******************************************************************************
+ * Cache manipulation API entries.
+ */
+
+#define GCIOCTL_CACHE _IOW(GCIOCTL_TYPE, GCIOCTL_BASE + 0x30, \
+ struct gcicache)
+
+struct gcicache {
+ /* Number of regions. */
+ int count;
+
+ /* The most regions that we deal with is 3. */
+ struct c2dmrgn rgn[3];
+
+ /* Direction of data. */
+ int dir;
+};
+
+
+/*******************************************************************************
+ * Callback API entry.
+ */
+
+#define GCIOCTL_CALLBACK_ALLOC _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x40, \
+ struct gcicallback)
+#define GCIOCTL_CALLBACK_FREE _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x41, \
+ struct gcicallback)
+#define GCIOCTL_CALLBACK_WAIT _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x42, \
+ struct gcicallbackwait)
+#define GCIOCTL_CALLBACK_ARM _IOWR(GCIOCTL_TYPE, GCIOCTL_BASE + 0x43, \
+ struct gcicallbackarm)
+
+/* GCIOCTL_CALLBACK_ALLOC / GCIOCTL_CALLBACK_FREE:
+ * To be able to use the callback mechanism each user space client must
+ * use the ALLOC/FREE APIs to manage a kernel side callback object
+ * represented by the handle member of struct gcicallback.
+ * ALLOC API allocates the object and returns the handle to it. */
+struct gcicallback {
+ /* Error code. */
+ enum gcerror gcerror;
+
+ /* Callback object handle. */
+ unsigned long handle;
+};
+
+/* GCIOCTL_CALLBACK_WAIT:
+ * Called by the user level client to block and wait until the hardware
+ * has executed a callback that was previosuly scheduled for the handle. */
+struct gcicallbackwait {
+ /* Error code. */
+ enum gcerror gcerror;
+
+ /* Callback object handle. */
+ unsigned long handle;
+
+ /* Timeout in milliseconds. */
+ unsigned long timeoutms;
+
+ /* OUT: if the call succeeds, callback and callbackparam are
+ * initialized with the callback to call. */
+ void (*callback) (void *callbackparam);
+ void *callbackparam;
+};
+
+/* GCIOCTL_CALLBACK_ARM:
+ * Called by the client to arm a callback. This is similar to what
+ * COMMIT API does, but in a separate API. */
+struct gcicallbackarm {
+ /* Return status code. */
+ enum gcerror gcerror;
+
+ /* Pointer to the callback function to be called when the GPU completes
+ * execution of all buffers specified in this call. This member can be
+ * NULL if no callback is desired. callbackparam specifies data to be
+ * passed to the callback. */
+ void (*callback) (void *callbackparam);
+ void *callbackparam;
+
+ /* Callback object handle allocated with GCIOCTL_CALLBACK_ALLOC API. */
+ unsigned long handle;
+};
+
+#endif
diff --git a/include/linux/gcreg.h b/include/linux/gcreg.h
--- /dev/null
+++ b/include/linux/gcreg.h
@@ -0,0 +1,10335 @@
+/*
+ * gcreg.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __gcreg_h
+#define __gcreg_h
+
+/*******************************************************************************
+** Register access macros.
+*/
+
+#define GCREGSTART(reg_field) \
+( \
+ 0 ? reg_field \
+)
+
+#define GCREGEND(reg_field) \
+( \
+ 1 ? reg_field \
+)
+
+#define GCREGSIZE(reg_field) \
+( \
+ GCREGEND(reg_field) - GCREGSTART(reg_field) + 1 \
+)
+
+#define GCREGALIGN(data, reg_field) \
+( \
+ ((unsigned int) (data)) << GCREGSTART(reg_field) \
+)
+
+#define GCREGMASK(reg_field) \
+( \
+ GCREGALIGN(~0UL >> (32 - GCREGSIZE(reg_field)), reg_field) \
+)
+
+#define GCSETFIELDVAL(data, reg, field, value) \
+( \
+ (((unsigned int) (data)) & ~GCREGMASK(reg##_##field)) \
+ | (GCREGALIGN(reg##_##field##_##value, reg##_##field) \
+ & GCREGMASK(reg##_##field)) \
+)
+
+#define GCSETFIELD(data, reg, field, value) \
+( \
+ (((unsigned int) (data)) & ~GCREGMASK(reg##_##field)) \
+ | (GCREGALIGN((unsigned int) (value), reg##_##field) \
+ & GCREGMASK(reg##_##field)) \
+)
+
+#define GCGETFIELD(data, reg, field) \
+( \
+ (((unsigned int) (data)) & GCREGMASK(reg##_##field)) \
+ >> GCREGSTART(reg##_##field) \
+)
+
+#define GCREGVALUE(reg, field, val) \
+( \
+ reg##_##field##_##val \
+)
+
+/*******************************************************************************
+** Register gcregHiClockControl
+*/
+
+#define GCREG_HI_CLOCK_CONTROL_Address 0x00000
+#define GCREG_HI_CLOCK_CONTROL_MSB 15
+#define GCREG_HI_CLOCK_CONTROL_LSB 0
+#define GCREG_HI_CLOCK_CONTROL_BLK 0
+#define GCREG_HI_CLOCK_CONTROL_Count 1
+#define GCREG_HI_CLOCK_CONTROL_FieldMask 0x000A17FE
+#define GCREG_HI_CLOCK_CONTROL_ReadMask 0x000A17FE
+#define GCREG_HI_CLOCK_CONTROL_WriteMask 0x000817FE
+#define GCREG_HI_CLOCK_CONTROL_ResetValue 0x00000100
+
+/* Disable 3D clock. */
+#define GCREG_HI_CLOCK_CONTROL_CLK3D_DIS 0 : 0
+#define GCREG_HI_CLOCK_CONTROL_CLK3D_DIS_End 0
+#define GCREG_HI_CLOCK_CONTROL_CLK3D_DIS_Start 0
+#define GCREG_HI_CLOCK_CONTROL_CLK3D_DIS_Type U01
+
+/* Disable 2D clock. */
+#define GCREG_HI_CLOCK_CONTROL_CLK2D_DIS 1 : 1
+#define GCREG_HI_CLOCK_CONTROL_CLK2D_DIS_End 1
+#define GCREG_HI_CLOCK_CONTROL_CLK2D_DIS_Start 1
+#define GCREG_HI_CLOCK_CONTROL_CLK2D_DIS_Type U01
+
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_VAL 8 : 2
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_VAL_End 8
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_VAL_Start 2
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_VAL_Type U07
+
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD 9 : 9
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD_End 9
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD_Start 9
+#define GCREG_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD_Type U01
+
+/* Disables clock gating for rams. */
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING 10 : 10
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING_End 10
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING_Start 10
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING_Type U01
+
+/* Disable debug registers. If this bit is 1, debug regs are clock gated. */
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS 11 : 11
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS_End 11
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS_Start 11
+#define GCREG_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS_Type U01
+
+/* Soft resets the IP. */
+#define GCREG_HI_CLOCK_CONTROL_SOFT_RESET 12 : 12
+#define GCREG_HI_CLOCK_CONTROL_SOFT_RESET_End 12
+#define GCREG_HI_CLOCK_CONTROL_SOFT_RESET_Start 12
+#define GCREG_HI_CLOCK_CONTROL_SOFT_RESET_Type U01
+
+/* 3D pipe is idle. */
+#define GCREG_HI_CLOCK_CONTROL_IDLE_3D 16 : 16
+#define GCREG_HI_CLOCK_CONTROL_IDLE_3D_End 16
+#define GCREG_HI_CLOCK_CONTROL_IDLE_3D_Start 16
+#define GCREG_HI_CLOCK_CONTROL_IDLE_3D_Type U01
+
+/* 2D pipe is idle. */
+#define GCREG_HI_CLOCK_CONTROL_IDLE_2D 17 : 17
+#define GCREG_HI_CLOCK_CONTROL_IDLE_2D_End 17
+#define GCREG_HI_CLOCK_CONTROL_IDLE_2D_Start 17
+#define GCREG_HI_CLOCK_CONTROL_IDLE_2D_Type U01
+
+/* VG pipe is idle. */
+#define GCREG_HI_CLOCK_CONTROL_IDLE_VG 18 : 18
+#define GCREG_HI_CLOCK_CONTROL_IDLE_VG_End 18
+#define GCREG_HI_CLOCK_CONTROL_IDLE_VG_Start 18
+#define GCREG_HI_CLOCK_CONTROL_IDLE_VG_Type U01
+
+/* Isolate GPU bit */
+#define GCREG_HI_CLOCK_CONTROL_ISOLATE_GPU 19 : 19
+#define GCREG_HI_CLOCK_CONTROL_ISOLATE_GPU_End 19
+#define GCREG_HI_CLOCK_CONTROL_ISOLATE_GPU_Start 19
+#define GCREG_HI_CLOCK_CONTROL_ISOLATE_GPU_Type U01
+
+union gcclockcontrol {
+ struct {
+ /* gcregHiClockControl:
+ GCREG_HI_CLOCK_CONTROL_CLK3D_DIS */
+ unsigned int disable3d:1;
+
+ /* gcregHiClockControl:
+ GCREG_HI_CLOCK_CONTROL_CLK2D_DIS */
+ unsigned int disable2d:1;
+
+ /* gcregHiClockControl:
+ GCREG_HI_CLOCK_CONTROL_FSCALE_VAL */
+ unsigned int pulsecount:7;
+
+ /* gcregHiClockControl:
+ GCREG_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD */
+ unsigned int pulseset:1;
+
+ /* gcregHiClockControl:
+ GCREG_HI_CLOCK_CONTROL_DISABLE_RAM_CLK_GATING */
+ unsigned int ramgate:1;
+
+ /* gcregHiClockControl:
+ GCREG_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS */
+ unsigned int disabledbg:1;
+
+ /* gcregHiClockControl:
+ GCREG_HI_CLOCK_CONTROL_SOFT_RESET */
+ unsigned int reset:1;
+
+ /* gcregHiClockControl:
+ reserved */
+ unsigned int _reserved_13_15:3;
+
+ /* gcregHiClockControl:
+ GCREG_HI_CLOCK_CONTROL_IDLE_3D */
+ unsigned int idle3d:1;
+
+ /* gcregHiClockControl:
+ GCREG_HI_CLOCK_CONTROL_IDLE_2D */
+ unsigned int idle2d:1;
+
+ /* gcregHiClockControl:
+ GCREG_HI_CLOCK_CONTROL_IDLE_VG */
+ unsigned int idlevg:1;
+
+ /* gcregHiClockControl:
+ GCREG_HI_CLOCK_CONTROL_ISOLATE_GPU */
+ unsigned int isolate:1;
+
+ /* gcregHiClockControl:
+ reserved */
+ unsigned int _reserved_20_31:12;
+ } reg;
+
+ unsigned int raw;
+};
+
+/*******************************************************************************
+** Register gcregHiIdle
+*/
+
+#define GCREG_HI_IDLE_Address 0x00004
+#define GCREG_HI_IDLE_MSB 15
+#define GCREG_HI_IDLE_LSB 0
+#define GCREG_HI_IDLE_BLK 0
+#define GCREG_HI_IDLE_Count 1
+#define GCREG_HI_IDLE_FieldMask 0x80000007
+#define GCREG_HI_IDLE_ReadMask 0x80000007
+#define GCREG_HI_IDLE_WriteMask 0x00000000
+#define GCREG_HI_IDLE_ResetValue 0x00000007
+
+/* FE is idle. */
+#define GCREG_HI_IDLE_IDLE_FE 0 : 0
+#define GCREG_HI_IDLE_IDLE_FE_End 0
+#define GCREG_HI_IDLE_IDLE_FE_Start 0
+#define GCREG_HI_IDLE_IDLE_FE_Type U01
+
+/* DE is idle. */
+#define GCREG_HI_IDLE_IDLE_DE 1 : 1
+#define GCREG_HI_IDLE_IDLE_DE_End 1
+#define GCREG_HI_IDLE_IDLE_DE_Start 1
+#define GCREG_HI_IDLE_IDLE_DE_Type U01
+
+/* PE is idle. */
+#define GCREG_HI_IDLE_IDLE_PE 2 : 2
+#define GCREG_HI_IDLE_IDLE_PE_End 2
+#define GCREG_HI_IDLE_IDLE_PE_Start 2
+#define GCREG_HI_IDLE_IDLE_PE_Type U01
+
+/* AXI is in low power mode. */
+#define GCREG_HI_IDLE_AXI_LP 31 : 31
+#define GCREG_HI_IDLE_AXI_LP_End 31
+#define GCREG_HI_IDLE_AXI_LP_Start 31
+#define GCREG_HI_IDLE_AXI_LP_Type U01
+
+union gcidle {
+ struct {
+ /* gcregHiIdle: GCREG_HI_IDLE_IDLE_FE */
+ unsigned int fe:1;
+
+ /* gcregHiIdle: GCREG_HI_IDLE_IDLE_DE */
+ unsigned int de:1;
+
+ /* gcregHiIdle: GCREG_HI_IDLE_IDLE_PE */
+ unsigned int pe:1;
+
+ /* gcregHiIdle: reserved */
+ unsigned int _reserved_3_30:28;
+
+ /* gcregHiIdle: GCREG_HI_IDLE_AXI_LP */
+ unsigned int axilp:1;
+ } reg;
+
+ unsigned int raw;
+};
+
+/*******************************************************************************
+** Register gcregAxiConfig
+*/
+
+#define GCREG_AXI_CONFIG_Address 0x00008
+#define GCREG_AXI_CONFIG_MSB 15
+#define GCREG_AXI_CONFIG_LSB 0
+#define GCREG_AXI_CONFIG_BLK 0
+#define GCREG_AXI_CONFIG_Count 1
+#define GCREG_AXI_CONFIG_FieldMask 0x0000FFFF
+#define GCREG_AXI_CONFIG_ReadMask 0x0000FFFF
+#define GCREG_AXI_CONFIG_WriteMask 0x0000FFFF
+#define GCREG_AXI_CONFIG_ResetValue 0x00000000
+
+#define GCREG_AXI_CONFIG_AWID 3 : 0
+#define GCREG_AXI_CONFIG_AWID_End 3
+#define GCREG_AXI_CONFIG_AWID_Start 0
+#define GCREG_AXI_CONFIG_AWID_Type U04
+
+#define GCREG_AXI_CONFIG_ARID 7 : 4
+#define GCREG_AXI_CONFIG_ARID_End 7
+#define GCREG_AXI_CONFIG_ARID_Start 4
+#define GCREG_AXI_CONFIG_ARID_Type U04
+
+#define GCREG_AXI_CONFIG_AWCACHE 11 : 8
+#define GCREG_AXI_CONFIG_AWCACHE_End 11
+#define GCREG_AXI_CONFIG_AWCACHE_Start 8
+#define GCREG_AXI_CONFIG_AWCACHE_Type U04
+
+#define GCREG_AXI_CONFIG_ARCACHE 15 : 12
+#define GCREG_AXI_CONFIG_ARCACHE_End 15
+#define GCREG_AXI_CONFIG_ARCACHE_Start 12
+#define GCREG_AXI_CONFIG_ARCACHE_Type U04
+
+/*******************************************************************************
+** Register gcregAxiStatus
+*/
+
+#define GCREG_AXI_STATUS_Address 0x0000C
+#define GCREG_AXI_STATUS_MSB 15
+#define GCREG_AXI_STATUS_LSB 0
+#define GCREG_AXI_STATUS_BLK 0
+#define GCREG_AXI_STATUS_Count 1
+#define GCREG_AXI_STATUS_FieldMask 0x000003FF
+#define GCREG_AXI_STATUS_ReadMask 0x000003FF
+#define GCREG_AXI_STATUS_WriteMask 0x00000000
+#define GCREG_AXI_STATUS_ResetValue 0x00000000
+
+#define GCREG_AXI_STATUS_DET_RD_ERR 9 : 9
+#define GCREG_AXI_STATUS_DET_RD_ERR_End 9
+#define GCREG_AXI_STATUS_DET_RD_ERR_Start 9
+#define GCREG_AXI_STATUS_DET_RD_ERR_Type U01
+
+#define GCREG_AXI_STATUS_DET_WR_ERR 8 : 8
+#define GCREG_AXI_STATUS_DET_WR_ERR_End 8
+#define GCREG_AXI_STATUS_DET_WR_ERR_Start 8
+#define GCREG_AXI_STATUS_DET_WR_ERR_Type U01
+
+#define GCREG_AXI_STATUS_RD_ERR_ID 7 : 4
+#define GCREG_AXI_STATUS_RD_ERR_ID_End 7
+#define GCREG_AXI_STATUS_RD_ERR_ID_Start 4
+#define GCREG_AXI_STATUS_RD_ERR_ID_Type U04
+
+#define GCREG_AXI_STATUS_WR_ERR_ID 3 : 0
+#define GCREG_AXI_STATUS_WR_ERR_ID_End 3
+#define GCREG_AXI_STATUS_WR_ERR_ID_Start 0
+#define GCREG_AXI_STATUS_WR_ERR_ID_Type U04
+
+/*******************************************************************************
+** Register gcregIntrAcknowledge
+*/
+
+/* Interrupt acknowledge register. Each bit represents a corresponding event
+** being triggered. Reading from this register clears the outstanding interrupt.
+*/
+
+#define GCREG_INTR_ACKNOWLEDGE_Address 0x00010
+#define GCREG_INTR_ACKNOWLEDGE_MSB 15
+#define GCREG_INTR_ACKNOWLEDGE_LSB 0
+#define GCREG_INTR_ACKNOWLEDGE_BLK 0
+#define GCREG_INTR_ACKNOWLEDGE_Count 1
+#define GCREG_INTR_ACKNOWLEDGE_FieldMask 0xFFFFFFFF
+#define GCREG_INTR_ACKNOWLEDGE_ReadMask 0xFFFFFFFF
+#define GCREG_INTR_ACKNOWLEDGE_WriteMask 0x00000000
+#define GCREG_INTR_ACKNOWLEDGE_ResetValue 0x00000000
+
+#define GCREG_INTR_ACKNOWLEDGE_INTR_VEC 31 : 0
+#define GCREG_INTR_ACKNOWLEDGE_INTR_VEC_End 31
+#define GCREG_INTR_ACKNOWLEDGE_INTR_VEC_Start 0
+#define GCREG_INTR_ACKNOWLEDGE_INTR_VEC_Type U32
+
+/*******************************************************************************
+** Register gcregIntrEnbl
+*/
+
+/* Interrupt enable register. Each bit enables a corresponding event. */
+
+#define GCREG_INTR_ENBL_Address 0x00014
+#define GCREG_INTR_ENBL_MSB 15
+#define GCREG_INTR_ENBL_LSB 0
+#define GCREG_INTR_ENBL_BLK 0
+#define GCREG_INTR_ENBL_Count 1
+#define GCREG_INTR_ENBL_FieldMask 0xFFFFFFFF
+#define GCREG_INTR_ENBL_ReadMask 0xFFFFFFFF
+#define GCREG_INTR_ENBL_WriteMask 0xFFFFFFFF
+#define GCREG_INTR_ENBL_ResetValue 0x00000000
+
+#define GCREG_INTR_ENBL_INTR_ENBL_VEC 31 : 0
+#define GCREG_INTR_ENBL_INTR_ENBL_VEC_End 31
+#define GCREG_INTR_ENBL_INTR_ENBL_VEC_Start 0
+#define GCREG_INTR_ENBL_INTR_ENBL_VEC_Type U32
+
+/*******************************************************************************
+** Register GCFeatures
+*/
+
+/* Shows which features are enabled in this chip. This register has no set
+** reset value. It varies with the implementation.
+*/
+
+#define GC_FEATURES_Address 0x0001C
+#define GC_FEATURES_MSB 15
+#define GC_FEATURES_LSB 0
+#define GC_FEATURES_BLK 0
+#define GC_FEATURES_Count 1
+#define GC_FEATURES_FieldMask 0xFFFFFFFF
+#define GC_FEATURES_ReadMask 0xFFFFFFFF
+#define GC_FEATURES_WriteMask 0x00000000
+#define GC_FEATURES_ResetValue 0x00000000
+
+/* Fast clear. */
+#define GC_FEATURES_FAST_CLEAR 0 : 0
+#define GC_FEATURES_FAST_CLEAR_End 0
+#define GC_FEATURES_FAST_CLEAR_Start 0
+#define GC_FEATURES_FAST_CLEAR_Type U01
+#define GC_FEATURES_FAST_CLEAR_NONE 0x0
+#define GC_FEATURES_FAST_CLEAR_AVAILABLE 0x1
+
+/* Full-screen anti-aliasing. */
+#define GC_FEATURES_SPECIAL_ANTI_ALIASING 1 : 1
+#define GC_FEATURES_SPECIAL_ANTI_ALIASING_End 1
+#define GC_FEATURES_SPECIAL_ANTI_ALIASING_Start 1
+#define GC_FEATURES_SPECIAL_ANTI_ALIASING_Type U01
+#define GC_FEATURES_SPECIAL_ANTI_ALIASING_NONE 0x0
+#define GC_FEATURES_SPECIAL_ANTI_ALIASING_AVAILABLE 0x1
+
+/* 3D pipe. */
+#define GC_FEATURES_PIPE_3D 2 : 2
+#define GC_FEATURES_PIPE_3D_End 2
+#define GC_FEATURES_PIPE_3D_Start 2
+#define GC_FEATURES_PIPE_3D_Type U01
+#define GC_FEATURES_PIPE_3D_NONE 0x0
+#define GC_FEATURES_PIPE_3D_AVAILABLE 0x1
+
+/* DXT texture compression. */
+#define GC_FEATURES_DXT_TEXTURE_COMPRESSION 3 : 3
+#define GC_FEATURES_DXT_TEXTURE_COMPRESSION_End 3
+#define GC_FEATURES_DXT_TEXTURE_COMPRESSION_Start 3
+#define GC_FEATURES_DXT_TEXTURE_COMPRESSION_Type U01
+#define GC_FEATURES_DXT_TEXTURE_COMPRESSION_NONE 0x0
+#define GC_FEATURES_DXT_TEXTURE_COMPRESSION_AVAILABLE 0x1
+
+/* Debug registers. */
+#define GC_FEATURES_DEBUG_MODE 4 : 4
+#define GC_FEATURES_DEBUG_MODE_End 4
+#define GC_FEATURES_DEBUG_MODE_Start 4
+#define GC_FEATURES_DEBUG_MODE_Type U01
+#define GC_FEATURES_DEBUG_MODE_NONE 0x0
+#define GC_FEATURES_DEBUG_MODE_AVAILABLE 0x1
+
+/* Depth and color compression. */
+#define GC_FEATURES_ZCOMPRESSION 5 : 5
+#define GC_FEATURES_ZCOMPRESSION_End 5
+#define GC_FEATURES_ZCOMPRESSION_Start 5
+#define GC_FEATURES_ZCOMPRESSION_Type U01
+#define GC_FEATURES_ZCOMPRESSION_NONE 0x0
+#define GC_FEATURES_ZCOMPRESSION_AVAILABLE 0x1
+
+/* YUV 4:2:0 support in filter blit. */
+#define GC_FEATURES_YUV420_FILTER 6 : 6
+#define GC_FEATURES_YUV420_FILTER_End 6
+#define GC_FEATURES_YUV420_FILTER_Start 6
+#define GC_FEATURES_YUV420_FILTER_Type U01
+#define GC_FEATURES_YUV420_FILTER_NONE 0x0
+#define GC_FEATURES_YUV420_FILTER_AVAILABLE 0x1
+
+/* MSAA support. */
+#define GC_FEATURES_MSAA 7 : 7
+#define GC_FEATURES_MSAA_End 7
+#define GC_FEATURES_MSAA_Start 7
+#define GC_FEATURES_MSAA_Type U01
+#define GC_FEATURES_MSAA_NONE 0x0
+#define GC_FEATURES_MSAA_AVAILABLE 0x1
+
+/* Shows if there is a display controller in the IP. */
+#define GC_FEATURES_DC 8 : 8
+#define GC_FEATURES_DC_End 8
+#define GC_FEATURES_DC_Start 8
+#define GC_FEATURES_DC_Type U01
+#define GC_FEATURES_DC_NONE 0x0
+#define GC_FEATURES_DC_AVAILABLE 0x1
+
+/* Shows if there is 2D engine. */
+#define GC_FEATURES_PIPE_2D 9 : 9
+#define GC_FEATURES_PIPE_2D_End 9
+#define GC_FEATURES_PIPE_2D_Start 9
+#define GC_FEATURES_PIPE_2D_Type U01
+#define GC_FEATURES_PIPE_2D_NONE 0x0
+#define GC_FEATURES_PIPE_2D_AVAILABLE 0x1
+
+/* ETC1 texture compression. */
+#define GC_FEATURES_ETC1_TEXTURE_COMPRESSION 10 : 10
+#define GC_FEATURES_ETC1_TEXTURE_COMPRESSION_End 10
+#define GC_FEATURES_ETC1_TEXTURE_COMPRESSION_Start 10
+#define GC_FEATURES_ETC1_TEXTURE_COMPRESSION_Type U01
+#define GC_FEATURES_ETC1_TEXTURE_COMPRESSION_NONE 0x0
+#define GC_FEATURES_ETC1_TEXTURE_COMPRESSION_AVAILABLE 0x1
+
+/* Shows if the IP has HD scaler. */
+#define GC_FEATURES_FAST_SCALER 11 : 11
+#define GC_FEATURES_FAST_SCALER_End 11
+#define GC_FEATURES_FAST_SCALER_Start 11
+#define GC_FEATURES_FAST_SCALER_Type U01
+#define GC_FEATURES_FAST_SCALER_NONE 0x0
+#define GC_FEATURES_FAST_SCALER_AVAILABLE 0x1
+
+/* Shows if the IP has HDR support. */
+#define GC_FEATURES_HIGH_DYNAMIC_RANGE 12 : 12
+#define GC_FEATURES_HIGH_DYNAMIC_RANGE_End 12
+#define GC_FEATURES_HIGH_DYNAMIC_RANGE_Start 12
+#define GC_FEATURES_HIGH_DYNAMIC_RANGE_Type U01
+#define GC_FEATURES_HIGH_DYNAMIC_RANGE_NONE 0x0
+#define GC_FEATURES_HIGH_DYNAMIC_RANGE_AVAILABLE 0x1
+
+/* YUV 4:2:0 tiler is available. */
+#define GC_FEATURES_YUV420_TILER 13 : 13
+#define GC_FEATURES_YUV420_TILER_End 13
+#define GC_FEATURES_YUV420_TILER_Start 13
+#define GC_FEATURES_YUV420_TILER_Type U01
+#define GC_FEATURES_YUV420_TILER_NONE 0x0
+#define GC_FEATURES_YUV420_TILER_AVAILABLE 0x1
+
+/* Second level clock gating is available. */
+#define GC_FEATURES_MODULE_CG 14 : 14
+#define GC_FEATURES_MODULE_CG_End 14
+#define GC_FEATURES_MODULE_CG_Start 14
+#define GC_FEATURES_MODULE_CG_Type U01
+#define GC_FEATURES_MODULE_CG_NONE 0x0
+#define GC_FEATURES_MODULE_CG_AVAILABLE 0x1
+
+/* IP is configured to have minimum area. */
+#define GC_FEATURES_MIN_AREA 15 : 15
+#define GC_FEATURES_MIN_AREA_End 15
+#define GC_FEATURES_MIN_AREA_Start 15
+#define GC_FEATURES_MIN_AREA_Type U01
+#define GC_FEATURES_MIN_AREA_NONE 0x0
+#define GC_FEATURES_MIN_AREA_AVAILABLE 0x1
+
+/* IP does not have early-Z. */
+#define GC_FEATURES_NO_EZ 16 : 16
+#define GC_FEATURES_NO_EZ_End 16
+#define GC_FEATURES_NO_EZ_Start 16
+#define GC_FEATURES_NO_EZ_Type U01
+#define GC_FEATURES_NO_EZ_NONE 0x0
+#define GC_FEATURES_NO_EZ_AVAILABLE 0x1
+
+/* IP does not have 422 texture input format. */
+#define GC_FEATURES_NO422_TEXTURE 17 : 17
+#define GC_FEATURES_NO422_TEXTURE_End 17
+#define GC_FEATURES_NO422_TEXTURE_Start 17
+#define GC_FEATURES_NO422_TEXTURE_Type U01
+#define GC_FEATURES_NO422_TEXTURE_NONE 0x0
+#define GC_FEATURES_NO422_TEXTURE_AVAILABLE 0x1
+
+/* IP supports interleaving depth and color buffers. */
+#define GC_FEATURES_BUFFER_INTERLEAVING 18 : 18
+#define GC_FEATURES_BUFFER_INTERLEAVING_End 18
+#define GC_FEATURES_BUFFER_INTERLEAVING_Start 18
+#define GC_FEATURES_BUFFER_INTERLEAVING_Type U01
+#define GC_FEATURES_BUFFER_INTERLEAVING_NONE 0x0
+#define GC_FEATURES_BUFFER_INTERLEAVING_AVAILABLE 0x1
+
+/* Supports byte write in 2D. */
+#define GC_FEATURES_BYTE_WRITE_2D 19 : 19
+#define GC_FEATURES_BYTE_WRITE_2D_End 19
+#define GC_FEATURES_BYTE_WRITE_2D_Start 19
+#define GC_FEATURES_BYTE_WRITE_2D_Type U01
+#define GC_FEATURES_BYTE_WRITE_2D_NONE 0x0
+#define GC_FEATURES_BYTE_WRITE_2D_AVAILABLE 0x1
+
+/* IP does not have 2D scaler. */
+#define GC_FEATURES_NO_SCALER 20 : 20
+#define GC_FEATURES_NO_SCALER_End 20
+#define GC_FEATURES_NO_SCALER_Start 20
+#define GC_FEATURES_NO_SCALER_Type U01
+#define GC_FEATURES_NO_SCALER_NONE 0x0
+#define GC_FEATURES_NO_SCALER_AVAILABLE 0x1
+
+/* YUY2 averaging support in resolve. */
+#define GC_FEATURES_YUY2_AVERAGING 21 : 21
+#define GC_FEATURES_YUY2_AVERAGING_End 21
+#define GC_FEATURES_YUY2_AVERAGING_Start 21
+#define GC_FEATURES_YUY2_AVERAGING_Type U01
+#define GC_FEATURES_YUY2_AVERAGING_NONE 0x0
+#define GC_FEATURES_YUY2_AVERAGING_AVAILABLE 0x1
+
+/* PE cache is half. */
+#define GC_FEATURES_HALF_PE_CACHE 22 : 22
+#define GC_FEATURES_HALF_PE_CACHE_End 22
+#define GC_FEATURES_HALF_PE_CACHE_Start 22
+#define GC_FEATURES_HALF_PE_CACHE_Type U01
+#define GC_FEATURES_HALF_PE_CACHE_NONE 0x0
+#define GC_FEATURES_HALF_PE_CACHE_AVAILABLE 0x1
+
+/* TX cache is half. */
+#define GC_FEATURES_HALF_TX_CACHE 23 : 23
+#define GC_FEATURES_HALF_TX_CACHE_End 23
+#define GC_FEATURES_HALF_TX_CACHE_Start 23
+#define GC_FEATURES_HALF_TX_CACHE_Type U01
+#define GC_FEATURES_HALF_TX_CACHE_NONE 0x0
+#define GC_FEATURES_HALF_TX_CACHE_AVAILABLE 0x1
+
+/* YUY2 support in PE and YUY2 to RGB conversion in resolve. */
+#define GC_FEATURES_YUY2_RENDER_TARGET 24 : 24
+#define GC_FEATURES_YUY2_RENDER_TARGET_End 24
+#define GC_FEATURES_YUY2_RENDER_TARGET_Start 24
+#define GC_FEATURES_YUY2_RENDER_TARGET_Type U01
+#define GC_FEATURES_YUY2_RENDER_TARGET_NONE 0x0
+#define GC_FEATURES_YUY2_RENDER_TARGET_AVAILABLE 0x1
+
+/* 32 bit memory address support. */
+#define GC_FEATURES_MEM32_BIT_SUPPORT 25 : 25
+#define GC_FEATURES_MEM32_BIT_SUPPORT_End 25
+#define GC_FEATURES_MEM32_BIT_SUPPORT_Start 25
+#define GC_FEATURES_MEM32_BIT_SUPPORT_Type U01
+#define GC_FEATURES_MEM32_BIT_SUPPORT_NONE 0x0
+#define GC_FEATURES_MEM32_BIT_SUPPORT_AVAILABLE 0x1
+
+/* VG pipe is present. */
+#define GC_FEATURES_PIPE_VG 26 : 26
+#define GC_FEATURES_PIPE_VG_End 26
+#define GC_FEATURES_PIPE_VG_Start 26
+#define GC_FEATURES_PIPE_VG_Type U01
+#define GC_FEATURES_PIPE_VG_NONE 0x0
+#define GC_FEATURES_PIPE_VG_AVAILABLE 0x1
+
+/* VG tesselator is present. */
+#define GC_FEATURES_VGTS 27 : 27
+#define GC_FEATURES_VGTS_End 27
+#define GC_FEATURES_VGTS_Start 27
+#define GC_FEATURES_VGTS_Type U01
+#define GC_FEATURES_VGTS_NONE 0x0
+#define GC_FEATURES_VGTS_AVAILABLE 0x1
+
+/* FE 2.0 is present. */
+#define GC_FEATURES_FE20 28 : 28
+#define GC_FEATURES_FE20_End 28
+#define GC_FEATURES_FE20_Start 28
+#define GC_FEATURES_FE20_Type U01
+#define GC_FEATURES_FE20_NONE 0x0
+#define GC_FEATURES_FE20_AVAILABLE 0x1
+
+/* 3D PE has byte write capability. */
+#define GC_FEATURES_BYTE_WRITE_3D 29 : 29
+#define GC_FEATURES_BYTE_WRITE_3D_End 29
+#define GC_FEATURES_BYTE_WRITE_3D_Start 29
+#define GC_FEATURES_BYTE_WRITE_3D_Type U01
+#define GC_FEATURES_BYTE_WRITE_3D_NONE 0x0
+#define GC_FEATURES_BYTE_WRITE_3D_AVAILABLE 0x1
+
+/* Supports resolveing into YUV target. */
+#define GC_FEATURES_RS_YUV_TARGET 30 : 30
+#define GC_FEATURES_RS_YUV_TARGET_End 30
+#define GC_FEATURES_RS_YUV_TARGET_Start 30
+#define GC_FEATURES_RS_YUV_TARGET_Type U01
+#define GC_FEATURES_RS_YUV_TARGET_NONE 0x0
+#define GC_FEATURES_RS_YUV_TARGET_AVAILABLE 0x1
+
+/* Supports 20 bit index. */
+#define GC_FEATURES_FE20_BIT_INDEX 31 : 31
+#define GC_FEATURES_FE20_BIT_INDEX_End 31
+#define GC_FEATURES_FE20_BIT_INDEX_Start 31
+#define GC_FEATURES_FE20_BIT_INDEX_Type U01
+#define GC_FEATURES_FE20_BIT_INDEX_NONE 0x0
+#define GC_FEATURES_FE20_BIT_INDEX_AVAILABLE 0x1
+
+union gcfeatures {
+ struct {
+ /* GC_FEATURES_Address:FAST_CLEAR */
+ unsigned int fastclear:1;
+
+ /* GC_FEATURES_Address:SPECIAL_ANTI_ALIASING */
+ unsigned int specialantialiasing:1;
+
+ /* GC_FEATURES_Address:PIPE_3D */
+ unsigned int pipe3d:1;
+
+ /* GC_FEATURES_Address:DXT_TEXTURE_COMPRESSION */
+ unsigned int dxt:1;
+
+ /* GC_FEATURES_Address:DEBUG_MODE */
+ unsigned int debugmode:1;
+
+ /* GC_FEATURES_Address:ZCOMPRESSION */
+ unsigned int zcompression:1;
+
+ /* GC_FEATURES_Address:YUV420_FILTER */
+ unsigned int yuv420filter:1;
+
+ /* GC_FEATURES_Address:MSAA */
+ unsigned int msaa:1;
+
+ /* GC_FEATURES_Address:DC */
+ unsigned int dc:1;
+
+ /* GC_FEATURES_Address:PIPE_2D */
+ unsigned int pipe2d:1;
+
+ /* GC_FEATURES_Address:ETC1_TEXTURE_COMPRESSION */
+ unsigned int etc:1;
+
+ /* GC_FEATURES_Address:FAST_SCALER */
+ unsigned int fastscaler:1;
+
+ /* GC_FEATURES_Address:HIGH_DYNAMIC_RANGE */
+ unsigned int hdr:1;
+
+ /* GC_FEATURES_Address:YUV420_TILER */
+ unsigned int yuv420tiler:1;
+
+ /* GC_FEATURES_Address:MODULE_CG */
+ unsigned int clockgating:1;
+
+ /* GC_FEATURES_Address:MIN_AREA */
+ unsigned int minarea:1;
+
+ /* GC_FEATURES_Address:NO_EZ */
+ unsigned int noez:1;
+
+ /* GC_FEATURES_Address:NO422_TEXTURE */
+ unsigned int no422texture:1;
+
+ /* GC_FEATURES_Address:BUFFER_INTERLEAVING */
+ unsigned int bufinterleaving:1;
+
+ /* GC_FEATURES_Address:BYTE_WRITE_2D */
+ unsigned int bytewrite2d:1;
+
+ /* GC_FEATURES_Address:NO_SCALER */
+ unsigned int noscaler:1;
+
+ /* GC_FEATURES_Address:YUY2_AVERAGING */
+ unsigned int yuy2averaging:1;
+
+ /* GC_FEATURES_Address:HALF_PE_CACHE */
+ unsigned int halfpecache:1;
+
+ /* GC_FEATURES_Address:HALF_TX_CACHE */
+ unsigned int halftxcache:1;
+
+ /* GC_FEATURES_Address:YUY2_RENDER_TARGET */
+ unsigned int yuy2target:1;
+
+ /* GC_FEATURES_Address:MEM32_BIT_SUPPORT */
+ unsigned int mem32:1;
+
+ /* GC_FEATURES_Address:PIPE_VG */
+ unsigned int pipevg:1;
+
+ /* GC_FEATURES_Address:VGTS */
+ unsigned int vgts:1;
+
+ /* GC_FEATURES_Address:FE20 */
+ unsigned int fe20:1;
+
+ /* GC_FEATURES_Address:BYTE_WRITE_3D */
+ unsigned int bytewrite3d:1;
+
+ /* GC_FEATURES_Address:RS_YUV_TARGET */
+ unsigned int rsyuvtarget:1;
+
+ /* GC_FEATURES_Address:FE20_BIT_INDEX */
+ unsigned int fe20bit:1;
+ } reg;
+
+ unsigned int raw;
+};
+
+/*******************************************************************************
+** Register GCChipId
+*/
+
+/* Shows the ID for the chip in BCD. This register has no set reset value.
+** It varies with the implementation.
+*/
+
+#define GC_CHIP_ID_Address 0x00020
+#define GC_CHIP_ID_MSB 15
+#define GC_CHIP_ID_LSB 0
+#define GC_CHIP_ID_BLK 0
+#define GC_CHIP_ID_Count 1
+#define GC_CHIP_ID_FieldMask 0xFFFFFFFF
+#define GC_CHIP_ID_ReadMask 0xFFFFFFFF
+#define GC_CHIP_ID_WriteMask 0x00000000
+#define GC_CHIP_ID_ResetValue 0x00000000
+
+/* Id. */
+#define GC_CHIP_ID_ID 31 : 0
+#define GC_CHIP_ID_ID_End 31
+#define GC_CHIP_ID_ID_Start 0
+#define GC_CHIP_ID_ID_Type U32
+
+/*******************************************************************************
+** Register GCChipRev
+*/
+
+/* Shows the revision for the chip in BCD. This register has no set reset
+** value. It varies with the implementation.
+*/
+
+#define GC_CHIP_REV_Address 0x00024
+#define GC_CHIP_REV_MSB 15
+#define GC_CHIP_REV_LSB 0
+#define GC_CHIP_REV_BLK 0
+#define GC_CHIP_REV_Count 1
+#define GC_CHIP_REV_FieldMask 0xFFFFFFFF
+#define GC_CHIP_REV_ReadMask 0xFFFFFFFF
+#define GC_CHIP_REV_WriteMask 0x00000000
+#define GC_CHIP_REV_ResetValue 0x00000000
+
+/* Revision. */
+#define GC_CHIP_REV_REV 31 : 0
+#define GC_CHIP_REV_REV_End 31
+#define GC_CHIP_REV_REV_Start 0
+#define GC_CHIP_REV_REV_Type U32
+
+/*******************************************************************************
+** Register GCChipDate
+*/
+
+/* Shows the release date for the IP. This register has no set reset value.
+** It varies with the implementation.
+*/
+
+#define GC_CHIP_DATE_Address 0x00028
+#define GC_CHIP_DATE_MSB 15
+#define GC_CHIP_DATE_LSB 0
+#define GC_CHIP_DATE_BLK 0
+#define GC_CHIP_DATE_Count 1
+#define GC_CHIP_DATE_FieldMask 0xFFFFFFFF
+#define GC_CHIP_DATE_ReadMask 0xFFFFFFFF
+#define GC_CHIP_DATE_WriteMask 0x00000000
+#define GC_CHIP_DATE_ResetValue 0x00000000
+
+/* Date. */
+#define GC_CHIP_DATE_DATE 31 : 0
+#define GC_CHIP_DATE_DATE_End 31
+#define GC_CHIP_DATE_DATE_Start 0
+#define GC_CHIP_DATE_DATE_Type U32
+
+/*******************************************************************************
+** Register GCChipTime
+*/
+
+/* Shows the release time for the IP. This register has no set reset value.
+** It varies with the implementation.
+*/
+
+#define GC_CHIP_TIME_Address 0x0002C
+#define GC_CHIP_TIME_MSB 15
+#define GC_CHIP_TIME_LSB 0
+#define GC_CHIP_TIME_BLK 0
+#define GC_CHIP_TIME_Count 1
+#define GC_CHIP_TIME_FieldMask 0xFFFFFFFF
+#define GC_CHIP_TIME_ReadMask 0xFFFFFFFF
+#define GC_CHIP_TIME_WriteMask 0x00000000
+#define GC_CHIP_TIME_ResetValue 0x00000000
+
+/* Time. */
+#define GC_CHIP_TIME_TIME 31 : 0
+#define GC_CHIP_TIME_TIME_End 31
+#define GC_CHIP_TIME_TIME_Start 0
+#define GC_CHIP_TIME_TIME_Type U32
+
+/*******************************************************************************
+** Register GCMinorFeatures0
+*/
+
+/* Shows which minor features are enabled in this chip. This register has no
+** set reset value. It varies with the implementation.
+*/
+
+#define GC_FEATURES0_Address 0x00034
+#define GC_FEATURES0_MSB 15
+#define GC_FEATURES0_LSB 0
+#define GC_FEATURES0_BLK 0
+#define GC_FEATURES0_Count 1
+#define GC_FEATURES0_FieldMask 0xFFFFFFFF
+#define GC_FEATURES0_ReadMask 0xFFFFFFFF
+#define GC_FEATURES0_WriteMask 0x00000000
+#define GC_FEATURES0_ResetValue 0x00000000
+
+/* Y flipping capability is added to resolve. */
+#define GC_FEATURES0_FLIP_Y 0 : 0
+#define GC_FEATURES0_FLIP_Y_End 0
+#define GC_FEATURES0_FLIP_Y_Start 0
+#define GC_FEATURES0_FLIP_Y_Type U01
+#define GC_FEATURES0_FLIP_Y_NONE 0x0
+#define GC_FEATURES0_FLIP_Y_AVAILABLE 0x1
+
+/* Dual Return Bus from HI to clients. */
+#define GC_FEATURES0_DUAL_RETURN_BUS 1 : 1
+#define GC_FEATURES0_DUAL_RETURN_BUS_End 1
+#define GC_FEATURES0_DUAL_RETURN_BUS_Start 1
+#define GC_FEATURES0_DUAL_RETURN_BUS_Type U01
+#define GC_FEATURES0_DUAL_RETURN_BUS_NONE 0x0
+#define GC_FEATURES0_DUAL_RETURN_BUS_AVAILABLE 0x1
+
+/* Configurable endianness support. */
+#define GC_FEATURES0_ENDIANNESS_CONFIG 2 : 2
+#define GC_FEATURES0_ENDIANNESS_CONFIG_End 2
+#define GC_FEATURES0_ENDIANNESS_CONFIG_Start 2
+#define GC_FEATURES0_ENDIANNESS_CONFIG_Type U01
+#define GC_FEATURES0_ENDIANNESS_CONFIG_NONE 0x0
+#define GC_FEATURES0_ENDIANNESS_CONFIG_AVAILABLE 0x1
+
+/* Supports 8Kx8K textures. */
+#define GC_FEATURES0_TEXTURE8_K 3 : 3
+#define GC_FEATURES0_TEXTURE8_K_End 3
+#define GC_FEATURES0_TEXTURE8_K_Start 3
+#define GC_FEATURES0_TEXTURE8_K_Type U01
+#define GC_FEATURES0_TEXTURE8_K_NONE 0x0
+#define GC_FEATURES0_TEXTURE8_K_AVAILABLE 0x1
+
+/* Driver hack is not needed. */
+#define GC_FEATURES0_CORRECT_TEXTURE_CONVERTER 4 : 4
+#define GC_FEATURES0_CORRECT_TEXTURE_CONVERTER_End 4
+#define GC_FEATURES0_CORRECT_TEXTURE_CONVERTER_Start 4
+#define GC_FEATURES0_CORRECT_TEXTURE_CONVERTER_Type U01
+#define GC_FEATURES0_CORRECT_TEXTURE_CONVERTER_NONE 0x0
+#define GC_FEATURES0_CORRECT_TEXTURE_CONVERTER_AVAILABLE 0x1
+
+/* Special LOD calculation when MSAA is on. */
+#define GC_FEATURES0_SPECIAL_MSAA_LOD 5 : 5
+#define GC_FEATURES0_SPECIAL_MSAA_LOD_End 5
+#define GC_FEATURES0_SPECIAL_MSAA_LOD_Start 5
+#define GC_FEATURES0_SPECIAL_MSAA_LOD_Type U01
+#define GC_FEATURES0_SPECIAL_MSAA_LOD_NONE 0x0
+#define GC_FEATURES0_SPECIAL_MSAA_LOD_AVAILABLE 0x1
+
+/* Proper flush is done in fast clear cache. */
+#define GC_FEATURES0_FAST_CLEAR_FLUSH 6 : 6
+#define GC_FEATURES0_FAST_CLEAR_FLUSH_End 6
+#define GC_FEATURES0_FAST_CLEAR_FLUSH_Start 6
+#define GC_FEATURES0_FAST_CLEAR_FLUSH_Type U01
+#define GC_FEATURES0_FAST_CLEAR_FLUSH_NONE 0x0
+#define GC_FEATURES0_FAST_CLEAR_FLUSH_AVAILABLE 0x1
+
+/* 2D PE 2.0 is present. */
+#define GC_FEATURES0_2DPE20 7 : 7
+#define GC_FEATURES0_2DPE20_End 7
+#define GC_FEATURES0_2DPE20_Start 7
+#define GC_FEATURES0_2DPE20_Type U01
+#define GC_FEATURES0_2DPE20_NONE 0x0
+#define GC_FEATURES0_2DPE20_AVAILABLE 0x1
+
+/* Reserved. */
+#define GC_FEATURES0_CORRECT_AUTO_DISABLE 8 : 8
+#define GC_FEATURES0_CORRECT_AUTO_DISABLE_End 8
+#define GC_FEATURES0_CORRECT_AUTO_DISABLE_Start 8
+#define GC_FEATURES0_CORRECT_AUTO_DISABLE_Type U01
+#define GC_FEATURES0_CORRECT_AUTO_DISABLE_NONE 0x0
+#define GC_FEATURES0_CORRECT_AUTO_DISABLE_AVAILABLE 0x1
+
+/* Supports 8K render target. */
+#define GC_FEATURES0_RENDER_8K 9 : 9
+#define GC_FEATURES0_RENDER_8K_End 9
+#define GC_FEATURES0_RENDER_8K_Start 9
+#define GC_FEATURES0_RENDER_8K_Type U01
+#define GC_FEATURES0_RENDER_8K_NONE 0x0
+#define GC_FEATURES0_RENDER_8K_AVAILABLE 0x1
+
+/* 2 bits are used instead of 4 bits for tile status. */
+#define GC_FEATURES0_TILE_STATUS_2BITS 10 : 10
+#define GC_FEATURES0_TILE_STATUS_2BITS_End 10
+#define GC_FEATURES0_TILE_STATUS_2BITS_Start 10
+#define GC_FEATURES0_TILE_STATUS_2BITS_Type U01
+#define GC_FEATURES0_TILE_STATUS_2BITS_NONE 0x0
+#define GC_FEATURES0_TILE_STATUS_2BITS_AVAILABLE 0x1
+
+/* Use 2 separate tile status buffers in interleaved mode. */
+#define GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED 11 : 11
+#define GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED_End 11
+#define GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED_Start 11
+#define GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED_Type U01
+#define GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED_NONE 0x0
+#define GC_FEATURES0_SEPARATE_TILE_STATUS_WHEN_INTERLEAVED_AVAILABLE 0x1
+
+/* 32x32 super tile is available. */
+#define GC_FEATURES0_SUPER_TILED_32X32 12 : 12
+#define GC_FEATURES0_SUPER_TILED_32X32_End 12
+#define GC_FEATURES0_SUPER_TILED_32X32_Start 12
+#define GC_FEATURES0_SUPER_TILED_32X32_Type U01
+#define GC_FEATURES0_SUPER_TILED_32X32_NONE 0x0
+#define GC_FEATURES0_SUPER_TILED_32X32_AVAILABLE 0x1
+
+/* Major updates to VG pipe (TS buffer tiling. State masking.). */
+#define GC_FEATURES0_VG_20 13 : 13
+#define GC_FEATURES0_VG_20_End 13
+#define GC_FEATURES0_VG_20_Start 13
+#define GC_FEATURES0_VG_20_Type U01
+#define GC_FEATURES0_VG_20_NONE 0x0
+#define GC_FEATURES0_VG_20_AVAILABLE 0x1
+
+/* New commands added to the tessellator. */
+#define GC_FEATURES0_TS_EXTENDED_COMMANDS 14 : 14
+#define GC_FEATURES0_TS_EXTENDED_COMMANDS_End 14
+#define GC_FEATURES0_TS_EXTENDED_COMMANDS_Start 14
+#define GC_FEATURES0_TS_EXTENDED_COMMANDS_Type U01
+#define GC_FEATURES0_TS_EXTENDED_COMMANDS_NONE 0x0
+#define GC_FEATURES0_TS_EXTENDED_COMMANDS_AVAILABLE 0x1
+
+/* If this bit is not set, the FIFO counter should be set to 50. Else, the **
+** default should remain. */
+#define GC_FEATURES0_COMPRESSION_FIFO_FIXED 15 : 15
+#define GC_FEATURES0_COMPRESSION_FIFO_FIXED_End 15
+#define GC_FEATURES0_COMPRESSION_FIFO_FIXED_Start 15
+#define GC_FEATURES0_COMPRESSION_FIFO_FIXED_Type U01
+#define GC_FEATURES0_COMPRESSION_FIFO_FIXED_NONE 0x0
+#define GC_FEATURES0_COMPRESSION_FIFO_FIXED_AVAILABLE 0x1
+
+/* Floor, ceil, and sign instructions are available. */
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0 16 : 16
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0_End 16
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0_Start 16
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0_Type U01
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0_NONE 0x0
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS0_AVAILABLE 0x1
+
+/* VG filter is available. */
+#define GC_FEATURES0_VG_FILTER 17 : 17
+#define GC_FEATURES0_VG_FILTER_End 17
+#define GC_FEATURES0_VG_FILTER_Start 17
+#define GC_FEATURES0_VG_FILTER_Type U01
+#define GC_FEATURES0_VG_FILTER_NONE 0x0
+#define GC_FEATURES0_VG_FILTER_AVAILABLE 0x1
+
+/* Minor updates to VG pipe (Event generation from VG, TS, PE). Tiled image **
+** support. */
+#define GC_FEATURES0_VG_21 18 : 18
+#define GC_FEATURES0_VG_21_End 18
+#define GC_FEATURES0_VG_21_Start 18
+#define GC_FEATURES0_VG_21_Type U01
+#define GC_FEATURES0_VG_21_NONE 0x0
+#define GC_FEATURES0_VG_21_AVAILABLE 0x1
+
+/* W is sent to SH from RA. */
+#define GC_FEATURES0_SHADER_GETS_W 19 : 19
+#define GC_FEATURES0_SHADER_GETS_W_End 19
+#define GC_FEATURES0_SHADER_GETS_W_Start 19
+#define GC_FEATURES0_SHADER_GETS_W_Type U01
+#define GC_FEATURES0_SHADER_GETS_W_NONE 0x0
+#define GC_FEATURES0_SHADER_GETS_W_AVAILABLE 0x1
+
+/* Sqrt, sin, cos instructions are available. */
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1 20 : 20
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1_End 20
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1_Start 20
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1_Type U01
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1_NONE 0x0
+#define GC_FEATURES0_EXTRA_SHADER_INSTRUCTIONS1_AVAILABLE 0x1
+
+/* Unavailable registers will return 0. */
+#define GC_FEATURES0_DEFAULT_REG0 21 : 21
+#define GC_FEATURES0_DEFAULT_REG0_End 21
+#define GC_FEATURES0_DEFAULT_REG0_Start 21
+#define GC_FEATURES0_DEFAULT_REG0_Type U01
+#define GC_FEATURES0_DEFAULT_REG0_NONE 0x0
+#define GC_FEATURES0_DEFAULT_REG0_AVAILABLE 0x1
+
+/* New style MC with separate paths for color and depth. */
+#define GC_FEATURES0_MC_20 22 : 22
+#define GC_FEATURES0_MC_20_End 22
+#define GC_FEATURES0_MC_20_Start 22
+#define GC_FEATURES0_MC_20_Type U01
+#define GC_FEATURES0_MC_20_NONE 0x0
+#define GC_FEATURES0_MC_20_AVAILABLE 0x1
+
+/* Put the MSAA data into sideband fifo. */
+#define GC_FEATURES0_SHADER_MSAA_SIDEBAND 23 : 23
+#define GC_FEATURES0_SHADER_MSAA_SIDEBAND_End 23
+#define GC_FEATURES0_SHADER_MSAA_SIDEBAND_Start 23
+#define GC_FEATURES0_SHADER_MSAA_SIDEBAND_Type U01
+#define GC_FEATURES0_SHADER_MSAA_SIDEBAND_NONE 0x0
+#define GC_FEATURES0_SHADER_MSAA_SIDEBAND_AVAILABLE 0x1
+
+#define GC_FEATURES0_BUG_FIXES0 24 : 24
+#define GC_FEATURES0_BUG_FIXES0_End 24
+#define GC_FEATURES0_BUG_FIXES0_Start 24
+#define GC_FEATURES0_BUG_FIXES0_Type U01
+#define GC_FEATURES0_BUG_FIXES0_NONE 0x0
+#define GC_FEATURES0_BUG_FIXES0_AVAILABLE 0x1
+
+/* VAA is available or not. */
+#define GC_FEATURES0_VAA 25 : 25
+#define GC_FEATURES0_VAA_End 25
+#define GC_FEATURES0_VAA_Start 25
+#define GC_FEATURES0_VAA_Type U01
+#define GC_FEATURES0_VAA_NONE 0x0
+#define GC_FEATURES0_VAA_AVAILABLE 0x1
+
+/* Shader supports bypass mode when MSAA is enabled. */
+#define GC_FEATURES0_BYPASS_IN_MSAA 26 : 26
+#define GC_FEATURES0_BYPASS_IN_MSAA_End 26
+#define GC_FEATURES0_BYPASS_IN_MSAA_Start 26
+#define GC_FEATURES0_BYPASS_IN_MSAA_Type U01
+#define GC_FEATURES0_BYPASS_IN_MSAA_NONE 0x0
+#define GC_FEATURES0_BYPASS_IN_MSAA_AVAILABLE 0x1
+
+/* Hierarchiccal Z is supported. */
+#define GC_FEATURES0_HIERARCHICAL_Z 27 : 27
+#define GC_FEATURES0_HIERARCHICAL_Z_End 27
+#define GC_FEATURES0_HIERARCHICAL_Z_Start 27
+#define GC_FEATURES0_HIERARCHICAL_Z_Type U01
+#define GC_FEATURES0_HIERARCHICAL_Z_NONE 0x0
+#define GC_FEATURES0_HIERARCHICAL_Z_AVAILABLE 0x1
+
+/* New texture unit is available. */
+#define GC_FEATURES0_NEW_TEXTURE 28 : 28
+#define GC_FEATURES0_NEW_TEXTURE_End 28
+#define GC_FEATURES0_NEW_TEXTURE_Start 28
+#define GC_FEATURES0_NEW_TEXTURE_Type U01
+#define GC_FEATURES0_NEW_TEXTURE_NONE 0x0
+#define GC_FEATURES0_NEW_TEXTURE_AVAILABLE 0x1
+
+/* 2D engine supports A8 target. */
+#define GC_FEATURES0_A8_TARGET_SUPPORT 29 : 29
+#define GC_FEATURES0_A8_TARGET_SUPPORT_End 29
+#define GC_FEATURES0_A8_TARGET_SUPPORT_Start 29
+#define GC_FEATURES0_A8_TARGET_SUPPORT_Type U01
+#define GC_FEATURES0_A8_TARGET_SUPPORT_NONE 0x0
+#define GC_FEATURES0_A8_TARGET_SUPPORT_AVAILABLE 0x1
+
+/* Correct stencil behavior in depth only. */
+#define GC_FEATURES0_CORRECT_STENCIL 30 : 30
+#define GC_FEATURES0_CORRECT_STENCIL_End 30
+#define GC_FEATURES0_CORRECT_STENCIL_Start 30
+#define GC_FEATURES0_CORRECT_STENCIL_Type U01
+#define GC_FEATURES0_CORRECT_STENCIL_NONE 0x0
+#define GC_FEATURES0_CORRECT_STENCIL_AVAILABLE 0x1
+
+/* Enhance VR and add a mode to walk 16 pixels in 16-bit mode in Vertical **
+** pass to improve $ hit rate when rotating 90/270. */
+#define GC_FEATURES0_ENHANCE_VR 31 : 31
+#define GC_FEATURES0_ENHANCE_VR_End 31
+#define GC_FEATURES0_ENHANCE_VR_Start 31
+#define GC_FEATURES0_ENHANCE_VR_Type U01
+#define GC_FEATURES0_ENHANCE_VR_NONE 0x0
+#define GC_FEATURES0_ENHANCE_VR_AVAILABLE 0x1
+
+union gcfeatures0 {
+ struct {
+ /* GC_FEATURES0_Address:FLIP_Y */
+ unsigned int flipy:1;
+
+ /* GC_FEATURES0_Address:DUAL_RETURN_BUS */
+ unsigned int dualreturnbus:1;
+
+ /* GC_FEATURES0_Address:ENDIANNESS_CONFIG */
+ unsigned int endianessconfig:1;
+
+ /* GC_FEATURES0_Address:TEXTURE8_K */
+ unsigned int texture8k:1;
+
+ /* GC_FEATURES0_Address:CORRECT_TEXTURE_CONVERTER */
+ unsigned int correcttextureconverter:1;
+
+ /* GC_FEATURES0_Address:SPECIAL_MSAA_LOD */
+ unsigned int specialmsaalod:1;
+
+ /* GC_FEATURES0_Address:FAST_CLEAR_FLUSH */
+ unsigned int fastclearflush:1;
+
+ /* GC_FEATURES0_Address:2DPE20 */
+ unsigned int pe2d20:1;
+
+ /* GC_FEATURES0_Address:CORRECT_AUTO_DISABLE */
+ unsigned int correctautodisable:1;
+
+ /* GC_FEATURES0_Address:RENDER_8K */
+ unsigned int render8k:1;
+
+ /* GC_FEATURES0_Address:TILE_STATUS_2BITS */
+ unsigned int tilestatus2bits:1;
+
+ /* GC_FEATURES0_Address:SEPARATE_TILE_STATUS_WHEN_INTERLEAVED */
+ unsigned int separatetilestatus:1;
+
+ /* GC_FEATURES0_Address:SUPER_TILED_32X32 */
+ unsigned int supertiled32x32:1;
+
+ /* GC_FEATURES0_Address:VG_20 */
+ unsigned int vg20:1;
+
+ /* GC_FEATURES0_Address:TS_EXTENDED_COMMANDS */
+ unsigned int tsplus:1;
+
+ /* GC_FEATURES0_Address:COMPRESSION_FIFO_FIXED */
+ unsigned int compressionfifo:1;
+
+ /* GC_FEATURES0_Address:EXTRA_SHADER_INSTRUCTIONS0 */
+ unsigned int shaderinst0:1;
+
+ /* GC_FEATURES0_Address:VG_FILTER */
+ unsigned int vgfilter:1;
+
+ /* GC_FEATURES0_Address:VG_21 */
+ unsigned int vg21:1;
+
+ /* GC_FEATURES0_Address:SHADER_GETS_W */
+ unsigned int shadergetsw:1;
+
+ /* GC_FEATURES0_Address:EXTRA_SHADER_INSTRUCTIONS1 */
+ unsigned int shaderinst1:1;
+
+ /* GC_FEATURES0_Address:DEFAULT_REG0 */
+ unsigned int defaultreg0:1;
+
+ /* GC_FEATURES0_Address:MC_20 */
+ unsigned int mc20:1;
+
+ /* GC_FEATURES0_Address:SHADER_MSAA_SIDEBAND */
+ unsigned int shadermsaasideband:1;
+
+ /* GC_FEATURES0_Address:BUG_FIXES0 */
+ unsigned int bugfixes0:1;
+
+ /* GC_FEATURES0_Address:VAA */
+ unsigned int vaa:1;
+
+ /* GC_FEATURES0_Address:BYPASS_IN_MSAA */
+ unsigned int bypassmsaa:1;
+
+ /* GC_FEATURES0_Address:HIERARCHICAL_Z */
+ unsigned int hz:1;
+
+ /* GC_FEATURES0_Address:NEW_TEXTURE */
+ unsigned int newtx:1;
+
+ /* GC_FEATURES0_Address:A8_TARGET_SUPPORT */
+ unsigned int a8target:1;
+
+ /* GC_FEATURES0_Address:CORRECT_STENCIL */
+ unsigned int correctstencil:1;
+
+ /* GC_FEATURES0_Address:ENHANCE_VR */
+ unsigned int vr20:1;
+ } reg;
+
+ unsigned int raw;
+};
+
+/*******************************************************************************
+** Register GCMinorFeatures1
+*/
+
+/* Shows which features are enabled in this chip. This register has no set
+** reset value. It varies with the implementation.
+*/
+
+#define GC_FEATURES1_Address 0x00074
+#define GC_FEATURES1_MSB 15
+#define GC_FEATURES1_LSB 0
+#define GC_FEATURES1_BLK 0
+#define GC_FEATURES1_Count 1
+#define GC_FEATURES1_FieldMask 0xFFFFFFFF
+#define GC_FEATURES1_ReadMask 0xFFFFFFFF
+#define GC_FEATURES1_WriteMask 0x00000000
+#define GC_FEATURES1_ResetValue 0x00000000
+
+/* Resolve UV swizzle. */
+#define GC_FEATURES1_RSUV_SWIZZLE 0 : 0
+#define GC_FEATURES1_RSUV_SWIZZLE_End 0
+#define GC_FEATURES1_RSUV_SWIZZLE_Start 0
+#define GC_FEATURES1_RSUV_SWIZZLE_Type U01
+#define GC_FEATURES1_RSUV_SWIZZLE_NONE 0x0
+#define GC_FEATURES1_RSUV_SWIZZLE_AVAILABLE 0x1
+
+/* V2 compression. */
+#define GC_FEATURES1_V2_COMPRESSION 1 : 1
+#define GC_FEATURES1_V2_COMPRESSION_End 1
+#define GC_FEATURES1_V2_COMPRESSION_Start 1
+#define GC_FEATURES1_V2_COMPRESSION_Type U01
+#define GC_FEATURES1_V2_COMPRESSION_NONE 0x0
+#define GC_FEATURES1_V2_COMPRESSION_AVAILABLE 0x1
+
+/* Double buffering support for VG (second TS-->VG semaphore is present). */
+#define GC_FEATURES1_VG_DOUBLE_BUFFER 2 : 2
+#define GC_FEATURES1_VG_DOUBLE_BUFFER_End 2
+#define GC_FEATURES1_VG_DOUBLE_BUFFER_Start 2
+#define GC_FEATURES1_VG_DOUBLE_BUFFER_Type U01
+#define GC_FEATURES1_VG_DOUBLE_BUFFER_NONE 0x0
+#define GC_FEATURES1_VG_DOUBLE_BUFFER_AVAILABLE 0x1
+
+#define GC_FEATURES1_BUG_FIXES1 3 : 3
+#define GC_FEATURES1_BUG_FIXES1_End 3
+#define GC_FEATURES1_BUG_FIXES1_Start 3
+#define GC_FEATURES1_BUG_FIXES1_Type U01
+#define GC_FEATURES1_BUG_FIXES1_NONE 0x0
+#define GC_FEATURES1_BUG_FIXES1_AVAILABLE 0x1
+
+#define GC_FEATURES1_BUG_FIXES2 4 : 4
+#define GC_FEATURES1_BUG_FIXES2_End 4
+#define GC_FEATURES1_BUG_FIXES2_Start 4
+#define GC_FEATURES1_BUG_FIXES2_Type U01
+#define GC_FEATURES1_BUG_FIXES2_NONE 0x0
+#define GC_FEATURES1_BUG_FIXES2_AVAILABLE 0x1
+
+/* Texture has stride and memory addressing. */
+#define GC_FEATURES1_TEXTURE_STRIDE 5 : 5
+#define GC_FEATURES1_TEXTURE_STRIDE_End 5
+#define GC_FEATURES1_TEXTURE_STRIDE_Start 5
+#define GC_FEATURES1_TEXTURE_STRIDE_Type U01
+#define GC_FEATURES1_TEXTURE_STRIDE_NONE 0x0
+#define GC_FEATURES1_TEXTURE_STRIDE_AVAILABLE 0x1
+
+#define GC_FEATURES1_BUG_FIXES3 6 : 6
+#define GC_FEATURES1_BUG_FIXES3_End 6
+#define GC_FEATURES1_BUG_FIXES3_Start 6
+#define GC_FEATURES1_BUG_FIXES3_Type U01
+#define GC_FEATURES1_BUG_FIXES3_NONE 0x0
+#define GC_FEATURES1_BUG_FIXES3_AVAILABLE 0x1
+
+#define GC_FEATURES1_CORRECT_AUTO_DISABLE 7 : 7
+#define GC_FEATURES1_CORRECT_AUTO_DISABLE_End 7
+#define GC_FEATURES1_CORRECT_AUTO_DISABLE_Start 7
+#define GC_FEATURES1_CORRECT_AUTO_DISABLE_Type U01
+#define GC_FEATURES1_CORRECT_AUTO_DISABLE_NONE 0x0
+#define GC_FEATURES1_CORRECT_AUTO_DISABLE_AVAILABLE 0x1
+
+#define GC_FEATURES1_AUTO_RESTART_TS 8 : 8
+#define GC_FEATURES1_AUTO_RESTART_TS_End 8
+#define GC_FEATURES1_AUTO_RESTART_TS_Start 8
+#define GC_FEATURES1_AUTO_RESTART_TS_Type U01
+#define GC_FEATURES1_AUTO_RESTART_TS_NONE 0x0
+#define GC_FEATURES1_AUTO_RESTART_TS_AVAILABLE 0x1
+
+#define GC_FEATURES1_BUG_FIXES4 9 : 9
+#define GC_FEATURES1_BUG_FIXES4_End 9
+#define GC_FEATURES1_BUG_FIXES4_Start 9
+#define GC_FEATURES1_BUG_FIXES4_Type U01
+#define GC_FEATURES1_BUG_FIXES4_NONE 0x0
+#define GC_FEATURES1_BUG_FIXES4_AVAILABLE 0x1
+
+#define GC_FEATURES1_L2_WINDOWING 10 : 10
+#define GC_FEATURES1_L2_WINDOWING_End 10
+#define GC_FEATURES1_L2_WINDOWING_Start 10
+#define GC_FEATURES1_L2_WINDOWING_Type U01
+#define GC_FEATURES1_L2_WINDOWING_NONE 0x0
+#define GC_FEATURES1_L2_WINDOWING_AVAILABLE 0x1
+
+#define GC_FEATURES1_HALF_FLOAT_PIPE 11 : 11
+#define GC_FEATURES1_HALF_FLOAT_PIPE_End 11
+#define GC_FEATURES1_HALF_FLOAT_PIPE_Start 11
+#define GC_FEATURES1_HALF_FLOAT_PIPE_Type U01
+#define GC_FEATURES1_HALF_FLOAT_PIPE_NONE 0x0
+#define GC_FEATURES1_HALF_FLOAT_PIPE_AVAILABLE 0x1
+
+#define GC_FEATURES1_PIXEL_DITHER 12 : 12
+#define GC_FEATURES1_PIXEL_DITHER_End 12
+#define GC_FEATURES1_PIXEL_DITHER_Start 12
+#define GC_FEATURES1_PIXEL_DITHER_Type U01
+#define GC_FEATURES1_PIXEL_DITHER_NONE 0x0
+#define GC_FEATURES1_PIXEL_DITHER_AVAILABLE 0x1
+
+#define GC_FEATURES1_TWO_STENCIL_REFERENCE 13 : 13
+#define GC_FEATURES1_TWO_STENCIL_REFERENCE_End 13
+#define GC_FEATURES1_TWO_STENCIL_REFERENCE_Start 13
+#define GC_FEATURES1_TWO_STENCIL_REFERENCE_Type U01
+#define GC_FEATURES1_TWO_STENCIL_REFERENCE_NONE 0x0
+#define GC_FEATURES1_TWO_STENCIL_REFERENCE_AVAILABLE 0x1
+
+#define GC_FEATURES1_EXTENDED_PIXEL_FORMAT 14 : 14
+#define GC_FEATURES1_EXTENDED_PIXEL_FORMAT_End 14
+#define GC_FEATURES1_EXTENDED_PIXEL_FORMAT_Start 14
+#define GC_FEATURES1_EXTENDED_PIXEL_FORMAT_Type U01
+#define GC_FEATURES1_EXTENDED_PIXEL_FORMAT_NONE 0x0
+#define GC_FEATURES1_EXTENDED_PIXEL_FORMAT_AVAILABLE 0x1
+
+/* EEZ and HZ are correct. */
+#define GC_FEATURES1_CORRECT_MIN_MAX_DEPTH 15 : 15
+#define GC_FEATURES1_CORRECT_MIN_MAX_DEPTH_End 15
+#define GC_FEATURES1_CORRECT_MIN_MAX_DEPTH_Start 15
+#define GC_FEATURES1_CORRECT_MIN_MAX_DEPTH_Type U01
+#define GC_FEATURES1_CORRECT_MIN_MAX_DEPTH_NONE 0x0
+#define GC_FEATURES1_CORRECT_MIN_MAX_DEPTH_AVAILABLE 0x1
+
+/* Dither and filter+alpha available. */
+#define GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D 16 : 16
+#define GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_End 16
+#define GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_Start 16
+#define GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_Type U01
+#define GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_NONE 0x0
+#define GC_FEATURES1_DITHER_AND_FILTER_PLUS_ALPHA_2D_AVAILABLE 0x1
+
+#define GC_FEATURES1_BUG_FIXES5 17 : 17
+#define GC_FEATURES1_BUG_FIXES5_End 17
+#define GC_FEATURES1_BUG_FIXES5_Start 17
+#define GC_FEATURES1_BUG_FIXES5_Type U01
+#define GC_FEATURES1_BUG_FIXES5_NONE 0x0
+#define GC_FEATURES1_BUG_FIXES5_AVAILABLE 0x1
+
+#define GC_FEATURES1_NEW_2D 18 : 18
+#define GC_FEATURES1_NEW_2D_End 18
+#define GC_FEATURES1_NEW_2D_Start 18
+#define GC_FEATURES1_NEW_2D_Type U01
+#define GC_FEATURES1_NEW_2D_NONE 0x0
+#define GC_FEATURES1_NEW_2D_AVAILABLE 0x1
+
+#define GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC 19 : 19
+#define GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_End 19
+#define GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_Start 19
+#define GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_Type U01
+#define GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_NONE 0x0
+#define GC_FEATURES1_NEW_FLOATING_POINT_ARITHMETIC_AVAILABLE 0x1
+
+#define GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT 20 : 20
+#define GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_End 20
+#define GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_Start 20
+#define GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_Type U01
+#define GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_NONE 0x0
+#define GC_FEATURES1_TEXTURE_HORIZONTAL_ALIGNMENT_SELECT_AVAILABLE 0x1
+
+#define GC_FEATURES1_NON_POWER_OF_TWO 21 : 21
+#define GC_FEATURES1_NON_POWER_OF_TWO_End 21
+#define GC_FEATURES1_NON_POWER_OF_TWO_Start 21
+#define GC_FEATURES1_NON_POWER_OF_TWO_Type U01
+#define GC_FEATURES1_NON_POWER_OF_TWO_NONE 0x0
+#define GC_FEATURES1_NON_POWER_OF_TWO_AVAILABLE 0x1
+
+#define GC_FEATURES1_LINEAR_TEXTURE_SUPPORT 22 : 22
+#define GC_FEATURES1_LINEAR_TEXTURE_SUPPORT_End 22
+#define GC_FEATURES1_LINEAR_TEXTURE_SUPPORT_Start 22
+#define GC_FEATURES1_LINEAR_TEXTURE_SUPPORT_Type U01
+#define GC_FEATURES1_LINEAR_TEXTURE_SUPPORT_NONE 0x0
+#define GC_FEATURES1_LINEAR_TEXTURE_SUPPORT_AVAILABLE 0x1
+
+#define GC_FEATURES1_HALTI0 23 : 23
+#define GC_FEATURES1_HALTI0_End 23
+#define GC_FEATURES1_HALTI0_Start 23
+#define GC_FEATURES1_HALTI0_Type U01
+#define GC_FEATURES1_HALTI0_NONE 0x0
+#define GC_FEATURES1_HALTI0_AVAILABLE 0x1
+
+#define GC_FEATURES1_CORRECT_OVERFLOW_VG 24 : 24
+#define GC_FEATURES1_CORRECT_OVERFLOW_VG_End 24
+#define GC_FEATURES1_CORRECT_OVERFLOW_VG_Start 24
+#define GC_FEATURES1_CORRECT_OVERFLOW_VG_Type U01
+#define GC_FEATURES1_CORRECT_OVERFLOW_VG_NONE 0x0
+#define GC_FEATURES1_CORRECT_OVERFLOW_VG_AVAILABLE 0x1
+
+#define GC_FEATURES1_NEGATIVE_LOG_FIX 25 : 25
+#define GC_FEATURES1_NEGATIVE_LOG_FIX_End 25
+#define GC_FEATURES1_NEGATIVE_LOG_FIX_Start 25
+#define GC_FEATURES1_NEGATIVE_LOG_FIX_Type U01
+#define GC_FEATURES1_NEGATIVE_LOG_FIX_NONE 0x0
+#define GC_FEATURES1_NEGATIVE_LOG_FIX_AVAILABLE 0x1
+
+#define GC_FEATURES1_RESOLVE_OFFSET 26 : 26
+#define GC_FEATURES1_RESOLVE_OFFSET_End 26
+#define GC_FEATURES1_RESOLVE_OFFSET_Start 26
+#define GC_FEATURES1_RESOLVE_OFFSET_Type U01
+#define GC_FEATURES1_RESOLVE_OFFSET_NONE 0x0
+#define GC_FEATURES1_RESOLVE_OFFSET_AVAILABLE 0x1
+
+#define GC_FEATURES1_OK_TO_GATE_AXI_CLOCK 27 : 27
+#define GC_FEATURES1_OK_TO_GATE_AXI_CLOCK_End 27
+#define GC_FEATURES1_OK_TO_GATE_AXI_CLOCK_Start 27
+#define GC_FEATURES1_OK_TO_GATE_AXI_CLOCK_Type U01
+#define GC_FEATURES1_OK_TO_GATE_AXI_CLOCK_NONE 0x0
+#define GC_FEATURES1_OK_TO_GATE_AXI_CLOCK_AVAILABLE 0x1
+
+#define GC_FEATURES1_MMU 28 : 28
+#define GC_FEATURES1_MMU_End 28
+#define GC_FEATURES1_MMU_Start 28
+#define GC_FEATURES1_MMU_Type U01
+#define GC_FEATURES1_MMU_NONE 0x0
+#define GC_FEATURES1_MMU_AVAILABLE 0x1
+
+#define GC_FEATURES1_WIDE_LINE 29 : 29
+#define GC_FEATURES1_WIDE_LINE_End 29
+#define GC_FEATURES1_WIDE_LINE_Start 29
+#define GC_FEATURES1_WIDE_LINE_Type U01
+#define GC_FEATURES1_WIDE_LINE_NONE 0x0
+#define GC_FEATURES1_WIDE_LINE_AVAILABLE 0x1
+
+#define GC_FEATURES1_BUG_FIXES6 30 : 30
+#define GC_FEATURES1_BUG_FIXES6_End 30
+#define GC_FEATURES1_BUG_FIXES6_Start 30
+#define GC_FEATURES1_BUG_FIXES6_Type U01
+#define GC_FEATURES1_BUG_FIXES6_NONE 0x0
+#define GC_FEATURES1_BUG_FIXES6_AVAILABLE 0x1
+
+#define GC_FEATURES1_FC_FLUSH_STALL 31 : 31
+#define GC_FEATURES1_FC_FLUSH_STALL_End 31
+#define GC_FEATURES1_FC_FLUSH_STALL_Start 31
+#define GC_FEATURES1_FC_FLUSH_STALL_Type U01
+#define GC_FEATURES1_FC_FLUSH_STALL_NONE 0x0
+#define GC_FEATURES1_FC_FLUSH_STALL_AVAILABLE 0x1
+
+union gcfeatures1 {
+ struct {
+ /* GC_FEATURES1_Address:RSUV_SWIZZLE */
+ unsigned int rsuvswizzle:1;
+
+ /* GC_FEATURES1_Address:V2_COMPRESSION */
+ unsigned int v2compression:1;
+
+ /* GC_FEATURES1_Address:VG_DOUBLE_BUFFER */
+ unsigned int vgdblbuffer:1;
+
+ /* GC_FEATURES1_Address:BUG_FIXES1 */
+ unsigned int bugfixes1:1;
+
+ /* GC_FEATURES1_Address:BUG_FIXES2 */
+ unsigned int bugfixes2:1;
+
+ /* GC_FEATURES1_Address:TEXTURE_STRIDE */
+ unsigned int txstride:1;
+
+ /* GC_FEATURES1_Address:BUG_FIXES3 */
+ unsigned int bugfixes3:1;
+
+ /* GC_FEATURES1_Address:CORRECT_AUTO_DISABLE */
+ unsigned int correctautodisable:1;
+
+ /* GC_FEATURES1_Address:AUTO_RESTART_TS */
+ unsigned int autorestartts:1;
+
+ /* GC_FEATURES1_Address:BUG_FIXES4 */
+ unsigned int bugfixes4:1;
+
+ /* GC_FEATURES1_Address:L2_WINDOWING */
+ unsigned int l2win:1;
+
+ /* GC_FEATURES1_Address:HALF_FLOAT_PIPE */
+ unsigned int halffloatpipe:1;
+
+ /* GC_FEATURES1_Address:PIXEL_DITHER */
+ unsigned int pixeldither:1;
+
+ /* GC_FEATURES1_Address:TWO_STENCIL_REFERENCE */
+ unsigned int twostencilref:1;
+
+ /* GC_FEATURES1_Address:EXTENDED_PIXEL_FORMAT */
+ unsigned int pixformatex:1;
+
+ /* GC_FEATURES1_Address:CORRECT_MIN_MAX_DEPTH */
+ unsigned int correctminmaxdepth:1;
+
+ /* GC_FEATURES1_Address:DITHER_AND_FILTER_PLUS_ALPHA_2D */
+ unsigned int ditherfilter:1;
+
+ /* GC_FEATURES1_Address:BUG_FIXES5 */
+ unsigned int bugfixes5:1;
+
+ /* GC_FEATURES1_Address:NEW_2D */
+ unsigned int new2d:1;
+
+ /* GC_FEATURES1_Address:NEW_FLOATING_POINT_ARITHMETIC */
+ unsigned int newfp:1;
+
+ /* GC_FEATURES1_Address:TEXTURE_HORIZONTAL_ALIGNMENT_SELECT */
+ unsigned int txalign:1;
+
+ /* GC_FEATURES1_Address:NON_POWER_OF_TWO */
+ unsigned int nonpowof2:1;
+
+ /* GC_FEATURES1_Address:LINEAR_TEXTURE_SUPPORT */
+ unsigned int lineartx:1;
+
+ /* GC_FEATURES1_Address:HALTI0 */
+ unsigned int halti0:1;
+
+ /* GC_FEATURES1_Address:CORRECT_OVERFLOW_VG */
+ unsigned int correctoverflowvg:1;
+
+ /* GC_FEATURES1_Address:NEGATIVE_LOG_FIX */
+ unsigned int neglogfix:1;
+
+ /* GC_FEATURES1_Address:RESOLVE_OFFSET */
+ unsigned int rsoffset:1;
+
+ /* GC_FEATURES1_Address:OK_TO_GATE_AXI_CLOCK */
+ unsigned int axiclockgating:1;
+
+ /* GC_FEATURES1_Address:MMU */
+ unsigned int mmu:1;
+
+ /* GC_FEATURES1_Address:WIDE_LINE */
+ unsigned int wideline:1;
+
+ /* GC_FEATURES1_Address:BUG_FIXES6 */
+ unsigned int bugfixes6:1;
+
+ /* GC_FEATURES1_Address:FC_FLUSH_STALL */
+ unsigned int fcflushstall:1;
+ } reg;
+
+ unsigned int raw;
+};
+
+/*******************************************************************************
+** Register GCMinorFeatures2
+*/
+
+/* Shows which features are enabled in this chip. This register has no set **
+** reset value. It varies with the implementation. */
+
+#define GC_FEATURES2_Address 0x00084
+#define GC_FEATURES2_MSB 15
+#define GC_FEATURES2_LSB 0
+#define GC_FEATURES2_BLK 0
+#define GC_FEATURES2_Count 1
+#define GC_FEATURES2_FieldMask 0xFFFFFFFF
+#define GC_FEATURES2_ReadMask 0xFFFFFFFF
+#define GC_FEATURES2_WriteMask 0x00000000
+#define GC_FEATURES2_ResetValue 0x00000000
+
+#define GC_FEATURES2_LINE_LOOP 0 : 0
+#define GC_FEATURES2_LINE_LOOP_End 0
+#define GC_FEATURES2_LINE_LOOP_Start 0
+#define GC_FEATURES2_LINE_LOOP_Type U01
+#define GC_FEATURES2_LINE_LOOP_NONE 0x0
+#define GC_FEATURES2_LINE_LOOP_AVAILABLE 0x1
+
+#define GC_FEATURES2_LOGIC_OP 1 : 1
+#define GC_FEATURES2_LOGIC_OP_End 1
+#define GC_FEATURES2_LOGIC_OP_Start 1
+#define GC_FEATURES2_LOGIC_OP_Type U01
+#define GC_FEATURES2_LOGIC_OP_NONE 0x0
+#define GC_FEATURES2_LOGIC_OP_AVAILABLE 0x1
+
+#define GC_FEATURES2_SEAMLESS_CUBE_MAP 2 : 2
+#define GC_FEATURES2_SEAMLESS_CUBE_MAP_End 2
+#define GC_FEATURES2_SEAMLESS_CUBE_MAP_Start 2
+#define GC_FEATURES2_SEAMLESS_CUBE_MAP_Type U01
+#define GC_FEATURES2_SEAMLESS_CUBE_MAP_NONE 0x0
+#define GC_FEATURES2_SEAMLESS_CUBE_MAP_AVAILABLE 0x1
+
+#define GC_FEATURES2_SUPER_TILED_TEXTURE 3 : 3
+#define GC_FEATURES2_SUPER_TILED_TEXTURE_End 3
+#define GC_FEATURES2_SUPER_TILED_TEXTURE_Start 3
+#define GC_FEATURES2_SUPER_TILED_TEXTURE_Type U01
+#define GC_FEATURES2_SUPER_TILED_TEXTURE_NONE 0x0
+#define GC_FEATURES2_SUPER_TILED_TEXTURE_AVAILABLE 0x1
+
+#define GC_FEATURES2_LINEAR_PE 4 : 4
+#define GC_FEATURES2_LINEAR_PE_End 4
+#define GC_FEATURES2_LINEAR_PE_Start 4
+#define GC_FEATURES2_LINEAR_PE_Type U01
+#define GC_FEATURES2_LINEAR_PE_NONE 0x0
+#define GC_FEATURES2_LINEAR_PE_AVAILABLE 0x1
+
+#define GC_FEATURES2_RECT_PRIMITIVE 5 : 5
+#define GC_FEATURES2_RECT_PRIMITIVE_End 5
+#define GC_FEATURES2_RECT_PRIMITIVE_Start 5
+#define GC_FEATURES2_RECT_PRIMITIVE_Type U01
+#define GC_FEATURES2_RECT_PRIMITIVE_NONE 0x0
+#define GC_FEATURES2_RECT_PRIMITIVE_AVAILABLE 0x1
+
+#define GC_FEATURES2_COMPOSITION 6 : 6
+#define GC_FEATURES2_COMPOSITION_End 6
+#define GC_FEATURES2_COMPOSITION_Start 6
+#define GC_FEATURES2_COMPOSITION_Type U01
+#define GC_FEATURES2_COMPOSITION_NONE 0x0
+#define GC_FEATURES2_COMPOSITION_AVAILABLE 0x1
+
+#define GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH 7 : 7
+#define GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH_End 7
+#define GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH_Start 7
+#define GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH_Type U01
+#define GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH_NONE 0x0
+#define GC_FEATURES2_CORRECT_AUTO_DISABLE_COUNT_WIDTH_AVAILABLE 0x1
+
+#define GC_FEATURES2_PE_SWIZZLE 8 : 8
+#define GC_FEATURES2_PE_SWIZZLE_End 8
+#define GC_FEATURES2_PE_SWIZZLE_Start 8
+#define GC_FEATURES2_PE_SWIZZLE_Type U01
+#define GC_FEATURES2_PE_SWIZZLE_NONE 0x0
+#define GC_FEATURES2_PE_SWIZZLE_AVAILABLE 0x1
+
+#define GC_FEATURES2_END_EVENT 9 : 9
+#define GC_FEATURES2_END_EVENT_End 9
+#define GC_FEATURES2_END_EVENT_Start 9
+#define GC_FEATURES2_END_EVENT_Type U01
+#define GC_FEATURES2_END_EVENT_NONE 0x0
+#define GC_FEATURES2_END_EVENT_AVAILABLE 0x1
+
+#define GC_FEATURES2_S1S8 10 : 10
+#define GC_FEATURES2_S1S8_End 10
+#define GC_FEATURES2_S1S8_Start 10
+#define GC_FEATURES2_S1S8_Type U01
+#define GC_FEATURES2_S1S8_NONE 0x0
+#define GC_FEATURES2_S1S8_AVAILABLE 0x1
+
+#define GC_FEATURES2_HALTI1 11 : 11
+#define GC_FEATURES2_HALTI1_End 11
+#define GC_FEATURES2_HALTI1_Start 11
+#define GC_FEATURES2_HALTI1_Type U01
+#define GC_FEATURES2_HALTI1_NONE 0x0
+#define GC_FEATURES2_HALTI1_AVAILABLE 0x1
+
+#define GC_FEATURES2_RGB888 12 : 12
+#define GC_FEATURES2_RGB888_End 12
+#define GC_FEATURES2_RGB888_Start 12
+#define GC_FEATURES2_RGB888_Type U01
+#define GC_FEATURES2_RGB888_NONE 0x0
+#define GC_FEATURES2_RGB888_AVAILABLE 0x1
+
+#define GC_FEATURES2_TX__YUV_ASSEMBLER 13 : 13
+#define GC_FEATURES2_TX__YUV_ASSEMBLER_End 13
+#define GC_FEATURES2_TX__YUV_ASSEMBLER_Start 13
+#define GC_FEATURES2_TX__YUV_ASSEMBLER_Type U01
+#define GC_FEATURES2_TX__YUV_ASSEMBLER_NONE 0x0
+#define GC_FEATURES2_TX__YUV_ASSEMBLER_AVAILABLE 0x1
+
+#define GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING 14 : 14
+#define GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING_End 14
+#define GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING_Start 14
+#define GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING_Type U01
+#define GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING_NONE 0x0
+#define GC_FEATURES2_DYNAMIC_FREQUENCY_SCALING_AVAILABLE 0x1
+
+#define GC_FEATURES2_TX_FILTER 15 : 15
+#define GC_FEATURES2_TX_FILTER_End 15
+#define GC_FEATURES2_TX_FILTER_Start 15
+#define GC_FEATURES2_TX_FILTER_Type U01
+#define GC_FEATURES2_TX_FILTER_NONE 0x0
+#define GC_FEATURES2_TX_FILTER_AVAILABLE 0x1
+
+#define GC_FEATURES2_FULL_DIRECT_FB 16 : 16
+#define GC_FEATURES2_FULL_DIRECT_FB_End 16
+#define GC_FEATURES2_FULL_DIRECT_FB_Start 16
+#define GC_FEATURES2_FULL_DIRECT_FB_Type U01
+#define GC_FEATURES2_FULL_DIRECT_FB_NONE 0x0
+#define GC_FEATURES2_FULL_DIRECT_FB_AVAILABLE 0x1
+
+#define GC_FEATURES2_ONE_PASS_2D_FILTER 17 : 17
+#define GC_FEATURES2_ONE_PASS_2D_FILTER_End 17
+#define GC_FEATURES2_ONE_PASS_2D_FILTER_Start 17
+#define GC_FEATURES2_ONE_PASS_2D_FILTER_Type U01
+#define GC_FEATURES2_ONE_PASS_2D_FILTER_NONE 0x0
+#define GC_FEATURES2_ONE_PASS_2D_FILTER_AVAILABLE 0x1
+
+#define GC_FEATURES2_THREAD_WALKER_IN_PS 18 : 18
+#define GC_FEATURES2_THREAD_WALKER_IN_PS_End 18
+#define GC_FEATURES2_THREAD_WALKER_IN_PS_Start 18
+#define GC_FEATURES2_THREAD_WALKER_IN_PS_Type U01
+#define GC_FEATURES2_THREAD_WALKER_IN_PS_NONE 0x0
+#define GC_FEATURES2_THREAD_WALKER_IN_PS_AVAILABLE 0x1
+
+#define GC_FEATURES2_TILE_FILLER 19 : 19
+#define GC_FEATURES2_TILE_FILLER_End 19
+#define GC_FEATURES2_TILE_FILLER_Start 19
+#define GC_FEATURES2_TILE_FILLER_Type U01
+#define GC_FEATURES2_TILE_FILLER_NONE 0x0
+#define GC_FEATURES2_TILE_FILLER_AVAILABLE 0x1
+
+#define GC_FEATURES2_YUV_STANDARD 20 : 20
+#define GC_FEATURES2_YUV_STANDARD_End 20
+#define GC_FEATURES2_YUV_STANDARD_Start 20
+#define GC_FEATURES2_YUV_STANDARD_Type U01
+#define GC_FEATURES2_YUV_STANDARD_NONE 0x0
+#define GC_FEATURES2_YUV_STANDARD_AVAILABLE 0x1
+
+#define GC_FEATURES2_MULTI_SOURCE_BLT 21 : 21
+#define GC_FEATURES2_MULTI_SOURCE_BLT_End 21
+#define GC_FEATURES2_MULTI_SOURCE_BLT_Start 21
+#define GC_FEATURES2_MULTI_SOURCE_BLT_Type U01
+#define GC_FEATURES2_MULTI_SOURCE_BLT_NONE 0x0
+#define GC_FEATURES2_MULTI_SOURCE_BLT_AVAILABLE 0x1
+
+#define GC_FEATURES2_YUV_CONVERSION 22 : 22
+#define GC_FEATURES2_YUV_CONVERSION_End 22
+#define GC_FEATURES2_YUV_CONVERSION_Start 22
+#define GC_FEATURES2_YUV_CONVERSION_Type U01
+#define GC_FEATURES2_YUV_CONVERSION_NONE 0x0
+#define GC_FEATURES2_YUV_CONVERSION_AVAILABLE 0x1
+
+#define GC_FEATURES2_FLUSH_FIXED_2D 23 : 23
+#define GC_FEATURES2_FLUSH_FIXED_2D_End 23
+#define GC_FEATURES2_FLUSH_FIXED_2D_Start 23
+#define GC_FEATURES2_FLUSH_FIXED_2D_Type U01
+#define GC_FEATURES2_FLUSH_FIXED_2D_NONE 0x0
+#define GC_FEATURES2_FLUSH_FIXED_2D_AVAILABLE 0x1
+
+#define GC_FEATURES2_INTERLEAVER 24 : 24
+#define GC_FEATURES2_INTERLEAVER_End 24
+#define GC_FEATURES2_INTERLEAVER_Start 24
+#define GC_FEATURES2_INTERLEAVER_Type U01
+#define GC_FEATURES2_INTERLEAVER_NONE 0x0
+#define GC_FEATURES2_INTERLEAVER_AVAILABLE 0x1
+
+#define GC_FEATURES2_MIXED_STREAMS 25 : 25
+#define GC_FEATURES2_MIXED_STREAMS_End 25
+#define GC_FEATURES2_MIXED_STREAMS_Start 25
+#define GC_FEATURES2_MIXED_STREAMS_Type U01
+#define GC_FEATURES2_MIXED_STREAMS_NONE 0x0
+#define GC_FEATURES2_MIXED_STREAMS_AVAILABLE 0x1
+
+#define GC_FEATURES2_L2_CACHE_FOR_2D_420 26 : 26
+#define GC_FEATURES2_L2_CACHE_FOR_2D_420_End 26
+#define GC_FEATURES2_L2_CACHE_FOR_2D_420_Start 26
+#define GC_FEATURES2_L2_CACHE_FOR_2D_420_Type U01
+#define GC_FEATURES2_L2_CACHE_FOR_2D_420_NONE 0x0
+#define GC_FEATURES2_L2_CACHE_FOR_2D_420_AVAILABLE 0x1
+
+#define GC_FEATURES2_BUG_FIXES7 27 : 27
+#define GC_FEATURES2_BUG_FIXES7_End 27
+#define GC_FEATURES2_BUG_FIXES7_Start 27
+#define GC_FEATURES2_BUG_FIXES7_Type U01
+#define GC_FEATURES2_BUG_FIXES7_NONE 0x0
+#define GC_FEATURES2_BUG_FIXES7_AVAILABLE 0x1
+
+#define GC_FEATURES2_NO_INDEX_PATTERN 28 : 28
+#define GC_FEATURES2_NO_INDEX_PATTERN_End 28
+#define GC_FEATURES2_NO_INDEX_PATTERN_Start 28
+#define GC_FEATURES2_NO_INDEX_PATTERN_Type U01
+#define GC_FEATURES2_NO_INDEX_PATTERN_NONE 0x0
+#define GC_FEATURES2_NO_INDEX_PATTERN_AVAILABLE 0x1
+
+#define GC_FEATURES2_TEXTURE_TILE_STATUS 29 : 29
+#define GC_FEATURES2_TEXTURE_TILE_STATUS_End 29
+#define GC_FEATURES2_TEXTURE_TILE_STATUS_Start 29
+#define GC_FEATURES2_TEXTURE_TILE_STATUS_Type U01
+#define GC_FEATURES2_TEXTURE_TILE_STATUS_NONE 0x0
+#define GC_FEATURES2_TEXTURE_TILE_STATUS_AVAILABLE 0x1
+
+#define GC_FEATURES2_DECOMPRESS_Z16 30 : 30
+#define GC_FEATURES2_DECOMPRESS_Z16_End 30
+#define GC_FEATURES2_DECOMPRESS_Z16_Start 30
+#define GC_FEATURES2_DECOMPRESS_Z16_Type U01
+#define GC_FEATURES2_DECOMPRESS_Z16_NONE 0x0
+#define GC_FEATURES2_DECOMPRESS_Z16_AVAILABLE 0x1
+
+#define GC_FEATURES2_BUG_FIXES8 31 : 31
+#define GC_FEATURES2_BUG_FIXES8_End 31
+#define GC_FEATURES2_BUG_FIXES8_Start 31
+#define GC_FEATURES2_BUG_FIXES8_Type U01
+#define GC_FEATURES2_BUG_FIXES8_NONE 0x0
+#define GC_FEATURES2_BUG_FIXES8_AVAILABLE 0x1
+
+union gcfeatures2 {
+ struct {
+ /* GC_FEATURES2_Address:LINE_LOOP */
+ unsigned int lineloop:1;
+
+ /* GC_FEATURES2_Address:LOGIC_OP */
+ unsigned int logop:1;
+
+ /* GC_FEATURES2_Address:SEAMLESS_CUBE_MAP */
+ unsigned int cubemap:1;
+
+ /* GC_FEATURES2_Address:SUPER_TILED_TEXTURE */
+ unsigned int supertiledtx:1;
+
+ /* GC_FEATURES2_Address:LINEAR_PE */
+ unsigned int linearpe:1;
+
+ /* GC_FEATURES2_Address:RECT_PRIMITIVE */
+ unsigned int rectprim:1;
+
+ /* GC_FEATURES2_Address:COMPOSITION */
+ unsigned int composition:1;
+
+ /* GC_FEATURES2_Address:CORRECT_AUTO_DISABLE_COUNT_WIDTH */
+ unsigned int correctcountwidth:1;
+
+ /* GC_FEATURES2_Address:PE_SWIZZLE */
+ unsigned int peswizzle:1;
+
+ /* GC_FEATURES2_Address:END_EVENT */
+ unsigned int endevent:1;
+
+ /* GC_FEATURES2_Address:S1S8 */
+ unsigned int s1s8:1;
+
+ /* GC_FEATURES2_Address:HALTI1 */
+ unsigned int halti1:1;
+
+ /* GC_FEATURES2_Address:RGB888 */
+ unsigned int rgb888:1;
+
+ /* GC_FEATURES2_Address:TX__YUV_ASSEMBLER */
+ unsigned int txyuvasm:1;
+
+ /* GC_FEATURES2_Address:DYNAMIC_FREQUENCY_SCALING */
+ unsigned int dynscaling:1;
+
+ /* GC_FEATURES2_Address:TX_FILTER */
+ unsigned int txfilter:1;
+
+ /* GC_FEATURES2_Address:FULL_DIRECT_FB */
+ unsigned int dfb:1;
+
+ /* GC_FEATURES2_Address:ONE_PASS_2D_FILTER */
+ unsigned int onepassfilter:1;
+
+ /* GC_FEATURES2_Address:THREAD_WALKER_IN_PS */
+ unsigned int pstw:1;
+
+ /* GC_FEATURES2_Address:TILE_FILLER */
+ unsigned int tilefiller:1;
+
+ /* GC_FEATURES2_Address:YUV_STANDARD */
+ unsigned int yuvstd:1;
+
+ /* GC_FEATURES2_Address:MULTI_SOURCE_BLT */
+ unsigned int multisrc:1;
+
+ /* GC_FEATURES2_Address:YUV_CONVERSION */
+ unsigned int yuvconvert:1;
+
+ /* GC_FEATURES2_Address:FLUSH_FIXED_2D */
+ unsigned int flushfixed2d:1;
+
+ /* GC_FEATURES2_Address:INTERLEAVER */
+ unsigned int interleaver:1;
+
+ /* GC_FEATURES2_Address:MIXED_STREAMS */
+ unsigned int mixedstreams:1;
+
+ /* GC_FEATURES2_Address:L2_CACHE_FOR_2D_420 */
+ unsigned int l2cachefor420:1;
+
+ /* GC_FEATURES2_Address:BUG_FIXES7 */
+ unsigned int bugfixes7:1;
+
+ /* GC_FEATURES2_Address:NO_INDEX_PATTERN */
+ unsigned int noindexpatern:1;
+
+ /* GC_FEATURES2_Address:TEXTURE_TILE_STATUS */
+ unsigned int tilestatustx:1;
+
+ /* GC_FEATURES2_Address:DECOMPRESS_Z16 */
+ unsigned int decompressz16:1;
+
+ /* GC_FEATURES2_Address:BUG_FIXES8 */
+ unsigned int bugfixes8:1;
+ } reg;
+
+ unsigned int raw;
+};
+
+/*******************************************************************************
+** Register GCMinorFeatures3
+*/
+
+/* Shows which features are enabled in this chip. This register has no set **
+** reset value, it varies with the implementation. */
+
+#define GC_FEATURES3_Address 0x00088
+#define GC_FEATURES3_MSB 15
+#define GC_FEATURES3_LSB 0
+#define GC_FEATURES3_BLK 0
+#define GC_FEATURES3_Count 1
+#define GC_FEATURES3_FieldMask 0x003FFFFF
+#define GC_FEATURES3_ReadMask 0x003FFFFF
+#define GC_FEATURES3_WriteMask 0x00000000
+#define GC_FEATURES3_ResetValue 0x00000000
+
+#define GC_FEATURES3_DE_ROTATION_STALL_FIX 0 : 0
+#define GC_FEATURES3_DE_ROTATION_STALL_FIX_End 0
+#define GC_FEATURES3_DE_ROTATION_STALL_FIX_Start 0
+#define GC_FEATURES3_DE_ROTATION_STALL_FIX_Type U01
+#define GC_FEATURES3_DE_ROTATION_STALL_FIX_NONE 0x0
+#define GC_FEATURES3_DE_ROTATION_STALL_FIX_AVAILABLE 0x1
+
+#define GC_FEATURES3_OCL_ONLY 1 : 1
+#define GC_FEATURES3_OCL_ONLY_End 1
+#define GC_FEATURES3_OCL_ONLY_Start 1
+#define GC_FEATURES3_OCL_ONLY_Type U01
+#define GC_FEATURES3_OCL_ONLY_NONE 0x0
+#define GC_FEATURES3_OCL_ONLY_AVAILABLE 0x1
+
+#define GC_FEATURES3_NEW_FEATURES0 2 : 2
+#define GC_FEATURES3_NEW_FEATURES0_End 2
+#define GC_FEATURES3_NEW_FEATURES0_Start 2
+#define GC_FEATURES3_NEW_FEATURES0_Type U01
+#define GC_FEATURES3_NEW_FEATURES0_NONE 0x0
+#define GC_FEATURES3_NEW_FEATURES0_AVAILABLE 0x1
+
+#define GC_FEATURES3_INSTRUCTION_CACHE 3 : 3
+#define GC_FEATURES3_INSTRUCTION_CACHE_End 3
+#define GC_FEATURES3_INSTRUCTION_CACHE_Start 3
+#define GC_FEATURES3_INSTRUCTION_CACHE_Type U01
+#define GC_FEATURES3_INSTRUCTION_CACHE_NONE 0x0
+#define GC_FEATURES3_INSTRUCTION_CACHE_AVAILABLE 0x1
+
+#define GC_FEATURES3_GEOMETRY_SHADER 4 : 4
+#define GC_FEATURES3_GEOMETRY_SHADER_End 4
+#define GC_FEATURES3_GEOMETRY_SHADER_Start 4
+#define GC_FEATURES3_GEOMETRY_SHADER_Type U01
+#define GC_FEATURES3_GEOMETRY_SHADER_NONE 0x0
+#define GC_FEATURES3_GEOMETRY_SHADER_AVAILABLE 0x1
+
+#define GC_FEATURES3_TEX_COMPRESSION_SUPERTILED 5 : 5
+#define GC_FEATURES3_TEX_COMPRESSION_SUPERTILED_End 5
+#define GC_FEATURES3_TEX_COMPRESSION_SUPERTILED_Start 5
+#define GC_FEATURES3_TEX_COMPRESSION_SUPERTILED_Type U01
+#define GC_FEATURES3_TEX_COMPRESSION_SUPERTILED_NONE 0x0
+#define GC_FEATURES3_TEX_COMPRESSION_SUPERTILED_AVAILABLE 0x1
+
+#define GC_FEATURES3_GENERICS 6 : 6
+#define GC_FEATURES3_GENERICS_End 6
+#define GC_FEATURES3_GENERICS_Start 6
+#define GC_FEATURES3_GENERICS_Type U01
+#define GC_FEATURES3_GENERICS_NONE 0x0
+#define GC_FEATURES3_GENERICS_AVAILABLE 0x1
+
+#define GC_FEATURES3_BUG_FIXES9 7 : 7
+#define GC_FEATURES3_BUG_FIXES9_End 7
+#define GC_FEATURES3_BUG_FIXES9_Start 7
+#define GC_FEATURES3_BUG_FIXES9_Type U01
+#define GC_FEATURES3_BUG_FIXES9_NONE 0x0
+#define GC_FEATURES3_BUG_FIXES9_AVAILABLE 0x1
+
+#define GC_FEATURES3_FAST_MSAA 8 : 8
+#define GC_FEATURES3_FAST_MSAA_End 8
+#define GC_FEATURES3_FAST_MSAA_Start 8
+#define GC_FEATURES3_FAST_MSAA_Type U01
+#define GC_FEATURES3_FAST_MSAA_NONE 0x0
+#define GC_FEATURES3_FAST_MSAA_AVAILABLE 0x1
+
+#define GC_FEATURES3_WCLIP 9 : 9
+#define GC_FEATURES3_WCLIP_End 9
+#define GC_FEATURES3_WCLIP_Start 9
+#define GC_FEATURES3_WCLIP_Type U01
+#define GC_FEATURES3_WCLIP_NONE 0x0
+#define GC_FEATURES3_WCLIP_AVAILABLE 0x1
+
+#define GC_FEATURES3_BUG_FIXES10 10 : 10
+#define GC_FEATURES3_BUG_FIXES10_End 10
+#define GC_FEATURES3_BUG_FIXES10_Start 10
+#define GC_FEATURES3_BUG_FIXES10_Type U01
+#define GC_FEATURES3_BUG_FIXES10_NONE 0x0
+#define GC_FEATURES3_BUG_FIXES10_AVAILABLE 0x1
+
+#define GC_FEATURES3_UNIFIED_SAMPLERS 11 : 11
+#define GC_FEATURES3_UNIFIED_SAMPLERS_End 11
+#define GC_FEATURES3_UNIFIED_SAMPLERS_Start 11
+#define GC_FEATURES3_UNIFIED_SAMPLERS_Type U01
+#define GC_FEATURES3_UNIFIED_SAMPLERS_NONE 0x0
+#define GC_FEATURES3_UNIFIED_SAMPLERS_AVAILABLE 0x1
+
+#define GC_FEATURES3_BUG_FIXES11 12 : 12
+#define GC_FEATURES3_BUG_FIXES11_End 12
+#define GC_FEATURES3_BUG_FIXES11_Start 12
+#define GC_FEATURES3_BUG_FIXES11_Type U01
+#define GC_FEATURES3_BUG_FIXES11_NONE 0x0
+#define GC_FEATURES3_BUG_FIXES11_AVAILABLE 0x1
+
+#define GC_FEATURES3_PERFORMANCE_COUNTERS 13 : 13
+#define GC_FEATURES3_PERFORMANCE_COUNTERS_End 13
+#define GC_FEATURES3_PERFORMANCE_COUNTERS_Start 13
+#define GC_FEATURES3_PERFORMANCE_COUNTERS_Type U01
+#define GC_FEATURES3_PERFORMANCE_COUNTERS_NONE 0x0
+#define GC_FEATURES3_PERFORMANCE_COUNTERS_AVAILABLE 0x1
+
+/* High precision transcendentals are available. */
+#define GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2 14 : 14
+#define GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2_End 14
+#define GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2_Start 14
+#define GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2_Type U01
+#define GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2_NONE 0x0
+#define GC_FEATURES3_EXTRA_SHADER_INSTRUCTIONS2_AVAILABLE 0x1
+
+#define GC_FEATURES3_BUG_FIXES12 15 : 15
+#define GC_FEATURES3_BUG_FIXES12_End 15
+#define GC_FEATURES3_BUG_FIXES12_Start 15
+#define GC_FEATURES3_BUG_FIXES12_Type U01
+#define GC_FEATURES3_BUG_FIXES12_NONE 0x0
+#define GC_FEATURES3_BUG_FIXES12_AVAILABLE 0x1
+
+#define GC_FEATURES3_BUG_FIXES13 16 : 16
+#define GC_FEATURES3_BUG_FIXES13_End 16
+#define GC_FEATURES3_BUG_FIXES13_Start 16
+#define GC_FEATURES3_BUG_FIXES13_Type U01
+#define GC_FEATURES3_BUG_FIXES13_NONE 0x0
+#define GC_FEATURES3_BUG_FIXES13_AVAILABLE 0x1
+
+#define GC_FEATURES3_DE_ENHANCEMENTS1 17 : 17
+#define GC_FEATURES3_DE_ENHANCEMENTS1_End 17
+#define GC_FEATURES3_DE_ENHANCEMENTS1_Start 17
+#define GC_FEATURES3_DE_ENHANCEMENTS1_Type U01
+#define GC_FEATURES3_DE_ENHANCEMENTS1_NONE 0x0
+#define GC_FEATURES3_DE_ENHANCEMENTS1_AVAILABLE 0x1
+
+#define GC_FEATURES3_ACE 18 : 18
+#define GC_FEATURES3_ACE_End 18
+#define GC_FEATURES3_ACE_Start 18
+#define GC_FEATURES3_ACE_Type U01
+#define GC_FEATURES3_ACE_NONE 0x0
+#define GC_FEATURES3_ACE_AVAILABLE 0x1
+
+#define GC_FEATURES3_TX_ENHANCEMENTS1 19 : 19
+#define GC_FEATURES3_TX_ENHANCEMENTS1_End 19
+#define GC_FEATURES3_TX_ENHANCEMENTS1_Start 19
+#define GC_FEATURES3_TX_ENHANCEMENTS1_Type U01
+#define GC_FEATURES3_TX_ENHANCEMENTS1_NONE 0x0
+#define GC_FEATURES3_TX_ENHANCEMENTS1_AVAILABLE 0x1
+
+#define GC_FEATURES3_SH_ENHANCEMENTS1 20 : 20
+#define GC_FEATURES3_SH_ENHANCEMENTS1_End 20
+#define GC_FEATURES3_SH_ENHANCEMENTS1_Start 20
+#define GC_FEATURES3_SH_ENHANCEMENTS1_Type U01
+#define GC_FEATURES3_SH_ENHANCEMENTS1_NONE 0x0
+#define GC_FEATURES3_SH_ENHANCEMENTS1_AVAILABLE 0x1
+
+#define GC_FEATURES3_SH_ENHANCEMENTS2 21 : 21
+#define GC_FEATURES3_SH_ENHANCEMENTS2_End 21
+#define GC_FEATURES3_SH_ENHANCEMENTS2_Start 21
+#define GC_FEATURES3_SH_ENHANCEMENTS2_Type U01
+#define GC_FEATURES3_SH_ENHANCEMENTS2_NONE 0x0
+#define GC_FEATURES3_SH_ENHANCEMENTS2_AVAILABLE 0x1
+
+union gcfeatures3 {
+ struct {
+ /* GC_FEATURES3_Address:DE_ROTATION_STALL_FIX */
+ unsigned int rotationfix:1;
+
+ /* GC_FEATURES3_Address:OCL_ONLY */
+ unsigned int ocl:1;
+
+ /* GC_FEATURES3_Address:NEW_FEATURES0 */
+ unsigned int newfeatures0:1;
+
+ /* GC_FEATURES3_Address:INSTRUCTION_CACHE */
+ unsigned int icache:1;
+
+ /* GC_FEATURES3_Address:GEOMETRY_SHADER */
+ unsigned int gs:1;
+
+ /* GC_FEATURES3_Address:TEX_COMPRESSION_SUPERTILED */
+ unsigned int supertiledtxcompression:1;
+
+ /* GC_FEATURES3_Address:GENERICS */
+ unsigned int generics:1;
+
+ /* GC_FEATURES3_Address:BUG_FIXES9 */
+ unsigned int bugfixes9:1;
+
+ /* GC_FEATURES3_Address:FAST_MSAA */
+ unsigned int fastmsaa:1;
+
+ /* GC_FEATURES3_Address:WCLIP */
+ unsigned int wclip:1;
+
+ /* GC_FEATURES3_Address:BUG_FIXES10 */
+ unsigned int bugfixes10:1;
+
+ /* GC_FEATURES3_Address:UNIFIED_SAMPLERS */
+ unsigned int unifiedsamplers:1;
+
+ /* GC_FEATURES3_Address:BUG_FIXES11 */
+ unsigned int bugfixes11:1;
+
+ /* GC_FEATURES3_Address:PERFORMANCE_COUNTERS */
+ unsigned int perfcounters:1;
+
+ /* GC_FEATURES3_Address:EXTRA_SHADER_INSTRUCTIONS2 */
+ unsigned int shaderinst2:1;
+
+ /* GC_FEATURES3_Address:BUG_FIXES12 */
+ unsigned int bugfixes12:1;
+
+ /* GC_FEATURES3_Address:BUG_FIXES13 */
+ unsigned int bugfixes13:1;
+
+ /* GC_FEATURES3_Address:DE_ENHANCEMENTS1 */
+ unsigned int deenhancements1:1;
+
+ /* GC_FEATURES3_Address:ACE */
+ unsigned int ace:1;
+
+ /* GC_FEATURES3_Address:TX_ENHANCEMENTS1 */
+ unsigned int txenhancements1:1;
+
+ /* GC_FEATURES3_Address:SH_ENHANCEMENTS1 */
+ unsigned int shenhancements1:1;
+
+ /* GC_FEATURES3_Address:SH_ENHANCEMENTS2 */
+ unsigned int shenhancements2:1;
+
+ /* GC_FEATURES3_Address:reserved */
+ unsigned int _reserved_22_31:10;
+ } reg;
+
+ unsigned int raw;
+};
+
+/*******************************************************************************
+** Register GCResetMemCounters
+*/
+
+/* Writing 1 will reset the counters and stop counting. Write 0 to start
+** counting again. This register is write only so it has no reset value.
+*/
+
+#define GC_RESET_MEM_COUNTERS_Address 0x0003C
+#define GC_RESET_MEM_COUNTERS_MSB 15
+#define GC_RESET_MEM_COUNTERS_LSB 0
+#define GC_RESET_MEM_COUNTERS_BLK 0
+#define GC_RESET_MEM_COUNTERS_Count 1
+#define GC_RESET_MEM_COUNTERS_FieldMask 0x00000001
+#define GC_RESET_MEM_COUNTERS_ReadMask 0x00000000
+#define GC_RESET_MEM_COUNTERS_WriteMask 0x00000001
+#define GC_RESET_MEM_COUNTERS_ResetValue 0x00000000
+
+#define GC_RESET_MEM_COUNTERS_RESET 0 : 0
+#define GC_RESET_MEM_COUNTERS_RESET_End 0
+#define GC_RESET_MEM_COUNTERS_RESET_Start 0
+#define GC_RESET_MEM_COUNTERS_RESET_Type U01
+
+/*******************************************************************************
+** Register gcTotalReads
+*/
+
+/* Total reads in terms of 64bits. */
+
+#define GC_TOTAL_READS_Address 0x00040
+#define GC_TOTAL_READS_MSB 15
+#define GC_TOTAL_READS_LSB 0
+#define GC_TOTAL_READS_BLK 0
+#define GC_TOTAL_READS_Count 1
+#define GC_TOTAL_READS_FieldMask 0xFFFFFFFF
+#define GC_TOTAL_READS_ReadMask 0xFFFFFFFF
+#define GC_TOTAL_READS_WriteMask 0x00000000
+#define GC_TOTAL_READS_ResetValue 0x00000000
+
+#define GC_TOTAL_READS_COUNT 31 : 0
+#define GC_TOTAL_READS_COUNT_End 31
+#define GC_TOTAL_READS_COUNT_Start 0
+#define GC_TOTAL_READS_COUNT_Type U32
+
+/*******************************************************************************
+** Register gcTotalWrites
+*/
+
+/* Total writes in terms of 64bits. */
+
+#define GC_TOTAL_WRITES_Address 0x00044
+#define GC_TOTAL_WRITES_MSB 15
+#define GC_TOTAL_WRITES_LSB 0
+#define GC_TOTAL_WRITES_BLK 0
+#define GC_TOTAL_WRITES_Count 1
+#define GC_TOTAL_WRITES_FieldMask 0xFFFFFFFF
+#define GC_TOTAL_WRITES_ReadMask 0xFFFFFFFF
+#define GC_TOTAL_WRITES_WriteMask 0x00000000
+#define GC_TOTAL_WRITES_ResetValue 0x00000000
+
+#define GC_TOTAL_WRITES_COUNT 31 : 0
+#define GC_TOTAL_WRITES_COUNT_End 31
+#define GC_TOTAL_WRITES_COUNT_Start 0
+#define GC_TOTAL_WRITES_COUNT_Type U32
+
+/*******************************************************************************
+** Register gcTotalWriteBursts
+*/
+
+/* Total write Data Count in terms of 64bits value. */
+
+#define GC_TOTAL_WRITE_BURSTS_Address 0x0004C
+#define GC_TOTAL_WRITE_BURSTS_MSB 15
+#define GC_TOTAL_WRITE_BURSTS_LSB 0
+#define GC_TOTAL_WRITE_BURSTS_BLK 0
+#define GC_TOTAL_WRITE_BURSTS_Count 1
+#define GC_TOTAL_WRITE_BURSTS_FieldMask 0xFFFFFFFF
+#define GC_TOTAL_WRITE_BURSTS_ReadMask 0xFFFFFFFF
+#define GC_TOTAL_WRITE_BURSTS_WriteMask 0x00000000
+#define GC_TOTAL_WRITE_BURSTS_ResetValue 0x00000000
+
+#define GC_TOTAL_WRITE_BURSTS_COUNT 31 : 0
+#define GC_TOTAL_WRITE_BURSTS_COUNT_End 31
+#define GC_TOTAL_WRITE_BURSTS_COUNT_Start 0
+#define GC_TOTAL_WRITE_BURSTS_COUNT_Type U32
+
+/*******************************************************************************
+** Register gcTotalWriteReqs
+*/
+
+/* Total write Request Count. */
+
+#define GC_TOTAL_WRITE_REQS_Address 0x00050
+#define GC_TOTAL_WRITE_REQS_MSB 15
+#define GC_TOTAL_WRITE_REQS_LSB 0
+#define GC_TOTAL_WRITE_REQS_BLK 0
+#define GC_TOTAL_WRITE_REQS_Count 1
+#define GC_TOTAL_WRITE_REQS_FieldMask 0xFFFFFFFF
+#define GC_TOTAL_WRITE_REQS_ReadMask 0xFFFFFFFF
+#define GC_TOTAL_WRITE_REQS_WriteMask 0x00000000
+#define GC_TOTAL_WRITE_REQS_ResetValue 0x00000000
+
+#define GC_TOTAL_WRITE_REQS_COUNT 31 : 0
+#define GC_TOTAL_WRITE_REQS_COUNT_End 31
+#define GC_TOTAL_WRITE_REQS_COUNT_Start 0
+#define GC_TOTAL_WRITE_REQS_COUNT_Type U32
+
+/*******************************************************************************
+** Register gcTotalReadBursts
+*/
+
+/* Total Read Data Count in terms of 64bits. */
+
+#define GC_TOTAL_READ_BURSTS_Address 0x00058
+#define GC_TOTAL_READ_BURSTS_MSB 15
+#define GC_TOTAL_READ_BURSTS_LSB 0
+#define GC_TOTAL_READ_BURSTS_BLK 0
+#define GC_TOTAL_READ_BURSTS_Count 1
+#define GC_TOTAL_READ_BURSTS_FieldMask 0xFFFFFFFF
+#define GC_TOTAL_READ_BURSTS_ReadMask 0xFFFFFFFF
+#define GC_TOTAL_READ_BURSTS_WriteMask 0x00000000
+#define GC_TOTAL_READ_BURSTS_ResetValue 0x00000000
+
+#define GC_TOTAL_READ_BURSTS_COUNT 31 : 0
+#define GC_TOTAL_READ_BURSTS_COUNT_End 31
+#define GC_TOTAL_READ_BURSTS_COUNT_Start 0
+#define GC_TOTAL_READ_BURSTS_COUNT_Type U32
+
+/*******************************************************************************
+** Register gcTotalReadReqs
+*/
+
+/* Total Read Request Count. */
+
+#define GC_TOTAL_READ_REQS_Address 0x0005C
+#define GC_TOTAL_READ_REQS_MSB 15
+#define GC_TOTAL_READ_REQS_LSB 0
+#define GC_TOTAL_READ_REQS_BLK 0
+#define GC_TOTAL_READ_REQS_Count 1
+#define GC_TOTAL_READ_REQS_FieldMask 0xFFFFFFFF
+#define GC_TOTAL_READ_REQS_ReadMask 0xFFFFFFFF
+#define GC_TOTAL_READ_REQS_WriteMask 0x00000000
+#define GC_TOTAL_READ_REQS_ResetValue 0x00000000
+
+#define GC_TOTAL_READ_REQS_COUNT 31 : 0
+#define GC_TOTAL_READ_REQS_COUNT_End 31
+#define GC_TOTAL_READ_REQS_COUNT_Start 0
+#define GC_TOTAL_READ_REQS_COUNT_Type U32
+
+/*******************************************************************************
+** Register gcTotalReadLasts
+*/
+
+/* Total RLAST Count. This is used to match with GCTotalReadReqs. */
+
+#define GC_TOTAL_READ_LASTS_Address 0x00060
+#define GC_TOTAL_READ_LASTS_MSB 15
+#define GC_TOTAL_READ_LASTS_LSB 0
+#define GC_TOTAL_READ_LASTS_BLK 0
+#define GC_TOTAL_READ_LASTS_Count 1
+#define GC_TOTAL_READ_LASTS_FieldMask 0xFFFFFFFF
+#define GC_TOTAL_READ_LASTS_ReadMask 0xFFFFFFFF
+#define GC_TOTAL_READ_LASTS_WriteMask 0x00000000
+#define GC_TOTAL_READ_LASTS_ResetValue 0x00000000
+
+#define GC_TOTAL_READ_LASTS_COUNT 31 : 0
+#define GC_TOTAL_READ_LASTS_COUNT_End 31
+#define GC_TOTAL_READ_LASTS_COUNT_Start 0
+#define GC_TOTAL_READ_LASTS_COUNT_Type U32
+
+/*******************************************************************************
+** Register gcGpOut0
+*/
+
+/* General Purpose output register0. R/W but not connected to anywhere. */
+
+#define GC_GP_OUT0_Address 0x00064
+#define GC_GP_OUT0_MSB 15
+#define GC_GP_OUT0_LSB 0
+#define GC_GP_OUT0_BLK 0
+#define GC_GP_OUT0_Count 1
+#define GC_GP_OUT0_FieldMask 0xFFFFFFFF
+#define GC_GP_OUT0_ReadMask 0xFFFFFFFF
+#define GC_GP_OUT0_WriteMask 0xFFFFFFFF
+#define GC_GP_OUT0_ResetValue 0x00000000
+
+#define GC_GP_OUT0_COUNT 31 : 0
+#define GC_GP_OUT0_COUNT_End 31
+#define GC_GP_OUT0_COUNT_Start 0
+#define GC_GP_OUT0_COUNT_Type U32
+
+/*******************************************************************************
+** Register gcGpOut1
+*/
+
+/* General Purpose output register1. R/W but not connected to anywhere. */
+
+#define GC_GP_OUT1_Address 0x00068
+#define GC_GP_OUT1_MSB 15
+#define GC_GP_OUT1_LSB 0
+#define GC_GP_OUT1_BLK 0
+#define GC_GP_OUT1_Count 1
+#define GC_GP_OUT1_FieldMask 0xFFFFFFFF
+#define GC_GP_OUT1_ReadMask 0xFFFFFFFF
+#define GC_GP_OUT1_WriteMask 0xFFFFFFFF
+#define GC_GP_OUT1_ResetValue 0x00000000
+
+#define GC_GP_OUT1_COUNT 31 : 0
+#define GC_GP_OUT1_COUNT_End 31
+#define GC_GP_OUT1_COUNT_Start 0
+#define GC_GP_OUT1_COUNT_Type U32
+
+/*******************************************************************************
+** Register gcGpOut2
+*/
+
+/* General Purpose output register2. R/W but not connected to anywhere. */
+
+#define GC_GP_OUT2_Address 0x0006C
+#define GC_GP_OUT2_MSB 15
+#define GC_GP_OUT2_LSB 0
+#define GC_GP_OUT2_BLK 0
+#define GC_GP_OUT2_Count 1
+#define GC_GP_OUT2_FieldMask 0xFFFFFFFF
+#define GC_GP_OUT2_ReadMask 0xFFFFFFFF
+#define GC_GP_OUT2_WriteMask 0xFFFFFFFF
+#define GC_GP_OUT2_ResetValue 0x00000000
+
+#define GC_GP_OUT2_COUNT 31 : 0
+#define GC_GP_OUT2_COUNT_End 31
+#define GC_GP_OUT2_COUNT_Start 0
+#define GC_GP_OUT2_COUNT_Type U32
+
+/*******************************************************************************
+** Register gcAxiControl
+*/
+
+/* Special Handling on AXI Bus */
+
+#define GC_AXI_CONTROL_Address 0x00070
+#define GC_AXI_CONTROL_MSB 15
+#define GC_AXI_CONTROL_LSB 0
+#define GC_AXI_CONTROL_BLK 0
+#define GC_AXI_CONTROL_Count 1
+#define GC_AXI_CONTROL_FieldMask 0x00000001
+#define GC_AXI_CONTROL_ReadMask 0x00000001
+#define GC_AXI_CONTROL_WriteMask 0x00000001
+#define GC_AXI_CONTROL_ResetValue 0x00000000
+
+#define GC_AXI_CONTROL_WR_FULL_BURST_MODE 0 : 0
+#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_End 0
+#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_Start 0
+#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_Type U01
+#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_NO_BURST_RESET_VALUE 0x0
+#define GC_AXI_CONTROL_WR_FULL_BURST_MODE_BURST_RESET_VALUE 0x1
+
+/*******************************************************************************
+** Register gcTotalCycles
+*/
+
+/* Total cycles. This register is a free running counter. It can be reset by
+** writing 0 to it.
+*/
+
+#define GC_TOTAL_CYCLES_Address 0x00078
+#define GC_TOTAL_CYCLES_MSB 15
+#define GC_TOTAL_CYCLES_LSB 0
+#define GC_TOTAL_CYCLES_BLK 0
+#define GC_TOTAL_CYCLES_Count 1
+#define GC_TOTAL_CYCLES_FieldMask 0xFFFFFFFF
+#define GC_TOTAL_CYCLES_ReadMask 0xFFFFFFFF
+#define GC_TOTAL_CYCLES_WriteMask 0xFFFFFFFF
+#define GC_TOTAL_CYCLES_ResetValue 0x00000000
+
+#define GC_TOTAL_CYCLES_CYCLES 31 : 0
+#define GC_TOTAL_CYCLES_CYCLES_End 31
+#define GC_TOTAL_CYCLES_CYCLES_Start 0
+#define GC_TOTAL_CYCLES_CYCLES_Type U32
+
+/*******************************************************************************
+** Register gcTotalIdleCycles
+*/
+
+/* Total cycles where the GPU is idle. It is reset when gcTotalCycles register
+** is written to. It looks at all the blocks but FE when determining the IP is
+** idle.
+*/
+
+#define GC_TOTAL_IDLE_CYCLES_Address 0x0007C
+#define GC_TOTAL_IDLE_CYCLES_MSB 15
+#define GC_TOTAL_IDLE_CYCLES_LSB 0
+#define GC_TOTAL_IDLE_CYCLES_BLK 0
+#define GC_TOTAL_IDLE_CYCLES_Count 1
+#define GC_TOTAL_IDLE_CYCLES_FieldMask 0xFFFFFFFF
+#define GC_TOTAL_IDLE_CYCLES_ReadMask 0xFFFFFFFF
+#define GC_TOTAL_IDLE_CYCLES_WriteMask 0xFFFFFFFF
+#define GC_TOTAL_IDLE_CYCLES_ResetValue 0x00000000
+
+#define GC_TOTAL_IDLE_CYCLES_CYCLES 31 : 0
+#define GC_TOTAL_IDLE_CYCLES_CYCLES_End 31
+#define GC_TOTAL_IDLE_CYCLES_CYCLES_Start 0
+#define GC_TOTAL_IDLE_CYCLES_CYCLES_Type U32
+
+/*******************************************************************************
+** Command opcodes.
+*/
+
+#define GCREG_COMMAND_OPCODE_LOAD_STATE 0x01
+#define GCREG_COMMAND_OPCODE_END 0x02
+#define GCREG_COMMAND_OPCODE_NOP 0x03
+#define GCREG_COMMAND_OPCODE_STARTDE 0x04
+#define GCREG_COMMAND_OPCODE_WAIT 0x07
+#define GCREG_COMMAND_OPCODE_LINK 0x08
+#define GCREG_COMMAND_OPCODE_STALL 0x09
+#define GCREG_COMMAND_OPCODE_CALL 0x0A
+#define GCREG_COMMAND_OPCODE_RETURN 0x0B
+
+/*******************************************************************************
+** Command gcregCommandLoadState
+*/
+
+/* When enabled, convert 16.16 fixed point into 32-bit floating point. */
+#define GCREG_COMMAND_LOAD_STATE_FLOAT 26 : 26
+#define GCREG_COMMAND_LOAD_STATE_FLOAT_End 26
+#define GCREG_COMMAND_LOAD_STATE_FLOAT_Start 26
+#define GCREG_COMMAND_LOAD_STATE_FLOAT_Type U01
+#define GCREG_COMMAND_LOAD_STATE_FLOAT_NORMAL 0x0
+#define GCREG_COMMAND_LOAD_STATE_FLOAT_FIXED16_DOT16 0x1
+
+/* Number of states. 0 = 1024. */
+#define GCREG_COMMAND_LOAD_STATE_COUNT 25 : 16
+#define GCREG_COMMAND_LOAD_STATE_COUNT_End 25
+#define GCREG_COMMAND_LOAD_STATE_COUNT_Start 16
+#define GCREG_COMMAND_LOAD_STATE_COUNT_Type U10
+
+/* Starting state address. */
+#define GCREG_COMMAND_LOAD_STATE_ADDRESS 15 : 0
+#define GCREG_COMMAND_LOAD_STATE_ADDRESS_End 15
+#define GCREG_COMMAND_LOAD_STATE_ADDRESS_Start 0
+#define GCREG_COMMAND_LOAD_STATE_ADDRESS_Type U16
+
+#define GCREG_COMMAND_LOAD_STATE_OPCODE 31 : 27
+#define GCREG_COMMAND_LOAD_STATE_OPCODE_End 31
+#define GCREG_COMMAND_LOAD_STATE_OPCODE_Start 27
+#define GCREG_COMMAND_LOAD_STATE_OPCODE_Type U05
+
+struct gccmdldstate {
+ /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_ADDRESS */
+ unsigned int address:16;
+
+ /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COUNT */
+ unsigned int count:10;
+
+ /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_FLOAT */
+ unsigned int fixed:1;
+
+ /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_OPCODE */
+ unsigned int opcode:5;
+};
+
+#define GCLDSTATE(Address, Count) \
+{ \
+ /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_ADDRESS */ \
+ Address, \
+ \
+ /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_COUNT */ \
+ Count, \
+ \
+ /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_FLOAT */ \
+ GCREG_COMMAND_LOAD_STATE_FLOAT_NORMAL, \
+ \
+ /* gcregCommandLoadState:GCREG_COMMAND_LOAD_STATE_OPCODE */ \
+ GCREG_COMMAND_OPCODE_LOAD_STATE \
+}
+
+/*******************************************************************************
+** Command gcregCommandEnd
+*/
+
+/* Send event when END is completed. */
+#define GCREG_COMMAND_END_EVENT 8 : 8
+#define GCREG_COMMAND_END_EVENT_End 8
+#define GCREG_COMMAND_END_EVENT_Start 8
+#define GCREG_COMMAND_END_EVENT_Type U01
+#define GCREG_COMMAND_END_EVENT_DISABLE 0x0
+#define GCREG_COMMAND_END_EVENT_ENABLE 0x1
+
+/* Event ID to be send. */
+#define GCREG_COMMAND_END_EVENT_ID 4 : 0
+#define GCREG_COMMAND_END_EVENT_ID_End 4
+#define GCREG_COMMAND_END_EVENT_ID_Start 0
+#define GCREG_COMMAND_END_EVENT_ID_Type U05
+
+#define GCREG_COMMAND_END_OPCODE 31 : 27
+#define GCREG_COMMAND_END_OPCODE_End 31
+#define GCREG_COMMAND_END_OPCODE_Start 27
+#define GCREG_COMMAND_END_OPCODE_Type U05
+
+struct gcfldend {
+ /* gcregCommandEnd:GCREG_COMMAND_END_EVENT_ID */
+ unsigned int signalid:5;
+
+ /* gcregCommandEnd:reserved */
+ unsigned int _reserved_5_7:3;
+
+ /* gcregCommandEnd:GCREG_COMMAND_END_EVENT_ENABLE */
+ unsigned int signal:1;
+
+ /* gcregCommandEnd:reserved */
+ unsigned int _reserved_9_26:18;
+
+ /* gcregCommandEnd:GCREG_COMMAND_END_OPCODE */
+ unsigned int opcode:5;
+};
+
+struct gccmdend {
+ union {
+ struct gcfldend fld;
+ unsigned int raw;
+ }
+ cmd;
+
+ /* Alignment filler. */
+ unsigned int _filler;
+};
+
+static const struct gccmdend gccmdend_const = {
+ /* cmd */
+ {
+ /* fld */
+ {
+ /* gcregCommandEnd:GCREG_COMMAND_END_EVENT_ID */
+ 0,
+
+ /* gcregCommandEnd:reserved */
+ 0,
+
+ /* gcregCommandEnd:GCREG_COMMAND_END_EVENT */
+ GCREG_COMMAND_END_EVENT_DISABLE,
+
+ /* gcregCommandEnd:reserved */
+ 0,
+
+ /* gcregCommandEnd:GCREG_COMMAND_END_OPCODE */
+ GCREG_COMMAND_OPCODE_END
+ }
+ },
+
+ /* Alignment filler. */
+ 0
+};
+
+/*******************************************************************************
+** Command gcregCommandNop
+*/
+
+#define GCREG_COMMAND_NOP_OPCODE 31 : 27
+#define GCREG_COMMAND_NOP_OPCODE_End 31
+#define GCREG_COMMAND_NOP_OPCODE_Start 27
+#define GCREG_COMMAND_NOP_OPCODE_Type U05
+
+struct gcfldnop {
+ /* gcregCommandNop:reserved */
+ unsigned int _reserved_0_26:27;
+
+ /* gcregCommandNop:GCREG_COMMAND_NOP_OPCODE */
+ unsigned int opcode:5;
+};
+
+struct gccmdnop {
+ union {
+ struct gcfldnop fld;
+ unsigned int raw;
+ }
+ cmd;
+
+ /* Alignment filler. */
+ unsigned int _filler;
+};
+
+static const struct gccmdnop gccmdnop_const = {
+ /* cmd */
+ {
+ /* fld */
+ {
+ /* gcregCommandNop:reserved */
+ 0,
+
+ /* gcregCommandNop:GCREG_COMMAND_NOP_OPCODE */
+ GCREG_COMMAND_OPCODE_NOP
+ }
+ },
+
+ /* Alignment filler. */
+ 0
+};
+
+/*******************************************************************************
+** Command gcregCommandStartDE
+*/
+
+/* Offset Command
+** ~~~~~~~~~~~~~~ */
+
+/* Number of 32-bit data words to send.
+** The data follows the rectangles, aligned at 64-bit.
+*/
+#define GCREG_COMMAND_STARTDE_DATA_COUNT 26 : 16
+#define GCREG_COMMAND_STARTDE_DATA_COUNT_End 26
+#define GCREG_COMMAND_STARTDE_DATA_COUNT_Start 16
+#define GCREG_COMMAND_STARTDE_DATA_COUNT_Type U11
+
+/* Number of rectangles to send.
+** The rectangles follow the command, aligned at 64-bit.
+*/
+#define GCREG_COMMAND_STARTDE_COUNT 15 : 8
+#define GCREG_COMMAND_STARTDE_COUNT_End 15
+#define GCREG_COMMAND_STARTDE_COUNT_Start 8
+#define GCREG_COMMAND_STARTDE_COUNT_Type U08
+
+#define GCREG_COMMAND_STARTDE_OPCODE 31 : 27
+#define GCREG_COMMAND_STARTDE_OPCODE_End 31
+#define GCREG_COMMAND_STARTDE_OPCODE_Start 27
+#define GCREG_COMMAND_STARTDE_OPCODE_Type U05
+
+struct gcfldstartde {
+ /* gcregCommandStartDE:reserved */
+ unsigned int _reserved_0_7:8;
+
+ /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_COUNT */
+ unsigned int rectcount:8;
+
+ /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_DATA_COUNT */
+ unsigned int datacount:11;
+
+ /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_OPCODE */
+ unsigned int opcode:5;
+};
+
+struct gccmdstartde {
+ union {
+ struct gcfldstartde fld;
+ unsigned int raw;
+ } cmd;
+
+ /* Alignment filler. */
+ unsigned int _filler;
+};
+
+static const struct gcfldstartde gcfldstartde = {
+ /* gcregCommandStartDE:reserved */
+ 0,
+
+ /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_COUNT */
+ 1,
+
+ /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_DATA_COUNT */
+ 0,
+
+ /* gcregCommandStartDE:GCREG_COMMAND_STARTDE_OPCODE */
+ GCREG_COMMAND_OPCODE_STARTDE
+};
+
+/* Offset TopLeft
+** ~~~~~~~~~~~~~~ */
+
+#define GCREG_COMMAND_TOP_LEFT_Y 31 : 16
+#define GCREG_COMMAND_TOP_LEFT_Y_End 31
+#define GCREG_COMMAND_TOP_LEFT_Y_Start 16
+#define GCREG_COMMAND_TOP_LEFT_Y_Type U16
+
+#define GCREG_COMMAND_TOP_LEFT_X 15 : 0
+#define GCREG_COMMAND_TOP_LEFT_X_End 15
+#define GCREG_COMMAND_TOP_LEFT_X_Start 0
+#define GCREG_COMMAND_TOP_LEFT_X_Type U16
+
+/* Offset BottomRight
+** ~~~~~~~~~~~~~~~~~~ */
+
+#define GCREG_COMMAND_BOTTOM_RIGHT_Y 31 : 16
+#define GCREG_COMMAND_BOTTOM_RIGHT_Y_End 31
+#define GCREG_COMMAND_BOTTOM_RIGHT_Y_Start 16
+#define GCREG_COMMAND_BOTTOM_RIGHT_Y_Type U16
+
+#define GCREG_COMMAND_BOTTOM_RIGHT_X 15 : 0
+#define GCREG_COMMAND_BOTTOM_RIGHT_X_End 15
+#define GCREG_COMMAND_BOTTOM_RIGHT_X_Start 0
+#define GCREG_COMMAND_BOTTOM_RIGHT_X_Type U16
+
+struct gccmdstartderect {
+ /* GCREG_COMMAND_TOP_LEFT_X */
+ unsigned int left:16;
+
+ /* GCREG_COMMAND_TOP_LEFT_Y */
+ unsigned int top:16;
+
+ /* GCREG_COMMAND_BOTTOM_RIGHT_X */
+ unsigned int right:16;
+
+ /* GCREG_COMMAND_BOTTOM_RIGHT_Y */
+ unsigned int bottom:16;
+};
+
+/*******************************************************************************
+** Command gcregCommandWait
+*/
+
+/* Number of cycles to wait until the next command gets fetched. */
+#define GCREG_COMMAND_WAIT_DELAY 15 : 0
+#define GCREG_COMMAND_WAIT_DELAY_End 15
+#define GCREG_COMMAND_WAIT_DELAY_Start 0
+#define GCREG_COMMAND_WAIT_DELAY_Type U16
+
+#define GCREG_COMMAND_WAIT_OPCODE 31 : 27
+#define GCREG_COMMAND_WAIT_OPCODE_End 31
+#define GCREG_COMMAND_WAIT_OPCODE_Start 27
+#define GCREG_COMMAND_WAIT_OPCODE_Type U05
+
+struct gcfldwait {
+ /* gcregCommandWait:GCREG_COMMAND_WAIT_DELAY */
+ unsigned int delay:16;
+
+ /* gcregCommandWait:reserved */
+ unsigned int _reserved_16_26:11;
+
+ /* gcregCommandWait:GCREG_COMMAND_WAIT_OPCODE */
+ unsigned int opcode:5;
+};
+
+struct gccmdwait {
+ union {
+ struct gcfldwait fld;
+ unsigned int raw;
+ } cmd;
+
+ /* Alignment filler. */
+ unsigned int _filler;
+};
+
+static const struct gcfldwait gcfldwait200 = {
+ /* gcregCommandWait:GCREG_COMMAND_WAIT_DELAY */
+ 200,
+
+ /* gcregCommandWait:reserved */
+ 0,
+
+ /* gcregCommandWait:GCREG_COMMAND_WAIT_OPCODE */
+ GCREG_COMMAND_OPCODE_WAIT
+};
+
+/*******************************************************************************
+** Command gcregCommandLink
+*/
+
+/* Number of 64-bit words to fetch. Make sure this number is not too low,
+** nothing else will be fetched. So, make sure that the last command in the
+** new command buffer is either an END, a LINK, a CALL, or a RETURN.
+*/
+#define GCREG_COMMAND_LINK_PREFETCH 15 : 0
+#define GCREG_COMMAND_LINK_PREFETCH_End 15
+#define GCREG_COMMAND_LINK_PREFETCH_Start 0
+#define GCREG_COMMAND_LINK_PREFETCH_Type U16
+
+#define GCREG_COMMAND_LINK_OPCODE 31 : 27
+#define GCREG_COMMAND_LINK_OPCODE_End 31
+#define GCREG_COMMAND_LINK_OPCODE_Start 27
+#define GCREG_COMMAND_LINK_OPCODE_Type U05
+
+/* Offset Address
+** ~~~~~~~~~~~~~~ */
+#define GCREG_COMMAND_LINK_ADDRESS_Index 1
+#define GCREG_COMMAND_LINK_ADDRESS_CmdAddrs 0x0F0D
+
+#define GCREG_COMMAND_LINK_ADDRESS_ADDRESS 31 : 0
+#define GCREG_COMMAND_LINK_ADDRESS_ADDRESS_End 30
+#define GCREG_COMMAND_LINK_ADDRESS_ADDRESS_Start 0
+#define GCREG_COMMAND_LINK_ADDRESS_ADDRESS_Type U31
+
+struct gcfldlink {
+ /* gcregCommandLink:GCREG_COMMAND_LINK_PREFETCH */
+ unsigned int count:16;
+
+ /* gcregCommandLink:reserved */
+ unsigned int _reserved_16_26:11;
+
+ /* gcregCommandLink:GCREG_COMMAND_LINK_OPCODE */
+ unsigned int opcode:5;
+};
+
+struct gccmdlink {
+ union {
+ struct gcfldlink fld;
+ unsigned int raw;
+ } cmd;
+
+ /* gcregCommandLink:GCREG_COMMAND_LINK_ADDRESS_ADDRESS */
+ unsigned int address;
+};
+
+static const struct gcfldlink gcfldlink2 = {
+ /* gcregCommandLink:GCREG_COMMAND_LINK_PREFETCH */
+ 2,
+
+ /* gcregCommandLink:reserved */
+ 0,
+
+ /* gcregCommandLink:GCREG_COMMAND_LINK_OPCODE */
+ GCREG_COMMAND_OPCODE_LINK
+};
+
+static const struct gcfldlink gcfldlink4 = {
+ /* gcregCommandLink:GCREG_COMMAND_LINK_PREFETCH */
+ 4,
+
+ /* gcregCommandLink:reserved */
+ 0,
+
+ /* gcregCommandLink:GCREG_COMMAND_LINK_OPCODE */
+ GCREG_COMMAND_OPCODE_LINK
+};
+
+/*******************************************************************************
+** Command gcregCommandStall
+*/
+
+/* Offset Command
+** ~~~~~~~~~~~~~~ */
+#define GCREG_COMMAND_STALL_OPCODE 31 : 27
+#define GCREG_COMMAND_STALL_OPCODE_End 31
+#define GCREG_COMMAND_STALL_OPCODE_Start 27
+#define GCREG_COMMAND_STALL_OPCODE_Type U05
+
+/* Offset Stall
+** ~~~~~~~~~~~~ */
+#define GCREG_COMMAND_STALL_STALL_SOURCE 4 : 0
+#define GCREG_COMMAND_STALL_STALL_SOURCE_End 4
+#define GCREG_COMMAND_STALL_STALL_SOURCE_Start 0
+#define GCREG_COMMAND_STALL_STALL_SOURCE_Type U05
+#define GCREG_COMMAND_STALL_STALL_SOURCE_FRONT_END 0x01
+#define GCREG_COMMAND_STALL_STALL_SOURCE_PIXEL_ENGINE 0x07
+#define GCREG_COMMAND_STALL_STALL_SOURCE_DRAWING_ENGINE 0x0B
+
+#define GCREG_COMMAND_STALL_STALL_DESTINATION 12 : 8
+#define GCREG_COMMAND_STALL_STALL_DESTINATION_End 12
+#define GCREG_COMMAND_STALL_STALL_DESTINATION_Start 8
+#define GCREG_COMMAND_STALL_STALL_DESTINATION_Type U05
+#define GCREG_COMMAND_STALL_STALL_DESTINATION_FRONT_END 0x01
+#define GCREG_COMMAND_STALL_STALL_DESTINATION_PIXEL_ENGINE 0x07
+#define GCREG_COMMAND_STALL_STALL_DESTINATION_DRAWING_ENGINE 0x0B
+
+struct gcfldstall {
+ /* gcregCommandStall:reserved */
+ unsigned int _reserved_0_26:27;
+
+ /* gcregCommandStall:GCREG_COMMAND_STALL_OPCODE */
+ unsigned int opcode:5;
+};
+
+struct gcfldstallarg {
+ /* gcregCommandStall:GCREG_COMMAND_STALL_STALL_SOURCE */
+ unsigned int src:5;
+
+ /* gcregCommandStall:reserved */
+ unsigned int _reserved_5_7:3;
+
+ /* gcregCommandStall:GCREG_COMMAND_STALL_STALL_DESTINATION */
+ unsigned int dst:5;
+
+ /* gcregCommandStall:reserved */
+ unsigned int _reserved_13_31:19;
+};
+
+struct gccmdstall {
+ union {
+ struct gcfldstall fld;
+ unsigned int raw;
+ } cmd;
+
+ union {
+ struct gcfldstallarg fld;
+ unsigned int raw;
+ } arg;
+};
+
+static const struct gcfldstall gcfldstall = {
+ /* gcregCommandStall:reserved */
+ 0,
+
+ /* gcregCommandStall:GCREG_COMMAND_STALL_OPCODE */
+ GCREG_COMMAND_OPCODE_STALL
+};
+
+static const struct gcfldstallarg gcfldstall_fe_pe = {
+ /* gcregCommandStall:GCREG_COMMAND_STALL_STALL_SOURCE */
+ GCREG_COMMAND_STALL_STALL_SOURCE_FRONT_END,
+
+ /* gcregCommandStall:reserved */
+ 0,
+
+ /* gcregCommandStall:GCREG_COMMAND_STALL_STALL_DESTINATION */
+ GCREG_COMMAND_STALL_STALL_DESTINATION_PIXEL_ENGINE,
+
+ /* gcregCommandStall:reserved */
+ 0
+};
+
+/*******************************************************************************
+** Command gcregCommandCall
+*/
+
+/* Offset Command
+** ~~~~~~~~~~~~~~ */
+
+/* Number of 64-bit words to fetch. Make sure this number is not too low,
+** nothing else will be fetched. So, make sure that the last command in the
+** new command buffer is either an END, a LINK, a CALL, or a RETURN.
+*/
+#define GCREG_COMMAND_CALL_PREFETCH 15 : 0
+#define GCREG_COMMAND_CALL_PREFETCH_End 15
+#define GCREG_COMMAND_CALL_PREFETCH_Start 0
+#define GCREG_COMMAND_CALL_PREFETCH_Type U16
+
+#define GCREG_COMMAND_CALL_OPCODE 31 : 27
+#define GCREG_COMMAND_CALL_OPCODE_End 31
+#define GCREG_COMMAND_CALL_OPCODE_Start 27
+#define GCREG_COMMAND_CALL_OPCODE_Type U05
+
+/* Offset Address
+** ~~~~~~~~~~~~~~ */
+
+#define GCREG_COMMAND_CALL_ADDRESS_ADDRESS 31 : 0
+#define GCREG_COMMAND_CALL_ADDRESS_ADDRESS_End 30
+#define GCREG_COMMAND_CALL_ADDRESS_ADDRESS_Start 0
+#define GCREG_COMMAND_CALL_ADDRESS_ADDRESS_Type U31
+
+/* Offset ReturnPrefetch
+** ~~~~~~~~~~~~~~~~~~~~~ */
+
+/* Number of 64-bit words to fetch after a Return has been issued. Make sure **
+** this number if not too low nothing else will be fetched. So, make sure **
+** the last command in this prefetch block is either an END, a LINK, a CALL, **
+** or a RETURN. */
+#define GCREG_COMMAND_CALL_RETURN_PREFETCH_PREFETCH 15 : 0
+#define GCREG_COMMAND_CALL_RETURN_PREFETCH_PREFETCH_End 15
+#define GCREG_COMMAND_CALL_RETURN_PREFETCH_PREFETCH_Start 0
+#define GCREG_COMMAND_CALL_RETURN_PREFETCH_PREFETCH_Type U16
+
+/* Offset ReturnAddress
+** ~~~~~~~~~~~~~~~~~~~~ */
+
+#define GCREG_COMMAND_CALL_RETURN_ADDRESS_ADDRESS 31 : 0
+#define GCREG_COMMAND_CALL_RETURN_ADDRESS_ADDRESS_End 30
+#define GCREG_COMMAND_CALL_RETURN_ADDRESS_ADDRESS_Start 0
+#define GCREG_COMMAND_CALL_RETURN_ADDRESS_ADDRESS_Type U31
+
+struct gccmdcall {
+ /* gcregCommandCall:GCREG_COMMAND_CALL_PREFETCH */
+ unsigned int count:16;
+
+ /* gcregCommandCall:reserved */
+ unsigned int _reserved_16_26:11;
+
+ /* gcregCommandCall:GCREG_COMMAND_CALL_OPCODE */
+ unsigned int opcode:5;
+
+ /* gcregCommandCall:GCREG_COMMAND_CALL_ADDRESS_ADDRESS */
+ unsigned int address;
+
+ /* gcregCommandCall:GCREG_COMMAND_CALL_RETURN_PREFETCH_PREFETCH */
+ unsigned int retcount;
+
+ /* gcregCommandCall:GCREG_COMMAND_CALL_RETURN_ADDRESS_ADDRESS */
+ unsigned int retaddress;
+};
+
+/*******************************************************************************
+** Command gccmdCommandReturn
+*/
+
+#define GCREG_COMMAND_RETURN_OPCODE 31 : 27
+#define GCREG_COMMAND_RETURN_OPCODE_End 31
+#define GCREG_COMMAND_RETURN_OPCODE_Start 27
+#define GCREG_COMMAND_RETURN_OPCODE_Type U05
+
+struct gcfldret {
+ /* gccmdCommandReturn:reserved */
+ unsigned int _reserved_0_26:27;
+
+ /* gccmdCommandReturn:GCREG_COMMAND_RETURN_OPCODE */
+ unsigned int opcode:5;
+};
+
+struct gccmdret {
+ union {
+ struct gcfldret fld;
+ unsigned int raw;
+ }
+ cmd;
+
+ /* Alignment filler. */
+ unsigned int _filler;
+};
+
+static const struct gcfldret gcfldret = {
+ /* gccmdCommandReturn:reserved */
+ 0,
+
+ /* gccmdCommandReturn:GCREG_COMMAND_RETURN_OPCODE */
+ GCREG_COMMAND_OPCODE_RETURN
+};
+
+/*******************************************************************************
+** State gcregStall
+*/
+
+#define gcregStallRegAddrs 0x0F00
+#define GCREG_STALL_Count 1
+#define GCREG_STALL_ResetValue 0x00000000
+
+#define GCREG_STALL_FLIP0 30 : 30
+#define GCREG_STALL_FLIP0_End 30
+#define GCREG_STALL_FLIP0_Start 30
+#define GCREG_STALL_FLIP0_Type U01
+
+#define GCREG_STALL_FLIP1 31 : 31
+#define GCREG_STALL_FLIP1_End 31
+#define GCREG_STALL_FLIP1_Start 31
+#define GCREG_STALL_FLIP1_Type U01
+
+#define GCREG_STALL_SOURCE 4 : 0
+#define GCREG_STALL_SOURCE_End 4
+#define GCREG_STALL_SOURCE_Start 0
+#define GCREG_STALL_SOURCE_Type U05
+#define GCREG_STALL_SOURCE_FRONT_END 0x01
+#define GCREG_STALL_SOURCE_PIXEL_ENGINE 0x07
+#define GCREG_STALL_SOURCE_DRAWING_ENGINE 0x0B
+
+#define GCREG_STALL_DESTINATION 12 : 8
+#define GCREG_STALL_DESTINATION_End 12
+#define GCREG_STALL_DESTINATION_Start 8
+#define GCREG_STALL_DESTINATION_Type U05
+#define GCREG_STALL_DESTINATION_FRONT_END 0x01
+#define GCREG_STALL_DESTINATION_PIXEL_ENGINE 0x07
+#define GCREG_STALL_DESTINATION_DRAWING_ENGINE 0x0B
+
+/*******************************************************************************
+** State gcregPipeSelect
+*/
+
+/* Select the current graphics pipe. */
+
+#define gcregPipeSelectRegAddrs 0x0E00
+#define GCREG_PIPE_SELECT_MSB 15
+#define GCREG_PIPE_SELECT_LSB 0
+#define GCREG_PIPE_SELECT_BLK 0
+#define GCREG_PIPE_SELECT_Count 1
+#define GCREG_PIPE_SELECT_FieldMask 0x00000001
+#define GCREG_PIPE_SELECT_ReadMask 0x00000001
+#define GCREG_PIPE_SELECT_WriteMask 0x00000001
+#define GCREG_PIPE_SELECT_ResetValue 0x00000000
+
+/* Selects the pipe to send states and data to. Make sure the PE is idle **
+** before you switch pipes. */
+#define GCREG_PIPE_SELECT_PIPE 0 : 0
+#define GCREG_PIPE_SELECT_PIPE_End 0
+#define GCREG_PIPE_SELECT_PIPE_Start 0
+#define GCREG_PIPE_SELECT_PIPE_Type U01
+#define GCREG_PIPE_SELECT_PIPE_PIPE3D 0x0
+#define GCREG_PIPE_SELECT_PIPE_PIPE2D 0x1
+
+struct gcregpipeselect {
+ /* gcregPipeSelectRegAddrs:GCREG_PIPE_SELECT_PIPE */
+ unsigned int pipe:1;
+
+ /* gcregPipeSelectRegAddrs:reserved */
+ unsigned int _reserved_1_31:31;
+};
+
+static const struct gcregpipeselect gcregpipeselect_2D = {
+ /* gcregPipeSelectRegAddrs:GCREG_PIPE_SELECT_PIPE */
+ GCREG_PIPE_SELECT_PIPE_PIPE2D,
+
+ /* gcregPipeSelectRegAddrs:reserved */
+ 0
+};
+
+static const struct gcregpipeselect gcregpipeselect_3D = {
+ /* gcregPipeSelectRegAddrs:GCREG_PIPE_SELECT_PIPE */
+ GCREG_PIPE_SELECT_PIPE_PIPE3D,
+
+ /* gcregPipeSelectRegAddrs:reserved */
+ 0
+};
+
+/*******************************************************************************
+** State gcregEvent
+*/
+
+/* Send an event. */
+
+#define gcregEventRegAddrs 0x0E01
+#define GCREG_EVENT_MSB 15
+#define GCREG_EVENT_LSB 0
+#define GCREG_EVENT_BLK 0
+#define GCREG_EVENT_Count 1
+#define GCREG_EVENT_FieldMask 0x0000007F
+#define GCREG_EVENT_ReadMask 0x0000007F
+#define GCREG_EVENT_WriteMask 0x0000007F
+#define GCREG_EVENT_ResetValue 0x00000000
+
+/* 5-bit event ID to send. */
+#define GCREG_EVENT_EVENT_ID 4 : 0
+#define GCREG_EVENT_EVENT_ID_End 4
+#define GCREG_EVENT_EVENT_ID_Start 0
+#define GCREG_EVENT_EVENT_ID_Type U05
+
+/* The event is sent by the FE. */
+#define GCREG_EVENT_FE_SRC 5 : 5
+#define GCREG_EVENT_FE_SRC_End 5
+#define GCREG_EVENT_FE_SRC_Start 5
+#define GCREG_EVENT_FE_SRC_Type U01
+#define GCREG_EVENT_FE_SRC_DISABLE 0x0
+#define GCREG_EVENT_FE_SRC_ENABLE 0x1
+
+/* The event is sent by the PE. */
+#define GCREG_EVENT_PE_SRC 6 : 6
+#define GCREG_EVENT_PE_SRC_End 6
+#define GCREG_EVENT_PE_SRC_Start 6
+#define GCREG_EVENT_PE_SRC_Type U01
+#define GCREG_EVENT_PE_SRC_DISABLE 0x0
+#define GCREG_EVENT_PE_SRC_ENABLE 0x1
+
+struct gcregevent {
+ /* gcregEventRegAddrs:GCREG_EVENT_EVENT_ID */
+ unsigned int id:5;
+
+ /* gcregEventRegAddrs:GCREG_EVENT_FE_SRC */
+ unsigned int fe:1;
+
+ /* gcregEventRegAddrs:GCREG_EVENT_PE_SRC */
+ unsigned int pe:1;
+
+ /* gcregEventRegAddrs:reserved */
+ unsigned int _reserved_7_31:25;
+};
+
+/*******************************************************************************
+** State gcregSemaphore
+*/
+
+/* A sempahore state arms the semaphore in the destination. */
+
+#define gcregSemaphoreRegAddrs 0x0E02
+#define GCREG_SEMAPHORE_MSB 15
+#define GCREG_SEMAPHORE_LSB 0
+#define GCREG_SEMAPHORE_BLK 0
+#define GCREG_SEMAPHORE_Count 1
+#define GCREG_SEMAPHORE_FieldMask 0x00001F1F
+#define GCREG_SEMAPHORE_ReadMask 0x00001F1F
+#define GCREG_SEMAPHORE_WriteMask 0x00001F1F
+#define GCREG_SEMAPHORE_ResetValue 0x00000000
+
+#define GCREG_SEMAPHORE_SOURCE 4 : 0
+#define GCREG_SEMAPHORE_SOURCE_End 4
+#define GCREG_SEMAPHORE_SOURCE_Start 0
+#define GCREG_SEMAPHORE_SOURCE_Type U05
+#define GCREG_SEMAPHORE_SOURCE_FRONT_END 0x01
+#define GCREG_SEMAPHORE_SOURCE_PIXEL_ENGINE 0x07
+#define GCREG_SEMAPHORE_SOURCE_DRAWING_ENGINE 0x0B
+
+#define GCREG_SEMAPHORE_DESTINATION 12 : 8
+#define GCREG_SEMAPHORE_DESTINATION_End 12
+#define GCREG_SEMAPHORE_DESTINATION_Start 8
+#define GCREG_SEMAPHORE_DESTINATION_Type U05
+#define GCREG_SEMAPHORE_DESTINATION_FRONT_END 0x01
+#define GCREG_SEMAPHORE_DESTINATION_PIXEL_ENGINE 0x07
+#define GCREG_SEMAPHORE_DESTINATION_DRAWING_ENGINE 0x0B
+
+struct gcregsemaphore {
+ /* gcregSemaphoreRegAddrs:GCREG_SEMAPHORE_SOURCE */
+ unsigned int src:5;
+
+ /* gcregSemaphoreRegAddrs:reserved */
+ unsigned int _reserved_5_7:3;
+
+ /* gcregSemaphoreRegAddrs:GCREG_SEMAPHORE_DESTINATION */
+ unsigned int dst:5;
+
+ /* gcregSemaphoreRegAddrs:reserved */
+ unsigned int _reserved_13_31:19;
+};
+
+static const struct gcregsemaphore gcregsema_fe_pe = {
+ /* gcregSemaphoreRegAddrs:GCREG_SEMAPHORE_SOURCE */
+ GCREG_SEMAPHORE_SOURCE_FRONT_END,
+
+ /* gcregSemaphoreRegAddrs:reserved */
+ 0,
+
+ /* gcregSemaphoreRegAddrs:GCREG_SEMAPHORE_DESTINATION */
+ GCREG_SEMAPHORE_DESTINATION_PIXEL_ENGINE,
+
+ /* gcregSemaphoreRegAddrs:reserved */
+ 0
+};
+
+
+/*******************************************************************************
+** State gcregFlush
+*/
+
+/* Flush the current pipe. */
+
+#define gcregFlushRegAddrs 0x0E03
+#define GCREG_FLUSH_MSB 15
+#define GCREG_FLUSH_LSB 0
+#define GCREG_FLUSH_BLK 0
+#define GCREG_FLUSH_Count 1
+#define GCREG_FLUSH_FieldMask 0x00000008
+#define GCREG_FLUSH_ReadMask 0x00000008
+#define GCREG_FLUSH_WriteMask 0x00000008
+#define GCREG_FLUSH_ResetValue 0x00000000
+
+/* Flush the 2D pixel cache. */
+#define GCREG_FLUSH_PE2D_CACHE 3 : 3
+#define GCREG_FLUSH_PE2D_CACHE_End 3
+#define GCREG_FLUSH_PE2D_CACHE_Start 3
+#define GCREG_FLUSH_PE2D_CACHE_Type U01
+#define GCREG_FLUSH_PE2D_CACHE_DISABLE 0x0
+#define GCREG_FLUSH_PE2D_CACHE_ENABLE 0x1
+
+struct gcregflush {
+ /* gcregFlushRegAddrs:reserved */
+ unsigned int _reserved_0_2:3;
+
+ /* gcregFlushRegAddrs:GCREG_FLUSH_PE2D_CACHE */
+ unsigned int enable:1;
+
+ /* gcregFlushRegAddrs:reserved */
+ unsigned int _reserved_4_31:28;
+};
+
+static const struct gcregflush gcregflush_pe2D = {
+ /* gcregFlushRegAddrs:reserved */
+ 0,
+
+ /* gcregFlushRegAddrs:GCREG_FLUSH_PE2D_CACHE */
+ GCREG_FLUSH_PE2D_CACHE_ENABLE,
+
+ /* gcregFlushRegAddrs:reserved */
+ 0
+};
+
+/*******************************************************************************
+** State gcregMMUFlush
+*/
+
+/* Flush the virtual addrses lookup cache inside the MC. */
+
+#define gcregMMUFlushRegAddrs 0x0E04
+#define gcregMMU_FLUSH_MSB 15
+#define gcregMMU_FLUSH_LSB 0
+#define gcregMMU_FLUSH_BLK 0
+#define gcregMMU_FLUSH_Count 1
+#define gcregMMU_FLUSH_FieldMask 0x00000009
+#define gcregMMU_FLUSH_ReadMask 0x00000009
+#define gcregMMU_FLUSH_WriteMask 0x00000009
+#define gcregMMU_FLUSH_ResetValue 0x00000000
+
+/* Flush the FE address translation caches. */
+#define gcregMMU_FLUSH_FEMMU 0 : 0
+#define gcregMMU_FLUSH_FEMMU_End 0
+#define gcregMMU_FLUSH_FEMMU_Start 0
+#define gcregMMU_FLUSH_FEMMU_Type U01
+#define gcregMMU_FLUSH_FEMMU_DISABLE 0x0
+#define gcregMMU_FLUSH_FEMMU_ENABLE 0x1
+
+/* Flush the PE render target address translation caches. */
+#define gcregMMU_FLUSH_PEMMU 3 : 3
+#define gcregMMU_FLUSH_PEMMU_End 3
+#define gcregMMU_FLUSH_PEMMU_Start 3
+#define gcregMMU_FLUSH_PEMMU_Type U01
+#define gcregMMU_FLUSH_PEMMU_DISABLE 0x0
+#define gcregMMU_FLUSH_PEMMU_ENABLE 0x1
+
+/*******************************************************************************
+** Register gcregCmdBufferAddr
+*/
+
+/* Base address for the command buffer. The address must be 64-bit aligned
+** and it is always physical. This register cannot be read. To check the value
+** of the current fetch address use gcregFEDebugCurCmdAdr. Since this is a write
+** only register is has no reset value.
+*/
+
+#define GCREG_CMD_BUFFER_ADDR_Address 0x00654
+#define GCREG_CMD_BUFFER_ADDR_MSB 15
+#define GCREG_CMD_BUFFER_ADDR_LSB 0
+#define GCREG_CMD_BUFFER_ADDR_BLK 0
+#define GCREG_CMD_BUFFER_ADDR_Count 1
+#define GCREG_CMD_BUFFER_ADDR_FieldMask 0xFFFFFFFF
+#define GCREG_CMD_BUFFER_ADDR_ReadMask 0x00000000
+#define GCREG_CMD_BUFFER_ADDR_WriteMask 0xFFFFFFFC
+#define GCREG_CMD_BUFFER_ADDR_ResetValue 0x00000000
+
+#define GCREG_CMD_BUFFER_ADDR_ADDRESS 31 : 0
+#define GCREG_CMD_BUFFER_ADDR_ADDRESS_End 30
+#define GCREG_CMD_BUFFER_ADDR_ADDRESS_Start 0
+#define GCREG_CMD_BUFFER_ADDR_ADDRESS_Type U31
+
+/*******************************************************************************
+** Register gcregCmdBufferCtrl
+*/
+
+/* Since this is a write only register is has no reset value. */
+
+#define GCREG_CMD_BUFFER_CTRL_Address 0x00658
+#define GCREG_CMD_BUFFER_CTRL_MSB 15
+#define GCREG_CMD_BUFFER_CTRL_LSB 0
+#define GCREG_CMD_BUFFER_CTRL_BLK 0
+#define GCREG_CMD_BUFFER_CTRL_Count 1
+#define GCREG_CMD_BUFFER_CTRL_FieldMask 0x0001FFFF
+#define GCREG_CMD_BUFFER_CTRL_ReadMask 0x00010000
+#define GCREG_CMD_BUFFER_CTRL_WriteMask 0x0001FFFF
+#define GCREG_CMD_BUFFER_CTRL_ResetValue 0x00000000
+
+/* Number of 64-bit words to fetch from the command buffer. */
+#define GCREG_CMD_BUFFER_CTRL_PREFETCH 15 : 0
+#define GCREG_CMD_BUFFER_CTRL_PREFETCH_End 15
+#define GCREG_CMD_BUFFER_CTRL_PREFETCH_Start 0
+#define GCREG_CMD_BUFFER_CTRL_PREFETCH_Type U16
+
+/* Enable the command parser. */
+#define GCREG_CMD_BUFFER_CTRL_ENABLE 16 : 16
+#define GCREG_CMD_BUFFER_CTRL_ENABLE_End 16
+#define GCREG_CMD_BUFFER_CTRL_ENABLE_Start 16
+#define GCREG_CMD_BUFFER_CTRL_ENABLE_Type U01
+#define GCREG_CMD_BUFFER_CTRL_ENABLE_DISABLE 0x0
+#define GCREG_CMD_BUFFER_CTRL_ENABLE_ENABLE 0x1
+
+/*******************************************************************************
+** Register gcregFEDebugState
+*/
+
+#define GCREG_FE_DEBUG_STATE_Address 0x00660
+#define GCREG_FE_DEBUG_STATE_MSB 15
+#define GCREG_FE_DEBUG_STATE_LSB 0
+#define GCREG_FE_DEBUG_STATE_BLK 0
+#define GCREG_FE_DEBUG_STATE_Count 1
+#define GCREG_FE_DEBUG_STATE_FieldMask 0x0003FF1F
+#define GCREG_FE_DEBUG_STATE_ReadMask 0x0003FF1F
+#define GCREG_FE_DEBUG_STATE_WriteMask 0x00000000
+#define GCREG_FE_DEBUG_STATE_ResetValue 0x00000000
+
+#define GCREG_FE_DEBUG_STATE_CMD_STATE 4 : 0
+#define GCREG_FE_DEBUG_STATE_CMD_STATE_End 4
+#define GCREG_FE_DEBUG_STATE_CMD_STATE_Start 0
+#define GCREG_FE_DEBUG_STATE_CMD_STATE_Type U05
+
+#define GCREG_FE_DEBUG_STATE_CMD_DMA_STATE 9 : 8
+#define GCREG_FE_DEBUG_STATE_CMD_DMA_STATE_End 9
+#define GCREG_FE_DEBUG_STATE_CMD_DMA_STATE_Start 8
+#define GCREG_FE_DEBUG_STATE_CMD_DMA_STATE_Type U02
+
+#define GCREG_FE_DEBUG_STATE_CMD_FETCH_STATE 11 : 10
+#define GCREG_FE_DEBUG_STATE_CMD_FETCH_STATE_End 11
+#define GCREG_FE_DEBUG_STATE_CMD_FETCH_STATE_Start 10
+#define GCREG_FE_DEBUG_STATE_CMD_FETCH_STATE_Type U02
+
+#define GCREG_FE_DEBUG_STATE_REQ_DMA_STATE 13 : 12
+#define GCREG_FE_DEBUG_STATE_REQ_DMA_STATE_End 13
+#define GCREG_FE_DEBUG_STATE_REQ_DMA_STATE_Start 12
+#define GCREG_FE_DEBUG_STATE_REQ_DMA_STATE_Type U02
+
+#define GCREG_FE_DEBUG_STATE_CAL_STATE 15 : 14
+#define GCREG_FE_DEBUG_STATE_CAL_STATE_End 15
+#define GCREG_FE_DEBUG_STATE_CAL_STATE_Start 14
+#define GCREG_FE_DEBUG_STATE_CAL_STATE_Type U02
+
+#define GCREG_FE_DEBUG_STATE_VE_REQ_STATE 17 : 16
+#define GCREG_FE_DEBUG_STATE_VE_REQ_STATE_End 17
+#define GCREG_FE_DEBUG_STATE_VE_REQ_STATE_Start 16
+#define GCREG_FE_DEBUG_STATE_VE_REQ_STATE_Type U02
+
+/*******************************************************************************
+** Register gcregFEDebugCurCmdAdr
+*/
+
+/* This is the command decoder address. The address is always physical so
+** the MSB should always be 0. It has no reset value.
+*/
+
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_Address 0x00664
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_MSB 15
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_LSB 0
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_BLK 0
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_Count 1
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_FieldMask 0xFFFFFFF8
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_ReadMask 0xFFFFFFF8
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_WriteMask 0x00000000
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_ResetValue 0x00000000
+
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_CUR_CMD_ADR 31 : 3
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_CUR_CMD_ADR_End 31
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_CUR_CMD_ADR_Start 3
+#define GCREG_FE_DEBUG_CUR_CMD_ADR_CUR_CMD_ADR_Type U29
+
+/*******************************************************************************
+** Register gcregFEDebugCmdLowReg
+*/
+
+#define GCREG_FE_DEBUG_CMD_LOW_REG_Address 0x00668
+#define GCREG_FE_DEBUG_CMD_LOW_REG_MSB 15
+#define GCREG_FE_DEBUG_CMD_LOW_REG_LSB 0
+#define GCREG_FE_DEBUG_CMD_LOW_REG_BLK 0
+#define GCREG_FE_DEBUG_CMD_LOW_REG_Count 1
+#define GCREG_FE_DEBUG_CMD_LOW_REG_FieldMask 0xFFFFFFFF
+#define GCREG_FE_DEBUG_CMD_LOW_REG_ReadMask 0xFFFFFFFF
+#define GCREG_FE_DEBUG_CMD_LOW_REG_WriteMask 0x00000000
+#define GCREG_FE_DEBUG_CMD_LOW_REG_ResetValue 0x00000000
+
+/* Command register used by CmdState. */
+#define GCREG_FE_DEBUG_CMD_LOW_REG_CMD_LOW_REG 31 : 0
+#define GCREG_FE_DEBUG_CMD_LOW_REG_CMD_LOW_REG_End 31
+#define GCREG_FE_DEBUG_CMD_LOW_REG_CMD_LOW_REG_Start 0
+#define GCREG_FE_DEBUG_CMD_LOW_REG_CMD_LOW_REG_Type U32
+
+/*******************************************************************************
+** Register gcregFEDebugCmdHiReg
+*/
+
+#define GCREG_FE_DEBUG_CMD_HI_REG_Address 0x0066C
+#define GCREG_FE_DEBUG_CMD_HI_REG_MSB 15
+#define GCREG_FE_DEBUG_CMD_HI_REG_LSB 0
+#define GCREG_FE_DEBUG_CMD_HI_REG_BLK 0
+#define GCREG_FE_DEBUG_CMD_HI_REG_Count 1
+#define GCREG_FE_DEBUG_CMD_HI_REG_FieldMask 0xFFFFFFFF
+#define GCREG_FE_DEBUG_CMD_HI_REG_ReadMask 0xFFFFFFFF
+#define GCREG_FE_DEBUG_CMD_HI_REG_WriteMask 0x00000000
+#define GCREG_FE_DEBUG_CMD_HI_REG_ResetValue 0x00000000
+
+/* Command register used by CmdState. */
+#define GCREG_FE_DEBUG_CMD_HI_REG_CMD_HI_REG 31 : 0
+#define GCREG_FE_DEBUG_CMD_HI_REG_CMD_HI_REG_End 31
+#define GCREG_FE_DEBUG_CMD_HI_REG_CMD_HI_REG_Start 0
+#define GCREG_FE_DEBUG_CMD_HI_REG_CMD_HI_REG_Type U32
+
+/*******************************************************************************
+** State gcregMMUSafeAddress
+*/
+
+/* A 64-byte address that will acts as a 'safe' zone. Any address that would
+** cause an exception is routed to this safe zone. Reads will happend and
+** writes will go to this address, but with a write-enable of 0. This
+** register can only be programmed once after a reset - any attempt to write
+** to this register after the initial write-after-reset will be ignored.
+*/
+
+#define gcregMMUSafeAddressRegAddrs 0x0060
+#define GCREG_MMU_SAFE_ADDRESS_MSB 15
+#define GCREG_MMU_SAFE_ADDRESS_LSB 0
+#define GCREG_MMU_SAFE_ADDRESS_BLK 0
+#define GCREG_MMU_SAFE_ADDRESS_Count 1
+#define GCREG_MMU_SAFE_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_MMU_SAFE_ADDRESS_ReadMask 0xFFFFFFC0
+#define GCREG_MMU_SAFE_ADDRESS_WriteMask 0xFFFFFFC0
+#define GCREG_MMU_SAFE_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_MMU_SAFE_ADDRESS_ADDRESS 31 : 0
+#define GCREG_MMU_SAFE_ADDRESS_ADDRESS_End 31
+#define GCREG_MMU_SAFE_ADDRESS_ADDRESS_Start 0
+#define GCREG_MMU_SAFE_ADDRESS_ADDRESS_Type U32
+
+/*******************************************************************************
+** State gcregMMUConfiguration
+*/
+
+/* This register controls the master TLB of the MMU. */
+
+#define gcregMMUConfigurationRegAddrs 0x0061
+#define GCREG_MMU_CONFIGURATION_MSB 15
+#define GCREG_MMU_CONFIGURATION_LSB 0
+#define GCREG_MMU_CONFIGURATION_BLK 0
+#define GCREG_MMU_CONFIGURATION_Count 1
+#define GCREG_MMU_CONFIGURATION_FieldMask 0xFFFFFD99
+#define GCREG_MMU_CONFIGURATION_ReadMask 0xFFFFFD99
+#define GCREG_MMU_CONFIGURATION_WriteMask 0xFFFFFD99
+#define GCREG_MMU_CONFIGURATION_ResetValue 0x00000000
+
+/* Upper bits of the page aligned (depending on the mode) master TLB. */
+#define GCREG_MMU_CONFIGURATION_ADDRESS 31 : 10
+#define GCREG_MMU_CONFIGURATION_ADDRESS_End 31
+#define GCREG_MMU_CONFIGURATION_ADDRESS_Start 10
+#define GCREG_MMU_CONFIGURATION_ADDRESS_Type U22
+
+/* Mask for Address field. */
+#define GCREG_MMU_CONFIGURATION_MASK_ADDRESS 8 : 8
+#define GCREG_MMU_CONFIGURATION_MASK_ADDRESS_End 8
+#define GCREG_MMU_CONFIGURATION_MASK_ADDRESS_Start 8
+#define GCREG_MMU_CONFIGURATION_MASK_ADDRESS_Type U01
+#define GCREG_MMU_CONFIGURATION_MASK_ADDRESS_ENABLED 0x0
+#define GCREG_MMU_CONFIGURATION_MASK_ADDRESS_MASKED 0x1
+
+/* Mask Flush field. */
+#define GCREG_MMU_CONFIGURATION_MASK_FLUSH 7 : 7
+#define GCREG_MMU_CONFIGURATION_MASK_FLUSH_End 7
+#define GCREG_MMU_CONFIGURATION_MASK_FLUSH_Start 7
+#define GCREG_MMU_CONFIGURATION_MASK_FLUSH_Type U01
+#define GCREG_MMU_CONFIGURATION_MASK_FLUSH_ENABLED 0x0
+#define GCREG_MMU_CONFIGURATION_MASK_FLUSH_MASKED 0x1
+
+/* Flush the MMU caches. */
+#define GCREG_MMU_CONFIGURATION_FLUSH 4 : 4
+#define GCREG_MMU_CONFIGURATION_FLUSH_End 4
+#define GCREG_MMU_CONFIGURATION_FLUSH_Start 4
+#define GCREG_MMU_CONFIGURATION_FLUSH_Type U01
+#define GCREG_MMU_CONFIGURATION_FLUSH_FLUSH 0x1
+
+/* Mask Mode field. */
+#define GCREG_MMU_CONFIGURATION_MASK_MODE 3 : 3
+#define GCREG_MMU_CONFIGURATION_MASK_MODE_End 3
+#define GCREG_MMU_CONFIGURATION_MASK_MODE_Start 3
+#define GCREG_MMU_CONFIGURATION_MASK_MODE_Type U01
+#define GCREG_MMU_CONFIGURATION_MASK_MODE_ENABLED 0x0
+#define GCREG_MMU_CONFIGURATION_MASK_MODE_MASKED 0x1
+
+/* Set the mode for the Master TLB. */
+#define GCREG_MMU_CONFIGURATION_MODE 0 : 0
+#define GCREG_MMU_CONFIGURATION_MODE_End 0
+#define GCREG_MMU_CONFIGURATION_MODE_Start 0
+#define GCREG_MMU_CONFIGURATION_MODE_Type U01
+/* The Master TLB is 4kB in size and contains 1024 entries. Each page can be **
+** 4kB or 64kB in size. */
+#define GCREG_MMU_CONFIGURATION_MODE_MODE4_K 0x0
+/* The Master TLB is 1kB in size and contains 256 entries. Each page can be **
+** 4kB, 64kB, 1MB or 16MB in size. */
+#define GCREG_MMU_CONFIGURATION_MODE_MODE1_K 0x1
+
+struct gcregmmuconfiguration {
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MODE */
+ unsigned int master:1;
+
+ /* gcregMMUConfiguration:reserved */
+ unsigned int _reserved_1_2:2;
+
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_MODE */
+ unsigned int master_mask:1;
+
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_FLUSH */
+ unsigned int flush:1;
+
+ /* gcregMMUConfiguration:reserved */
+ unsigned int _reserved_5_6:2;
+
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_FLUSH */
+ unsigned int flush_mask:1;
+
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_ADDRESS */
+ unsigned int address_mask:1;
+
+ /* gcregMMUConfiguration:reserved */
+ unsigned int _reserved_9:1;
+
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_ADDRESS */
+ unsigned int address:22;
+};
+
+static const struct gcregmmuconfiguration gcregmmu_flush = {
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MODE */
+ 0,
+
+ /* gcregMMUConfiguration:reserved */
+ 0,
+
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_MODE */
+ GCREG_MMU_CONFIGURATION_MASK_MODE_MASKED,
+
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_FLUSH */
+ GCREG_MMU_CONFIGURATION_FLUSH_FLUSH,
+
+ /* gcregMMUConfiguration:reserved */
+ 0,
+
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_FLUSH */
+ GCREG_MMU_CONFIGURATION_MASK_FLUSH_ENABLED,
+
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_MASK_ADDRESS */
+ GCREG_MMU_CONFIGURATION_MASK_ADDRESS_MASKED,
+
+ /* gcregMMUConfiguration:reserved */
+ 0,
+
+ /* gcregMMUConfiguration:GCREG_MMU_CONFIGURATION_ADDRESS */
+ 0
+};
+
+/*******************************************************************************
+** Register gcregMMUStatus
+*/
+
+/* Status register that holds which MMU generated an exception. */
+
+#define GCREG_MMU_STATUS_Address 0x00188
+#define GCREG_MMU_STATUS_MSB 15
+#define GCREG_MMU_STATUS_LSB 0
+#define GCREG_MMU_STATUS_BLK 0
+#define GCREG_MMU_STATUS_Count 1
+#define GCREG_MMU_STATUS_FieldMask 0x00003333
+#define GCREG_MMU_STATUS_ReadMask 0x00003333
+#define GCREG_MMU_STATUS_WriteMask 0x00000000
+#define GCREG_MMU_STATUS_ResetValue 0x00000000
+
+/* MMU 3 caused an exception and the fourth gcregMMUException register holds **
+** the offending address. */
+#define GCREG_MMU_STATUS_EXCEPTION3 13 : 12
+#define GCREG_MMU_STATUS_EXCEPTION3_End 13
+#define GCREG_MMU_STATUS_EXCEPTION3_Start 12
+#define GCREG_MMU_STATUS_EXCEPTION3_Type U02
+#define GCREG_MMU_STATUS_EXCEPTION3_SLAVE_NOT_PRESENT 0x1
+#define GCREG_MMU_STATUS_EXCEPTION3_PAGE_NOT_PRESENT 0x2
+#define GCREG_MMU_STATUS_EXCEPTION3_WRITE_VIOLATION 0x3
+
+/* MMU 2 caused an exception and the third gcregMMUException register holds **
+** the offending address. */
+#define GCREG_MMU_STATUS_EXCEPTION2 9 : 8
+#define GCREG_MMU_STATUS_EXCEPTION2_End 9
+#define GCREG_MMU_STATUS_EXCEPTION2_Start 8
+#define GCREG_MMU_STATUS_EXCEPTION2_Type U02
+#define GCREG_MMU_STATUS_EXCEPTION2_SLAVE_NOT_PRESENT 0x1
+#define GCREG_MMU_STATUS_EXCEPTION2_PAGE_NOT_PRESENT 0x2
+#define GCREG_MMU_STATUS_EXCEPTION2_WRITE_VIOLATION 0x3
+
+/* MMU 1 caused an exception and the second gcregMMUException register holds **
+** the offending address. */
+#define GCREG_MMU_STATUS_EXCEPTION1 5 : 4
+#define GCREG_MMU_STATUS_EXCEPTION1_End 5
+#define GCREG_MMU_STATUS_EXCEPTION1_Start 4
+#define GCREG_MMU_STATUS_EXCEPTION1_Type U02
+#define GCREG_MMU_STATUS_EXCEPTION1_SLAVE_NOT_PRESENT 0x1
+#define GCREG_MMU_STATUS_EXCEPTION1_PAGE_NOT_PRESENT 0x2
+#define GCREG_MMU_STATUS_EXCEPTION1_WRITE_VIOLATION 0x3
+
+/* MMU 0 caused an exception and the first gcregMMUException register holds **
+** the offending address. */
+#define GCREG_MMU_STATUS_EXCEPTION0 1 : 0
+#define GCREG_MMU_STATUS_EXCEPTION0_End 1
+#define GCREG_MMU_STATUS_EXCEPTION0_Start 0
+#define GCREG_MMU_STATUS_EXCEPTION0_Type U02
+#define GCREG_MMU_STATUS_EXCEPTION0_SLAVE_NOT_PRESENT 0x1
+#define GCREG_MMU_STATUS_EXCEPTION0_PAGE_NOT_PRESENT 0x2
+#define GCREG_MMU_STATUS_EXCEPTION0_WRITE_VIOLATION 0x3
+
+/*******************************************************************************
+** Register gcregMMUControl
+*/
+
+/* Control register that enables the MMU (only time shot). */
+
+#define GCREG_MMU_CONTROL_Address 0x0018C
+#define GCREG_MMU_CONTROL_MSB 15
+#define GCREG_MMU_CONTROL_LSB 0
+#define GCREG_MMU_CONTROL_BLK 0
+#define GCREG_MMU_CONTROL_Count 1
+#define GCREG_MMU_CONTROL_FieldMask 0x00000001
+#define GCREG_MMU_CONTROL_ReadMask 0x00000000
+#define GCREG_MMU_CONTROL_WriteMask 0x00000001
+#define GCREG_MMU_CONTROL_ResetValue 0x00000000
+
+/* Enable the MMU. For security reasons, once the MMU is enabled it cannot **
+** be disabled anymore. */
+#define GCREG_MMU_CONTROL_ENABLE 0 : 0
+#define GCREG_MMU_CONTROL_ENABLE_End 0
+#define GCREG_MMU_CONTROL_ENABLE_Start 0
+#define GCREG_MMU_CONTROL_ENABLE_Type U01
+#define GCREG_MMU_CONTROL_ENABLE_ENABLE 0x1
+
+/*******************************************************************************
+** State/Register gcregMMUException (4 in total)
+*/
+
+/* Up to 4 registers that will hold the original address that generated an
+** exception. Use load state form for exception resolution.
+*/
+
+#define gcregMMUExceptionRegAddrs 0x0064
+#define GCREG_MMU_EXCEPTION_Address 0x00190
+#define GCREG_MMU_EXCEPTION_MSB 15
+#define GCREG_MMU_EXCEPTION_LSB 2
+#define GCREG_MMU_EXCEPTION_BLK 2
+#define GCREG_MMU_EXCEPTION_Count 4
+#define GCREG_MMU_EXCEPTION_FieldMask 0xFFFFFFFF
+#define GCREG_MMU_EXCEPTION_ReadMask 0xFFFFFFFF
+#define GCREG_MMU_EXCEPTION_WriteMask 0xFFFFFFFF
+#define GCREG_MMU_EXCEPTION_ResetValue 0x00000000
+
+#define GCREG_MMU_EXCEPTION_ADDRESS 31 : 0
+#define GCREG_MMU_EXCEPTION_ADDRESS_End 31
+#define GCREG_MMU_EXCEPTION_ADDRESS_Start 0
+#define GCREG_MMU_EXCEPTION_ADDRESS_Type U32
+
+/*******************************************************************************
+** Register gcModulePowerControls
+*/
+
+/* Control register for module level power controls. */
+
+#define GC_MODULE_POWER_CONTROLS_Address 0x00100
+#define GC_MODULE_POWER_CONTROLS_MSB 15
+#define GC_MODULE_POWER_CONTROLS_LSB 0
+#define GC_MODULE_POWER_CONTROLS_BLK 0
+#define GC_MODULE_POWER_CONTROLS_Count 1
+#define GC_MODULE_POWER_CONTROLS_FieldMask 0xFFFF00F7
+#define GC_MODULE_POWER_CONTROLS_ReadMask 0xFFFF00F7
+#define GC_MODULE_POWER_CONTROLS_WriteMask 0xFFFF00F7
+#define GC_MODULE_POWER_CONTROLS_ResetValue 0x00140020
+
+/* Enables module level clock gating. */
+#define GC_MODULE_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING 0 : 0
+#define GC_MODULE_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING_End 0
+#define GC_MODULE_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING_Start 0
+#define GC_MODULE_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING_Type U01
+
+/* Disables module level clock gating for stall condition. */
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING 1 : 1
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING_End 1
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING_Start 1
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING_Type U01
+
+/* Disables module level clock gating for starve/idle condition. */
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STARVE_MODULE_CLOCK_GATING 2 : 2
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STARVE_MODULE_CLOCK_GATING_End 2
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STARVE_MODULE_CLOCK_GATING_Start 2
+#define GC_MODULE_POWER_CONTROLS_DISABLE_STARVE_MODULE_CLOCK_GATING_Type U01
+
+/* Number of clock cycles to wait after turning on the clock. */
+#define GC_MODULE_POWER_CONTROLS_TURN_ON_COUNTER 7 : 4
+#define GC_MODULE_POWER_CONTROLS_TURN_ON_COUNTER_End 7
+#define GC_MODULE_POWER_CONTROLS_TURN_ON_COUNTER_Start 4
+#define GC_MODULE_POWER_CONTROLS_TURN_ON_COUNTER_Type U04
+
+/* Counter value for clock gating the module if the module is idle for this **
+** amount of clock cycles. */
+#define GC_MODULE_POWER_CONTROLS_TURN_OFF_COUNTER 31 : 16
+#define GC_MODULE_POWER_CONTROLS_TURN_OFF_COUNTER_End 31
+#define GC_MODULE_POWER_CONTROLS_TURN_OFF_COUNTER_Start 16
+#define GC_MODULE_POWER_CONTROLS_TURN_OFF_COUNTER_Type U16
+
+/*******************************************************************************
+** Register gcModulePowerModuleControl
+*/
+
+/* Module level control registers. */
+
+#define GC_MODULE_POWER_MODULE_CONTROL_Address 0x00104
+#define GC_MODULE_POWER_MODULE_CONTROL_MSB 15
+#define GC_MODULE_POWER_MODULE_CONTROL_LSB 0
+#define GC_MODULE_POWER_MODULE_CONTROL_BLK 0
+#define GC_MODULE_POWER_MODULE_CONTROL_Count 1
+#define GC_MODULE_POWER_MODULE_CONTROL_FieldMask 0x00000007
+#define GC_MODULE_POWER_MODULE_CONTROL_ReadMask 0x00000007
+#define GC_MODULE_POWER_MODULE_CONTROL_WriteMask 0x00000007
+#define GC_MODULE_POWER_MODULE_CONTROL_ResetValue 0x00000000
+
+/* Disables module level clock gating for FE. */
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_FE 0 : 0
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_FE_End 0
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_FE_Start 0
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_FE_Type U01
+
+/* Disables module level clock gating for DE. */
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_DE 1 : 1
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_DE_End 1
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_DE_Start 1
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_DE_Type U01
+
+/* Disables module level clock gating for PE. */
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_PE 2 : 2
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_PE_End 2
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_PE_Start 2
+#define GC_MODULE_POWER_MODULE_CONTROL_DISABLE_MODULE_CLOCK_GATING_PE_Type U01
+
+/*******************************************************************************
+** Register gcModulePowerModuleStatus
+*/
+
+/* Module level control status. */
+
+#define GC_MODULE_POWER_MODULE_STATUS_Address 0x00108
+#define GC_MODULE_POWER_MODULE_STATUS_MSB 15
+#define GC_MODULE_POWER_MODULE_STATUS_LSB 0
+#define GC_MODULE_POWER_MODULE_STATUS_BLK 0
+#define GC_MODULE_POWER_MODULE_STATUS_Count 1
+#define GC_MODULE_POWER_MODULE_STATUS_FieldMask 0x00000007
+#define GC_MODULE_POWER_MODULE_STATUS_ReadMask 0x00000007
+#define GC_MODULE_POWER_MODULE_STATUS_WriteMask 0x00000000
+#define GC_MODULE_POWER_MODULE_STATUS_ResetValue 0x00000000
+
+/* Module level clock gating is ON for FE. */
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_FE 0 : 0
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_FE_End 0
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_FE_Start 0
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_FE_Type U01
+
+/* Module level clock gating is ON for DE. */
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_DE 1 : 1
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_DE_End 1
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_DE_Start 1
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_DE_Type U01
+
+/* Module level clock gating is ON for PE. */
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_PE 2 : 2
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_PE_End 2
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_PE_Start 2
+#define GC_MODULE_POWER_MODULE_STATUS_MODULE_CLOCK_GATED_PE_Type U01
+
+/*******************************************************************************
+** State gcregSrcAddress
+*/
+
+/* 32-bit aligned base address of the source surface. */
+
+#define gcregSrcAddressRegAddrs 0x0480
+#define GCREG_SRC_ADDRESS_MSB 15
+#define GCREG_SRC_ADDRESS_LSB 0
+#define GCREG_SRC_ADDRESS_BLK 0
+#define GCREG_SRC_ADDRESS_Count 1
+#define GCREG_SRC_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_SRC_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_SRC_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_SRC_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_SRC_ADDRESS_ADDRESS 31 : 0
+#define GCREG_SRC_ADDRESS_ADDRESS_End 30
+#define GCREG_SRC_ADDRESS_ADDRESS_Start 0
+#define GCREG_SRC_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregSrcStride
+*/
+
+/* Stride of the source surface in bytes. To calculate the stride multiply
+** the surface width in pixels (8-pixel aligned) by the number of bytes per
+** pixel.
+*/
+
+#define gcregSrcStrideRegAddrs 0x0481
+#define GCREG_SRC_STRIDE_MSB 15
+#define GCREG_SRC_STRIDE_LSB 0
+#define GCREG_SRC_STRIDE_BLK 0
+#define GCREG_SRC_STRIDE_Count 1
+#define GCREG_SRC_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_SRC_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_SRC_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_SRC_STRIDE_ResetValue 0x00000000
+
+#define GCREG_SRC_STRIDE_STRIDE 17 : 0
+#define GCREG_SRC_STRIDE_STRIDE_End 17
+#define GCREG_SRC_STRIDE_STRIDE_Start 0
+#define GCREG_SRC_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State gcregSrcRotationConfig
+*/
+
+/* 90 degree rotation configuration for the source surface. Width field
+** specifies the width of the surface in pixels.
+*/
+
+#define gcregSrcRotationConfigRegAddrs 0x0482
+#define GCREG_SRC_ROTATION_CONFIG_MSB 15
+#define GCREG_SRC_ROTATION_CONFIG_LSB 0
+#define GCREG_SRC_ROTATION_CONFIG_BLK 0
+#define GCREG_SRC_ROTATION_CONFIG_Count 1
+#define GCREG_SRC_ROTATION_CONFIG_FieldMask 0x0001FFFF
+#define GCREG_SRC_ROTATION_CONFIG_ReadMask 0x0001FFFF
+#define GCREG_SRC_ROTATION_CONFIG_WriteMask 0x0001FFFF
+#define GCREG_SRC_ROTATION_CONFIG_ResetValue 0x00000000
+
+#define GCREG_SRC_ROTATION_CONFIG_WIDTH 15 : 0
+#define GCREG_SRC_ROTATION_CONFIG_WIDTH_End 15
+#define GCREG_SRC_ROTATION_CONFIG_WIDTH_Start 0
+#define GCREG_SRC_ROTATION_CONFIG_WIDTH_Type U16
+
+#define GCREG_SRC_ROTATION_CONFIG_ROTATION 16 : 16
+#define GCREG_SRC_ROTATION_CONFIG_ROTATION_End 16
+#define GCREG_SRC_ROTATION_CONFIG_ROTATION_Start 16
+#define GCREG_SRC_ROTATION_CONFIG_ROTATION_Type U01
+#define GCREG_SRC_ROTATION_CONFIG_ROTATION_DISABLE 0x0
+#define GCREG_SRC_ROTATION_CONFIG_ROTATION_ENABLE 0x1
+
+struct gcregsrcrotationconfig {
+ /* gcregSrcRotationConfigRegAddrs:GCREG_SRC_ROTATION_CONFIG_WIDTH */
+ unsigned int surf_width:16;
+
+ /* gcregSrcRotationConfigRegAddrs:GCREG_SRC_ROTATION_CONFIG_ROTATION */
+ unsigned int enable:1;
+
+ /* gcregSrcRotationConfigRegAddrs:reserved */
+ unsigned int _reserved_17_31:15;
+};
+
+/*******************************************************************************
+** State gcregSrcConfig
+*/
+
+/* Source surface configuration register. */
+
+#define gcregSrcConfigRegAddrs 0x0483
+#define GCREG_SRC_CONFIG_MSB 15
+#define GCREG_SRC_CONFIG_LSB 0
+#define GCREG_SRC_CONFIG_BLK 0
+#define GCREG_SRC_CONFIG_Count 1
+#define GCREG_SRC_CONFIG_FieldMask 0xFF31B1FF
+#define GCREG_SRC_CONFIG_ReadMask 0xFF31B1FF
+#define GCREG_SRC_CONFIG_WriteMask 0xFF31B1FF
+#define GCREG_SRC_CONFIG_ResetValue 0x00000000
+
+/* Control source endianess. */
+#define GCREG_SRC_CONFIG_ENDIAN_CONTROL 31 : 30
+#define GCREG_SRC_CONFIG_ENDIAN_CONTROL_End 31
+#define GCREG_SRC_CONFIG_ENDIAN_CONTROL_Start 30
+#define GCREG_SRC_CONFIG_ENDIAN_CONTROL_Type U02
+#define GCREG_SRC_CONFIG_ENDIAN_CONTROL_NO_SWAP 0x0
+#define GCREG_SRC_CONFIG_ENDIAN_CONTROL_SWAP_WORD 0x1
+#define GCREG_SRC_CONFIG_ENDIAN_CONTROL_SWAP_DWORD 0x2
+
+/* Disable 420 L2 cache NOTE: the field is valid for chips with 420 L2 cache **
+** defined. */
+#define GCREG_SRC_CONFIG_DISABLE420_L2_CACHE 29 : 29
+#define GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_End 29
+#define GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_Start 29
+#define GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_Type U01
+#define GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_ENABLED 0x0
+#define GCREG_SRC_CONFIG_DISABLE420_L2_CACHE_DISABLED 0x1
+
+/* Defines the pixel format of the source surface. */
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT 28 : 24
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_End 28
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_Start 24
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_Type U05
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_X4R4G4B4 0x00
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_A4R4G4B4 0x01
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_X1R5G5B5 0x02
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_A1R5G5B5 0x03
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_R5G6B5 0x04
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_X8R8G8B8 0x05
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_A8R8G8B8 0x06
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_YUY2 0x07
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_UYVY 0x08
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_INDEX8 0x09
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_MONOCHROME 0x0A
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_YV12 0x0F
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_A8 0x10
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_NV12 0x11
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_NV16 0x12
+#define GCREG_SRC_CONFIG_SOURCE_FORMAT_RG16 0x13
+
+/* Color channel swizzles. */
+#define GCREG_SRC_CONFIG_SWIZZLE 21 : 20
+#define GCREG_SRC_CONFIG_SWIZZLE_End 21
+#define GCREG_SRC_CONFIG_SWIZZLE_Start 20
+#define GCREG_SRC_CONFIG_SWIZZLE_Type U02
+#define GCREG_SRC_CONFIG_SWIZZLE_ARGB 0x0
+#define GCREG_SRC_CONFIG_SWIZZLE_RGBA 0x1
+#define GCREG_SRC_CONFIG_SWIZZLE_ABGR 0x2
+#define GCREG_SRC_CONFIG_SWIZZLE_BGRA 0x3
+
+/* Mono expansion: if 0, transparency color will be 0, otherwise transparency **
+** color will be 1. */
+#define GCREG_SRC_CONFIG_MONO_TRANSPARENCY 15 : 15
+#define GCREG_SRC_CONFIG_MONO_TRANSPARENCY_End 15
+#define GCREG_SRC_CONFIG_MONO_TRANSPARENCY_Start 15
+#define GCREG_SRC_CONFIG_MONO_TRANSPARENCY_Type U01
+#define GCREG_SRC_CONFIG_MONO_TRANSPARENCY_BACKGROUND 0x0
+#define GCREG_SRC_CONFIG_MONO_TRANSPARENCY_FOREGROUND 0x1
+
+/* Mono expansion or masked blit: stream packing in pixels. Determines how **
+** many horizontal pixels are there per each 32-bit chunk. For example, if **
+** set to Packed8, each 32-bit chunk is 8-pixel wide, which also means that **
+** it defines 4 vertical lines of pixels. */
+#define GCREG_SRC_CONFIG_PACK 13 : 12
+#define GCREG_SRC_CONFIG_PACK_End 13
+#define GCREG_SRC_CONFIG_PACK_Start 12
+#define GCREG_SRC_CONFIG_PACK_Type U02
+#define GCREG_SRC_CONFIG_PACK_PACKED8 0x0
+#define GCREG_SRC_CONFIG_PACK_PACKED16 0x1
+#define GCREG_SRC_CONFIG_PACK_PACKED32 0x2
+#define GCREG_SRC_CONFIG_PACK_UNPACKED 0x3
+
+/* Source data location: set to STREAM for mono expansion blits or masked **
+** blits. For mono expansion blits the complete bitmap comes from the command **
+** stream. For masked blits the source data comes from the memory and the **
+** mask from the command stream. */
+#define GCREG_SRC_CONFIG_LOCATION 8 : 8
+#define GCREG_SRC_CONFIG_LOCATION_End 8
+#define GCREG_SRC_CONFIG_LOCATION_Start 8
+#define GCREG_SRC_CONFIG_LOCATION_Type U01
+#define GCREG_SRC_CONFIG_LOCATION_MEMORY 0x0
+#define GCREG_SRC_CONFIG_LOCATION_STREAM 0x1
+
+/* Source linear/tiled address computation control. */
+#define GCREG_SRC_CONFIG_TILED 7 : 7
+#define GCREG_SRC_CONFIG_TILED_End 7
+#define GCREG_SRC_CONFIG_TILED_Start 7
+#define GCREG_SRC_CONFIG_TILED_Type U01
+#define GCREG_SRC_CONFIG_TILED_DISABLED 0x0
+#define GCREG_SRC_CONFIG_TILED_ENABLED 0x1
+
+/* If set to ABSOLUTE, the source coordinates are treated as absolute **
+** coordinates inside the source surface. If set to RELATIVE, the source **
+** coordinates are treated as the offsets from the destination coordinates **
+** with the source size equal to the size of the destination. */
+#define GCREG_SRC_CONFIG_SRC_RELATIVE 6 : 6
+#define GCREG_SRC_CONFIG_SRC_RELATIVE_End 6
+#define GCREG_SRC_CONFIG_SRC_RELATIVE_Start 6
+#define GCREG_SRC_CONFIG_SRC_RELATIVE_Type U01
+#define GCREG_SRC_CONFIG_SRC_RELATIVE_ABSOLUTE 0x0
+#define GCREG_SRC_CONFIG_SRC_RELATIVE_RELATIVE 0x1
+
+struct gcregsrcconfig {
+ /* gcregSrcConfigRegAddrs:reserved */
+ unsigned int _reserved_0_5:6;
+
+ /* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_SRC_RELATIVE */
+ unsigned int relative:1;
+
+ /* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_TILED */
+ unsigned int tiled:1;
+
+ /* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_LOCATION */
+ unsigned int stream:1;
+
+ /* gcregSrcConfigRegAddrs:reserved */
+ unsigned int _reserved_9_11:3;
+
+ /* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_PACK */
+ unsigned int monopack:2;
+
+ /* gcregSrcConfigRegAddrs:reserved */
+ unsigned int _reserved_14:1;
+
+ /* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_MONO_TRANSPARENCY */
+ unsigned int monotransp:1;
+
+ /* gcregSrcConfigRegAddrs:reserved */
+ unsigned int _reserved_16_19:4;
+
+ /* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_SWIZZLE */
+ unsigned int swizzle:2;
+
+ /* gcregSrcConfigRegAddrs:reserved */
+ unsigned int _reserved_22_23:2;
+
+ /* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_SOURCE_FORMAT */
+ unsigned int format:5;
+
+ /* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_DISABLE420_L2_CACHE */
+ unsigned int disable420L2cache:1;
+
+ /* gcregSrcConfigRegAddrs:GCREG_SRC_CONFIG_ENDIAN_CONTROL */
+ unsigned int endian:2;
+};
+
+/*******************************************************************************
+** State gcregSrcOrigin
+*/
+
+/* Absolute or relative (see SRC_RELATIVE field of gcregSrcConfig register) X
+** and Y coordinates in pixels of the top left corner of the source rectangle
+** within the source surface.
+*/
+
+#define gcregSrcOriginRegAddrs 0x0484
+#define GCREG_SRC_ORIGIN_MSB 15
+#define GCREG_SRC_ORIGIN_LSB 0
+#define GCREG_SRC_ORIGIN_BLK 0
+#define GCREG_SRC_ORIGIN_Count 1
+#define GCREG_SRC_ORIGIN_FieldMask 0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_ReadMask 0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_WriteMask 0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_ResetValue 0x00000000
+
+#define GCREG_SRC_ORIGIN_Y 31 : 16
+#define GCREG_SRC_ORIGIN_Y_End 31
+#define GCREG_SRC_ORIGIN_Y_Start 16
+#define GCREG_SRC_ORIGIN_Y_Type U16
+
+#define GCREG_SRC_ORIGIN_X 15 : 0
+#define GCREG_SRC_ORIGIN_X_End 15
+#define GCREG_SRC_ORIGIN_X_Start 0
+#define GCREG_SRC_ORIGIN_X_Type U16
+
+struct gcregsrcorigin {
+ /* gcregSrcOriginRegAddrs:GCREG_SRC_ORIGIN_X */
+ unsigned int x:16;
+
+ /* gcregSrcOriginRegAddrs:GCREG_SRC_ORIGIN_Y */
+ unsigned int y:16;
+};
+
+static const struct gcregsrcorigin gcregsrcorigin_min = {
+ /* gcregSrcOriginRegAddrs:GCREG_SRC_ORIGIN_X */
+ 0,
+
+ /* gcregSrcOriginRegAddrs:GCREG_SRC_ORIGIN_Y */
+ 0
+};
+
+/*******************************************************************************
+** State gcregSrcSize
+*/
+
+/* Width and height of the source rectangle in pixels. If the source is
+** relative (see SRC_RELATIVE field of gcregSrcConfig register) or a regular
+** bitblt is being performed without stretching, this register is ignored and
+** the source size is assumed to be the same as the destination.
+*/
+
+#define gcregSrcSizeRegAddrs 0x0485
+#define GCREG_SRC_SIZE_MSB 15
+#define GCREG_SRC_SIZE_LSB 0
+#define GCREG_SRC_SIZE_BLK 0
+#define GCREG_SRC_SIZE_Count 1
+#define GCREG_SRC_SIZE_FieldMask 0xFFFFFFFF
+#define GCREG_SRC_SIZE_ReadMask 0xFFFFFFFF
+#define GCREG_SRC_SIZE_WriteMask 0xFFFFFFFF
+#define GCREG_SRC_SIZE_ResetValue 0x00000000
+
+#define GCREG_SRC_SIZE_Y 31 : 16
+#define GCREG_SRC_SIZE_Y_End 31
+#define GCREG_SRC_SIZE_Y_Start 16
+#define GCREG_SRC_SIZE_Y_Type U16
+
+#define GCREG_SRC_SIZE_X 15 : 0
+#define GCREG_SRC_SIZE_X_End 15
+#define GCREG_SRC_SIZE_X_Start 0
+#define GCREG_SRC_SIZE_X_Type U16
+
+struct gcregsrcsize {
+ /* gcregSrcOriginRegAddrs:GCREG_SRC_SIZE_X */
+ unsigned int width:16;
+
+ /* gcregSrcOriginRegAddrs:GCREG_SRC_SIZE_Y */
+ unsigned int height:16;
+};
+
+static const struct gcregsrcsize gcregsrcsize_max = {
+ /* gcregSrcOriginRegAddrs:GCREG_SRC_SIZE_X */
+ 32767,
+
+ /* gcregSrcOriginRegAddrs:GCREG_SRC_SIZE_Y */
+ 32767
+};
+
+/*******************************************************************************
+** State gcregSrcColorBg
+*/
+
+/* In mono expansion defines the source color if the mono pixel is 0. The color
+** must be set in A8R8G8B8 format. In color blits defines the source
+** transparency color and must be of the same format as the source surface.
+*/
+
+#define gcregSrcColorBgRegAddrs 0x0486
+#define GCREG_SRC_COLOR_BG_MSB 15
+#define GCREG_SRC_COLOR_BG_LSB 0
+#define GCREG_SRC_COLOR_BG_BLK 0
+#define GCREG_SRC_COLOR_BG_Count 1
+#define GCREG_SRC_COLOR_BG_FieldMask 0xFFFFFFFF
+#define GCREG_SRC_COLOR_BG_ReadMask 0xFFFFFFFF
+#define GCREG_SRC_COLOR_BG_WriteMask 0xFFFFFFFF
+#define GCREG_SRC_COLOR_BG_ResetValue 0x00000000
+
+#define GCREG_SRC_COLOR_BG_ALPHA 31 : 24
+#define GCREG_SRC_COLOR_BG_ALPHA_End 31
+#define GCREG_SRC_COLOR_BG_ALPHA_Start 24
+#define GCREG_SRC_COLOR_BG_ALPHA_Type U08
+
+#define GCREG_SRC_COLOR_BG_RED 23 : 16
+#define GCREG_SRC_COLOR_BG_RED_End 23
+#define GCREG_SRC_COLOR_BG_RED_Start 16
+#define GCREG_SRC_COLOR_BG_RED_Type U08
+
+#define GCREG_SRC_COLOR_BG_GREEN 15 : 8
+#define GCREG_SRC_COLOR_BG_GREEN_End 15
+#define GCREG_SRC_COLOR_BG_GREEN_Start 8
+#define GCREG_SRC_COLOR_BG_GREEN_Type U08
+
+#define GCREG_SRC_COLOR_BG_BLUE 7 : 0
+#define GCREG_SRC_COLOR_BG_BLUE_End 7
+#define GCREG_SRC_COLOR_BG_BLUE_Start 0
+#define GCREG_SRC_COLOR_BG_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregSrcColorFg
+*/
+
+/* In mono expansion defines the source color if the mono pixel is 1. The color
+** must be set in A8R8G8B8.
+*/
+
+#define gcregSrcColorFgRegAddrs 0x0487
+#define GCREG_SRC_COLOR_FG_MSB 15
+#define GCREG_SRC_COLOR_FG_LSB 0
+#define GCREG_SRC_COLOR_FG_BLK 0
+#define GCREG_SRC_COLOR_FG_Count 1
+#define GCREG_SRC_COLOR_FG_FieldMask 0xFFFFFFFF
+#define GCREG_SRC_COLOR_FG_ReadMask 0xFFFFFFFF
+#define GCREG_SRC_COLOR_FG_WriteMask 0xFFFFFFFF
+#define GCREG_SRC_COLOR_FG_ResetValue 0x00000000
+
+#define GCREG_SRC_COLOR_FG_ALPHA 31 : 24
+#define GCREG_SRC_COLOR_FG_ALPHA_End 31
+#define GCREG_SRC_COLOR_FG_ALPHA_Start 24
+#define GCREG_SRC_COLOR_FG_ALPHA_Type U08
+
+#define GCREG_SRC_COLOR_FG_RED 23 : 16
+#define GCREG_SRC_COLOR_FG_RED_End 23
+#define GCREG_SRC_COLOR_FG_RED_Start 16
+#define GCREG_SRC_COLOR_FG_RED_Type U08
+
+#define GCREG_SRC_COLOR_FG_GREEN 15 : 8
+#define GCREG_SRC_COLOR_FG_GREEN_End 15
+#define GCREG_SRC_COLOR_FG_GREEN_Start 8
+#define GCREG_SRC_COLOR_FG_GREEN_Type U08
+
+#define GCREG_SRC_COLOR_FG_BLUE 7 : 0
+#define GCREG_SRC_COLOR_FG_BLUE_End 7
+#define GCREG_SRC_COLOR_FG_BLUE_Start 0
+#define GCREG_SRC_COLOR_FG_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregStretchFactorLow
+*/
+
+#define gcregStretchFactorLowRegAddrs 0x0488
+#define GCREG_STRETCH_FACTOR_LOW_MSB 15
+#define GCREG_STRETCH_FACTOR_LOW_LSB 0
+#define GCREG_STRETCH_FACTOR_LOW_BLK 0
+#define GCREG_STRETCH_FACTOR_LOW_Count 1
+#define GCREG_STRETCH_FACTOR_LOW_FieldMask 0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_LOW_ReadMask 0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_LOW_WriteMask 0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_LOW_ResetValue 0x00000000
+
+/* Horizontal stretch factor in 15.16 fixed point format. The value is **
+** calculated using the following formula: factor = ((srcWidth - 1) << 16) / **
+** (dstWidth - 1). Stretch blit uses only the integer part of the value, **
+** while Filter blit uses all 31 bits. */
+#define GCREG_STRETCH_FACTOR_LOW_X 30 : 0
+#define GCREG_STRETCH_FACTOR_LOW_X_End 30
+#define GCREG_STRETCH_FACTOR_LOW_X_Start 0
+#define GCREG_STRETCH_FACTOR_LOW_X_Type U31
+
+/*******************************************************************************
+** State gcregStretchFactorHigh
+*/
+
+#define gcregStretchFactorHighRegAddrs 0x0489
+#define GCREG_STRETCH_FACTOR_HIGH_MSB 15
+#define GCREG_STRETCH_FACTOR_HIGH_LSB 0
+#define GCREG_STRETCH_FACTOR_LOW_HIGH_BLK 0
+#define GCREG_STRETCH_FACTOR_HIGH_Count 1
+#define GCREG_STRETCH_FACTOR_HIGH_FieldMask 0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_HIGH_ReadMask 0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_HIGH_WriteMask 0x7FFFFFFF
+#define GCREG_STRETCH_FACTOR_HIGH_ResetValue 0x00000000
+
+/* Vertical stretch factor in 15.16 fixed point format. The value is **
+** calculated using the following formula: factor = ((srcHeight - 1) << 16) / **
+** (dstHeight - 1). Stretch blit uses only the integer part of the value, **
+** while Filter blit uses all 31 bits. */
+#define GCREG_STRETCH_FACTOR_HIGH_Y 30 : 0
+#define GCREG_STRETCH_FACTOR_HIGH_Y_End 30
+#define GCREG_STRETCH_FACTOR_HIGH_Y_Start 0
+#define GCREG_STRETCH_FACTOR_HIGH_Y_Type U31
+
+/*******************************************************************************
+** State gcregDestAddress
+*/
+
+/* 32-bit aligned base address of the destination surface. */
+
+#define gcregDestAddressRegAddrs 0x048A
+#define GCREG_DEST_ADDRESS_MSB 15
+#define GCREG_DEST_ADDRESS_LSB 0
+#define GCREG_DEST_ADDRESS_BLK 0
+#define GCREG_DEST_ADDRESS_Count 1
+#define GCREG_DEST_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_DEST_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_DEST_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_DEST_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_DEST_ADDRESS_ADDRESS 31 : 0
+#define GCREG_DEST_ADDRESS_ADDRESS_End 30
+#define GCREG_DEST_ADDRESS_ADDRESS_Start 0
+#define GCREG_DEST_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregDestStride
+*/
+
+/* Stride of the destination surface in bytes. To calculate the stride
+** multiply the surface width in pixels (8-pixel aligned) by the number of
+** bytes per pixel.
+*/
+
+#define gcregDestStrideRegAddrs 0x048B
+#define GCREG_DEST_STRIDE_MSB 15
+#define GCREG_DEST_STRIDE_LSB 0
+#define GCREG_DEST_STRIDE_BLK 0
+#define GCREG_DEST_STRIDE_Count 1
+#define GCREG_DEST_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_DEST_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_DEST_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_DEST_STRIDE_ResetValue 0x00000000
+
+#define GCREG_DEST_STRIDE_STRIDE 17 : 0
+#define GCREG_DEST_STRIDE_STRIDE_End 17
+#define GCREG_DEST_STRIDE_STRIDE_Start 0
+#define GCREG_DEST_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State gcregDestRotationConfig
+*/
+
+/* 90 degree rotation configuration for the destination surface. Width field
+** specifies the width of the surface in pixels.
+*/
+
+#define gcregDestRotationConfigRegAddrs 0x048C
+#define GCREG_DEST_ROTATION_CONFIG_MSB 15
+#define GCREG_DEST_ROTATION_CONFIG_LSB 0
+#define GCREG_DEST_ROTATION_CONFIG_BLK 0
+#define GCREG_DEST_ROTATION_CONFIG_Count 1
+#define GCREG_DEST_ROTATION_CONFIG_FieldMask 0x0001FFFF
+#define GCREG_DEST_ROTATION_CONFIG_ReadMask 0x0001FFFF
+#define GCREG_DEST_ROTATION_CONFIG_WriteMask 0x0001FFFF
+#define GCREG_DEST_ROTATION_CONFIG_ResetValue 0x00000000
+
+#define GCREG_DEST_ROTATION_CONFIG_WIDTH 15 : 0
+#define GCREG_DEST_ROTATION_CONFIG_WIDTH_End 15
+#define GCREG_DEST_ROTATION_CONFIG_WIDTH_Start 0
+#define GCREG_DEST_ROTATION_CONFIG_WIDTH_Type U16
+
+#define GCREG_DEST_ROTATION_CONFIG_ROTATION 16 : 16
+#define GCREG_DEST_ROTATION_CONFIG_ROTATION_End 16
+#define GCREG_DEST_ROTATION_CONFIG_ROTATION_Start 16
+#define GCREG_DEST_ROTATION_CONFIG_ROTATION_Type U01
+#define GCREG_DEST_ROTATION_CONFIG_ROTATION_DISABLE 0x0
+#define GCREG_DEST_ROTATION_CONFIG_ROTATION_ENABLE 0x1
+
+struct gcregdstrotationconfig {
+ /* gcregDestRotationConfigRegAddrs:GCREG_DEST_ROTATION_CONFIG_WIDTH */
+ unsigned int surf_width:16;
+
+ /* gcregDestRotationConfigRegAddrs:GCREG_DEST_ROTATION_CONFIG_ROTATION*/
+ unsigned int enable:1;
+
+ /* gcregDestRotationConfigRegAddrs:reserved */
+ unsigned int _reserved_17_31:15;
+};
+
+/*******************************************************************************
+** State gcregDestConfig
+*/
+
+/* Destination surface configuration register. */
+
+#define gcregDestConfigRegAddrs 0x048D
+#define GCREG_DEST_CONFIG_MSB 15
+#define GCREG_DEST_CONFIG_LSB 0
+#define GCREG_DEST_CONFIG_BLK 0
+#define GCREG_DEST_CONFIG_Count 1
+#define GCREG_DEST_CONFIG_FieldMask 0x0733F11F
+#define GCREG_DEST_CONFIG_ReadMask 0x0733F11F
+#define GCREG_DEST_CONFIG_WriteMask 0x0733F11F
+#define GCREG_DEST_CONFIG_ResetValue 0x00000000
+
+/* MinorTile. */
+#define GCREG_DEST_CONFIG_MINOR_TILED 26 : 26
+#define GCREG_DEST_CONFIG_MINOR_TILED_End 26
+#define GCREG_DEST_CONFIG_MINOR_TILED_Start 26
+#define GCREG_DEST_CONFIG_MINOR_TILED_Type U01
+#define GCREG_DEST_CONFIG_MINOR_TILED_DISABLED 0x0
+#define GCREG_DEST_CONFIG_MINOR_TILED_ENABLED 0x1
+
+/* Performance fix for de. */
+#define GCREG_DEST_CONFIG_INTER_TILE_PER_FIX 25 : 25
+#define GCREG_DEST_CONFIG_INTER_TILE_PER_FIX_End 25
+#define GCREG_DEST_CONFIG_INTER_TILE_PER_FIX_Start 25
+#define GCREG_DEST_CONFIG_INTER_TILE_PER_FIX_Type U01
+#define GCREG_DEST_CONFIG_INTER_TILE_PER_FIX_DISABLED 0x1
+#define GCREG_DEST_CONFIG_INTER_TILE_PER_FIX_ENABLED 0x0
+
+/* Control GDI Strecth Blit. */
+#define GCREG_DEST_CONFIG_GDI_STRE 24 : 24
+#define GCREG_DEST_CONFIG_GDI_STRE_End 24
+#define GCREG_DEST_CONFIG_GDI_STRE_Start 24
+#define GCREG_DEST_CONFIG_GDI_STRE_Type U01
+#define GCREG_DEST_CONFIG_GDI_STRE_DISABLED 0x0
+#define GCREG_DEST_CONFIG_GDI_STRE_ENABLED 0x1
+
+/* Control destination endianess. */
+#define GCREG_DEST_CONFIG_ENDIAN_CONTROL 21 : 20
+#define GCREG_DEST_CONFIG_ENDIAN_CONTROL_End 21
+#define GCREG_DEST_CONFIG_ENDIAN_CONTROL_Start 20
+#define GCREG_DEST_CONFIG_ENDIAN_CONTROL_Type U02
+#define GCREG_DEST_CONFIG_ENDIAN_CONTROL_NO_SWAP 0x0
+#define GCREG_DEST_CONFIG_ENDIAN_CONTROL_SWAP_WORD 0x1
+#define GCREG_DEST_CONFIG_ENDIAN_CONTROL_SWAP_DWORD 0x2
+
+/* Color channel swizzles. */
+#define GCREG_DEST_CONFIG_SWIZZLE 17 : 16
+#define GCREG_DEST_CONFIG_SWIZZLE_End 17
+#define GCREG_DEST_CONFIG_SWIZZLE_Start 16
+#define GCREG_DEST_CONFIG_SWIZZLE_Type U02
+#define GCREG_DEST_CONFIG_SWIZZLE_ARGB 0x0
+#define GCREG_DEST_CONFIG_SWIZZLE_RGBA 0x1
+#define GCREG_DEST_CONFIG_SWIZZLE_ABGR 0x2
+#define GCREG_DEST_CONFIG_SWIZZLE_BGRA 0x3
+
+/* Determines the type of primitive to be rendered. BIT_BLT_REVERSED and **
+** INVALID_COMMAND values are defined for internal use and should not be **
+** used. */
+#define GCREG_DEST_CONFIG_COMMAND 15 : 12
+#define GCREG_DEST_CONFIG_COMMAND_End 15
+#define GCREG_DEST_CONFIG_COMMAND_Start 12
+#define GCREG_DEST_CONFIG_COMMAND_Type U04
+#define GCREG_DEST_CONFIG_COMMAND_CLEAR 0x0
+#define GCREG_DEST_CONFIG_COMMAND_LINE 0x1
+#define GCREG_DEST_CONFIG_COMMAND_BIT_BLT 0x2
+#define GCREG_DEST_CONFIG_COMMAND_BIT_BLT_REVERSED 0x3
+#define GCREG_DEST_CONFIG_COMMAND_STRETCH_BLT 0x4
+#define GCREG_DEST_CONFIG_COMMAND_HOR_FILTER_BLT 0x5
+#define GCREG_DEST_CONFIG_COMMAND_VER_FILTER_BLT 0x6
+#define GCREG_DEST_CONFIG_COMMAND_ONE_PASS_FILTER_BLT 0x7
+#define GCREG_DEST_CONFIG_COMMAND_MULTI_SOURCE_BLT 0x8
+
+/* Destination linear/tiled address computation control. Reserved field for **
+** future expansion. */
+#define GCREG_DEST_CONFIG_TILED 8 : 8
+#define GCREG_DEST_CONFIG_TILED_End 8
+#define GCREG_DEST_CONFIG_TILED_Start 8
+#define GCREG_DEST_CONFIG_TILED_Type U01
+#define GCREG_DEST_CONFIG_TILED_DISABLED 0x0
+#define GCREG_DEST_CONFIG_TILED_ENABLED 0x1
+
+/* Defines the pixel format of the destination surface. */
+#define GCREG_DEST_CONFIG_FORMAT 4 : 0
+#define GCREG_DEST_CONFIG_FORMAT_End 4
+#define GCREG_DEST_CONFIG_FORMAT_Start 0
+#define GCREG_DEST_CONFIG_FORMAT_Type U05
+#define GCREG_DEST_CONFIG_FORMAT_X4R4G4B4 0x00
+#define GCREG_DEST_CONFIG_FORMAT_A4R4G4B4 0x01
+#define GCREG_DEST_CONFIG_FORMAT_X1R5G5B5 0x02
+#define GCREG_DEST_CONFIG_FORMAT_A1R5G5B5 0x03
+#define GCREG_DEST_CONFIG_FORMAT_R5G6B5 0x04
+#define GCREG_DEST_CONFIG_FORMAT_X8R8G8B8 0x05
+#define GCREG_DEST_CONFIG_FORMAT_A8R8G8B8 0x06
+#define GCREG_DEST_CONFIG_FORMAT_YUY2 0x07
+#define GCREG_DEST_CONFIG_FORMAT_UYVY 0x08
+#define GCREG_DEST_CONFIG_FORMAT_INDEX8 0x09
+#define GCREG_DEST_CONFIG_FORMAT_MONOCHROME 0x0A
+#define GCREG_DEST_CONFIG_FORMAT_YV12 0x0F
+#define GCREG_DEST_CONFIG_FORMAT_A8 0x10
+#define GCREG_DEST_CONFIG_FORMAT_NV12 0x11
+#define GCREG_DEST_CONFIG_FORMAT_NV16 0x12
+#define GCREG_DEST_CONFIG_FORMAT_RG16 0x13
+
+struct gcregdstconfig {
+ /* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_FORMAT */
+ unsigned int format:5;
+
+ /* gcregDestConfigRegAddrs:reserved */
+ unsigned int _reserved_5_7:3;
+
+ /* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_TILED */
+ unsigned int tiled:1;
+
+ /* gcregDestConfigRegAddrs:reserved */
+ unsigned int _reserved_9_11:3;
+
+ /* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_COMMAND */
+ unsigned int command:4;
+
+ /* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_SWIZZLE */
+ unsigned int swizzle:2;
+
+ /* gcregDestConfigRegAddrs:reserved */
+ unsigned int _reserved_18_19:2;
+
+ /* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_ENDIAN_CONTROL */
+ unsigned int endian:2;
+
+ /* gcregDestConfigRegAddrs:reserved */
+ unsigned int _reserved_22_23:2;
+
+ /* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_GDI_STRE */
+ unsigned int gdi:1;
+
+ /* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_INTER_TILE_PER_FIX */
+ unsigned int inner_tile_fix:1;
+
+ /* gcregDestConfigRegAddrs:GCREG_DEST_CONFIG_MINOR_TILED */
+ unsigned int minor_tile:1;
+
+ /* gcregDestConfigRegAddrs:reserved */
+ unsigned int _reserved_27_31:5;
+};
+
+/*******************************************************************************
+** State gcregFilterKernel
+*/
+
+/* Filter blit coefficient table. The algorithm uses 5 bits of pixel
+** coordinate's fraction to index the kernel array, which makes it a 32-entry
+** array. Each entry consists of 9 kernel values. In practice we store only a
+** half of the table, because the other half is a mirror of the first,
+** therefore:
+** rows_to_store = 32 / 2 + 1 = 17
+** values_to_store = rows_to_store * 9 = 153
+** even_value_count = (values_to_store + 1) & ~1 = 154
+** dword_count = even_value_count / 2 = 77
+*/
+
+#define gcregFilterKernelRegAddrs 0x0600
+#define GCREG_FILTER_KERNEL_MSB 15
+#define GCREG_FILTER_KERNEL_LSB 7
+#define GCREG_FILTER_KERNEL_BLK 7
+#define GCREG_FILTER_KERNEL_Count 128
+#define GCREG_FILTER_KERNEL_FieldMask 0xFFFFFFFF
+#define GCREG_FILTER_KERNEL_ReadMask 0xFFFFFFFF
+#define GCREG_FILTER_KERNEL_WriteMask 0xFFFFFFFF
+#define GCREG_FILTER_KERNEL_ResetValue 0x00000000
+
+#define GCREG_FILTER_KERNEL_COEFFICIENT0 15 : 0
+#define GCREG_FILTER_KERNEL_COEFFICIENT0_End 15
+#define GCREG_FILTER_KERNEL_COEFFICIENT0_Start 0
+#define GCREG_FILTER_KERNEL_COEFFICIENT0_Type U16
+
+#define GCREG_FILTER_KERNEL_COEFFICIENT1 31 : 16
+#define GCREG_FILTER_KERNEL_COEFFICIENT1_End 31
+#define GCREG_FILTER_KERNEL_COEFFICIENT1_Start 16
+#define GCREG_FILTER_KERNEL_COEFFICIENT1_Type U16
+
+struct gcregfilterkernelpair {
+ /* gcregFilterKernelRegAddrs:COEFFICIENT0 */
+ unsigned int coeff0:16;
+
+ /* gcregFilterKernelRegAddrs:COEFFICIENT1 */
+ unsigned int coeff1:16;
+};
+
+struct gcregfilterkernel {
+ struct gcregfilterkernelpair filter[77];
+};
+
+/*******************************************************************************
+** State gcregHoriFilterKernel
+*/
+
+/* One Pass filter Filter blit hori coefficient table. */
+
+#define gcregHoriFilterKernelRegAddrs 0x0A00
+#define GCREG_HORI_FILTER_KERNEL_MSB 15
+#define GCREG_HORI_FILTER_KERNEL_LSB 7
+#define GCREG_HORI_FILTER_KERNEL_BLK 7
+#define GCREG_HORI_FILTER_KERNEL_Count 128
+#define GCREG_HORI_FILTER_KERNEL_FieldMask 0xFFFFFFFF
+#define GCREG_HORI_FILTER_KERNEL_ReadMask 0xFFFFFFFF
+#define GCREG_HORI_FILTER_KERNEL_WriteMask 0xFFFFFFFF
+#define GCREG_HORI_FILTER_KERNEL_ResetValue 0x00000000
+
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT0 15 : 0
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT0_End 15
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT0_Start 0
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT0_Type U16
+
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT1 31 : 16
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT1_End 31
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT1_Start 16
+#define GCREG_HORI_FILTER_KERNEL_COEFFICIENT1_Type U16
+
+/*******************************************************************************
+** State gcregVertiFilterKernel
+*/
+
+/* One Pass Filter blit vertical coefficient table. */
+
+#define gcregVertiFilterKernelRegAddrs 0x0A80
+#define GCREG_VERTI_FILTER_KERNEL_MSB 15
+#define GCREG_VERTI_FILTER_KERNEL_LSB 7
+#define GCREG_VERTI_FILTER_KERNEL_BLK 7
+#define GCREG_VERTI_FILTER_KERNEL_Count 128
+#define GCREG_VERTI_FILTER_KERNEL_FieldMask 0xFFFFFFFF
+#define GCREG_VERTI_FILTER_KERNEL_ReadMask 0xFFFFFFFF
+#define GCREG_VERTI_FILTER_KERNEL_WriteMask 0xFFFFFFFF
+#define GCREG_VERTI_FILTER_KERNEL_ResetValue 0x00000000
+
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT0 15 : 0
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT0_End 15
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT0_Start 0
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT0_Type U16
+
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT1 31 : 16
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT1_End 31
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT1_Start 16
+#define GCREG_VERTI_FILTER_KERNEL_COEFFICIENT1_Type U16
+
+/*******************************************************************************
+** State gcregVRConfig
+*/
+
+/* Video Rasterizer kick-off register. */
+
+#define gcregVRConfigRegAddrs 0x04A5
+#define GCREG_VR_CONFIG_MSB 15
+#define GCREG_VR_CONFIG_LSB 0
+#define GCREG_VR_CONFIG_BLK 0
+#define GCREG_VR_CONFIG_Count 1
+#define GCREG_VR_CONFIG_FieldMask 0x0000000B
+#define GCREG_VR_CONFIG_ReadMask 0x0000000B
+#define GCREG_VR_CONFIG_WriteMask 0x0000000B
+#define GCREG_VR_CONFIG_ResetValue 0x00000000
+
+/* Kick-off command. */
+#define GCREG_VR_CONFIG_START 1 : 0
+#define GCREG_VR_CONFIG_START_End 1
+#define GCREG_VR_CONFIG_START_Start 0
+#define GCREG_VR_CONFIG_START_Type U02
+#define GCREG_VR_CONFIG_START_HORIZONTAL_BLIT 0x0
+#define GCREG_VR_CONFIG_START_VERTICAL_BLIT 0x1
+#define GCREG_VR_CONFIG_START_ONE_PASS_BLIT 0x2
+
+#define GCREG_VR_CONFIG_MASK_START 3 : 3
+#define GCREG_VR_CONFIG_MASK_START_End 3
+#define GCREG_VR_CONFIG_MASK_START_Start 3
+#define GCREG_VR_CONFIG_MASK_START_Type U01
+#define GCREG_VR_CONFIG_MASK_START_ENABLED 0x0
+#define GCREG_VR_CONFIG_MASK_START_MASKED 0x1
+
+struct gcregvrconfig {
+ /* gcregVRConfigRegAddrs:START */
+ unsigned int start:2;
+
+ /* gcregVRConfigRegAddrs:reserved */
+ unsigned int _reserved_2:1;
+
+ /* gcregVRConfigRegAddrs:MASK_START */
+ unsigned int start_mask:1;
+
+ /* gcregVRConfigRegAddrs:reserved */
+ unsigned int _reserved_4_31:28;
+};
+
+static const struct gcregvrconfig gcregvrconfig_horizontal = {
+ /* gcregVRConfigRegAddrs:START */
+ GCREG_VR_CONFIG_START_HORIZONTAL_BLIT,
+
+ /* gcregVRConfigRegAddrs:reserved */
+ 0,
+
+ /* gcregVRConfigRegAddrs:MASK_START */
+ GCREG_VR_CONFIG_MASK_START_ENABLED,
+
+ /* gcregVRConfigRegAddrs:reserved */
+ 0
+};
+
+static const struct gcregvrconfig gcregvrconfig_vertical = {
+ /* gcregVRConfigRegAddrs:START */
+ GCREG_VR_CONFIG_START_VERTICAL_BLIT,
+
+ /* gcregVRConfigRegAddrs:reserved */
+ 0,
+
+ /* gcregVRConfigRegAddrs:MASK_START */
+ GCREG_VR_CONFIG_MASK_START_ENABLED,
+
+ /* gcregVRConfigRegAddrs:reserved */
+ 0
+};
+
+static const struct gcregvrconfig gcregvrconfig_onepass = {
+ /* gcregVRConfigRegAddrs:START */
+ GCREG_VR_CONFIG_START_ONE_PASS_BLIT,
+
+ /* gcregVRConfigRegAddrs:reserved */
+ 0,
+
+ /* gcregVRConfigRegAddrs:MASK_START */
+ GCREG_VR_CONFIG_MASK_START_ENABLED,
+
+ /* gcregVRConfigRegAddrs:reserved */
+ 0
+};
+
+/*******************************************************************************
+** State gcregVRSourceImageLow
+*/
+
+/* Bounding box of the source image. */
+
+#define gcregVRSourceImageLowRegAddrs 0x04A6
+#define GCREG_VR_SOURCE_IMAGE_LOW_Address 0x01298
+#define GCREG_VR_SOURCE_IMAGE_LOW_MSB 15
+#define GCREG_VR_SOURCE_IMAGE_LOW_LSB 0
+#define GCREG_VR_SOURCE_IMAGE_LOW_BLK 0
+#define GCREG_VR_SOURCE_IMAGE_LOW_Count 1
+#define GCREG_VR_SOURCE_IMAGE_LOW_FieldMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_LOW_ReadMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_LOW_WriteMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_LOW_ResetValue 0x00000000
+
+#define GCREG_VR_SOURCE_IMAGE_LOW_LEFT 15 : 0
+#define GCREG_VR_SOURCE_IMAGE_LOW_LEFT_End 15
+#define GCREG_VR_SOURCE_IMAGE_LOW_LEFT_Start 0
+#define GCREG_VR_SOURCE_IMAGE_LOW_LEFT_Type U16
+
+#define GCREG_VR_SOURCE_IMAGE_LOW_TOP 31 : 16
+#define GCREG_VR_SOURCE_IMAGE_LOW_TOP_End 31
+#define GCREG_VR_SOURCE_IMAGE_LOW_TOP_Start 16
+#define GCREG_VR_SOURCE_IMAGE_LOW_TOP_Type U16
+
+struct gcregvrsourceimagelow {
+ /* gcregVRSourceImageLowRegAddrs:LEFT */
+ unsigned int left:16;
+
+ /* gcregVRSourceImageLowRegAddrs:TOP */
+ unsigned int top:16;
+};
+
+/*******************************************************************************
+** State gcregVRSourceImageHigh
+*/
+
+#define gcregVRSourceImageHighRegAddrs 0x04A7
+#define GCREG_VR_SOURCE_IMAGE_HIGH_MSB 15
+#define GCREG_VR_SOURCE_IMAGE_HIGH_LSB 0
+#define GCREG_VR_SOURCE_IMAGE_LOW_HIGH_BLK 0
+#define GCREG_VR_SOURCE_IMAGE_HIGH_Count 1
+#define GCREG_VR_SOURCE_IMAGE_HIGH_FieldMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_HIGH_ReadMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_HIGH_WriteMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_IMAGE_HIGH_ResetValue 0x00000000
+
+#define GCREG_VR_SOURCE_IMAGE_HIGH_RIGHT 15 : 0
+#define GCREG_VR_SOURCE_IMAGE_HIGH_RIGHT_End 15
+#define GCREG_VR_SOURCE_IMAGE_HIGH_RIGHT_Start 0
+#define GCREG_VR_SOURCE_IMAGE_HIGH_RIGHT_Type U16
+
+#define GCREG_VR_SOURCE_IMAGE_HIGH_BOTTOM 31 : 16
+#define GCREG_VR_SOURCE_IMAGE_HIGH_BOTTOM_End 31
+#define GCREG_VR_SOURCE_IMAGE_HIGH_BOTTOM_Start 16
+#define GCREG_VR_SOURCE_IMAGE_HIGH_BOTTOM_Type U16
+
+struct gcregvrsourceimagehigh {
+ /* gcregVRSourceImageHighRegAddrs:RIGHT */
+ unsigned int right:16;
+
+ /* gcregVRSourceImageHighRegAddrs:BOTTOM */
+ unsigned int bottom:16;
+};
+
+/*******************************************************************************
+** State gcregVRSourceOriginLow
+*/
+
+/* Fractional origin of the source window to be rendered within the source
+** image.
+*/
+
+#define gcregVRSourceOriginLowRegAddrs 0x04A8
+#define GCREG_VR_SOURCE_ORIGIN_LOW_MSB 15
+#define GCREG_VR_SOURCE_ORIGIN_LOW_LSB 0
+#define GCREG_VR_SOURCE_ORIGIN_LOW_BLK 0
+#define GCREG_VR_SOURCE_ORIGIN_LOW_Count 1
+#define GCREG_VR_SOURCE_ORIGIN_LOW_FieldMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_LOW_ReadMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_LOW_WriteMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_LOW_ResetValue 0x00000000
+
+#define GCREG_VR_SOURCE_ORIGIN_LOW_X 31 : 0
+#define GCREG_VR_SOURCE_ORIGIN_LOW_X_End 31
+#define GCREG_VR_SOURCE_ORIGIN_LOW_X_Start 0
+#define GCREG_VR_SOURCE_ORIGIN_LOW_X_Type U32
+
+/*******************************************************************************
+** State gcregVRSourceOriginHigh
+*/
+
+#define gcregVRSourceOriginHighRegAddrs 0x04A9
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_MSB 15
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_LSB 0
+#define GCREG_VR_SOURCE_ORIGIN_LOW_HIGH_BLK 0
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_Count 1
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_FieldMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_ReadMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_WriteMask 0xFFFFFFFF
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_ResetValue 0x00000000
+
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_Y 31 : 0
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_Y_End 31
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_Y_Start 0
+#define GCREG_VR_SOURCE_ORIGIN_HIGH_Y_Type U32
+
+/*******************************************************************************
+** State gcregVRTargetWindowLow
+*/
+
+/* Bounding box of the destination window to be rendered within the
+** destination image.
+*/
+
+#define gcregVRTargetWindowLowRegAddrs 0x04AA
+#define GCREG_VR_TARGET_WINDOW_LOW_Address 0x012A8
+#define GCREG_VR_TARGET_WINDOW_LOW_MSB 15
+#define GCREG_VR_TARGET_WINDOW_LOW_LSB 0
+#define GCREG_VR_TARGET_WINDOW_LOW_BLK 0
+#define GCREG_VR_TARGET_WINDOW_LOW_Count 1
+#define GCREG_VR_TARGET_WINDOW_LOW_FieldMask 0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_LOW_ReadMask 0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_LOW_WriteMask 0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_LOW_ResetValue 0x00000000
+
+#define GCREG_VR_TARGET_WINDOW_LOW_LEFT 15 : 0
+#define GCREG_VR_TARGET_WINDOW_LOW_LEFT_End 15
+#define GCREG_VR_TARGET_WINDOW_LOW_LEFT_Start 0
+#define GCREG_VR_TARGET_WINDOW_LOW_LEFT_Type U16
+
+#define GCREG_VR_TARGET_WINDOW_LOW_TOP 31 : 16
+#define GCREG_VR_TARGET_WINDOW_LOW_TOP_End 31
+#define GCREG_VR_TARGET_WINDOW_LOW_TOP_Start 16
+#define GCREG_VR_TARGET_WINDOW_LOW_TOP_Type U16
+
+struct gcregvrtargetwindowlow {
+ /* gcregVRTargetWindowLowRegAddrs:LEFT */
+ unsigned int left:16;
+
+ /* gcregVRTargetWindowLowRegAddrs:TOP */
+ unsigned int top:16;
+};
+
+/*******************************************************************************
+** State gcregVRTargetWindowHigh
+*/
+
+#define gcregVRTargetWindowHighRegAddrs 0x04AB
+#define GCREG_VR_TARGET_WINDOW_HIGH_MSB 15
+#define GCREG_VR_TARGET_WINDOW_HIGH_LSB 0
+#define GCREG_VR_TARGET_WINDOW_LOW_HIGH_BLK 0
+#define GCREG_VR_TARGET_WINDOW_HIGH_Count 1
+#define GCREG_VR_TARGET_WINDOW_HIGH_FieldMask 0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_HIGH_ReadMask 0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_HIGH_WriteMask 0xFFFFFFFF
+#define GCREG_VR_TARGET_WINDOW_HIGH_ResetValue 0x00000000
+
+#define GCREG_VR_TARGET_WINDOW_HIGH_RIGHT 15 : 0
+#define GCREG_VR_TARGET_WINDOW_HIGH_RIGHT_End 15
+#define GCREG_VR_TARGET_WINDOW_HIGH_RIGHT_Start 0
+#define GCREG_VR_TARGET_WINDOW_HIGH_RIGHT_Type U16
+
+#define GCREG_VR_TARGET_WINDOW_HIGH_BOTTOM 31 : 16
+#define GCREG_VR_TARGET_WINDOW_HIGH_BOTTOM_End 31
+#define GCREG_VR_TARGET_WINDOW_HIGH_BOTTOM_Start 16
+#define GCREG_VR_TARGET_WINDOW_HIGH_BOTTOM_Type U16
+
+struct gcregvrtargetwindowhigh {
+ /* gcregVRTargetWindowHighRegAddrs:LEFT */
+ unsigned int right:16;
+
+ /* gcregVRTargetWindowHighRegAddrs:TOP */
+ unsigned int bottom:16;
+};
+
+/*******************************************************************************
+** State gcregVRConfigEx
+*/
+
+/* Video Rasterizer configuration register. */
+
+#define gcregVRConfigExRegAddrs 0x04B9
+#define GCREG_VR_CONFIG_EX_Address 0x012E4
+#define GCREG_VR_CONFIG_EX_MSB 15
+#define GCREG_VR_CONFIG_EX_LSB 0
+#define GCREG_VR_CONFIG_EX_BLK 0
+#define GCREG_VR_CONFIG_EX_Count 1
+#define GCREG_VR_CONFIG_EX_FieldMask 0x000001FB
+#define GCREG_VR_CONFIG_EX_ReadMask 0x000001FB
+#define GCREG_VR_CONFIG_EX_WriteMask 0x000001FB
+#define GCREG_VR_CONFIG_EX_ResetValue 0x00000000
+
+/* Line width in pixels for vertical pass. */
+#define GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH 1 : 0
+#define GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_End 1
+#define GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_Start 0
+#define GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_Type U02
+#define GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_AUTO 0x0
+#define GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_PIXELS16 0x1
+#define GCREG_VR_CONFIG_EX_VERTICAL_LINE_WIDTH_PIXELS32 0x2
+
+#define GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH 3 : 3
+#define GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH_End 3
+#define GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH_Start 3
+#define GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH_Type U01
+#define GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH_ENABLED 0x0
+#define GCREG_VR_CONFIG_EX_MASK_VERTICAL_LINE_WIDTH_MASKED 0x1
+
+/* one pass filter tap. */
+#define GCREG_VR_CONFIG_EX_FILTER_TAP 7 : 4
+#define GCREG_VR_CONFIG_EX_FILTER_TAP_End 7
+#define GCREG_VR_CONFIG_EX_FILTER_TAP_Start 4
+#define GCREG_VR_CONFIG_EX_FILTER_TAP_Type U04
+
+#define GCREG_VR_CONFIG_EX_MASK_FILTER_TAP 8 : 8
+#define GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_End 8
+#define GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_Start 8
+#define GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_Type U01
+#define GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_ENABLED 0x0
+#define GCREG_VR_CONFIG_EX_MASK_FILTER_TAP_MASKED 0x1
+
+struct gcregvrconfigex {
+ /* gcregVRConfigExRegAddrs:VERTICAL_LINE_WIDTH */
+ unsigned int stripe:2;
+
+ /* gcregVRConfigExRegAddrs:reserved */
+ unsigned int _reserved_2:1;
+
+ /* gcregVRConfigExRegAddrs:MASK_VERTICAL_LINE_WIDTH */
+ unsigned int mask_stripe:1;
+
+ /* gcregVRConfigExRegAddrs:FILTER_TAP */
+ unsigned int kernelsize:4;
+
+ /* gcregVRConfigExRegAddrs:MASK_FILTER_TAP */
+ unsigned int mask_kernelsize:1;
+
+ /* gcregVRConfigExRegAddrs:reserved */
+ unsigned int _reserved_9_31:23;
+};
+
+/*******************************************************************************
+** State gcregBWConfig
+*/
+
+#define gcregBWConfigRegAddrs 0x04BC
+#define GCREG_BW_CONFIG_MSB 15
+#define GCREG_BW_CONFIG_LSB 0
+#define GCREG_BW_CONFIG_BLK 0
+#define GCREG_BW_CONFIG_Count 1
+#define GCREG_BW_CONFIG_FieldMask 0x00009999
+#define GCREG_BW_CONFIG_ReadMask 0x00009999
+#define GCREG_BW_CONFIG_WriteMask 0x00009999
+#define GCREG_BW_CONFIG_ResetValue 0x00000000
+
+/* One Pass Filter Block Config. */
+#define GCREG_BW_CONFIG_BLOCK_CONFIG 0 : 0
+#define GCREG_BW_CONFIG_BLOCK_CONFIG_End 0
+#define GCREG_BW_CONFIG_BLOCK_CONFIG_Start 0
+#define GCREG_BW_CONFIG_BLOCK_CONFIG_Type U01
+#define GCREG_BW_CONFIG_BLOCK_CONFIG_AUTO 0x0
+#define GCREG_BW_CONFIG_BLOCK_CONFIG_CUSTOMIZE 0x1
+
+#define GCREG_BW_CONFIG_MASK_BLOCK_CONFIG 3 : 3
+#define GCREG_BW_CONFIG_MASK_BLOCK_CONFIG_End 3
+#define GCREG_BW_CONFIG_MASK_BLOCK_CONFIG_Start 3
+#define GCREG_BW_CONFIG_MASK_BLOCK_CONFIG_Type U01
+#define GCREG_BW_CONFIG_MASK_BLOCK_CONFIG_ENABLED 0x0
+#define GCREG_BW_CONFIG_MASK_BLOCK_CONFIG_MASKED 0x1
+
+/* block walk direction in one pass filter blit. */
+#define GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION 4 : 4
+#define GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION_End 4
+#define GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION_Start 4
+#define GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION_Type U01
+#define GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION_RIGHT_BOTTOM 0x0
+#define GCREG_BW_CONFIG_BLOCK_WALK_DIRECTION_BOTTOM_RIGHT 0x1
+
+#define GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION 7 : 7
+#define GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION_End 7
+#define GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION_Start 7
+#define GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION_Type U01
+#define GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION_ENABLED 0x0
+#define GCREG_BW_CONFIG_MASK_BLOCK_WALK_DIRECTION_MASKED 0x1
+
+/* block walk direction in one pass filter blit. */
+#define GCREG_BW_CONFIG_TILE_WALK_DIRECTION 8 : 8
+#define GCREG_BW_CONFIG_TILE_WALK_DIRECTION_End 8
+#define GCREG_BW_CONFIG_TILE_WALK_DIRECTION_Start 8
+#define GCREG_BW_CONFIG_TILE_WALK_DIRECTION_Type U01
+#define GCREG_BW_CONFIG_TILE_WALK_DIRECTION_RIGHT_BOTTOM 0x0
+#define GCREG_BW_CONFIG_TILE_WALK_DIRECTION_BOTTOM_RIGHT 0x1
+
+#define GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION 11 : 11
+#define GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION_End 11
+#define GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION_Start 11
+#define GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION_Type U01
+#define GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION_ENABLED 0x0
+#define GCREG_BW_CONFIG_MASK_TILE_WALK_DIRECTION_MASKED 0x1
+
+/* block walk direction in one pass filter blit. */
+#define GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION 12 : 12
+#define GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION_End 12
+#define GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION_Start 12
+#define GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION_Type U01
+#define GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION_RIGHT_BOTTOM 0x0
+#define GCREG_BW_CONFIG_PIXEL_WALK_DIRECTION_BOTTOM_RIGHT 0x1
+
+#define GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION 15 : 15
+#define GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION_End 15
+#define GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION_Start 15
+#define GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION_Type U01
+#define GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION_ENABLED 0x0
+#define GCREG_BW_CONFIG_MASK_PIXEL_WALK_DIRECTION_MASKED 0x1
+
+/*******************************************************************************
+** State gcregBWBlockSize
+*/
+
+/* Walker Block size. */
+
+#define gcregBWBlockSizeRegAddrs 0x04BD
+#define GCREG_BW_BLOCK_SIZE_MSB 15
+#define GCREG_BW_BLOCK_SIZE_LSB 0
+#define GCREG_BW_BLOCK_SIZE_BLK 0
+#define GCREG_BW_BLOCK_SIZE_Count 1
+#define GCREG_BW_BLOCK_SIZE_FieldMask 0xFFFFFFFF
+#define GCREG_BW_BLOCK_SIZE_ReadMask 0xFFFFFFFF
+#define GCREG_BW_BLOCK_SIZE_WriteMask 0xFFFFFFFF
+#define GCREG_BW_BLOCK_SIZE_ResetValue 0x00000000
+
+#define GCREG_BW_BLOCK_SIZE_WIDTH 15 : 0
+#define GCREG_BW_BLOCK_SIZE_WIDTH_End 15
+#define GCREG_BW_BLOCK_SIZE_WIDTH_Start 0
+#define GCREG_BW_BLOCK_SIZE_WIDTH_Type U16
+
+#define GCREG_BW_BLOCK_SIZE_HEIGHT 31 : 16
+#define GCREG_BW_BLOCK_SIZE_HEIGHT_End 31
+#define GCREG_BW_BLOCK_SIZE_HEIGHT_Start 16
+#define GCREG_BW_BLOCK_SIZE_HEIGHT_Type U16
+
+/*******************************************************************************
+** State gcregBWTileSize
+*/
+
+/* Walker tile size. */
+
+#define gcregBWTileSizeRegAddrs 0x04BE
+#define GCREG_BW_TILE_SIZE_MSB 15
+#define GCREG_BW_TILE_SIZE_LSB 0
+#define GCREG_BW_TILE_SIZE_BLK 0
+#define GCREG_BW_TILE_SIZE_Count 1
+#define GCREG_BW_TILE_SIZE_FieldMask 0xFFFFFFFF
+#define GCREG_BW_TILE_SIZE_ReadMask 0xFFFFFFFF
+#define GCREG_BW_TILE_SIZE_WriteMask 0xFFFFFFFF
+#define GCREG_BW_TILE_SIZE_ResetValue 0x00000000
+
+#define GCREG_BW_TILE_SIZE_WIDTH 15 : 0
+#define GCREG_BW_TILE_SIZE_WIDTH_End 15
+#define GCREG_BW_TILE_SIZE_WIDTH_Start 0
+#define GCREG_BW_TILE_SIZE_WIDTH_Type U16
+
+#define GCREG_BW_TILE_SIZE_HEIGHT 31 : 16
+#define GCREG_BW_TILE_SIZE_HEIGHT_End 31
+#define GCREG_BW_TILE_SIZE_HEIGHT_Start 16
+#define GCREG_BW_TILE_SIZE_HEIGHT_Type U16
+
+/*******************************************************************************
+** State gcregBWBlockMask
+*/
+
+/* Walker Block Mask. */
+
+#define gcregBWBlockMaskRegAddrs 0x04BF
+#define GCREG_BW_BLOCK_MASK_MSB 15
+#define GCREG_BW_BLOCK_MASK_LSB 0
+#define GCREG_BW_BLOCK_MASK_BLK 0
+#define GCREG_BW_BLOCK_MASK_Count 1
+#define GCREG_BW_BLOCK_MASK_FieldMask 0xFFFFFFFF
+#define GCREG_BW_BLOCK_MASK_ReadMask 0xFFFFFFFF
+#define GCREG_BW_BLOCK_MASK_WriteMask 0xFFFFFFFF
+#define GCREG_BW_BLOCK_MASK_ResetValue 0x00000000
+
+#define GCREG_BW_BLOCK_MASK_HORIZONTAL 15 : 0
+#define GCREG_BW_BLOCK_MASK_HORIZONTAL_End 15
+#define GCREG_BW_BLOCK_MASK_HORIZONTAL_Start 0
+#define GCREG_BW_BLOCK_MASK_HORIZONTAL_Type U16
+
+#define GCREG_BW_BLOCK_MASK_VERTICAL 31 : 16
+#define GCREG_BW_BLOCK_MASK_VERTICAL_End 31
+#define GCREG_BW_BLOCK_MASK_VERTICAL_Start 16
+#define GCREG_BW_BLOCK_MASK_VERTICAL_Type U16
+
+/*******************************************************************************
+** State gcregIndexColorTable
+*/
+
+/* 256 color entries for the indexed color mode. Colors are assumed to be in
+** the destination format and no color conversion is done on the values.
+*/
+
+#define gcregIndexColorTableRegAddrs 0x0700
+#define GCREG_INDEX_COLOR_TABLE_MSB 15
+#define GCREG_INDEX_COLOR_TABLE_LSB 8
+#define GCREG_INDEX_COLOR_TABLE_BLK 8
+#define GCREG_INDEX_COLOR_TABLE_Count 256
+#define GCREG_INDEX_COLOR_TABLE_FieldMask 0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE_ReadMask 0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE_WriteMask 0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE_ResetValue 0x00000000
+
+#define GCREG_INDEX_COLOR_TABLE_ALPHA 31 : 24
+#define GCREG_INDEX_COLOR_TABLE_ALPHA_End 31
+#define GCREG_INDEX_COLOR_TABLE_ALPHA_Start 24
+#define GCREG_INDEX_COLOR_TABLE_ALPHA_Type U08
+
+#define GCREG_INDEX_COLOR_TABLE_RED 23 : 16
+#define GCREG_INDEX_COLOR_TABLE_RED_End 23
+#define GCREG_INDEX_COLOR_TABLE_RED_Start 16
+#define GCREG_INDEX_COLOR_TABLE_RED_Type U08
+
+#define GCREG_INDEX_COLOR_TABLE_GREEN 15 : 8
+#define GCREG_INDEX_COLOR_TABLE_GREEN_End 15
+#define GCREG_INDEX_COLOR_TABLE_GREEN_Start 8
+#define GCREG_INDEX_COLOR_TABLE_GREEN_Type U08
+
+#define GCREG_INDEX_COLOR_TABLE_BLUE 7 : 0
+#define GCREG_INDEX_COLOR_TABLE_BLUE_End 7
+#define GCREG_INDEX_COLOR_TABLE_BLUE_Start 0
+#define GCREG_INDEX_COLOR_TABLE_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregIndexColorTable32
+*/
+
+/* 256 color entries for the indexed color mode. Colors are assumed to be in
+** the A8R8G8B8 format and no color conversion is done on the values. This
+** register is used only with chips with PE20 feature available.
+*/
+
+#define gcregIndexColorTable32RegAddrs 0x0D00
+#define GCREG_INDEX_COLOR_TABLE32_MSB 15
+#define GCREG_INDEX_COLOR_TABLE32_LSB 8
+#define GCREG_INDEX_COLOR_TABLE32_BLK 8
+#define GCREG_INDEX_COLOR_TABLE32_Count 256
+#define GCREG_INDEX_COLOR_TABLE32_FieldMask 0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE32_ReadMask 0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE32_WriteMask 0xFFFFFFFF
+#define GCREG_INDEX_COLOR_TABLE32_ResetValue 0x00000000
+
+#define GCREG_INDEX_COLOR_TABLE32_ALPHA 31 : 24
+#define GCREG_INDEX_COLOR_TABLE32_ALPHA_End 31
+#define GCREG_INDEX_COLOR_TABLE32_ALPHA_Start 24
+#define GCREG_INDEX_COLOR_TABLE32_ALPHA_Type U08
+
+#define GCREG_INDEX_COLOR_TABLE32_RED 23 : 16
+#define GCREG_INDEX_COLOR_TABLE32_RED_End 23
+#define GCREG_INDEX_COLOR_TABLE32_RED_Start 16
+#define GCREG_INDEX_COLOR_TABLE32_RED_Type U08
+
+#define GCREG_INDEX_COLOR_TABLE32_GREEN 15 : 8
+#define GCREG_INDEX_COLOR_TABLE32_GREEN_End 15
+#define GCREG_INDEX_COLOR_TABLE32_GREEN_Start 8
+#define GCREG_INDEX_COLOR_TABLE32_GREEN_Type U08
+
+#define GCREG_INDEX_COLOR_TABLE32_BLUE 7 : 0
+#define GCREG_INDEX_COLOR_TABLE32_BLUE_End 7
+#define GCREG_INDEX_COLOR_TABLE32_BLUE_Start 0
+#define GCREG_INDEX_COLOR_TABLE32_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregRop
+*/
+
+/* Raster operation foreground and background codes. Even though ROP is not
+** used in CLEAR, HOR_FILTER_BLT, VER_FILTER_BLT and alpha-eanbled BIT_BLTs,
+** ROP code still has to be programmed, because the engine makes the decision
+** whether source, destination and pattern are involved in the current
+** operation and the correct decision is essential for the engine to complete
+** the operation as expected.
+*/
+
+#define gcregRopRegAddrs 0x0497
+#define GCREG_ROP_MSB 15
+#define GCREG_ROP_LSB 0
+#define GCREG_ROP_BLK 0
+#define GCREG_ROP_Count 1
+#define GCREG_ROP_FieldMask 0x0030FFFF
+#define GCREG_ROP_ReadMask 0x0030FFFF
+#define GCREG_ROP_WriteMask 0x0030FFFF
+#define GCREG_ROP_ResetValue 0x00000000
+
+/* ROP type: ROP2, ROP3 or ROP4 */
+#define GCREG_ROP_TYPE 21 : 20
+#define GCREG_ROP_TYPE_End 21
+#define GCREG_ROP_TYPE_Start 20
+#define GCREG_ROP_TYPE_Type U02
+#define GCREG_ROP_TYPE_ROP2_PATTERN 0x0
+#define GCREG_ROP_TYPE_ROP2_SOURCE 0x1
+#define GCREG_ROP_TYPE_ROP3 0x2
+#define GCREG_ROP_TYPE_ROP4 0x3
+
+/* Background ROP code is used for transparent pixels. */
+#define GCREG_ROP_ROP_BG 15 : 8
+#define GCREG_ROP_ROP_BG_End 15
+#define GCREG_ROP_ROP_BG_Start 8
+#define GCREG_ROP_ROP_BG_Type U08
+
+/* Background ROP code is used for opaque pixels. */
+#define GCREG_ROP_ROP_FG 7 : 0
+#define GCREG_ROP_ROP_FG_End 7
+#define GCREG_ROP_ROP_FG_Start 0
+#define GCREG_ROP_ROP_FG_Type U08
+
+struct gcregrop {
+ /* gcregRopRegAddrs:ROP_FG */
+ unsigned int fg:8;
+
+ /* gcregRopRegAddrs:ROP_BG */
+ unsigned int bg:8;
+
+ /* gcregRopRegAddrs:reserved */
+ unsigned int _reserved_16_19:4;
+
+ /* gcregRopRegAddrs:ROP_TYPE */
+ unsigned int type:2;
+
+ /* gcregRopRegAddrs:reserved */
+ unsigned int _reserved_22_31:10;
+};
+
+/*******************************************************************************
+** State gcregClipTopLeft
+*/
+
+/* Top left corner of the clipping rectangle defined in pixels. Clipping is
+** always on and everything beyond the clipping rectangle will be clipped
+** out. Clipping is not used with filter blits.
+*/
+
+#define gcregClipTopLeftRegAddrs 0x0498
+#define GCREG_CLIP_TOP_LEFT_MSB 15
+#define GCREG_CLIP_TOP_LEFT_LSB 0
+#define GCREG_CLIP_TOP_LEFT_BLK 0
+#define GCREG_CLIP_TOP_LEFT_Count 1
+#define GCREG_CLIP_TOP_LEFT_FieldMask 0x7FFF7FFF
+#define GCREG_CLIP_TOP_LEFT_ReadMask 0x7FFF7FFF
+#define GCREG_CLIP_TOP_LEFT_WriteMask 0x7FFF7FFF
+#define GCREG_CLIP_TOP_LEFT_ResetValue 0x00000000
+
+#define GCREG_CLIP_TOP_LEFT_Y 30 : 16
+#define GCREG_CLIP_TOP_LEFT_Y_End 30
+#define GCREG_CLIP_TOP_LEFT_Y_Start 16
+#define GCREG_CLIP_TOP_LEFT_Y_Type U15
+
+#define GCREG_CLIP_TOP_LEFT_X 14 : 0
+#define GCREG_CLIP_TOP_LEFT_X_End 14
+#define GCREG_CLIP_TOP_LEFT_X_Start 0
+#define GCREG_CLIP_TOP_LEFT_X_Type U15
+
+struct gcregcliplt {
+ /* gcregClipTopLeftRegAddrs:X */
+ unsigned int left:15;
+
+ /* gcregClipTopLeftRegAddrs:reserved */
+ unsigned int _reserved_15:1;
+
+ /* gcregClipTopLeftRegAddrs:Y */
+ unsigned int top:15;
+
+ /* gcregClipTopLeftRegAddrs:reserved */
+ unsigned int _reserved_31:1;
+};
+
+/*******************************************************************************
+** State gcregClipBottomRight
+*/
+
+/* Bottom right corner of the clipping rectangle defined in pixels. Clipping
+** is always on and everything beyond the clipping rectangle will be clipped
+** out. Clipping is not used with filter blits.
+*/
+
+#define gcregClipBottomRightRegAddrs 0x0499
+#define GCREG_CLIP_BOTTOM_RIGHT_MSB 15
+#define GCREG_CLIP_BOTTOM_RIGHT_LSB 0
+#define GCREG_CLIP_BOTTOM_RIGHT_BLK 0
+#define GCREG_CLIP_BOTTOM_RIGHT_Count 1
+#define GCREG_CLIP_BOTTOM_RIGHT_FieldMask 0x7FFF7FFF
+#define GCREG_CLIP_BOTTOM_RIGHT_ReadMask 0x7FFF7FFF
+#define GCREG_CLIP_BOTTOM_RIGHT_WriteMask 0x7FFF7FFF
+#define GCREG_CLIP_BOTTOM_RIGHT_ResetValue 0x00000000
+
+#define GCREG_CLIP_BOTTOM_RIGHT_Y 30 : 16
+#define GCREG_CLIP_BOTTOM_RIGHT_Y_End 30
+#define GCREG_CLIP_BOTTOM_RIGHT_Y_Start 16
+#define GCREG_CLIP_BOTTOM_RIGHT_Y_Type U15
+
+#define GCREG_CLIP_BOTTOM_RIGHT_X 14 : 0
+#define GCREG_CLIP_BOTTOM_RIGHT_X_End 14
+#define GCREG_CLIP_BOTTOM_RIGHT_X_Start 0
+#define GCREG_CLIP_BOTTOM_RIGHT_X_Type U15
+
+struct gcregcliprb {
+ /* gcregClipBottomRightRegAddrs:X */
+ unsigned int right:15;
+
+ /* gcregClipBottomRightRegAddrs:reserved */
+ unsigned int _reserved_15:1;
+
+ /* gcregClipBottomRightRegAddrs:Y */
+ unsigned int bottom:15;
+
+ /* gcregClipBottomRightRegAddrs:reserved */
+ unsigned int _reserved_31:1;
+};
+
+/*******************************************************************************
+** State gcregConfig
+*/
+
+#define gcregConfigRegAddrs 0x049B
+#define GCREG_CONFIG_MSB 15
+#define GCREG_CONFIG_LSB 0
+#define GCREG_CONFIG_BLK 0
+#define GCREG_CONFIG_Count 1
+#define GCREG_CONFIG_FieldMask 0x00370031
+#define GCREG_CONFIG_ReadMask 0x00370031
+#define GCREG_CONFIG_WriteMask 0x00370031
+#define GCREG_CONFIG_ResetValue 0x00000000
+
+#define GCREG_CONFIG_MIRROR_BLT_MODE 5 : 4
+#define GCREG_CONFIG_MIRROR_BLT_MODE_End 5
+#define GCREG_CONFIG_MIRROR_BLT_MODE_Start 4
+#define GCREG_CONFIG_MIRROR_BLT_MODE_Type U02
+#define GCREG_CONFIG_MIRROR_BLT_MODE_NORMAL 0x0
+#define GCREG_CONFIG_MIRROR_BLT_MODE_HMIRROR 0x1
+#define GCREG_CONFIG_MIRROR_BLT_MODE_VMIRROR 0x2
+#define GCREG_CONFIG_MIRROR_BLT_MODE_FULL_MIRROR 0x3
+
+#define GCREG_CONFIG_MIRROR_BLT_ENABLE 0 : 0
+#define GCREG_CONFIG_MIRROR_BLT_ENABLE_End 0
+#define GCREG_CONFIG_MIRROR_BLT_ENABLE_Start 0
+#define GCREG_CONFIG_MIRROR_BLT_ENABLE_Type U01
+#define GCREG_CONFIG_MIRROR_BLT_ENABLE_OFF 0x0
+#define GCREG_CONFIG_MIRROR_BLT_ENABLE_ON 0x1
+
+/* Source select for the old walkers. */
+#define GCREG_CONFIG_SOURCE_SELECT 18 : 16
+#define GCREG_CONFIG_SOURCE_SELECT_End 18
+#define GCREG_CONFIG_SOURCE_SELECT_Start 16
+#define GCREG_CONFIG_SOURCE_SELECT_Type U03
+
+/* Destination select for the old walkers. */
+#define GCREG_CONFIG_DESTINATION_SELECT 21 : 20
+#define GCREG_CONFIG_DESTINATION_SELECT_End 21
+#define GCREG_CONFIG_DESTINATION_SELECT_Start 20
+#define GCREG_CONFIG_DESTINATION_SELECT_Type U02
+
+/*******************************************************************************
+** State gcregSrcOriginFraction
+*/
+
+/* Fraction for the source origin. Together with values in gcregSrcOrigin
+** these values form signed 16.16 fixed point origin for the source
+** rectangle. Fractions are only used in filter blit in split frame mode.
+*/
+
+#define gcregSrcOriginFractionRegAddrs 0x049E
+#define GCREG_SRC_ORIGIN_FRACTION_MSB 15
+#define GCREG_SRC_ORIGIN_FRACTION_LSB 0
+#define GCREG_SRC_ORIGIN_FRACTION_BLK 0
+#define GCREG_SRC_ORIGIN_FRACTION_Count 1
+#define GCREG_SRC_ORIGIN_FRACTION_FieldMask 0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_FRACTION_ReadMask 0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_FRACTION_WriteMask 0xFFFFFFFF
+#define GCREG_SRC_ORIGIN_FRACTION_ResetValue 0x00000000
+
+#define GCREG_SRC_ORIGIN_FRACTION_Y 31 : 16
+#define GCREG_SRC_ORIGIN_FRACTION_Y_End 31
+#define GCREG_SRC_ORIGIN_FRACTION_Y_Start 16
+#define GCREG_SRC_ORIGIN_FRACTION_Y_Type U16
+
+#define GCREG_SRC_ORIGIN_FRACTION_X 15 : 0
+#define GCREG_SRC_ORIGIN_FRACTION_X_End 15
+#define GCREG_SRC_ORIGIN_FRACTION_X_Start 0
+#define GCREG_SRC_ORIGIN_FRACTION_X_Type U16
+
+/*******************************************************************************
+** State gcregAlphaControl
+*/
+
+#define gcregAlphaControlRegAddrs 0x049F
+#define GCREG_ALPHA_CONTROL_MSB 15
+#define GCREG_ALPHA_CONTROL_LSB 0
+#define GCREG_ALPHA_CONTROL_BLK 0
+#define GCREG_ALPHA_CONTROL_Count 1
+#define GCREG_ALPHA_CONTROL_FieldMask 0xFFFF0001
+#define GCREG_ALPHA_CONTROL_ReadMask 0xFFFF0001
+#define GCREG_ALPHA_CONTROL_WriteMask 0xFFFF0001
+#define GCREG_ALPHA_CONTROL_ResetValue 0x00000000
+
+#define GCREG_ALPHA_CONTROL_ENABLE 0 : 0
+#define GCREG_ALPHA_CONTROL_ENABLE_End 0
+#define GCREG_ALPHA_CONTROL_ENABLE_Start 0
+#define GCREG_ALPHA_CONTROL_ENABLE_Type U01
+#define GCREG_ALPHA_CONTROL_ENABLE_OFF 0x0
+#define GCREG_ALPHA_CONTROL_ENABLE_ON 0x1
+
+struct gcregalphacontrol {
+ /* gcregAlphaControlRegAddrs:GCREG_ALPHA_CONTROL_ENABLE */
+ unsigned int enable:1;
+
+ /* gcregAlphaControlRegAddrs:reserved */
+ unsigned int _reserved_1_31:31;
+};
+
+static const struct gcregalphacontrol gcregalpha_off = {
+ /* gcregAlphaControlRegAddrs:GCREG_ALPHA_CONTROL_ENABLE */
+ GCREG_ALPHA_CONTROL_ENABLE_OFF,
+
+ /* gcregAlphaControlRegAddrs:reserved */
+ 0
+};
+
+static const struct gcregalphacontrol gcregalpha_on = {
+ /* gcregAlphaControlRegAddrs:GCREG_ALPHA_CONTROL_ENABLE */
+ GCREG_ALPHA_CONTROL_ENABLE_ON,
+
+ /* gcregAlphaControlRegAddrs:reserved */
+ 0
+};
+
+/*******************************************************************************
+** State gcregAlphaModes
+*/
+
+#define gcregAlphaModesRegAddrs 0x04A0
+#define GCREG_ALPHA_MODES_MSB 15
+#define GCREG_ALPHA_MODES_LSB 0
+#define GCREG_ALPHA_MODES_BLK 0
+#define GCREG_ALPHA_MODES_Count 1
+#define GCREG_ALPHA_MODES_FieldMask 0xFF113311
+#define GCREG_ALPHA_MODES_ReadMask 0xFF113311
+#define GCREG_ALPHA_MODES_WriteMask 0xFF113311
+#define GCREG_ALPHA_MODES_ResetValue 0x00000000
+
+#define GCREG_ALPHA_MODES_SRC_ALPHA_MODE 0 : 0
+#define GCREG_ALPHA_MODES_SRC_ALPHA_MODE_End 0
+#define GCREG_ALPHA_MODES_SRC_ALPHA_MODE_Start 0
+#define GCREG_ALPHA_MODES_SRC_ALPHA_MODE_Type U01
+#define GCREG_ALPHA_MODES_SRC_ALPHA_MODE_NORMAL 0x0
+#define GCREG_ALPHA_MODES_SRC_ALPHA_MODE_INVERSED 0x1
+
+#define GCREG_ALPHA_MODES_DST_ALPHA_MODE 4 : 4
+#define GCREG_ALPHA_MODES_DST_ALPHA_MODE_End 4
+#define GCREG_ALPHA_MODES_DST_ALPHA_MODE_Start 4
+#define GCREG_ALPHA_MODES_DST_ALPHA_MODE_Type U01
+#define GCREG_ALPHA_MODES_DST_ALPHA_MODE_NORMAL 0x0
+#define GCREG_ALPHA_MODES_DST_ALPHA_MODE_INVERSED 0x1
+
+#define GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE 9 : 8
+#define GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_End 9
+#define GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Start 8
+#define GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Type U02
+#define GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_NORMAL 0x0
+#define GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_GLOBAL 0x1
+#define GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_SCALED 0x2
+
+#define GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE 13 : 12
+#define GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_End 13
+#define GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Start 12
+#define GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Type U02
+#define GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_NORMAL 0x0
+#define GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_GLOBAL 0x1
+#define GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_SCALED 0x2
+
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE 26 : 24
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_End 26
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_Start 24
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_Type U03
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_ZERO 0x0
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_ONE 0x1
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_NORMAL 0x2
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_INVERSED 0x3
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_COLOR 0x4
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_COLOR_INVERSED 0x5
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_ALPHA 0x6
+#define GCREG_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_DEST_ALPHA 0x7
+
+/* Src Blending factor is calculate from Src alpha. */
+#define GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR 27 : 27
+#define GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR_End 27
+#define GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR_Start 27
+#define GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR_Type U01
+#define GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR_DISABLED 0x0
+#define GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR_ENABLED 0x1
+
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE 30 : 28
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_End 30
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_Start 28
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_Type U03
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_ZERO 0x0
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_ONE 0x1
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_NORMAL 0x2
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_INVERSED 0x3
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_COLOR 0x4
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_COLOR_INVERSED 0x5
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_ALPHA 0x6
+#define GCREG_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_DEST_ALPHA 0x7
+
+/* Dst Blending factor is calculate from Dst alpha. */
+#define GCREG_ALPHA_MODES_DST_ALPHA_FACTOR 31 : 31
+#define GCREG_ALPHA_MODES_DST_ALPHA_FACTOR_End 31
+#define GCREG_ALPHA_MODES_DST_ALPHA_FACTOR_Start 31
+#define GCREG_ALPHA_MODES_DST_ALPHA_FACTOR_Type U01
+#define GCREG_ALPHA_MODES_DST_ALPHA_FACTOR_DISABLED 0x0
+#define GCREG_ALPHA_MODES_DST_ALPHA_FACTOR_ENABLED 0x1
+
+struct gcregalphamodes {
+ /* gcregAlphaModes:GCREG_ALPHA_MODES_SRC_ALPHA_MODE */
+ unsigned int src_inverse:1;
+
+ /* gcregAlphaModes:reserved */
+ unsigned int _reserved_1_3:3;
+
+ /* gcregAlphaModes:GCREG_ALPHA_MODES_DST_ALPHA_MODE */
+ unsigned int dst_inverse:1;
+
+ /* gcregAlphaModes:reserved */
+ unsigned int _reserved_5_7:3;
+
+ /* gcregAlphaModes:GCREG_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE */
+ unsigned int src_global_alpha_mode:2;
+
+ /* gcregAlphaModes:reserved */
+ unsigned int _reserved_10_11:2;
+
+ /* gcregAlphaModes:GCREG_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE */
+ unsigned int dst_global_alpha_mode:2;
+
+ /* gcregAlphaModes:reserved */
+ unsigned int _reserved_14_23:10;
+
+ /* gcregAlphaModes:GCREG_ALPHA_MODES_SRC_BLENDING_MODE */
+ unsigned int src_blend:3;
+
+ /* gcregAlphaModes:GCREG_ALPHA_MODES_SRC_ALPHA_FACTOR */
+ unsigned int src_color_reverse:1;
+
+ /* gcregAlphaModes:GCREG_ALPHA_MODES_DST_BLENDING_MODE */
+ unsigned int dst_blend:3;
+
+ /* gcregAlphaModes:GCREG_ALPHA_MODES_DST_ALPHA_FACTOR */
+ unsigned int dst_color_reverse:1;
+};
+
+/*******************************************************************************
+** State UPlaneAddress
+*/
+
+/* 32-bit aligned base address of the source U plane. */
+
+#define gcregUPlaneAddressRegAddrs 0x04A1
+#define GCREG_UPLANE_ADDRESS_MSB 15
+#define GCREG_UPLANE_ADDRESS_LSB 0
+#define GCREG_UPLANE_ADDRESS_BLK 0
+#define GCREG_UPLANE_ADDRESS_Count 1
+#define GCREG_UPLANE_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_UPLANE_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_UPLANE_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_UPLANE_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_UPLANE_ADDRESS_ADDRESS 31 : 0
+#define GCREG_UPLANE_ADDRESS_ADDRESS_End 30
+#define GCREG_UPLANE_ADDRESS_ADDRESS_Start 0
+#define GCREG_UPLANE_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State UPlaneStride
+*/
+
+/* Stride of the source U plane in bytes. */
+
+#define gcregUPlaneStrideRegAddrs 0x04A2
+#define GCREG_UPLANE_STRIDE_MSB 15
+#define GCREG_UPLANE_STRIDE_LSB 0
+#define GCREG_UPLANE_STRIDE_BLK 0
+#define GCREG_UPLANE_STRIDE_Count 1
+#define GCREG_UPLANE_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_UPLANE_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_UPLANE_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_UPLANE_STRIDE_ResetValue 0x00000000
+
+#define GCREG_UPLANE_STRIDE_STRIDE 17 : 0
+#define GCREG_UPLANE_STRIDE_STRIDE_End 17
+#define GCREG_UPLANE_STRIDE_STRIDE_Start 0
+#define GCREG_UPLANE_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State VPlaneAddress
+*/
+
+/* 32-bit aligned base address of the source V plane. */
+
+#define gcregVPlaneAddressRegAddrs 0x04A3
+#define GCREG_VPLANE_ADDRESS_MSB 15
+#define GCREG_VPLANE_ADDRESS_LSB 0
+#define GCREG_VPLANE_ADDRESS_BLK 0
+#define GCREG_VPLANE_ADDRESS_Count 1
+#define GCREG_VPLANE_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_VPLANE_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_VPLANE_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_VPLANE_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_VPLANE_ADDRESS_ADDRESS 31 : 0
+#define GCREG_VPLANE_ADDRESS_ADDRESS_End 30
+#define GCREG_VPLANE_ADDRESS_ADDRESS_Start 0
+#define GCREG_VPLANE_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State VPlaneStride
+*/
+
+/* Stride of the source V plane in bytes. */
+
+#define gcregVPlaneStrideRegAddrs 0x04A4
+#define GCREG_VPLANE_STRIDE_MSB 15
+#define GCREG_VPLANE_STRIDE_LSB 0
+#define GCREG_VPLANE_STRIDE_BLK 0
+#define GCREG_VPLANE_STRIDE_Count 1
+#define GCREG_VPLANE_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_VPLANE_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_VPLANE_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_VPLANE_STRIDE_ResetValue 0x00000000
+
+#define GCREG_VPLANE_STRIDE_STRIDE 17 : 0
+#define GCREG_VPLANE_STRIDE_STRIDE_End 17
+#define GCREG_VPLANE_STRIDE_STRIDE_Start 0
+#define GCREG_VPLANE_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State gcregPEConfig
+*/
+
+/* PE debug register. */
+
+#define gcregPEConfigRegAddrs 0x04AC
+#define GCREG_PE_CONFIG_Address 0x012B0
+#define GCREG_PE_CONFIG_MSB 15
+#define GCREG_PE_CONFIG_LSB 0
+#define GCREG_PE_CONFIG_BLK 0
+#define GCREG_PE_CONFIG_Count 1
+#define GCREG_PE_CONFIG_FieldMask 0x0000000B
+#define GCREG_PE_CONFIG_ReadMask 0x0000000B
+#define GCREG_PE_CONFIG_WriteMask 0x0000000B
+#define GCREG_PE_CONFIG_ResetValue 0x00000000
+
+#define GCREG_PE_CONFIG_DESTINATION_FETCH 1 : 0
+#define GCREG_PE_CONFIG_DESTINATION_FETCH_End 1
+#define GCREG_PE_CONFIG_DESTINATION_FETCH_Start 0
+#define GCREG_PE_CONFIG_DESTINATION_FETCH_Type U02
+#define GCREG_PE_CONFIG_DESTINATION_FETCH_DISABLE 0x0
+#define GCREG_PE_CONFIG_DESTINATION_FETCH_DEFAULT 0x1
+#define GCREG_PE_CONFIG_DESTINATION_FETCH_ALWAYS 0x2
+
+#define GCREG_PE_CONFIG_MASK_DESTINATION_FETCH 3 : 3
+#define GCREG_PE_CONFIG_MASK_DESTINATION_FETCH_End 3
+#define GCREG_PE_CONFIG_MASK_DESTINATION_FETCH_Start 3
+#define GCREG_PE_CONFIG_MASK_DESTINATION_FETCH_Type U01
+#define GCREG_PE_CONFIG_MASK_DESTINATION_FETCH_ENABLED 0x0
+#define GCREG_PE_CONFIG_MASK_DESTINATION_FETCH_MASKED 0x1
+
+/*******************************************************************************
+** State gcregDstRotationHeight
+*/
+
+/* 180/270 degree rotation configuration for the destination surface. Height
+** field specifies the height of the surface in pixels.
+*/
+
+#define gcregDstRotationHeightRegAddrs 0x04AD
+#define GCREG_DST_ROTATION_HEIGHT_MSB 15
+#define GCREG_DST_ROTATION_HEIGHT_LSB 0
+#define GCREG_DST_ROTATION_HEIGHT_BLK 0
+#define GCREG_DST_ROTATION_HEIGHT_Count 1
+#define GCREG_DST_ROTATION_HEIGHT_FieldMask 0x0000FFFF
+#define GCREG_DST_ROTATION_HEIGHT_ReadMask 0x0000FFFF
+#define GCREG_DST_ROTATION_HEIGHT_WriteMask 0x0000FFFF
+#define GCREG_DST_ROTATION_HEIGHT_ResetValue 0x00000000
+
+#define GCREG_DST_ROTATION_HEIGHT_HEIGHT 15 : 0
+#define GCREG_DST_ROTATION_HEIGHT_HEIGHT_End 15
+#define GCREG_DST_ROTATION_HEIGHT_HEIGHT_Start 0
+#define GCREG_DST_ROTATION_HEIGHT_HEIGHT_Type U16
+
+struct gcregdstrotationheight {
+ /* gcregDstRotationHeightRegAddrs:GCREG_DST_ROTATION_HEIGHT_HEIGHT */
+ unsigned int height:16;
+
+ /* gcregDstRotationHeightRegAddrs:reserved */
+ unsigned int _reserved_16_31:16;
+};
+
+/*******************************************************************************
+** State gcregSrcRotationHeight
+*/
+
+/* 180/270 degree rotation configuration for the Source surface. Height field
+** specifies the height of the surface in pixels.
+*/
+
+#define gcregSrcRotationHeightRegAddrs 0x04AE
+#define GCREG_SRC_ROTATION_HEIGHT_MSB 15
+#define GCREG_SRC_ROTATION_HEIGHT_LSB 0
+#define GCREG_SRC_ROTATION_HEIGHT_BLK 0
+#define GCREG_SRC_ROTATION_HEIGHT_Count 1
+#define GCREG_SRC_ROTATION_HEIGHT_FieldMask 0x0000FFFF
+#define GCREG_SRC_ROTATION_HEIGHT_ReadMask 0x0000FFFF
+#define GCREG_SRC_ROTATION_HEIGHT_WriteMask 0x0000FFFF
+#define GCREG_SRC_ROTATION_HEIGHT_ResetValue 0x00000000
+
+#define GCREG_SRC_ROTATION_HEIGHT_HEIGHT 15 : 0
+#define GCREG_SRC_ROTATION_HEIGHT_HEIGHT_End 15
+#define GCREG_SRC_ROTATION_HEIGHT_HEIGHT_Start 0
+#define GCREG_SRC_ROTATION_HEIGHT_HEIGHT_Type U16
+
+struct gcregsrcrotationheight {
+ /* gcregSrcRotationHeightRegAddrs:GCREG_SRC_ROTATION_HEIGHT_HEIGHT */
+ unsigned int height:16;
+
+ /* gcregSrcRotationHeightRegAddrs:reserved */
+ unsigned int _reserved_16_31:16;
+};
+
+/*******************************************************************************
+** State gcregRotAngle
+*/
+
+/* 0/90/180/270 degree rotation configuration for the Source surface. Height
+** field specifies the height of the surface in pixels.
+*/
+
+#define gcregRotAngleRegAddrs 0x04AF
+#define GCREG_ROT_ANGLE_MSB 15
+#define GCREG_ROT_ANGLE_LSB 0
+#define GCREG_ROT_ANGLE_BLK 0
+#define GCREG_ROT_ANGLE_Count 1
+#define GCREG_ROT_ANGLE_FieldMask 0x000BB33F
+#define GCREG_ROT_ANGLE_ReadMask 0x000BB33F
+#define GCREG_ROT_ANGLE_WriteMask 0x000BB33F
+#define GCREG_ROT_ANGLE_ResetValue 0x00000000
+
+#define GCREG_ROT_ANGLE_SRC 2 : 0
+#define GCREG_ROT_ANGLE_SRC_End 2
+#define GCREG_ROT_ANGLE_SRC_Start 0
+#define GCREG_ROT_ANGLE_SRC_Type U03
+#define GCREG_ROT_ANGLE_SRC_ROT0 0x0
+#define GCREG_ROT_ANGLE_SRC_FLIP_X 0x1
+#define GCREG_ROT_ANGLE_SRC_FLIP_Y 0x2
+#define GCREG_ROT_ANGLE_SRC_ROT90 0x4
+#define GCREG_ROT_ANGLE_SRC_ROT180 0x5
+#define GCREG_ROT_ANGLE_SRC_ROT270 0x6
+
+#define GCREG_ROT_ANGLE_DST 5 : 3
+#define GCREG_ROT_ANGLE_DST_End 5
+#define GCREG_ROT_ANGLE_DST_Start 3
+#define GCREG_ROT_ANGLE_DST_Type U03
+#define GCREG_ROT_ANGLE_DST_ROT0 0x0
+#define GCREG_ROT_ANGLE_DST_FLIP_X 0x1
+#define GCREG_ROT_ANGLE_DST_FLIP_Y 0x2
+#define GCREG_ROT_ANGLE_DST_ROT90 0x4
+#define GCREG_ROT_ANGLE_DST_ROT180 0x5
+#define GCREG_ROT_ANGLE_DST_ROT270 0x6
+
+#define GCREG_ROT_ANGLE_MASK_SRC 8 : 8
+#define GCREG_ROT_ANGLE_MASK_SRC_End 8
+#define GCREG_ROT_ANGLE_MASK_SRC_Start 8
+#define GCREG_ROT_ANGLE_MASK_SRC_Type U01
+#define GCREG_ROT_ANGLE_MASK_SRC_ENABLED 0x0
+#define GCREG_ROT_ANGLE_MASK_SRC_MASKED 0x1
+
+#define GCREG_ROT_ANGLE_MASK_DST 9 : 9
+#define GCREG_ROT_ANGLE_MASK_DST_End 9
+#define GCREG_ROT_ANGLE_MASK_DST_Start 9
+#define GCREG_ROT_ANGLE_MASK_DST_Type U01
+#define GCREG_ROT_ANGLE_MASK_DST_ENABLED 0x0
+#define GCREG_ROT_ANGLE_MASK_DST_MASKED 0x1
+
+#define GCREG_ROT_ANGLE_SRC_MIRROR 13 : 12
+#define GCREG_ROT_ANGLE_SRC_MIRROR_End 13
+#define GCREG_ROT_ANGLE_SRC_MIRROR_Start 12
+#define GCREG_ROT_ANGLE_SRC_MIRROR_Type U02
+#define GCREG_ROT_ANGLE_SRC_MIRROR_NONE 0x0
+#define GCREG_ROT_ANGLE_SRC_MIRROR_MIRROR_X 0x1
+#define GCREG_ROT_ANGLE_SRC_MIRROR_MIRROR_Y 0x2
+#define GCREG_ROT_ANGLE_SRC_MIRROR_MIRROR_XY 0x3
+
+#define GCREG_ROT_ANGLE_MASK_SRC_MIRROR 15 : 15
+#define GCREG_ROT_ANGLE_MASK_SRC_MIRROR_End 15
+#define GCREG_ROT_ANGLE_MASK_SRC_MIRROR_Start 15
+#define GCREG_ROT_ANGLE_MASK_SRC_MIRROR_Type U01
+#define GCREG_ROT_ANGLE_MASK_SRC_MIRROR_ENABLED 0x0
+#define GCREG_ROT_ANGLE_MASK_SRC_MIRROR_MASKED 0x1
+
+#define GCREG_ROT_ANGLE_DST_MIRROR 17 : 16
+#define GCREG_ROT_ANGLE_DST_MIRROR_End 17
+#define GCREG_ROT_ANGLE_DST_MIRROR_Start 16
+#define GCREG_ROT_ANGLE_DST_MIRROR_Type U02
+#define GCREG_ROT_ANGLE_DST_MIRROR_NONE 0x0
+#define GCREG_ROT_ANGLE_DST_MIRROR_MIRROR_X 0x1
+#define GCREG_ROT_ANGLE_DST_MIRROR_MIRROR_Y 0x2
+#define GCREG_ROT_ANGLE_DST_MIRROR_MIRROR_XY 0x3
+
+#define GCREG_ROT_ANGLE_MASK_DST_MIRROR 19 : 19
+#define GCREG_ROT_ANGLE_MASK_DST_MIRROR_End 19
+#define GCREG_ROT_ANGLE_MASK_DST_MIRROR_Start 19
+#define GCREG_ROT_ANGLE_MASK_DST_MIRROR_Type U01
+#define GCREG_ROT_ANGLE_MASK_DST_MIRROR_ENABLED 0x0
+#define GCREG_ROT_ANGLE_MASK_DST_MIRROR_MASKED 0x1
+
+struct gcregrotangle {
+ /* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_SRC */
+ unsigned int src:3;
+
+ /* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_DST */
+ unsigned int dst:3;
+
+ /* gcregRotAngleRegAddrs:reserved */
+ unsigned int _reserved_6_7:2;
+
+ /* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_MASK_SRC */
+ unsigned int src_mask:1;
+
+ /* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_MASK_DST */
+ unsigned int dst_mask:1;
+
+ /* gcregRotAngleRegAddrs:reserved */
+ unsigned int _reserved_10_11:2;
+
+ /* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_SRC_MIRROR */
+ unsigned int src_mirror:2;
+
+ /* gcregRotAngleRegAddrs:reserved */
+ unsigned int _reserved_14:1;
+
+ /* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_MASK_SRC_MIRROR */
+ unsigned int src_mirror_mask:1;
+
+ /* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_DST_MIRROR */
+ unsigned int dst_mirror:2;
+
+ /* gcregRotAngleRegAddrs:reserved */
+ unsigned int _reserved_18:1;
+
+ /* gcregRotAngleRegAddrs:GCREG_ROT_ANGLE_MASK_DST_MIRROR */
+ unsigned int dst_mirror_mask:1;
+
+ /* gcregRotAngleRegAddrs:reserved */
+ unsigned int _reserved_20_31:12;
+};
+
+/*******************************************************************************
+** State gcregClearPixelValue32
+*/
+
+/* Clear color value in A8R8G8B8 format. */
+
+#define gcregClearPixelValue32RegAddrs 0x04B0
+#define GCREG_CLEAR_PIXEL_VALUE32_MSB 15
+#define GCREG_CLEAR_PIXEL_VALUE32_LSB 0
+#define GCREG_CLEAR_PIXEL_VALUE32_BLK 0
+#define GCREG_CLEAR_PIXEL_VALUE32_Count 1
+#define GCREG_CLEAR_PIXEL_VALUE32_FieldMask 0xFFFFFFFF
+#define GCREG_CLEAR_PIXEL_VALUE32_ReadMask 0xFFFFFFFF
+#define GCREG_CLEAR_PIXEL_VALUE32_WriteMask 0xFFFFFFFF
+#define GCREG_CLEAR_PIXEL_VALUE32_ResetValue 0x00000000
+
+#define GCREG_CLEAR_PIXEL_VALUE32_ALPHA 31 : 24
+#define GCREG_CLEAR_PIXEL_VALUE32_ALPHA_End 31
+#define GCREG_CLEAR_PIXEL_VALUE32_ALPHA_Start 24
+#define GCREG_CLEAR_PIXEL_VALUE32_ALPHA_Type U08
+
+#define GCREG_CLEAR_PIXEL_VALUE32_RED 23 : 16
+#define GCREG_CLEAR_PIXEL_VALUE32_RED_End 23
+#define GCREG_CLEAR_PIXEL_VALUE32_RED_Start 16
+#define GCREG_CLEAR_PIXEL_VALUE32_RED_Type U08
+
+#define GCREG_CLEAR_PIXEL_VALUE32_GREEN 15 : 8
+#define GCREG_CLEAR_PIXEL_VALUE32_GREEN_End 15
+#define GCREG_CLEAR_PIXEL_VALUE32_GREEN_Start 8
+#define GCREG_CLEAR_PIXEL_VALUE32_GREEN_Type U08
+
+#define GCREG_CLEAR_PIXEL_VALUE32_BLUE 7 : 0
+#define GCREG_CLEAR_PIXEL_VALUE32_BLUE_End 7
+#define GCREG_CLEAR_PIXEL_VALUE32_BLUE_Start 0
+#define GCREG_CLEAR_PIXEL_VALUE32_BLUE_Type U08
+
+struct gcregclearcolor {
+ /* gcregClearPixelValue32RegAddrs:GCREG_CLEAR_PIXEL_VALUE32_BLUE */
+ unsigned int b:8;
+
+ /* gcregClearPixelValue32RegAddrs:GCREG_CLEAR_PIXEL_VALUE32_GREEN */
+ unsigned int g:8;
+
+ /* gcregClearPixelValue32RegAddrs:GCREG_CLEAR_PIXEL_VALUE32_RED */
+ unsigned int r:8;
+
+ /* gcregClearPixelValue32RegAddrs:GCREG_CLEAR_PIXEL_VALUE32_ALPHA */
+ unsigned int a:8;
+};
+
+/*******************************************************************************
+** State gcregDestColorKey
+*/
+
+/* Defines the destination transparency color in destination format. */
+
+#define gcregDestColorKeyRegAddrs 0x04B1
+#define GCREG_DEST_COLOR_KEY_MSB 15
+#define GCREG_DEST_COLOR_KEY_LSB 0
+#define GCREG_DEST_COLOR_KEY_BLK 0
+#define GCREG_DEST_COLOR_KEY_Count 1
+#define GCREG_DEST_COLOR_KEY_FieldMask 0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_ReadMask 0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_WriteMask 0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_ResetValue 0x00000000
+
+#define GCREG_DEST_COLOR_KEY_ALPHA 31 : 24
+#define GCREG_DEST_COLOR_KEY_ALPHA_End 31
+#define GCREG_DEST_COLOR_KEY_ALPHA_Start 24
+#define GCREG_DEST_COLOR_KEY_ALPHA_Type U08
+
+#define GCREG_DEST_COLOR_KEY_RED 23 : 16
+#define GCREG_DEST_COLOR_KEY_RED_End 23
+#define GCREG_DEST_COLOR_KEY_RED_Start 16
+#define GCREG_DEST_COLOR_KEY_RED_Type U08
+
+#define GCREG_DEST_COLOR_KEY_GREEN 15 : 8
+#define GCREG_DEST_COLOR_KEY_GREEN_End 15
+#define GCREG_DEST_COLOR_KEY_GREEN_Start 8
+#define GCREG_DEST_COLOR_KEY_GREEN_Type U08
+
+#define GCREG_DEST_COLOR_KEY_BLUE 7 : 0
+#define GCREG_DEST_COLOR_KEY_BLUE_End 7
+#define GCREG_DEST_COLOR_KEY_BLUE_Start 0
+#define GCREG_DEST_COLOR_KEY_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregGlobalSrcColor
+*/
+
+/* Defines the global source color and alpha values. */
+
+#define gcregGlobalSrcColorRegAddrs 0x04B2
+#define GCREG_GLOBAL_SRC_COLOR_MSB 15
+#define GCREG_GLOBAL_SRC_COLOR_LSB 0
+#define GCREG_GLOBAL_SRC_COLOR_BLK 0
+#define GCREG_GLOBAL_SRC_COLOR_Count 1
+#define GCREG_GLOBAL_SRC_COLOR_FieldMask 0xFFFFFFFF
+#define GCREG_GLOBAL_SRC_COLOR_ReadMask 0xFFFFFFFF
+#define GCREG_GLOBAL_SRC_COLOR_WriteMask 0xFFFFFFFF
+#define GCREG_GLOBAL_SRC_COLOR_ResetValue 0x00000000
+
+#define GCREG_GLOBAL_SRC_COLOR_ALPHA 31 : 24
+#define GCREG_GLOBAL_SRC_COLOR_ALPHA_End 31
+#define GCREG_GLOBAL_SRC_COLOR_ALPHA_Start 24
+#define GCREG_GLOBAL_SRC_COLOR_ALPHA_Type U08
+
+#define GCREG_GLOBAL_SRC_COLOR_RED 23 : 16
+#define GCREG_GLOBAL_SRC_COLOR_RED_End 23
+#define GCREG_GLOBAL_SRC_COLOR_RED_Start 16
+#define GCREG_GLOBAL_SRC_COLOR_RED_Type U08
+
+#define GCREG_GLOBAL_SRC_COLOR_GREEN 15 : 8
+#define GCREG_GLOBAL_SRC_COLOR_GREEN_End 15
+#define GCREG_GLOBAL_SRC_COLOR_GREEN_Start 8
+#define GCREG_GLOBAL_SRC_COLOR_GREEN_Type U08
+
+#define GCREG_GLOBAL_SRC_COLOR_BLUE 7 : 0
+#define GCREG_GLOBAL_SRC_COLOR_BLUE_End 7
+#define GCREG_GLOBAL_SRC_COLOR_BLUE_Start 0
+#define GCREG_GLOBAL_SRC_COLOR_BLUE_Type U08
+
+struct gcregglobalsrccolor {
+ /* gcregGlobalSrcColorRegAddrs:GCREG_GLOBAL_SRC_COLOR_BLUE */
+ unsigned int b:8;
+
+ /* gcregGlobalSrcColorRegAddrs:GCREG_GLOBAL_SRC_COLOR_GREEN */
+ unsigned int g:8;
+
+ /* gcregGlobalSrcColorRegAddrs:GCREG_GLOBAL_SRC_COLOR_RED */
+ unsigned int r:8;
+
+ /* gcregGlobalSrcColorRegAddrs:GCREG_GLOBAL_SRC_COLOR_ALPHA */
+ unsigned int a:8;
+};
+
+/*******************************************************************************
+** State gcregGlobalDestColor
+*/
+
+/* Defines the global destination color and alpha values. */
+
+#define gcregGlobalDestColorRegAddrs 0x04B3
+#define GCREG_GLOBAL_DEST_COLOR_MSB 15
+#define GCREG_GLOBAL_DEST_COLOR_LSB 0
+#define GCREG_GLOBAL_DEST_COLOR_BLK 0
+#define GCREG_GLOBAL_DEST_COLOR_Count 1
+#define GCREG_GLOBAL_DEST_COLOR_FieldMask 0xFFFFFFFF
+#define GCREG_GLOBAL_DEST_COLOR_ReadMask 0xFFFFFFFF
+#define GCREG_GLOBAL_DEST_COLOR_WriteMask 0xFFFFFFFF
+#define GCREG_GLOBAL_DEST_COLOR_ResetValue 0x00000000
+
+#define GCREG_GLOBAL_DEST_COLOR_ALPHA 31 : 24
+#define GCREG_GLOBAL_DEST_COLOR_ALPHA_End 31
+#define GCREG_GLOBAL_DEST_COLOR_ALPHA_Start 24
+#define GCREG_GLOBAL_DEST_COLOR_ALPHA_Type U08
+
+#define GCREG_GLOBAL_DEST_COLOR_RED 23 : 16
+#define GCREG_GLOBAL_DEST_COLOR_RED_End 23
+#define GCREG_GLOBAL_DEST_COLOR_RED_Start 16
+#define GCREG_GLOBAL_DEST_COLOR_RED_Type U08
+
+#define GCREG_GLOBAL_DEST_COLOR_GREEN 15 : 8
+#define GCREG_GLOBAL_DEST_COLOR_GREEN_End 15
+#define GCREG_GLOBAL_DEST_COLOR_GREEN_Start 8
+#define GCREG_GLOBAL_DEST_COLOR_GREEN_Type U08
+
+#define GCREG_GLOBAL_DEST_COLOR_BLUE 7 : 0
+#define GCREG_GLOBAL_DEST_COLOR_BLUE_End 7
+#define GCREG_GLOBAL_DEST_COLOR_BLUE_Start 0
+#define GCREG_GLOBAL_DEST_COLOR_BLUE_Type U08
+
+struct gcregglobaldstcolor {
+ /* gcregGlobalDestColorRegAddrs:GCREG_GLOBAL_DEST_COLOR_BLUE */
+ unsigned int b:8;
+
+ /* gcregGlobalDestColorRegAddrs:GCREG_GLOBAL_DEST_COLOR_GREEN */
+ unsigned int g:8;
+
+ /* gcregGlobalDestColorRegAddrs:GCREG_GLOBAL_DEST_COLOR_RED */
+ unsigned int r:8;
+
+ /* gcregGlobalDestColorRegAddrs:GCREG_GLOBAL_DEST_COLOR_ALPHA */
+ unsigned int a:8;
+};
+
+/*******************************************************************************
+** State gcregColorMultiplyModes
+*/
+
+/* Color modes to multiply Source or Destination pixel color by alpha
+** channel. Alpha can be from global color source or current pixel.
+*/
+
+#define gcregColorMultiplyModesRegAddrs 0x04B4
+#define GCREG_COLOR_MULTIPLY_MODES_MSB 15
+#define GCREG_COLOR_MULTIPLY_MODES_LSB 0
+#define GCREG_COLOR_MULTIPLY_MODES_BLK 0
+#define GCREG_COLOR_MULTIPLY_MODES_Count 1
+#define GCREG_COLOR_MULTIPLY_MODES_FieldMask 0x00100311
+#define GCREG_COLOR_MULTIPLY_MODES_ReadMask 0x00100311
+#define GCREG_COLOR_MULTIPLY_MODES_WriteMask 0x00100311
+#define GCREG_COLOR_MULTIPLY_MODES_ResetValue 0x00000000
+
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY 0 : 0
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_End 0
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Start 0
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Type U01
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE 0x0
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE 0x1
+
+#define GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY 4 : 4
+#define GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_End 4
+#define GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Start 4
+#define GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Type U01
+#define GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_DISABLE 0x0
+#define GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_ENABLE 0x1
+
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY 9 : 8
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_End 9
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Start 8
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Type U02
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE 0x0
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_ALPHA 0x1
+#define GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_COLOR 0x2
+
+#define GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY 20 : 20
+#define GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_End 20
+#define GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Start 20
+#define GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Type U01
+#define GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE 0x0
+#define GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE 0x1
+
+struct gcregcolormultiplymodes {
+ /* gcregColorMultiplyModesRegAddrs:
+ GCREG_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY */
+ unsigned int srcpremul:1;
+
+ /* gcregColorMultiplyModesRegAddrs:
+ reserved */
+ unsigned int _reserved_1_3:3;
+
+ /* gcregColorMultiplyModesRegAddrs:
+ GCREG_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY */
+ unsigned int dstpremul:1;
+
+ /* gcregColorMultiplyModesRegAddrs:
+ reserved */
+ unsigned int _reserved_5_7:3;
+
+ /* gcregColorMultiplyModesRegAddrs:
+ GCREG_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY */
+ unsigned int srcglobalpremul:2;
+
+ /* gcregColorMultiplyModesRegAddrs:
+ reserved */
+ unsigned int _reserved_10_19:10;
+
+ /* gcregColorMultiplyModesRegAddrs:
+ GCREG_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY */
+ unsigned int dstdemul:1;
+
+ /* gcregColorMultiplyModesRegAddrs:
+ reserved */
+ unsigned int _reserved_21_31:11;
+};
+
+/*******************************************************************************
+** State gcregPETransparency
+*/
+
+#define gcregPETransparencyRegAddrs 0x04B5
+#define GCREG_PE_TRANSPARENCY_MSB 15
+#define GCREG_PE_TRANSPARENCY_LSB 0
+#define GCREG_PE_TRANSPARENCY_BLK 0
+#define GCREG_PE_TRANSPARENCY_Count 1
+#define GCREG_PE_TRANSPARENCY_FieldMask 0xB3331333
+#define GCREG_PE_TRANSPARENCY_ReadMask 0xB3331333
+#define GCREG_PE_TRANSPARENCY_WriteMask 0xB3331333
+#define GCREG_PE_TRANSPARENCY_ResetValue 0x00000000
+
+/* Source transparency mode. */
+#define GCREG_PE_TRANSPARENCY_SOURCE 1 : 0
+#define GCREG_PE_TRANSPARENCY_SOURCE_End 1
+#define GCREG_PE_TRANSPARENCY_SOURCE_Start 0
+#define GCREG_PE_TRANSPARENCY_SOURCE_Type U02
+#define GCREG_PE_TRANSPARENCY_SOURCE_OPAQUE 0x0
+#define GCREG_PE_TRANSPARENCY_SOURCE_MASK 0x1
+#define GCREG_PE_TRANSPARENCY_SOURCE_KEY 0x2
+
+/* Pattern transparency mode. KEY transparency mode is reserved. */
+#define GCREG_PE_TRANSPARENCY_PATTERN 5 : 4
+#define GCREG_PE_TRANSPARENCY_PATTERN_End 5
+#define GCREG_PE_TRANSPARENCY_PATTERN_Start 4
+#define GCREG_PE_TRANSPARENCY_PATTERN_Type U02
+#define GCREG_PE_TRANSPARENCY_PATTERN_OPAQUE 0x0
+#define GCREG_PE_TRANSPARENCY_PATTERN_MASK 0x1
+#define GCREG_PE_TRANSPARENCY_PATTERN_KEY 0x2
+
+/* Destination transparency mode. MASK transparency mode is reserved. */
+#define GCREG_PE_TRANSPARENCY_DESTINATION 9 : 8
+#define GCREG_PE_TRANSPARENCY_DESTINATION_End 9
+#define GCREG_PE_TRANSPARENCY_DESTINATION_Start 8
+#define GCREG_PE_TRANSPARENCY_DESTINATION_Type U02
+#define GCREG_PE_TRANSPARENCY_DESTINATION_OPAQUE 0x0
+#define GCREG_PE_TRANSPARENCY_DESTINATION_MASK 0x1
+#define GCREG_PE_TRANSPARENCY_DESTINATION_KEY 0x2
+
+/* Mask field for Source/Pattern/Destination fields. */
+#define GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY 12 : 12
+#define GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY_End 12
+#define GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY_Start 12
+#define GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY_Type U01
+#define GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY_ENABLED 0x0
+#define GCREG_PE_TRANSPARENCY_MASK_TRANSPARENCY_MASKED 0x1
+
+/* Source usage override. */
+#define GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE 17 : 16
+#define GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_End 17
+#define GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_Start 16
+#define GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_Type U02
+#define GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_DEFAULT 0x0
+#define GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_USE_ENABLE 0x1
+#define GCREG_PE_TRANSPARENCY_USE_SRC_OVERRIDE_USE_DISABLE 0x2
+
+/* Pattern usage override. */
+#define GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE 21 : 20
+#define GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_End 21
+#define GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_Start 20
+#define GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_Type U02
+#define GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_DEFAULT 0x0
+#define GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_USE_ENABLE 0x1
+#define GCREG_PE_TRANSPARENCY_USE_PAT_OVERRIDE_USE_DISABLE 0x2
+
+/* Destination usage override. */
+#define GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE 25 : 24
+#define GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_End 25
+#define GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_Start 24
+#define GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_Type U02
+#define GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_DEFAULT 0x0
+#define GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_USE_ENABLE 0x1
+#define GCREG_PE_TRANSPARENCY_USE_DST_OVERRIDE_USE_DISABLE 0x2
+
+/* 2D resource usage override mask field. */
+#define GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE 28 : 28
+#define GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_End 28
+#define GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Start 28
+#define GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Type U01
+#define GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_ENABLED 0x0
+#define GCREG_PE_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_MASKED 0x1
+
+/* DEB Color Key. */
+#define GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY 29 : 29
+#define GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY_End 29
+#define GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY_Start 29
+#define GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY_Type U01
+#define GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY_DISABLED 0x0
+#define GCREG_PE_TRANSPARENCY_DFB_COLOR_KEY_ENABLED 0x1
+
+#define GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY 31 : 31
+#define GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY_End 31
+#define GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY_Start 31
+#define GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY_Type U01
+#define GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY_ENABLED 0x0
+#define GCREG_PE_TRANSPARENCY_MASK_DFB_COLOR_KEY_MASKED 0x1
+
+/*******************************************************************************
+** State gcregPEControl
+*/
+
+/* General purpose control register. */
+
+#define gcregPEControlRegAddrs 0x04B6
+#define GCREG_PE_CONTROL_MSB 15
+#define GCREG_PE_CONTROL_LSB 0
+#define GCREG_PE_CONTROL_BLK 0
+#define GCREG_PE_CONTROL_Count 1
+#define GCREG_PE_CONTROL_FieldMask 0x00000999
+#define GCREG_PE_CONTROL_ReadMask 0x00000999
+#define GCREG_PE_CONTROL_WriteMask 0x00000999
+#define GCREG_PE_CONTROL_ResetValue 0x00000000
+
+#define GCREG_PE_CONTROL_YUV 0 : 0
+#define GCREG_PE_CONTROL_YUV_End 0
+#define GCREG_PE_CONTROL_YUV_Start 0
+#define GCREG_PE_CONTROL_YUV_Type U01
+#define GCREG_PE_CONTROL_YUV_601 0x0
+#define GCREG_PE_CONTROL_YUV_709 0x1
+
+#define GCREG_PE_CONTROL_MASK_YUV 3 : 3
+#define GCREG_PE_CONTROL_MASK_YUV_End 3
+#define GCREG_PE_CONTROL_MASK_YUV_Start 3
+#define GCREG_PE_CONTROL_MASK_YUV_Type U01
+#define GCREG_PE_CONTROL_MASK_YUV_ENABLED 0x0
+#define GCREG_PE_CONTROL_MASK_YUV_MASKED 0x1
+
+#define GCREG_PE_CONTROL_UV_SWIZZLE 4 : 4
+#define GCREG_PE_CONTROL_UV_SWIZZLE_End 4
+#define GCREG_PE_CONTROL_UV_SWIZZLE_Start 4
+#define GCREG_PE_CONTROL_UV_SWIZZLE_Type U01
+#define GCREG_PE_CONTROL_UV_SWIZZLE_UV 0x0
+#define GCREG_PE_CONTROL_UV_SWIZZLE_VU 0x1
+
+#define GCREG_PE_CONTROL_MASK_UV_SWIZZLE 7 : 7
+#define GCREG_PE_CONTROL_MASK_UV_SWIZZLE_End 7
+#define GCREG_PE_CONTROL_MASK_UV_SWIZZLE_Start 7
+#define GCREG_PE_CONTROL_MASK_UV_SWIZZLE_Type U01
+#define GCREG_PE_CONTROL_MASK_UV_SWIZZLE_ENABLED 0x0
+#define GCREG_PE_CONTROL_MASK_UV_SWIZZLE_MASKED 0x1
+
+/* YUV to RGB convert enable */
+#define GCREG_PE_CONTROL_YUVRGB 8 : 8
+#define GCREG_PE_CONTROL_YUVRGB_End 8
+#define GCREG_PE_CONTROL_YUVRGB_Start 8
+#define GCREG_PE_CONTROL_YUVRGB_Type U01
+#define GCREG_PE_CONTROL_YUVRGB_DISABLED 0x0
+#define GCREG_PE_CONTROL_YUVRGB_ENABLED 0x1
+
+#define GCREG_PE_CONTROL_MASK_YUVRGB 11 : 11
+#define GCREG_PE_CONTROL_MASK_YUVRGB_End 11
+#define GCREG_PE_CONTROL_MASK_YUVRGB_Start 11
+#define GCREG_PE_CONTROL_MASK_YUVRGB_Type U01
+#define GCREG_PE_CONTROL_MASK_YUVRGB_ENABLED 0x0
+#define GCREG_PE_CONTROL_MASK_YUVRGB_MASKED 0x1
+
+struct gcregpecontrol {
+ /* gcregPEControlRegAddrs:YUV */
+ unsigned int standard:1;
+
+ /* gcregPEControlRegAddrs:reserved */
+ unsigned int _reserved_1_2:2;
+
+ /* gcregPEControlRegAddrs:MASK_YUV */
+ unsigned int standard_mask:1;
+
+ /* gcregPEControlRegAddrs:UV_SWIZZLE */
+ unsigned int swizzle:1;
+
+ /* gcregPEControlRegAddrs:reserved */
+ unsigned int _reserved_5_6:2;
+
+ /* gcregPEControlRegAddrs:MASK_UV_SWIZZLE */
+ unsigned int swizzle_mask:1;
+
+ /* gcregPEControlRegAddrs:YUVRGB */
+ unsigned int convert:1;
+
+ /* gcregPEControlRegAddrs:reserved */
+ unsigned int _reserved_9_10:2;
+
+ /* gcregPEControlRegAddrs:MASK_YUVRGB */
+ unsigned int convert_mask:1;
+
+ /* gcregPEControlRegAddrs:reserved */
+ unsigned int _reserved_12_31:20;
+};
+
+/*******************************************************************************
+** State gcregSrcColorKeyHigh
+*/
+
+/* Defines the source transparency color in source format. */
+
+#define gcregSrcColorKeyHighRegAddrs 0x04B7
+#define GCREG_SRC_COLOR_KEY_HIGH_Address 0x012DC
+#define GCREG_SRC_COLOR_KEY_HIGH_MSB 15
+#define GCREG_SRC_COLOR_KEY_HIGH_LSB 0
+#define GCREG_SRC_COLOR_KEY_HIGH_BLK 0
+#define GCREG_SRC_COLOR_KEY_HIGH_Count 1
+#define GCREG_SRC_COLOR_KEY_HIGH_FieldMask 0xFFFFFFFF
+#define GCREG_SRC_COLOR_KEY_HIGH_ReadMask 0xFFFFFFFF
+#define GCREG_SRC_COLOR_KEY_HIGH_WriteMask 0xFFFFFFFF
+#define GCREG_SRC_COLOR_KEY_HIGH_ResetValue 0x00000000
+
+#define GCREG_SRC_COLOR_KEY_HIGH_ALPHA 31 : 24
+#define GCREG_SRC_COLOR_KEY_HIGH_ALPHA_End 31
+#define GCREG_SRC_COLOR_KEY_HIGH_ALPHA_Start 24
+#define GCREG_SRC_COLOR_KEY_HIGH_ALPHA_Type U08
+
+#define GCREG_SRC_COLOR_KEY_HIGH_RED 23 : 16
+#define GCREG_SRC_COLOR_KEY_HIGH_RED_End 23
+#define GCREG_SRC_COLOR_KEY_HIGH_RED_Start 16
+#define GCREG_SRC_COLOR_KEY_HIGH_RED_Type U08
+
+#define GCREG_SRC_COLOR_KEY_HIGH_GREEN 15 : 8
+#define GCREG_SRC_COLOR_KEY_HIGH_GREEN_End 15
+#define GCREG_SRC_COLOR_KEY_HIGH_GREEN_Start 8
+#define GCREG_SRC_COLOR_KEY_HIGH_GREEN_Type U08
+
+#define GCREG_SRC_COLOR_KEY_HIGH_BLUE 7 : 0
+#define GCREG_SRC_COLOR_KEY_HIGH_BLUE_End 7
+#define GCREG_SRC_COLOR_KEY_HIGH_BLUE_Start 0
+#define GCREG_SRC_COLOR_KEY_HIGH_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregDestColorKeyHigh
+*/
+
+/* Defines the destination transparency color in destination format. */
+
+#define gcregDestColorKeyHighRegAddrs 0x04B8
+#define GCREG_DEST_COLOR_KEY_HIGH_MSB 15
+#define GCREG_DEST_COLOR_KEY_HIGH_LSB 0
+#define GCREG_DEST_COLOR_KEY_HIGH_BLK 0
+#define GCREG_DEST_COLOR_KEY_HIGH_Count 1
+#define GCREG_DEST_COLOR_KEY_HIGH_FieldMask 0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_HIGH_ReadMask 0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_HIGH_WriteMask 0xFFFFFFFF
+#define GCREG_DEST_COLOR_KEY_HIGH_ResetValue 0x00000000
+
+#define GCREG_DEST_COLOR_KEY_HIGH_ALPHA 31 : 24
+#define GCREG_DEST_COLOR_KEY_HIGH_ALPHA_End 31
+#define GCREG_DEST_COLOR_KEY_HIGH_ALPHA_Start 24
+#define GCREG_DEST_COLOR_KEY_HIGH_ALPHA_Type U08
+
+#define GCREG_DEST_COLOR_KEY_HIGH_RED 23 : 16
+#define GCREG_DEST_COLOR_KEY_HIGH_RED_End 23
+#define GCREG_DEST_COLOR_KEY_HIGH_RED_Start 16
+#define GCREG_DEST_COLOR_KEY_HIGH_RED_Type U08
+
+#define GCREG_DEST_COLOR_KEY_HIGH_GREEN 15 : 8
+#define GCREG_DEST_COLOR_KEY_HIGH_GREEN_End 15
+#define GCREG_DEST_COLOR_KEY_HIGH_GREEN_Start 8
+#define GCREG_DEST_COLOR_KEY_HIGH_GREEN_Type U08
+
+#define GCREG_DEST_COLOR_KEY_HIGH_BLUE 7 : 0
+#define GCREG_DEST_COLOR_KEY_HIGH_BLUE_End 7
+#define GCREG_DEST_COLOR_KEY_HIGH_BLUE_Start 0
+#define GCREG_DEST_COLOR_KEY_HIGH_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregPEDitherLow
+*/
+
+/* PE dither register.
+** If you don't want dither, set all fields to their reset values.
+*/
+
+#define gcregPEDitherLowRegAddrs 0x04BA
+#define GCREG_PE_DITHER_LOW_MSB 15
+#define GCREG_PE_DITHER_LOW_LSB 0
+#define GCREG_PE_DITHER_LOW_BLK 0
+#define GCREG_PE_DITHER_LOW_Count 1
+#define GCREG_PE_DITHER_LOW_FieldMask 0xFFFFFFFF
+#define GCREG_PE_DITHER_LOW_ReadMask 0xFFFFFFFF
+#define GCREG_PE_DITHER_LOW_WriteMask 0xFFFFFFFF
+#define GCREG_PE_DITHER_LOW_ResetValue 0xFFFFFFFF
+
+/* X,Y = 0,0 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y0 3 : 0
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y0_End 3
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y0_Start 0
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y0_Type U04
+
+/* X,Y = 1,0 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y0 7 : 4
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y0_End 7
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y0_Start 4
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y0_Type U04
+
+/* X,Y = 2,0 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y0 11 : 8
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y0_End 11
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y0_Start 8
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y0_Type U04
+
+/* X,Y = 3,0 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y0 15 : 12
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y0_End 15
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y0_Start 12
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y0_Type U04
+
+/* X,Y = 0,1 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y1 19 : 16
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y1_End 19
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y1_Start 16
+#define GCREG_PE_DITHER_LOW_PIXEL_X0_Y1_Type U04
+
+/* X,Y = 1,1 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y1 23 : 20
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y1_End 23
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y1_Start 20
+#define GCREG_PE_DITHER_LOW_PIXEL_X1_Y1_Type U04
+
+/* X,Y = 2,1 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y1 27 : 24
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y1_End 27
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y1_Start 24
+#define GCREG_PE_DITHER_LOW_PIXEL_X2_Y1_Type U04
+
+/* X,Y = 3,1 */
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y1 31 : 28
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y1_End 31
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y1_Start 28
+#define GCREG_PE_DITHER_LOW_PIXEL_X3_Y1_Type U04
+
+/*******************************************************************************
+** State gcregPEDitherHigh
+*/
+
+#define gcregPEDitherHighRegAddrs 0x04BB
+#define GCREG_PE_DITHER_HIGH_MSB 15
+#define GCREG_PE_DITHER_HIGH_LSB 0
+#define GCREG_PE_DITHER_LOW_HIGH_BLK 0
+#define GCREG_PE_DITHER_HIGH_Count 1
+#define GCREG_PE_DITHER_HIGH_FieldMask 0xFFFFFFFF
+#define GCREG_PE_DITHER_HIGH_ReadMask 0xFFFFFFFF
+#define GCREG_PE_DITHER_HIGH_WriteMask 0xFFFFFFFF
+#define GCREG_PE_DITHER_HIGH_ResetValue 0xFFFFFFFF
+
+/* X,Y = 0,2 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y2 3 : 0
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y2_End 3
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y2_Start 0
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y2_Type U04
+
+/* X,Y = 1,2 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y2 7 : 4
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y2_End 7
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y2_Start 4
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y2_Type U04
+
+/* X,Y = 2,2 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y2 11 : 8
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y2_End 11
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y2_Start 8
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y2_Type U04
+
+/* X,Y = 0,3 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y2 15 : 12
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y2_End 15
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y2_Start 12
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y2_Type U04
+
+/* X,Y = 1,3 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y3 19 : 16
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y3_End 19
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y3_Start 16
+#define GCREG_PE_DITHER_HIGH_PIXEL_X0_Y3_Type U04
+
+/* X,Y = 2,3 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y3 23 : 20
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y3_End 23
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y3_Start 20
+#define GCREG_PE_DITHER_HIGH_PIXEL_X1_Y3_Type U04
+
+/* X,Y = 3,3 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y3 27 : 24
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y3_End 27
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y3_Start 24
+#define GCREG_PE_DITHER_HIGH_PIXEL_X2_Y3_Type U04
+
+/* X,Y = 3,2 */
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y3 31 : 28
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y3_End 31
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y3_Start 28
+#define GCREG_PE_DITHER_HIGH_PIXEL_X3_Y3_Type U04
+
+/*******************************************************************************
+** State gcregSrcExConfig
+*/
+
+#define gcregSrcExConfigRegAddrs 0x04C0
+#define GCREG_SRC_EX_CONFIG_MSB 15
+#define GCREG_SRC_EX_CONFIG_LSB 0
+#define GCREG_SRC_EX_CONFIG_BLK 0
+#define GCREG_SRC_EX_CONFIG_Count 1
+#define GCREG_SRC_EX_CONFIG_FieldMask 0x00000109
+#define GCREG_SRC_EX_CONFIG_ReadMask 0x00000109
+#define GCREG_SRC_EX_CONFIG_WriteMask 0x00000109
+#define GCREG_SRC_EX_CONFIG_ResetValue 0x00000000
+
+/* Source multi tiled address computation control. */
+#define GCREG_SRC_EX_CONFIG_MULTI_TILED 0 : 0
+#define GCREG_SRC_EX_CONFIG_MULTI_TILED_End 0
+#define GCREG_SRC_EX_CONFIG_MULTI_TILED_Start 0
+#define GCREG_SRC_EX_CONFIG_MULTI_TILED_Type U01
+#define GCREG_SRC_EX_CONFIG_MULTI_TILED_DISABLED 0x0
+#define GCREG_SRC_EX_CONFIG_MULTI_TILED_ENABLED 0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_SRC_EX_CONFIG_SUPER_TILED 3 : 3
+#define GCREG_SRC_EX_CONFIG_SUPER_TILED_End 3
+#define GCREG_SRC_EX_CONFIG_SUPER_TILED_Start 3
+#define GCREG_SRC_EX_CONFIG_SUPER_TILED_Type U01
+#define GCREG_SRC_EX_CONFIG_SUPER_TILED_DISABLED 0x0
+#define GCREG_SRC_EX_CONFIG_SUPER_TILED_ENABLED 0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_SRC_EX_CONFIG_MINOR_TILED 8 : 8
+#define GCREG_SRC_EX_CONFIG_MINOR_TILED_End 8
+#define GCREG_SRC_EX_CONFIG_MINOR_TILED_Start 8
+#define GCREG_SRC_EX_CONFIG_MINOR_TILED_Type U01
+#define GCREG_SRC_EX_CONFIG_MINOR_TILED_DISABLED 0x0
+#define GCREG_SRC_EX_CONFIG_MINOR_TILED_ENABLED 0x1
+
+/* Source CacheMode. */
+#define GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE 12 : 12
+#define GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE_End 12
+#define GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE_Start 12
+#define GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE_Type U01
+#define GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE_DISABLED 0x0
+#define GCREG_SRC_SRC_EX_CONFIG_CACHE_MODE_ENABLED 0x1
+
+/*******************************************************************************
+** State gcregSrcExAddress
+*/
+
+/* 32-bit aligned base address of the source extra surface. */
+
+#define gcregSrcExAddressRegAddrs 0x04C1
+#define GCREG_SRC_EX_ADDRESS_MSB 15
+#define GCREG_SRC_EX_ADDRESS_LSB 0
+#define GCREG_SRC_EX_ADDRESS_BLK 0
+#define GCREG_SRC_EX_ADDRESS_Count 1
+#define GCREG_SRC_EX_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_SRC_EX_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_SRC_EX_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_SRC_EX_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_SRC_EX_ADDRESS_ADDRESS 31 : 0
+#define GCREG_SRC_EX_ADDRESS_ADDRESS_End 30
+#define GCREG_SRC_EX_ADDRESS_ADDRESS_Start 0
+#define GCREG_SRC_EX_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregDEMultiSource
+*/
+
+/* MutiSource control register. */
+
+#define gcregDEMultiSourceRegAddrs 0x04C2
+#define GCREG_DE_MULTI_SOURCE_MSB 15
+#define GCREG_DE_MULTI_SOURCE_LSB 0
+#define GCREG_DE_MULTI_SOURCE_BLK 0
+#define GCREG_DE_MULTI_SOURCE_Count 1
+#define GCREG_DE_MULTI_SOURCE_FieldMask 0x00070707
+#define GCREG_DE_MULTI_SOURCE_ReadMask 0x00070707
+#define GCREG_DE_MULTI_SOURCE_WriteMask 0x00070707
+#define GCREG_DE_MULTI_SOURCE_ResetValue 0x00000000
+
+/* Number of source surfaces minus 1. */
+#define GCREG_DE_MULTI_SOURCE_MAX_SOURCE 2 : 0
+#define GCREG_DE_MULTI_SOURCE_MAX_SOURCE_End 2
+#define GCREG_DE_MULTI_SOURCE_MAX_SOURCE_Start 0
+#define GCREG_DE_MULTI_SOURCE_MAX_SOURCE_Type U03
+
+/* Number of pixels for horizontal block walker. */
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK 10 : 8
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_End 10
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_Start 8
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_Type U03
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL16 0x0
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL32 0x1
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL64 0x2
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL128 0x3
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL256 0x4
+#define GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK_PIXEL512 0x5
+
+/* Number of lines for vertical block walker. */
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK 18 : 16
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_End 18
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_Start 16
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_Type U03
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE1 0x0
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE2 0x1
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE4 0x2
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE8 0x3
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE16 0x4
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE32 0x5
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE64 0x6
+#define GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK_LINE128 0x7
+
+struct gcregmultisource {
+ /* gcregDEMultiSourceRegAddrs:GCREG_DE_MULTI_SOURCE_MAX_SOURCE */
+ unsigned int srccount:3;
+
+ /* gcregDEMultiSourceRegAddrs:reserved */
+ unsigned int _reserved_3_7:5;
+
+ /* gcregDEMultiSourceRegAddrs:GCREG_DE_MULTI_SOURCE_HORIZONTAL_BLOCK */
+ unsigned int horblock:3;
+
+ /* gcregDEMultiSourceRegAddrs:reserved */
+ unsigned int _reserved_11_15:5;
+
+ /* gcregDEMultiSourceRegAddrs:GCREG_DE_MULTI_SOURCE_VERTICAL_BLOCK */
+ unsigned int verblock:3;
+
+ /* gcregDEMultiSourceRegAddrs:reserved */
+ unsigned int _reserved_19_31:13;
+};
+
+/*******************************************************************************
+** State gcregDEYUVConversion
+*/
+
+/* Configure the YUV to YUV conversion. */
+
+#define gcregDEYUVConversionRegAddrs 0x04C3
+#define GCREG_DEYUV_CONVERSION_MSB 15
+#define GCREG_DEYUV_CONVERSION_LSB 0
+#define GCREG_DEYUV_CONVERSION_BLK 0
+#define GCREG_DEYUV_CONVERSION_Count 1
+#define GCREG_DEYUV_CONVERSION_FieldMask 0xFFFFFFFF
+#define GCREG_DEYUV_CONVERSION_ReadMask 0xFFFFFFFF
+#define GCREG_DEYUV_CONVERSION_WriteMask 0xFFFFFFFF
+#define GCREG_DEYUV_CONVERSION_ResetValue 0x00000000
+
+/* Select the number of planes we need to process. */
+#define GCREG_DEYUV_CONVERSION_ENABLE 1 : 0
+#define GCREG_DEYUV_CONVERSION_ENABLE_End 1
+#define GCREG_DEYUV_CONVERSION_ENABLE_Start 0
+#define GCREG_DEYUV_CONVERSION_ENABLE_Type U02
+/* YUV to YUV conversion is turned off. */
+#define GCREG_DEYUV_CONVERSION_ENABLE_OFF 0x0
+/* YUV to YUV conversion is writing to 1 plane. */
+#define GCREG_DEYUV_CONVERSION_ENABLE_PLANE1 0x1
+/* YUV to YUV conversion is writing to 2 planes. */
+#define GCREG_DEYUV_CONVERSION_ENABLE_PLANE2 0x2
+/* YUV to YUV conversion is writing to 3 planes. */
+#define GCREG_DEYUV_CONVERSION_ENABLE_PLANE3 0x3
+
+/* Number of channels to process - 1 for plane 1. */
+#define GCREG_DEYUV_CONVERSION_PLANE1_COUNT 3 : 2
+#define GCREG_DEYUV_CONVERSION_PLANE1_COUNT_End 3
+#define GCREG_DEYUV_CONVERSION_PLANE1_COUNT_Start 2
+#define GCREG_DEYUV_CONVERSION_PLANE1_COUNT_Type U02
+
+/* Number of channels to process - 1 for plane 2. */
+#define GCREG_DEYUV_CONVERSION_PLANE2_COUNT 5 : 4
+#define GCREG_DEYUV_CONVERSION_PLANE2_COUNT_End 5
+#define GCREG_DEYUV_CONVERSION_PLANE2_COUNT_Start 4
+#define GCREG_DEYUV_CONVERSION_PLANE2_COUNT_Type U02
+
+/* Number of channels to process - 1 for plane 3. */
+#define GCREG_DEYUV_CONVERSION_PLANE3_COUNT 7 : 6
+#define GCREG_DEYUV_CONVERSION_PLANE3_COUNT_End 7
+#define GCREG_DEYUV_CONVERSION_PLANE3_COUNT_Start 6
+#define GCREG_DEYUV_CONVERSION_PLANE3_COUNT_Type U02
+
+/* Select which color channel to pick for B channel for plane 1. */
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B 9 : 8
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_End 9
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_Start 8
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_B_ALPHA 0x3
+
+/* Select which color channel to pick for G channel for plane 1. */
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G 11 : 10
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_End 11
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_Start 10
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_G_ALPHA 0x3
+
+/* Select which color channel to pick for R channel for plane 1. */
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R 13 : 12
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_End 13
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_Start 12
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_R_ALPHA 0x3
+
+/* Select which color channel to pick for A channel for plane 1. */
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A 15 : 14
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_End 15
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_Start 14
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE1_SWIZZLE_A_ALPHA 0x3
+
+/* Select which color channel to pick for B channel for plane 2. */
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B 17 : 16
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_End 17
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_Start 16
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_B_ALPHA 0x3
+
+/* Select which color channel to pick for G channel for plane 2. */
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G 19 : 18
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_End 19
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_Start 18
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_G_ALPHA 0x3
+
+/* Select which color channel to pick for R channel for plane 2. */
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R 21 : 20
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_End 21
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_Start 20
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_R_ALPHA 0x3
+
+/* Select which color channel to pick for A channel for plane 2. */
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A 23 : 22
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_End 23
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_Start 22
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE2_SWIZZLE_A_ALPHA 0x3
+
+/* Select which color channel to pick for B channel for plane 3. */
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B 25 : 24
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_End 25
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_Start 24
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_B_ALPHA 0x3
+
+/* Select which color channel to pick for G channel for plane 3. */
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G 27 : 26
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_End 27
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_Start 26
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_G_ALPHA 0x3
+
+/* Select which color channel to pick for R channel for plane 3. */
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R 29 : 28
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_End 29
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_Start 28
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_R_ALPHA 0x3
+
+/* Select which color channel to pick for A channel for plane 3. */
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A 31 : 30
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_End 31
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_Start 30
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_Type U02
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_BLUE 0x0
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_GREEN 0x1
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_RED 0x2
+#define GCREG_DEYUV_CONVERSION_PLANE3_SWIZZLE_A_ALPHA 0x3
+
+/*******************************************************************************
+** State gcregDEPlane2Address
+*/
+
+/* Address for plane 2 if gcregDEYUVConversion.
+** Enable is set to Plane2 or Plane3.
+*/
+
+#define gcregDEPlane2AddressRegAddrs 0x04C4
+#define GCREG_DE_PLANE2_ADDRESS_Address 0x01310
+#define GCREG_DE_PLANE2_ADDRESS_MSB 15
+#define GCREG_DE_PLANE2_ADDRESS_LSB 0
+#define GCREG_DE_PLANE2_ADDRESS_BLK 0
+#define GCREG_DE_PLANE2_ADDRESS_Count 1
+#define GCREG_DE_PLANE2_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_DE_PLANE2_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_DE_PLANE2_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_DE_PLANE2_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_DE_PLANE2_ADDRESS_ADDRESS 31 : 0
+#define GCREG_DE_PLANE2_ADDRESS_ADDRESS_End 30
+#define GCREG_DE_PLANE2_ADDRESS_ADDRESS_Start 0
+#define GCREG_DE_PLANE2_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregDEPlane2Stride
+*/
+
+/* Stride for plane 2 if gcregDEYUVConversion.
+** Enable is set to Plane2 or Plane3.
+*/
+
+#define gcregDEPlane2StrideRegAddrs 0x04C5
+#define GCREG_DE_PLANE2_STRIDE_MSB 15
+#define GCREG_DE_PLANE2_STRIDE_LSB 0
+#define GCREG_DE_PLANE2_STRIDE_BLK 0
+#define GCREG_DE_PLANE2_STRIDE_Count 1
+#define GCREG_DE_PLANE2_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_DE_PLANE2_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_DE_PLANE2_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_DE_PLANE2_STRIDE_ResetValue 0x00000000
+
+#define GCREG_DE_PLANE2_STRIDE_STRIDE 17 : 0
+#define GCREG_DE_PLANE2_STRIDE_STRIDE_End 17
+#define GCREG_DE_PLANE2_STRIDE_STRIDE_Start 0
+#define GCREG_DE_PLANE2_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State gcregDEPlane3Address
+*/
+
+/* Address for plane 3 if gcregDEYUVConversion.
+** Enable is set to Plane3.
+*/
+
+#define gcregDEPlane3AddressRegAddrs 0x04C6
+#define GCREG_DE_PLANE3_ADDRESS_MSB 15
+#define GCREG_DE_PLANE3_ADDRESS_LSB 0
+#define GCREG_DE_PLANE3_ADDRESS_BLK 0
+#define GCREG_DE_PLANE3_ADDRESS_Count 1
+#define GCREG_DE_PLANE3_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_DE_PLANE3_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_DE_PLANE3_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_DE_PLANE3_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_DE_PLANE3_ADDRESS_ADDRESS 31 : 0
+#define GCREG_DE_PLANE3_ADDRESS_ADDRESS_End 30
+#define GCREG_DE_PLANE3_ADDRESS_ADDRESS_Start 0
+#define GCREG_DE_PLANE3_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregDEPlane3Stride
+*/
+
+/* Stride for plane 3 if gcregDEYUVConversion.
+** Enable is set to Plane3.
+*/
+
+#define gcregDEPlane3StrideRegAddrs 0x04C7
+#define GCREG_DE_PLANE3_STRIDE_MSB 15
+#define GCREG_DE_PLANE3_STRIDE_LSB 0
+#define GCREG_DE_PLANE3_STRIDE_BLK 0
+#define GCREG_DE_PLANE3_STRIDE_Count 1
+#define GCREG_DE_PLANE3_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_DE_PLANE3_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_DE_PLANE3_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_DE_PLANE3_STRIDE_ResetValue 0x00000000
+
+#define GCREG_DE_PLANE3_STRIDE_STRIDE 17 : 0
+#define GCREG_DE_PLANE3_STRIDE_STRIDE_End 17
+#define GCREG_DE_PLANE3_STRIDE_STRIDE_Start 0
+#define GCREG_DE_PLANE3_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State gcregDEStallDE
+*/
+
+#define gcregDEStallDERegAddrs 0x04C8
+#define GCREG_DE_STALL_DE_MSB 15
+#define GCREG_DE_STALL_DE_LSB 0
+#define GCREG_DE_STALL_DE_BLK 0
+#define GCREG_DE_STALL_DE_Count 1
+#define GCREG_DE_STALL_DE_FieldMask 0x00000001
+#define GCREG_DE_STALL_DE_ReadMask 0x00000001
+#define GCREG_DE_STALL_DE_WriteMask 0x00000001
+#define GCREG_DE_STALL_DE_ResetValue 0x00000000
+
+/* Stall de enable. */
+#define GCREG_DE_STALL_DE_ENABLE 0 : 0
+#define GCREG_DE_STALL_DE_ENABLE_End 0
+#define GCREG_DE_STALL_DE_ENABLE_Start 0
+#define GCREG_DE_STALL_DE_ENABLE_Type U01
+#define GCREG_DE_STALL_DE_ENABLE_DISABLED 0x0
+#define GCREG_DE_STALL_DE_ENABLE_ENABLED 0x1
+
+/*******************************************************************************
+** State gcregBlock4SrcAddress
+*/
+
+/* 32-bit aligned base address of the source surface. */
+
+#define gcregBlock4SrcAddressRegAddrs 0x4A00
+#define GCREG_BLOCK4_SRC_ADDRESS_MSB 15
+#define GCREG_BLOCK4_SRC_ADDRESS_LSB 2
+#define GCREG_BLOCK4_SRC_ADDRESS_BLK 0
+#define GCREG_BLOCK4_SRC_ADDRESS_Count 4
+#define GCREG_BLOCK4_SRC_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_BLOCK4_SRC_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_BLOCK4_SRC_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_SRC_ADDRESS_ADDRESS 31 : 0
+#define GCREG_BLOCK4_SRC_ADDRESS_ADDRESS_End 30
+#define GCREG_BLOCK4_SRC_ADDRESS_ADDRESS_Start 0
+#define GCREG_BLOCK4_SRC_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregBlock4SrcStride
+*/
+
+/* Stride of the source surface in bytes. To calculate the stride multiply
+** the surface width in pixels by the number of bytes per pixel.
+*/
+
+#define gcregBlock4SrcStrideRegAddrs 0x4A04
+#define GCREG_BLOCK4_SRC_STRIDE_MSB 15
+#define GCREG_BLOCK4_SRC_STRIDE_LSB 2
+#define GCREG_BLOCK4_SRC_STRIDE_BLK 0
+#define GCREG_BLOCK4_SRC_STRIDE_Count 4
+#define GCREG_BLOCK4_SRC_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_BLOCK4_SRC_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_BLOCK4_SRC_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_BLOCK4_SRC_STRIDE_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_SRC_STRIDE_STRIDE 17 : 0
+#define GCREG_BLOCK4_SRC_STRIDE_STRIDE_End 17
+#define GCREG_BLOCK4_SRC_STRIDE_STRIDE_Start 0
+#define GCREG_BLOCK4_SRC_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State gcregBlock4SrcRotationConfig
+*/
+
+/* 90 degree rotation configuration for the source surface. Width field
+** specifies the width of the surface in pixels.
+*/
+
+#define gcregBlock4SrcRotationConfigRegAddrs 0x4A08
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_MSB 15
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_LSB 2
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_BLK 0
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_Count 4
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_FieldMask 0x0001FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ReadMask 0x0001FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_WriteMask 0x0001FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_WIDTH 15 : 0
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_WIDTH_End 15
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_WIDTH_Start 0
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_WIDTH_Type U16
+
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION 16 : 16
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_End 16
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_Start 16
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_Type U01
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_DISABLE 0x0
+#define GCREG_BLOCK4_SRC_ROTATION_CONFIG_ROTATION_ENABLE 0x1
+
+/*******************************************************************************
+** State gcregBlock4SrcConfig
+*/
+
+/* Source surface configuration register. */
+
+#define gcregBlock4SrcConfigRegAddrs 0x4A0C
+#define GCREG_BLOCK4_SRC_CONFIG_MSB 15
+#define GCREG_BLOCK4_SRC_CONFIG_LSB 2
+#define GCREG_BLOCK4_SRC_CONFIG_BLK 0
+#define GCREG_BLOCK4_SRC_CONFIG_Count 4
+#define GCREG_BLOCK4_SRC_CONFIG_FieldMask 0xDF30B1C0
+#define GCREG_BLOCK4_SRC_CONFIG_ReadMask 0xDF30B1C0
+#define GCREG_BLOCK4_SRC_CONFIG_WriteMask 0xDF30B1C0
+#define GCREG_BLOCK4_SRC_CONFIG_ResetValue 0x00000000
+
+/* Control source endianess. */
+#define GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL 31 : 30
+#define GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_End 31
+#define GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_Start 30
+#define GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_Type U02
+#define GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_NO_SWAP 0x0
+#define GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_SWAP_WORD 0x1
+#define GCREG_BLOCK4_SRC_CONFIG_ENDIAN_CONTROL_SWAP_DWORD 0x2
+
+/* Defines the pixel format of the source surface. */
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT 28 : 24
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_End 28
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_Start 24
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_Type U05
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_X4R4G4B4 0x00
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_A4R4G4B4 0x01
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_X1R5G5B5 0x02
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_A1R5G5B5 0x03
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_R5G6B5 0x04
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_X8R8G8B8 0x05
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_A8R8G8B8 0x06
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_YUY2 0x07
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_UYVY 0x08
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_INDEX8 0x09
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_MONOCHROME 0x0A
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_YV12 0x0F
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_A8 0x10
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_NV12 0x11
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_NV16 0x12
+#define GCREG_BLOCK4_SRC_CONFIG_SOURCE_FORMAT_RG16 0x13
+
+/* Color channel swizzles. */
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE 21 : 20
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_End 21
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_Start 20
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_Type U02
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_ARGB 0x0
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_RGBA 0x1
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_ABGR 0x2
+#define GCREG_BLOCK4_SRC_CONFIG_SWIZZLE_BGRA 0x3
+
+/* Mono expansion: if 0, transparency color will be 0, otherwise transparency **
+** color will be 1. */
+#define GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY 15 : 15
+#define GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_End 15
+#define GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_Start 15
+#define GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_Type U01
+#define GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_BACKGROUND 0x0
+#define GCREG_BLOCK4_SRC_CONFIG_MONO_TRANSPARENCY_FOREGROUND 0x1
+
+/* Mono expansion or masked blit: stream packing in pixels. Determines how **
+** many horizontal pixels are there per each 32-bit chunk. For example, if **
+** set to Packed8, each 32-bit chunk is 8-pixel wide, which also means that **
+** it defines 4 vertical lines of pixels. */
+#define GCREG_BLOCK4_SRC_CONFIG_PACK 13 : 12
+#define GCREG_BLOCK4_SRC_CONFIG_PACK_End 13
+#define GCREG_BLOCK4_SRC_CONFIG_PACK_Start 12
+#define GCREG_BLOCK4_SRC_CONFIG_PACK_Type U02
+#define GCREG_BLOCK4_SRC_CONFIG_PACK_PACKED8 0x0
+#define GCREG_BLOCK4_SRC_CONFIG_PACK_PACKED16 0x1
+#define GCREG_BLOCK4_SRC_CONFIG_PACK_PACKED32 0x2
+#define GCREG_BLOCK4_SRC_CONFIG_PACK_UNPACKED 0x3
+
+/* Source data location: set to STREAM for mono expansion blits or masked **
+** blits. For mono expansion blits the complete bitmap comes from the command **
+** stream. For masked blits the source data comes from the memory and the **
+** mask from the command stream. */
+#define GCREG_BLOCK4_SRC_CONFIG_LOCATION 8 : 8
+#define GCREG_BLOCK4_SRC_CONFIG_LOCATION_End 8
+#define GCREG_BLOCK4_SRC_CONFIG_LOCATION_Start 8
+#define GCREG_BLOCK4_SRC_CONFIG_LOCATION_Type U01
+#define GCREG_BLOCK4_SRC_CONFIG_LOCATION_MEMORY 0x0
+#define GCREG_BLOCK4_SRC_CONFIG_LOCATION_STREAM 0x1
+
+/* Source linear/tiled address computation control. */
+#define GCREG_BLOCK4_SRC_CONFIG_TILED 7 : 7
+#define GCREG_BLOCK4_SRC_CONFIG_TILED_End 7
+#define GCREG_BLOCK4_SRC_CONFIG_TILED_Start 7
+#define GCREG_BLOCK4_SRC_CONFIG_TILED_Type U01
+#define GCREG_BLOCK4_SRC_CONFIG_TILED_DISABLED 0x0
+#define GCREG_BLOCK4_SRC_CONFIG_TILED_ENABLED 0x1
+
+/* If set to ABSOLUTE, the source coordinates are treated as absolute **
+** coordinates inside the source surface. If set to RELATIVE, the source **
+** coordinates are treated as the offsets from the destination coordinates **
+** with the source size equal to the size of the destination. */
+#define GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE 6 : 6
+#define GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE_End 6
+#define GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE_Start 6
+#define GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE_Type U01
+#define GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE_ABSOLUTE 0x0
+#define GCREG_BLOCK4_SRC_CONFIG_SRC_RELATIVE_RELATIVE 0x1
+
+/*******************************************************************************
+** State gcregBlock4SrcOrigin
+*/
+
+/* Absolute or relative (see SRC_RELATIVE field of gcregBlock4SrcConfig
+** register) X and Y coordinates in pixels of the top left corner of the
+** source rectangle within the source surface.
+*/
+
+#define gcregBlock4SrcOriginRegAddrs 0x4A10
+#define GCREG_BLOCK4_SRC_ORIGIN_MSB 15
+#define GCREG_BLOCK4_SRC_ORIGIN_LSB 2
+#define GCREG_BLOCK4_SRC_ORIGIN_BLK 0
+#define GCREG_BLOCK4_SRC_ORIGIN_Count 4
+#define GCREG_BLOCK4_SRC_ORIGIN_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_ORIGIN_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_ORIGIN_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_ORIGIN_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_SRC_ORIGIN_Y 31 : 16
+#define GCREG_BLOCK4_SRC_ORIGIN_Y_End 31
+#define GCREG_BLOCK4_SRC_ORIGIN_Y_Start 16
+#define GCREG_BLOCK4_SRC_ORIGIN_Y_Type U16
+
+#define GCREG_BLOCK4_SRC_ORIGIN_X 15 : 0
+#define GCREG_BLOCK4_SRC_ORIGIN_X_End 15
+#define GCREG_BLOCK4_SRC_ORIGIN_X_Start 0
+#define GCREG_BLOCK4_SRC_ORIGIN_X_Type U16
+
+/*******************************************************************************
+** State gcregBlock4SrcSize
+*/
+
+/* Width and height of the source rectangle in pixels. If the source is
+** relative (see SRC_RELATIVE field of gcregBlock4SrcConfig register) or a
+** regular bitblt is being performed without stretching, this register is
+** ignored and the source size is assumed to be the same as the destination.
+*/
+
+#define gcregBlock4SrcSizeRegAddrs 0x4A14
+#define GCREG_BLOCK4_SRC_SIZE_MSB 15
+#define GCREG_BLOCK4_SRC_SIZE_LSB 2
+#define GCREG_BLOCK4_SRC_SIZE_BLK 0
+#define GCREG_BLOCK4_SRC_SIZE_Count 4
+#define GCREG_BLOCK4_SRC_SIZE_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_SIZE_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_SIZE_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_SIZE_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_SRC_SIZE_Y 31 : 16
+#define GCREG_BLOCK4_SRC_SIZE_Y_End 31
+#define GCREG_BLOCK4_SRC_SIZE_Y_Start 16
+#define GCREG_BLOCK4_SRC_SIZE_Y_Type U16
+
+#define GCREG_BLOCK4_SRC_SIZE_X 15 : 0
+#define GCREG_BLOCK4_SRC_SIZE_X_End 15
+#define GCREG_BLOCK4_SRC_SIZE_X_Start 0
+#define GCREG_BLOCK4_SRC_SIZE_X_Type U16
+
+/*******************************************************************************
+** State gcregBlock4SrcColorBg
+*/
+
+/* Select the color where source becomes transparent. It must be programmed
+** in A8R8G8B8 format.
+*/
+
+#define gcregBlock4SrcColorBgRegAddrs 0x4A18
+#define GCREG_BLOCK4_SRC_COLOR_BG_MSB 15
+#define GCREG_BLOCK4_SRC_COLOR_BG_LSB 2
+#define GCREG_BLOCK4_SRC_COLOR_BG_BLK 0
+#define GCREG_BLOCK4_SRC_COLOR_BG_Count 4
+#define GCREG_BLOCK4_SRC_COLOR_BG_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_BG_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_BG_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_BG_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_SRC_COLOR_BG_ALPHA 31 : 24
+#define GCREG_BLOCK4_SRC_COLOR_BG_ALPHA_End 31
+#define GCREG_BLOCK4_SRC_COLOR_BG_ALPHA_Start 24
+#define GCREG_BLOCK4_SRC_COLOR_BG_ALPHA_Type U08
+
+#define GCREG_BLOCK4_SRC_COLOR_BG_RED 23 : 16
+#define GCREG_BLOCK4_SRC_COLOR_BG_RED_End 23
+#define GCREG_BLOCK4_SRC_COLOR_BG_RED_Start 16
+#define GCREG_BLOCK4_SRC_COLOR_BG_RED_Type U08
+
+#define GCREG_BLOCK4_SRC_COLOR_BG_GREEN 15 : 8
+#define GCREG_BLOCK4_SRC_COLOR_BG_GREEN_End 15
+#define GCREG_BLOCK4_SRC_COLOR_BG_GREEN_Start 8
+#define GCREG_BLOCK4_SRC_COLOR_BG_GREEN_Type U08
+
+#define GCREG_BLOCK4_SRC_COLOR_BG_BLUE 7 : 0
+#define GCREG_BLOCK4_SRC_COLOR_BG_BLUE_End 7
+#define GCREG_BLOCK4_SRC_COLOR_BG_BLUE_Start 0
+#define GCREG_BLOCK4_SRC_COLOR_BG_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregBlock4Rop
+*/
+
+/* Raster operation foreground and background codes. Even though ROP is not
+** used in CLEAR, HOR_FILTER_BLT, VER_FILTER_BLT and alpha-eanbled BIT_BLTs,
+** ROP code still has to be programmed, because the engine makes the decision
+** whether source, destination and pattern are involved in the current
+** operation and the correct decision is essential for the engine to complete
+** the operation as expected.
+*/
+
+#define gcregBlock4RopRegAddrs 0x4A1C
+#define GCREG_BLOCK4_ROP_MSB 15
+#define GCREG_BLOCK4_ROP_LSB 2
+#define GCREG_BLOCK4_ROP_BLK 0
+#define GCREG_BLOCK4_ROP_Count 4
+#define GCREG_BLOCK4_ROP_FieldMask 0x0030FFFF
+#define GCREG_BLOCK4_ROP_ReadMask 0x0030FFFF
+#define GCREG_BLOCK4_ROP_WriteMask 0x0030FFFF
+#define GCREG_BLOCK4_ROP_ResetValue 0x00000000
+
+/* ROP type: ROP2, ROP3 or ROP4 */
+#define GCREG_BLOCK4_ROP_TYPE 21 : 20
+#define GCREG_BLOCK4_ROP_TYPE_End 21
+#define GCREG_BLOCK4_ROP_TYPE_Start 20
+#define GCREG_BLOCK4_ROP_TYPE_Type U02
+#define GCREG_BLOCK4_ROP_TYPE_ROP2_PATTERN 0x0
+#define GCREG_BLOCK4_ROP_TYPE_ROP2_SOURCE 0x1
+#define GCREG_BLOCK4_ROP_TYPE_ROP3 0x2
+#define GCREG_BLOCK4_ROP_TYPE_ROP4 0x3
+
+/* Background ROP code is used for transparent pixels. */
+#define GCREG_BLOCK4_ROP_ROP_BG 15 : 8
+#define GCREG_BLOCK4_ROP_ROP_BG_End 15
+#define GCREG_BLOCK4_ROP_ROP_BG_Start 8
+#define GCREG_BLOCK4_ROP_ROP_BG_Type U08
+
+/* Background ROP code is used for opaque pixels. */
+#define GCREG_BLOCK4_ROP_ROP_FG 7 : 0
+#define GCREG_BLOCK4_ROP_ROP_FG_End 7
+#define GCREG_BLOCK4_ROP_ROP_FG_Start 0
+#define GCREG_BLOCK4_ROP_ROP_FG_Type U08
+
+/*******************************************************************************
+** State gcregBlock4AlphaControl
+*/
+
+#define gcregBlock4AlphaControlRegAddrs 0x4A20
+#define GCREG_BLOCK4_ALPHA_CONTROL_MSB 15
+#define GCREG_BLOCK4_ALPHA_CONTROL_LSB 2
+#define GCREG_BLOCK4_ALPHA_CONTROL_BLK 0
+#define GCREG_BLOCK4_ALPHA_CONTROL_Count 4
+#define GCREG_BLOCK4_ALPHA_CONTROL_FieldMask 0x00000001
+#define GCREG_BLOCK4_ALPHA_CONTROL_ReadMask 0x00000001
+#define GCREG_BLOCK4_ALPHA_CONTROL_WriteMask 0x00000001
+#define GCREG_BLOCK4_ALPHA_CONTROL_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_ALPHA_CONTROL_ENABLE 0 : 0
+#define GCREG_BLOCK4_ALPHA_CONTROL_ENABLE_End 0
+#define GCREG_BLOCK4_ALPHA_CONTROL_ENABLE_Start 0
+#define GCREG_BLOCK4_ALPHA_CONTROL_ENABLE_Type U01
+#define GCREG_BLOCK4_ALPHA_CONTROL_ENABLE_OFF 0x0
+#define GCREG_BLOCK4_ALPHA_CONTROL_ENABLE_ON 0x1
+
+/*******************************************************************************
+** State gcregBlock4AlphaModes
+*/
+
+#define gcregBlock4AlphaModesRegAddrs 0x4A24
+#define GCREG_BLOCK4_ALPHA_MODES_MSB 15
+#define GCREG_BLOCK4_ALPHA_MODES_LSB 2
+#define GCREG_BLOCK4_ALPHA_MODES_BLK 0
+#define GCREG_BLOCK4_ALPHA_MODES_Count 4
+#define GCREG_BLOCK4_ALPHA_MODES_FieldMask 0xFF003311
+#define GCREG_BLOCK4_ALPHA_MODES_ReadMask 0xFF003311
+#define GCREG_BLOCK4_ALPHA_MODES_WriteMask 0xFF003311
+#define GCREG_BLOCK4_ALPHA_MODES_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE 0 : 0
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_End 0
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_Start 0
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_Type U01
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_NORMAL 0x0
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_MODE_INVERSED 0x1
+
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE 4 : 4
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_End 4
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_Start 4
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_Type U01
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_NORMAL 0x0
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_MODE_INVERSED 0x1
+
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE 9 : 8
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_End 9
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Start 8
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Type U02
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_NORMAL 0x0
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_GLOBAL 0x1
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_SCALED 0x2
+
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE 13 : 12
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_End 13
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Start 12
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Type U02
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_NORMAL 0x0
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_GLOBAL 0x1
+#define GCREG_BLOCK4_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_SCALED 0x2
+
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE 26 : 24
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_End 26
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_Start 24
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_Type U03
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_ZERO 0x0
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_ONE 0x1
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_NORMAL 0x2
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_INVERSED 0x3
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_COLOR 0x4
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_COLOR_INVERSED 0x5
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_ALPHA 0x6
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_DEST_ALPHA 0x7
+
+/* Src Blending factor is calculate from Src alpha. */
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR 27 : 27
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_End 27
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_Start 27
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_Type U01
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_DISABLED 0x0
+#define GCREG_BLOCK4_ALPHA_MODES_SRC_ALPHA_FACTOR_ENABLED 0x1
+
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE 30 : 28
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_End 30
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_Start 28
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_Type U03
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_ZERO 0x0
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_ONE 0x1
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_NORMAL 0x2
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_INVERSED 0x3
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_COLOR 0x4
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_COLOR_INVERSED 0x5
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_ALPHA 0x6
+#define GCREG_BLOCK4_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_DEST_ALPHA 0x7
+
+/* Dst Blending factor is calculate from Dst alpha. */
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR 31 : 31
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_End 31
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_Start 31
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_Type U01
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_DISABLED 0x0
+#define GCREG_BLOCK4_ALPHA_MODES_DST_ALPHA_FACTOR_ENABLED 0x1
+
+/*******************************************************************************
+** State gcregBlock4AddressU
+*/
+
+/* 32-bit aligned base address of the source U plane. */
+
+#define gcregBlock4UPlaneAddressRegAddrs 0x4A28
+#define GCREG_BLOCK4_UPLANE_ADDRESS_MSB 15
+#define GCREG_BLOCK4_UPLANE_ADDRESS_LSB 2
+#define GCREG_BLOCK4_UPLANE_ADDRESS_BLK 0
+#define GCREG_BLOCK4_UPLANE_ADDRESS_Count 4
+#define GCREG_BLOCK4_UPLANE_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_BLOCK4_UPLANE_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ADDRESS 31 : 0
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ADDRESS_End 30
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ADDRESS_Start 0
+#define GCREG_BLOCK4_UPLANE_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregBlock4StrideU
+*/
+
+/* Stride of the source U plane in bytes. */
+
+#define gcregBlock4UPlaneStrideRegAddrs 0x4A2C
+#define GCREG_BLOCK4_UPLANE_STRIDE_MSB 15
+#define GCREG_BLOCK4_UPLANE_STRIDE_LSB 2
+#define GCREG_BLOCK4_UPLANE_STRIDE_BLK 0
+#define GCREG_BLOCK4_UPLANE_STRIDE_Count 4
+#define GCREG_BLOCK4_UPLANE_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_BLOCK4_UPLANE_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_BLOCK4_UPLANE_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_BLOCK4_UPLANE_STRIDE_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_UPLANE_STRIDE_STRIDE 17 : 0
+#define GCREG_BLOCK4_UPLANE_STRIDE_STRIDE_End 17
+#define GCREG_BLOCK4_UPLANE_STRIDE_STRIDE_Start 0
+#define GCREG_BLOCK4_UPLANE_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State gcregBlock4AddressV
+*/
+
+/* 32-bit aligned base address of the source V plane. */
+
+#define gcregBlock4VPlaneAddressRegAddrs 0x4A30
+#define GCREG_BLOCK4_VPLANE_ADDRESS_MSB 15
+#define GCREG_BLOCK4_VPLANE_ADDRESS_LSB 2
+#define GCREG_BLOCK4_VPLANE_ADDRESS_BLK 0
+#define GCREG_BLOCK4_VPLANE_ADDRESS_Count 4
+#define GCREG_BLOCK4_VPLANE_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_BLOCK4_VPLANE_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ADDRESS 31 : 0
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ADDRESS_End 30
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ADDRESS_Start 0
+#define GCREG_BLOCK4_VPLANE_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregBlock4StrideV
+*/
+
+/* Stride of the source V plane in bytes. */
+
+#define gcregBlock4VPlaneStrideRegAddrs 0x4A34
+#define GCREG_BLOCK4_VPLANE_STRIDE_MSB 15
+#define GCREG_BLOCK4_VPLANE_STRIDE_LSB 2
+#define GCREG_BLOCK4_VPLANE_STRIDE_BLK 0
+#define GCREG_BLOCK4_VPLANE_STRIDE_Count 4
+#define GCREG_BLOCK4_VPLANE_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_BLOCK4_VPLANE_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_BLOCK4_VPLANE_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_BLOCK4_VPLANE_STRIDE_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_VPLANE_STRIDE_STRIDE 17 : 0
+#define GCREG_BLOCK4_VPLANE_STRIDE_STRIDE_End 17
+#define GCREG_BLOCK4_VPLANE_STRIDE_STRIDE_Start 0
+#define GCREG_BLOCK4_VPLANE_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State gcregBlock4SrcRotationHeight
+*/
+
+/* 180/270 degree rotation configuration for the Source surface. Height field
+** specifies the height of the surface in pixels.
+*/
+
+#define gcregBlock4SrcRotationHeightRegAddrs 0x4A38
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_MSB 15
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_LSB 2
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_BLK 0
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_Count 4
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_FieldMask 0x0000FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_ReadMask 0x0000FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_WriteMask 0x0000FFFF
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT 15 : 0
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT_End 15
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT_Start 0
+#define GCREG_BLOCK4_SRC_ROTATION_HEIGHT_HEIGHT_Type U16
+
+/*******************************************************************************
+** State gcregBlock4RotAngle
+*/
+
+/* 0/90/180/270 degree rotation configuration for the Source surface. Height
+** field specifies the height of the surface in pixels.
+*/
+
+#define gcregBlock4RotAngleRegAddrs 0x4A3C
+#define GCREG_BLOCK4_ROT_ANGLE_MSB 15
+#define GCREG_BLOCK4_ROT_ANGLE_LSB 2
+#define GCREG_BLOCK4_ROT_ANGLE_BLK 0
+#define GCREG_BLOCK4_ROT_ANGLE_Count 4
+#define GCREG_BLOCK4_ROT_ANGLE_FieldMask 0x000BB33F
+#define GCREG_BLOCK4_ROT_ANGLE_ReadMask 0x000BB33F
+#define GCREG_BLOCK4_ROT_ANGLE_WriteMask 0x000BB33F
+#define GCREG_BLOCK4_ROT_ANGLE_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_ROT_ANGLE_SRC 2 : 0
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_End 2
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_Start 0
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_Type U03
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_ROT0 0x0
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_FLIP_X 0x1
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_FLIP_Y 0x2
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_ROT90 0x4
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_ROT180 0x5
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_ROT270 0x6
+
+#define GCREG_BLOCK4_ROT_ANGLE_DST 5 : 3
+#define GCREG_BLOCK4_ROT_ANGLE_DST_End 5
+#define GCREG_BLOCK4_ROT_ANGLE_DST_Start 3
+#define GCREG_BLOCK4_ROT_ANGLE_DST_Type U03
+#define GCREG_BLOCK4_ROT_ANGLE_DST_ROT0 0x0
+#define GCREG_BLOCK4_ROT_ANGLE_DST_FLIP_X 0x1
+#define GCREG_BLOCK4_ROT_ANGLE_DST_FLIP_Y 0x2
+#define GCREG_BLOCK4_ROT_ANGLE_DST_ROT90 0x4
+#define GCREG_BLOCK4_ROT_ANGLE_DST_ROT180 0x5
+#define GCREG_BLOCK4_ROT_ANGLE_DST_ROT270 0x6
+
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC 8 : 8
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_End 8
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_Start 8
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_Type U01
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_ENABLED 0x0
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MASKED 0x1
+
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST 9 : 9
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_End 9
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_Start 9
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_Type U01
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_ENABLED 0x0
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MASKED 0x1
+
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR 13 : 12
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_End 13
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_Start 12
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_Type U02
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_NONE 0x0
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_MIRROR_X 0x1
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_MIRROR_Y 0x2
+#define GCREG_BLOCK4_ROT_ANGLE_SRC_MIRROR_MIRROR_XY 0x3
+
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR 15 : 15
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR_End 15
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR_Start 15
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR_Type U01
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR_ENABLED 0x0
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_SRC_MIRROR_MASKED 0x1
+
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR 17 : 16
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_End 17
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_Start 16
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_Type U02
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_NONE 0x0
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_MIRROR_X 0x1
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_MIRROR_Y 0x2
+#define GCREG_BLOCK4_ROT_ANGLE_DST_MIRROR_MIRROR_XY 0x3
+
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR 19 : 19
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR_End 19
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR_Start 19
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR_Type U01
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR_ENABLED 0x0
+#define GCREG_BLOCK4_ROT_ANGLE_MASK_DST_MIRROR_MASKED 0x1
+
+/*******************************************************************************
+** State gcregBlock4GlobalSrcColor
+*/
+
+/* Defines the global source color and alpha values. */
+
+#define gcregBlock4GlobalSrcColorRegAddrs 0x4A40
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_MSB 15
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_LSB 2
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_BLK 0
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_Count 4
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ALPHA 31 : 24
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ALPHA_End 31
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ALPHA_Start 24
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_ALPHA_Type U08
+
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_RED 23 : 16
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_RED_End 23
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_RED_Start 16
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_RED_Type U08
+
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_GREEN 15 : 8
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_GREEN_End 15
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_GREEN_Start 8
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_GREEN_Type U08
+
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_BLUE 7 : 0
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_BLUE_End 7
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_BLUE_Start 0
+#define GCREG_BLOCK4_GLOBAL_SRC_COLOR_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregBlock4GlobalDestColor
+*/
+
+/* Defines the global destination color and alpha values. */
+
+#define gcregBlock4GlobalDestColorRegAddrs 0x4A44
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_MSB 15
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_LSB 2
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_BLK 0
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_Count 4
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ALPHA 31 : 24
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ALPHA_End 31
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ALPHA_Start 24
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_ALPHA_Type U08
+
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_RED 23 : 16
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_RED_End 23
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_RED_Start 16
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_RED_Type U08
+
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_GREEN 15 : 8
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_GREEN_End 15
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_GREEN_Start 8
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_GREEN_Type U08
+
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_BLUE 7 : 0
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_BLUE_End 7
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_BLUE_Start 0
+#define GCREG_BLOCK4_GLOBAL_DEST_COLOR_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregBlock4ColorMultiplyModes
+*/
+
+/* Color modes to multiply Source or Destination pixel color by alpha
+** channel. Alpha can be from global color source or current pixel.
+*/
+
+#define gcregBlock4ColorMultiplyModesRegAddrs 0x4A48
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_MSB 15
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_LSB 2
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_BLK 0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_Count 4
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_FieldMask 0x00100311
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_ReadMask 0x00100311
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_WriteMask 0x00100311
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY 0 : 0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_End 0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Start 0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Type U01
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE 0x0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE 0x1
+
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY 4 : 4
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_End 4
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Start 4
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Type U01
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_DISABLE 0x0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_ENABLE 0x1
+
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY 9 : 8
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_End 9
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Start 8
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Type U02
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE 0x0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_ALPHA 0x1
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_COLOR 0x2
+
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY 20 : 20
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_End 20
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Start 20
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Type U01
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE 0x0
+#define GCREG_BLOCK4_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE 0x1
+
+/*******************************************************************************
+** State gcregBlock4Transparency
+*/
+
+#define gcregBlock4TransparencyRegAddrs 0x4A4C
+#define GCREG_BLOCK4_TRANSPARENCY_MSB 15
+#define GCREG_BLOCK4_TRANSPARENCY_LSB 2
+#define GCREG_BLOCK4_TRANSPARENCY_BLK 0
+#define GCREG_BLOCK4_TRANSPARENCY_Count 4
+#define GCREG_BLOCK4_TRANSPARENCY_FieldMask 0xB3331333
+#define GCREG_BLOCK4_TRANSPARENCY_ReadMask 0xB3331333
+#define GCREG_BLOCK4_TRANSPARENCY_WriteMask 0xB3331333
+#define GCREG_BLOCK4_TRANSPARENCY_ResetValue 0x00000000
+
+/* Source transparency mode. */
+#define GCREG_BLOCK4_TRANSPARENCY_SOURCE 1 : 0
+#define GCREG_BLOCK4_TRANSPARENCY_SOURCE_End 1
+#define GCREG_BLOCK4_TRANSPARENCY_SOURCE_Start 0
+#define GCREG_BLOCK4_TRANSPARENCY_SOURCE_Type U02
+#define GCREG_BLOCK4_TRANSPARENCY_SOURCE_OPAQUE 0x0
+#define GCREG_BLOCK4_TRANSPARENCY_SOURCE_MASK 0x1
+#define GCREG_BLOCK4_TRANSPARENCY_SOURCE_KEY 0x2
+
+/* Pattern transparency mode. KEY transparency mode is reserved. */
+#define GCREG_BLOCK4_TRANSPARENCY_PATTERN 5 : 4
+#define GCREG_BLOCK4_TRANSPARENCY_PATTERN_End 5
+#define GCREG_BLOCK4_TRANSPARENCY_PATTERN_Start 4
+#define GCREG_BLOCK4_TRANSPARENCY_PATTERN_Type U02
+#define GCREG_BLOCK4_TRANSPARENCY_PATTERN_OPAQUE 0x0
+#define GCREG_BLOCK4_TRANSPARENCY_PATTERN_MASK 0x1
+#define GCREG_BLOCK4_TRANSPARENCY_PATTERN_KEY 0x2
+
+/* Destination transparency mode. MASK transparency mode is reserved. */
+#define GCREG_BLOCK4_TRANSPARENCY_DESTINATION 9 : 8
+#define GCREG_BLOCK4_TRANSPARENCY_DESTINATION_End 9
+#define GCREG_BLOCK4_TRANSPARENCY_DESTINATION_Start 8
+#define GCREG_BLOCK4_TRANSPARENCY_DESTINATION_Type U02
+#define GCREG_BLOCK4_TRANSPARENCY_DESTINATION_OPAQUE 0x0
+#define GCREG_BLOCK4_TRANSPARENCY_DESTINATION_MASK 0x1
+#define GCREG_BLOCK4_TRANSPARENCY_DESTINATION_KEY 0x2
+
+/* Mask field for Source/Pattern/Destination fields. */
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY 12 : 12
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY_End 12
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY_Start 12
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY_Type U01
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY_ENABLED 0x0
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_TRANSPARENCY_MASKED 0x1
+
+/* Source usage override. */
+#define GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE 17 : 16
+#define GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_End 17
+#define GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_Start 16
+#define GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_Type U02
+#define GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_DEFAULT 0x0
+#define GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_USE_ENABLE 0x1
+#define GCREG_BLOCK4_TRANSPARENCY_USE_SRC_OVERRIDE_USE_DISABLE 0x2
+
+/* Pattern usage override. */
+#define GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE 21 : 20
+#define GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_End 21
+#define GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_Start 20
+#define GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_Type U02
+#define GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_DEFAULT 0x0
+#define GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_USE_ENABLE 0x1
+#define GCREG_BLOCK4_TRANSPARENCY_USE_PAT_OVERRIDE_USE_DISABLE 0x2
+
+/* Destination usage override. */
+#define GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE 25 : 24
+#define GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_End 25
+#define GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_Start 24
+#define GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_Type U02
+#define GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_DEFAULT 0x0
+#define GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_USE_ENABLE 0x1
+#define GCREG_BLOCK4_TRANSPARENCY_USE_DST_OVERRIDE_USE_DISABLE 0x2
+
+/* 2D resource usage override mask field. */
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE 28 : 28
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_End 28
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Start 28
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Type U01
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_ENABLED 0x0
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_MASKED 0x1
+
+/* DFB Color Key. */
+#define GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY 29 : 29
+#define GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_End 29
+#define GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_Start 29
+#define GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_Type U01
+#define GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_DISABLED 0x0
+#define GCREG_BLOCK4_TRANSPARENCY_DFB_COLOR_KEY_ENABLED 0x1
+
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY 31 : 31
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY_End 31
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY_Start 31
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY_Type U01
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY_ENABLED 0x0
+#define GCREG_BLOCK4_TRANSPARENCY_MASK_DFB_COLOR_KEY_MASKED 0x1
+
+/*******************************************************************************
+** State gcregBlock4Control
+*/
+
+/* General purpose control register. */
+
+#define gcregBlock4PEControlRegAddrs 0x4A50
+#define GCREG_BLOCK4_PE_CONTROL_MSB 15
+#define GCREG_BLOCK4_PE_CONTROL_LSB 2
+#define GCREG_BLOCK4_PE_CONTROL_BLK 0
+#define GCREG_BLOCK4_PE_CONTROL_Count 4
+#define GCREG_BLOCK4_PE_CONTROL_FieldMask 0x00000999
+#define GCREG_BLOCK4_PE_CONTROL_ReadMask 0x00000999
+#define GCREG_BLOCK4_PE_CONTROL_WriteMask 0x00000999
+#define GCREG_BLOCK4_PE_CONTROL_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_PE_CONTROL_YUV 0 : 0
+#define GCREG_BLOCK4_PE_CONTROL_YUV_End 0
+#define GCREG_BLOCK4_PE_CONTROL_YUV_Start 0
+#define GCREG_BLOCK4_PE_CONTROL_YUV_Type U01
+#define GCREG_BLOCK4_PE_CONTROL_YUV_601 0x0
+#define GCREG_BLOCK4_PE_CONTROL_YUV_709 0x1
+
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUV 3 : 3
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUV_End 3
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUV_Start 3
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUV_Type U01
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUV_ENABLED 0x0
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUV_MASKED 0x1
+
+#define GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE 4 : 4
+#define GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE_End 4
+#define GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE_Start 4
+#define GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE_Type U01
+#define GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE_UV 0x0
+#define GCREG_BLOCK4_PE_CONTROL_UV_SWIZZLE_VU 0x1
+
+#define GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE 7 : 7
+#define GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE_End 7
+#define GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE_Start 7
+#define GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE_Type U01
+#define GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE_ENABLED 0x0
+#define GCREG_BLOCK4_PE_CONTROL_MASK_UV_SWIZZLE_MASKED 0x1
+
+/* YUV to RGB convert enable */
+#define GCREG_BLOCK4_PE_CONTROL_YUVRGB 8 : 8
+#define GCREG_BLOCK4_PE_CONTROL_YUVRGB_End 8
+#define GCREG_BLOCK4_PE_CONTROL_YUVRGB_Start 8
+#define GCREG_BLOCK4_PE_CONTROL_YUVRGB_Type U01
+#define GCREG_BLOCK4_PE_CONTROL_YUVRGB_DISABLED 0x0
+#define GCREG_BLOCK4_PE_CONTROL_YUVRGB_ENABLED 0x1
+
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB 11 : 11
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB_End 11
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB_Start 11
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB_Type U01
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB_ENABLED 0x0
+#define GCREG_BLOCK4_PE_CONTROL_MASK_YUVRGB_MASKED 0x1
+
+/*******************************************************************************
+** State gcregBlock4SrcColorKeyHigh
+*/
+
+/* Defines the source transparency color in source format. */
+
+#define gcregBlock4SrcColorKeyHighRegAddrs 0x4A54
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_MSB 15
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_LSB 2
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_BLK 0
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_Count 4
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ALPHA 31 : 24
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ALPHA_End 31
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ALPHA_Start 24
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_ALPHA_Type U08
+
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_RED 23 : 16
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_RED_End 23
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_RED_Start 16
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_RED_Type U08
+
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_GREEN 15 : 8
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_GREEN_End 15
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_GREEN_Start 8
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_GREEN_Type U08
+
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_BLUE 7 : 0
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_BLUE_End 7
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_BLUE_Start 0
+#define GCREG_BLOCK4_SRC_COLOR_KEY_HIGH_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregBlock4SrcExConfig
+*/
+
+#define gcregBlock4SrcExConfigRegAddrs 0x4A58
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MSB 15
+#define GCREG_BLOCK4_SRC_EX_CONFIG_LSB 2
+#define GCREG_BLOCK4_SRC_EX_CONFIG_BLK 0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_Count 4
+#define GCREG_BLOCK4_SRC_EX_CONFIG_FieldMask 0x00000109
+#define GCREG_BLOCK4_SRC_EX_CONFIG_ReadMask 0x00000109
+#define GCREG_BLOCK4_SRC_EX_CONFIG_WriteMask 0x00000109
+#define GCREG_BLOCK4_SRC_EX_CONFIG_ResetValue 0x00000000
+
+/* Source multi tiled address computation control. */
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED 0 : 0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_End 0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_Start 0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_Type U01
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_DISABLED 0x0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MULTI_TILED_ENABLED 0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED 3 : 3
+#define GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_End 3
+#define GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_Start 3
+#define GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_Type U01
+#define GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_DISABLED 0x0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_SUPER_TILED_ENABLED 0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED 8 : 8
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_End 8
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_Start 8
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_Type U01
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_DISABLED 0x0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_MINOR_TILED_ENABLED 0x1
+
+/* Source CacheMode. */
+#define GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE 12 : 12
+#define GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE_End 12
+#define GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE_Start 12
+#define GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE_Type U01
+#define GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE_DISABLED 0x0
+#define GCREG_BLOCK4_SRC_EX_CONFIG_CACHE_MODE_ENABLED 0x1
+
+/*******************************************************************************
+** State gcregBlock4SrcExAddress
+*/
+
+/* 32-bit aligned base address of the source extra surface. */
+
+#define gcregBlock4SrcExAddressRegAddrs 0x4A5C
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_MSB 15
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_LSB 2
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_BLK 0
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_Count 4
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ADDRESS 31 : 0
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ADDRESS_End 30
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ADDRESS_Start 0
+#define GCREG_BLOCK4_SRC_EX_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregBlock8SrcAddressEx
+*/
+
+/* 32-bit aligned base address of the source surface. */
+
+#define gcregBlock8SrcAddressRegAddrs 0x4A80
+#define GCREG_BLOCK8_SRC_ADDRESS_MSB 15
+#define GCREG_BLOCK8_SRC_ADDRESS_LSB 3
+#define GCREG_BLOCK8_SRC_ADDRESS_BLK 0
+#define GCREG_BLOCK8_SRC_ADDRESS_Count 8
+#define GCREG_BLOCK8_SRC_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_BLOCK8_SRC_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_BLOCK8_SRC_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_SRC_ADDRESS_ADDRESS 31 : 0
+#define GCREG_BLOCK8_SRC_ADDRESS_ADDRESS_End 30
+#define GCREG_BLOCK8_SRC_ADDRESS_ADDRESS_Start 0
+#define GCREG_BLOCK8_SRC_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregBlock8SrcStride
+*/
+
+/* Stride of the source surface in bytes. To calculate the stride multiply
+** the surface width in pixels by the number of bytes per pixel.
+*/
+
+#define gcregBlock8SrcStrideRegAddrs 0x4A88
+#define GCREG_BLOCK8_SRC_STRIDE_MSB 15
+#define GCREG_BLOCK8_SRC_STRIDE_LSB 3
+#define GCREG_BLOCK8_SRC_STRIDE_BLK 0
+#define GCREG_BLOCK8_SRC_STRIDE_Count 8
+#define GCREG_BLOCK8_SRC_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_BLOCK8_SRC_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_BLOCK8_SRC_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_BLOCK8_SRC_STRIDE_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_SRC_STRIDE_STRIDE 17 : 0
+#define GCREG_BLOCK8_SRC_STRIDE_STRIDE_End 17
+#define GCREG_BLOCK8_SRC_STRIDE_STRIDE_Start 0
+#define GCREG_BLOCK8_SRC_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State gcregBlock8SrcRotationConfig
+*/
+
+/* 90 degree rotation configuration for the source surface. Width field
+** specifies the width of the surface in pixels.
+*/
+
+#define gcregBlock8SrcRotationConfigRegAddrs 0x4A90
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_MSB 15
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_LSB 3
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_BLK 0
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_Count 8
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_FieldMask 0x0001FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ReadMask 0x0001FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_WriteMask 0x0001FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_WIDTH 15 : 0
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_WIDTH_End 15
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_WIDTH_Start 0
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_WIDTH_Type U16
+
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION 16 : 16
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_End 16
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_Start 16
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_Type U01
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_NORMAL 0x0
+#define GCREG_BLOCK8_SRC_ROTATION_CONFIG_ROTATION_ROTATED 0x1
+
+/*******************************************************************************
+** State gcregBlock8SrcConfig
+*/
+
+/* Source surface configuration register. */
+
+#define gcregBlock8SrcConfigRegAddrs 0x4A98
+#define GCREG_BLOCK8_SRC_CONFIG_MSB 15
+#define GCREG_BLOCK8_SRC_CONFIG_LSB 3
+#define GCREG_BLOCK8_SRC_CONFIG_BLK 0
+#define GCREG_BLOCK8_SRC_CONFIG_Count 8
+#define GCREG_BLOCK8_SRC_CONFIG_FieldMask 0xDF30B1C0
+#define GCREG_BLOCK8_SRC_CONFIG_ReadMask 0xDF30B1C0
+#define GCREG_BLOCK8_SRC_CONFIG_WriteMask 0xDF30B1C0
+#define GCREG_BLOCK8_SRC_CONFIG_ResetValue 0x00000000
+
+/* Control source endianess. */
+#define GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL 31 : 30
+#define GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_End 31
+#define GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_Start 30
+#define GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_Type U02
+#define GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_NO_SWAP 0x0
+#define GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_SWAP_WORD 0x1
+#define GCREG_BLOCK8_SRC_CONFIG_ENDIAN_CONTROL_SWAP_DWORD 0x2
+
+/* Defines the pixel format of the source surface. */
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT 28 : 24
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_End 28
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_Start 24
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_Type U05
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_X4R4G4B4 0x00
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_A4R4G4B4 0x01
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_X1R5G5B5 0x02
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_A1R5G5B5 0x03
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_R5G6B5 0x04
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_X8R8G8B8 0x05
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_A8R8G8B8 0x06
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_YUY2 0x07
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_UYVY 0x08
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_INDEX8 0x09
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_MONOCHROME 0x0A
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_YV12 0x0F
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_A8 0x10
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_NV12 0x11
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_NV16 0x12
+#define GCREG_BLOCK8_SRC_CONFIG_SOURCE_FORMAT_RG16 0x13
+
+/* Color channel swizzles. */
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE 21 : 20
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_End 21
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_Start 20
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_Type U02
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_ARGB 0x0
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_RGBA 0x1
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_ABGR 0x2
+#define GCREG_BLOCK8_SRC_CONFIG_SWIZZLE_BGRA 0x3
+
+/* Mono expansion: if 0, transparency color will be 0, otherwise transparency **
+** color will be 1. */
+#define GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY 15 : 15
+#define GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_End 15
+#define GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_Start 15
+#define GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_Type U01
+#define GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_BACKGROUND 0x0
+#define GCREG_BLOCK8_SRC_CONFIG_MONO_TRANSPARENCY_FOREGROUND 0x1
+
+/* Mono expansion or masked blit: stream packing in pixels. Determines how **
+** many horizontal pixels are there per each 32-bit chunk. For example, if **
+** set to Packed8, each 32-bit chunk is 8-pixel wide, which also means that **
+** it defines 4 vertical lines of pixels. */
+#define GCREG_BLOCK8_SRC_CONFIG_PACK 13 : 12
+#define GCREG_BLOCK8_SRC_CONFIG_PACK_End 13
+#define GCREG_BLOCK8_SRC_CONFIG_PACK_Start 12
+#define GCREG_BLOCK8_SRC_CONFIG_PACK_Type U02
+#define GCREG_BLOCK8_SRC_CONFIG_PACK_PACKED8 0x0
+#define GCREG_BLOCK8_SRC_CONFIG_PACK_PACKED16 0x1
+#define GCREG_BLOCK8_SRC_CONFIG_PACK_PACKED32 0x2
+#define GCREG_BLOCK8_SRC_CONFIG_PACK_UNPACKED 0x3
+
+/* Source data location: set to STREAM for mono expansion blits or masked **
+** blits. For mono expansion blits the complete bitmap comes from the command **
+** stream. For masked blits the source data comes from the memory and the **
+** mask from the command stream. */
+#define GCREG_BLOCK8_SRC_CONFIG_LOCATION 8 : 8
+#define GCREG_BLOCK8_SRC_CONFIG_LOCATION_End 8
+#define GCREG_BLOCK8_SRC_CONFIG_LOCATION_Start 8
+#define GCREG_BLOCK8_SRC_CONFIG_LOCATION_Type U01
+#define GCREG_BLOCK8_SRC_CONFIG_LOCATION_MEMORY 0x0
+#define GCREG_BLOCK8_SRC_CONFIG_LOCATION_STREAM 0x1
+
+/* Source linear/tiled address computation control. */
+#define GCREG_BLOCK8_SRC_CONFIG_TILED 7 : 7
+#define GCREG_BLOCK8_SRC_CONFIG_TILED_End 7
+#define GCREG_BLOCK8_SRC_CONFIG_TILED_Start 7
+#define GCREG_BLOCK8_SRC_CONFIG_TILED_Type U01
+#define GCREG_BLOCK8_SRC_CONFIG_TILED_DISABLED 0x0
+#define GCREG_BLOCK8_SRC_CONFIG_TILED_ENABLED 0x1
+
+/* If set to ABSOLUTE, the source coordinates are treated as absolute **
+** coordinates inside the source surface. If set to RELATIVE, the source **
+** coordinates are treated as the offsets from the destination coordinates **
+** with the source size equal to the size of the destination. */
+#define GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE 6 : 6
+#define GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE_End 6
+#define GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE_Start 6
+#define GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE_Type U01
+#define GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE_ABSOLUTE 0x0
+#define GCREG_BLOCK8_SRC_CONFIG_SRC_RELATIVE_RELATIVE 0x1
+
+/*******************************************************************************
+** State gcregBlock8SrcOrigin
+*/
+
+/* Absolute or relative (see SRC_RELATIVE field of gcregBlock8SrcConfig
+** register) X and Y coordinates in pixels of the top left corner of the
+** source rectangle within the source surface.
+*/
+
+#define gcregBlock8SrcOriginRegAddrs 0x4AA0
+#define GCREG_BLOCK8_SRC_ORIGIN_MSB 15
+#define GCREG_BLOCK8_SRC_ORIGIN_LSB 3
+#define GCREG_BLOCK8_SRC_ORIGIN_BLK 0
+#define GCREG_BLOCK8_SRC_ORIGIN_Count 8
+#define GCREG_BLOCK8_SRC_ORIGIN_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_ORIGIN_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_ORIGIN_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_ORIGIN_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_SRC_ORIGIN_Y 31 : 16
+#define GCREG_BLOCK8_SRC_ORIGIN_Y_End 31
+#define GCREG_BLOCK8_SRC_ORIGIN_Y_Start 16
+#define GCREG_BLOCK8_SRC_ORIGIN_Y_Type U16
+
+#define GCREG_BLOCK8_SRC_ORIGIN_X 15 : 0
+#define GCREG_BLOCK8_SRC_ORIGIN_X_End 15
+#define GCREG_BLOCK8_SRC_ORIGIN_X_Start 0
+#define GCREG_BLOCK8_SRC_ORIGIN_X_Type U16
+
+/*******************************************************************************
+** State gcregBlock8SrcSize
+*/
+
+/* Width and height of the source rectangle in pixels. If the source is
+** relative (see SRC_RELATIVE field of gcregBlock8SrcConfig register) or a
+** regular bitblt is being performed without stretching, this register is
+** ignored and the source size is assumed to be the same as the destination.
+*/
+
+#define gcregBlock8SrcSizeRegAddrs 0x4AA8
+#define GCREG_BLOCK8_SRC_SIZE_MSB 15
+#define GCREG_BLOCK8_SRC_SIZE_LSB 3
+#define GCREG_BLOCK8_SRC_SIZE_BLK 0
+#define GCREG_BLOCK8_SRC_SIZE_Count 8
+#define GCREG_BLOCK8_SRC_SIZE_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_SIZE_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_SIZE_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_SIZE_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_SRC_SIZE_Y 31 : 16
+#define GCREG_BLOCK8_SRC_SIZE_Y_End 31
+#define GCREG_BLOCK8_SRC_SIZE_Y_Start 16
+#define GCREG_BLOCK8_SRC_SIZE_Y_Type U16
+
+#define GCREG_BLOCK8_SRC_SIZE_X 15 : 0
+#define GCREG_BLOCK8_SRC_SIZE_X_End 15
+#define GCREG_BLOCK8_SRC_SIZE_X_Start 0
+#define GCREG_BLOCK8_SRC_SIZE_X_Type U16
+
+/*******************************************************************************
+** State gcregBlock8SrcColorBg
+*/
+
+/* Select the color where source becomes transparent. It must be programmed
+** in A8R8G8B8 format.
+*/
+
+#define gcregBlock8SrcColorBgRegAddrs 0x4AB0
+#define GCREG_BLOCK8_SRC_COLOR_BG_MSB 15
+#define GCREG_BLOCK8_SRC_COLOR_BG_LSB 3
+#define GCREG_BLOCK8_SRC_COLOR_BG_BLK 0
+#define GCREG_BLOCK8_SRC_COLOR_BG_Count 8
+#define GCREG_BLOCK8_SRC_COLOR_BG_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_BG_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_BG_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_BG_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_SRC_COLOR_BG_ALPHA 31 : 24
+#define GCREG_BLOCK8_SRC_COLOR_BG_ALPHA_End 31
+#define GCREG_BLOCK8_SRC_COLOR_BG_ALPHA_Start 24
+#define GCREG_BLOCK8_SRC_COLOR_BG_ALPHA_Type U08
+
+#define GCREG_BLOCK8_SRC_COLOR_BG_RED 23 : 16
+#define GCREG_BLOCK8_SRC_COLOR_BG_RED_End 23
+#define GCREG_BLOCK8_SRC_COLOR_BG_RED_Start 16
+#define GCREG_BLOCK8_SRC_COLOR_BG_RED_Type U08
+
+#define GCREG_BLOCK8_SRC_COLOR_BG_GREEN 15 : 8
+#define GCREG_BLOCK8_SRC_COLOR_BG_GREEN_End 15
+#define GCREG_BLOCK8_SRC_COLOR_BG_GREEN_Start 8
+#define GCREG_BLOCK8_SRC_COLOR_BG_GREEN_Type U08
+
+#define GCREG_BLOCK8_SRC_COLOR_BG_BLUE 7 : 0
+#define GCREG_BLOCK8_SRC_COLOR_BG_BLUE_End 7
+#define GCREG_BLOCK8_SRC_COLOR_BG_BLUE_Start 0
+#define GCREG_BLOCK8_SRC_COLOR_BG_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregBlock8Rop
+*/
+
+/* Raster operation foreground and background codes. Even though ROP is not
+** used in CLEAR, HOR_FILTER_BLT, VER_FILTER_BLT and alpha-eanbled BIT_BLTs,
+** ROP code still has to be programmed, because the engine makes the decision
+** whether source, destination and pattern are involved in the current
+** operation and the correct decision is essential for the engine to complete
+** the operation as expected.
+*/
+
+#define gcregBlock8RopRegAddrs 0x4AB8
+#define GCREG_BLOCK8_ROP_MSB 15
+#define GCREG_BLOCK8_ROP_LSB 3
+#define GCREG_BLOCK8_ROP_BLK 0
+#define GCREG_BLOCK8_ROP_Count 8
+#define GCREG_BLOCK8_ROP_FieldMask 0x0030FFFF
+#define GCREG_BLOCK8_ROP_ReadMask 0x0030FFFF
+#define GCREG_BLOCK8_ROP_WriteMask 0x0030FFFF
+#define GCREG_BLOCK8_ROP_ResetValue 0x00000000
+
+/* ROP type: ROP2, ROP3 or ROP4 */
+#define GCREG_BLOCK8_ROP_TYPE 21 : 20
+#define GCREG_BLOCK8_ROP_TYPE_End 21
+#define GCREG_BLOCK8_ROP_TYPE_Start 20
+#define GCREG_BLOCK8_ROP_TYPE_Type U02
+#define GCREG_BLOCK8_ROP_TYPE_ROP2_PATTERN 0x0
+#define GCREG_BLOCK8_ROP_TYPE_ROP2_SOURCE 0x1
+#define GCREG_BLOCK8_ROP_TYPE_ROP3 0x2
+#define GCREG_BLOCK8_ROP_TYPE_ROP4 0x3
+
+/* Background ROP code is used for transparent pixels. */
+#define GCREG_BLOCK8_ROP_ROP_BG 15 : 8
+#define GCREG_BLOCK8_ROP_ROP_BG_End 15
+#define GCREG_BLOCK8_ROP_ROP_BG_Start 8
+#define GCREG_BLOCK8_ROP_ROP_BG_Type U08
+
+/* Background ROP code is used for opaque pixels. */
+#define GCREG_BLOCK8_ROP_ROP_FG 7 : 0
+#define GCREG_BLOCK8_ROP_ROP_FG_End 7
+#define GCREG_BLOCK8_ROP_ROP_FG_Start 0
+#define GCREG_BLOCK8_ROP_ROP_FG_Type U08
+
+/*******************************************************************************
+** State gcregBlock8AlphaControl
+*/
+
+#define gcregBlock8AlphaControlRegAddrs 0x4AC0
+#define GCREG_BLOCK8_ALPHA_CONTROL_MSB 15
+#define GCREG_BLOCK8_ALPHA_CONTROL_LSB 3
+#define GCREG_BLOCK8_ALPHA_CONTROL_BLK 0
+#define GCREG_BLOCK8_ALPHA_CONTROL_Count 8
+#define GCREG_BLOCK8_ALPHA_CONTROL_FieldMask 0x00000001
+#define GCREG_BLOCK8_ALPHA_CONTROL_ReadMask 0x00000001
+#define GCREG_BLOCK8_ALPHA_CONTROL_WriteMask 0x00000001
+#define GCREG_BLOCK8_ALPHA_CONTROL_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_ALPHA_CONTROL_ENABLE 0 : 0
+#define GCREG_BLOCK8_ALPHA_CONTROL_ENABLE_End 0
+#define GCREG_BLOCK8_ALPHA_CONTROL_ENABLE_Start 0
+#define GCREG_BLOCK8_ALPHA_CONTROL_ENABLE_Type U01
+#define GCREG_BLOCK8_ALPHA_CONTROL_ENABLE_OFF 0x0
+#define GCREG_BLOCK8_ALPHA_CONTROL_ENABLE_ON 0x1
+
+/*******************************************************************************
+** State gcregBlock8AlphaModes
+*/
+
+#define gcregBlock8AlphaModesRegAddrs 0x4AC8
+#define GCREG_BLOCK8_ALPHA_MODES_MSB 15
+#define GCREG_BLOCK8_ALPHA_MODES_LSB 3
+#define GCREG_BLOCK8_ALPHA_MODES_BLK 0
+#define GCREG_BLOCK8_ALPHA_MODES_Count 8
+#define GCREG_BLOCK8_ALPHA_MODES_FieldMask 0xFF003311
+#define GCREG_BLOCK8_ALPHA_MODES_ReadMask 0xFF003311
+#define GCREG_BLOCK8_ALPHA_MODES_WriteMask 0xFF003311
+#define GCREG_BLOCK8_ALPHA_MODES_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE 0 : 0
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_End 0
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_Start 0
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_Type U01
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_NORMAL 0x0
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_MODE_INVERSED 0x1
+
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE 4 : 4
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_End 4
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_Start 4
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_Type U01
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_NORMAL 0x0
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_MODE_INVERSED 0x1
+
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE 9 : 8
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_End 9
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Start 8
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_Type U02
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_NORMAL 0x0
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_GLOBAL 0x1
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_SRC_ALPHA_MODE_SCALED 0x2
+
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE 13 : 12
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_End 13
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Start 12
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_Type U02
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_NORMAL 0x0
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_GLOBAL 0x1
+#define GCREG_BLOCK8_ALPHA_MODES_GLOBAL_DST_ALPHA_MODE_SCALED 0x2
+
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE 26 : 24
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_End 26
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_Start 24
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_Type U03
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_ZERO 0x0
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_ONE 0x1
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_NORMAL 0x2
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_INVERSED 0x3
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_COLOR 0x4
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_COLOR_INVERSED 0x5
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_ALPHA 0x6
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_BLENDING_MODE_SATURATED_DEST_ALPHA 0x7
+
+/* Src Blending factor is calculate from Src alpha. */
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR 27 : 27
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_End 27
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_Start 27
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_Type U01
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_DISABLED 0x0
+#define GCREG_BLOCK8_ALPHA_MODES_SRC_ALPHA_FACTOR_ENABLED 0x1
+
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE 30 : 28
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_End 30
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_Start 28
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_Type U03
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_ZERO 0x0
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_ONE 0x1
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_NORMAL 0x2
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_INVERSED 0x3
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_COLOR 0x4
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_COLOR_INVERSED 0x5
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_ALPHA 0x6
+#define GCREG_BLOCK8_ALPHA_MODES_DST_BLENDING_MODE_SATURATED_DEST_ALPHA 0x7
+
+/* Dst Blending factor is calculate from Dst alpha. */
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR 31 : 31
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_End 31
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_Start 31
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_Type U01
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_DISABLED 0x0
+#define GCREG_BLOCK8_ALPHA_MODES_DST_ALPHA_FACTOR_ENABLED 0x1
+
+/*******************************************************************************
+** State gcregBlock8AddressU
+*/
+
+/* 32-bit aligned base address of the source U plane. */
+
+#define gcregBlock8UPlaneAddressRegAddrs 0x4AD0
+#define GCREG_BLOCK8_UPLANE_ADDRESS_MSB 15
+#define GCREG_BLOCK8_UPLANE_ADDRESS_LSB 3
+#define GCREG_BLOCK8_UPLANE_ADDRESS_BLK 0
+#define GCREG_BLOCK8_UPLANE_ADDRESS_Count 8
+#define GCREG_BLOCK8_UPLANE_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_BLOCK8_UPLANE_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ADDRESS 31 : 0
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ADDRESS_End 30
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ADDRESS_Start 0
+#define GCREG_BLOCK8_UPLANE_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregBlock8StrideU
+*/
+
+/* Stride of the source U plane in bytes. */
+
+#define gcregBlock8UPlaneStrideRegAddrs 0x4AD8
+#define GCREG_BLOCK8_UPLANE_STRIDE_MSB 15
+#define GCREG_BLOCK8_UPLANE_STRIDE_LSB 3
+#define GCREG_BLOCK8_UPLANE_STRIDE_BLK 0
+#define GCREG_BLOCK8_UPLANE_STRIDE_Count 8
+#define GCREG_BLOCK8_UPLANE_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_BLOCK8_UPLANE_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_BLOCK8_UPLANE_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_BLOCK8_UPLANE_STRIDE_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_UPLANE_STRIDE_STRIDE 17 : 0
+#define GCREG_BLOCK8_UPLANE_STRIDE_STRIDE_End 17
+#define GCREG_BLOCK8_UPLANE_STRIDE_STRIDE_Start 0
+#define GCREG_BLOCK8_UPLANE_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State gcregBlock8AddressV
+*/
+
+/* 32-bit aligned base address of the source V plane. */
+
+#define gcregBlock8VPlaneAddressRegAddrs 0x4AE0
+#define GCREG_BLOCK8_VPLANE_ADDRESS_MSB 15
+#define GCREG_BLOCK8_VPLANE_ADDRESS_LSB 3
+#define GCREG_BLOCK8_VPLANE_ADDRESS_BLK 0
+#define GCREG_BLOCK8_VPLANE_ADDRESS_Count 8
+#define GCREG_BLOCK8_VPLANE_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_BLOCK8_VPLANE_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ADDRESS 31 : 0
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ADDRESS_End 30
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ADDRESS_Start 0
+#define GCREG_BLOCK8_VPLANE_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** State gcregBlock8StrideV
+*/
+
+/* Stride of the source V plane in bytes. */
+
+#define gcregBlock8VPlaneStrideRegAddrs 0x4AE8
+#define GCREG_BLOCK8_VPLANE_STRIDE_MSB 15
+#define GCREG_BLOCK8_VPLANE_STRIDE_LSB 3
+#define GCREG_BLOCK8_VPLANE_STRIDE_BLK 0
+#define GCREG_BLOCK8_VPLANE_STRIDE_Count 8
+#define GCREG_BLOCK8_VPLANE_STRIDE_FieldMask 0x0003FFFF
+#define GCREG_BLOCK8_VPLANE_STRIDE_ReadMask 0x0003FFFC
+#define GCREG_BLOCK8_VPLANE_STRIDE_WriteMask 0x0003FFFC
+#define GCREG_BLOCK8_VPLANE_STRIDE_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_VPLANE_STRIDE_STRIDE 17 : 0
+#define GCREG_BLOCK8_VPLANE_STRIDE_STRIDE_End 17
+#define GCREG_BLOCK8_VPLANE_STRIDE_STRIDE_Start 0
+#define GCREG_BLOCK8_VPLANE_STRIDE_STRIDE_Type U18
+
+/*******************************************************************************
+** State gcregBlock8SrcRotationHeight
+*/
+
+/* 180/270 degree rotation configuration for the Source surface. Height field
+** specifies the height of the surface in pixels.
+*/
+
+#define gcregBlock8SrcRotationHeightRegAddrs 0x4AF0
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_MSB 15
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_LSB 3
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_BLK 0
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_Count 8
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_FieldMask 0x0000FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_ReadMask 0x0000FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_WriteMask 0x0000FFFF
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT 15 : 0
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT_End 15
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT_Start 0
+#define GCREG_BLOCK8_SRC_ROTATION_HEIGHT_HEIGHT_Type U16
+
+/*******************************************************************************
+** State gcregBlock8RotAngle
+*/
+
+/* 0/90/180/270 degree rotation configuration for the Source surface. Height
+** field specifies the height of the surface in pixels.
+*/
+
+#define gcregBlock8RotAngleRegAddrs 0x4AF8
+#define GCREG_BLOCK8_ROT_ANGLE_MSB 15
+#define GCREG_BLOCK8_ROT_ANGLE_LSB 3
+#define GCREG_BLOCK8_ROT_ANGLE_BLK 0
+#define GCREG_BLOCK8_ROT_ANGLE_Count 8
+#define GCREG_BLOCK8_ROT_ANGLE_FieldMask 0x000BB33F
+#define GCREG_BLOCK8_ROT_ANGLE_ReadMask 0x000BB33F
+#define GCREG_BLOCK8_ROT_ANGLE_WriteMask 0x000BB33F
+#define GCREG_BLOCK8_ROT_ANGLE_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_ROT_ANGLE_SRC 2 : 0
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_End 2
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_Start 0
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_Type U03
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_ROT0 0x0
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_FLIP_X 0x1
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_FLIP_Y 0x2
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_ROT90 0x4
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_ROT180 0x5
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_ROT270 0x6
+
+#define GCREG_BLOCK8_ROT_ANGLE_DST 5 : 3
+#define GCREG_BLOCK8_ROT_ANGLE_DST_End 5
+#define GCREG_BLOCK8_ROT_ANGLE_DST_Start 3
+#define GCREG_BLOCK8_ROT_ANGLE_DST_Type U03
+#define GCREG_BLOCK8_ROT_ANGLE_DST_ROT0 0x0
+#define GCREG_BLOCK8_ROT_ANGLE_DST_FLIP_X 0x1
+#define GCREG_BLOCK8_ROT_ANGLE_DST_FLIP_Y 0x2
+#define GCREG_BLOCK8_ROT_ANGLE_DST_ROT90 0x4
+#define GCREG_BLOCK8_ROT_ANGLE_DST_ROT180 0x5
+#define GCREG_BLOCK8_ROT_ANGLE_DST_ROT270 0x6
+
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC 8 : 8
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_End 8
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_Start 8
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_Type U01
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_ENABLED 0x0
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MASKED 0x1
+
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST 9 : 9
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_End 9
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_Start 9
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_Type U01
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_ENABLED 0x0
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MASKED 0x1
+
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR 13 : 12
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_End 13
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_Start 12
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_Type U02
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_NONE 0x0
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_MIRROR_X 0x1
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_MIRROR_Y 0x2
+#define GCREG_BLOCK8_ROT_ANGLE_SRC_MIRROR_MIRROR_XY 0x3
+
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR 15 : 15
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR_End 15
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR_Start 15
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR_Type U01
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR_ENABLED 0x0
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_SRC_MIRROR_MASKED 0x1
+
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR 17 : 16
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_End 17
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_Start 16
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_Type U02
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_NONE 0x0
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_MIRROR_X 0x1
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_MIRROR_Y 0x2
+#define GCREG_BLOCK8_ROT_ANGLE_DST_MIRROR_MIRROR_XY 0x3
+
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR 19 : 19
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR_End 19
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR_Start 19
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR_Type U01
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR_ENABLED 0x0
+#define GCREG_BLOCK8_ROT_ANGLE_MASK_DST_MIRROR_MASKED 0x1
+
+/*******************************************************************************
+** State gcregBlock8GlobalSrcColor
+*/
+
+/* Defines the global source color and alpha values. */
+
+#define gcregBlock8GlobalSrcColorRegAddrs 0x4B00
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_MSB 15
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_LSB 3
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_BLK 0
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_Count 8
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ALPHA 31 : 24
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ALPHA_End 31
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ALPHA_Start 24
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_ALPHA_Type U08
+
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_RED 23 : 16
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_RED_End 23
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_RED_Start 16
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_RED_Type U08
+
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_GREEN 15 : 8
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_GREEN_End 15
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_GREEN_Start 8
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_GREEN_Type U08
+
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_BLUE 7 : 0
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_BLUE_End 7
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_BLUE_Start 0
+#define GCREG_BLOCK8_GLOBAL_SRC_COLOR_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregBlock8GlobalDestColor
+*/
+
+/* Defines the global destination color and alpha values. */
+
+#define gcregBlock8GlobalDestColorRegAddrs 0x4B08
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_MSB 15
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_LSB 3
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_BLK 0
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_Count 8
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ALPHA 31 : 24
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ALPHA_End 31
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ALPHA_Start 24
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_ALPHA_Type U08
+
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_RED 23 : 16
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_RED_End 23
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_RED_Start 16
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_RED_Type U08
+
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_GREEN 15 : 8
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_GREEN_End 15
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_GREEN_Start 8
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_GREEN_Type U08
+
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_BLUE 7 : 0
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_BLUE_End 7
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_BLUE_Start 0
+#define GCREG_BLOCK8_GLOBAL_DEST_COLOR_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregBlock8ColorMultiplyModes
+*/
+
+/* Color modes to multiply Source or Destination pixel color by alpha
+** channel. Alpha can be from global color source or current pixel.
+*/
+
+#define gcregBlock8ColorMultiplyModesRegAddrs 0x4B10
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_MSB 15
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_LSB 3
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_BLK 0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_Count 8
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_FieldMask 0x00100311
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_ReadMask 0x00100311
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_WriteMask 0x00100311
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY 0 : 0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_End 0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Start 0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_Type U01
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_DISABLE 0x0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_PREMULTIPLY_ENABLE 0x1
+
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY 4 : 4
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_End 4
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Start 4
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_Type U01
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_DISABLE 0x0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_PREMULTIPLY_ENABLE 0x1
+
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY 9 : 8
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_End 9
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Start 8
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_Type U02
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_DISABLE 0x0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_ALPHA 0x1
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_SRC_GLOBAL_PREMULTIPLY_COLOR 0x2
+
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY 20 : 20
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_End 20
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Start 20
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_Type U01
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_DISABLE 0x0
+#define GCREG_BLOCK8_COLOR_MULTIPLY_MODES_DST_DEMULTIPLY_ENABLE 0x1
+
+/*******************************************************************************
+** State gcregBlock8Transparency
+*/
+
+#define gcregBlock8TransparencyRegAddrs 0x4B18
+#define GCREG_BLOCK8_TRANSPARENCY_MSB 15
+#define GCREG_BLOCK8_TRANSPARENCY_LSB 3
+#define GCREG_BLOCK8_TRANSPARENCY_BLK 0
+#define GCREG_BLOCK8_TRANSPARENCY_Count 8
+#define GCREG_BLOCK8_TRANSPARENCY_FieldMask 0xB3331333
+#define GCREG_BLOCK8_TRANSPARENCY_ReadMask 0xB3331333
+#define GCREG_BLOCK8_TRANSPARENCY_WriteMask 0xB3331333
+#define GCREG_BLOCK8_TRANSPARENCY_ResetValue 0x00000000
+
+/* Source transparency mode. */
+#define GCREG_BLOCK8_TRANSPARENCY_SOURCE 1 : 0
+#define GCREG_BLOCK8_TRANSPARENCY_SOURCE_End 1
+#define GCREG_BLOCK8_TRANSPARENCY_SOURCE_Start 0
+#define GCREG_BLOCK8_TRANSPARENCY_SOURCE_Type U02
+#define GCREG_BLOCK8_TRANSPARENCY_SOURCE_OPAQUE 0x0
+#define GCREG_BLOCK8_TRANSPARENCY_SOURCE_MASK 0x1
+#define GCREG_BLOCK8_TRANSPARENCY_SOURCE_KEY 0x2
+
+/* Pattern transparency mode. KEY transparency mode is reserved. */
+#define GCREG_BLOCK8_TRANSPARENCY_PATTERN 5 : 4
+#define GCREG_BLOCK8_TRANSPARENCY_PATTERN_End 5
+#define GCREG_BLOCK8_TRANSPARENCY_PATTERN_Start 4
+#define GCREG_BLOCK8_TRANSPARENCY_PATTERN_Type U02
+#define GCREG_BLOCK8_TRANSPARENCY_PATTERN_OPAQUE 0x0
+#define GCREG_BLOCK8_TRANSPARENCY_PATTERN_MASK 0x1
+#define GCREG_BLOCK8_TRANSPARENCY_PATTERN_KEY 0x2
+
+/* Destination transparency mode. MASK transparency mode is reserved. */
+#define GCREG_BLOCK8_TRANSPARENCY_DESTINATION 9 : 8
+#define GCREG_BLOCK8_TRANSPARENCY_DESTINATION_End 9
+#define GCREG_BLOCK8_TRANSPARENCY_DESTINATION_Start 8
+#define GCREG_BLOCK8_TRANSPARENCY_DESTINATION_Type U02
+#define GCREG_BLOCK8_TRANSPARENCY_DESTINATION_OPAQUE 0x0
+#define GCREG_BLOCK8_TRANSPARENCY_DESTINATION_MASK 0x1
+#define GCREG_BLOCK8_TRANSPARENCY_DESTINATION_KEY 0x2
+
+/* Mask field for Source/Pattern/Destination fields. */
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY 12 : 12
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY_End 12
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY_Start 12
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY_Type U01
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY_ENABLED 0x0
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_TRANSPARENCY_MASKED 0x1
+
+/* Source usage override. */
+#define GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE 17 : 16
+#define GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_End 17
+#define GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_Start 16
+#define GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_Type U02
+#define GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_DEFAULT 0x0
+#define GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_USE_ENABLE 0x1
+#define GCREG_BLOCK8_TRANSPARENCY_USE_SRC_OVERRIDE_USE_DISABLE 0x2
+
+/* Pattern usage override. */
+#define GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE 21 : 20
+#define GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_End 21
+#define GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_Start 20
+#define GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_Type U02
+#define GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_DEFAULT 0x0
+#define GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_USE_ENABLE 0x1
+#define GCREG_BLOCK8_TRANSPARENCY_USE_PAT_OVERRIDE_USE_DISABLE 0x2
+
+/* Destination usage override. */
+#define GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE 25 : 24
+#define GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_End 25
+#define GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_Start 24
+#define GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_Type U02
+#define GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_DEFAULT 0x0
+#define GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_USE_ENABLE 0x1
+#define GCREG_BLOCK8_TRANSPARENCY_USE_DST_OVERRIDE_USE_DISABLE 0x2
+
+/* 2D resource usage override mask field. */
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE 28 : 28
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_End 28
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Start 28
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_Type U01
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_ENABLED 0x0
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_RESOURCE_OVERRIDE_MASKED 0x1
+
+/* DFB Color Key. */
+#define GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY 29 : 29
+#define GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_End 29
+#define GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_Start 29
+#define GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_Type U01
+#define GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_DISABLED 0x0
+#define GCREG_BLOCK8_TRANSPARENCY_DFB_COLOR_KEY_ENABLED 0x1
+
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY 31 : 31
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY_End 31
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY_Start 31
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY_Type U01
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY_ENABLED 0x0
+#define GCREG_BLOCK8_TRANSPARENCY_MASK_DFB_COLOR_KEY_MASKED 0x1
+
+/*******************************************************************************
+** State gcregBlock8Control
+*/
+
+/* General purpose control register. */
+
+#define gcregBlock8PEControlRegAddrs 0x4B20
+#define GCREG_BLOCK8_PE_CONTROL_MSB 15
+#define GCREG_BLOCK8_PE_CONTROL_LSB 3
+#define GCREG_BLOCK8_PE_CONTROL_BLK 0
+#define GCREG_BLOCK8_PE_CONTROL_Count 8
+#define GCREG_BLOCK8_PE_CONTROL_FieldMask 0x00000999
+#define GCREG_BLOCK8_PE_CONTROL_ReadMask 0x00000999
+#define GCREG_BLOCK8_PE_CONTROL_WriteMask 0x00000999
+#define GCREG_BLOCK8_PE_CONTROL_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_PE_CONTROL_YUV 0 : 0
+#define GCREG_BLOCK8_PE_CONTROL_YUV_End 0
+#define GCREG_BLOCK8_PE_CONTROL_YUV_Start 0
+#define GCREG_BLOCK8_PE_CONTROL_YUV_Type U01
+#define GCREG_BLOCK8_PE_CONTROL_YUV_601 0x0
+#define GCREG_BLOCK8_PE_CONTROL_YUV_709 0x1
+
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUV 3 : 3
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUV_End 3
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUV_Start 3
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUV_Type U01
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUV_ENABLED 0x0
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUV_MASKED 0x1
+
+#define GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE 4 : 4
+#define GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE_End 4
+#define GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE_Start 4
+#define GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE_Type U01
+#define GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE_UV 0x0
+#define GCREG_BLOCK8_PE_CONTROL_UV_SWIZZLE_VU 0x1
+
+#define GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE 7 : 7
+#define GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE_End 7
+#define GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE_Start 7
+#define GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE_Type U01
+#define GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE_ENABLED 0x0
+#define GCREG_BLOCK8_PE_CONTROL_MASK_UV_SWIZZLE_MASKED 0x1
+
+/* YUV to RGB convert enable */
+#define GCREG_BLOCK8_PE_CONTROL_YUVRGB 8 : 8
+#define GCREG_BLOCK8_PE_CONTROL_YUVRGB_End 8
+#define GCREG_BLOCK8_PE_CONTROL_YUVRGB_Start 8
+#define GCREG_BLOCK8_PE_CONTROL_YUVRGB_Type U01
+#define GCREG_BLOCK8_PE_CONTROL_YUVRGB_DISABLED 0x0
+#define GCREG_BLOCK8_PE_CONTROL_YUVRGB_ENABLED 0x1
+
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB 11 : 11
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB_End 11
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB_Start 11
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB_Type U01
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB_ENABLED 0x0
+#define GCREG_BLOCK8_PE_CONTROL_MASK_YUVRGB_MASKED 0x1
+
+/*******************************************************************************
+** State gcregBlock8SrcColorKeyHigh
+*/
+
+/* Defines the source transparency color in source format. */
+
+#define gcregBlock8SrcColorKeyHighRegAddrs 0x4B28
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_MSB 15
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_LSB 3
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_BLK 0
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_Count 8
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ReadMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_WriteMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ALPHA 31 : 24
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ALPHA_End 31
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ALPHA_Start 24
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_ALPHA_Type U08
+
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_RED 23 : 16
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_RED_End 23
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_RED_Start 16
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_RED_Type U08
+
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_GREEN 15 : 8
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_GREEN_End 15
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_GREEN_Start 8
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_GREEN_Type U08
+
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_BLUE 7 : 0
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_BLUE_End 7
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_BLUE_Start 0
+#define GCREG_BLOCK8_SRC_COLOR_KEY_HIGH_BLUE_Type U08
+
+/*******************************************************************************
+** State gcregBlock8SrcExConfig
+*/
+
+#define gcregBlock8SrcExConfigRegAddrs 0x4B30
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MSB 15
+#define GCREG_BLOCK8_SRC_EX_CONFIG_LSB 3
+#define GCREG_BLOCK8_SRC_EX_CONFIG_BLK 0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_Count 8
+#define GCREG_BLOCK8_SRC_EX_CONFIG_FieldMask 0x00000109
+#define GCREG_BLOCK8_SRC_EX_CONFIG_ReadMask 0x00000109
+#define GCREG_BLOCK8_SRC_EX_CONFIG_WriteMask 0x00000109
+#define GCREG_BLOCK8_SRC_EX_CONFIG_ResetValue 0x00000000
+
+/* Source multi tiled address computation control. */
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED 0 : 0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_End 0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_Start 0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_Type U01
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_DISABLED 0x0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MULTI_TILED_ENABLED 0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED 3 : 3
+#define GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_End 3
+#define GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_Start 3
+#define GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_Type U01
+#define GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_DISABLED 0x0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_SUPER_TILED_ENABLED 0x1
+
+/* Source super tiled address computation control. */
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED 8 : 8
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_End 8
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_Start 8
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_Type U01
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_DISABLED 0x0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_MINOR_TILED_ENABLED 0x1
+
+/* Source CacheMode. */
+#define GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE 12 : 12
+#define GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE_End 12
+#define GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE_Start 12
+#define GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE_Type U01
+#define GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE_DISABLED 0x0
+#define GCREG_BLOCK8_SRC_EX_CONFIG_CACHE_MODE_ENABLED 0x1
+
+/*******************************************************************************
+** State gcregBlock8SrcExAddress
+*/
+
+/* 32-bit aligned base address of the source extra surface. */
+
+#define gcregBlock8SrcExAddressRegAddrs 0x4B38
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_MSB 15
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_LSB 3
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_BLK 0
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_Count 8
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_FieldMask 0xFFFFFFFF
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ReadMask 0xFFFFFFFC
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_WriteMask 0xFFFFFFFC
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ResetValue 0x00000000
+
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ADDRESS 31 : 0
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ADDRESS_End 30
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ADDRESS_Start 0
+#define GCREG_BLOCK8_SRC_EX_ADDRESS_ADDRESS_Type U31
+
+/*******************************************************************************
+** Generic defines
+*/
+
+#define GCREG_FORMAT_SUB_SAMPLE_MODE_YUV_MODE422 0x0
+#define GCREG_FORMAT_SUB_SAMPLE_MODE_YUV_MODE420 0x1
+
+#define GCREG_DE_SWIZZLE_ARGB 0x0
+#define GCREG_DE_SWIZZLE_RGBA 0x1
+#define GCREG_DE_SWIZZLE_ABGR 0x2
+#define GCREG_DE_SWIZZLE_BGRA 0x3
+
+#define GCREG_DE_FORMAT_X4R4G4B4 0x00
+#define GCREG_DE_FORMAT_A4R4G4B4 0x01
+#define GCREG_DE_FORMAT_X1R5G5B5 0x02
+#define GCREG_DE_FORMAT_A1R5G5B5 0x03
+#define GCREG_DE_FORMAT_R5G6B5 0x04
+#define GCREG_DE_FORMAT_X8R8G8B8 0x05
+#define GCREG_DE_FORMAT_A8R8G8B8 0x06
+#define GCREG_DE_FORMAT_YUY2 0x07
+#define GCREG_DE_FORMAT_UYVY 0x08
+#define GCREG_DE_FORMAT_INDEX8 0x09
+#define GCREG_DE_FORMAT_MONOCHROME 0x0A
+#define GCREG_DE_FORMAT_YV12 0x0F
+#define GCREG_DE_FORMAT_A8 0x10
+#define GCREG_DE_FORMAT_NV12 0x11
+#define GCREG_DE_FORMAT_NV16 0x12
+#define GCREG_DE_FORMAT_RG16 0x13
+
+/* ~~~~~~~~~~~~~ */
+
+#define GCREG_ALPHA_MODE_NORMAL 0x0
+#define GCREG_ALPHA_MODE_INVERSED 0x1
+
+#define GCREG_GLOBAL_ALPHA_MODE_NORMAL 0x0
+#define GCREG_GLOBAL_ALPHA_MODE_GLOBAL 0x1
+#define GCREG_GLOBAL_ALPHA_MODE_SCALED 0x2
+
+#define GCREG_COLOR_MODE_NORMAL 0x0
+#define GCREG_COLOR_MODE_MULTIPLY 0x1
+
+#define GCREG_BLENDING_MODE_ZERO 0x0
+#define GCREG_BLENDING_MODE_ONE 0x1
+#define GCREG_BLENDING_MODE_NORMAL 0x2
+#define GCREG_BLENDING_MODE_INVERSED 0x3
+#define GCREG_BLENDING_MODE_COLOR 0x4
+#define GCREG_BLENDING_MODE_COLOR_INVERSED 0x5
+#define GCREG_BLENDING_MODE_SATURATED_ALPHA 0x6
+#define GCREG_BLENDING_MODE_SATURATED_DEST_ALPHA 0x7
+
+#define GCREG_SRC_GLOBAL_PREMULTIPLY_DISABLE 0x0
+#define GCREG_SRC_GLOBAL_PREMULTIPLY_ALPHA 0x1
+#define GCREG_SRC_GLOBAL_PREMULTIPLY_COLOR 0x2
+
+/* ~~~~~~~~~~~~~ */
+
+#define GCREG_FACTOR_INVERSE_DISABLE 0x0
+#define GCREG_FACTOR_INVERSE_ENABLE 0x1
+
+/* ~~~~~~~~~~~~~ */
+
+#define GCREG_RESOURCE_USAGE_OVERRIDE_DEFAULT 0x0
+#define GCREG_RESOURCE_USAGE_OVERRIDE_USE_ENABLE 0x1
+#define GCREG_RESOURCE_USAGE_OVERRIDE_USE_DISABLE 0x2
+
+/*******************************************************************************
+** Modular operations: pipesel
+*/
+
+static const struct gccmdldstate gcmopipesel_pipesel_ldst =
+ GCLDSTATE(gcregPipeSelectRegAddrs, 1);
+
+struct gcmopipesel {
+ /* gcregPipeSelectRegAddrs */
+ struct gccmdldstate pipesel_ldst;
+
+ /* gcregPipeSelectRegAddrs */
+ union {
+ struct gcregpipeselect reg;
+ unsigned int raw;
+ } pipesel;
+};
+
+/*******************************************************************************
+** Modular operations: signal
+*/
+
+static const struct gccmdldstate gcmosignal_signal_ldst =
+ GCLDSTATE(gcregEventRegAddrs, 1);
+
+struct gcmosignal {
+ /* gcregEventRegAddrs */
+ struct gccmdldstate signal_ldst;
+
+ /* gcregEventRegAddrs */
+ union {
+ struct gcregevent reg;
+ unsigned int raw;
+ } signal;
+};
+
+/*******************************************************************************
+** Modular operations: flush
+*/
+
+static const struct gccmdldstate gcmoflush_flush_ldst =
+ GCLDSTATE(gcregFlushRegAddrs, 1);
+
+struct gcmoflush {
+ /* gcregFlushRegAddrs */
+ struct gccmdldstate flush_ldst;
+
+ /* gcregFlushRegAddrs */
+ union {
+ struct gcregflush reg;
+ unsigned int raw;
+ } flush;
+};
+
+/*******************************************************************************
+** Modular operations: semaphore
+*/
+
+static const struct gccmdldstate gcmosema_sema_ldst =
+ GCLDSTATE(gcregSemaphoreRegAddrs, 1);
+
+struct gcmosema {
+ /* gcregSemaphoreRegAddrs */
+ struct gccmdldstate sema_ldst;
+
+ /* gcregSemaphoreRegAddrs */
+ union {
+ struct gcregsemaphore reg;
+ unsigned int raw;
+ } sema;
+};
+
+/*******************************************************************************
+** Modular operations: mmuinit
+*/
+
+struct gcmoterminator {
+ union {
+ struct gcmosignal done;
+ struct gccmdnop nop;
+ } u1;
+
+ union {
+ struct gccmdwait wait;
+ struct gccmdlink linknext;
+ struct gccmdend end;
+ } u2;
+
+ union {
+ struct gccmdlink linkwait;
+ struct gccmdnop nop;
+ } u3;
+};
+
+/*******************************************************************************
+** Modular operations: mmuinit
+*/
+
+static const struct gccmdldstate gcmommuinit_safe_ldst =
+ GCLDSTATE(gcregMMUSafeAddressRegAddrs, 2);
+
+struct gcmommuinit {
+ /* gcregMMUSafeAddressRegAddrs */
+ struct gccmdldstate safe_ldst;
+
+ /* gcregMMUSafeAddressRegAddrs */
+ unsigned int safe;
+
+ /* gcregMMUConfigurationRegAddrs */
+ unsigned int mtlb;
+
+ /* Alignment filler. */
+ unsigned int _filler;
+};
+
+/*******************************************************************************
+** Modular operations: mmumaster
+*/
+
+static const struct gccmdldstate gcmommumaster_master_ldst =
+ GCLDSTATE(gcregMMUConfigurationRegAddrs, 1);
+
+struct gcmommumaster {
+ /* gcregMMUConfigurationRegAddrs */
+ struct gccmdldstate master_ldst;
+
+ /* gcregMMUConfigurationRegAddrs */
+ unsigned int master;
+};
+
+/*******************************************************************************
+** Modular operations: mmuflush
+*/
+
+static const struct gccmdldstate gcmommuflush_mmuflush_ldst =
+ GCLDSTATE(gcregMMUConfigurationRegAddrs, 1);
+
+struct gcmommuflush {
+ /* PE cache flush. */
+ struct gcmoflush peflush;
+
+ /* Semaphore/stall after PE flush. */
+ struct gcmosema peflushsema;
+ struct gccmdstall peflushstall;
+
+ /* Link to flush FE FIFO. */
+ struct gccmdlink feflush;
+
+ /* MMU flush. */
+ struct gccmdldstate mmuflush_ldst;
+
+ /* gcregMMUConfigurationRegAddrs */
+ union {
+ struct gcregmmuconfiguration reg;
+ unsigned int raw;
+ } mmuflush;
+
+ /* Semaphore/stall after MMU flush. */
+ struct gcmosema mmuflushsema;
+ struct gccmdstall mmuflushstall;
+
+ /* Link to the user buffer. */
+ struct gccmdlink link;
+};
+
+/*******************************************************************************
+** Modular operations: dst
+*/
+
+static const struct gccmdldstate gcmodst_config_ldst =
+ GCLDSTATE(gcregDestAddressRegAddrs, 3);
+
+static const struct gccmdldstate gcmodst_rotationheight_ldst =
+ GCLDSTATE(gcregDstRotationHeightRegAddrs, 1);
+
+static const struct gccmdldstate gcmodst_clip_ldst =
+ GCLDSTATE(gcregClipTopLeftRegAddrs, 2);
+
+struct gcmodst {
+ /* Configuration block. */
+ struct gccmdldstate config_ldst;
+
+ /* gcregDestAddressRegAddrs */
+ unsigned int address;
+
+ /* gcregDestStrideRegAddrs */
+ unsigned int stride;
+
+ /* gcregDestRotationConfigRegAddrs */
+ union {
+ struct gcregdstrotationconfig reg;
+ unsigned int raw;
+ } rotation;
+
+ /* gcregDstRotationHeightRegAddrs */
+ struct gccmdldstate rotationheight_ldst;
+
+ /* gcregDstRotationHeightRegAddrs */
+ union {
+ struct gcregdstrotationheight reg;
+ unsigned int raw;
+ } rotationheight;
+
+ /* Clipping block. */
+ struct gccmdldstate clip_ldst;
+
+ /* gcregClipTopLeftRegAddrs */
+ union {
+ struct gcregcliplt reg;
+ unsigned int raw;
+ } cliplt;
+
+ /* gcregClipBottomRight */
+ union {
+ struct gcregcliprb reg;
+ unsigned int raw;
+ } cliprb;
+
+ /* Alignment filler. */
+ unsigned int _filler;
+};
+
+/*******************************************************************************
+** Modular operations: alphaoff
+*/
+
+static const struct gccmdldstate gcmoalphaoff_control_ldst[8] = {
+ GCLDSTATE(gcregAlphaControlRegAddrs, 1),
+ GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 7, 1)
+};
+
+struct gcmoalphaoff {
+ /* gcregAlphaControlRegAddrs */
+ struct gccmdldstate control_ldst;
+
+ /* gcregAlphaControlRegAddrs */
+ union {
+ struct gcregalphacontrol reg;
+ unsigned int raw;
+ } control;
+};
+
+/*******************************************************************************
+** Modular operations: alpha
+*/
+
+static const struct gccmdldstate gcmoalpha_config_ldst =
+ GCLDSTATE(gcregAlphaControlRegAddrs, 2);
+
+struct gcmoalpha {
+ /* Alpha control block. */
+ struct gccmdldstate config_ldst;
+
+ /* gcregAlphaControlRegAddrs */
+ union {
+ struct gcregalphacontrol reg;
+ unsigned int raw;
+ } control;
+
+ /* gcregAlphaModesRegAddrs */
+ union {
+ struct gcregalphamodes reg;
+ unsigned int raw;
+ } mode;
+
+ /* Alignment filler. */
+ unsigned int _filler;
+};
+
+static const struct gccmdldstate gcmoxsrcalpha_control_ldst[8] = {
+ GCLDSTATE(gcregAlphaControlRegAddrs, 1),
+ GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4AlphaControlRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8AlphaControlRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcalpha_mode_ldst[8] = {
+ GCLDSTATE(gcregAlphaModesRegAddrs, 1),
+ GCLDSTATE(gcregBlock4AlphaModesRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4AlphaModesRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4AlphaModesRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8AlphaModesRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8AlphaModesRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8AlphaModesRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8AlphaModesRegAddrs + 7, 1)
+};
+
+struct gcmoxsrcalpha {
+ /* gcregBlock4AlphaControlRegAddrs */
+ struct gccmdldstate control_ldst;
+
+ /* gcregBlock4AlphaControlRegAddrs */
+ union {
+ struct gcregalphacontrol reg;
+ unsigned int raw;
+ } control;
+
+ /* gcregBlock4AlphaModesRegAddrs */
+ struct gccmdldstate mode_ldst;
+
+ /* gcregBlock4AlphaModesRegAddrs */
+ union {
+ struct gcregalphamodes reg;
+ unsigned int raw;
+ } mode;
+};
+
+/*******************************************************************************
+** Modular operations: alphaglobal
+*/
+
+static const struct gccmdldstate gcmoglobal_color_ldst =
+ GCLDSTATE(gcregGlobalSrcColorRegAddrs, 2);
+
+struct gcmoglobal {
+ /* Global color block. */
+ struct gccmdldstate color_ldst;
+
+ /* gcregGlobalSrcColorRegAddrs */
+ union {
+ struct gcregglobalsrccolor reg;
+ unsigned int raw;
+ } srcglobal;
+
+ /* gcregGlobalDestColorRegAddrs */
+ union {
+ struct gcregglobaldstcolor reg;
+ unsigned int raw;
+ } dstglobal;
+
+ /* Alignment filler. */
+ unsigned int _filler;
+};
+
+static const struct gccmdldstate gcmoxsrcglobal_srcglobal_ldst[8] = {
+ GCLDSTATE(gcregGlobalSrcColorRegAddrs, 1),
+ GCLDSTATE(gcregBlock4GlobalSrcColorRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4GlobalSrcColorRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4GlobalSrcColorRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8GlobalSrcColorRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8GlobalSrcColorRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8GlobalSrcColorRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8GlobalSrcColorRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcglobal_dstglobal_ldst[8] = {
+ GCLDSTATE(gcregGlobalDestColorRegAddrs, 1),
+ GCLDSTATE(gcregBlock4GlobalDestColorRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4GlobalDestColorRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4GlobalDestColorRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8GlobalDestColorRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8GlobalDestColorRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8GlobalDestColorRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8GlobalDestColorRegAddrs + 7, 1)
+};
+
+struct gcmoxsrcglobal {
+ /* gcregBlock4GlobalSrcColorRegAddrs */
+ struct gccmdldstate srcglobal_ldst;
+
+ /* gcregBlock4GlobalSrcColorRegAddrs */
+ union {
+ struct gcregglobalsrccolor reg;
+ unsigned int raw;
+ } srcglobal;
+
+ /* gcregBlock4GlobalDestColorRegAddrs */
+ struct gccmdldstate dstglobal_ldst;
+
+ /* gcregBlock4GlobalDestColorRegAddrs */
+ union {
+ struct gcregglobaldstcolor reg;
+ unsigned int raw;
+ } dstglobal;
+};
+
+/*******************************************************************************
+** Modular operations: yuv
+*/
+
+static const struct gccmdldstate gcmoyuv_pectrl_ldst =
+ GCLDSTATE(gcregPEControlRegAddrs, 1);
+
+static const struct gccmdldstate gcmoyuv2_plane_ldst =
+ GCLDSTATE(gcregUPlaneAddressRegAddrs, 2);
+
+static const struct gccmdldstate gcmoyuv3_plane_ldst =
+ GCLDSTATE(gcregUPlaneAddressRegAddrs, 4);
+
+struct gcmoyuv1 {
+ /* gcregPEControlRegAddrs */
+ struct gccmdldstate pectrl_ldst;
+
+ /* gcregPEControlRegAddrs */
+ union {
+ struct gcregpecontrol reg;
+ unsigned int raw;
+ } pectrl;
+};
+
+struct gcmoyuv2 {
+ /* gcregPEControlRegAddrs */
+ struct gccmdldstate pectrl_ldst;
+
+ /* gcregPEControlRegAddrs */
+ union {
+ struct gcregpecontrol reg;
+ unsigned int raw;
+ } pectrl;
+
+ /* Plane state block. */
+ struct gccmdldstate plane_ldst;
+
+ /* gcregUPlaneAddressRegAddrs */
+ unsigned int uplaneaddress;
+
+ /* gcregUPlaneStrideRegAddrs */
+ unsigned int uplanestride;
+
+ /* Alignment filler. */
+ unsigned int _filler1;
+};
+
+struct gcmoyuv3 {
+ /* gcregPEControlRegAddrs */
+ struct gccmdldstate pectrl_ldst;
+
+ /* gcregPEControlRegAddrs */
+ union {
+ struct gcregpecontrol reg;
+ unsigned int raw;
+ } pectrl;
+
+ /* Plane state block. */
+ struct gccmdldstate plane_ldst;
+
+ /* gcregUPlaneAddressRegAddrs */
+ unsigned int uplaneaddress;
+
+ /* gcregUPlaneStrideRegAddrs */
+ unsigned int uplanestride;
+
+ /* gcregVPlaneAddressRegAddrs */
+ unsigned int vplaneaddress;
+
+ /* gcregVPlaneStrideRegAddrs */
+ unsigned int vplanestride;
+
+ /* Alignment filler. */
+ unsigned int _filler1;
+};
+
+/*******************************************************************************
+** Modular operations: xsrcyuv
+*/
+
+static const struct gccmdldstate gcmoxsrcyuv_uplaneaddress_ldst[8] = {
+ GCLDSTATE(gcregUPlaneAddressRegAddrs, 1),
+ GCLDSTATE(gcregBlock4UPlaneAddressRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4UPlaneAddressRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4UPlaneAddressRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8UPlaneAddressRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8UPlaneAddressRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8UPlaneAddressRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8UPlaneAddressRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcyuv_uplanestride_ldst[8] = {
+ GCLDSTATE(gcregUPlaneStrideRegAddrs, 1),
+ GCLDSTATE(gcregBlock4UPlaneStrideRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4UPlaneStrideRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4UPlaneStrideRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8UPlaneStrideRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8UPlaneStrideRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8UPlaneStrideRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8UPlaneStrideRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcyuv_vplaneaddress_ldst[8] = {
+ GCLDSTATE(gcregVPlaneAddressRegAddrs, 1),
+ GCLDSTATE(gcregBlock4VPlaneAddressRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4VPlaneAddressRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4VPlaneAddressRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8VPlaneAddressRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8VPlaneAddressRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8VPlaneAddressRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8VPlaneAddressRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcyuv_vplanestride_ldst[8] = {
+ GCLDSTATE(gcregVPlaneStrideRegAddrs, 1),
+ GCLDSTATE(gcregBlock4VPlaneStrideRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4VPlaneStrideRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4VPlaneStrideRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8VPlaneStrideRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8VPlaneStrideRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8VPlaneStrideRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8VPlaneStrideRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmoxsrcyuv_pectrl_ldst[8] = {
+ GCLDSTATE(gcregPEControlRegAddrs, 1),
+ GCLDSTATE(gcregBlock4PEControlRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4PEControlRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4PEControlRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8PEControlRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8PEControlRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8PEControlRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8PEControlRegAddrs + 7, 1)
+};
+
+struct gcmoxsrcyuv1 {
+ /* gcregBlock4PEControlRegAddrs */
+ struct gccmdldstate pectrl_ldst;
+
+ /* gcregBlock4PEControlRegAddrs */
+ union {
+ struct gcregpecontrol reg;
+ unsigned int raw;
+ } pectrl;
+};
+
+struct gcmoxsrcyuv2 {
+ /* gcregBlock4PEControlRegAddrs */
+ struct gccmdldstate pectrl_ldst;
+
+ /* gcregBlock4PEControlRegAddrs */
+ union {
+ struct gcregpecontrol reg;
+ unsigned int raw;
+ } pectrl;
+
+ /* gcregBlock4UPlaneAddressRegAddrs */
+ struct gccmdldstate uplaneaddress_ldst;
+
+ /* gcregBlock4UPlaneAddressRegAddrs */
+ unsigned int uplaneaddress;
+
+ /* gcregBlock4UPlaneStrideRegAddrs */
+ struct gccmdldstate uplanestride_ldst;
+
+ /* gcregBlock4UPlaneStrideRegAddrs */
+ unsigned int uplanestride;
+};
+
+struct gcmoxsrcyuv3 {
+ /* gcregBlock4PEControlRegAddrs */
+ struct gccmdldstate pectrl_ldst;
+
+ /* gcregBlock4PEControlRegAddrs */
+ union {
+ struct gcregpecontrol reg;
+ unsigned int raw;
+ } pectrl;
+
+ /* gcregBlock4UPlaneAddressRegAddrs */
+ struct gccmdldstate uplaneaddress_ldst;
+
+ /* gcregBlock4UPlaneAddressRegAddrs */
+ unsigned int uplaneaddress;
+
+ /* gcregBlock4UPlaneStrideRegAddrs */
+ struct gccmdldstate uplanestride_ldst;
+
+ /* gcregBlock4UPlaneStrideRegAddrs */
+ unsigned int uplanestride;
+
+ /* gcregBlock4VPlaneAddressRegAddrs */
+ struct gccmdldstate vplaneaddress_ldst;
+
+ /* gcregBlock4VPlaneAddressRegAddrs */
+ unsigned int vplaneaddress;
+
+ /* gcregBlock4VPlaneStrideRegAddrs */
+ struct gccmdldstate vplanestride_ldst;
+
+ /* gcregBlock4VPlaneStrideRegAddrs */
+ unsigned int vplanestride;
+};
+
+/*******************************************************************************
+** Modular operations: src
+*/
+
+static const struct gccmdldstate gcmosrc0_config_ldst =
+ GCLDSTATE(gcregSrcAddressRegAddrs, 6);
+
+static const struct gccmdldstate gcmosrc0_rotation_ldst =
+ GCLDSTATE(gcregSrcRotationHeightRegAddrs, 2);
+
+static const struct gccmdldstate gcmosrc0_rop_ldst =
+ GCLDSTATE(gcregRopRegAddrs, 1);
+
+static const struct gccmdldstate gcmosrc0_mult_ldst =
+ GCLDSTATE(gcregColorMultiplyModesRegAddrs, 1);
+
+struct gcmosrc0 {
+ /* Configuration block. */
+ struct gccmdldstate config_ldst;
+
+ /* gcregSrcAddressRegAddrs */
+ unsigned int address;
+
+ /* gcregSrcStrideRegAddrs */
+ unsigned int stride;
+
+ /* gcregSrcRotationConfigRegAddrs */
+ union {
+ struct gcregsrcrotationconfig reg;
+ unsigned int raw;
+ } rotation;
+
+ /* gcregSrcConfigRegAddrs */
+ union {
+ struct gcregsrcconfig reg;
+ unsigned int raw;
+ } config;
+
+ /* gcregSrcOriginRegAddrs */
+ union {
+ struct gcregsrcorigin reg;
+ unsigned int raw;
+ } origin;
+
+ /* gcregSrcSizeRegAddrs */
+ union {
+ struct gcregsrcsize reg;
+ unsigned int raw;
+ } size;
+
+ /* Alignment filler. */
+ unsigned int _filler1;
+
+ /* Rotation block. */
+ struct gccmdldstate rotation_ldst;
+
+ /* gcregSrcRotationHeightRegAddrs */
+ union {
+ struct gcregsrcrotationheight reg;
+ unsigned int raw;
+ } rotationheight;
+
+ /* gcregRotAngleRegAddrs */
+ union {
+ struct gcregrotangle reg;
+ unsigned int raw;
+ } rotationangle;
+
+ /* Alignment filler. */
+ unsigned int _filler2;
+
+ /* gcregRopRegAddrs */
+ struct gccmdldstate rop_ldst;
+
+ /* gcregRopRegAddrs */
+ union {
+ struct gcregrop reg;
+ unsigned int raw;
+ } rop;
+
+ /* gcregColorMultiplyModesRegAddrs */
+ struct gccmdldstate mult_ldst;
+
+ /* gcregColorMultiplyModesRegAddrs */
+ union {
+ struct gcregcolormultiplymodes reg;
+ unsigned int raw;
+ } mult;
+};
+
+static const struct gccmdldstate gcmosrc_address_ldst[8] = {
+ GCLDSTATE(gcregSrcAddressRegAddrs, 1),
+ GCLDSTATE(gcregBlock4SrcAddressRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4SrcAddressRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4SrcAddressRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8SrcAddressRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8SrcAddressRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8SrcAddressRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8SrcAddressRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_stride_ldst[8] = {
+ GCLDSTATE(gcregSrcStrideRegAddrs, 1),
+ GCLDSTATE(gcregBlock4SrcStrideRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4SrcStrideRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4SrcStrideRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8SrcStrideRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8SrcStrideRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8SrcStrideRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8SrcStrideRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_rotation_ldst[8] = {
+ GCLDSTATE(gcregSrcRotationConfigRegAddrs, 1),
+ GCLDSTATE(gcregBlock4SrcRotationConfigRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4SrcRotationConfigRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4SrcRotationConfigRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8SrcRotationConfigRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8SrcRotationConfigRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8SrcRotationConfigRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8SrcRotationConfigRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_config_ldst[8] = {
+ GCLDSTATE(gcregSrcConfigRegAddrs, 1),
+ GCLDSTATE(gcregBlock4SrcConfigRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4SrcConfigRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4SrcConfigRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8SrcConfigRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8SrcConfigRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8SrcConfigRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8SrcConfigRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_origin_ldst[8] = {
+ GCLDSTATE(gcregSrcOriginRegAddrs, 1),
+ GCLDSTATE(gcregBlock4SrcOriginRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4SrcOriginRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4SrcOriginRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8SrcOriginRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8SrcOriginRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8SrcOriginRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8SrcOriginRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_size_ldst[8] = {
+ GCLDSTATE(gcregSrcSizeRegAddrs, 1),
+ GCLDSTATE(gcregBlock4SrcSizeRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4SrcSizeRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4SrcSizeRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8SrcSizeRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8SrcSizeRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8SrcSizeRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8SrcSizeRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_rotationheight_ldst[8] = {
+ GCLDSTATE(gcregSrcRotationHeightRegAddrs, 1),
+ GCLDSTATE(gcregBlock4SrcRotationHeightRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4SrcRotationHeightRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4SrcRotationHeightRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8SrcRotationHeightRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8SrcRotationHeightRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8SrcRotationHeightRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8SrcRotationHeightRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_rotationangle_ldst[8] = {
+ GCLDSTATE(gcregRotAngleRegAddrs, 1),
+ GCLDSTATE(gcregBlock4RotAngleRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4RotAngleRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4RotAngleRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8RotAngleRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8RotAngleRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8RotAngleRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8RotAngleRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_rop_ldst[8] = {
+ GCLDSTATE(gcregRopRegAddrs, 1),
+ GCLDSTATE(gcregBlock4RopRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4RopRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4RopRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8RopRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8RopRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8RopRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8RopRegAddrs + 7, 1)
+};
+
+static const struct gccmdldstate gcmosrc_mult_ldst[8] = {
+ GCLDSTATE(gcregColorMultiplyModesRegAddrs, 1),
+ GCLDSTATE(gcregBlock4ColorMultiplyModesRegAddrs + 1, 1),
+ GCLDSTATE(gcregBlock4ColorMultiplyModesRegAddrs + 2, 1),
+ GCLDSTATE(gcregBlock4ColorMultiplyModesRegAddrs + 3, 1),
+ GCLDSTATE(gcregBlock8ColorMultiplyModesRegAddrs + 4, 1),
+ GCLDSTATE(gcregBlock8ColorMultiplyModesRegAddrs + 5, 1),
+ GCLDSTATE(gcregBlock8ColorMultiplyModesRegAddrs + 6, 1),
+ GCLDSTATE(gcregBlock8ColorMultiplyModesRegAddrs + 7, 1)
+};
+
+struct gcmosrc {
+ /* gcregBlock4SrcAddressRegAddrs */
+ struct gccmdldstate address_ldst;
+
+ /* gcregBlock4SrcAddressRegAddrs */
+ unsigned int address;
+
+ /* gcregBlock4SrcStrideRegAddrs */
+ struct gccmdldstate stride_ldst;
+
+ /* gcregBlock4SrcStrideRegAddrs */
+ unsigned int stride;
+
+ /* gcregBlock4SrcRotationConfigRegAddrs */
+ struct gccmdldstate rotation_ldst;
+
+ /* gcregBlock4SrcRotationConfigRegAddrs */
+ union {
+ struct gcregsrcrotationconfig reg;
+ unsigned int raw;
+ } rotation;
+
+ /* gcregBlock4SrcConfigRegAddrs */
+ struct gccmdldstate config_ldst;
+
+ /* gcregBlock4SrcConfigRegAddrs */
+ union {
+ struct gcregsrcconfig reg;
+ unsigned int raw;
+ } config;
+
+ /* gcregBlock4SrcOriginRegAddrs */
+ struct gccmdldstate origin_ldst;
+
+ /* gcregBlock4SrcOriginRegAddrs */
+ union {
+ struct gcregsrcorigin reg;
+ unsigned int raw;
+ } origin;
+
+ /* gcregBlock4SrcSizeRegAddrs */
+ struct gccmdldstate size_ldst;
+
+ /* gcregBlock4SrcSizeRegAddrs */
+ union {
+ struct gcregsrcsize reg;
+ unsigned int raw;
+ } size;
+
+ /* gcregBlock4SrcRotationHeightRegAddrs */
+ struct gccmdldstate rotationheight_ldst;
+
+ /* gcregBlock4SrcRotationHeightRegAddrs */
+ union {
+ struct gcregsrcrotationheight reg;
+ unsigned int raw;
+ } rotationheight;
+
+ /* gcregBlock4RotAngleRegAddrs */
+ struct gccmdldstate rotationangle_ldst;
+
+ /* gcregBlock4RotAngleRegAddrs */
+ union {
+ struct gcregrotangle reg;
+ unsigned int raw;
+ } rotationangle;
+
+ /* gcregBlock4RopRegAddrs */
+ struct gccmdldstate rop_ldst;
+
+ /* gcregBlock4RopRegAddrs */
+ union {
+ struct gcregrop reg;
+ unsigned int raw;
+ } rop;
+
+ /* gcregBlock4ColorMultiplyModesRegAddrs */
+ struct gccmdldstate mult_ldst;
+
+ /* gcregBlock4ColorMultiplyModesRegAddrs */
+ union {
+ struct gcregcolormultiplymodes reg;
+ unsigned int raw;
+ } mult;
+};
+
+static const struct gccmdldstate gcmovrsrc_config_ldst =
+ GCLDSTATE(gcregSrcAddressRegAddrs, 4);
+
+static const struct gccmdldstate gcmovrsrc_pos_ldst =
+ GCLDSTATE(gcregVRSourceImageLowRegAddrs, 4);
+
+static const struct gccmdldstate gcmovrsrc_rotation_ldst =
+ GCLDSTATE(gcregSrcRotationHeightRegAddrs, 2);
+
+static const struct gccmdldstate gcmovrsrc_rop_ldst =
+ GCLDSTATE(gcregRopRegAddrs, 1);
+
+static const struct gccmdldstate gcmovrsrc_mult_ldst =
+ GCLDSTATE(gcregColorMultiplyModesRegAddrs, 1);
+
+struct gcmovrsrc {
+ /* Configuration block. */
+ struct gccmdldstate config_ldst;
+
+ /* gcregSrcAddressRegAddrs */
+ unsigned int address;
+
+ /* gcregSrcStrideRegAddrs */
+ unsigned int stride;
+
+ /* gcregSrcRotationConfigRegAddrs */
+ union {
+ struct gcregsrcrotationconfig reg;
+ unsigned int raw;
+ } rotation;
+
+ /* gcregSrcConfigRegAddrs */
+ union {
+ struct gcregsrcconfig reg;
+ unsigned int raw;
+ } config;
+
+ /* Alignment filler. */
+ unsigned int _filler1;
+
+ /* Source position block. */
+ struct gccmdldstate pos_ldst;
+
+ /* gcregVRSourceImageLowRegAddrs */
+ union {
+ struct gcregvrsourceimagelow reg;
+ unsigned int raw;
+ } lt;
+
+ /* gcregVRSourceImageHighRegAddrs */
+ union {
+ struct gcregvrsourceimagehigh reg;
+ unsigned int raw;
+ } rb;
+
+ /* gcregVRSourceOriginLowRegAddrs */
+ unsigned int x;
+
+ /* gcregVRSourceOriginHighRegAddrs */
+ unsigned int y;
+
+ /* Alignment filler. */
+ unsigned int _filler2;
+
+ /* Rotation block. */
+ struct gccmdldstate rotation_ldst;
+
+ /* gcregSrcRotationHeightRegAddrs */
+ union {
+ struct gcregsrcrotationheight reg;
+ unsigned int raw;
+ } rotationheight;
+
+ /* gcregRotAngleRegAddrs */
+ union {
+ struct gcregrotangle reg;
+ unsigned int raw;
+ } rotationangle;
+
+ /* Alignment filler. */
+ unsigned int _filler3;
+
+ /* gcregRopRegAddrs */
+ struct gccmdldstate rop_ldst;
+
+ /* gcregRopRegAddrs */
+ union {
+ struct gcregrop reg;
+ unsigned int raw;
+ } rop;
+
+ /* gcregColorMultiplyModesRegAddrs */
+ struct gccmdldstate mult_ldst;
+
+ /* gcregColorMultiplyModesRegAddrs */
+ union {
+ struct gcregcolormultiplymodes reg;
+ unsigned int raw;
+ } mult;
+};
+
+/*******************************************************************************
+** Modular operations: bltconfig
+*/
+
+static const struct gccmdldstate gcmobltconfig_multisource_ldst =
+ GCLDSTATE(gcregDEMultiSourceRegAddrs, 1);
+
+static const struct gccmdldstate gcmobltconfig_dstconfig_ldst =
+ GCLDSTATE(gcregDestConfigRegAddrs, 1);
+
+struct gcmobltconfig {
+ /* gcregDEMultiSourceRegAddrs */
+ struct gccmdldstate multisource_ldst;
+
+ /* gcregDEMultiSourceRegAddrs */
+ union {
+ struct gcregmultisource reg;
+ unsigned int raw;
+ } multisource;
+
+ /* gcregDestConfigRegAddrs */
+ struct gccmdldstate dstconfig_ldst;
+
+ /* gcregDestConfigRegAddrs */
+ union {
+ struct gcregdstconfig reg;
+ unsigned int raw;
+ } dstconfig;
+};
+
+/*******************************************************************************
+** Modular operations: startde
+*/
+
+struct gcmostartde {
+ /* Start DE command. */
+ struct gccmdstartde startde;
+ struct gccmdstartderect rect;
+};
+
+/*******************************************************************************
+** Modular operations: fillsrc
+*/
+
+static const struct gccmdldstate gcmofillsrc_rotation_ldst =
+ GCLDSTATE(gcregSrcRotationConfigRegAddrs, 2);
+
+static const struct gccmdldstate gcmofillsrc_rotationheight_ldst =
+ GCLDSTATE(gcregSrcRotationHeightRegAddrs, 2);
+
+static const struct gccmdldstate gcmofillsrc_alphacontrol_ldst =
+ GCLDSTATE(gcregAlphaControlRegAddrs, 1);
+
+struct gcmofillsrc {
+ /* gcregSrcRotationConfigRegAddrs */
+ struct gccmdldstate rotation_ldst;
+
+ /* gcregSrcRotationConfigRegAddrs */
+ union {
+ struct gcregsrcrotationconfig reg;
+ unsigned int raw;
+ } rotation;
+
+ /* gcregSrcConfigRegAddrs */
+ union {
+ struct gcregsrcconfig reg;
+ unsigned int raw;
+ } config;
+
+ /* Alignment filler. */
+ unsigned int _filler1;
+
+ /* gcregSrcRotationHeightRegAddrs */
+ struct gccmdldstate rotationheight_ldst;
+
+ /* gcregSrcRotationHeightRegAddrs */
+ union {
+ struct gcregsrcrotationheight reg;
+ unsigned int raw;
+ } rotationheight;
+
+ /* gcregRotAngleRegAddrs */
+ union {
+ struct gcregrotangle reg;
+ unsigned int raw;
+ } rotationangle;
+
+ /* Alignment filler. */
+ unsigned int _filler2;
+
+ /* gcregAlphaControlRegAddrs */
+ struct gccmdldstate alphacontrol_ldst;
+
+ /* gcregAlphaControlRegAddrs */
+ union {
+ struct gcregalphacontrol reg;
+ unsigned int raw;
+ } alphacontrol;
+};
+
+/*******************************************************************************
+** Modular operations: fill
+*/
+
+static const struct gccmdldstate gcmofill_clearcolor_ldst =
+ GCLDSTATE(gcregClearPixelValue32RegAddrs, 1);
+
+static const struct gccmdldstate gcmofill_dstconfig_ldst =
+ GCLDSTATE(gcregDestConfigRegAddrs, 1);
+
+static const struct gccmdldstate gcmofill_rop_ldst =
+ GCLDSTATE(gcregRopRegAddrs, 1);
+
+struct gcmofill {
+ struct gcmofillsrc src;
+
+ /* gcregClearPixelValue32RegAddrs */
+ struct gccmdldstate clearcolor_ldst;
+
+ /* gcregClearPixelValue32RegAddrs */
+ union {
+ struct gcregclearcolor reg;
+ unsigned int raw;
+ } clearcolor;
+
+ /* gcregDestConfigRegAddrs */
+ struct gccmdldstate dstconfig_ldst;
+
+ /* gcregDestConfigRegAddrs */
+ union {
+ struct gcregdstconfig reg;
+ unsigned int raw;
+ } dstconfig;
+
+ /* gcregRopRegAddrs */
+ struct gccmdldstate rop_ldst;
+
+ /* gcregRopRegAddrs */
+ union {
+ struct gcregrop reg;
+ unsigned int raw;
+ } rop;
+
+ /* Start DE command. */
+ struct gccmdstartde startde;
+ struct gccmdstartderect rect;
+};
+
+/*******************************************************************************
+** Modular operations: filterkernel
+*/
+
+static const struct gccmdldstate gcmofilterkernel_shared_ldst =
+ GCLDSTATE(gcregFilterKernelRegAddrs, 77);
+
+static const struct gccmdldstate gcmofilterkernel_horizontal_ldst =
+ GCLDSTATE(gcregHoriFilterKernelRegAddrs, 77);
+
+static const struct gccmdldstate gcmofilterkernel_vertical_ldst =
+ GCLDSTATE(gcregVertiFilterKernelRegAddrs, 77);
+
+struct gcmofilterkernel {
+ /* Kernel array block. */
+ struct gccmdldstate kernelarray_ldst;
+
+ /* Array of kernel coefficients. */
+ struct gcregfilterkernel kernelarray;
+};
+
+/*******************************************************************************
+** Modular operations: vrdst
+*/
+
+static const struct gccmdldstate gcmovrdst_config_ldst =
+ GCLDSTATE(gcregDestAddressRegAddrs, 4);
+
+static const struct gccmdldstate gcmovrdst_rotationheight_ldst =
+ GCLDSTATE(gcregDstRotationHeightRegAddrs, 1);
+
+struct gcmovrdst {
+ /* Configuration block. */
+ struct gccmdldstate config_ldst;
+
+ /* gcregDestAddressRegAddrs */
+ unsigned int address;
+
+ /* gcregDestStrideRegAddrs */
+ unsigned int stride;
+
+ /* gcregDestRotationConfigRegAddrs */
+ union {
+ struct gcregdstrotationconfig reg;
+ unsigned int raw;
+ } rotation;
+
+ /* gcregDestConfigRegAddrs */
+ union {
+ struct gcregdstconfig reg;
+ unsigned int raw;
+ } config;
+
+ /* Alignment filler. */
+ unsigned int _filler;
+
+ /* gcregDstRotationHeightRegAddrs */
+ struct gccmdldstate rotationheight_ldst;
+
+ /* gcregDstRotationHeightRegAddrs */
+ union {
+ struct gcregdstrotationheight reg;
+ unsigned int raw;
+ } rotationheight;
+};
+
+/*******************************************************************************
+** Modular operations: vrconfigex
+*/
+
+static const struct gccmdldstate gcmovrconfigex_config_ldst =
+ GCLDSTATE(gcregVRConfigExRegAddrs, 1);
+
+struct gcmovrconfigex {
+ /* gcregVRConfigExRegAddrs */
+ struct gccmdldstate config_ldst;
+
+ /* gcregVRConfigExRegAddrs */
+ union {
+ struct gcregvrconfigex reg;
+ unsigned int raw;
+ } config;
+};
+
+/*******************************************************************************
+** Modular operations: startvr
+*/
+
+static const struct gccmdldstate gcmostartvr_scale_ldst =
+ GCLDSTATE(gcregStretchFactorLowRegAddrs, 2);
+
+static const struct gccmdldstate gcmostartvr_rect_ldst =
+ GCLDSTATE(gcregVRTargetWindowLowRegAddrs, 2);
+
+static const struct gccmdldstate gcmostartvr_config_ldst =
+ GCLDSTATE(gcregVRConfigRegAddrs, 1);
+
+struct gcmostartvr {
+ /* Scale factor block. */
+ struct gccmdldstate scale_ldst;
+
+ /* gcregStretchFactorLowRegAddrs */
+ unsigned int scalex;
+
+ /* gcregStretchFactorHighRegAddrs */
+ unsigned int scaley;
+
+ /* Alignment filler. */
+ unsigned int _filler1;
+
+ /* Target rectangle. */
+ struct gccmdldstate rect_ldst;
+
+ /* gcregVRTargetWindowLowRegAddrs */
+ struct gcregvrtargetwindowlow lt;
+
+ /* gcregVRTargetWindowHighRegAddrs */
+ struct gcregvrtargetwindowhigh rb;
+
+ /* Alignment filler. */
+ unsigned int _filler2;
+
+ /* Start video raster commad. */
+ struct gccmdldstate config_ldst;
+
+ /* gcregVRConfigRegAddrs */
+ struct gcregvrconfig config;
+};
+
+#endif
diff --git a/include/linux/gcx.h b/include/linux/gcx.h
--- /dev/null
+++ b/include/linux/gcx.h
@@ -0,0 +1,106 @@
+/*
+ * gcx.h
+ *
+ * Copyright (C) 2010-2011 Vivante Corporation.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef GCX_H
+#define GCX_H
+
+#include "semaphore.h"
+#include "gcerror.h"
+#include "gcreg.h"
+#include "gcdbglog.h"
+#include "gcdebug.h"
+
+#ifndef countof
+#define countof(a) \
+( \
+ sizeof(a) / sizeof(a[0]) \
+)
+#endif
+
+#define GC_PTR2INT(p) \
+( \
+ (unsigned int) (p) \
+)
+
+#define GC_ALIGN(n, align) \
+( \
+ ((n) + ((align) - 1)) & ~((align) - 1) \
+)
+
+#define GCLOCK_TIMEOUT_SEC 10
+#define GCLOCK_TIMEOUT_JIF (msecs_to_jiffies(GCLOCK_TIMEOUT_SEC * 1000))
+
+#define GCLOCK_TYPE \
+ struct semaphore
+
+#define GCDEFINE_LOCK(name) \
+ DEFINE_SEMAPHORE(name)
+
+#define GCLOCK_INIT(lock) \
+ sema_init(lock, 1)
+
+#define GCLOCK_DESTROY(lock) \
+ do { } while (0)
+
+#define GCLOCK(lock) { \
+ unsigned long __result__; \
+ while (true) { \
+ __result__ = down_timeout(lock, GCLOCK_TIMEOUT_JIF); \
+ if (__result__ == 0) \
+ break; \
+ printk(KERN_ERR "%s(%d) GCLOCK timeout (%lu).\n", \
+ __func__, __LINE__, __result__); \
+ GCGPUSTATUS(); \
+ printk(KERN_INFO "%s(%d)\n", __func__, __LINE__); \
+ } \
+}
+
+#define GCUNLOCK(lock) \
+ up(lock)
+
+#define GCWAIT_FOR_COMPLETION(completion) { \
+ unsigned long __result__; \
+ while (true) { \
+ __result__ = wait_for_completion_timeout(completion, \
+ GCLOCK_TIMEOUT_JIF); \
+ if (__result__ != 0) \
+ break; \
+ printk(KERN_ERR \
+ "%s(%d) GCWAIT_FOR_COMPLETION timeout (%lu).\n", \
+ __func__, __LINE__, __result__); \
+ GCGPUSTATUS(); \
+ printk(KERN_INFO "%s(%d)\n", __func__, __LINE__); \
+ } \
+}
+
+#define GCWAIT_FOR_COMPLETION_TIMEOUT(result, completion, timeout) { \
+ if (timeout == MAX_SCHEDULE_TIMEOUT) { \
+ while (true) { \
+ result = wait_for_completion_timeout(completion, \
+ GCLOCK_TIMEOUT_JIF); \
+ if (result != 0) \
+ break; \
+ printk(KERN_ERR \
+ "%s(%d) GCWAIT_FOR_COMPLETION_TIMEOUT" \
+ " timeout (%lu).\n", \
+ __func__, __LINE__, result); \
+ GCGPUSTATUS(); \
+ printk(KERN_INFO "%s(%d)\n", __func__, __LINE__); \
+ } \
+ } else { \
+ result = wait_for_completion_timeout(completion, timeout); \
+ } \
+}
+
+#endif
diff --git a/include/linux/ocd.h b/include/linux/ocd.h
--- /dev/null
+++ b/include/linux/ocd.h
@@ -0,0 +1,781 @@
+/*
+ * ocd.h
+ *
+ * Open Color format Definitions
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file defines the Open Color format Definitions (OCD), an open,
+ * extensible, color format definition.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef OCD_H
+#define OCD_H
+
+/*
+ * ocdformat - specifies one of the supported color formats
+ *
+ * ocdformat consists of 8 bits indicating the vendor ID, followed by 24 bits
+ * specified by the vendor.
+ *
+ * VENDOR_ALL is a common ID with formats defined below.
+ */
+
+/****** Bits 31-24 are the vendor ID. The other 24 are vendor defined. ******/
+#define OCDFMTDEF_VENDOR_SHIFT 24
+#define OCDFMTDEF_VENDOR_MASK (0xFF << OCDFMTDEF_VENDOR_SHIFT)
+
+#define OCDFMTDEF_VENDOR_ALL \
+ (0x00 << OCDFMTDEF_VENDOR_SHIFT) /* Common format */
+#define OCDFMTDEF_VENDOR_TI \
+ (0x01 << OCDFMTDEF_VENDOR_SHIFT) /* Texas Instruments, Inc. */
+/* 0xF0-0xFF reserved */
+
+/***** OCDFMTDEF_VENDOR_ALL *****/
+/* The formats in this group are created using combinations of the values
+ listed below. */
+
+/*
+ * 33222222 222 21 1 1 1 11 111 1
+ * 10987654 321 09 8 7 6 54 321 0 9 876 543210
+ * [------] [-] [] | | | [] [-] | | [-] [----]
+ * | | | | | | | | | | | |
+ * | | | | | | | | | | | color bits minus 1
+ * | | | | | | | | | | |
+ * | | | | | | | | | | container
+ * | | | | | | | | | |
+ * | | | | | | | | | left justified
+ * | | | | | | | | |
+ * | | | | | | | | reversed
+ * | | | | | | | |
+ * | | | | | | | layout
+ * | | | | | | |
+ * | | | | | | subsampling
+ * | | | | | |
+ * | | | | | subsample position \
+ * | | | | | |
+ * | | | | non-premult/fill empty 0 > alpha components
+ * | | | | |
+ * | | | alpha /
+ * | | |
+ * | | standard
+ * | |
+ * | color space
+ * |
+ * vendor ID (VENDOR_ALL = 0x00)
+ */
+
+/**** Bits 23-21 define the color space. ****/
+#define OCDFMTDEF_CS_SHIFT 21
+#define OCDFMTDEF_CS_MASK (7 << OCDFMTDEF_CS_SHIFT)
+
+#define OCDFMTDEF_CS_MONO \
+ (0 << OCDFMTDEF_CS_SHIFT) /* Monochrome (luma only) */
+#define OCDFMTDEF_CS_LUT \
+ (1 << OCDFMTDEF_CS_SHIFT) /* Look-up table (using palette) */
+#define OCDFMTDEF_CS_RGB \
+ (2 << OCDFMTDEF_CS_SHIFT) /* Red, green, blue */
+#define OCDFMTDEF_CS_YCbCr \
+ (3 << OCDFMTDEF_CS_SHIFT) /* YCbCr (YUV) (luma & chroma) */
+#define OCDFMTDEF_CS_ALPHA \
+ (4 << OCDFMTDEF_CS_SHIFT) /* Alpha only (transparency) */
+/* 5 reserved */
+/* 6 reserved */
+/* 7 reserved */
+
+/**** Bits 20-19 define the standard ****/
+#define OCDFMTDEF_STD_SHIFT 19
+#define OCDFMTDEF_STD_MASK (3 << OCDFMTDEF_STD_SHIFT)
+
+#define OCDFMTDEF_STD_ITUR_601_YCbCr \
+ (0 << OCDFMTDEF_STD_SHIFT) /* ITU-R BT.601 - YCbCr only */
+/* 0 default for non-YCbCr */
+#define OCDFMTDEF_STD_ITUR_709_YCbCr \
+ (1 << OCDFMTDEF_STD_SHIFT) /* ITU-R BT.709 - YCbCr only */
+/* 1 reserved for non-YCbCr */
+/* 2 reserved */
+#define OCDFMTDEF_FULLSCALE_YCbCr \
+ (3 << OCDFMTDEF_STD_SHIFT) /* RGB 0 to 255 =>
+ YCbCr 0 to 255, -128 to 127 */
+/* 3 reserved for non-YCbCr */
+
+/**** Bits 18-16 are component modifiers for non-alpha c/s only ****/
+#define OCDFMTDEF_ALPHA \
+ (1 << 18) /* An alpha component is added to the format */
+#define OCDFMTDEF_NON_PREMULT \
+ (1 << 17) /* Component(s) is(are) not premultiplied by the alpha
+ (default is premultiplied) */
+#define OCDFMTDEF_FILL_EMPTY_0 \
+ (1 << 17) /* Empty bits are hard-wired to 0 (default is 1) */
+#define OCDFMTDEF_SUBSAMPLE_HORZ_ALIGNED \
+ (0 << 16) /* Subsamples aligned w/1st non-subsample (e.g. MPEG-2) */
+#define OCDFMTDEF_SUBSAMPLE_HORZ_CENTERED \
+ (1 << 16) /* Subsamples are between non-subsamples (e.g. MPEG-1) */
+
+/*** Bits 18-16 are used differently for alpha c/s ***/
+/* Bit 18 is reserved */
+/*** Bits 17-16 define the number of alpha components for alpha c/s ***/
+#define OCDFMTDEF_ALPHA_COMPONENTS_SHIFT 16
+#define OCDFMTDEF_ALPHA_COMPONENTS_MASK (3 << OCDFMTDEF_ALPHA_COMPONENTS_SHIFT)
+
+#define OCDFMTDEF_ALPHA_COMPONENTS_1 (0 << OCDFMTDEF_ALPHA_COMPONENTS_SHIFT)
+#define OCDFMTDEF_ALPHA_COMPONENTS_2 (1 << OCDFMTDEF_ALPHA_COMPONENTS_SHIFT)
+#define OCDFMTDEF_ALPHA_COMPONENTS_3 (2 << OCDFMTDEF_ALPHA_COMPONENTS_SHIFT)
+#define OCDFMTDEF_ALPHA_COMPONENTS_4 (3 << OCDFMTDEF_ALPHA_COMPONENTS_SHIFT)
+
+/**** Bits 15-14 define subsampling ****/
+#define OCDFMTDEF_SUBSAMPLE_SHIFT 14
+#define OCDFMTDEF_SUBSAMPLE_MASK (3 << OCDFMTDEF_SUBSAMPLE_SHIFT)
+
+#define OCDFMTDEF_SUBSAMPLE_NONE \
+ (0 << OCDFMTDEF_SUBSAMPLE_SHIFT) /* No subsampling;
+ each pixel has each component */
+#define OCDFMTDEF_SUBSAMPLE_422_YCbCr \
+ (1 << OCDFMTDEF_SUBSAMPLE_SHIFT) /* 4:2:2 subsampling;
+ each horizontal pair of pixels
+ has one Y (luma) component each,
+ but shares one Cb and Cr (chroma)
+ component. */
+/* 1 reserved for non-YCbCr */
+#define OCDFMTDEF_SUBSAMPLE_420_YCbCr \
+ (2 << OCDFMTDEF_SUBSAMPLE_SHIFT) /* 4:2:0 subsampling;
+ each square of four pixels has
+ one Y (luma) component each, but
+ shares one Cb and Cr (chroma)
+ component. */
+/* 2 reserved for non-YCbCr */
+#define OCDFMTDEF_SUBSAMPLE_411_YCbCr \
+ (3 << OCDFMTDEF_SUBSAMPLE_SHIFT) /* 4:1:1 subsampling;
+ each horizontal four pixels have
+ one Y (luma) component each, but
+ shares one Cb and Cr (chroma)
+ component. */
+/* 3 reserved for non-YCbCr */
+
+/**** Bits 13-11 define the memory layout
+ (combined with _REVERSED and _LEFT_JUSTIFIED) ****/
+#define OCDFMTDEF_LAYOUT_SHIFT 11
+#define OCDFMTDEF_LAYOUT_MASK (7 << OCDFMTDEF_LAYOUT_SHIFT)
+
+#define OCDFMTDEF_PACKED \
+ (0 << OCDFMTDEF_LAYOUT_SHIFT) /* Components interleaved together */
+#define OCDFMTDEF_DISTRIBUTED \
+ (1 << OCDFMTDEF_LAYOUT_SHIFT) /* Components are distributed evenly
+ across the container; e.g. a 64-bit
+ container with four 8-bit components
+ are distributed with 8 bits between
+ them: __C0__C1__C2__C3 */
+#define OCDFMTDEF_2_PLANE_YCbCr \
+ (2 << OCDFMTDEF_LAYOUT_SHIFT) /* Y component is separated from Cb & Cr
+ components. After the Y plane, an
+ interleaved CbCr plane follows. */
+/* 2 reserved for non-YCbCr */
+#define OCDFMTDEF_3_PLANE_STACKED \
+ (3 << OCDFMTDEF_LAYOUT_SHIFT) /* Y, Cb, and Cr components are
+ separated. After the Y plane is a Cb
+ plane, and then a Cr plane. */
+/* 3 reserved for non-YCbCr and non-RGB */
+/* 4 reserved */
+/* 5 reserved */
+/* 6 reserved */
+#define OCDFMTDEF_3_PLANE_SIDE_BY_SIDE_YCbCr \
+ (7 << OCDFMTDEF_LAYOUT_SHIFT) /* Y, Cb, and Cr components are
+ separated. After the Y plane the Cb
+ and Cr planes are separated but
+ side-by-side in memory (interleaved
+ on a line-by-line basis). */
+/* 7 reserved for non-YCbCr */
+
+/**** Bits 10-9 are layout modifiers. ****/
+#define OCDFMTDEF_REVERSED \
+ (1 << 10) /* Order of components reversed (default is RGB or CbCr) */
+#define OCDFMTDEF_LEFT_JUSTIFIED \
+ (1 << 9) /* Components are shifted left (default is shifted right);
+ for 3-plane YCbCr, this indicates wasted space to the
+ right of the Cb & Cr planes (stride matches Y plane). */
+
+/**** Bits 6-8 specify the container type. ****/
+#define OCDFMTDEF_CONTAINER_SHIFT 6
+#define OCDFMTDEF_CONTAINER_MASK (7 << OCDFMTDEF_CONTAINER_SHIFT)
+
+#define OCDFMTDEF_CONTAINER_8BIT (0 << OCDFMTDEF_CONTAINER_SHIFT)
+#define OCDFMTDEF_CONTAINER_16BIT (1 << OCDFMTDEF_CONTAINER_SHIFT)
+#define OCDFMTDEF_CONTAINER_24BIT (2 << OCDFMTDEF_CONTAINER_SHIFT)
+#define OCDFMTDEF_CONTAINER_32BIT (3 << OCDFMTDEF_CONTAINER_SHIFT)
+/* 4 (0x008000) reserved */
+#define OCDFMTDEF_CONTAINER_48BIT (5 << OCDFMTDEF_CONTAINER_SHIFT)
+/* 6 (0x00C000) reserved */
+#define OCDFMTDEF_CONTAINER_64BIT (7 << OCDFMTDEF_CONTAINER_SHIFT)
+
+/**** Bits 0-5 contain the total number of component bits minus one. ****/
+/* To calculate the number of bits for each RGBA component, use the following
+ * formula:
+ *
+ * green bits = int((color bits + 2) / 3)
+ * blue bits = int((color bits - green bits) / 2)
+ * red bits = color bits - green bits - blue bits
+ * alpha bits (when present) = container size - color bits
+ *
+ * Ex. 1: RGB16 -> 16 bits
+ * green bits = int((16 + 2) / 3) = 6
+ * blue bits = int((16 - 6) / 2) = 5
+ * red bits = 16 - 6 - 5 = 5
+ * alpha bits = n/a
+ * Ex. 2: ARGB16 -> 16 bits
+ * green bits = int((16 + 2) / 3) = 6
+ * blue bits = int((16 - 6) / 2) = 5
+ * red bits = 16 - 6 - 5 = 5
+ * alpha bits = 24 - 16 = 8
+ * Ex. 3: RGB32 -> 32 bits
+ * green bits = int((32 + 2) / 3) = 11
+ * blue bits = int((32 - 11) / 2) = 10
+ * red bits = 32 - 11 - 10 = 11
+ * alpha bits = n/a
+ *
+ * For planar formats, the container indicates the total number of bits on the
+ * subsampled boundary, while the component bits are the average number of
+ * bits per pixel.
+ *
+ * Ex. 1: YV12 -> YCbCr 4:2:0 w/8-bit samples -> 4x8 + 2x8 = 48 bit container
+ * 48 bits / 4 pixels = 12 bpp
+ * Ex. 2: NV16 -> YCbCr 4:2:2 w/8-bit samples -> 2x8 + 2x8 = 32 bit container
+ * 24 bits / 2 pixels = 16 bpp
+ */
+#define OCDFMTDEF_COMPONENTSIZEMINUS1_SHIFT 0
+#define OCDFMTDEF_COMPONENTSIZEMINUS1_MASK \
+ (0x3F << OCDFMTDEF_COMPONENTSIZEMINUS1_SHIFT)
+
+
+/*
+ * The formats below are constructed from the definitions above. However, not
+ * all formats possible are specified (and named) below. The other formats
+ * which can be uniquely formed using the above definitions are legitimate
+ * formats, and may be used as well.
+ */
+enum ocdformat {
+ OCDFMT_UNKNOWN = -1,
+ OCDFMT_NONE = OCDFMT_UNKNOWN,
+
+ /*** Alpha only ***/
+ /** Packed **/
+ OCDFMT_ALPHA1 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_ALPHA |
+ OCDFMTDEF_ALPHA_COMPONENTS_1 |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (1 - 1),
+ OCDFMT_ALPHA2 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_ALPHA |
+ OCDFMTDEF_ALPHA_COMPONENTS_1 |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (2 - 1),
+ OCDFMT_ALPHA4 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_ALPHA |
+ OCDFMTDEF_ALPHA_COMPONENTS_1 |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (4 - 1),
+ OCDFMT_ALPHA8 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_ALPHA |
+ OCDFMTDEF_ALPHA_COMPONENTS_1 |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (8 - 1),
+ /* Sub-pixel */
+ OCDFMT_ALPHA4x1 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_ALPHA |
+ OCDFMTDEF_ALPHA_COMPONENTS_4 |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (4 - 1),
+ OCDFMT_ALPHA3x8 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_ALPHA |
+ OCDFMTDEF_ALPHA_COMPONENTS_3 |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_24BIT |
+ (24 - 1),
+ OCDFMT_ALPHA4x8 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_ALPHA |
+ OCDFMTDEF_ALPHA_COMPONENTS_4 |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_32BIT |
+ (32 - 1),
+
+ /*** Monochrome ***/
+ /** Packed **/
+ OCDFMT_MONO1 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_MONO |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (1 - 1),
+ OCDFMT_MONO2 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_MONO |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (2 - 1),
+ OCDFMT_MONO4 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_MONO |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (4 - 1),
+ OCDFMT_MONO8 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_MONO |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (8 - 1),
+
+ /*** Palettized (look-up-table) ***/
+ /** Packed **/
+ OCDFMT_LUT1 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_LUT |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (1 - 1),
+ OCDFMT_LUT2 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_LUT |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (2 - 1),
+ OCDFMT_LUT4 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_LUT |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (4 - 1),
+ OCDFMT_LUT8 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_LUT |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_8BIT |
+ (8 - 1),
+
+ /*** RGB ***/
+ /** Packed **/
+ /* No subsampling */
+ OCDFMT_RGB12 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_RGB |
+ OCDFMTDEF_SUBSAMPLE_NONE |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_16BIT |
+ (12 - 1), /* (15):4:4:4 */
+ OCDFMT_xRGB12 = OCDFMT_RGB12,
+ OCDFMT_1RGB12 = OCDFMT_xRGB12,
+ OCDFMT_0RGB12 = OCDFMT_xRGB12 |
+ OCDFMTDEF_FILL_EMPTY_0, /* (0):4:4:4 */
+
+ OCDFMT_BGR12 = OCDFMT_RGB12 |
+ OCDFMTDEF_REVERSED, /* (15):4:4:4 */
+ OCDFMT_xBGR12 = OCDFMT_BGR12,
+ OCDFMT_1BGR12 = OCDFMT_xBGR12,
+ OCDFMT_0BGR12 = OCDFMT_xBGR12 |
+ OCDFMTDEF_FILL_EMPTY_0, /* (0):4:4:4 */
+
+ OCDFMT_RGBx12 = OCDFMT_xRGB12 |
+ OCDFMTDEF_LEFT_JUSTIFIED, /* 4:4:4:(15) */
+ OCDFMT_RGB112 = OCDFMT_RGBx12,
+ OCDFMT_RGB012 = OCDFMT_RGBx12 |
+ OCDFMTDEF_FILL_EMPTY_0, /* 4:4:4:(0) */
+
+ OCDFMT_BGRx12 = OCDFMT_xRGB12 |
+ OCDFMTDEF_LEFT_JUSTIFIED |
+ OCDFMTDEF_REVERSED, /* 4:4:4:(15) */
+ OCDFMT_BGR112 = OCDFMT_BGRx12,
+ OCDFMT_BGR012 = OCDFMT_BGRx12 |
+ OCDFMTDEF_FILL_EMPTY_0, /* 4:4:4:(0) */
+
+ OCDFMT_RGB15 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_RGB |
+ OCDFMTDEF_SUBSAMPLE_NONE |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_16BIT |
+ (15 - 1), /* (1):5:5:5 */
+ OCDFMT_xRGB15 = OCDFMT_RGB15,
+ OCDFMT_1RGB15 = OCDFMT_xRGB15,
+ OCDFMT_0RGB15 = OCDFMT_xRGB15 |
+ OCDFMTDEF_FILL_EMPTY_0, /* (0):5:5:5 */
+
+ OCDFMT_BGR15 = OCDFMT_RGB15 |
+ OCDFMTDEF_REVERSED, /* (1):5:5:5 */
+ OCDFMT_xBGR15 = OCDFMT_BGR15,
+ OCDFMT_1BGR15 = OCDFMT_xBGR15,
+ OCDFMT_0BGR15 = OCDFMT_xBGR15 |
+ OCDFMTDEF_FILL_EMPTY_0, /* (0):5:5:5 */
+
+ OCDFMT_RGBx15 = OCDFMT_RGB15 |
+ OCDFMTDEF_LEFT_JUSTIFIED, /* 5:5:5:(1) */
+ OCDFMT_RGB115 = OCDFMT_RGBx15,
+ OCDFMT_RGB015 = OCDFMT_RGBx15 |
+ OCDFMTDEF_FILL_EMPTY_0, /* 5:5:5:(0) */
+
+ OCDFMT_BGRx15 = OCDFMT_RGB15 |
+ OCDFMTDEF_LEFT_JUSTIFIED |
+ OCDFMTDEF_REVERSED, /* 5:5:5:(1) */
+ OCDFMT_BGR115 = OCDFMT_BGRx15,
+ OCDFMT_BGR015 = OCDFMT_BGRx15 |
+ OCDFMTDEF_FILL_EMPTY_0, /* 5:5:5:(0) */
+
+ OCDFMT_RGB16 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_RGB |
+ OCDFMTDEF_SUBSAMPLE_NONE |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_16BIT |
+ (16 - 1), /* 5:6:5 */
+ OCDFMT_BGR16 = OCDFMT_RGB16 |
+ OCDFMTDEF_REVERSED, /* 5:6:5 */
+
+ OCDFMT_RGB24 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_RGB |
+ OCDFMTDEF_SUBSAMPLE_NONE |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_24BIT |
+ (24 - 1), /* 8:8:8 */
+ OCDFMT_BGR24 = OCDFMT_RGB24 |
+ OCDFMTDEF_REVERSED, /* 8:8:8 */
+
+ OCDFMT_xRGB16 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_RGB |
+ OCDFMTDEF_SUBSAMPLE_NONE |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_24BIT |
+ (16 - 1), /* (255):5:6:5 */
+ OCDFMT_1RGB16 = OCDFMT_xRGB16,
+ OCDFMT_0RGB16 = OCDFMT_xRGB16 |
+ OCDFMTDEF_FILL_EMPTY_0, /* (0):5:6:5 */
+
+ OCDFMT_xBGR16 = OCDFMT_xRGB16 |
+ OCDFMTDEF_REVERSED, /* (255):5:6:5 */
+ OCDFMT_1BGR16 = OCDFMT_xBGR16,
+ OCDFMT_0BGR16 = OCDFMT_xBGR16 |
+ OCDFMTDEF_FILL_EMPTY_0, /* (0):5:6:5 */
+
+ OCDFMT_RGBx16 = OCDFMT_xRGB16 |
+ OCDFMTDEF_LEFT_JUSTIFIED, /* 5:6:5:(255) */
+ OCDFMT_RGB116 = OCDFMT_RGBx16,
+ OCDFMT_RGB016 = OCDFMT_RGBx16 |
+ OCDFMTDEF_FILL_EMPTY_0, /* 5:6:5:(0) */
+
+ OCDFMT_BGRx16 = OCDFMT_xRGB16 |
+ OCDFMTDEF_LEFT_JUSTIFIED |
+ OCDFMTDEF_REVERSED, /* 5:6:5:(255) */
+ OCDFMT_BGR116 = OCDFMT_BGRx16,
+ OCDFMT_BGR016 = OCDFMT_BGRx16 |
+ OCDFMTDEF_FILL_EMPTY_0, /* 5:6:5:(0) */
+
+ OCDFMT_xRGB24 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_RGB |
+ OCDFMTDEF_SUBSAMPLE_NONE |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_32BIT |
+ (24 - 1), /* (255):8:8:8 */
+ OCDFMT_1RGB24 = OCDFMT_xRGB24,
+ OCDFMT_0RGB24 = OCDFMT_xRGB24 |
+ OCDFMTDEF_FILL_EMPTY_0, /* (0):8:8:8 */
+
+ OCDFMT_xBGR24 = OCDFMT_xRGB24 |
+ OCDFMTDEF_REVERSED, /* (255):8:8:8 */
+ OCDFMT_1BGR24 = OCDFMT_xBGR24,
+ OCDFMT_0BGR24 = OCDFMT_xBGR24 |
+ OCDFMTDEF_FILL_EMPTY_0, /* (0):8:8:8 */
+
+ OCDFMT_RGBx24 = OCDFMT_xRGB24 |
+ OCDFMTDEF_LEFT_JUSTIFIED, /* 8:8:8:(255) */
+ OCDFMT_RGB124 = OCDFMT_RGBx24,
+ OCDFMT_RGB024 = OCDFMT_RGBx24 |
+ OCDFMTDEF_FILL_EMPTY_0, /* 8:8:8:(0) */
+
+ OCDFMT_BGRx24 = OCDFMT_xRGB24 |
+ OCDFMTDEF_LEFT_JUSTIFIED |
+ OCDFMTDEF_REVERSED, /* 8:8:8:(255) */
+ OCDFMT_BGR124 = OCDFMT_BGRx24,
+ OCDFMT_BGR024 = OCDFMT_BGRx24 |
+ OCDFMTDEF_FILL_EMPTY_0, /* 8:8:8:(0) */
+
+ /* Premultiplied ARGB */
+ OCDFMT_ARGB12 = OCDFMT_xRGB12 |
+ OCDFMTDEF_ALPHA, /* 4:4:4:4 */
+ OCDFMT_ABGR12 = OCDFMT_xBGR12 |
+ OCDFMTDEF_ALPHA, /* 4:4:4:4 */
+ OCDFMT_RGBA12 = OCDFMT_RGBx12 |
+ OCDFMTDEF_ALPHA, /* 4:4:4:4 */
+ OCDFMT_BGRA12 = OCDFMT_BGRx12 |
+ OCDFMTDEF_ALPHA, /* 4:4:4:4 */
+
+ OCDFMT_ARGB16 = OCDFMT_xRGB16 |
+ OCDFMTDEF_ALPHA, /* 8:5:6:5 */
+ OCDFMT_ABGR16 = OCDFMT_ARGB16 |
+ OCDFMTDEF_REVERSED, /* 8:5:6:5 */
+ OCDFMT_RGBA16 = OCDFMT_ARGB16 |
+ OCDFMTDEF_LEFT_JUSTIFIED, /* 5:6:5:8 */
+ OCDFMT_BGRA16 = OCDFMT_ARGB16 |
+ OCDFMTDEF_LEFT_JUSTIFIED |
+ OCDFMTDEF_REVERSED, /* 5:6:5:8 */
+
+ OCDFMT_ARGB24 = OCDFMT_xRGB24 |
+ OCDFMTDEF_ALPHA, /* 8:8:8:8 */
+ OCDFMT_ABGR24 = OCDFMT_xBGR24 |
+ OCDFMTDEF_ALPHA, /* 8:8:8:8 */
+ OCDFMT_RGBA24 = OCDFMT_RGBx24 |
+ OCDFMTDEF_ALPHA, /* 8:8:8:8 */
+ OCDFMT_BGRA24 = OCDFMT_BGRx24 |
+ OCDFMTDEF_ALPHA, /* 8:8:8:8 */
+
+ /* Non-premultiplied ARGB */
+ OCDFMT_nARGB12 = OCDFMT_ARGB12 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_ARGB12_NON_PREMULT = OCDFMT_nARGB12,
+
+ OCDFMT_nABGR12 = OCDFMT_ABGR12 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_ABGR12_NON_PREMULT = OCDFMT_nABGR12,
+
+ OCDFMT_nRGBA12 = OCDFMT_RGBA12 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_RGBA12_NON_PREMULT = OCDFMT_nRGBA12,
+
+ OCDFMT_nBGRA12 = OCDFMT_BGRA12 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_BGRA12_NON_PREMULT = OCDFMT_nBGRA12,
+
+ OCDFMT_ARGB15 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_RGB |
+ OCDFMTDEF_ALPHA |
+ OCDFMTDEF_NON_PREMULT |
+ OCDFMTDEF_SUBSAMPLE_NONE |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_16BIT |
+ (15 - 1), /* 1:5:5:5 - "normal"
+ format is not
+ premultiplied */
+ OCDFMT_nARGB15 = OCDFMT_ARGB15,
+ OCDFMT_ARGB15_NON_PREMULT = OCDFMT_nARGB15,
+
+ OCDFMT_ABGR15 = OCDFMT_ARGB15 |
+ OCDFMTDEF_REVERSED, /* 1:5:5:5 - "normal"
+ format is not
+ premultiplied */
+ OCDFMT_nABGR15 = OCDFMT_ABGR15,
+ OCDFMT_ABGR15_NON_PREMULT = OCDFMT_nABGR15,
+
+ OCDFMT_RGBA15 = OCDFMT_ARGB15 |
+ OCDFMTDEF_LEFT_JUSTIFIED, /* 5:5:5:1 - "normal"
+ format is not
+ premultiplied */
+ OCDFMT_nRGBA15 = OCDFMT_RGBA15,
+ OCDFMT_RGBA15_NON_PREMULT = OCDFMT_nRGBA15,
+
+ OCDFMT_BGRA15 = OCDFMT_ARGB15 |
+ OCDFMTDEF_LEFT_JUSTIFIED |
+ OCDFMTDEF_REVERSED, /* 5:5:5:1 - "normal"
+ format is not
+ premultiplied */
+ OCDFMT_nBGRA15 = OCDFMT_BGRA15,
+ OCDFMT_BGRA15_NON_PREMULT = OCDFMT_nRGBA15,
+
+ OCDFMT_nARGB16 = OCDFMT_ARGB16 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_ARGB16_NON_PREMULT = OCDFMT_nARGB16,
+
+ OCDFMT_nABGR16 = OCDFMT_ABGR16 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_ABGR16_NON_PREMULT = OCDFMT_nABGR16,
+
+ OCDFMT_nRGBA16 = OCDFMT_RGBA16 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_RGBA16_NON_PREMULT = OCDFMT_nRGBA16,
+
+ OCDFMT_nBGRA16 = OCDFMT_BGRA16 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_BGRA16_NON_PREMULT = OCDFMT_nBGRA16,
+
+ OCDFMT_nARGB24 = OCDFMT_ARGB24 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_ARGB24_NON_PREMULT = OCDFMT_nARGB24,
+
+ OCDFMT_nABGR24 = OCDFMT_ABGR24 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_ABGR24_NON_PREMULT = OCDFMT_nABGR24,
+
+ OCDFMT_nRGBA24 = OCDFMT_RGBA24 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_RGBA24_NON_PREMULT = OCDFMT_nRGBA24,
+
+ OCDFMT_nBGRA24 = OCDFMT_BGRA24 |
+ OCDFMTDEF_NON_PREMULT,
+ OCDFMT_BGRA24_NON_PREMULT = OCDFMT_nBGRA24,
+
+ /*** YCbCr ***/
+ /** Packed **/
+ /* YCbCr 4:2:2 */
+ OCDFMT_UYVY = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_422_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_HORZ_ALIGNED |
+ OCDFMTDEF_PACKED |
+ OCDFMTDEF_CONTAINER_32BIT |
+ (16 - 1),
+ OCDFMT_UYVY_601 = OCDFMT_UYVY |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_UYVY_709 = OCDFMT_UYVY |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+ OCDFMT_Y422 = OCDFMT_UYVY,
+ OCDFMT_Y422_601 = OCDFMT_UYVY_601,
+ OCDFMT_Y422_709 = OCDFMT_UYVY_709,
+
+ OCDFMT_VYUY = OCDFMT_UYVY |
+ OCDFMTDEF_REVERSED,
+ OCDFMT_VYUY_601 = OCDFMT_VYUY |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_VYUY_709 = OCDFMT_VYUY |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+ OCDFMT_YUYV = OCDFMT_UYVY |
+ OCDFMTDEF_LEFT_JUSTIFIED,
+ OCDFMT_YUYV_601 = OCDFMT_YUYV |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_YUYV_709 = OCDFMT_YUYV |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+ OCDFMT_YUY2 = OCDFMT_YUYV,
+ OCDFMT_YUY2_601 = OCDFMT_YUYV_601,
+ OCDFMT_YUY2_709 = OCDFMT_YUYV_709,
+
+ OCDFMT_YVYU = OCDFMT_VYUY |
+ OCDFMTDEF_LEFT_JUSTIFIED,
+ OCDFMT_YVYU_601 = OCDFMT_YVYU |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_YVYU_709 = OCDFMT_YVYU |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+ /** 3-plane **/
+ /* YCbCr 4:2:2 */
+ OCDFMT_YV16 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_422_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_HORZ_ALIGNED |
+ OCDFMTDEF_3_PLANE_STACKED |
+ OCDFMTDEF_CONTAINER_32BIT |
+ (16 - 1),
+ OCDFMT_YV16_601 = OCDFMT_YV16 |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_YV16_709 = OCDFMT_YV16 |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+ /* YCbCr 4:2:0 */
+ OCDFMT_IYUV = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_420_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_HORZ_ALIGNED |
+ OCDFMTDEF_3_PLANE_STACKED |
+ OCDFMTDEF_CONTAINER_48BIT |
+ (12 - 1),
+ OCDFMT_IYUV_601 = OCDFMT_IYUV |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_IYUV_709 = OCDFMT_IYUV |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+ OCDFMT_I420 = OCDFMT_IYUV,
+ OCDFMT_I420_601 = OCDFMT_IYUV_601,
+ OCDFMT_I420_709 = OCDFMT_IYUV_709,
+
+ OCDFMT_YV12 = OCDFMT_IYUV |
+ OCDFMTDEF_REVERSED,
+ OCDFMT_YV12_601 = OCDFMT_YV12 |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_YV12_709 = OCDFMT_YV12 |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+ OCDFMT_IMC3 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_420_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_HORZ_ALIGNED |
+ OCDFMTDEF_3_PLANE_STACKED |
+ OCDFMTDEF_LEFT_JUSTIFIED | /* Indicates wasted
+ space to the
+ right */
+ OCDFMTDEF_CONTAINER_48BIT |
+ (12 - 1),
+ OCDFMT_IMC3_601 = OCDFMT_IMC3 |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_IMC3_709 = OCDFMT_IMC3 |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+ OCDFMT_IMC1 = OCDFMT_IMC3 |
+ OCDFMTDEF_REVERSED,
+ OCDFMT_IMC1_601 = OCDFMT_IMC1 |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_IMC1_709 = OCDFMT_IMC1 |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+ OCDFMT_IMC4 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_YCbCr |
+ OCDFMTDEF_STD_ITUR_601_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_420_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_HORZ_ALIGNED |
+ OCDFMTDEF_3_PLANE_SIDE_BY_SIDE_YCbCr |
+ OCDFMTDEF_CONTAINER_48BIT |
+ (12 - 1),
+ OCDFMT_IMC4_601 = OCDFMT_IMC4 |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_IMC4_709 = OCDFMT_IMC4 |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+ OCDFMT_IMC2 = OCDFMT_IMC4 |
+ OCDFMTDEF_REVERSED,
+ OCDFMT_IMC2_601 = OCDFMT_IMC2 |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_IMC2_709 = OCDFMT_IMC2 |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+ /** 2-plane **/
+ /* YCbCr 4:2:2 */
+ OCDFMT_NV16 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_422_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_HORZ_ALIGNED |
+ OCDFMTDEF_2_PLANE_YCbCr |
+ OCDFMTDEF_CONTAINER_32BIT |
+ (16 - 1),
+ OCDFMT_NV16_601 = OCDFMT_NV16 |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_NV16_709 = OCDFMT_NV16 |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+ OCDFMT_NV61 = OCDFMT_NV16 |
+ OCDFMTDEF_REVERSED,
+ OCDFMT_NV61_601 = OCDFMT_NV61 |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_NV61_709 = OCDFMT_NV61 |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+ /* YCbCr 4:2:0 */
+ OCDFMT_NV12 = OCDFMTDEF_VENDOR_ALL |
+ OCDFMTDEF_CS_YCbCr |
+ OCDFMTDEF_STD_ITUR_601_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_420_YCbCr |
+ OCDFMTDEF_SUBSAMPLE_HORZ_ALIGNED |
+ OCDFMTDEF_2_PLANE_YCbCr |
+ OCDFMTDEF_CONTAINER_48BIT |
+ (12 - 1),
+ OCDFMT_NV12_601 = OCDFMT_NV12 |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_NV12_709 = OCDFMT_NV12 |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+ OCDFMT_NV21 = OCDFMT_NV12 |
+ OCDFMTDEF_REVERSED,
+ OCDFMT_NV21_601 = OCDFMT_NV21 |
+ OCDFMTDEF_STD_ITUR_601_YCbCr,
+ OCDFMT_NV21_709 = OCDFMT_NV21 |
+ OCDFMTDEF_STD_ITUR_709_YCbCr,
+
+#ifdef OCD_EXTERNAL_INCLUDE
+#include OCD_EXTERNAL_INCLUDE
+#endif
+};
+
+#endif /* OCD_H */
diff --git a/include/linux/omap_ion.h b/include/linux/omap_ion.h
--- /dev/null
+++ b/include/linux/omap_ion.h
@@ -0,0 +1,103 @@
+/*
+ * include/linux/omap_ion.h
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_OMAP_ION_H
+#define _LINUX_OMAP_ION_H
+
+#include <linux/types.h>
+
+
+/**
+ * struct omap_ion_tiler_alloc_data - metadata passed from userspace for allocations
+ * @w: width of the allocation
+ * @h: height of the allocation
+ * @fmt: format of the data (8, 16, 32bit or page)
+ * @flags: flags passed to heap
+ * @stride: stride of the allocation, returned to caller from kernel
+ * @handle: pointer that will be populated with a cookie to use to refer
+ * to this allocation
+ *
+ * Provided by userspace as an argument to the ioctl
+ */
+struct omap_ion_tiler_alloc_data {
+ size_t w;
+ size_t h;
+ int fmt;
+ unsigned int flags;
+ struct ion_handle *handle;
+ size_t stride;
+ size_t offset;
+ u32 out_align;
+ u32 token;
+};
+
+#ifdef __KERNEL__
+int omap_ion_tiler_alloc(struct ion_client *client,
+ struct omap_ion_tiler_alloc_data *data);
+int omap_ion_nonsecure_tiler_alloc(struct ion_client *client,
+ struct omap_ion_tiler_alloc_data *data);
+/* given a handle in the tiler, return a list of tiler pages that back it */
+int omap_tiler_pages(struct ion_client *client, struct ion_handle *handle,
+ int *n, u32 **tiler_pages);
+int omap_ion_fd_to_handles(int fd, struct ion_client **client,
+ struct ion_handle **handles,
+ int *num_handles);
+int omap_tiler_vinfo(struct ion_client *client,
+ struct ion_handle *handle, unsigned int *vstride,
+ unsigned int *vsize);
+
+int omap_ion_share_fd_to_buffers(int fd, struct ion_buffer **buffers,
+ int *num_handles);
+
+extern struct ion_device *omap_ion_device;
+#endif /* __KERNEL__ */
+
+/* additional heaps used only on omap */
+enum {
+ OMAP_ION_HEAP_TYPE_TILER = ION_HEAP_TYPE_CUSTOM + 1,
+ OMAP_ION_HEAP_TYPE_TILER_RESERVATION,
+};
+
+#define OMAP_ION_HEAP_TILER_MASK (1 << OMAP_ION_HEAP_TYPE_TILER)
+
+enum {
+ OMAP_ION_TILER_ALLOC,
+};
+
+/**
+ * These should match the defines in the tiler driver
+ */
+enum {
+ TILER_PIXEL_FMT_MIN = 0,
+ TILER_PIXEL_FMT_8BIT = 0,
+ TILER_PIXEL_FMT_16BIT = 1,
+ TILER_PIXEL_FMT_32BIT = 2,
+ TILER_PIXEL_FMT_PAGE = 3,
+ TILER_PIXEL_FMT_MAX = 3
+};
+
+/**
+ * List of heaps in the system
+ */
+enum {
+ OMAP_ION_HEAP_SYSTEM,
+ OMAP_ION_HEAP_TILER,
+ OMAP_ION_HEAP_SECURE_INPUT,
+ OMAP_ION_HEAP_NONSECURE_TILER,
+ OMAP_ION_HEAP_TILER_RESERVATION,
+};
+
+#endif /* _LINUX_ION_H */
diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
--- a/include/linux/omapfb.h
+++ b/include/linux/omapfb.h
#define __LINUX_OMAPFB_H__
#include <uapi/linux/omapfb.h>
+#ifdef CONFIG_ARCH_OMAP1
+#define OMAPFB_PLANE_NUM 1
+#else
+#define OMAPFB_PLANE_NUM 3
+#endif
+struct omapfb_mem_region {
+ u32 paddr;
+ void __iomem *vaddr;
+ unsigned long size;
+ u8 type; /* OMAPFB_PLANE_MEM_* */
+ enum omapfb_color_format format;/* OMAPFB_COLOR_* */
+ unsigned format_used:1; /* Must be set when format is set.
+ * Needed b/c of the badly chosen 0
+ * base for OMAPFB_COLOR_* values
+ */
+ unsigned alloc:1; /* allocated by the driver */
+ unsigned map:1; /* kernel mapped by the driver */
+};
+
+struct omapfb_mem_desc {
+ int region_cnt;
+ struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
+};
struct omap_lcd_config {
char panel_name[16];
struct omapfb_platform_data {
struct omap_lcd_config lcd;
+ struct omapfb_mem_desc mem_desc;
};
+extern void omapfb_set_platform_data(struct omapfb_platform_data *data);
+
void __init omapfb_set_lcd_config(const struct omap_lcd_config *config);
+/* helper methods that may be used by other modules */
+enum omap_color_mode;
+int omapfb_mode_to_dss_mode(struct fb_var_screeninfo *var,
+ enum omap_color_mode *mode);
+struct omap_video_timings;
+void omapfb_fb2dss_timings(struct fb_videomode *fb_timings,
+ struct omap_video_timings *dss_timings);
+void omapfb_dss2fb_timings(struct omap_video_timings *dss_timings,
+ struct fb_videomode *fb_timings);
#endif /* __OMAPFB_H */
index 8db5ae03b6e3f679c16988e492e8241f1567b2f5..416c1d2abe630c065ad8ddf8df38733d2421b0ca 100644 (file)
u8 version;
u8 txnumevt;
u8 rxnumevt;
+ u32 tx_dismod;
+ u32 rx_dismod;
};
enum {
MCASP_VERSION_1 = 0, /* DM646x */
MCASP_VERSION_2, /* DA8xx/OMAPL1x */
MCASP_VERSION_3, /* TI81xx/AM33xx */
+ MCASP_VERSION_4, /* DRA7xxx */
};
enum mcbsp_clk_input_pin {
diff --git a/include/linux/platform_data/omap_gcx.h b/include/linux/platform_data/omap_gcx.h
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * arch/arm/plat-omap/include/plat/omap_gcx.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef OMAP_GCX_H
+#define OMAP_GCX_H
+
+struct omap_gcx_platform_data {
+ bool is_hw_present;
+ void *regbase;
+ /*bool (*was_context_lost)(struct device *dev);*/
+ int (*get_context_loss_count)(struct device *dev);
+ /* device scale */
+ int (*scale_dev)(struct device *dev, unsigned long freq);
+ /* bandwith */
+ int (*set_bw)(struct device *dev, unsigned long v);
+};
+
+#endif
index 7bc732ce6e50c5793f3db777d07a2ced422f91ef..8f3063f458d9e39e2535be5594dc3c06b4dd1f97 100644 (file)
static inline int regulator_set_voltage_tol(struct regulator *regulator,
int new_uV, int tol_uV)
{
- return regulator_set_voltage(regulator,
- new_uV - tol_uV, new_uV + tol_uV);
+ if (regulator_set_voltage(regulator, new_uV, new_uV + tol_uV) == 0)
+ return 0;
+ else
+ return regulator_set_voltage(regulator,
+ new_uV - tol_uV, new_uV + tol_uV);
}
static inline int regulator_is_supported_voltage_tol(struct regulator *regulator,
index b09c37e04a91f64f007a0699cf89d3adc1b97483..8e863b3e802676fae11041af7381a10adbc58b5f 100644 (file)
struct usb_gadget_driver gadget_driver;
};
+extern int usb_composite_probe_ready(struct usb_composite_driver *driver);
extern int usb_composite_probe(struct usb_composite_driver *driver);
extern void usb_composite_unregister(struct usb_composite_driver *driver);
extern void usb_composite_setup_continue(struct usb_composite_dev *cdev);
index 5615f4d8272499d4cbc5d1c9850d0cc06e9bf319..64c78a56d4bbcf10ed339c85211f9a643abfc134 100644 (file)
};
#if (defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_DWC3_MODULE))
-extern int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status);
+extern int dwc3_omap_mailbox(struct device *dev, enum omap_dwc3_vbus_id_status status);
#else
-static inline int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+static inline int dwc3_omap_mailbox(struct device *dev, enum omap_dwc3_vbus_id_status status)
{
return -ENODEV;
}
index 0af6569b8cc60778c619f3a059d4b78ff49f07f4..29ae631d8a90ab1b6b7c90da5d907b7d931261bf 100644 (file)
extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
extern void usb_del_gadget_udc(struct usb_gadget *gadget);
+extern int usb_gadget_probe_driver_ready(struct usb_gadget_driver *driver);
+
/*-------------------------------------------------------------------------*/
diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h
--- /dev/null
+++ b/include/linux/usb/of.h
@@ -0,0 +1,36 @@
+/*
+ * OF helpers for usb devices.
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_USB_OF_H
+#define __LINUX_USB_OF_H
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/phy.h>
+
+#ifdef CONFIG_OF
+enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np);
+enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np);
+enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np);
+#else
+static inline enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np)
+{
+ return USBPHY_INTERFACE_MODE_UNKNOWN;
+}
+
+static inline enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
+{
+ return USB_DR_MODE_UNKNOWN;
+}
+
+static inline enum usb_device_speed
+of_usb_get_maximum_speed(struct device_node *np)
+{
+ return USB_SPEED_UNKNOWN;
+}
+#endif
+
+#endif /* __LINUX_USB_OF_H */
index 27b5b8c931b0bd70d1e20d636b08beb6ebe3dc64..8574dd8a27968f3700ba92914c4ee16b586aae8a 100644 (file)
u32 __iomem *dev_conf;
u32 __iomem *otghs_control;
u32 __iomem *phy_power;
+ u32 __iomem *ctrl_core_srcomp_north_side;
+ u32 __iomem *dummy_reg;
struct clk *sys_clk;
};
/* To differentiate ctrl module IP having either mailbox or USB3 PHY power */
-#define OMAP_CTRL_DEV_TYPE1 0x1
-#define OMAP_CTRL_DEV_TYPE2 0x2
+#define OMAP_CTRL_DEV_TYPE1 0x1 /* mailbox */
+#define OMAP_CTRL_DEV_TYPE2 0x2 /* has a usb2 and usb3 phy */
+#define OMAP_CTRL_DEV_TYPE3 0x3 /* has only a usb2 phy */
#define OMAP_CTRL_DEV_PHY_PD BIT(0)
#define OMAP_CTRL_USB3_PHY_TX_RX_POWERON 0x3
#define OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF 0x0
+#define OMAP_CTRL_USB_SRCOMP_NORTH_SIDE_PD BIT(28)
+
#if IS_ENABLED(CONFIG_OMAP_CONTROL_USB)
extern struct device *omap_get_control_dev(void);
extern void omap_control_usb_phy_power(struct device *dev, int on);
index 6ae29360e1d2a1be611a6ec188af9addc68cabd5..f53932389f8b9a5d5f65a7eaf1b67290bc3c6192 100644 (file)
struct clk *sys_clk;
struct clk *optclk;
u8 is_suspended:1;
+ struct device_node *control_node;
};
#define phy_to_omapusb(x) container_of((x), struct omap_usb, phy)
index e8a5fe87c6bdeb0700310503defff73ee630864a..4e8bfbb8024c110413bcc988aca6910723105325 100644 (file)
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
/* for OTG controller drivers (and maybe other stuff) */
extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
+enum usb_dr_mode {
+ USB_DR_MODE_UNKNOWN,
+ USB_DR_MODE_HOST,
+ USB_DR_MODE_PERIPHERAL,
+ USB_DR_MODE_OTG,
+};
+
#endif /* __LINUX_USB_OTG_H */
index 15847cbdb512b804347b3219d60c7b96563fd9bd..f4cb438165356c5dfc84793e80b73035bdb3dc63 100644 (file)
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
#include <linux/notifier.h>
#include <linux/usb.h>
+enum usb_phy_interface {
+ USBPHY_INTERFACE_MODE_UNKNOWN,
+ USBPHY_INTERFACE_MODE_UTMI,
+ USBPHY_INTERFACE_MODE_UTMIW,
+ USBPHY_INTERFACE_MODE_ULPI,
+ USBPHY_INTERFACE_MODE_SERIAL,
+ USBPHY_INTERFACE_MODE_HSIC,
+};
+
enum usb_phy_events {
USB_EVENT_NONE, /* no events or cable disconnected */
USB_EVENT_VBUS, /* vbus valid event */
/* helpers for direct access thru low-level io interface */
static inline int usb_phy_io_read(struct usb_phy *x, u32 reg)
{
- if (x->io_ops && x->io_ops->read)
+ if (x && x->io_ops && x->io_ops->read)
return x->io_ops->read(x, reg);
return -EINVAL;
static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg)
{
- if (x->io_ops && x->io_ops->write)
+ if (x && x->io_ops && x->io_ops->write)
return x->io_ops->write(x, val, reg);
return -EINVAL;
static inline int
usb_phy_init(struct usb_phy *x)
{
- if (x->init)
+ if (x && x->init)
return x->init(x);
return 0;
static inline void
usb_phy_shutdown(struct usb_phy *x)
{
- if (x->shutdown)
+ if (x && x->shutdown)
x->shutdown(x);
}
static inline int
usb_phy_set_suspend(struct usb_phy *x, int suspend)
{
- if (x->set_suspend != NULL)
+ if (x && x->set_suspend != NULL)
return x->set_suspend(x, suspend);
else
return 0;
static inline int
usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
{
- if (x->notify_connect)
+ if (x && x->notify_connect)
return x->notify_connect(x, speed);
else
return 0;
static inline int
usb_phy_notify_disconnect(struct usb_phy *x, enum usb_device_speed speed)
{
- if (x->notify_disconnect)
+ if (x && x->notify_disconnect)
return x->notify_disconnect(x, speed);
else
return 0;
index 7c97bc00ac6d9682ddd8ae32e7ce69d16f4ad116..709a1f2b237acb1ce04cf623a58374f384a7fb89 100644 (file)
#define OMAPFB_GET_VRAM_INFO OMAP_IOR(61, struct omapfb_vram_info)
#define OMAPFB_SET_TEARSYNC OMAP_IOW(62, struct omapfb_tearsync_info)
#define OMAPFB_GET_DISPLAY_INFO OMAP_IOR(63, struct omapfb_display_info)
+#define OMAPFB_ENABLEVSYNC OMAP_IOW(64, int)
#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
#define OMAPFB_CAPS_LCDC_MASK 0x00fff000
diff --git a/include/video/dsscomp.h b/include/video/dsscomp.h
--- /dev/null
+++ b/include/video/dsscomp.h
@@ -0,0 +1,734 @@
+/*
+ * include/video/dsscomp.h
+ *
+ * DSS Composition header file
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc
+ * Author: Lajos Molnar <molnar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _LINUX_DSSCOMP_H
+#define _LINUX_DSSCOMP_H
+
+#ifdef __KERNEL__
+#include <video/omapdss.h>
+#else
+
+/* exporting enumerations from arch/arm/plat-omap/include/plat/display.h */
+enum omap_plane {
+ OMAP_DSS_GFX = 0,
+ OMAP_DSS_VIDEO1 = 1,
+ OMAP_DSS_VIDEO2 = 2,
+ OMAP_DSS_VIDEO3 = 3,
+ OMAP_DSS_WB = 4,
+};
+
+enum omap_channel {
+ OMAP_DSS_CHANNEL_LCD = 0,
+ OMAP_DSS_CHANNEL_DIGIT = 1,
+ OMAP_DSS_CHANNEL_LCD2 = 2,
+};
+
+enum omap_color_mode {
+ OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */
+ OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */
+ OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */
+ OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */
+
+ /* also referred to as RGB 12-BPP, 16-bit container */
+ OMAP_DSS_COLOR_RGB12U = 1 << 4, /* xRGB12-4444 */
+ OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16-4444 */
+ OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16-565 */
+
+ /* also referred to as RGB 24-BPP, 32-bit container */
+ OMAP_DSS_COLOR_RGB24U = 1 << 7, /* xRGB24-8888 */
+ OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24-888 */
+ OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */
+ OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */
+ OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32-8888 */
+ OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32-8888 */
+
+ /* also referred to as RGBx 32 in TRM */
+ OMAP_DSS_COLOR_RGBX24 = 1 << 13, /* RGBx32-8888 */
+ OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32-8888 */
+ OMAP_DSS_COLOR_NV12 = 1 << 14, /* NV12 format: YUV 4:2:0 */
+
+ /* also referred to as RGBA12-4444 in TRM */
+ OMAP_DSS_COLOR_RGBA16 = 1 << 15, /* RGBA16-4444 */
+
+ OMAP_DSS_COLOR_RGBX12 = 1 << 16, /* RGBx16-4444 */
+ OMAP_DSS_COLOR_RGBX16 = 1 << 16, /* RGBx16-4444 */
+ OMAP_DSS_COLOR_ARGB16_1555 = 1 << 17, /* ARGB16-1555 */
+
+ /* also referred to as xRGB16-555 in TRM */
+ OMAP_DSS_COLOR_XRGB15 = 1 << 18, /* xRGB16-1555 */
+ OMAP_DSS_COLOR_XRGB16_1555 = 1 << 18, /* xRGB16-1555 */
+};
+
+/* Writeback data structures */
+enum omap_writeback_source {
+ OMAP_WB_LCD1 = 0,
+ OMAP_WB_TV = 1,
+ OMAP_WB_LCD2 = 2,
+ OMAP_WB_GFX = 3,
+ OMAP_WB_VID1 = 4,
+ OMAP_WB_VID2 = 5,
+ OMAP_WB_VID3 = 6,
+};
+
+enum omap_writeback_mode {
+ OMAP_WB_CAPTURE_MODE = 0,
+ OMAP_WB_MEM2MEM_MODE = 1,
+};
+
+enum omap_dss_trans_key_type {
+ OMAP_DSS_COLOR_KEY_GFX_DST = 0,
+ OMAP_DSS_COLOR_KEY_VID_SRC = 1,
+};
+
+enum omap_dss_display_state {
+ OMAP_DSS_DISPLAY_DISABLED = 0,
+ OMAP_DSS_DISPLAY_ACTIVE,
+ OMAP_DSS_DISPLAY_SUSPENDED,
+ OMAP_DSS_DISPLAY_TRANSITION,
+};
+
+struct omap_video_timings {
+ /* Unit: pixels */
+ __u16 x_res;
+ /* Unit: pixels */
+ __u16 y_res;
+ /* Unit: KHz */
+ __u32 pixel_clock;
+ /* Unit: pixel clocks */
+ __u16 hsw; /* Horizontal synchronization pulse width */
+ /* Unit: pixel clocks */
+ __u16 hfp; /* Horizontal front porch */
+ /* Unit: pixel clocks */
+ __u16 hbp; /* Horizontal back porch */
+ /* Unit: line clocks */
+ __u16 vsw; /* Vertical synchronization pulse width */
+ /* Unit: line clocks */
+ __u16 vfp; /* Vertical front porch */
+ /* Unit: line clocks */
+ __u16 vbp; /* Vertical back porch */
+};
+
+/* YUV to RGB color conversion info */
+struct omap_dss_cconv_coefs {
+ __s16 ry, rcr, rcb;
+ __s16 gy, gcr, gcb;
+ __s16 by, bcr, bcb;
+
+ /* Y is 16..235, UV is 16..240 if not fullrange. Otherwise 0..255 */
+ __u16 full_range;
+} __aligned(4);
+
+struct omap_dss_cpr_coefs {
+ __s16 rr, rg, rb;
+ __s16 gr, gg, gb;
+ __s16 br, bg, bb;
+};
+
+/*
+ * Stereoscopic Panel types
+ * row, column, overunder, sidebyside options
+ * are with respect to native scan order
+ */
+enum s3d_disp_type {
+ S3D_DISP_NONE = 0,
+ S3D_DISP_FRAME_SEQ,
+ S3D_DISP_ROW_IL,
+ S3D_DISP_COL_IL,
+ S3D_DISP_PIX_IL,
+ S3D_DISP_CHECKB,
+ S3D_DISP_OVERUNDER,
+ S3D_DISP_SIDEBYSIDE,
+};
+
+/* Subsampling direction is based on native panel scan order.*/
+enum s3d_disp_sub_sampling {
+ S3D_DISP_SUB_SAMPLE_NONE = 0,
+ S3D_DISP_SUB_SAMPLE_V,
+ S3D_DISP_SUB_SAMPLE_H,
+};
+
+/*
+ * Indicates if display expects left view first followed by right or viceversa
+ * For row interlaved displays, defines first row view
+ * For column interleaved displays, defines first column view
+ * For checkerboard, defines first pixel view
+ * For overunder, defines top view
+ * For sidebyside, defines west view
+ */
+enum s3d_disp_order {
+ S3D_DISP_ORDER_L = 0,
+ S3D_DISP_ORDER_R = 1,
+};
+
+/*
+ * Indicates current view
+ * Used mainly for displays that need to trigger a sync signal
+ */
+enum s3d_disp_view {
+ S3D_DISP_VIEW_L = 0,
+ S3D_DISP_VIEW_R,
+};
+
+struct s3d_disp_info {
+ enum s3d_disp_type type;
+ enum s3d_disp_sub_sampling sub_samp;
+ enum s3d_disp_order order;
+ /*
+ * Gap between left and right views
+ * For over/under units are lines
+ * For sidebyside units are pixels
+ * For other types ignored
+ */
+ unsigned int gap;
+};
+
+#endif
+
+/* copy of fb_videomode */
+struct dsscomp_videomode {
+ const char *name; /* optional */
+ __u32 refresh; /* optional */
+ __u32 xres;
+ __u32 yres;
+ __u32 pixclock;
+ __u32 left_margin;
+ __u32 right_margin;
+ __u32 upper_margin;
+ __u32 lower_margin;
+ __u32 hsync_len;
+ __u32 vsync_len;
+ __u32 sync;
+ __u32 vmode;
+ __u32 flag;
+};
+
+enum omap_dss_ilace_mode {
+ OMAP_DSS_ILACE = (1 << 0), /* interlaced vs. progressive */
+ OMAP_DSS_ILACE_SEQ = (1 << 1), /* sequential vs interleaved */
+ OMAP_DSS_ILACE_SWAP = (1 << 2), /* swap fields, e.g. TB=>BT */
+
+ OMAP_DSS_ILACE_NONE = 0,
+ OMAP_DSS_ILACE_IL_TB = OMAP_DSS_ILACE,
+ OMAP_DSS_ILACE_IL_BT = OMAP_DSS_ILACE | OMAP_DSS_ILACE_SWAP,
+ OMAP_DSS_ILACE_SEQ_TB = OMAP_DSS_ILACE_IL_TB | OMAP_DSS_ILACE_SEQ,
+ OMAP_DSS_ILACE_SEQ_BT = OMAP_DSS_ILACE_IL_BT | OMAP_DSS_ILACE_SEQ,
+};
+
+/* YUV VC1 range mapping info */
+struct dss2_vc1_range_map_info {
+ __u8 enable; /* bool */
+
+ __u8 range_y; /* 0..7 */
+ __u8 range_uv; /* 0..7 */
+} __aligned(4);
+
+/* standard rectangle */
+struct dss2_rect_t {
+ __s32 x; /* left */
+ __s32 y; /* top */
+ __u32 w; /* width */
+ __u32 h; /* height */
+} __aligned(4);
+
+/* decimation constraints */
+struct dss2_decim {
+ __u8 min_x;
+ __u8 max_x; /* 0 is same as 255 */
+ __u8 min_y;
+ __u8 max_y; /* 0 is same as 255 */
+} __aligned(4);
+
+/*
+ * A somewhat more user friendly interface to the DSS2. This is a
+ * direct interface to the DSS2 overlay and overlay_manager modules.
+ * User-space APIs are provided for HW-specific control of DSS in
+ * contrast with V4L2/FB that are more generic, but in this process
+ * omit HW-specific features.
+ *
+ * For now managers are specified by display index as opposed to manager
+ * type, so that display0 is always the default display (e.g. HDMI on
+ * panda, and LCD blaze.) For now you would need to query the displays
+ * or use sysfs to find a specific display.
+ *
+ * Userspace operations are as follows:
+ *
+ * 1) check if DSS supports an overlay configuration, use DSSCIOC_CHECK_OVL
+ * ioctl with the manager, overlay, and setup-mode information filled out.
+ * All fields should be filled out as it may influence whether DSS can
+ * display/render the overlay.
+ *
+ * If proper address information is not available, it may be possible to
+ * use a type-of-address enumeration instead for luma/rgb and chroma (if
+ * applicable) frames.
+ *
+ * Do this for each overlay before attempting to configure DSS.
+ *
+ * 2) configure DSS pipelines for display/manager using DSSCIOC_SETUP_MANAGER
+ * ioctl. You can delay applying the settings until an dss2_manager_apply()
+ * is called for the internal composition object, if the APPLY bit of setup mode
+ * is not set. However the CAPTURE/DISPLAY bits of the setup mode settings will
+ * determine if at this time a capture will take place (in case of capture
+ * only mode). You may also set up additional pipelines with
+ * dss2_overlay_setup() before this.
+ *
+ * 3) On OMAP4/5 you can use the DSS WB pipeline to copy (and convert) a buffer
+ * using DSS. Use the DSSCIOC_WB_COPY ioctl for this. This is a blocking
+ * call, and it may possibly fail if an ongoing WB capture mode has been
+ * scheduled (which is outside of the current scope of the DSS2 interface.)
+ *
+ * There is also a one-shot configuration API (DSSCIOC_SETUP_DISPC). This
+ * allows you to set-up all overlays on all managers in one call. This call
+ * performs additional functionality:
+ *
+ * - it maps userspace 1D buffers into TILER 1D for the duration of the display
+ * - it disables all overlays that were specified before, but are no longer
+ * specified
+ *
+ */
+
+/*
+ * DSS2 overlay information. This structure contains all information
+ * needed to set up the overlay for a particular buffer to be displayed
+ * at a particular orientation.
+ *
+ * The following information is deemed to be set globally, so it is not
+ * included:
+ * - whether to enable zorder (always enabled)
+ * - whether to replicate/truncate color fields (it is decided per the
+ * whole manager/overlay settings, and is enabled unless overlay is
+ * directed to WB.)
+ *
+ * There is also no support for CLUT formats
+ *
+ * Requirements:
+ *
+ * 1) 0 <= crop.x <= crop.x + crop.w <= width
+ * 2) 0 <= crop.y <= crop.y + crop.h <= height
+ * 3) win.x <= win.x + win.w and win.w >= 0
+ * 4) win.y <= win.y + win.h and win.h >= 0
+ *
+ * 5) color_mode is supported by overlay
+ * 6) requested scaling is supported by overlay and functional clocks
+ *
+ * Notes:
+ *
+ * 1) Any portions of X:[pos_x, pos_x + out_width] and
+ * Y:[pos_y, pos_y + out_height] outside of the screen
+ * X:[0, screen.width], Y:[0, screen.height] will be cropped
+ * automatically without changing the scaling ratio.
+ *
+ * 2) Crop region will be adjusted to the pixel granularity:
+ * (2-by-1) for YUV422, (2-by-2) for YUV420. This will
+ * not modify the output region. Crop region is for the
+ * original (unrotated) buffer, so it does not change with
+ * rotation.
+ *
+ * 3) Rotation will not modify the output region, specifically
+ * its height and width. Also the coordinate system of the
+ * display is always (0,0) = top left.
+ *
+ * 4) cconv and vc1 only needs to be filled for YUV color modes.
+ *
+ * 5) vc1.range_y and vc1.range_uv only needs to be filled if
+ * vc1.enable is true.
+ */
+struct dss2_ovl_cfg {
+ __u16 width; /* buffer width */
+ __u16 height; /* buffer height */
+ __u32 stride; /* buffer stride */
+
+ enum omap_color_mode color_mode;
+ __u8 pre_mult_alpha; /* bool */
+ __u8 global_alpha; /* 0..255 */
+ __u8 rotation; /* 0..3 (*90 degrees clockwise) */
+ __u8 mirror; /* left-to-right: mirroring is applied after rotation */
+
+ enum omap_dss_ilace_mode ilace; /* interlace mode */
+
+ struct dss2_rect_t win; /* output window - on display */
+ struct dss2_rect_t crop; /* crop window - in source buffer */
+
+ struct dss2_decim decim; /* predecimation limits */
+
+ struct omap_dss_cconv_coefs cconv;
+ struct dss2_vc1_range_map_info vc1;
+
+ __u8 wb_source; /* pipe: is source or not, wb: capture device id */
+ enum omap_writeback_mode wb_mode;
+ __u8 ix; /* ovl index same as sysfs/overlay# */
+ __u8 zorder; /* 0..3 */
+ __u8 enabled; /* bool */
+ __u8 zonly; /* only set zorder and enabled bit */
+ __u8 mgr_ix; /* mgr index */
+
+ bool force_1d;
+ bool mflag_en; /* mflag for the overlay */
+} __aligned(4);
+
+enum omapdss_buffer_type {
+ OMAP_DSS_BUFTYPE_SDMA,
+ OMAP_DSS_BUFTYPE_TILER_8BIT,
+ OMAP_DSS_BUFTYPE_TILER_16BIT,
+ OMAP_DSS_BUFTYPE_TILER_32BIT,
+ OMAP_DSS_BUFTYPE_TILER_PAGE,
+};
+
+enum omapdss_buffer_addressing_type {
+ OMAP_DSS_BUFADDR_DIRECT, /* using direct addresses */
+ OMAP_DSS_BUFADDR_BYTYPE, /* using buffer types */
+ OMAP_DSS_BUFADDR_ION, /* using ion handle(s) */
+ OMAP_DSS_BUFADDR_GRALLOC, /* using gralloc handle */
+ OMAP_DSS_BUFADDR_OVL_IX, /* using a prior overlay */
+ OMAP_DSS_BUFADDR_LAYER_IX, /* using a Post2 layer */
+ OMAP_DSS_BUFADDR_FB, /* using framebuffer memory */
+};
+
+struct dss2_ovl_info {
+ struct dss2_ovl_cfg cfg;
+
+ enum omapdss_buffer_addressing_type addressing;
+
+ union {
+ /* user-space interfaces */
+ struct {
+ void *address; /* main buffer address */
+ void *uv_address; /* uv buffer */
+ };
+
+ /*
+ * For DSSCIOC_CHECK_OVL we allow specifying just the
+ * type of each buffer. This is used if we need to
+ * check whether DSS will be able to display a buffer
+ * if using a particular memory type before spending
+ * time to map/copy the buffer into that type of
+ * memory.
+ */
+ struct {
+ enum omapdss_buffer_type ba_type;
+ enum omapdss_buffer_type uv_type;
+ };
+
+ /* kernel-space interfaces */
+
+ /*
+ * for fbmem, highest 4-bits of address is fb index,
+ * rest of the bits are the offset
+ */
+ struct {
+ __u32 ba; /* base address or index */
+ __u32 uv; /* uv address */
+ };
+ };
+};
+
+/*
+ * DSS2 manager information.
+ *
+ * The following information is deemed to be set globally, so it is not
+ * included:
+ * gamma correction
+ * whether to enable zorder (always enabled)
+ * whether to replicate/truncate color fields (it is decided per the
+ * whole manager/overlay settings, and is enabled unless overlay is
+ * directed to WB.)
+ * Notes:
+ *
+ * 1) trans_key_type and trans_enabled only need to be filled if
+ * trans_enabled is true, and alpha_blending is false.
+ */
+struct dss2_mgr_info {
+ __u32 ix; /* display index same as sysfs/display# */
+
+ __u32 default_color;
+
+ enum omap_dss_trans_key_type trans_key_type;
+ __u32 trans_key;
+ struct omap_dss_cpr_coefs cpr_coefs;
+
+ __u8 trans_enabled; /* bool */
+
+ __u8 interlaced; /* bool */
+ __u8 alpha_blending; /* bool - overrides trans_enabled */
+ __u8 cpr_enabled; /* bool */
+ __u8 swap_rb; /* bool - swap red and blue */
+} __aligned(4);
+
+/*
+ * ioctl: DSSCIOC_SETUP_MGR, struct dsscomp_setup_mgr_data
+ *
+ * 1. sets manager of each ovl in composition to the display
+ * 2. calls set_dss_ovl_info() for each ovl to set up the
+ * overlay staging structures (this is a wrapper around ovl->set_info())
+ * 3. calls set_dss_mgr_info() for mgr to set up the manager
+ * staging structures (this is a wrapper around mgr->set_info())
+ * 4. if update is true:
+ * calls manager->apply()
+ * calls driver->update() in a non-blocking fashion
+ * this will program the DSS synchronously
+ *
+ * Notes:
+ *
+ * 1) x, y, w, h only needs to be set if update is true.
+ *
+ * All non-specified pipelines that currently are on the same display
+ * will remain the same as on the previous frame. You may want to
+ * disable unused pipelines to avoid surprises.
+ *
+ * If get_sync_obj is false, it returns 0 on success, <0 error value
+ * on failure.
+ *
+ * If get_sync_obj is true, it returns fd on success, or a negative value
+ * on failure. You can use the fd to wait on (using DSSCIOC_WAIT ioctl()).
+ *
+ * Note: frames do not get eclipsed when the display turns off. Queue a
+ * blank frame to eclipse old frames. Blank frames get eclipsed when
+ * programmed into DSS.
+ *
+ * (A blank frame is queued to the display automatically in Android before
+ * the display is turned off.)
+ *
+ * All overlays to be used on the frame must be listed. There is no way
+ * to add another overlay to a defined frame.
+ */
+enum dsscomp_setup_mode {
+ DSSCOMP_SETUP_MODE_APPLY = (1 << 0), /* applies changes to cache */
+ DSSCOMP_SETUP_MODE_DISPLAY = (1 << 1), /* calls display update */
+ DSSCOMP_SETUP_MODE_CAPTURE = (1 << 2), /* capture to WB */
+
+ /* just apply changes for next vsync/update */
+ DSSCOMP_SETUP_APPLY = DSSCOMP_SETUP_MODE_APPLY,
+ /* trigger an update (wait for vsync) */
+ DSSCOMP_SETUP_DISPLAY =
+ DSSCOMP_SETUP_MODE_APPLY | DSSCOMP_SETUP_MODE_DISPLAY,
+ /* capture to WB - WB must be configured */
+ DSSCOMP_SETUP_CAPTURE =
+ DSSCOMP_SETUP_MODE_APPLY | DSSCOMP_SETUP_MODE_CAPTURE,
+ /* display and capture to WB - WB must be configured */
+ DSSCOMP_SETUP_DISPLAY_CAPTURE =
+ DSSCOMP_SETUP_DISPLAY | DSSCOMP_SETUP_CAPTURE,
+};
+
+struct dsscomp_setup_mgr_data {
+ __u32 sync_id; /* synchronization ID - for debugging */
+
+ struct dss2_rect_t win; /* update region, set w/h to 0 for fullscreen */
+ enum dsscomp_setup_mode mode;
+ __u16 num_ovls; /* # of overlays used in the composition */
+ __u16 get_sync_obj; /* ioctl should return a sync object */
+
+ struct dss2_mgr_info mgr;
+ struct dss2_ovl_info ovls[0]; /* up to 5 overlays to set up */
+};
+
+/*
+ * ioctl: DSSCIOC_CHECK_OVL, struct dsscomp_check_ovl_data
+ *
+ * DISPLAY and/or CAPTURE bits must be filled for the mode field
+ * correctly to be able to decide correctly if DSS can properly
+ * render the overlay.
+ *
+ * ovl.ix is ignored.
+ *
+ * Returns a positive bitmask regarding which overlay of DSS can
+ * render the overlay as it is configured for the display/display's
+ * manager. NOTE: that overlays that are assigned to other displays
+ * may be returned. If there is an invalid configuration (negative
+ * sizes, etc.), a negative error value is returned.
+ *
+ * ovl->decim's min values will be modified to the smallest decimation that
+ * DSS can use to support the overlay configuration.
+ *
+ * Assumptions:
+ * - zorder will be distinct from other pipelines on that manager
+ * - overlay will be enabled and routed to the display specified
+ */
+struct dsscomp_check_ovl_data {
+ enum dsscomp_setup_mode mode;
+ struct dss2_mgr_info mgr;
+ struct dss2_ovl_info ovl;
+};
+
+/*
+ * This structure is used to set up the entire DISPC (all managers),
+ * and is analogous to dsscomp_setup_mgr_data.
+ *
+ * Additional features:
+ * - all overlays that were specified in a prior use of this
+ * structure, and are no longer specified, will be disabled.
+ * - 1D buffers under 4M will be mapped into TILER1D.
+ *
+ * Limitations:
+ * - only DISPLAY mode is supported (DISPLAY and APPLY bits will
+ * automatically be set)
+ * - getting a sync object is not supported.
+ */
+struct dsscomp_setup_dispc_data {
+ __u32 sync_id; /* synchronization ID - for debugging */
+
+ enum dsscomp_setup_mode mode;
+ __u16 num_ovls; /* # of overlays used in the composition */
+ __u16 num_mgrs; /* # of managers used in the composition */
+ __u16 get_sync_obj; /* ioctl should return a sync object */
+
+ struct dss2_mgr_info mgrs[3];
+ struct dss2_ovl_info ovls[5]; /* up to 5 overlays to set up */
+};
+
+/*
+ * ioctl: DSSCIOC_WB_COPY, struct dsscomp_wb_copy_data
+ *
+ * Requirements:
+ * wb.ix must be OMAP_DSS_WB.
+ *
+ * Returns 0 on success (copy is completed), non-0 on failure.
+ */
+struct dsscomp_wb_copy_data {
+ struct dss2_ovl_info ovl, wb;
+};
+
+/*
+ * ioctl: DSSCIOC_QUERY_DISPLAY, struct dsscomp_display_info
+ *
+ * Gets informations about the display. Fill in ix and modedb_len before
+ * calling ioctl, and rest of the fields are filled in by ioctl. Up to
+ * modedb_len timings are retrieved in the order of display preference.
+ *
+ * Returns: 0 on success, non-0 error value on failure.
+ */
+struct dsscomp_display_info {
+ __u32 ix; /* display index (sysfs/display#) */
+ __u32 overlays_available; /* bitmask of available overlays */
+ __u32 overlays_owned; /* bitmask of owned overlays */
+ enum omap_channel channel;
+ enum omap_dss_display_state state;
+ __u8 enabled; /* bool: resume-state if suspended */
+ struct omap_video_timings timings;
+ struct s3d_disp_info s3d_info; /* any S3D specific information */
+ struct dss2_mgr_info mgr; /* manager information */
+ __u16 width_in_mm; /* screen dimensions */
+ __u16 height_in_mm;
+
+ __u32 modedb_len; /* number of video timings */
+ struct dsscomp_videomode modedb[]; /* display supported timings */
+};
+
+/*
+ * ioctl: DSSCIOC_SETUP_DISPLAY, struct dsscomp_setup_display_data
+ *
+ * Gets informations about the display. Fill in ix before calling
+ * ioctl, and rest of the fields are filled in by ioctl.
+ *
+ * Returns: 0 on success, non-0 error value on failure.
+ */
+struct dsscomp_setup_display_data {
+ __u32 ix; /* display index (sysfs/display#) */
+ struct dsscomp_videomode mode; /* video timings */
+};
+
+/*
+ * ioctl: DSSCIOC_WAIT, struct dsscomp_wait_data
+ *
+ * Use this ioctl to wait for one of the following events:
+ *
+ * A) the moment a composition is programmed into DSS
+ * B) the moment a composition is first displayed (or captured)
+ * C) the moment when a composition is no longer queued or displayed on a
+ * display (it is released). (A composition is assumed to be superceded
+ * when another composition has been programmed into DSS, even if that
+ * subsequent composition does not update/specify all overlays used by
+ * the prior composition; moreover, even if it uses the same buffers.)
+ *
+ * Set timeout to desired timeout value in microseconds.
+ *
+ * This ioctl must be used on the sync object returned by the
+ * DSSCIOC_SETUP_MGR or DSSCIOC_SETUP_DISPC ioctls.
+ *
+ * Returns: >=0 on success, <0 error value on failure (e.g. -ETIME).
+ */
+enum dsscomp_wait_phase {
+ DSSCOMP_WAIT_PROGRAMMED = 1,
+ DSSCOMP_WAIT_DISPLAYED,
+ DSSCOMP_WAIT_RELEASED,
+};
+
+struct dsscomp_wait_data {
+ __u32 timeout_us; /* timeout in microseconds */
+ enum dsscomp_wait_phase phase; /* phase to wait for */
+};
+
+enum dsscomp_fbmem_type {
+ DSSCOMP_FBMEM_TILER2D = 0,
+ DSSCOMP_FBMEM_VRAM = 1,
+};
+
+/*
+ * ioctl: DSSCIOC_QUERY_PLATFORM, struct dsscomp_platform_info
+ *
+ * Use this ioctl to get platform information needed to decide
+ * DSS/DSSCOMP capabilities, by filling out the passed structure with:
+ *
+ * A) predecimation limits
+ * B) maximum fclk (DSS is assumed to scale up to this fclk automatically
+ * to support frames)
+ * C) minimum and maximum sizes (for now we use the same limits for
+ * both source and window sizes, which works for OMAP4/5)
+ * D) scaler limitations. (assuming same max downscale limitation both
+ * horizontally/vertically; however, fclock requirements are only
+ * dependent on horizontal scaling, which works for OMAP4 ES1.1+ and
+ * OMAP5 only).
+ * integer_scale_ratio_limit is the maximum source width to round up
+ * fclock/pixclock to an integer.
+ * E) Tiler1D slot size
+ *
+ * Returns: 0 on success, <0 error value on failure (unlikely)
+ */
+
+struct dsscomp_platform_info {
+ /* decimation limits for 2D and 1D buffers */
+ __u8 max_xdecim_2d;
+ __u8 max_ydecim_2d;
+ __u8 max_xdecim_1d;
+ __u8 max_ydecim_1d;
+ __u32 fclk; /* dispc max fclk */
+ /* pipeline source/destination limits */
+ __u8 min_width;
+ __u16 max_width;
+ __u16 max_height;
+ /* scaler limitations */
+ __u8 max_downscale;
+ /* below this width, we assume integer pixelclk scale */
+ __u16 integer_scale_ratio_limit;
+ __u32 tiler1d_slot_size;
+ enum dsscomp_fbmem_type fbmem_type; /* TILER2D vs VRAM */
+};
+
+/* IOCTLS */
+#define DSSCIOC_SETUP_MGR _IOW('O', 128, struct dsscomp_setup_mgr_data)
+#define DSSCIOC_CHECK_OVL _IOWR('O', 129, struct dsscomp_check_ovl_data)
+#define DSSCIOC_WB_COPY _IOW('O', 130, struct dsscomp_wb_copy_data)
+#define DSSCIOC_QUERY_DISPLAY _IOWR('O', 131, struct dsscomp_display_info)
+#define DSSCIOC_WAIT _IOW('O', 132, struct dsscomp_wait_data)
+
+#define DSSCIOC_SETUP_DISPC _IOW('O', 133, struct dsscomp_setup_dispc_data)
+#define DSSCIOC_SETUP_DISPLAY \
+ _IOW('O', 134, struct dsscomp_setup_display_data)
+#define DSSCIOC_QUERY_PLATFORM _IOR('O', 135, struct dsscomp_platform_info)
+#endif
diff --git a/include/video/omap_hwc.h b/include/video/omap_hwc.h
--- /dev/null
+++ b/include/video/omap_hwc.h
@@ -0,0 +1,118 @@
+/*
+ *
+ * Copyright (C) 2012 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _LINUX_OMAP_HWC_H
+#define _LINUX_OMAP_HWC_H
+
+/*
+ * Client of the omap_hwc_data API
+ * -------------------------------
+ * This is really a kernel to kernel API (not an ioctl interface) but most of
+ * the values are populated in user space by a single client, specifically the
+ * Android hardware composer HAL (HWC) which is a library loaded by the
+ * SurfaceFlinger composition process.
+ *
+ * Implementation details
+ * ----------------------
+ * The SGX display driver (called OMAPLFB) will obtain this data structure
+ * from the GPU driver (aka PVR kernel services) as well as an array of
+ * memory descriptors managed by PVR services. OMAPLFB is responsible
+ * for fixing up the buffer data within the omap_hwc_data data structure
+ * before calling the DSSCOMP module and (optionally) the Bltsville kernel
+ * API/implementation.
+ *
+ * Buffer referencing
+ * ------------------
+ * When calling from the HWC (via PVR services) the actual address of buffers
+ * involved in composition are typically unknown. It is a convention to store
+ * an index in the appropriate field of the sub-structures in omap_hwc_data.
+ * PVR services also passes an array of memory data structures that these
+ * indexes (commonly) refer to.
+ *
+ * The dsscomp API fully describes how it manages buffering when called
+ * from a kernel client context. The simplest scenario is that individual
+ * overlays carry the buffer index in the overlay structure base address.
+ *
+ * For Bltsville kernel mode support, buffers are identified by storing the
+ * buffer index in the virtaddr of the various bvbuffdesc entries. Some
+ * exceptions are described below.
+ *
+ * Blitting
+ * --------
+ * Blit source buffers are managed in the same way as Post2 layers in the
+ * dsscomp API. The Android HWC constructs the blits using the Bltsville
+ * API but the actual blits are issued to Bltsville kernel mode implementation
+ * from OMAPLFB. Destination buffers are allocated and managed by OMAPLFB.
+ *
+ * When blitting it is expected that HWC will construct the overlay information
+ * appropriately in "dsscomp_data"
+ */
+
+/*
+ * Alternate blit descriptor information.
+ *
+ * As mentioned above buffers are refers to by index, alternate buffers
+ * can be refered to by the following
+ */
+#define HWC_BLT_DESC_FLAG 0x80000000
+
+/*
+ * With this value the descriptor refers to an available framebuffer. It
+ * is up to the client and OMAPLFB to track and manage the state of these
+ * buffers. The caller can also specify an overlay index that OMAPLFB will
+ * use when programming dsscomp with the result of the blit.
+ */
+#define HWC_BLT_DESC_FB 0x40000000
+
+#define HWC_BLT_DESC_FB_FN(ovlno) \
+ (HWC_BLT_DESC_FLAG | HWC_BLT_DESC_FB | (ovlno))
+
+/*
+ * This flag hints OMAPLFB the HWC has configured a DSS pipe for a blit FB
+ */
+#define HWC_BLT_FLAG_USE_FB (1 << 0)
+
+/*****************************************************************************/
+/* WARNING - These structs must keep in sync with user space code */
+/*****************************************************************************/
+struct rgz_blt_entry {
+ struct bvbltparams bp;
+ struct bvsurfgeom dstgeom;
+ struct bvsurfgeom src1geom;
+ struct bvbuffdesc src1desc;
+ struct bvsurfgeom src2geom;
+ struct bvbuffdesc src2desc;
+};
+
+struct omap_hwc_blit_data {
+ __u16 rgz_flags;
+ /* if rgz_items is 0 there is nothing to blit */
+ __u16 rgz_items;
+ struct rgz_blt_entry rgz_blts[0];
+};
+
+/*
+ * This structure is passed down from the Android HWC HAL
+ */
+struct omap_hwc_data {
+ struct dsscomp_setup_dispc_data dsscomp_data;
+ struct omap_hwc_blit_data blit_data;
+};
+
+#endif
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
OMAP_DSS_COLOR_RGBX16 = 1 << 16, /* RGBx16 - 4444 */
OMAP_DSS_COLOR_ARGB16_1555 = 1 << 17, /* ARGB16 - 1555 */
OMAP_DSS_COLOR_XRGB16_1555 = 1 << 18, /* xRGB16 - 1555 */
+ OMAP_DSS_COLOR_BGRA32 = 1 << 19, /* BGRA32 */
};
enum omap_dss_load_mode {
u16 out_height; /* if 0, out_height == height */
u8 global_alpha;
u8 pre_mult_alpha;
+ u8 wb_source;
u8 zorder;
u16 min_x_decim, max_x_decim, min_y_decim, max_y_decim;
/* regn is one greater than TRM's REGN value */
u16 regn;
u16 regm2;
+ u32 max_pixclk_khz;
} hdmi;
} clocks;
struct {
struct omap_video_timings timings;
+ struct fb_monspecs monspecs;
enum omap_dss_dsi_pixel_format dsi_pix_fmt;
enum omap_dss_dsi_mode dsi_mode;
struct omap_dss_dsi_videomode_timings dsi_vm_timings;
struct s3d_disp_info s3d_info;
-
u32 width_in_um;
u32 height_in_um;
-
- } panel;
+ u16 fb_xres;
+ u16 fb_yres;
+ } panel;
struct {
u8 pixel_size;
int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
u32 (*get_wss)(struct omap_dss_device *dssdev);
+ int (*get_modedb)(struct omap_dss_device *dssdev,
+ struct fb_videomode *modedb,
+ int modedb_len);
+ int (*set_mode)(struct omap_dss_device *dssdev,
+ struct fb_videomode *mode);
+
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
bool (*detect)(struct omap_dss_device *dssdev);
@@ -1010,6 +1020,8 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
+void omapdss_display_get_dimensions(struct omap_dss_device *dssdev,
+ u32 *width_in_um, u32 *height_in_um);
void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
bool enable);
int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
index 7ba62e99087ef79c16372d382ae99ebdc8cbad41..ef30dbdd7aeeafc2b5f79c04e80b448a22fca423 100644 (file)
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
+#include <linux/lcm.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include "davinci-pcm.h"
#include "davinci-mcasp.h"
+#include "../omap/omap-pcm.h"
/*
* McASP register definitions
/* Transmit Buffer for Serializer n */
#define DAVINCI_MCASP_TXBUF_REG 0x200
/* Receive Buffer for Serializer n */
-#define DAVINCI_MCASP_RXBUF_REG 0x280
+#define DAVINCI_MCASP_RXBUF_REG 0x284
/* McASP FIFO Registers */
#define DAVINCI_MCASP_WFIFOCTL (0x1010)
* DAVINCI_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits
*/
#define MODE(val) (val)
-#define DISMOD (val)(val<<2)
+#define DISMOD(val) (val << 2)
#define TXSTATE BIT(4)
#define RXSTATE BIT(5)
#define SRMOD_MASK 3
#define DAVINCI_MCASP_NUM_SERIALIZER 16
+/*
+ * Timeout value of 1 ms was chosen experimentally to account for the initial
+ * latency to have the first audio sample transferred to AFIFO by DMA
+ */
+#define MCASP_FIFO_FILL_TIMEOUT 1000
+
static inline void mcasp_set_bits(void __iomem *reg, u32 val)
{
__raw_writel(__raw_readl(reg) | val, reg);
static void mcasp_start_rx(struct davinci_audio_dev *dev)
{
+ u32 rxfmctl = mcasp_get_reg(dev->base + DAVINCI_MCASP_RXFMCTL_REG);
+
mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
+
+ /*
+ * Enable TX FSG when McASP is in sync mode and is master since the
+ * TX section provides FSYNC for RX too. TX clk dividers are also
+ * enabled for cases where ACLKR pin is not connected (typically
+ * done when AFSR is not used either)
+ */
+ if (rxfmctl & AFSRE) {
+ mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG,
+ TXHCLKRST);
+ mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG,
+ TXCLKRST);
+ }
+
mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
+
+ if (rxfmctl & AFSRE)
+ mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG,
+ TXFSRST);
}
static void mcasp_start_tx(struct davinci_audio_dev *dev)
mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
}
-static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
+static int davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
{
+ int i = 0;
+ u32 val;
+
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (dev->txnumevt) { /* enable FIFO */
switch (dev->version) {
case MCASP_VERSION_3:
+ case MCASP_VERSION_4:
mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL,
FIFO_ENABLE);
mcasp_set_bits(dev->base + MCASP_VER3_WFIFOCTL,
mcasp_set_bits(dev->base +
DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
}
+
+ /*
+ * Wait until DMA has loaded at least one sample into
+ * AFIFO to ensure XRUN is not immediately hit
+ * Implementation has to use udelay since it's executed
+ * in atomic context (trigger() callback)
+ */
+ while (++i) {
+ val = mcasp_get_reg(dev->base +
+ MCASP_VER3_WFIFOSTS);
+ if (val > 0)
+ break;
+
+ if (i > MCASP_FIFO_FILL_TIMEOUT)
+ return -ETIMEDOUT;
+
+ udelay(1);
+ }
}
mcasp_start_tx(dev);
} else {
if (dev->rxnumevt) { /* enable FIFO */
switch (dev->version) {
case MCASP_VERSION_3:
+ case MCASP_VERSION_4:
mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL,
FIFO_ENABLE);
mcasp_set_bits(dev->base + MCASP_VER3_RFIFOCTL,
}
mcasp_start_rx(dev);
}
+
+ return 0;
}
static void mcasp_stop_rx(struct davinci_audio_dev *dev)
{
+ u32 gblctl = mcasp_get_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG);
+ u32 rxfmctl = mcasp_get_reg(dev->base + DAVINCI_MCASP_RXFMCTL_REG);
+
+ /* Disable TX FSG if RX was the only active user */
+ if ((rxfmctl & AFSRE) && !(gblctl & TXSMRST))
+ mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
+
mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0);
mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
}
static void mcasp_stop_tx(struct davinci_audio_dev *dev)
{
- mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
+ u32 gblctl = mcasp_get_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG);
+ u32 rxfmctl = mcasp_get_reg(dev->base + DAVINCI_MCASP_RXFMCTL_REG);
+ u32 val = 0;
+
+ /* Keep FSG active until RX section is stopped too */
+ if ((rxfmctl & AFSRE) && (gblctl & RXSMRST))
+ val = TXHCLKRST | TXCLKRST | TXFSRST;
+
+ mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, val);
mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
}
if (dev->txnumevt) { /* disable FIFO */
switch (dev->version) {
case MCASP_VERSION_3:
+ case MCASP_VERSION_4:
mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL,
FIFO_ENABLE);
break;
if (dev->rxnumevt) { /* disable FIFO */
switch (dev->version) {
case MCASP_VERSION_3:
+ case MCASP_VERSION_4:
mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL,
FIFO_ENABLE);
break;
{
u32 fmt;
u32 tx_rotate = (word_length / 4) & 0x7;
- u32 rx_rotate = (32 - word_length) / 4;
+ u32 rx_rotate;
u32 mask = (1ULL << word_length) - 1;
+ u32 slot_length;
/*
* if s BCLK-to-LRCLK ratio has been configured via the set_clkdiv()
* tdm-slots (for I2S - divided by 2).
*/
if (dev->bclk_lrclk_ratio)
- word_length = dev->bclk_lrclk_ratio / dev->tdm_slots;
+ slot_length = dev->bclk_lrclk_ratio / dev->tdm_slots;
+ else
+ slot_length = word_length;
/* mapping of the XSSZ bit-field as described in the datasheet */
- fmt = (word_length >> 1) - 1;
+ fmt = (slot_length >> 1) - 1;
+
+ rx_rotate = (slot_length - word_length) / 4;
if (dev->op_mode != DAVINCI_MCASP_DIT_MODE) {
mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
u8 slots = dev->tdm_slots;
u8 max_active_serializers = (channels + slots - 1) / slots;
/* Default configuration */
- mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
+ if (dev->version != MCASP_VERSION_4)
+ mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG,
+ MCASP_SOFT);
/* All PINS as McASP */
mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000);
dev->serial_dir[i]);
if (dev->serial_dir[i] == TX_MODE &&
tx_ser < max_active_serializers) {
+ mcasp_mod_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
+ DISMOD(dev->tx_dismod), DISMOD(3));
+
mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
AXR(i));
tx_ser++;
} else if (dev->serial_dir[i] == RX_MODE &&
rx_ser < max_active_serializers) {
+ mcasp_mod_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
+ DISMOD(dev->rx_dismod), DISMOD(3));
+
mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
AXR(i));
rx_ser++;
switch (dev->version) {
case MCASP_VERSION_3:
+ case MCASP_VERSION_4:
mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, tx_ser,
NUMDMA_MASK);
mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL,
dev->rxnumevt = 1;
switch (dev->version) {
case MCASP_VERSION_3:
+ case MCASP_VERSION_4:
mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, rx_ser,
NUMDMA_MASK);
mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL,
return 0;
}
-static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
+static int davinci_hw_param(struct davinci_audio_dev *dev, int stream,
+ int channels)
{
int i, active_slots;
+ int total_slots = dev->tdm_slots;
+ int active_serializers;
u32 mask = 0;
+ u32 busel = 0;
+
+ if ((total_slots < 2) || (total_slots > 32)) {
+ dev_err(dev->dev, "tdm slot count %d not supported\n",
+ total_slots);
+ return -EINVAL;
+ }
+
+ /*
+ * If more than one serializer is needed, then use them with
+ * their specified tdm_slots count. Otherwise, one serializer
+ * can cope with the transaction using as many slots as channels
+ * in the stream, requires channels symmetry
+ */
+ active_serializers = (channels + total_slots - 1) / total_slots;
+ if (active_serializers == 1) {
+ active_slots = channels;
+ dev->channels = channels;
+ } else {
+ active_slots = total_slots;
+ }
- active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
for (i = 0; i < active_slots; i++)
mask |= (1 << i);
mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /* bit stream is MSB first with no delay */
- /* DSP_B mode */
- mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
- mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
-
- if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
- mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
- FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
- else
- printk(KERN_ERR "playback tdm slot %d not supported\n",
- dev->tdm_slots);
- } else {
- /* bit stream is MSB first with no delay */
- /* DSP_B mode */
- mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
- mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
-
- if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
- mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
- FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
- else
- printk(KERN_ERR "capture tdm slot %d not supported\n",
- dev->tdm_slots);
- }
+ if (dev->version == MCASP_VERSION_4 && !dev->dat_port)
+ busel = TXSEL;
+
+ /* bit stream is MSB first with no delay */
+ /* DSP_B mode */
+ mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
+ mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
+ mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
+ FSXMOD(total_slots), FSXMOD(0x1FF));
+
+ mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
+ mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
+ mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
+ FSRMOD(total_slots), FSRMOD(0x1FF));
+
+ return 0;
}
/* S/PDIF */
-static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
+static int davinci_hw_dit_param(struct davinci_audio_dev *dev)
{
/* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
and LSB first */
/* Enable the DIT */
mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN);
+
+ return 0;
+}
+
+static void davinci_mcasp_set_dma_params(struct snd_pcm_substream *substream,
+ struct davinci_audio_dev *dev,
+ int word_length, u8 fifo_level)
+{
+ if (dev->version == MCASP_VERSION_4) {
+ struct omap_pcm_dma_data *dma_data =
+ dev->dma_params[substream->stream];
+
+ dma_data->packet_size = fifo_level;
+ } else {
+ struct davinci_pcm_dma_params *dma_params =
+ dev->dma_params[substream->stream];
+
+ dma_params->data_type = word_length >> 3;
+ dma_params->fifo_level = fifo_level;
+
+ if (dev->version == MCASP_VERSION_2 && !fifo_level)
+ dma_params->acnt = 4;
+ else
+ dma_params->acnt = dma_params->data_type;
+ }
}
static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
- struct davinci_pcm_dma_params *dma_params =
- &dev->dma_params[substream->stream];
int word_length;
u8 fifo_level;
u8 slots = dev->tdm_slots;
u8 active_serializers;
- int channels;
- struct snd_interval *pcm_channels = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_CHANNELS);
- channels = pcm_channels->min;
+ int channels = params_channels(params);
+ int ret;
active_serializers = (channels + slots - 1) / slots;
fifo_level = dev->rxnumevt * active_serializers;
if (dev->op_mode == DAVINCI_MCASP_DIT_MODE)
- davinci_hw_dit_param(dev);
+ ret = davinci_hw_dit_param(dev);
else
- davinci_hw_param(dev, substream->stream);
+ ret = davinci_hw_param(dev, substream->stream, channels);
+
+ if (ret)
+ return ret;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_U8:
case SNDRV_PCM_FORMAT_S8:
- dma_params->data_type = 1;
word_length = 8;
break;
case SNDRV_PCM_FORMAT_U16_LE:
case SNDRV_PCM_FORMAT_S16_LE:
- dma_params->data_type = 2;
word_length = 16;
break;
case SNDRV_PCM_FORMAT_U24_3LE:
case SNDRV_PCM_FORMAT_S24_3LE:
- dma_params->data_type = 3;
word_length = 24;
break;
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_U32_LE:
case SNDRV_PCM_FORMAT_S32_LE:
- dma_params->data_type = 4;
word_length = 32;
break;
return -EINVAL;
}
- if (dev->version == MCASP_VERSION_2 && !fifo_level)
- dma_params->acnt = 4;
- else
- dma_params->acnt = dma_params->data_type;
-
- dma_params->fifo_level = fifo_level;
+ dev->sample_bits = word_length;
+ davinci_mcasp_set_dma_params(substream, dev, word_length, fifo_level);
davinci_config_channel_size(dev, word_length);
return 0;
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- ret = pm_runtime_get_sync(dev->dev);
- if (IS_ERR_VALUE(ret))
- dev_err(dev->dev, "pm_runtime_get_sync() failed\n");
- davinci_mcasp_start(dev, substream->stream);
+ ret = davinci_mcasp_start(dev, substream->stream);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
- davinci_mcasp_stop(dev, substream->stream);
- ret = pm_runtime_put_sync(dev->dev);
- if (IS_ERR_VALUE(ret))
- dev_err(dev->dev, "pm_runtime_put_sync() failed\n");
- break;
-
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
davinci_mcasp_stop(dev, substream->stream);
return ret;
}
+static int davinci_mcasp_hwrule_buffersize(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule,
+ int stream)
+{
+ struct snd_interval *buffer_size = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
+ int channels = params_channels(params);
+ int periods = params_periods(params);
+ struct davinci_audio_dev *dev = rule->private;
+ int i;
+ u8 slots = dev->tdm_slots;
+ u8 max_active_serializers = (channels + slots - 1) / slots;
+ u8 num_ser = 0;
+ u8 num_evt = 0;
+ unsigned long step = 1;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ for (i = 0; i < dev->num_serializer; i++) {
+ if (dev->serial_dir[i] == TX_MODE &&
+ num_ser < max_active_serializers)
+ num_ser++;
+ }
+ num_evt = dev->txnumevt * num_ser;
+ } else {
+ for (i = 0; i < dev->num_serializer; i++) {
+ if (dev->serial_dir[i] == RX_MODE &&
+ num_ser < max_active_serializers)
+ num_ser++;
+ }
+ num_evt = dev->rxnumevt * num_ser;
+ }
+
+ /*
+ * The buffersize (in samples), must be a multiple of num_evt. The
+ * buffersize (in frames) is the product of the period_size and the
+ * number of periods. Therefore, the buffersize should be a multiple
+ * of the number of periods. The below finds the least common
+ * multiple of num_evt and channels (since the number of samples
+ * per frame is equal to the number of channels). It also makes sure
+ * that the resulting step value (LCM / channels) is a multiple of the
+ * number of periods.
+ */
+ step = lcm((lcm(num_evt, channels) / channels), periods);
+
+ return snd_interval_step(buffer_size, 0, step);
+}
+
+static int davinci_mcasp_hwrule_txbuffersize(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+{
+ return davinci_mcasp_hwrule_buffersize(params, rule,
+ SNDRV_PCM_STREAM_PLAYBACK);
+}
+
+static int davinci_mcasp_hwrule_rxbuffersize(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+{
+ return davinci_mcasp_hwrule_buffersize(params, rule,
+ SNDRV_PCM_STREAM_CAPTURE);
+}
+
static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
- snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
+
+ if (dev->version == MCASP_VERSION_4) {
+ snd_soc_dai_set_dma_data(dai, substream,
+ dev->dma_params[substream->stream]);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (dev->txnumevt)
+ snd_pcm_hw_rule_add(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+ davinci_mcasp_hwrule_txbuffersize,
+ dev,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
+ } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ if (dev->rxnumevt)
+ snd_pcm_hw_rule_add(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+ davinci_mcasp_hwrule_rxbuffersize,
+ dev,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
+ }
+ }
+ else
+ snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
+
+ /* Apply channels symmetry, needed when using a single serializer */
+ if (dev->channels)
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ dev->channels, dev->channels);
+
+ /*
+ * Apply sample size symmetry since the slot size (defined by word
+ * length) has to be the same for playback and capture in McASP
+ * instances with unified clock/sync domain
+ */
+ if (dev->sample_bits)
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ dev->sample_bits,
+ dev->sample_bits);
+
return 0;
}
+static void davinci_mcasp_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+ if (!dai->active) {
+ dev->channels = 0;
+ dev->sample_bits = 0;
+ }
+}
+
static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
.startup = davinci_mcasp_startup,
+ .shutdown = davinci_mcasp_shutdown,
.trigger = davinci_mcasp_trigger,
.hw_params = davinci_mcasp_hw_params,
.set_fmt = davinci_mcasp_set_dai_fmt,
{
.name = "davinci-mcasp.0",
.playback = {
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 32 * 16,
.rates = DAVINCI_MCASP_RATES,
.formats = DAVINCI_MCASP_PCM_FMTS,
},
.capture = {
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 32 * 16,
.rates = DAVINCI_MCASP_RATES,
.formats = DAVINCI_MCASP_PCM_FMTS,
.compatible = "ti,omap2-mcasp-audio",
.data = (void *)MCASP_VERSION_3,
},
+ {
+ .compatible = "ti,dra7-mcasp-audio",
+ .data = (void *)MCASP_VERSION_4,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mcasp_dt_ids);
pdata->serial_dir = of_serial_dir;
}
+ of_property_read_u32(np, "ti,tx-inactive-mode", &pdata->tx_dismod);
+
+ of_property_read_u32(np, "ti,rx-inactive-mode", &pdata->rx_dismod);
+
+ /* DISMOD = 1 is a reserved value */
+ if ((pdata->tx_dismod == 1) || (pdata->rx_dismod == 1)) {
+ dev_err(&pdev->dev, "tx/rx-inactive-mode cannot be 1\n");
+ ret = -EINVAL;
+ goto nodata;
+ }
+
+ if ((pdata->tx_dismod > 3) || (pdata->rx_dismod > 3)) {
+ dev_err(&pdev->dev, "invalid tx/rx-inactive-mode\n");
+ ret = -EINVAL;
+ goto nodata;
+ }
+
ret = of_property_read_u32(np, "tx-num-evt", &val);
if (ret >= 0)
pdata->txnumevt = val;
static int davinci_mcasp_probe(struct platform_device *pdev)
{
- struct davinci_pcm_dma_params *dma_data;
- struct resource *mem, *ioarea, *res;
+ struct resource *mem, *ioarea, *mem_dat;
+ struct resource *tx_res, *rx_res;
struct snd_platform_data *pdata;
struct davinci_audio_dev *dev;
int ret;
return -EBUSY;
}
- pm_runtime_enable(&pdev->dev);
-
- ret = pm_runtime_get_sync(&pdev->dev);
- if (IS_ERR_VALUE(ret)) {
- dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
- return ret;
+ mem_dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
+ if (!mem_dat) {
+ dev_info(&pdev->dev, "data port resource not defined, cfg port will be used\n");
+ dev->dat_port = false;
+ } else {
+ dev->dat_port = true;
}
+ pm_runtime_enable(&pdev->dev);
+
dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
if (!dev->base) {
dev_err(&pdev->dev, "ioremap failed\n");
dev->version = pdata->version;
dev->txnumevt = pdata->txnumevt;
dev->rxnumevt = pdata->rxnumevt;
+ dev->tx_dismod = pdata->tx_dismod;
+ dev->rx_dismod = pdata->rx_dismod;
dev->dev = &pdev->dev;
- dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
- dma_data->asp_chan_q = pdata->asp_chan_q;
- dma_data->ram_chan_q = pdata->ram_chan_q;
- dma_data->sram_pool = pdata->sram_pool;
- dma_data->sram_size = pdata->sram_size_playback;
- dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
- mem->start);
-
/* first TX, then RX */
- res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!res) {
+ tx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!tx_res) {
dev_err(&pdev->dev, "no DMA resource\n");
- ret = -ENODEV;
- goto err_release_clk;
+ return -ENODEV;
}
- dma_data->channel = res->start;
+ rx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (!rx_res) {
+ dev_err(&pdev->dev, "no DMA resource\n");
+ return -ENODEV;
+ }
- dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
- dma_data->asp_chan_q = pdata->asp_chan_q;
- dma_data->ram_chan_q = pdata->ram_chan_q;
- dma_data->sram_pool = pdata->sram_pool;
- dma_data->sram_size = pdata->sram_size_capture;
- dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
- mem->start);
+ if (dev->version == MCASP_VERSION_4) {
+ struct omap_pcm_dma_data *dma_data;
- res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (!res) {
- dev_err(&pdev->dev, "no DMA resource\n");
- ret = -ENODEV;
- goto err_release_clk;
+ dma_data = devm_kzalloc(&pdev->dev, sizeof(*dma_data),
+ GFP_KERNEL);
+ if (!dma_data) {
+ ret = -ENOMEM;
+ goto err_release_clk;
+ }
+
+ dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = dma_data;
+ if (mem_dat)
+ dma_data->port_addr = mem_dat->start;
+ else
+ dma_data->port_addr = mem->start + DAVINCI_MCASP_TXBUF_REG;
+ dma_data->dma_req = tx_res->start;
+
+ dma_data = devm_kzalloc(&pdev->dev, sizeof(*dma_data),
+ GFP_KERNEL);
+ if (!dma_data) {
+ ret = -ENOMEM;
+ goto err_release_clk;
+ }
+
+ dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = dma_data;
+ if (mem_dat)
+ dma_data->port_addr = mem_dat->start;
+ else
+ dma_data->port_addr = mem->start + DAVINCI_MCASP_RXBUF_REG;
+ dma_data->dma_req = rx_res->start;
+ } else {
+ struct davinci_pcm_dma_params *dma_data;
+
+ dma_data = devm_kzalloc(&pdev->dev, sizeof(*dma_data),
+ GFP_KERNEL);
+ if (!dma_data) {
+ ret = -ENOMEM;
+ goto err_release_clk;
+ }
+
+ dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = dma_data;
+ dma_data->asp_chan_q = pdata->asp_chan_q;
+ dma_data->ram_chan_q = pdata->ram_chan_q;
+ dma_data->sram_pool = pdata->sram_pool;
+ dma_data->sram_size = pdata->sram_size_playback;
+ dma_data->channel = tx_res->start;
+ dma_data->dma_addr = (dma_addr_t)(pdata->tx_dma_offset +
+ mem->start);
+
+ dma_data = devm_kzalloc(&pdev->dev, sizeof(*dma_data),
+ GFP_KERNEL);
+ if (!dma_data) {
+ ret = -ENOMEM;
+ goto err_release_clk;
+ }
+
+ dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = dma_data;
+ dma_data->asp_chan_q = pdata->asp_chan_q;
+ dma_data->ram_chan_q = pdata->ram_chan_q;
+ dma_data->sram_pool = pdata->sram_pool;
+ dma_data->sram_size = pdata->sram_size_capture;
+ dma_data->channel = rx_res->start;
+ dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
+ mem->start);
}
- dma_data->channel = res->start;
dev_set_drvdata(&pdev->dev, dev);
ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]);
if (ret != 0)
goto err_release_clk;
- ret = davinci_soc_platform_register(&pdev->dev);
- if (ret) {
- dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
- goto err_unregister_dai;
+ if (dev->version != MCASP_VERSION_4) {
+ ret = davinci_soc_platform_register(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
+ goto err_unregister_dai;
+ }
}
return 0;
err_unregister_dai:
snd_soc_unregister_dai(&pdev->dev);
err_release_clk:
- pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return ret;
}
static int davinci_mcasp_remove(struct platform_device *pdev)
{
+ struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_dai(&pdev->dev);
- davinci_soc_platform_unregister(&pdev->dev);
- pm_runtime_put_sync(&pdev->dev);
+ if (dev->version != MCASP_VERSION_4)
+ davinci_soc_platform_unregister(&pdev->dev);
+
pm_runtime_disable(&pdev->dev);
return 0;
index a9ac0c11da71dd784ed26286e46d064f0cca66c9..48784954c83ce93745c96edb7a24f7afeacf3bc4 100644 (file)
#define DAVINCI_MCASP_DIT_DAI 1
struct davinci_audio_dev {
- struct davinci_pcm_dma_params dma_params[2];
+ void *dma_params[2];
void __iomem *base;
struct device *dev;
u8 op_mode;
u8 num_serializer;
u8 *serial_dir;
+ u32 tx_dismod;
+ u32 rx_dismod;
u8 version;
u16 bclk_lrclk_ratio;
+ unsigned int channels;
+ unsigned int sample_bits;
/* McASP FIFO related */
u8 txnumevt;
u8 rxnumevt;
+
+ /* McASP port related */
+ bool dat_port;
};
#endif /* DAVINCI_MCASP_H */
index fbb710c76c083ef90b9c442e1776ec00fcb8aa08..436722c27dc902e7b1296eca0393cf5f47e6327d 100644 (file)
unsigned int fifo_level;
};
+#ifdef CONFIG_SND_DAVINCI_SOC
+
int davinci_soc_platform_register(struct device *dev);
void davinci_soc_platform_unregister(struct device *dev);
+#else
+
+static inline int davinci_soc_platform_register(struct device *dev)
+{
+ return 0;
+}
+
+static inline void davinci_soc_platform_unregister(struct device *dev)
+{
+}
+
+#endif
+
#endif
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 9afb392e87e825cb9ac7958ac056c7aeec647517..0301876529141a213ae6c0d63a1c47f38823bba9 100644 (file)
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
select SND_SOC_TWL4030
help
Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
+
+config SND_DRA7_SOC_ATL
+ tristate
+
+config SND_SOC_DRA7_EVM
+ tristate "SoC Audio support for DRA7 EVM"
+ depends on SND_OMAP_SOC && SOC_DRA7XX
+ select SND_DAVINCI_SOC_MCASP
+ select SND_SOC_TLV320AIC3X
+ select SND_DRA7_SOC_ATL
+ help
+ Say Y if you want to add support for SoC audio on DRA7 EVM
index 4e89a7fd3e8f5b7a83750c8a0f5492a55c7b30f9..fc9c78177f5bb13330dc6db5b271b101bdaf0287 100644 (file)
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
snd-soc-omap-abe-objs := omap-abe-core.o omap-abe-dbg.o omap-abe-mixer.o \
omap-abe-mmap.o omap-abe-opp.o omap-abe-pcm.o \
omap-abe-pm.o
+snd-soc-dra7-atl-objs := dra7-atl.o
obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
obj-$(CONFIG_SND_OMAP_SOC_DMIC) += snd-soc-omap-dmic.o
obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o
obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o
obj-$(CONFIG_SND_OMAP_SOC_ABE) += snd-soc-omap-abe.o aess/
+obj-$(CONFIG_SND_DRA7_SOC_ATL) += snd-soc-dra7-atl.o
# OMAP Machine Support
snd-soc-n810-objs := n810.o
snd-soc-omap-twl4030-objs := omap-twl4030.o
snd-soc-omap3pandora-objs := omap3pandora.o
snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o
+snd-soc-dra7-evm-objs := dra7-evm.o
obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
+obj-$(CONFIG_SND_SOC_DRA7_EVM) += snd-soc-dra7-evm.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o
diff --git a/sound/soc/omap/dra7-atl.c b/sound/soc/omap/dra7-atl.c
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * dra7-atl.c -- DRA7xx Audio Tracking Logic driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * Author: Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+/* ATL instances */
+#define ATL0 0
+#define ATL1 1
+#define ATL2 2
+#define ATL3 3
+#define ATL_INSTANCES 4
+
+/* ATL instance offsets */
+#define ATL_INST(id) (0x200 + (id * 0x80))
+
+/* ATL registers */
+#define ATL_REVID 0x000
+#define ATL_PPMR(inst) (inst + 0x00)
+#define ATL_BBSR(inst) (inst + 0x04)
+#define ATL_ATLCR(inst) (inst + 0x08)
+#define ATL_SWEN(inst) (inst + 0x10)
+#define ATL_BWSMUX(inst) (inst + 0x14)
+#define ATL_AWSMUX(inst) (inst + 0x18)
+#define ATL_PCLKMUX(inst) (inst + 0x1c)
+
+/* ATL_ATCLCR */
+#define INTERNAL_DIVIDER_MAX 0x1F
+
+/* ATL_SWEN register */
+#define ATL_DISABLE 0
+#define ATL_ENABLE 1
+
+/* ATL_BWSMUX / ATL_AWSMUX register */
+#define ATL_WSMUX_MAX 0xF
+
+/* ATL_PCLKMUX register */
+#define PCLKMUX_OCP_CLK 0
+#define PCLKMUX_ATLPCLK 1
+
+struct atl_data {
+ struct device *dev;
+ void __iomem *io_base;
+ unsigned int atlpclk_freq;
+};
+
+static inline void dra7_atl_write(struct atl_data *atl, u32 reg, u32 val)
+{
+ __raw_writel(val, atl->io_base + reg);
+}
+
+static inline int dra7_atl_read(struct atl_data *atl, u32 reg)
+{
+ return __raw_readl(atl->io_base + reg);
+}
+
+static int dra7_atl_init(struct atl_data *atl)
+{
+ struct clk *gfclk, *parent_clk;
+ int ret;
+
+ gfclk = clk_get(atl->dev, "atl_gfclk_mux");
+ if (IS_ERR(gfclk)) {
+ dev_err(atl->dev, "failed to get ATLPCLK\n");
+ return PTR_ERR(gfclk);
+ }
+
+ parent_clk = clk_get(atl->dev, "dpll_abe_m2_ck");
+ if (IS_ERR(parent_clk)) {
+ dev_err(atl->dev, "failed to get new parent clock\n");
+ ret = PTR_ERR(parent_clk);
+ goto err1;
+ }
+
+ ret = clk_set_parent(gfclk, parent_clk);
+ if (ret) {
+ dev_err(atl->dev, "failed to reparent ATLPCLK\n");
+ goto err2;
+ }
+
+ atl->atlpclk_freq = clk_get_rate(gfclk);
+ dev_dbg(atl->dev, "ATLPCLK is at %u Hz\n", atl->atlpclk_freq);
+
+err2:
+ clk_put(parent_clk);
+err1:
+ clk_put(gfclk);
+ return ret;
+}
+
+static void dra7_atl_dump(struct atl_data *atl, int id)
+{
+ int inst = ATL_INST(id);
+
+ dev_dbg(atl->dev, "ATL_PPMR%d = 0x%08x\n",
+ id, dra7_atl_read(atl, ATL_PPMR(inst)));
+ dev_dbg(atl->dev, "ATL_BBSR%d = 0x%08x\n",
+ id, dra7_atl_read(atl, ATL_BBSR(inst)));
+ dev_dbg(atl->dev, "ATL_ATLCR%d = 0x%08x\n",
+ id, dra7_atl_read(atl, ATL_ATLCR(inst)));
+ dev_dbg(atl->dev, "ATL_SWEN%d = 0x%08x\n",
+ id, dra7_atl_read(atl, ATL_SWEN(inst)));
+ dev_dbg(atl->dev, "ATL_BWSMUX%d = 0x%08x\n",
+ id, dra7_atl_read(atl, ATL_BWSMUX(inst)));
+ dev_dbg(atl->dev, "ATL_AWSMUX%d = 0x%08x\n",
+ id, dra7_atl_read(atl, ATL_AWSMUX(inst)));
+ dev_dbg(atl->dev, "ATL_PCLKMUX%d = 0x%08x\n",
+ id, dra7_atl_read(atl, ATL_PCLKMUX(inst)));
+}
+
+static int dra7_atl_configure(struct atl_data *atl, int id,
+ unsigned int bws, unsigned int aws,
+ unsigned int atclk_freq)
+{
+ int inst = ATL_INST(id);
+ u32 divider;
+ unsigned int min_freq, max_freq;
+
+ if ((bws > ATL_WSMUX_MAX) || (aws > ATL_WSMUX_MAX)) {
+ dev_err(atl->dev, "invalid word select inputs bws %u aws %u\n",
+ bws, aws);
+ return -EINVAL;
+ }
+
+ /* Keep ATL instance disabled */
+ if (atclk_freq == 0)
+ return 0;
+
+ /*
+ * Internal divider cannot be 0 (divide-by-1), so ATCLK max freq
+ * cannot be higher than ATLPCLK / 2. Max divider allowed is 32
+ */
+ min_freq = atl->atlpclk_freq / (INTERNAL_DIVIDER_MAX + 1);
+ max_freq = atl->atlpclk_freq / 2;
+
+ dev_dbg(atl->dev, "configure ATL%d to %u Hz\n", id, atclk_freq);
+
+ if ((atclk_freq < min_freq) || (atclk_freq > max_freq)) {
+ dev_err(atl->dev, "requested freq %u is not allowed\n",
+ atclk_freq);
+ return -EINVAL;
+ }
+
+ /* Disable ATL while reparenting and changing ATLPCLK input */
+ dra7_atl_write(atl, ATL_SWEN(inst), ATL_DISABLE);
+
+ /* ATL divider (ATL_INTERNAL_DIVIDER): ATLPCLK-to-ATCLK ratio - 1 */
+ divider = (atl->atlpclk_freq / atclk_freq) - 1;
+ dra7_atl_write(atl, ATL_ATLCR(inst), divider);
+
+ /* Enable ATL */
+ dra7_atl_write(atl, ATL_SWEN(inst), ATL_ENABLE);
+
+ /* Basebased word select */
+ dra7_atl_write(atl, ATL_BWSMUX(inst), bws);
+
+ /* Audio word select */
+ dra7_atl_write(atl, ATL_AWSMUX(inst), aws);
+
+ dra7_atl_dump(atl, id);
+
+ return 0;
+}
+
+static void dra7_atl_reset(struct atl_data *atl, int id)
+{
+ dev_dbg(atl->dev, "reset ATL%d\n", id);
+ dra7_atl_write(atl, ATL_SWEN(ATL_INST(id)), ATL_DISABLE);
+}
+
+static int dra7_atl_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct atl_data *atl;
+ struct resource *res;
+ unsigned int atclk_freq;
+ unsigned int bws, aws;
+ char prop[128];
+ int i;
+ int ret;
+
+ atl = devm_kzalloc(&pdev->dev, sizeof(*atl), GFP_KERNEL);
+ if (!atl)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, atl);
+ atl->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENOMEM;
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), "atl"))
+ return -EBUSY;
+
+ atl->io_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!atl->io_base)
+ return -ENOMEM;
+
+ if (!node) {
+ dev_err(atl->dev, "missing of_node\n");
+ return -ENODEV;
+ }
+
+ ret = dra7_atl_init(atl);
+ if (ret) {
+ dev_err(atl->dev, "failed to initialize ATL\n");
+ return ret;
+ }
+
+ pm_runtime_enable(atl->dev);
+ pm_runtime_get_sync(atl->dev);
+
+ /*
+ * There is a single ATLPCLK mux for all ATL instances and
+ * is controlled by PCLKMUX0. The rest of PCLKMUXs don't have
+ * any effect of clock selection
+ */
+ dra7_atl_write(atl, ATL_PCLKMUX(ATL_INST(0)), PCLKMUX_ATLPCLK);
+
+ for (i = 0; i < ATL_INSTANCES; i++) {
+ atclk_freq = 0;
+ snprintf(prop, sizeof(prop), "ti,atclk%u-freq", i);
+ of_property_read_u32(node, prop, &atclk_freq);
+
+ bws = 0;
+ snprintf(prop, sizeof(prop), "ti,atl%u-bws-input", i);
+ of_property_read_u32(node, prop, &bws);
+
+ aws = 0;
+ snprintf(prop, sizeof(prop), "ti,atl%u-aws-input", i);
+ of_property_read_u32(node, prop, &aws);
+
+ ret = dra7_atl_configure(atl, i, bws, aws, atclk_freq);
+ if (ret) {
+ dev_err(atl->dev, "failed to configure ATL%d\n", i);
+ goto err;
+ }
+ }
+
+ return 0;
+
+err:
+ for (i--; i >= 0; --i)
+ dra7_atl_reset(atl, i);
+
+ pm_runtime_put_sync(atl->dev);
+ pm_runtime_disable(atl->dev);
+
+ return ret;
+}
+
+static int dra7_atl_remove(struct platform_device *pdev)
+{
+ struct atl_data *atl = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < ATL_INSTANCES; i++)
+ dra7_atl_reset(atl, i);
+
+ pm_runtime_put_sync(atl->dev);
+ pm_runtime_disable(atl->dev);
+
+ return 0;
+}
+
+static const struct of_device_id dra7_atl_of_match[] = {
+ {.compatible = "ti,dra7-atl", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, dra7_atl_of_match);
+
+static struct platform_driver dra7_atl_driver = {
+ .driver = {
+ .name = "dra7-atl-sound",
+ .owner = THIS_MODULE,
+ .of_match_table = dra7_atl_of_match,
+ },
+ .probe = dra7_atl_probe,
+ .remove = dra7_atl_remove,
+};
+
+module_platform_driver(dra7_atl_driver);
+
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
+MODULE_DESCRIPTION("ATL");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:dra7-atl");
diff --git a/sound/soc/omap/dra7-evm.c b/sound/soc/omap/dra7-evm.c
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * dr7-evm.c -- SoC audio for TI DRA7 EVM
+ *
+ * Author: Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dapm.h>
+
+struct dra7_snd_data {
+ unsigned int media_mclk_freq;
+ int media_slots;
+};
+
+static int dra7_mcasp_reparent(struct snd_soc_card *card,
+ const char *fclk_name,
+ const char *parent_name)
+{
+ struct clk *gfclk, *parent_clk;
+ int ret;
+
+ gfclk = clk_get(card->dev, fclk_name);
+ if (IS_ERR(gfclk)) {
+ dev_err(card->dev, "failed to get %s\n", fclk_name);
+ return PTR_ERR(gfclk);
+ }
+
+ parent_clk = clk_get(card->dev, parent_name);
+ if (IS_ERR(parent_clk)) {
+ dev_err(card->dev, "failed to get new parent clock %s\n",
+ parent_name);
+ ret = PTR_ERR(parent_clk);
+ goto err1;
+ }
+
+ ret = clk_set_parent(gfclk, parent_clk);
+ if (ret) {
+ dev_err(card->dev, "failed to reparent %s\n", fclk_name);
+ goto err2;
+ }
+
+err2:
+ clk_put(parent_clk);
+err1:
+ clk_put(gfclk);
+ return ret;
+}
+
+static unsigned int dra7_get_bclk(struct snd_pcm_hw_params *params, int slots)
+{
+ int sample_size = snd_pcm_format_width(params_format(params));
+ int rate = params_rate(params);
+
+ return sample_size * slots * rate;
+}
+
+static int dra7_snd_media_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_card *card = rtd->card;
+ struct dra7_snd_data *card_data = snd_soc_card_get_drvdata(card);
+ unsigned int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
+ unsigned int bclk_freq;
+ int ret;
+
+ bclk_freq = dra7_get_bclk(params, card_data->media_slots);
+ if (card_data->media_mclk_freq % bclk_freq) {
+ dev_err(card->dev, "can't produce exact sample freq\n");
+ return -EPERM;
+ }
+
+ /* McASP driver requires inverted frame for I2S */
+ ret = snd_soc_dai_set_fmt(cpu_dai, fmt | SND_SOC_DAIFMT_NB_IF);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set CPU DAI format %d\n", ret);
+ return ret;
+ }
+
+ /* Set McASP BCLK divider (clkid = 1) */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, 1,
+ card_data->media_mclk_freq / bclk_freq);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set CPU DAI clock divider %d\n", ret);
+ return ret;
+ }
+
+ /* Set McASP sysclk from AHCLKX sourced from ATL */
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0,
+ card_data->media_mclk_freq,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set CPU DAI sysclk %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_fmt(codec_dai, fmt | SND_SOC_DAIFMT_NB_NF);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set CODEC DAI format %d\n", ret);
+ return ret;
+ }
+
+ /* Set MCLK as clock source for tlv320aic3106 */
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0,
+ card_data->media_mclk_freq,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ dev_err(card->dev, "can't set CODEC sysclk %d\n", ret);
+
+ return ret;
+}
+
+static struct snd_soc_ops dra7_snd_media_ops = {
+ .hw_params = dra7_snd_media_hw_params,
+};
+
+static struct snd_soc_dai_link dra7_snd_dai[] = {
+ {
+ /* Media: McASP3 + tlv320aic3106 */
+ .name = "Media",
+ .codec_dai_name = "tlv320aic3x-hifi",
+ .platform_name = "omap-pcm-audio",
+ .ops = &dra7_snd_media_ops,
+ },
+};
+
+static int dra7_snd_add_dai_link(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_link,
+ const char *prefix)
+{
+ struct dra7_snd_data *card_data = snd_soc_card_get_drvdata(card);
+ struct device_node *node = card->dev->of_node;
+ struct device_node *dai_node;
+ char prop[32];
+ int ret;
+
+ if (!node) {
+ dev_err(card->dev, "card node is invalid\n");
+ return -EINVAL;
+ }
+
+ snprintf(prop, sizeof(prop), "%s-mclk-freq", prefix);
+ of_property_read_u32(node, prop,
+ &card_data->media_mclk_freq);
+
+ snprintf(prop, sizeof(prop), "%s-cpu", prefix);
+ dai_node = of_parse_phandle(node, prop, 0);
+ if (!dai_node) {
+ dev_err(card->dev, "cpu dai node is invalid\n");
+ return -EINVAL;
+ }
+
+ dai_link->cpu_of_node = dai_node;
+
+ snprintf(prop, sizeof(prop), "%s-codec", prefix);
+ dai_node = of_parse_phandle(node, prop, 0);
+ if (!dai_node) {
+ dev_err(card->dev, "codec dai node is invalid\n");
+ return -EINVAL;
+ }
+
+ dai_link->codec_of_node = dai_node;
+
+ snprintf(prop, sizeof(prop), "%s-slots", prefix);
+ of_property_read_u32(node, prop, &card_data->media_slots);
+ if ((card_data->media_slots < 1) ||
+ (card_data->media_slots > 32)) {
+ dev_err(card->dev, "invalid media slot count %d\n",
+ card_data->media_slots);
+ return -EINVAL;
+ }
+
+ ret = snd_soc_card_new_dai_links(card, dai_link, 1);
+ if (ret < 0) {
+ dev_err(card->dev, "failed to add dai link %s\n",
+ dai_link->name);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* DRA7 CPU board widgets */
+static const struct snd_soc_dapm_widget dra7_snd_dapm_widgets[] = {
+ /* CPU board input */
+ SND_SOC_DAPM_MIC("Main Mic", NULL),
+ SND_SOC_DAPM_LINE("Line In", NULL),
+
+ /* CPU board outputs */
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_LINE("Line Out", NULL),
+};
+
+/* Audio machine driver */
+static struct snd_soc_card dra7_snd_card = {
+ .owner = THIS_MODULE,
+ .dapm_widgets = dra7_snd_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(dra7_snd_dapm_widgets),
+};
+
+static int dra7_snd_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct snd_soc_card *card = &dra7_snd_card;
+ struct dra7_snd_data *card_data;
+ int ret;
+
+ /*
+ * HACK: DMA CROSSBAR
+ * CTRL_CORE_DMA_SYSTEM_DREQ_62_63
+ * McASP6 TX: DREQ_139 -> sDMA_62
+ * McASP6 RX: DREQ_138 -> sDMA_63
+ * CTRL_CORE_DMA_SYSTEM_DREQ_78_79
+ * McASP3 TX: DREQ_133 -> sDMA_78
+ * McASP3 RX: DREQ_132 -> sDMA_79
+ */
+ void __iomem *dma_sys_dreq = ioremap(0x4A002B78, SZ_1K);
+ __raw_writel(0x008a008b, dma_sys_dreq + 0x7c); /* DREQ_62_63 */
+ __raw_writel(0x00840085, dma_sys_dreq + 0x9c); /* DREQ_78_79 */
+ iounmap(dma_sys_dreq);
+
+ card->dev = &pdev->dev;
+
+ card_data = devm_kzalloc(&pdev->dev, sizeof(*card_data), GFP_KERNEL);
+ if (card_data == NULL)
+ return -ENOMEM;
+
+ if (!node) {
+ dev_err(card->dev, "missing of_node\n");
+ return -ENODEV;
+ }
+
+ ret = snd_soc_of_parse_card_name(card, "ti,model");
+ if (ret) {
+ dev_err(card->dev, "card name is not provided\n");
+ return -ENODEV;
+ }
+
+ ret = snd_soc_of_parse_audio_routing(card,
+ "ti,audio-routing");
+ if (ret) {
+ dev_err(card->dev, "failed to parse DAPM routing\n");
+ return ret;
+ }
+
+ snd_soc_card_set_drvdata(card, card_data);
+
+ ret = dra7_snd_add_dai_link(card, &dra7_snd_dai[0], "ti,media");
+ if (ret) {
+ dev_err(card->dev, "failed to add media dai link %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(card->dev, "failed to register sound card %d\n", ret);
+ goto err_card;
+ }
+
+ ret = dra7_mcasp_reparent(card, "mcasp3_ahclkx_mux", "atl_clkin2_ck");
+ if (ret) {
+ dev_err(card->dev, "failed to reparent McASP3 %d\n", ret);
+ goto err_reparent;
+ }
+
+ return 0;
+
+err_reparent:
+ snd_soc_unregister_card(card);
+err_card:
+ snd_soc_card_reset_dai_links(card);
+ return ret;
+}
+static int dra7_snd_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+ snd_soc_card_reset_dai_links(card);
+
+ return 0;
+}
+
+static const struct of_device_id dra7_snd_of_match[] = {
+ {.compatible = "ti,dra7-evm-sound", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, dra7_snd_of_match);
+
+static struct platform_driver dra7_snd_driver = {
+ .driver = {
+ .name = "dra7-evm-sound",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = dra7_snd_of_match,
+ },
+ .probe = dra7_snd_probe,
+ .remove = dra7_snd_remove,
+};
+
+module_platform_driver(dra7_snd_driver);
+
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC for DRA7 EVM");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:dra7-evm-sound");
index 1e32bf884a8aaec6b50e2c6dbde12d4f09c617a0..cb9ad8231d3f38d2d6677a434e3e4d1d00de468c 100644 (file)
return -ENODEV;
}
- printk(KERN_ERR "card name is %s", card->name);
-
dev_node = of_parse_phandle(node, "ti,hdmi_audio", 0);
if (!dev_node) {
dev_err(&pdev->dev, "hdmi node is not provided\n");
index b65a57484d087c6615428268170585bc43233caa..b60a32faf9ff685d35e73d8309113adeac7649b9 100644 (file)
cea->db3 = 0; /* not used, all zeros */
- /*
- * The OMAP HDMI IP requires to use the 8-channel channel code when
- * transmitting more than two channels.
- */
if (params_channels(params) == 2)
cea->db4_ca = 0x0;
+ else if (params_channels(params) == 6)
+ cea->db4_ca = 0xb;
else
cea->db4_ca = 0x13;
index 47bdbd415ad87af59686327ad3be8f25c48bf2a4..17793726fc3a1649496ffd5ce1d91b950a3ad9e9 100644 (file)
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct omap_pcm_dma_data *dma_data;
- struct dma_slave_config config;
+ struct dma_slave_config config = {0};
struct dma_chan *chan;
int err = 0;